summaryrefslogtreecommitdiff
path: root/chromium/ui/aura
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ui/aura
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
downloadqtwebengine-chromium-ab0a50979b9eb4dfa3320eff7e187e41efedf7a9.tar.gz
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/ui/aura')
-rw-r--r--chromium/ui/aura/BUILD.gn303
-rw-r--r--chromium/ui/aura/DEPS3
-rw-r--r--chromium/ui/aura/aura.gyp150
-rw-r--r--chromium/ui/aura/aura_export.h6
-rw-r--r--chromium/ui/aura/bench/DEPS2
-rw-r--r--chromium/ui/aura/bench/bench_main.cc157
-rw-r--r--chromium/ui/aura/client/activation_change_observer.cc29
-rw-r--r--chromium/ui/aura/client/activation_change_observer.h45
-rw-r--r--chromium/ui/aura/client/activation_client.cc38
-rw-r--r--chromium/ui/aura/client/activation_client.h77
-rw-r--r--chromium/ui/aura/client/activation_delegate.cc27
-rw-r--r--chromium/ui/aura/client/activation_delegate.h37
-rw-r--r--chromium/ui/aura/client/animation_host.cc32
-rw-r--r--chromium/ui/aura/client/animation_host.h48
-rw-r--r--chromium/ui/aura/client/capture_client.cc2
-rw-r--r--chromium/ui/aura/client/cursor_client.h13
-rw-r--r--chromium/ui/aura/client/default_activation_client.cc128
-rw-r--r--chromium/ui/aura/client/default_activation_client.h69
-rw-r--r--chromium/ui/aura/client/default_capture_client.cc5
-rw-r--r--chromium/ui/aura/client/dispatcher_client.cc29
-rw-r--r--chromium/ui/aura/client/dispatcher_client.h31
-rw-r--r--chromium/ui/aura/client/drag_drop_client.cc31
-rw-r--r--chromium/ui/aura/client/drag_drop_client.h62
-rw-r--r--chromium/ui/aura/client/drag_drop_delegate.cc27
-rw-r--r--chromium/ui/aura/client/drag_drop_delegate.h51
-rw-r--r--chromium/ui/aura/client/event_client.cc2
-rw-r--r--chromium/ui/aura/client/focus_client.cc2
-rw-r--r--chromium/ui/aura/client/screen_position_client.cc2
-rw-r--r--chromium/ui/aura/client/tooltip_client.cc42
-rw-r--r--chromium/ui/aura/client/tooltip_client.h38
-rw-r--r--chromium/ui/aura/client/user_action_client.cc30
-rw-r--r--chromium/ui/aura/client/user_action_client.h37
-rw-r--r--chromium/ui/aura/client/visibility_client.cc2
-rw-r--r--chromium/ui/aura/client/window_move_client.cc28
-rw-r--r--chromium/ui/aura/client/window_move_client.h56
-rw-r--r--chromium/ui/aura/client/window_stacking_client.cc3
-rw-r--r--chromium/ui/aura/client/window_stacking_client.h19
-rw-r--r--chromium/ui/aura/client/window_tree_client.cc2
-rw-r--r--chromium/ui/aura/client/window_types.h36
-rw-r--r--chromium/ui/aura/demo/DEPS3
-rw-r--r--chromium/ui/aura/demo/demo_main.cc71
-rw-r--r--chromium/ui/aura/device_list_updater_aurax11.cc32
-rw-r--r--chromium/ui/aura/device_list_updater_aurax11.h32
-rw-r--r--chromium/ui/aura/dispatcher_win.cc33
-rw-r--r--chromium/ui/aura/env.cc114
-rw-r--r--chromium/ui/aura/env.h70
-rw-r--r--chromium/ui/aura/env_observer.h10
-rw-r--r--chromium/ui/aura/gestures/gesture_recognizer_unittest.cc1584
-rw-r--r--chromium/ui/aura/remote_root_window_host_win.h298
-rw-r--r--chromium/ui/aura/remote_window_tree_host_win.cc (renamed from chromium/ui/aura/remote_root_window_host_win.cc)487
-rw-r--r--chromium/ui/aura/remote_window_tree_host_win.h194
-rw-r--r--chromium/ui/aura/root_window.cc1172
-rw-r--r--chromium/ui/aura/root_window.h401
-rw-r--r--chromium/ui/aura/root_window_host_ozone.cc133
-rw-r--r--chromium/ui/aura/root_window_host_ozone.h59
-rw-r--r--chromium/ui/aura/root_window_host_win.cc309
-rw-r--r--chromium/ui/aura/root_window_host_win.h96
-rw-r--r--chromium/ui/aura/root_window_host_x11.h152
-rw-r--r--chromium/ui/aura/root_window_host_x11_unittest.cc290
-rw-r--r--chromium/ui/aura/root_window_observer.h41
-rw-r--r--chromium/ui/aura/root_window_transformer.h45
-rw-r--r--chromium/ui/aura/root_window_unittest.cc1530
-rw-r--r--chromium/ui/aura/scoped_window_targeter.cc29
-rw-r--r--chromium/ui/aura/scoped_window_targeter.h46
-rw-r--r--chromium/ui/aura/window.cc566
-rw-r--r--chromium/ui/aura/window.h161
-rw-r--r--chromium/ui/aura/window_delegate.h15
-rw-r--r--chromium/ui/aura/window_event_dispatcher.cc861
-rw-r--r--chromium/ui/aura/window_event_dispatcher.h265
-rw-r--r--chromium/ui/aura/window_event_dispatcher_unittest.cc2219
-rw-r--r--chromium/ui/aura/window_observer.cc31
-rw-r--r--chromium/ui/aura/window_observer.h34
-rw-r--r--chromium/ui/aura/window_targeter.cc93
-rw-r--r--chromium/ui/aura/window_targeter.h17
-rw-r--r--chromium/ui/aura/window_targeter_unittest.cc125
-rw-r--r--chromium/ui/aura/window_tree_host.cc256
-rw-r--r--chromium/ui/aura/window_tree_host.h203
-rw-r--r--chromium/ui/aura/window_tree_host_delegate.h67
-rw-r--r--chromium/ui/aura/window_tree_host_mac.h61
-rw-r--r--chromium/ui/aura/window_tree_host_mac.mm114
-rw-r--r--chromium/ui/aura/window_tree_host_observer.h36
-rw-r--r--chromium/ui/aura/window_tree_host_ozone.cc118
-rw-r--r--chromium/ui/aura/window_tree_host_ozone.h58
-rw-r--r--chromium/ui/aura/window_tree_host_win.cc238
-rw-r--r--chromium/ui/aura/window_tree_host_win.h93
-rw-r--r--chromium/ui/aura/window_tree_host_x11.cc (renamed from chromium/ui/aura/root_window_host_x11.cc)574
-rw-r--r--chromium/ui/aura/window_tree_host_x11.h118
-rw-r--r--chromium/ui/aura/window_unittest.cc807
88 files changed, 7667 insertions, 8395 deletions
diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn
new file mode 100644
index 00000000000..5f177e979a9
--- /dev/null
+++ b/chromium/ui/aura/BUILD.gn
@@ -0,0 +1,303 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import ("//build/config/ui.gni")
+
+component("aura") {
+ sources = [
+ "client/aura_constants.cc",
+ "client/aura_constants.h",
+ "client/capture_client.cc",
+ "client/capture_client.h",
+ "client/capture_delegate.h",
+ "client/cursor_client.cc",
+ "client/cursor_client.h",
+ "client/cursor_client_observer.h",
+ "client/cursor_client_observer.cc",
+ "client/default_capture_client.cc",
+ "client/default_capture_client.h",
+ "client/event_client.cc",
+ "client/event_client.h",
+ "client/focus_change_observer.cc",
+ "client/focus_change_observer.h",
+ "client/focus_client.cc",
+ "client/focus_client.h",
+ "client/screen_position_client.cc",
+ "client/screen_position_client.h",
+ "client/visibility_client.cc",
+ "client/visibility_client.h",
+ "client/window_stacking_client.cc",
+ "client/window_stacking_client.h",
+ "client/window_tree_client.cc",
+ "client/window_tree_client.h",
+ "env.cc",
+ "env.h",
+ "env_observer.h",
+ "input_state_lookup.cc",
+ "input_state_lookup.h",
+ "input_state_lookup_win.cc",
+ "input_state_lookup_win.h",
+ "layout_manager.cc",
+ "layout_manager.h",
+ "remote_window_tree_host_win.cc",
+ "remote_window_tree_host_win.h",
+ "scoped_window_targeter.cc",
+ "scoped_window_targeter.h",
+ "window.cc",
+ "window.h",
+ "window_event_dispatcher.cc",
+ "window_event_dispatcher.h",
+ "window_delegate.h",
+ "window_layer_type.h",
+ "window_observer.h",
+ "window_targeter.cc",
+ "window_targeter.h",
+ "window_tracker.cc",
+ "window_tracker.h",
+ "window_tree_host.cc",
+ "window_tree_host.h",
+ "window_tree_host_mac.mm",
+ "window_tree_host_mac.h",
+ "window_tree_host_observer.h",
+ "window_tree_host_win.cc",
+ "window_tree_host_win.h",
+ "window_tree_host_x11.cc",
+ "window_tree_host_x11.h",
+ "../wm/public/activation_change_observer.h",
+ "../wm/public/activation_change_observer.cc",
+ "../wm/public/activation_client.cc",
+ "../wm/public/activation_client.h",
+ "../wm/public/activation_delegate.cc",
+ "../wm/public/activation_delegate.h",
+ "../wm/public/animation_host.cc",
+ "../wm/public/animation_host.h",
+ "../wm/public/dispatcher_client.cc",
+ "../wm/public/dispatcher_client.h",
+ "../wm/public/drag_drop_client.cc",
+ "../wm/public/drag_drop_client.h",
+ "../wm/public/drag_drop_delegate.cc",
+ "../wm/public/drag_drop_delegate.h",
+ "../wm/public/scoped_tooltip_disabler.cc",
+ "../wm/public/scoped_tooltip_disabler.h",
+ "../wm/public/tooltip_client.cc",
+ "../wm/public/tooltip_client.h",
+ "../wm/public/transient_window_client.cc",
+ "../wm/public/transient_window_client.h",
+ "../wm/public/window_move_client.cc",
+ "../wm/public/window_move_client.h",
+ ]
+
+ defines = [
+ "AURA_IMPLEMENTATION",
+ ]
+
+ deps = [
+ "//base",
+ "//base:i18n",
+ "//base/third_party/dynamic_annotations",
+ "//skia",
+ "//ui/base",
+ "//ui/compositor",
+ "//ui/events",
+ "//ui/events/platform",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ ]
+
+ if (use_x11) {
+ configs += [
+ "//build/config/linux:x11",
+ "//build/config/linux:xrandr",
+ ]
+ deps += [
+ "//ui/events/platform/x11",
+ ]
+ }
+
+ if (is_win) {
+ sources -= [
+ "input_state_lookup.cc",
+ ]
+
+ deps += [
+ "//ui/metro_viewer",
+ "//ipc",
+ ]
+ }
+
+ if (use_ozone) {
+ sources += [
+ "window_tree_host_ozone.cc",
+ "window_tree_host_ozone.h",
+ ]
+
+ # TODO(GYP) enable when these targets exist.
+ #deps += [
+ # "//ui/events/ozone",
+ # "//ui/ozone",
+ #]
+ }
+}
+
+source_set("aura_test_support") {
+ sources = [
+ "test/aura_test_base.cc",
+ "test/aura_test_base.h",
+ "test/aura_test_helper.cc",
+ "test/aura_test_helper.h",
+ "test/aura_test_utils.cc",
+ "test/aura_test_utils.h",
+ "test/env_test_helper.h",
+ "test/event_generator.cc",
+ "test/event_generator.h",
+ "test/test_cursor_client.cc",
+ "test/test_cursor_client.h",
+ "test/test_focus_client.cc",
+ "test/test_focus_client.h",
+ "test/test_screen.cc",
+ "test/test_screen.h",
+ "test/test_window_tree_client.cc",
+ "test/test_window_tree_client.h",
+ "test/test_windows.cc",
+ "test/test_windows.h",
+ "test/test_window_delegate.cc",
+ "test/test_window_delegate.h",
+ "test/ui_controls_factory_aura.h",
+ "test/window_test_api.cc",
+ "test/window_test_api.h",
+ ]
+
+ deps = [
+ ":aura",
+ "//skia",
+ "//testing/gtest",
+ "//ui/base",
+ "//ui/base:ui_base_test_support",
+ "//ui/compositor:test_support",
+ "//ui/events",
+ "//ui/events:events_base",
+ "//ui/events:events_test_support",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ ]
+
+ if (is_win) {
+ cflags = [
+ "/wd4267", # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ ]
+ }
+
+ if (use_aura) {
+ if (is_win) {
+ sources += [
+ "test/ui_controls_factory_aurawin.cc",
+ ]
+ }
+
+ if (use_x11) {
+ sources += [
+ "test/ui_controls_factory_aurax11.cc",
+ ]
+ }
+ }
+}
+
+#TODO(GYP): Enable this when everything it depends links.
+#executable("aura_demo") {
+# sources = [
+# "demo/demo_main.cc",
+# ]
+#
+# deps = [
+# ":aura",
+# ":aura_test_support",
+# "//base",
+# "//base:i18n",
+# "//skia",
+# "//third_party/icu",
+# "//ui/base",
+# "//ui/compositor",
+# "//ui/compositor:test_support",
+# "//ui/events",
+# "//ui/gfx",
+# "//ui/gfx/geometry",
+# ]
+#
+# if (use_x11) {
+# deps += [
+# "//ui/gfx/x",
+# ]
+# }
+#}
+
+#TODO(GYP): Enable this when everything it depends links.
+#executable("aura_bench") {
+# sources = [
+# "bench/bench_main.cc",
+# ]
+#
+# deps = [
+# ":aura",
+# ":aura_test_support",
+# "//base",
+# "//base:i18n",
+# "//cc",
+# "//skia",
+# "//third_party/icu",
+# "//ui/base",
+# "//ui/compositor",
+# "//ui/compositor:test_support",
+# "//ui/events",
+# "//ui/gfx",
+# "//ui/gfx/geometry",
+# ]
+#
+# if (use_x11) {
+# deps += [
+# "//ui/gfx/x",
+# ]
+# }
+#}
+
+#TODO(GYP): Enable this when everything it depends links.
+#test("aura_unittests") {
+# sources = [
+# "gestures/gesture_recognizer_unittest.cc",
+# "test/run_all_unittests.cc",
+# "window_event_dispatcher_unittest.cc",
+# "window_targeter_unittest.cc",
+# "window_unittest.cc",
+# ]
+#
+# deps = [
+# ":aura",
+# ":aura_test_support",
+# "//base/test:test_support",
+# "//skia",
+# "//testing/gtest",
+# "//ui/base",
+# "//ui/base:ui_base_test_support",
+# "//ui/compositor",
+# "//ui/compositor:test_support",
+# "//ui/events",
+# "//ui/events:events_base",
+# "//ui/events:gesture_detection",
+# "//ui/gfx",
+# "//ui/gfx/geometry",
+# "//ui/gl",
+# ]
+#
+# if (is_linux) {
+# deps += [
+# #"<(DEPTH)/third_party/mesa/mesa.gyp:osmesa",
+# ]
+# }
+#
+# if (is_linux) { # && use_allocator != "none") {
+# deps += [
+# # See http://crbug.com/162998#c4 for why this is needed.
+# "//base/allocator",
+# ]
+# }
+#}
diff --git a/chromium/ui/aura/DEPS b/chromium/ui/aura/DEPS
index c2522180289..f8d111d6eab 100644
--- a/chromium/ui/aura/DEPS
+++ b/chromium/ui/aura/DEPS
@@ -1,6 +1,4 @@
include_rules = [
- "+grit/ui_resources.h",
- "+grit/ui_strings.h",
"+skia/ext",
"+third_party/skia",
"+ui/base",
@@ -10,5 +8,6 @@ include_rules = [
"+ui/metro_viewer", # TODO(beng): investigate moving remote_root_window_host
# to ui/metro_viewer.
"+ui/ozone",
+ "+ui/wm/public",
]
diff --git a/chromium/ui/aura/aura.gyp b/chromium/ui/aura/aura.gyp
index 68164d4321a..56ef7987b44 100644
--- a/chromium/ui/aura/aura.gyp
+++ b/chromium/ui/aura/aura.gyp
@@ -14,28 +14,19 @@
'../../base/base.gyp:base',
'../../base/base.gyp:base_i18n',
'../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- '../../cc/cc.gyp:cc',
- '../../gpu/gpu.gyp:gpu',
'../../skia/skia.gyp:skia',
+ '../base/ui_base.gyp:ui_base',
'../compositor/compositor.gyp:compositor',
'../events/events.gyp:events',
'../events/events.gyp:events_base',
+ '../events/platform/events_platform.gyp:events_platform',
'../gfx/gfx.gyp:gfx',
- '../resources/ui_resources.gyp:ui_resources',
- '../ui.gyp:ui',
+ '../gfx/gfx.gyp:gfx_geometry',
],
'defines': [
'AURA_IMPLEMENTATION',
],
'sources': [
- 'client/activation_change_observer.h',
- 'client/activation_change_observer.cc',
- 'client/activation_client.cc',
- 'client/activation_client.h',
- 'client/activation_delegate.cc',
- 'client/activation_delegate.h',
- 'client/animation_host.cc',
- 'client/animation_host.h',
'client/aura_constants.cc',
'client/aura_constants.h',
'client/capture_client.cc',
@@ -45,16 +36,8 @@
'client/cursor_client.h',
'client/cursor_client_observer.h',
'client/cursor_client_observer.cc',
- 'client/default_activation_client.cc',
- 'client/default_activation_client.h',
'client/default_capture_client.cc',
'client/default_capture_client.h',
- 'client/dispatcher_client.cc',
- 'client/dispatcher_client.h',
- 'client/drag_drop_client.cc',
- 'client/drag_drop_client.h',
- 'client/drag_drop_delegate.cc',
- 'client/drag_drop_delegate.h',
'client/event_client.cc',
'client/event_client.h',
'client/focus_change_observer.cc',
@@ -63,22 +46,12 @@
'client/focus_client.h',
'client/screen_position_client.cc',
'client/screen_position_client.h',
- 'client/tooltip_client.cc',
- 'client/tooltip_client.h',
- 'client/user_action_client.cc',
- 'client/user_action_client.h',
'client/visibility_client.cc',
'client/visibility_client.h',
- 'client/window_move_client.cc',
- 'client/window_move_client.h',
'client/window_stacking_client.cc',
'client/window_stacking_client.h',
'client/window_tree_client.cc',
'client/window_tree_client.h',
- 'client/window_types.h',
- 'device_list_updater_aurax11.cc',
- 'device_list_updater_aurax11.h',
- 'dispatcher_win.cc',
'env.cc',
'env.h',
'env_observer.h',
@@ -88,40 +61,64 @@
'input_state_lookup_win.h',
'layout_manager.cc',
'layout_manager.h',
- 'remote_root_window_host_win.cc',
- 'remote_root_window_host_win.h',
- 'root_window_host_ozone.cc',
- 'root_window_host_ozone.h',
- 'root_window_host_win.cc',
- 'root_window_host_win.h',
- 'root_window_host_x11.cc',
- 'root_window_host_x11.h',
- 'root_window_transformer.h',
- 'root_window.cc',
- 'root_window.h',
+ 'remote_window_tree_host_win.cc',
+ 'remote_window_tree_host_win.h',
+ 'scoped_window_targeter.cc',
+ 'scoped_window_targeter.h',
'window.cc',
'window.h',
- 'window_targeter.cc',
- 'window_targeter.h',
+ 'window_event_dispatcher.cc',
+ 'window_event_dispatcher.h',
'window_delegate.h',
'window_layer_type.h',
+ 'window_observer.cc',
'window_observer.h',
+ 'window_targeter.cc',
+ 'window_targeter.h',
'window_tracker.cc',
'window_tracker.h',
'window_tree_host.cc',
'window_tree_host.h',
- 'window_tree_host_delegate.h',
+ 'window_tree_host_mac.mm',
+ 'window_tree_host_mac.h',
+ 'window_tree_host_observer.h',
+ 'window_tree_host_ozone.cc',
+ 'window_tree_host_ozone.h',
+ 'window_tree_host_win.cc',
+ 'window_tree_host_win.h',
+ 'window_tree_host_x11.cc',
+ 'window_tree_host_x11.h',
+ '../wm/public/activation_change_observer.h',
+ '../wm/public/activation_change_observer.cc',
+ '../wm/public/activation_client.cc',
+ '../wm/public/activation_client.h',
+ '../wm/public/activation_delegate.cc',
+ '../wm/public/activation_delegate.h',
+ '../wm/public/animation_host.cc',
+ '../wm/public/animation_host.h',
+ '../wm/public/dispatcher_client.cc',
+ '../wm/public/dispatcher_client.h',
+ '../wm/public/drag_drop_client.cc',
+ '../wm/public/drag_drop_client.h',
+ '../wm/public/drag_drop_delegate.cc',
+ '../wm/public/drag_drop_delegate.h',
+ '../wm/public/scoped_tooltip_disabler.cc',
+ '../wm/public/scoped_tooltip_disabler.h',
+ '../wm/public/tooltip_client.cc',
+ '../wm/public/tooltip_client.h',
+ '../wm/public/transient_window_client.cc',
+ '../wm/public/transient_window_client.h',
+ '../wm/public/window_move_client.cc',
+ '../wm/public/window_move_client.h',
],
'conditions': [
['use_x11==1', {
- 'link_settings': {
- 'libraries': [
- '-lX11',
- '-lXi',
- '-lXfixes',
- '-lXrandr',
- ],
- },
+ 'dependencies': [
+ '../../build/linux/system.gyp:x11',
+ '../../build/linux/system.gyp:xrandr',
+ '../../build/linux/system.gyp:xi',
+ '../events/platform/x11/x11_events_platform.gyp:x11_events_platform',
+ ],
}],
['OS=="win"', {
'dependencies': [
@@ -134,6 +131,7 @@
}],
['use_ozone==1', {
'dependencies': [
+ '../events/ozone/events_ozone.gyp:events_ozone',
'../ozone/ozone.gyp:ozone',
],
}],
@@ -145,13 +143,14 @@
'dependencies': [
'../../skia/skia.gyp:skia',
'../../testing/gtest.gyp:gtest',
+ '../base/ui_base.gyp:ui_base',
+ '../base/ui_base.gyp:ui_base_test_support',
'../compositor/compositor.gyp:compositor_test_support',
'../events/events.gyp:events',
'../events/events.gyp:events_base',
'../events/events.gyp:events_test_support',
'../gfx/gfx.gyp:gfx',
- '../ui.gyp:ui',
- '../ui_unittests.gyp:ui_test_support',
+ '../gfx/gfx.gyp:gfx_geometry',
'aura',
],
'include_dirs': [
@@ -162,13 +161,13 @@
'test/aura_test_base.h',
'test/aura_test_helper.cc',
'test/aura_test_helper.h',
+ 'test/aura_test_utils.cc',
+ 'test/aura_test_utils.h',
'test/env_test_helper.h',
'test/event_generator.cc',
'test/event_generator.h',
'test/test_cursor_client.cc',
'test/test_cursor_client.h',
- 'test/test_event_handler.cc',
- 'test/test_event_handler.h',
'test/test_focus_client.cc',
'test/test_focus_client.h',
'test/test_screen.cc',
@@ -197,12 +196,12 @@
'../../skia/skia.gyp:skia',
'../../third_party/icu/icu.gyp:icui18n',
'../../third_party/icu/icu.gyp:icuuc',
+ '../base/ui_base.gyp:ui_base',
'../compositor/compositor.gyp:compositor',
'../compositor/compositor.gyp:compositor_test_support',
'../events/events.gyp:events',
'../gfx/gfx.gyp:gfx',
- '../resources/ui_resources.gyp:ui_resources',
- '../ui.gyp:ui',
+ '../gfx/gfx.gyp:gfx_geometry',
'aura',
'aura_test_support',
],
@@ -212,6 +211,13 @@
'sources': [
'demo/demo_main.cc',
],
+ 'conditions': [
+ ['use_x11==1', {
+ 'dependencies': [
+ '../gfx/x/gfx_x11.gyp:gfx_x11',
+ ],
+ }],
+ ]
},
{
'target_name': 'aura_bench',
@@ -219,15 +225,17 @@
'dependencies': [
'../../base/base.gyp:base',
'../../base/base.gyp:base_i18n',
+ '../../cc/cc.gyp:cc',
+ '../../gpu/gpu.gyp:gles2_implementation',
'../../skia/skia.gyp:skia',
'../../third_party/icu/icu.gyp:icui18n',
'../../third_party/icu/icu.gyp:icuuc',
+ '../base/ui_base.gyp:ui_base',
'../compositor/compositor.gyp:compositor',
'../compositor/compositor.gyp:compositor_test_support',
'../events/events.gyp:events',
'../gfx/gfx.gyp:gfx',
- '../resources/ui_resources.gyp:ui_resources',
- '../ui.gyp:ui',
+ '../gfx/gfx.gyp:gfx_geometry',
'aura',
'aura_test_support',
],
@@ -237,24 +245,31 @@
'sources': [
'bench/bench_main.cc',
],
+ 'conditions': [
+ ['use_x11==1', {
+ 'dependencies': [
+ '../gfx/x/gfx_x11.gyp:gfx_x11',
+ ],
+ }],
+ ]
},
{
'target_name': 'aura_unittests',
'type': 'executable',
'dependencies': [
'../../base/base.gyp:test_support_base',
- '../../chrome/chrome_resources.gyp:packed_resources',
'../../skia/skia.gyp:skia',
'../../testing/gtest.gyp:gtest',
+ '../base/ui_base.gyp:ui_base',
+ '../base/ui_base.gyp:ui_base_test_support',
'../compositor/compositor.gyp:compositor',
'../compositor/compositor.gyp:compositor_test_support',
'../events/events.gyp:events',
'../events/events.gyp:events_base',
+ '../events/events.gyp:gesture_detection',
'../gfx/gfx.gyp:gfx',
+ '../gfx/gfx.gyp:gfx_geometry',
'../gl/gl.gyp:gl',
- '../resources/ui_resources.gyp:ui_resources',
- '../ui.gyp:ui',
- '../ui_unittests.gyp:ui_test_support',
'aura_test_support',
'aura',
],
@@ -263,11 +278,8 @@
],
'sources': [
'gestures/gesture_recognizer_unittest.cc',
- 'root_window_host_x11_unittest.cc',
- 'root_window_unittest.cc',
+ 'window_event_dispatcher_unittest.cc',
'test/run_all_unittests.cc',
- 'test/test_suite.cc',
- 'test/test_suite.h',
'window_targeter_unittest.cc',
'window_unittest.cc',
],
@@ -278,7 +290,7 @@
'<(DEPTH)/third_party/mesa/mesa.gyp:osmesa',
],
}],
- ['OS=="linux" and linux_use_tcmalloc==1', {
+ ['OS=="linux" and use_allocator!="none"', {
'dependencies': [
# See http://crbug.com/162998#c4 for why this is needed.
'../../base/allocator/allocator.gyp:allocator',
diff --git a/chromium/ui/aura/aura_export.h b/chromium/ui/aura/aura_export.h
index 9db662bbf7e..1093040a0c1 100644
--- a/chromium/ui/aura/aura_export.h
+++ b/chromium/ui/aura/aura_export.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_AURA_AURA_EXPORT_H
-#define UI_AURA_AURA_EXPORT_H
+#ifndef UI_AURA_AURA_EXPORT_H_
+#define UI_AURA_AURA_EXPORT_H_
// Defines AURA_EXPORT so that functionality implemented by the aura module
// can be exported to consumers.
@@ -29,4 +29,4 @@
#define AURA_EXPORT
#endif
-#endif // UI_AURA_AURA_EXPORT_H
+#endif // UI_AURA_AURA_EXPORT_H_
diff --git a/chromium/ui/aura/bench/DEPS b/chromium/ui/aura/bench/DEPS
index 70bd71ca290..7fa58f955ec 100644
--- a/chromium/ui/aura/bench/DEPS
+++ b/chromium/ui/aura/bench/DEPS
@@ -1,5 +1,7 @@
include_rules = [
"+cc",
+ "-cc/surfaces",
"+gpu/command_buffer/client/gles2_interface.h",
"+third_party/khronos",
+ "+ui/gl/gl_surface.h", # To initialize GL bindings.
]
diff --git a/chromium/ui/aura/bench/bench_main.cc b/chromium/ui/aura/bench/bench_main.cc
index 3f6717c80ce..b5dd3e75d3d 100644
--- a/chromium/ui/aura/bench/bench_main.cc
+++ b/chromium/ui/aura/bench/bench_main.cc
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#if defined(USE_X11)
+#include <X11/Xlib.h>
+#endif
+
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
@@ -16,35 +20,31 @@
#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/aura/client/default_capture_client.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/test/test_focus_client.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_paths.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/debug_utils.h"
#include "ui/compositor/layer.h"
-#include "ui/compositor/test/context_factories_for_test.h"
+#include "ui/compositor/test/in_process_context_factory.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/skia_util.h"
+#include "ui/gfx/x/x11_connection.h"
+#include "ui/gl/gl_surface.h"
+
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES 1
#endif
#include "third_party/khronos/GLES2/gl2ext.h"
-#if defined(USE_X11)
-#include "base/message_loop/message_pump_x11.h"
-#endif
-
using base::TimeTicks;
using ui::Compositor;
using ui::Layer;
using ui::LayerDelegate;
-using blink::WebGraphicsContext3D;
namespace {
@@ -123,11 +123,6 @@ class BenchCompositorObserver : public ui::CompositorObserver {
virtual void OnCompositingLockStateChanged(
Compositor* compositor) OVERRIDE {}
- virtual void OnUpdateVSyncParameters(ui::Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {
- }
-
virtual void Draw() {}
int frames() const { return frames_; }
@@ -140,46 +135,27 @@ class BenchCompositorObserver : public ui::CompositorObserver {
DISALLOW_COPY_AND_ASSIGN(BenchCompositorObserver);
};
-class WebGLTexture : public ui::Texture {
- public:
- WebGLTexture(gpu::gles2::GLES2Interface* gl, const gfx::Size& size)
- : ui::Texture(false, size, 1.0f),
- gl_(gl),
- texture_id_(0u) {
- gl->GenTextures(1, &texture_id_);
- gl->BindTexture(GL_TEXTURE_2D, texture_id_);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(),
- 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
-
- virtual unsigned int PrepareTexture() OVERRIDE {
- return texture_id_;
- }
-
- private:
- virtual ~WebGLTexture() {
- gl_->DeleteTextures(1, &texture_id_);
- }
-
- gpu::gles2::GLES2Interface* gl_;
- GLuint texture_id_;
-
- DISALLOW_COPY_AND_ASSIGN(WebGLTexture);
-};
+void ReturnMailbox(scoped_refptr<cc::ContextProvider> context_provider,
+ GLuint texture,
+ GLuint sync_point,
+ bool is_lost) {
+ gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
+ gl->WaitSyncPointCHROMIUM(sync_point);
+ gl->DeleteTextures(1, &texture);
+ gl->ShallowFlushCHROMIUM();
+}
// A benchmark that adds a texture layer that is updated every frame.
class WebGLBench : public BenchCompositorObserver {
public:
- WebGLBench(Layer* parent, Compositor* compositor, int max_frames)
+ WebGLBench(ui::ContextFactory* context_factory,
+ Layer* parent,
+ Compositor* compositor,
+ int max_frames)
: BenchCompositorObserver(max_frames),
parent_(parent),
webgl_(ui::LAYER_TEXTURED),
compositor_(compositor),
- texture_(),
fbo_(0),
do_draw_(true) {
CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -204,26 +180,49 @@ class WebGLBench : public BenchCompositorObserver {
webgl_.SetBounds(bounds);
parent_->Add(&webgl_);
- context_provider_ =
- ui::ContextFactory::GetInstance()->SharedMainThreadContextProvider();
+ context_provider_ = context_factory->SharedMainThreadContextProvider();
gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
- texture_ = new WebGLTexture(gl, bounds.size());
+ GLuint texture = 0;
+ gl->GenTextures(1, &texture);
+ gl->BindTexture(GL_TEXTURE_2D, texture);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gl->TexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ width,
+ height,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL);
+ gpu::Mailbox mailbox;
+ gl->GenMailboxCHROMIUM(mailbox.name);
+ gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+
gl->GenFramebuffers(1, &fbo_);
- compositor->AddObserver(this);
- webgl_.SetExternalTexture(texture_.get());
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
gl->FramebufferTexture2D(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, texture_->PrepareTexture(), 0);
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
gl->ClearColor(0.f, 1.f, 0.f, 1.f);
gl->Clear(GL_COLOR_BUFFER_BIT);
gl->Flush();
+
+ GLuint sync_point = gl->InsertSyncPointCHROMIUM();
+ webgl_.SetTextureMailbox(
+ cc::TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
+ cc::SingleReleaseCallback::Create(
+ base::Bind(ReturnMailbox, context_provider_, texture)),
+ bounds.size());
+ compositor->AddObserver(this);
}
virtual ~WebGLBench() {
- context_provider_->ContextGL()->DeleteFramebuffers(1, &fbo_);
webgl_.SetShowPaintedContent();
- texture_ = NULL;
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->DeleteFramebuffers(1, &fbo_);
compositor_->RemoveObserver(this);
}
@@ -234,7 +233,6 @@ class WebGLBench : public BenchCompositorObserver {
gl->Clear(GL_COLOR_BUFFER_BIT);
gl->Flush();
}
- webgl_.SetExternalTexture(texture_.get());
webgl_.SchedulePaint(gfx::Rect(webgl_.bounds().size()));
compositor_->ScheduleDraw();
}
@@ -244,7 +242,6 @@ class WebGLBench : public BenchCompositorObserver {
Layer webgl_;
Compositor* compositor_;
scoped_refptr<cc::ContextProvider> context_provider_;
- scoped_refptr<WebGLTexture> texture_;
// The FBO that is used to render to the texture.
unsigned int fbo_;
@@ -293,33 +290,40 @@ int main(int argc, char** argv) {
base::AtExitManager exit_manager;
+#if defined(USE_X11)
+ // This demo uses InProcessContextFactory which uses X on a separate Gpu
+ // thread.
+ gfx::InitializeThreadedX11();
+#endif
+
+ gfx::GLSurface::InitializeOneOff();
+
// The ContextFactory must exist before any Compositors are created.
- bool allow_test_contexts = false;
- ui::InitializeContextFactoryForTests(allow_test_contexts);
+ scoped_ptr<ui::InProcessContextFactory> context_factory(
+ new ui::InProcessContextFactory());
- ui::RegisterPathProvider();
base::i18n::InitializeICU();
- ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL);
- base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
- aura::Env::CreateInstance();
+ base::MessageLoopForUI message_loop;
+ aura::Env::CreateInstance(true);
+ aura::Env::GetInstance()->set_context_factory(context_factory.get());
scoped_ptr<aura::TestScreen> test_screen(
aura::TestScreen::CreateFullscreen());
gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
- scoped_ptr<aura::RootWindow> root_window(
- test_screen->CreateRootWindowForPrimaryDisplay());
+ scoped_ptr<aura::WindowTreeHost> host(
+ test_screen->CreateHostForPrimaryDisplay());
aura::client::SetCaptureClient(
- root_window->window(),
- new aura::client::DefaultCaptureClient(root_window->window()));
+ host->window(),
+ new aura::client::DefaultCaptureClient(host->window()));
scoped_ptr<aura::client::FocusClient> focus_client(
new aura::test::TestFocusClient);
- aura::client::SetFocusClient(root_window->window(), focus_client.get());
+ aura::client::SetFocusClient(host->window(), focus_client.get());
// add layers
ColoredLayer background(SK_ColorRED);
- background.SetBounds(root_window->window()->bounds());
- root_window->window()->layer()->Add(&background);
+ background.SetBounds(host->window()->bounds());
+ host->window()->layer()->Add(&background);
ColoredLayer window(SK_ColorBLUE);
window.SetBounds(gfx::Rect(background.bounds().size()));
@@ -344,22 +348,23 @@ int main(int argc, char** argv) {
if (command_line->HasSwitch("bench-software-scroll")) {
bench.reset(new SoftwareScrollBench(&page_background,
- root_window->compositor(),
+ host->compositor(),
frames));
} else {
- bench.reset(new WebGLBench(&page_background,
- root_window->compositor(),
+ bench.reset(new WebGLBench(context_factory.get(),
+ &page_background,
+ host->compositor(),
frames));
}
#ifndef NDEBUG
- ui::PrintLayerHierarchy(root_window->window()->layer(), gfx::Point(100, 100));
+ ui::PrintLayerHierarchy(host->window()->layer(), gfx::Point(100, 100));
#endif
- root_window->host()->Show();
+ host->Show();
base::MessageLoopForUI::current()->Run();
focus_client.reset();
- root_window.reset();
+ host.reset();
return 0;
}
diff --git a/chromium/ui/aura/client/activation_change_observer.cc b/chromium/ui/aura/client/activation_change_observer.cc
deleted file mode 100644
index db9f332cfae..00000000000
--- a/chromium/ui/aura/client/activation_change_observer.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/activation_change_observer.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationChangeObserver*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
- ActivationChangeObserver*, kActivationChangeObserverKey, NULL);
-
-void SetActivationChangeObserver(
- Window* window,
- ActivationChangeObserver* observer) {
- window->SetProperty(kActivationChangeObserverKey, observer);
-}
-
-ActivationChangeObserver* GetActivationChangeObserver(Window* window) {
- return window ? window->GetProperty(kActivationChangeObserverKey) : NULL;
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/activation_change_observer.h b/chromium/ui/aura/client/activation_change_observer.h
deleted file mode 100644
index 2f247db04b3..00000000000
--- a/chromium/ui/aura/client/activation_change_observer.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_ACTIVATION_CHANGE_OBSERVER_H_
-#define UI_AURA_CLIENT_ACTIVATION_CHANGE_OBSERVER_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace aura {
-class Window;
-
-namespace client {
-
-class AURA_EXPORT ActivationChangeObserver {
- public:
- // Called when |active| gains focus, or there is no active window
- // (|active| is NULL in this case.) |old_active| refers to the
- // previous active window or NULL if there was no previously active
- // window.
- virtual void OnWindowActivated(Window* gained_active,
- Window* lost_active) = 0;
-
- // Called when during window activation the currently active window is
- // selected for activation. This can happen when a window requested for
- // activation cannot be activated because a system modal window is active.
- virtual void OnAttemptToReactivateWindow(aura::Window* request_active,
- aura::Window* actual_active) {}
-
- protected:
- virtual ~ActivationChangeObserver() {}
-};
-
-// Gets/Sets the ActivationChangeObserver for a specific window. This observer
-// is notified after the ActivationClient notifies all registered observers.
-AURA_EXPORT void SetActivationChangeObserver(
- Window* window,
- ActivationChangeObserver* observer);
-AURA_EXPORT ActivationChangeObserver* GetActivationChangeObserver(
- Window* window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_ACTIVATION_CHANGE_OBSERVER_H_
diff --git a/chromium/ui/aura/client/activation_client.cc b/chromium/ui/aura/client/activation_client.cc
deleted file mode 100644
index b4633aec5ab..00000000000
--- a/chromium/ui/aura/client/activation_client.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/activation_client.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(AURA_EXPORT, aura::Window*)
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationClient*)
-
-namespace aura {
-namespace client {
-
-DEFINE_WINDOW_PROPERTY_KEY(
- ActivationClient*, kRootWindowActivationClientKey, NULL);
-DEFINE_WINDOW_PROPERTY_KEY(bool, kHideOnDeactivate, false);
-
-void SetActivationClient(Window* root_window, ActivationClient* client) {
- root_window->SetProperty(kRootWindowActivationClientKey, client);
-}
-
-ActivationClient* GetActivationClient(Window* root_window) {
- return root_window ?
- root_window->GetProperty(kRootWindowActivationClientKey) : NULL;
-}
-
-void SetHideOnDeactivate(Window* window, bool hide_on_deactivate) {
- window->SetProperty(kHideOnDeactivate, hide_on_deactivate);
-}
-
-bool GetHideOnDeactivate(Window* window) {
- return window->GetProperty(kHideOnDeactivate);
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/activation_client.h b/chromium/ui/aura/client/activation_client.h
deleted file mode 100644
index 054829ec2aa..00000000000
--- a/chromium/ui/aura/client/activation_client.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
-#define UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace ui {
-class Event;
-}
-
-namespace aura {
-class Window;
-
-namespace client {
-class ActivationChangeObserver;
-
-// An interface implemented by an object that manages window activation.
-class AURA_EXPORT ActivationClient {
- public:
- // Adds/Removes ActivationChangeObservers.
- virtual void AddObserver(ActivationChangeObserver* observer) = 0;
- virtual void RemoveObserver(ActivationChangeObserver* observer) = 0;
-
- // Activates |window|. If |window| is NULL, nothing happens.
- virtual void ActivateWindow(Window* window) = 0;
-
- // Deactivates |window|. What (if anything) is activated next is up to the
- // client. If |window| is NULL, nothing happens.
- virtual void DeactivateWindow(Window* window) = 0;
-
- // Retrieves the active window, or NULL if there is none.
- virtual Window* GetActiveWindow() = 0;
-
- // Retrieves the activatable window for |window|, or NULL if there is none.
- // Note that this is often but not always the toplevel window (see
- // GetToplevelWindow() below), as the toplevel window may not be activatable
- // (for example it may be blocked by a modal transient, or some other
- // condition).
- virtual Window* GetActivatableWindow(Window* window) = 0;
-
- // Retrieves the toplevel window for |window|, or NULL if there is none.
- virtual Window* GetToplevelWindow(Window* window) = 0;
-
- // Invoked prior to |window| getting focus as a result of the |event|. |event|
- // may be NULL. Returning false blocks |window| from getting focus.
- virtual bool OnWillFocusWindow(Window* window, const ui::Event* event) = 0;
-
- // Returns true if |window| can be activated, false otherwise. If |window| has
- // a modal child it can not be activated.
- virtual bool CanActivateWindow(Window* window) const = 0;
-
- protected:
- virtual ~ActivationClient() {}
-};
-
-// Sets/Gets the activation client on the root Window.
-AURA_EXPORT void SetActivationClient(Window* root_window,
- ActivationClient* client);
-AURA_EXPORT ActivationClient* GetActivationClient(Window* root_window);
-
-// Some types of transient window are only visible when active.
-// The transient parents of these windows may have visual appearance properties
-// that differ from transient parents that can be deactivated.
-// The presence of this property implies these traits.
-// TODO(beng): currently the UI framework (views) implements the actual
-// close-on-deactivate component of this feature but it should be
-// possible to implement in the aura client.
-AURA_EXPORT void SetHideOnDeactivate(Window* window, bool hide_on_deactivate);
-AURA_EXPORT bool GetHideOnDeactivate(Window* window);
-
-} // namespace clients
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
diff --git a/chromium/ui/aura/client/activation_delegate.cc b/chromium/ui/aura/client/activation_delegate.cc
deleted file mode 100644
index 51b22b00a61..00000000000
--- a/chromium/ui/aura/client/activation_delegate.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/activation_delegate.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationDelegate*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
- ActivationDelegate*, kActivationDelegateKey, NULL);
-
-void SetActivationDelegate(Window* window, ActivationDelegate* delegate) {
- window->SetProperty(kActivationDelegateKey, delegate);
-}
-
-ActivationDelegate* GetActivationDelegate(Window* window) {
- return window->GetProperty(kActivationDelegateKey);
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/activation_delegate.h b/chromium/ui/aura/client/activation_delegate.h
deleted file mode 100644
index 0ce86388f52..00000000000
--- a/chromium/ui/aura/client/activation_delegate.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
-#define UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace ui {
-class Event;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-// An interface implemented by an object that configures and responds to changes
-// to a window's activation state.
-class AURA_EXPORT ActivationDelegate {
- public:
- // Returns true if the window should be activated.
- virtual bool ShouldActivate() const = 0;
-
- protected:
- virtual ~ActivationDelegate() {}
-};
-
-// Sets/Gets the ActivationDelegate on the Window. No ownership changes.
-AURA_EXPORT void SetActivationDelegate(Window* window,
- ActivationDelegate* delegate);
-AURA_EXPORT ActivationDelegate* GetActivationDelegate(Window* window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
diff --git a/chromium/ui/aura/client/animation_host.cc b/chromium/ui/aura/client/animation_host.cc
deleted file mode 100644
index 5df22babc62..00000000000
--- a/chromium/ui/aura/client/animation_host.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/animation_host.h"
-
-#include "base/compiler_specific.h"
-#include "ui/aura/aura_export.h"
-
-#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::AnimationHost*)
-
-namespace aura {
-namespace client {
-
-DEFINE_WINDOW_PROPERTY_KEY(AnimationHost*, kRootWindowAnimationHostKey, NULL);
-
-void SetAnimationHost(Window* window, AnimationHost* animation_host) {
- DCHECK(window);
- window->SetProperty(kRootWindowAnimationHostKey, animation_host);
-}
-
-AnimationHost* GetAnimationHost(Window* window) {
- DCHECK(window);
- return window->GetProperty(kRootWindowAnimationHostKey);
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/animation_host.h b/chromium/ui/aura/client/animation_host.h
deleted file mode 100644
index c433b6d63dc..00000000000
--- a/chromium/ui/aura/client/animation_host.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_ANIMATION_HOST_H_
-#define UI_AURA_CLIENT_ANIMATION_HOST_H_
-
-#include "base/compiler_specific.h"
-#include "ui/aura/aura_export.h"
-
-namespace gfx {
-class Vector2d;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-// Interface for top level window host of animation. Communicates additional
-// bounds required for animation as well as animation completion for deferring
-// window closes on hide.
-class AURA_EXPORT AnimationHost {
- public:
- // Ensure the host window is at least this large so that transitions have
- // sufficient space.
- // The |top_left_delta| parameter contains the offset to be subtracted from
- // the window bounds for the top left corner.
- // The |bottom_right_delta| parameter contains the offset to be added to the
- // window bounds for the bottom right.
- virtual void SetHostTransitionOffsets(
- const gfx::Vector2d& top_left_delta,
- const gfx::Vector2d& bottom_right_delta) = 0;
-
- // Called after the window has faded out on a hide.
- virtual void OnWindowHidingAnimationCompleted() = 0;
-
- protected:
- virtual ~AnimationHost() {}
-};
-
-AURA_EXPORT void SetAnimationHost(Window* window,
- AnimationHost* animation_host);
-AURA_EXPORT AnimationHost* GetAnimationHost(Window* window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_ANIMATION_HOST_H_
diff --git a/chromium/ui/aura/client/capture_client.cc b/chromium/ui/aura/client/capture_client.cc
index cbcabd7393f..6d78c88d155 100644
--- a/chromium/ui/aura/client/capture_client.cc
+++ b/chromium/ui/aura/client/capture_client.cc
@@ -4,7 +4,7 @@
#include "ui/aura/client/capture_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
DECLARE_WINDOW_PROPERTY_TYPE(aura::client::CaptureClient*)
diff --git a/chromium/ui/aura/client/cursor_client.h b/chromium/ui/aura/client/cursor_client.h
index 99d9b6a1a1c..fc48e036107 100644
--- a/chromium/ui/aura/client/cursor_client.h
+++ b/chromium/ui/aura/client/cursor_client.h
@@ -14,6 +14,10 @@ namespace gfx {
class Display;
}
+namespace ui {
+class KeyEvent;
+}
+
namespace aura {
class Window;
namespace client {
@@ -35,12 +39,6 @@ class AURA_EXPORT CursorClient {
// invisible.
virtual void HideCursor() = 0;
- // Sets the scale of the mouse cursor icon.
- virtual void SetScale(float scale) = 0;
-
- // Gets the current scale of the mouse cursor icon.
- virtual float GetScale() const = 0;
-
// Sets the type of the mouse cursor icon.
virtual void SetCursorSet(ui::CursorSetType cursor_set) = 0;
@@ -80,6 +78,9 @@ class AURA_EXPORT CursorClient {
virtual void AddObserver(CursorClientObserver* observer) = 0;
virtual void RemoveObserver(CursorClientObserver* observer) = 0;
+ // Returns true if the mouse cursor should be hidden on |event|.
+ virtual bool ShouldHideCursorOnKeyEvent(const ui::KeyEvent& event) const = 0;
+
protected:
virtual ~CursorClient() {}
};
diff --git a/chromium/ui/aura/client/default_activation_client.cc b/chromium/ui/aura/client/default_activation_client.cc
deleted file mode 100644
index ccb660b81f4..00000000000
--- a/chromium/ui/aura/client/default_activation_client.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/default_activation_client.h"
-
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_delegate.h"
-#include "ui/aura/window.h"
-
-namespace aura {
-namespace client {
-
-////////////////////////////////////////////////////////////////////////////////
-// DefaultActivationClient, public:
-
-DefaultActivationClient::DefaultActivationClient(Window* root_window)
- : last_active_(NULL) {
- client::SetActivationClient(root_window, this);
-}
-
-DefaultActivationClient::~DefaultActivationClient() {
- for (unsigned int i = 0; i < active_windows_.size(); ++i) {
- active_windows_[i]->RemoveObserver(this);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DefaultActivationClient, client::ActivationClient implementation:
-
-void DefaultActivationClient::AddObserver(
- client::ActivationChangeObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void DefaultActivationClient::RemoveObserver(
- client::ActivationChangeObserver* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void DefaultActivationClient::ActivateWindow(Window* window) {
- Window* last_active = GetActiveWindow();
- if (last_active == window)
- return;
-
- last_active_ = last_active;
- RemoveActiveWindow(window);
- active_windows_.push_back(window);
- window->parent()->StackChildAtTop(window);
- window->AddObserver(this);
-
- FOR_EACH_OBSERVER(client::ActivationChangeObserver,
- observers_,
- OnWindowActivated(window, last_active));
-
- aura::client::ActivationChangeObserver* observer =
- aura::client::GetActivationChangeObserver(last_active);
- if (observer)
- observer->OnWindowActivated(window, last_active);
- observer = aura::client::GetActivationChangeObserver(window);
- if (observer)
- observer->OnWindowActivated(window, last_active);
-}
-
-void DefaultActivationClient::DeactivateWindow(Window* window) {
- aura::client::ActivationChangeObserver* observer =
- aura::client::GetActivationChangeObserver(window);
- if (observer)
- observer->OnWindowActivated(NULL, window);
- if (last_active_)
- ActivateWindow(last_active_);
-}
-
-Window* DefaultActivationClient::GetActiveWindow() {
- if (active_windows_.empty())
- return NULL;
- return active_windows_.back();
-}
-
-Window* DefaultActivationClient::GetActivatableWindow(Window* window) {
- return NULL;
-}
-
-Window* DefaultActivationClient::GetToplevelWindow(Window* window) {
- return NULL;
-}
-
-bool DefaultActivationClient::OnWillFocusWindow(Window* window,
- const ui::Event* event) {
- return true;
-}
-
-bool DefaultActivationClient::CanActivateWindow(Window* window) const {
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DefaultActivationClient, WindowObserver implementation:
-
-void DefaultActivationClient::OnWindowDestroyed(Window* window) {
- if (window == last_active_)
- last_active_ = NULL;
-
- if (window == GetActiveWindow()) {
- active_windows_.pop_back();
- Window* next_active = GetActiveWindow();
- if (next_active && aura::client::GetActivationChangeObserver(next_active)) {
- aura::client::GetActivationChangeObserver(next_active)->OnWindowActivated(
- next_active, NULL);
- }
- return;
- }
-
- RemoveActiveWindow(window);
-}
-
-void DefaultActivationClient::RemoveActiveWindow(Window* window) {
- for (unsigned int i = 0; i < active_windows_.size(); ++i) {
- if (active_windows_[i] == window) {
- active_windows_.erase(active_windows_.begin() + i);
- window->RemoveObserver(this);
- return;
- }
- }
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/default_activation_client.h b/chromium/ui/aura/client/default_activation_client.h
deleted file mode 100644
index 842ee909d62..00000000000
--- a/chromium/ui/aura/client/default_activation_client.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_DEFAULT_ACTIVATION_CLIENT_H_
-#define UI_AURA_CLIENT_DEFAULT_ACTIVATION_CLIENT_H_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/observer_list.h"
-#include "ui/aura/aura_export.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/window_observer.h"
-
-namespace aura {
-namespace client {
-class ActivationChangeObserver;
-}
-
-namespace client {
-
-// Simple ActivationClient implementation for use by tests and other targets
-// that just need basic behavior (e.g. activate windows whenever requested,
-// restack windows at the top when they're activated, etc.).
-class AURA_EXPORT DefaultActivationClient : public client::ActivationClient,
- public WindowObserver {
- public:
- explicit DefaultActivationClient(Window* root_window);
- virtual ~DefaultActivationClient();
-
- // Overridden from client::ActivationClient:
- virtual void AddObserver(client::ActivationChangeObserver* observer) OVERRIDE;
- virtual void RemoveObserver(
- client::ActivationChangeObserver* observer) OVERRIDE;
- virtual void ActivateWindow(Window* window) OVERRIDE;
- virtual void DeactivateWindow(Window* window) OVERRIDE;
- virtual Window* GetActiveWindow() OVERRIDE;
- virtual Window* GetActivatableWindow(Window* window) OVERRIDE;
- virtual Window* GetToplevelWindow(Window* window) OVERRIDE;
- virtual bool OnWillFocusWindow(Window* window,
- const ui::Event* event) OVERRIDE;
- virtual bool CanActivateWindow(Window* window) const OVERRIDE;
-
- // Overridden from WindowObserver:
- virtual void OnWindowDestroyed(Window* window) OVERRIDE;
-
- private:
- void RemoveActiveWindow(Window* window);
-
- // This class explicitly does NOT store the active window in a window property
- // to make sure that ActivationChangeObserver is not treated as part of the
- // aura API. Assumptions to that end will cause tests that use this client to
- // fail.
- std::vector<Window*> active_windows_;
-
- // The window which was active before the currently active one.
- Window* last_active_;
-
- ObserverList<client::ActivationChangeObserver> observers_;
-
- DISALLOW_COPY_AND_ASSIGN(DefaultActivationClient);
-};
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_DEFAULT_ACTIVATION_CLIENT_H_
diff --git a/chromium/ui/aura/client/default_capture_client.cc b/chromium/ui/aura/client/default_capture_client.cc
index df6a1b09745..69632d8a5be 100644
--- a/chromium/ui/aura/client/default_capture_client.cc
+++ b/chromium/ui/aura/client/default_capture_client.cc
@@ -4,8 +4,9 @@
#include "ui/aura/client/default_capture_client.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
namespace aura {
namespace client {
@@ -31,7 +32,7 @@ void DefaultCaptureClient::SetCapture(Window* window) {
Window* old_capture_window = capture_window_;
capture_window_ = window;
- CaptureDelegate* capture_delegate = root_window_->GetDispatcher();
+ CaptureDelegate* capture_delegate = root_window_->GetHost()->dispatcher();
if (capture_window_)
capture_delegate->SetNativeCapture();
else
diff --git a/chromium/ui/aura/client/dispatcher_client.cc b/chromium/ui/aura/client/dispatcher_client.cc
deleted file mode 100644
index a9e1a7d4cd5..00000000000
--- a/chromium/ui/aura/client/dispatcher_client.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/dispatcher_client.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DispatcherClient*);
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(DispatcherClient*, kDispatcherClientKey, NULL);
-
-void SetDispatcherClient(Window* root_window, DispatcherClient* client) {
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- root_window->SetProperty(kDispatcherClientKey, client);
-}
-
-DispatcherClient* GetDispatcherClient(Window* root_window) {
- if (root_window)
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- return root_window ? root_window->GetProperty(kDispatcherClientKey) : NULL;
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/dispatcher_client.h b/chromium/ui/aura/client/dispatcher_client.h
deleted file mode 100644
index f2d1ff8bcb3..00000000000
--- a/chromium/ui/aura/client/dispatcher_client.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
-#define UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
-
-#include "base/message_loop/message_loop.h"
-#include "ui/aura/aura_export.h"
-#include "ui/aura/window.h"
-
-namespace aura {
-class Window;
-namespace client {
-
-// An interface implemented by an object which handles nested dispatchers.
-class AURA_EXPORT DispatcherClient {
- public:
- virtual void RunWithDispatcher(base::MessageLoop::Dispatcher* dispatcher,
- aura::Window* associated_window,
- bool nestable_tasks_allowed) = 0;
-};
-
-AURA_EXPORT void SetDispatcherClient(Window* root_window,
- DispatcherClient* client);
-AURA_EXPORT DispatcherClient* GetDispatcherClient(Window* root_window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
diff --git a/chromium/ui/aura/client/drag_drop_client.cc b/chromium/ui/aura/client/drag_drop_client.cc
deleted file mode 100644
index abf5879e578..00000000000
--- a/chromium/ui/aura/client/drag_drop_client.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/drag_drop_client.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DragDropClient*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
- DragDropClient*, kRootWindowDragDropClientKey, NULL);
-
-void SetDragDropClient(Window* root_window, DragDropClient* client) {
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- root_window->SetProperty(kRootWindowDragDropClientKey, client);
-}
-
-DragDropClient* GetDragDropClient(Window* root_window) {
- if (root_window)
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- return root_window ?
- root_window->GetProperty(kRootWindowDragDropClientKey) : NULL;
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/drag_drop_client.h b/chromium/ui/aura/client/drag_drop_client.h
deleted file mode 100644
index 7277d6b3839..00000000000
--- a/chromium/ui/aura/client/drag_drop_client.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_DRAG_DROP_CLIENT_H_
-#define UI_AURA_CLIENT_DRAG_DROP_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace ui {
-class LocatedEvent;
-class OSExchangeData;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-// An interface implemented by an object that controls a drag and drop session.
-class AURA_EXPORT DragDropClient {
- public:
- virtual ~DragDropClient() {}
-
- // Initiates a drag and drop session. Returns the drag operation that was
- // applied at the end of the drag drop session. |root_location| is in the
- // root Window's coordinate system.
- virtual int StartDragAndDrop(const ui::OSExchangeData& data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& root_location,
- int operation,
- ui::DragDropTypes::DragEventSource source) = 0;
-
- // Called when mouse is dragged during a drag and drop.
- virtual void DragUpdate(aura::Window* target,
- const ui::LocatedEvent& event) = 0;
-
- // Called when mouse is released during a drag and drop.
- virtual void Drop(aura::Window* target,
- const ui::LocatedEvent& event) = 0;
-
- // Called when a drag and drop session is cancelled.
- virtual void DragCancel() = 0;
-
- // Returns true if a drag and drop session is in progress.
- virtual bool IsDragDropInProgress() = 0;
-};
-
-AURA_EXPORT void SetDragDropClient(Window* root_window,
- DragDropClient* client);
-AURA_EXPORT DragDropClient* GetDragDropClient(Window* root_window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_DRAG_DROP_CLIENT_H_
diff --git a/chromium/ui/aura/client/drag_drop_delegate.cc b/chromium/ui/aura/client/drag_drop_delegate.cc
deleted file mode 100644
index 92d986be8da..00000000000
--- a/chromium/ui/aura/client/drag_drop_delegate.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/drag_drop_delegate.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DragDropDelegate*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
- DragDropDelegate*, kDragDropDelegateKey, NULL);
-
-void SetDragDropDelegate(Window* window, DragDropDelegate* delegate) {
- window->SetProperty(kDragDropDelegateKey, delegate);
-}
-
-DragDropDelegate* GetDragDropDelegate(Window* window) {
- return window->GetProperty(kDragDropDelegateKey);
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/drag_drop_delegate.h b/chromium/ui/aura/client/drag_drop_delegate.h
deleted file mode 100644
index dde7f32ec73..00000000000
--- a/chromium/ui/aura/client/drag_drop_delegate.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_DRAG_DROP_DELEGATE_H_
-#define UI_AURA_CLIENT_DRAG_DROP_DELEGATE_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace ui {
-class DropTargetEvent;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-// Delegate interface for drag and drop actions on aura::Window.
-class AURA_EXPORT DragDropDelegate {
- public:
- // OnDragEntered is invoked when the mouse enters this window during a drag &
- // drop session. This is immediately followed by an invocation of
- // OnDragUpdated, and eventually one of OnDragExited or OnPerformDrop.
- virtual void OnDragEntered(const ui::DropTargetEvent& event) = 0;
-
- // Invoked during a drag and drop session while the mouse is over the window.
- // This should return a bitmask of the DragDropTypes::DragOperation supported
- // based on the location of the event. Return 0 to indicate the drop should
- // not be accepted.
- virtual int OnDragUpdated(const ui::DropTargetEvent& event) = 0;
-
- // Invoked during a drag and drop session when the mouse exits the window, or
- // when the drag session was canceled and the mouse was over the window.
- virtual void OnDragExited() = 0;
-
- // Invoked during a drag and drop session when OnDragUpdated returns a valid
- // operation and the user release the mouse.
- virtual int OnPerformDrop(const ui::DropTargetEvent& event) = 0;
-
- protected:
- virtual ~DragDropDelegate() {}
-};
-
-AURA_EXPORT void SetDragDropDelegate(Window* window,
- DragDropDelegate* delegate);
-AURA_EXPORT DragDropDelegate* GetDragDropDelegate(Window* window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_DRAG_DROP_DELEGATE_H_
diff --git a/chromium/ui/aura/client/event_client.cc b/chromium/ui/aura/client/event_client.cc
index c6699741b3c..d6da07e4245 100644
--- a/chromium/ui/aura/client/event_client.cc
+++ b/chromium/ui/aura/client/event_client.cc
@@ -4,7 +4,7 @@
#include "ui/aura/client/event_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
DECLARE_WINDOW_PROPERTY_TYPE(aura::client::EventClient*)
diff --git a/chromium/ui/aura/client/focus_client.cc b/chromium/ui/aura/client/focus_client.cc
index 0769b0dfac0..1f24a802cbc 100644
--- a/chromium/ui/aura/client/focus_client.cc
+++ b/chromium/ui/aura/client/focus_client.cc
@@ -4,7 +4,7 @@
#include "ui/aura/client/focus_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(AURA_EXPORT, aura::Window*)
diff --git a/chromium/ui/aura/client/screen_position_client.cc b/chromium/ui/aura/client/screen_position_client.cc
index 1fb75217bcb..8601005e4ea 100644
--- a/chromium/ui/aura/client/screen_position_client.cc
+++ b/chromium/ui/aura/client/screen_position_client.cc
@@ -4,7 +4,7 @@
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ScreenPositionClient*)
diff --git a/chromium/ui/aura/client/tooltip_client.cc b/chromium/ui/aura/client/tooltip_client.cc
deleted file mode 100644
index f018f262812..00000000000
--- a/chromium/ui/aura/client/tooltip_client.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/tooltip_client.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::TooltipClient*)
-DECLARE_WINDOW_PROPERTY_TYPE(base::string16*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
- TooltipClient*, kRootWindowTooltipClientKey, NULL);
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(base::string16*, kTooltipTextKey, NULL);
-
-void SetTooltipClient(Window* root_window, TooltipClient* client) {
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- root_window->SetProperty(kRootWindowTooltipClientKey, client);
-}
-
-TooltipClient* GetTooltipClient(Window* root_window) {
- if (root_window)
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- return root_window ?
- root_window->GetProperty(kRootWindowTooltipClientKey) : NULL;
-}
-
-void SetTooltipText(Window* window, base::string16* tooltip_text) {
- window->SetProperty(kTooltipTextKey, tooltip_text);
-}
-
-const base::string16 GetTooltipText(Window* window) {
- base::string16* string_ptr = window->GetProperty(kTooltipTextKey);
- return string_ptr ? *string_ptr : base::string16();
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/tooltip_client.h b/chromium/ui/aura/client/tooltip_client.h
deleted file mode 100644
index c280b8a8b75..00000000000
--- a/chromium/ui/aura/client/tooltip_client.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_TOOLTIP_CLIENT_H_
-#define UI_AURA_CLIENT_TOOLTIP_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-#include "ui/gfx/font.h"
-
-namespace aura {
-class Window;
-namespace client {
-
-class AURA_EXPORT TooltipClient {
- public:
- // Informs the shell tooltip manager of change in tooltip for window |target|.
- virtual void UpdateTooltip(Window* target) = 0;
-
- // Sets the time after which the tooltip is hidden for Window |target|. If
- // |timeout_in_ms| is <= 0, the tooltip is shown indefinitely.
- virtual void SetTooltipShownTimeout(Window* target, int timeout_in_ms) = 0;
-
- // Enables/Disables tooltips.
- virtual void SetTooltipsEnabled(bool enable) = 0;
-};
-
-AURA_EXPORT void SetTooltipClient(Window* root_window,
- TooltipClient* client);
-AURA_EXPORT TooltipClient* GetTooltipClient(Window* root_window);
-
-AURA_EXPORT void SetTooltipText(Window* window, base::string16* tooltip_text);
-AURA_EXPORT const base::string16 GetTooltipText(Window* window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_TOOLTIP_CLIENT_H_
diff --git a/chromium/ui/aura/client/user_action_client.cc b/chromium/ui/aura/client/user_action_client.cc
deleted file mode 100644
index 3dab666660c..00000000000
--- a/chromium/ui/aura/client/user_action_client.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/user_action_client.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/window_property.h"
-
-namespace aura {
-namespace client {
-
-DEFINE_WINDOW_PROPERTY_KEY(UserActionClient*,
- kRootWindowUserActionClientKey,
- NULL);
-
-void SetUserActionClient(Window* root_window, UserActionClient* client) {
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- root_window->SetProperty(kRootWindowUserActionClientKey, client);
-}
-
-UserActionClient* GetUserActionClient(Window* root_window) {
- if (root_window)
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- return root_window ?
- root_window->GetProperty(kRootWindowUserActionClientKey) : NULL;
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/user_action_client.h b/chromium/ui/aura/client/user_action_client.h
deleted file mode 100644
index 738a8d5fba1..00000000000
--- a/chromium/ui/aura/client/user_action_client.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_USER_ACTION_CLIENT_H_
-#define UI_AURA_CLIENT_USER_ACTION_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace aura {
-class Window;
-namespace client {
-
-// An interface for handling a user action that isn't handled by the standard
-// event path.
-class AURA_EXPORT UserActionClient {
- public:
- enum Command {
- BACK = 0,
- FORWARD,
- };
-
- // Returns true if the command was handled and false otherwise.
- virtual bool OnUserAction(Command command) = 0;
-
- virtual ~UserActionClient() {}
-};
-
-// Sets/gets the client for handling user action on the specified root window.
-AURA_EXPORT void SetUserActionClient(Window* root_window,
- UserActionClient* client);
-AURA_EXPORT UserActionClient* GetUserActionClient(Window* root_window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_USER_ACTION_CLIENT_H_
diff --git a/chromium/ui/aura/client/visibility_client.cc b/chromium/ui/aura/client/visibility_client.cc
index 5fc7beed7c1..853c034951f 100644
--- a/chromium/ui/aura/client/visibility_client.cc
+++ b/chromium/ui/aura/client/visibility_client.cc
@@ -4,7 +4,7 @@
#include "ui/aura/client/visibility_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
DECLARE_WINDOW_PROPERTY_TYPE(aura::client::VisibilityClient*)
diff --git a/chromium/ui/aura/client/window_move_client.cc b/chromium/ui/aura/client/window_move_client.cc
deleted file mode 100644
index c65452db607..00000000000
--- a/chromium/ui/aura/client/window_move_client.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/window_move_client.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::WindowMoveClient*)
-
-namespace aura {
-namespace client {
-
-// A property key to store a client that handles window moves.
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
- WindowMoveClient*, kWindowMoveClientKey, NULL);
-
-void SetWindowMoveClient(Window* window, WindowMoveClient* client) {
- window->SetProperty(kWindowMoveClientKey, client);
-}
-
-WindowMoveClient* GetWindowMoveClient(Window* window) {
- return window->GetProperty(kWindowMoveClientKey);
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/aura/client/window_move_client.h b/chromium/ui/aura/client/window_move_client.h
deleted file mode 100644
index 15e4245757b..00000000000
--- a/chromium/ui/aura/client/window_move_client.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_
-#define UI_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-#include "ui/gfx/vector2d.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-enum WindowMoveResult {
- MOVE_SUCCESSFUL, // Moving window was successful.
- MOVE_CANCELED // Moving window was canceled.
-};
-
-enum WindowMoveSource {
- WINDOW_MOVE_SOURCE_MOUSE,
- WINDOW_MOVE_SOURCE_TOUCH,
-};
-
-// An interface implemented by an object that manages programatically keyed
-// window moving.
-class AURA_EXPORT WindowMoveClient {
- public:
- // Starts a nested message loop for moving the window. |drag_offset| is the
- // offset from the window origin to the cursor when the drag was started.
- // Returns MOVE_SUCCESSFUL if the move has completed successfully, or
- // MOVE_CANCELED otherwise.
- virtual WindowMoveResult RunMoveLoop(Window* window,
- const gfx::Vector2d& drag_offset,
- WindowMoveSource source) = 0;
-
- // Ends a previously started move loop.
- virtual void EndMoveLoop() = 0;
-
- protected:
- virtual ~WindowMoveClient() {}
-};
-
-// Sets/Gets the activation client for the specified window.
-AURA_EXPORT void SetWindowMoveClient(Window* window,
- WindowMoveClient* client);
-AURA_EXPORT WindowMoveClient* GetWindowMoveClient(Window* window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_
diff --git a/chromium/ui/aura/client/window_stacking_client.cc b/chromium/ui/aura/client/window_stacking_client.cc
index 81da8d1ea6f..8f909766d64 100644
--- a/chromium/ui/aura/client/window_stacking_client.cc
+++ b/chromium/ui/aura/client/window_stacking_client.cc
@@ -14,11 +14,10 @@ WindowStackingClient* instance = NULL;
} // namespace
void SetWindowStackingClient(WindowStackingClient* client) {
- delete instance;
instance = client;
}
-AURA_EXPORT WindowStackingClient* GetWindowStackingClient() {
+WindowStackingClient* GetWindowStackingClient() {
return instance;
}
diff --git a/chromium/ui/aura/client/window_stacking_client.h b/chromium/ui/aura/client/window_stacking_client.h
index 35772ed71c4..848260397cb 100644
--- a/chromium/ui/aura/client/window_stacking_client.h
+++ b/chromium/ui/aura/client/window_stacking_client.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_AURA_CLIENT_WINDOW_STACKING_DELEGATE_H_
-#define UI_AURA_CLIENT_WINDOW_STACKING_DELEGATE_H_
+#ifndef UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_
+#define UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
@@ -15,20 +15,25 @@ namespace client {
class AURA_EXPORT WindowStackingClient {
public:
- virtual ~WindowStackingClient() {}
-
// Invoked from the various Window stacking functions. Allows the
// WindowStackingClient to alter the source, target and/or direction to stack.
- virtual void AdjustStacking(Window** child,
+ // Returns true if stacking should continue; false if the stacking should not
+ // happen.
+ virtual bool AdjustStacking(Window** child,
Window** target,
Window::StackDirection* direction) = 0;
+
+ protected:
+ virtual ~WindowStackingClient() {}
};
-// Sets/gets the WindowStackingClient. The setter takes ownership of |client|.
+// Sets/gets the WindowStackingClient. This does *not* take ownership of
+// |client|. It is assumed the caller will invoke SetWindowStackingClient(NULL)
+// before deleting |client|.
AURA_EXPORT void SetWindowStackingClient(WindowStackingClient* client);
AURA_EXPORT WindowStackingClient* GetWindowStackingClient();
} // namespace client
} // namespace aura
-#endif // UI_AURA_CLIENT_WINDOW_STACKING_DELEGATE_H_
+#endif // UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_
diff --git a/chromium/ui/aura/client/window_tree_client.cc b/chromium/ui/aura/client/window_tree_client.cc
index de1ece561d0..1b263c3e756 100644
--- a/chromium/ui/aura/client/window_tree_client.cc
+++ b/chromium/ui/aura/client/window_tree_client.cc
@@ -5,7 +5,7 @@
#include "ui/aura/client/window_tree_client.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
DECLARE_WINDOW_PROPERTY_TYPE(aura::client::WindowTreeClient*)
diff --git a/chromium/ui/aura/client/window_types.h b/chromium/ui/aura/client/window_types.h
deleted file mode 100644
index f0a7b777a8f..00000000000
--- a/chromium/ui/aura/client/window_types.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_WINDOW_TYPES_H_
-#define UI_AURA_WINDOW_TYPES_H_
-
-namespace aura {
-namespace client {
-
-// This isn't a property because it can't change after the window has been
-// initialized. It's in client because the Aura Client application derives
-// meaning from these values, not Aura itself.
-enum WindowType {
- WINDOW_TYPE_UNKNOWN = 0,
-
- // Regular windows that should be laid out by the client.
- WINDOW_TYPE_NORMAL,
-
- // Miscellaneous windows that should not be laid out by the shell.
- WINDOW_TYPE_POPUP,
-
- // A window intended as a control. Not laid out by the shell.
- WINDOW_TYPE_CONTROL,
-
- // Always on top windows aligned to bottom right of screen.
- WINDOW_TYPE_PANEL,
-
- WINDOW_TYPE_MENU,
- WINDOW_TYPE_TOOLTIP,
-};
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_AURA_WINDOW_TYPES_H_
diff --git a/chromium/ui/aura/demo/DEPS b/chromium/ui/aura/demo/DEPS
new file mode 100644
index 00000000000..07d824381a5
--- /dev/null
+++ b/chromium/ui/aura/demo/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+ui/gl/gl_surface.h", # To initialize GL bindings.
+]
diff --git a/chromium/ui/aura/demo/demo_main.cc b/chromium/ui/aura/demo/demo_main.cc
index 4dfd347577b..f531cd31c2e 100644
--- a/chromium/ui/aura/demo/demo_main.cc
+++ b/chromium/ui/aura/demo/demo_main.cc
@@ -11,21 +11,24 @@
#include "ui/aura/client/default_capture_client.h"
#include "ui/aura/client/window_tree_client.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/test/test_focus_client.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_paths.h"
-#include "ui/compositor/test/context_factories_for_test.h"
+#include "ui/compositor/test/in_process_context_factory.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/rect.h"
+#include "ui/gl/gl_surface.h"
#if defined(USE_X11)
-#include "base/message_loop/message_pump_x11.h"
+#include "ui/gfx/x/x11_connection.h"
+#endif
+
+#if defined(OS_WIN)
+#include "ui/gfx/win/dpi.h"
#endif
namespace {
@@ -63,13 +66,11 @@ class DemoWindowDelegate : public aura::WindowDelegate {
canvas->DrawColor(color_, SkXfermode::kSrc_Mode);
}
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
- virtual void OnWindowDestroying() OVERRIDE {}
- virtual void OnWindowDestroyed() OVERRIDE {}
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {}
+ virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {}
virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
virtual bool HasHitTestMask() const OVERRIDE { return false; }
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
- virtual void DidRecreateLayer(ui::Layer* old_layer,
- ui::Layer* new_layer) OVERRIDE {}
private:
SkColor color_;
@@ -107,51 +108,63 @@ class DemoWindowTreeClient : public aura::client::WindowTreeClient {
};
int DemoMain() {
- // Create the message-loop here before creating the root window.
- base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
+#if defined(USE_X11)
+ // This demo uses InProcessContextFactory which uses X on a separate Gpu
+ // thread.
+ gfx::InitializeThreadedX11();
+#endif
+
+ gfx::GLSurface::InitializeOneOff();
+
+#if defined(OS_WIN)
+ gfx::InitDeviceScaleFactor(1.0f);
+#endif
// The ContextFactory must exist before any Compositors are created.
- bool allow_test_contexts = false;
- ui::InitializeContextFactoryForTests(allow_test_contexts);
+ scoped_ptr<ui::InProcessContextFactory> context_factory(
+ new ui::InProcessContextFactory());
+
+ // Create the message-loop here before creating the root window.
+ base::MessageLoopForUI message_loop;
- aura::Env::CreateInstance();
- scoped_ptr<aura::TestScreen> test_screen(aura::TestScreen::Create());
+ aura::Env::CreateInstance(true);
+ aura::Env::GetInstance()->set_context_factory(context_factory.get());
+ scoped_ptr<aura::TestScreen> test_screen(
+ aura::TestScreen::Create(gfx::Size()));
gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
- scoped_ptr<aura::RootWindow> root_window(
- test_screen->CreateRootWindowForPrimaryDisplay());
- scoped_ptr<DemoWindowTreeClient> window_tree_client(new DemoWindowTreeClient(
- root_window->window()));
+ scoped_ptr<aura::WindowTreeHost> host(
+ test_screen->CreateHostForPrimaryDisplay());
+ scoped_ptr<DemoWindowTreeClient> window_tree_client(
+ new DemoWindowTreeClient(host->window()));
aura::test::TestFocusClient focus_client;
- aura::client::SetFocusClient(root_window->window(), &focus_client);
+ aura::client::SetFocusClient(host->window(), &focus_client);
// Create a hierarchy of test windows.
DemoWindowDelegate window_delegate1(SK_ColorBLUE);
aura::Window window1(&window_delegate1);
window1.set_id(1);
- window1.Init(ui::LAYER_TEXTURED);
+ window1.Init(aura::WINDOW_LAYER_TEXTURED);
window1.SetBounds(gfx::Rect(100, 100, 400, 400));
window1.Show();
- aura::client::ParentWindowWithContext(
- &window1, root_window->window(), gfx::Rect());
+ aura::client::ParentWindowWithContext(&window1, host->window(), gfx::Rect());
DemoWindowDelegate window_delegate2(SK_ColorRED);
aura::Window window2(&window_delegate2);
window2.set_id(2);
- window2.Init(ui::LAYER_TEXTURED);
+ window2.Init(aura::WINDOW_LAYER_TEXTURED);
window2.SetBounds(gfx::Rect(200, 200, 350, 350));
window2.Show();
- aura::client::ParentWindowWithContext(
- &window2, root_window->window(), gfx::Rect());
+ aura::client::ParentWindowWithContext(&window2, host->window(), gfx::Rect());
DemoWindowDelegate window_delegate3(SK_ColorGREEN);
aura::Window window3(&window_delegate3);
window3.set_id(3);
- window3.Init(ui::LAYER_TEXTURED);
+ window3.Init(aura::WINDOW_LAYER_TEXTURED);
window3.SetBounds(gfx::Rect(10, 10, 50, 50));
window3.Show();
window2.AddChild(&window3);
- root_window->host()->Show();
+ host->Show();
base::MessageLoopForUI::current()->Run();
return 0;
@@ -165,9 +178,7 @@ int main(int argc, char** argv) {
// The exit manager is in charge of calling the dtors of singleton objects.
base::AtExitManager exit_manager;
- ui::RegisterPathProvider();
base::i18n::InitializeICU();
- ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL);
return DemoMain();
}
diff --git a/chromium/ui/aura/device_list_updater_aurax11.cc b/chromium/ui/aura/device_list_updater_aurax11.cc
deleted file mode 100644
index 8240cb495c3..00000000000
--- a/chromium/ui/aura/device_list_updater_aurax11.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/device_list_updater_aurax11.h"
-
-#include <X11/extensions/XInput2.h>
-
-#include "ui/events/event_utils.h"
-
-namespace aura {
-
-DeviceListUpdaterAuraX11::DeviceListUpdaterAuraX11() {}
-
-DeviceListUpdaterAuraX11::~DeviceListUpdaterAuraX11() {}
-
-base::EventStatus DeviceListUpdaterAuraX11::WillProcessEvent(
- const base::NativeEvent& event) {
- // XI_HierarchyChanged events are special. There is no window associated with
- // these events. So process them directly from here.
- if (event->type == GenericEvent &&
- event->xgeneric.evtype == XI_HierarchyChanged) {
- ui::UpdateDeviceList();
- }
-
- return base::EVENT_CONTINUE;
-}
-
-void DeviceListUpdaterAuraX11::DidProcessEvent(const base::NativeEvent& event) {
-}
-
-} // namespace aura
diff --git a/chromium/ui/aura/device_list_updater_aurax11.h b/chromium/ui/aura/device_list_updater_aurax11.h
deleted file mode 100644
index cb8c884fe85..00000000000
--- a/chromium/ui/aura/device_list_updater_aurax11.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_DEVICE_LIST_UPDATER_AURAX11_H_
-#define UI_AURA_DEVICE_LIST_UPDATER_AURAX11_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/message_loop/message_pump_observer.h"
-
-namespace aura {
-
-// Filters out global XInput notifications and updates the DeviceList.
-class DeviceListUpdaterAuraX11 : public base::MessagePumpObserver {
- public:
- DeviceListUpdaterAuraX11();
- virtual ~DeviceListUpdaterAuraX11();
-
- // Overridden from base::MessagePumpObserver:
- virtual base::EventStatus WillProcessEvent(
- const base::NativeEvent& event) OVERRIDE;
- virtual void DidProcessEvent(
- const base::NativeEvent& event) OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DeviceListUpdaterAuraX11);
-};
-
-} // namespace aura
-
-#endif // UI_AURA_DEVICE_LIST_UPDATER_AURAX11_H_
diff --git a/chromium/ui/aura/dispatcher_win.cc b/chromium/ui/aura/dispatcher_win.cc
deleted file mode 100644
index 7160dc7771d..00000000000
--- a/chromium/ui/aura/dispatcher_win.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/message_loop/message_loop.h"
-
-namespace aura {
-
-class DispatcherWin : public base::MessageLoop::Dispatcher {
- public:
- DispatcherWin() {}
- virtual ~DispatcherWin() {}
-
- // Overridden from MessageLoop::Dispatcher:
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DispatcherWin);
-};
-
-bool DispatcherWin::Dispatch(const base::NativeEvent& msg) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- return true;
-}
-
-base::MessageLoop::Dispatcher* CreateDispatcher() {
- return new DispatcherWin;
-}
-
-} // namespace aura
diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc
index 0982d91ad26..71a43c9c5ae 100644
--- a/chromium/ui/aura/env.cc
+++ b/chromium/ui/aura/env.cc
@@ -4,62 +4,47 @@
#include "ui/aura/env.h"
-#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/threading/thread_local.h"
#include "ui/aura/env_observer.h"
#include "ui/aura/input_state_lookup.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/compositor.h"
-#include "ui/compositor/compositor_switches.h"
#include "ui/events/event_target_iterator.h"
+#include "ui/events/platform/platform_event_source.h"
-#if defined(USE_X11)
-#include "base/message_loop/message_pump_x11.h"
+#if defined(USE_OZONE)
+#include "ui/ozone/ozone_platform.h"
#endif
namespace aura {
-// static
-Env* Env::instance_ = NULL;
-
-////////////////////////////////////////////////////////////////////////////////
-// Env, public:
-
-Env::Env()
- : mouse_button_flags_(0),
- is_touch_down_(false),
- input_state_lookup_(InputStateLookup::Create().Pass()) {
-}
+namespace {
-Env::~Env() {
-#if defined(USE_X11)
- base::MessagePumpX11::Current()->RemoveObserver(
- &device_list_updater_aurax11_);
-#endif
+// Env is thread local so that aura may be used on multiple threads.
+base::LazyInstance<base::ThreadLocalPointer<Env> >::Leaky lazy_tls_ptr =
+ LAZY_INSTANCE_INITIALIZER;
- FOR_EACH_OBSERVER(EnvObserver, observers_, OnWillDestroyEnv());
+} // namespace
- ui::Compositor::Terminate();
-}
+////////////////////////////////////////////////////////////////////////////////
+// Env, public:
-//static
-void Env::CreateInstance() {
- if (!instance_) {
- instance_ = new Env;
- instance_->Init();
- }
+// static
+void Env::CreateInstance(bool create_event_source) {
+ if (!lazy_tls_ptr.Pointer()->Get())
+ (new Env())->Init(create_event_source);
}
// static
Env* Env::GetInstance() {
- DCHECK(instance_) << "Env::CreateInstance must be called before getting "
- "the instance of Env.";
- return instance_;
+ Env* env = lazy_tls_ptr.Pointer()->Get();
+ DCHECK(env) << "Env::CreateInstance must be called before getting the "
+ "instance of Env.";
+ return env;
}
// static
void Env::DeleteInstance() {
- delete instance_;
- instance_ = NULL;
+ delete lazy_tls_ptr.Pointer()->Get();
}
void Env::AddObserver(EnvObserver* observer) {
@@ -75,47 +60,44 @@ bool Env::IsMouseButtonDown() const {
mouse_button_flags_ != 0;
}
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
- !defined(USE_GTK_MESSAGE_PUMP)
-base::MessageLoop::Dispatcher* Env::GetDispatcher() {
-#if defined(USE_X11)
- return base::MessagePumpX11::Current();
-#else
- return dispatcher_.get();
-#endif
-}
-#endif
+////////////////////////////////////////////////////////////////////////////////
+// Env, private:
-void Env::RootWindowActivated(RootWindow* root_window) {
- FOR_EACH_OBSERVER(EnvObserver, observers_,
- OnRootWindowActivated(root_window));
+Env::Env()
+ : mouse_button_flags_(0),
+ is_touch_down_(false),
+ input_state_lookup_(InputStateLookup::Create().Pass()),
+ context_factory_(NULL) {
+ DCHECK(lazy_tls_ptr.Pointer()->Get() == NULL);
+ lazy_tls_ptr.Pointer()->Set(this);
}
-////////////////////////////////////////////////////////////////////////////////
-// Env, private:
+Env::~Env() {
+ FOR_EACH_OBSERVER(EnvObserver, observers_, OnWillDestroyEnv());
+ DCHECK_EQ(this, lazy_tls_ptr.Pointer()->Get());
+ lazy_tls_ptr.Pointer()->Set(NULL);
+}
-void Env::Init() {
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(USE_X11) && \
- !defined(USE_OZONE)
- dispatcher_.reset(CreateDispatcher());
-#endif
-#if defined(USE_X11)
- // We can't do this with a root window listener because XI_HierarchyChanged
- // messages don't have a target window.
- base::MessagePumpX11::Current()->AddObserver(
- &device_list_updater_aurax11_);
+void Env::Init(bool create_event_source) {
+#if defined(USE_OZONE)
+ // The ozone platform can provide its own event source. So initialize the
+ // platform before creating the default event source.
+ ui::OzonePlatform::InitializeForUI();
#endif
- ui::Compositor::Initialize();
+ if (create_event_source && !ui::PlatformEventSource::GetInstance())
+ event_source_ = ui::PlatformEventSource::CreateDefault();
}
void Env::NotifyWindowInitialized(Window* window) {
FOR_EACH_OBSERVER(EnvObserver, observers_, OnWindowInitialized(window));
}
-void Env::NotifyRootWindowInitialized(RootWindow* root_window) {
- FOR_EACH_OBSERVER(EnvObserver,
- observers_,
- OnRootWindowInitialized(root_window));
+void Env::NotifyHostInitialized(WindowTreeHost* host) {
+ FOR_EACH_OBSERVER(EnvObserver, observers_, OnHostInitialized(host));
+}
+
+void Env::NotifyHostActivated(WindowTreeHost* host) {
+ FOR_EACH_OBSERVER(EnvObserver, observers_, OnHostActivated(host));
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/aura/env.h b/chromium/ui/aura/env.h
index e326781264f..a4f67668482 100644
--- a/chromium/ui/aura/env.h
+++ b/chromium/ui/aura/env.h
@@ -6,17 +6,17 @@
#define UI_AURA_ENV_H_
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/observer_list.h"
+#include "base/supports_user_data.h"
#include "ui/aura/aura_export.h"
#include "ui/events/event_handler.h"
#include "ui/events/event_target.h"
#include "ui/gfx/point.h"
-#if defined(USE_X11)
-#include "ui/aura/device_list_updater_aurax11.h"
-#endif
-
+namespace ui {
+class ContextFactory;
+class PlatformEventSource;
+}
namespace aura {
namespace test {
@@ -25,28 +25,24 @@ class EnvTestHelper;
class EnvObserver;
class InputStateLookup;
-class RootWindow;
class Window;
-
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(USE_X11)
-// Creates a platform-specific native event dispatcher.
-base::MessageLoop::Dispatcher* CreateDispatcher();
-#endif
+class WindowTreeHost;
// A singleton object that tracks general state within Aura.
-// TODO(beng): manage RootWindows.
-class AURA_EXPORT Env : public ui::EventTarget {
+class AURA_EXPORT Env : public ui::EventTarget, public base::SupportsUserData {
public:
- Env();
- virtual ~Env();
-
- static void CreateInstance();
+ // Creates the single Env instance (if it hasn't been created yet). If
+ // |create_event_source| is true a PlatformEventSource is created.
+ // TODO(sky): nuke |create_event_source|. Only necessary while mojo's
+ // nativeviewportservice lives in the same process as the viewmanager.
+ static void CreateInstance(bool create_event_source);
static Env* GetInstance();
static void DeleteInstance();
void AddObserver(EnvObserver* observer);
void RemoveObserver(EnvObserver* observer);
+ const int mouse_button_flags() const { return mouse_button_flags_; }
void set_mouse_button_flags(int mouse_button_flags) {
mouse_button_flags_ = mouse_button_flags;
}
@@ -65,29 +61,30 @@ class AURA_EXPORT Env : public ui::EventTarget {
bool is_touch_down() const { return is_touch_down_; }
void set_touch_down(bool value) { is_touch_down_ = value; }
- // Returns the native event dispatcher. The result should only be passed to
- // base::RunLoop(dispatcher), or used to dispatch an event by
- // |Dispatch(const NativeEvent&)| on it. It must never be stored.
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
- !defined(USE_GTK_MESSAGE_PUMP)
- base::MessageLoop::Dispatcher* GetDispatcher();
-#endif
-
- // Invoked by RootWindow when its host is activated.
- void RootWindowActivated(RootWindow* root_window);
+ void set_context_factory(ui::ContextFactory* context_factory) {
+ context_factory_ = context_factory;
+ }
+ ui::ContextFactory* context_factory() { return context_factory_; }
private:
friend class test::EnvTestHelper;
friend class Window;
- friend class RootWindow;
+ friend class WindowTreeHost;
+
+ Env();
+ virtual ~Env();
- void Init();
+ // See description of CreateInstance() for deatils of |create_event_source|.
+ void Init(bool create_event_source);
// Called by the Window when it is initialized. Notifies observers.
void NotifyWindowInitialized(Window* window);
- // Called by the RootWindow when it is initialized. Notifies observers.
- void NotifyRootWindowInitialized(RootWindow* root_window);
+ // Called by the WindowTreeHost when it is initialized. Notifies observers.
+ void NotifyHostInitialized(WindowTreeHost* host);
+
+ // Invoked by WindowTreeHost when it is activated. Notifies observers.
+ void NotifyHostActivated(WindowTreeHost* host);
// Overridden from ui::EventTarget:
virtual bool CanAcceptEvent(const ui::Event& event) OVERRIDE;
@@ -96,21 +93,16 @@ class AURA_EXPORT Env : public ui::EventTarget {
virtual ui::EventTargeter* GetEventTargeter() OVERRIDE;
ObserverList<EnvObserver> observers_;
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(USE_X11)
- scoped_ptr<base::MessageLoop::Dispatcher> dispatcher_;
-#endif
- static Env* instance_;
int mouse_button_flags_;
// Location of last mouse event, in screen coordinates.
gfx::Point last_mouse_location_;
bool is_touch_down_;
-#if defined(USE_X11)
- DeviceListUpdaterAuraX11 device_list_updater_aurax11_;
-#endif
-
scoped_ptr<InputStateLookup> input_state_lookup_;
+ scoped_ptr<ui::PlatformEventSource> event_source_;
+
+ ui::ContextFactory* context_factory_;
DISALLOW_COPY_AND_ASSIGN(Env);
};
diff --git a/chromium/ui/aura/env_observer.h b/chromium/ui/aura/env_observer.h
index b624f91b6ec..51a69466b32 100644
--- a/chromium/ui/aura/env_observer.h
+++ b/chromium/ui/aura/env_observer.h
@@ -9,19 +9,19 @@
namespace aura {
-class RootWindow;
class Window;
+class WindowTreeHost;
class AURA_EXPORT EnvObserver {
public:
// Called when |window| has been initialized.
virtual void OnWindowInitialized(Window* window) = 0;
- // Called when |root_window| has been initialized.
- virtual void OnRootWindowInitialized(RootWindow* root_window) {};
+ // Called when a WindowTreeHost is initialized.
+ virtual void OnHostInitialized(WindowTreeHost* host) {};
- // Called when a RootWindow's host is activated.
- virtual void OnRootWindowActivated(RootWindow* root_window) {}
+ // Called when a WindowTreeHost is activated.
+ virtual void OnHostActivated(WindowTreeHost* host) {}
// Called right before Env is destroyed.
virtual void OnWillDestroyEnv() {}
diff --git a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
index 3a18d1fffc4..596cb1f40cb 100644
--- a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
+++ b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -9,12 +9,12 @@
#include "base/timer/timer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/hit_test.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/event.h"
@@ -93,15 +93,11 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
scroll_velocity_y_(0),
velocity_x_(0),
velocity_y_(0),
- scroll_x_ordinal_(0),
- scroll_y_ordinal_(0),
- scroll_velocity_x_ordinal_(0),
- scroll_velocity_y_ordinal_(0),
- velocity_x_ordinal_(0),
- velocity_y_ordinal_(0),
+ scroll_x_hint_(0),
+ scroll_y_hint_(0),
tap_count_(0),
- wait_until_event_(ui::ET_UNKNOWN) {
- }
+ flags_(0),
+ wait_until_event_(ui::ET_UNKNOWN) {}
virtual ~GestureEventConsumeDelegate() {}
@@ -129,6 +125,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
scroll_begin_position_.SetPoint(0, 0);
tap_location_.SetPoint(0, 0);
+ gesture_end_location_.SetPoint(0, 0);
scroll_x_ = 0;
scroll_y_ = 0;
@@ -136,13 +133,12 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
scroll_velocity_y_ = 0;
velocity_x_ = 0;
velocity_y_ = 0;
- scroll_x_ordinal_ = 0;
- scroll_y_ordinal_ = 0;
- scroll_velocity_x_ordinal_ = 0;
- scroll_velocity_y_ordinal_ = 0;
- velocity_x_ordinal_ = 0;
- velocity_y_ordinal_ = 0;
+ scroll_x_hint_ = 0;
+ scroll_y_hint_ = 0;
tap_count_ = 0;
+ scale_ = 0;
+ flags_ = 0;
+ latency_info_.Clear();
}
const std::vector<ui::EventType>& events() const { return events_; };
@@ -168,40 +164,43 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
bool swipe_up() const { return swipe_up_; }
bool swipe_down() const { return swipe_down_; }
- const gfx::Point scroll_begin_position() const {
+ const gfx::Point& scroll_begin_position() const {
return scroll_begin_position_;
}
- const gfx::Point tap_location() const {
+ const gfx::Point& tap_location() const {
return tap_location_;
}
+ const gfx::Point& gesture_end_location() const {
+ return gesture_end_location_;
+ }
+
float scroll_x() const { return scroll_x_; }
float scroll_y() const { return scroll_y_; }
float scroll_velocity_x() const { return scroll_velocity_x_; }
float scroll_velocity_y() const { return scroll_velocity_y_; }
float velocity_x() const { return velocity_x_; }
float velocity_y() const { return velocity_y_; }
- float scroll_x_ordinal() const { return scroll_x_ordinal_; }
- float scroll_y_ordinal() const { return scroll_y_ordinal_; }
- float scroll_velocity_x_ordinal() const { return scroll_velocity_x_ordinal_; }
- float scroll_velocity_y_ordinal() const { return scroll_velocity_y_ordinal_; }
- float velocity_x_ordinal() const { return velocity_x_ordinal_; }
- float velocity_y_ordinal() const { return velocity_y_ordinal_; }
- int touch_id() const { return touch_id_; }
+ float scroll_x_hint() const { return scroll_x_hint_; }
+ float scroll_y_hint() const { return scroll_y_hint_; }
+ float scale() const { return scale_; }
const gfx::Rect& bounding_box() const { return bounding_box_; }
int tap_count() const { return tap_count_; }
+ int flags() const { return flags_; }
+ const ui::LatencyInfo& latency_info() const { return latency_info_; }
void WaitUntilReceivedGesture(ui::EventType type) {
wait_until_event_ = type;
- run_loop_.reset(new base::RunLoop(
- Env::GetInstance()->GetDispatcher()));
+ run_loop_.reset(new base::RunLoop());
run_loop_->Run();
}
virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE {
events_.push_back(gesture->type());
bounding_box_ = gesture->details().bounding_box();
+ flags_ = gesture->flags();
+ latency_info_ = *gesture->latency();
switch (gesture->type()) {
case ui::ET_GESTURE_TAP:
tap_location_ = gesture->location();
@@ -219,21 +218,18 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
break;
case ui::ET_GESTURE_END:
end_ = true;
+ gesture_end_location_ = gesture->location();
break;
case ui::ET_GESTURE_SCROLL_BEGIN:
scroll_begin_ = true;
scroll_begin_position_ = gesture->location();
+ scroll_x_hint_ = gesture->details().scroll_x_hint();
+ scroll_y_hint_ = gesture->details().scroll_y_hint();
break;
case ui::ET_GESTURE_SCROLL_UPDATE:
scroll_update_ = true;
scroll_x_ += gesture->details().scroll_x();
scroll_y_ += gesture->details().scroll_y();
- scroll_velocity_x_ = gesture->details().velocity_x();
- scroll_velocity_y_ = gesture->details().velocity_y();
- scroll_x_ordinal_ += gesture->details().scroll_x_ordinal();
- scroll_y_ordinal_ += gesture->details().scroll_y_ordinal();
- scroll_velocity_x_ordinal_ = gesture->details().velocity_x_ordinal();
- scroll_velocity_y_ordinal_ = gesture->details().velocity_y_ordinal();
break;
case ui::ET_GESTURE_SCROLL_END:
EXPECT_TRUE(velocity_x_ == 0 && velocity_y_ == 0);
@@ -244,13 +240,13 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
break;
case ui::ET_GESTURE_PINCH_UPDATE:
pinch_update_ = true;
+ scale_ = gesture->details().scale();
break;
case ui::ET_GESTURE_PINCH_END:
pinch_end_ = true;
break;
case ui::ET_GESTURE_LONG_PRESS:
long_press_ = true;
- touch_id_ = gesture->details().touch_id();
break;
case ui::ET_GESTURE_LONG_TAP:
long_tap_ = true;
@@ -262,8 +258,6 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
fling_ = true;
velocity_x_ = gesture->details().velocity_x();
velocity_y_ = gesture->details().velocity_y();
- velocity_x_ordinal_ = gesture->details().velocity_x_ordinal();
- velocity_y_ordinal_ = gesture->details().velocity_y_ordinal();
break;
case ui::ET_GESTURE_TWO_FINGER_TAP:
two_finger_tap_ = true;
@@ -271,12 +265,15 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
case ui::ET_GESTURE_SHOW_PRESS:
show_press_ = true;
break;
- case ui::ET_GESTURE_MULTIFINGER_SWIPE:
+ case ui::ET_GESTURE_SWIPE:
swipe_left_ = gesture->details().swipe_left();
swipe_right_ = gesture->details().swipe_right();
swipe_up_ = gesture->details().swipe_up();
swipe_down_ = gesture->details().swipe_down();
break;
+ case ui::ET_SCROLL_FLING_CANCEL:
+ // Only used in unified gesture detection.
+ break;
default:
NOTREACHED();
}
@@ -314,6 +311,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
gfx::Point scroll_begin_position_;
gfx::Point tap_location_;
+ gfx::Point gesture_end_location_;
float scroll_x_;
float scroll_y_;
@@ -321,15 +319,13 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
float scroll_velocity_y_;
float velocity_x_;
float velocity_y_;
- float scroll_x_ordinal_;
- float scroll_y_ordinal_;
- float scroll_velocity_x_ordinal_;
- float scroll_velocity_y_ordinal_;
- float velocity_x_ordinal_;
- float velocity_y_ordinal_;
- int touch_id_;
+ float scroll_x_hint_;
+ float scroll_y_hint_;
+ float scale_;
gfx::Rect bounding_box_;
int tap_count_;
+ int flags_;
+ ui::LatencyInfo latency_info_;
ui::EventType wait_until_event_;
@@ -338,9 +334,9 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
class QueueTouchEventDelegate : public GestureEventConsumeDelegate {
public:
- explicit QueueTouchEventDelegate(RootWindow* root_window)
+ explicit QueueTouchEventDelegate(WindowEventDispatcher* dispatcher)
: window_(NULL),
- root_window_(root_window),
+ dispatcher_(dispatcher),
queue_events_(true) {
}
virtual ~QueueTouchEventDelegate() {
@@ -371,14 +367,14 @@ class QueueTouchEventDelegate : public GestureEventConsumeDelegate {
private:
void ReceivedAckImpl(bool prevent_defaulted) {
scoped_ptr<ui::TouchEvent> event(queue_.front());
- root_window_->ProcessedTouchEvent(event.get(), window_,
+ dispatcher_->ProcessedTouchEvent(event.get(), window_,
prevent_defaulted ? ui::ER_HANDLED : ui::ER_UNHANDLED);
queue_.pop();
}
std::queue<ui::TouchEvent*> queue_;
Window* window_;
- RootWindow* root_window_;
+ WindowEventDispatcher* dispatcher_;
bool queue_events_;
DISALLOW_COPY_AND_ASSIGN(QueueTouchEventDelegate);
@@ -543,7 +539,9 @@ class TimedEvents {
int simulated_now_;
public:
- TimedEvents() : simulated_now_(0) {
+ // Use a non-zero start time to pass DCHECKs which ensure events have had a
+ // time assigned.
+ TimedEvents() : simulated_now_(1) {
}
base::TimeDelta Now() {
@@ -561,9 +559,9 @@ class TimedEvents {
return base::TimeDelta::FromMilliseconds(simulated_now_ + time_in_millis);
}
- void SendScrollEvents(RootWindow* root_window,
- int x_start,
- int y_start,
+ void SendScrollEvents(ui::EventProcessor* dispatcher,
+ float x_start,
+ float y_start,
int dx,
int dy,
int touch_id,
@@ -576,24 +574,26 @@ class TimedEvents {
for (int i = 0; i < num_steps; i++) {
x += dx;
y += dy;
- ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(x, y),
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::PointF(x, y),
touch_id,
base::TimeDelta::FromMilliseconds(simulated_now_));
- root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&move);
+ ASSERT_FALSE(details.dispatcher_destroyed);
simulated_now_ += time_step;
}
}
- void SendScrollEvent(RootWindow* root_window,
- int x,
- int y,
+ void SendScrollEvent(ui::EventProcessor* dispatcher,
+ float x,
+ float y,
int touch_id,
GestureEventConsumeDelegate* delegate) {
delegate->Reset();
- ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(x, y),
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::PointF(x, y),
touch_id,
base::TimeDelta::FromMilliseconds(simulated_now_));
- root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&move);
+ ASSERT_FALSE(details.dispatcher_destroyed);
simulated_now_++;
}
};
@@ -601,8 +601,9 @@ class TimedEvents {
// An event handler to keep track of events.
class TestEventHandler : public ui::EventHandler {
public:
- TestEventHandler() : touch_released_count_(0), touch_pressed_count_(0),
- touch_moved_count_(0), touch_stationary_count_(0),
+ TestEventHandler() : touch_released_count_(0),
+ touch_pressed_count_(0),
+ touch_moved_count_(0),
touch_cancelled_count_(0) {
}
@@ -619,9 +620,6 @@ class TestEventHandler : public ui::EventHandler {
case ui::ET_TOUCH_MOVED:
touch_moved_count_++;
break;
- case ui::ET_TOUCH_STATIONARY:
- touch_stationary_count_++;
- break;
case ui::ET_TOUCH_CANCELLED:
touch_cancelled_count_++;
break;
@@ -634,21 +632,18 @@ class TestEventHandler : public ui::EventHandler {
touch_released_count_ = 0;
touch_pressed_count_ = 0;
touch_moved_count_ = 0;
- touch_stationary_count_ = 0;
touch_cancelled_count_ = 0;
}
int touch_released_count() const { return touch_released_count_; }
int touch_pressed_count() const { return touch_pressed_count_; }
int touch_moved_count() const { return touch_moved_count_; }
- int touch_stationary_count() const { return touch_stationary_count_; }
int touch_cancelled_count() const { return touch_cancelled_count_; }
private:
int touch_released_count_;
int touch_pressed_count_;
int touch_moved_count_;
- int touch_stationary_count_;
int touch_cancelled_count_;
DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
@@ -679,21 +674,34 @@ class RemoveOnTouchCancelHandler : public TestEventHandler {
} // namespace
-class GestureRecognizerTest : public AuraTestBase {
+class GestureRecognizerTest : public AuraTestBase,
+ public ::testing::WithParamInterface<bool> {
public:
GestureRecognizerTest() {}
+ bool UsingUnifiedGR() {
+ return GetParam();
+ }
+
virtual void SetUp() OVERRIDE {
- CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableScrollPrediction);
+ // TODO(tdresser): Once unified GR has landed, only run these tests once.
+ CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kUnifiedGestureDetector,
+ UsingUnifiedGR() ? switches::kUnifiedGestureDetectorEnabled
+ : switches::kUnifiedGestureDetectorDisabled);
+
AuraTestBase::SetUp();
+ ui::GestureConfiguration::set_min_touch_down_duration_in_seconds_for_click(
+ 0.001);
+ ui::GestureConfiguration::set_show_press_delay_in_ms(2);
+ ui::GestureConfiguration::set_long_press_time_in_seconds(0.003);
}
DISALLOW_COPY_AND_ASSIGN(GestureRecognizerTest);
};
// Check that appropriate touch events generate tap gesture events.
-TEST_F(GestureRecognizerTest, GestureEventTap) {
+TEST_P(GestureRecognizerTest, GestureEventTap) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -707,7 +715,7 @@ TEST_F(GestureRecognizerTest, GestureEventTap) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->show_press());
EXPECT_TRUE(delegate->tap_down());
@@ -729,7 +737,7 @@ TEST_F(GestureRecognizerTest, GestureEventTap) {
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -744,7 +752,12 @@ TEST_F(GestureRecognizerTest, GestureEventTap) {
// Check that appropriate touch events generate tap gesture events
// when information about the touch radii are provided.
-TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
+TEST_P(GestureRecognizerTest, GestureEventTapRegion) {
+ // TODO(tdresser): enable this test with unified GR once we resolve the
+ // bounding box differences. See crbug.com/366641.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -762,7 +775,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
kTouchId, tes.Now());
press.set_radius_x(5);
press.set_radius_y(12);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -780,7 +793,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
release.set_radius_x(5);
release.set_radius_y(12);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -805,7 +818,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
kTouchId, tes.Now());
press.set_radius_x(8);
press.set_radius_y(14);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -821,7 +834,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
release.set_radius_x(20);
release.set_radius_y(13);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -846,7 +859,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
kTouchId, tes.Now());
press.set_radius_x(6);
press.set_radius_y(10);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -862,7 +875,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
kTouchId, tes.LeapForward(50));
move.set_radius_x(8);
move.set_radius_y(12);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ DispatchEventUsingWindowDispatcher(&move);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -878,7 +891,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
release.set_radius_x(4);
release.set_radius_y(8);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -903,7 +916,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
kTouchId, tes.Now());
press.set_radius_x(7);
press.set_radius_y(10);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -918,7 +931,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
kTouchId, tes.LeapForward(50));
move.set_radius_x(13);
move.set_radius_y(12);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ DispatchEventUsingWindowDispatcher(&move);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -933,7 +946,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
kTouchId, tes.LeapForward(50));
move1.set_radius_x(16);
move1.set_radius_y(16);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1);
+ DispatchEventUsingWindowDispatcher(&move1);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -948,7 +961,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
kTouchId, tes.LeapForward(50));
move2.set_radius_x(14);
move2.set_radius_y(10);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -964,7 +977,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
release.set_radius_x(8);
release.set_radius_y(9);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -984,7 +997,12 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
}
// Check that appropriate touch events generate scroll gesture events.
-TEST_F(GestureRecognizerTest, GestureEventScroll) {
+TEST_P(GestureRecognizerTest, GestureEventScroll) {
+ // We'll start by moving the touch point by (10.5, 10.5). We want 5 dips of
+ // that distance to be consumed by the slop, so we set the slop radius to
+ // sqrt(5 * 5 + 5 * 5).
+ ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(
+ sqrt(static_cast<double>(5 * 5 + 5 * 5)));
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -998,7 +1016,7 @@ TEST_F(GestureRecognizerTest, GestureEventScroll) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_BEGIN,
ui::ET_GESTURE_TAP_DOWN);
@@ -1007,13 +1025,15 @@ TEST_F(GestureRecognizerTest, GestureEventScroll) {
// should generate both SCROLL_BEGIN and SCROLL_UPDATE gestures.
// The first movement is diagonal, to ensure that we have a free scroll,
// and not a rail scroll.
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 111.5, 211.5, kTouchId,
+ delegate.get());
EXPECT_3_EVENTS(delegate->events(),
ui::ET_GESTURE_TAP_CANCEL,
ui::ET_GESTURE_SCROLL_BEGIN,
ui::ET_GESTURE_SCROLL_UPDATE);
- EXPECT_EQ(29, delegate->scroll_x());
- EXPECT_EQ(29, delegate->scroll_y());
+ // The slop consumed 5 dips
+ EXPECT_FLOAT_EQ(5.5, delegate->scroll_x());
+ EXPECT_FLOAT_EQ(5.5, delegate->scroll_y());
EXPECT_EQ(gfx::Point(1, 1).ToString(),
delegate->scroll_begin_position().ToString());
@@ -1021,14 +1041,15 @@ TEST_F(GestureRecognizerTest, GestureEventScroll) {
// be empty, since it's a single point and the radius for testing is zero.
EXPECT_TRUE(delegate->bounding_box().IsEmpty());
- // Move some more to generate a few more scroll updates.
- tes.SendScrollEvent(dispatcher(), 110, 211, kTouchId, delegate.get());
+ // Move some more to generate a few more scroll updates. Make sure that we get
+ // out of the snap channel for the unified GR.
+ tes.SendScrollEvent(event_processor(), 20, 120, kTouchId, delegate.get());
EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
- EXPECT_EQ(-20, delegate->scroll_x());
- EXPECT_EQ(-19, delegate->scroll_y());
+ EXPECT_FLOAT_EQ(-91.5, delegate->scroll_x());
+ EXPECT_FLOAT_EQ(-91.5, delegate->scroll_y());
EXPECT_TRUE(delegate->bounding_box().IsEmpty());
- tes.SendScrollEvent(dispatcher(), 140, 215, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 50, 124, kTouchId, delegate.get());
EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
EXPECT_EQ(30, delegate->scroll_x());
EXPECT_EQ(4, delegate->scroll_y());
@@ -1039,7 +1060,7 @@ TEST_F(GestureRecognizerTest, GestureEventScroll) {
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId,
tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_SCROLL_FLING_START,
ui::ET_GESTURE_END);
@@ -1047,16 +1068,22 @@ TEST_F(GestureRecognizerTest, GestureEventScroll) {
}
// Check that predicted scroll update positions are correct.
-TEST_F(GestureRecognizerTest, GestureEventScrollPrediction) {
+TEST_P(GestureRecognizerTest, GestureEventScrollPrediction) {
const double prediction_interval = 0.03;
ui::GestureConfiguration::set_scroll_prediction_seconds(prediction_interval);
+ // We'll start by moving the touch point by (5, 5). We want all of that
+ // distance to be consumed by the slop, so we set the slop radius to
+ // sqrt(5 * 5 + 5 * 5).
+ ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(
+ sqrt(static_cast<double>(5 * 5 + 5 * 5)));
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
const int kWindowWidth = 123;
const int kWindowHeight = 45;
const int kTouchId = 5;
- gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight);
+ gfx::Rect bounds(95, 195, kWindowWidth, kWindowHeight);
scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
delegate.get(), -1234, bounds, root_window()));
@@ -1064,63 +1091,59 @@ TEST_F(GestureRecognizerTest, GestureEventScrollPrediction) {
// Tracks the total scroll since we want to verify that the correct position
// will be scrolled to throughout the prediction.
gfx::Vector2dF total_scroll;
- ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
+ ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(96, 196),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_BEGIN,
ui::ET_GESTURE_TAP_DOWN);
+ delegate->Reset();
+
+ // Get rid of touch slop.
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(111, 211),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move);
+ EXPECT_3_EVENTS(delegate->events(),
+ ui::ET_GESTURE_TAP_CANCEL,
+ ui::ET_GESTURE_SCROLL_BEGIN,
+ ui::ET_GESTURE_SCROLL_UPDATE);
+ total_scroll.set_x(total_scroll.x() + delegate->scroll_x());
+ total_scroll.set_y(total_scroll.y() + delegate->scroll_y());
// Move the touch-point enough so that it is considered as a scroll. This
// should generate both SCROLL_BEGIN and SCROLL_UPDATE gestures.
// The first movement is diagonal, to ensure that we have a free scroll,
// and not a rail scroll.
tes.LeapForward(30);
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId, delegate.get());
- EXPECT_3_EVENTS(delegate->events(),
- ui::ET_GESTURE_TAP_CANCEL,
- ui::ET_GESTURE_SCROLL_BEGIN,
- ui::ET_GESTURE_SCROLL_UPDATE);
- EXPECT_GT(delegate->scroll_velocity_x(), 0);
- EXPECT_GT(delegate->scroll_velocity_y(), 0);
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId, delegate.get());
+ EXPECT_1_EVENT(delegate->events(),
+ ui::ET_GESTURE_SCROLL_UPDATE);
total_scroll.set_x(total_scroll.x() + delegate->scroll_x());
total_scroll.set_y(total_scroll.y() + delegate->scroll_y());
- EXPECT_EQ((int)(29 + delegate->scroll_velocity_x() * prediction_interval),
- (int)(total_scroll.x()));
- EXPECT_EQ((int)(29 + delegate->scroll_velocity_y() * prediction_interval),
- (int)(total_scroll.y()));
// Move some more to generate a few more scroll updates.
tes.LeapForward(30);
- tes.SendScrollEvent(dispatcher(), 110, 211, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 110, 211, kTouchId, delegate.get());
EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
total_scroll.set_x(total_scroll.x() + delegate->scroll_x());
total_scroll.set_y(total_scroll.y() + delegate->scroll_y());
- EXPECT_EQ((int)(9 + delegate->scroll_velocity_x() * prediction_interval),
- (int)(total_scroll.x()));
- EXPECT_EQ((int)(10 + delegate->scroll_velocity_y() * prediction_interval),
- (int)(total_scroll.y()));
tes.LeapForward(30);
- tes.SendScrollEvent(dispatcher(), 140, 215, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 140, 215, kTouchId, delegate.get());
EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
total_scroll.set_x(total_scroll.x() + delegate->scroll_x());
total_scroll.set_y(total_scroll.y() + delegate->scroll_y());
- EXPECT_EQ((int)(39 + delegate->scroll_velocity_x() * prediction_interval),
- (int)(total_scroll.x()));
- EXPECT_EQ((int)(14 + delegate->scroll_velocity_y() * prediction_interval),
- (int)(total_scroll.y()));
// Release the touch. This should end the scroll.
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId,
tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
}
// Check that the bounding box during a scroll event is correct.
-TEST_F(GestureRecognizerTest, GestureEventScrollBoundingBox) {
+TEST_P(GestureRecognizerTest, GestureEventScrollBoundingBox) {
TimedEvents tes;
for (int radius = 1; radius <= 10; ++radius) {
ui::GestureConfiguration::set_default_radius(radius);
@@ -1140,7 +1163,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollBoundingBox) {
gfx::Point(kPositionX, kPositionY),
kTouchId,
tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_EQ(gfx::Rect(kPositionX - radius,
kPositionY - radius,
radius * 2,
@@ -1148,7 +1171,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollBoundingBox) {
delegate->bounding_box().ToString());
const int kScrollAmount = 50;
- tes.SendScrollEvents(dispatcher(), kPositionX, kPositionY,
+ tes.SendScrollEvents(event_processor(), kPositionX, kPositionY,
1, 1, kTouchId, 1, kScrollAmount, delegate.get());
EXPECT_EQ(gfx::Point(1, 1).ToString(),
delegate->scroll_begin_position().ToString());
@@ -1165,7 +1188,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollBoundingBox) {
kPositionY + kScrollAmount),
kTouchId, press.time_stamp() +
base::TimeDelta::FromMilliseconds(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_EQ(gfx::Rect(kPositionX + kScrollAmount - radius,
kPositionY + kScrollAmount - radius,
radius * 2,
@@ -1177,7 +1200,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollBoundingBox) {
// Check Scroll End Events report correct velocities
// if the user was on a horizontal rail
-TEST_F(GestureRecognizerTest, GestureEventHorizontalRailFling) {
+TEST_P(GestureRecognizerTest, GestureEventHorizontalRailFling) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -1188,30 +1211,31 @@ TEST_F(GestureRecognizerTest, GestureEventHorizontalRailFling) {
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
+
+ // Get rid of touch slop.
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 0),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move);
+ delegate->Reset();
+
// Move the touch-point horizontally enough that it is considered a
// horizontal scroll.
- tes.SendScrollEvent(dispatcher(), 20, 1, kTouchId, delegate.get());
- EXPECT_EQ(0, delegate->scroll_y());
- EXPECT_EQ(1, delegate->scroll_y_ordinal());
- EXPECT_EQ(20, delegate->scroll_x());
- EXPECT_EQ(20, delegate->scroll_x_ordinal());
+ tes.SendScrollEvent(event_processor(), 30, 1, kTouchId, delegate.get());
+ EXPECT_FLOAT_EQ(0, delegate->scroll_y());
+ EXPECT_FLOAT_EQ(20, delegate->scroll_x());
// Get a high x velocity, while still staying on the rail
- tes.SendScrollEvents(dispatcher(), 1, 1,
+ tes.SendScrollEvents(event_processor(), 1, 1,
100, 10, kTouchId, 1,
ui::GestureConfiguration::points_buffered_for_velocity(),
delegate.get());
- // The y-velocity during the scroll should be 0 since this is in a horizontal
- // rail scroll.
- EXPECT_GT(delegate->scroll_velocity_x(), 0);
- EXPECT_EQ(0, delegate->scroll_velocity_y());
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->fling());
EXPECT_FALSE(delegate->scroll_end());
@@ -1221,7 +1245,7 @@ TEST_F(GestureRecognizerTest, GestureEventHorizontalRailFling) {
// Check Scroll End Events report correct velocities
// if the user was on a vertical rail
-TEST_F(GestureRecognizerTest, GestureEventVerticalRailFling) {
+TEST_P(GestureRecognizerTest, GestureEventVerticalRailFling) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -1232,30 +1256,32 @@ TEST_F(GestureRecognizerTest, GestureEventVerticalRailFling) {
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
+
+ // Get rid of touch slop.
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(0, 10),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move);
+ delegate->Reset();
// Move the touch-point vertically enough that it is considered a
// vertical scroll.
- tes.SendScrollEvent(dispatcher(), 1, 20, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 1, 30, kTouchId, delegate.get());
EXPECT_EQ(20, delegate->scroll_y());
- EXPECT_EQ(20, delegate->scroll_y_ordinal());
EXPECT_EQ(0, delegate->scroll_x());
- EXPECT_EQ(1, delegate->scroll_x_ordinal());
EXPECT_EQ(0, delegate->scroll_velocity_x());
- EXPECT_GT(delegate->scroll_velocity_x_ordinal(), 0);
// Get a high y velocity, while still staying on the rail
- tes.SendScrollEvents(dispatcher(), 1, 1,
+ tes.SendScrollEvents(event_processor(), 1, 6,
10, 100, kTouchId, 1,
ui::GestureConfiguration::points_buffered_for_velocity(),
delegate.get());
EXPECT_EQ(0, delegate->scroll_velocity_x());
- EXPECT_GT(delegate->scroll_velocity_y(), 0);
delegate->Reset();
- ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
+ ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 206),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->fling());
EXPECT_FALSE(delegate->scroll_end());
@@ -1263,9 +1289,10 @@ TEST_F(GestureRecognizerTest, GestureEventVerticalRailFling) {
EXPECT_GT(delegate->velocity_y(), 0);
}
-// Check Scroll End Events reports zero velocities
-// if the user is not on a rail
-TEST_F(GestureRecognizerTest, GestureEventNonRailFling) {
+// Check Scroll End Events report non-zero velocities if the user is not on a
+// rail
+TEST_P(GestureRecognizerTest, GestureEventNonRailFling) {
+ ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(0);
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -1276,14 +1303,15 @@ TEST_F(GestureRecognizerTest, GestureEventNonRailFling) {
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
- // Move the touch-point such that a non-rail scroll begins
- tes.SendScrollEvent(dispatcher(), 20, 20, kTouchId, delegate.get());
- EXPECT_EQ(20, delegate->scroll_y());
- EXPECT_EQ(20, delegate->scroll_x());
+ // Move the touch-point such that a non-rail scroll begins, and we're outside
+ // the snap channel for the unified GR.
+ tes.SendScrollEvent(event_processor(), 50, 50, kTouchId, delegate.get());
+ EXPECT_EQ(50, delegate->scroll_y());
+ EXPECT_EQ(50, delegate->scroll_x());
- tes.SendScrollEvents(dispatcher(), 1, 1,
+ tes.SendScrollEvents(event_processor(), 1, 1,
10, 100, kTouchId, 1,
ui::GestureConfiguration::points_buffered_for_velocity(),
delegate.get());
@@ -1291,7 +1319,7 @@ TEST_F(GestureRecognizerTest, GestureEventNonRailFling) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->fling());
EXPECT_FALSE(delegate->scroll_end());
@@ -1300,10 +1328,12 @@ TEST_F(GestureRecognizerTest, GestureEventNonRailFling) {
}
// Check that appropriate touch events generate long press events
-TEST_F(GestureRecognizerTest, GestureEventLongPress) {
+TEST_P(GestureRecognizerTest, GestureEventLongPress) {
+ ui::GestureConfiguration::set_max_touch_down_duration_in_seconds_for_click(
+ 0.0025);
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
- TimedEvents tes;
const int kWindowWidth = 123;
const int kWindowHeight = 45;
const int kTouchId = 2;
@@ -1318,9 +1348,11 @@ TEST_F(GestureRecognizerTest, GestureEventLongPress) {
ScopedGestureRecognizerSetter gr_setter(gesture_recognizer);
- ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
- kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED,
+ gfx::Point(101, 201),
+ kTouchId,
+ ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_TRUE(delegate->tap_down());
EXPECT_TRUE(delegate->begin());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1331,25 +1363,26 @@ TEST_F(GestureRecognizerTest, GestureEventLongPress) {
// Wait until the timer runs out
delegate->WaitUntilReceivedGesture(ui::ET_GESTURE_LONG_PRESS);
EXPECT_TRUE(delegate->long_press());
- EXPECT_EQ(0, delegate->touch_id());
EXPECT_FALSE(delegate->tap_cancel());
delegate->Reset();
- ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
- kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ ui::TouchEvent release1(ui::ET_TOUCH_RELEASED,
+ gfx::Point(101, 201),
+ kTouchId,
+ ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->long_press());
- // Note the tap down isn't cancelled until the release
+ // Note the tap cancel isn't dispatched until the release
EXPECT_TRUE(delegate->tap_cancel());
+ EXPECT_FALSE(delegate->tap());
}
// Check that scrolling cancels a long press
-TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledByScroll) {
+TEST_P(GestureRecognizerTest, GestureEventLongPressCancelledByScroll) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
- ui::GestureConfiguration::set_long_press_time_in_seconds(.01);
const int kWindowWidth = 123;
const int kWindowHeight = 45;
const int kTouchId = 6;
@@ -1369,7 +1402,7 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledByScroll) {
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_TRUE(delegate->tap_down());
// We haven't pressed long enough for a long press to occur
@@ -1377,7 +1410,7 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledByScroll) {
EXPECT_FALSE(delegate->tap_cancel());
// Scroll around, to cancel the long press
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId, delegate.get());
// Wait until the timer runs out
gesture_sequence->ForceTimeout();
EXPECT_FALSE(delegate->long_press());
@@ -1386,16 +1419,17 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledByScroll) {
delegate->Reset();
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(10));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->long_press());
EXPECT_FALSE(delegate->tap_cancel());
}
// Check that appropriate touch events generate long tap events
-TEST_F(GestureRecognizerTest, GestureEventLongTap) {
+TEST_P(GestureRecognizerTest, GestureEventLongTap) {
+ ui::GestureConfiguration::set_max_touch_down_duration_in_seconds_for_click(
+ 0.0025);
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
- TimedEvents tes;
const int kWindowWidth = 123;
const int kWindowHeight = 45;
const int kTouchId = 2;
@@ -1410,9 +1444,11 @@ TEST_F(GestureRecognizerTest, GestureEventLongTap) {
ScopedGestureRecognizerSetter gr_setter(gesture_recognizer);
- ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
- kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED,
+ gfx::Point(101, 201),
+ kTouchId,
+ ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_TRUE(delegate->tap_down());
EXPECT_TRUE(delegate->begin());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1423,26 +1459,27 @@ TEST_F(GestureRecognizerTest, GestureEventLongTap) {
// Wait until the timer runs out
delegate->WaitUntilReceivedGesture(ui::ET_GESTURE_LONG_PRESS);
EXPECT_TRUE(delegate->long_press());
- EXPECT_EQ(0, delegate->touch_id());
EXPECT_FALSE(delegate->tap_cancel());
delegate->Reset();
- ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
- kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ ui::TouchEvent release1(ui::ET_TOUCH_RELEASED,
+ gfx::Point(101, 201),
+ kTouchId,
+ ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->long_press());
EXPECT_TRUE(delegate->long_tap());
- // Note the tap down isn't cancelled until the release
+ // Note the tap cancel isn't dispatched until the release
EXPECT_TRUE(delegate->tap_cancel());
+ EXPECT_FALSE(delegate->tap());
}
// Check that second tap cancels a long press
-TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledBySecondTap) {
+TEST_P(GestureRecognizerTest, GestureEventLongPressCancelledBySecondTap) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
- ui::GestureConfiguration::set_long_press_time_in_seconds(.01);
const int kWindowWidth = 300;
const int kWindowHeight = 400;
const int kTouchId1 = 8;
@@ -1462,7 +1499,7 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledBySecondTap) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_TRUE(delegate->tap_down());
EXPECT_TRUE(delegate->begin());
@@ -1473,7 +1510,7 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledBySecondTap) {
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_FALSE(delegate->tap_down()); // no touch down for second tap.
EXPECT_TRUE(delegate->tap_cancel());
EXPECT_TRUE(delegate->begin());
@@ -1487,7 +1524,7 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledBySecondTap) {
delegate->Reset();
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->long_press());
EXPECT_TRUE(delegate->two_finger_tap());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1495,7 +1532,7 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledBySecondTap) {
// Check that horizontal scroll gestures cause scrolls on horizontal rails.
// Also tests that horizontal rails can be broken.
-TEST_F(GestureRecognizerTest, GestureEventHorizontalRailScroll) {
+TEST_P(GestureRecognizerTest, GestureEventHorizontalRailScroll) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -1506,15 +1543,22 @@ TEST_F(GestureRecognizerTest, GestureEventHorizontalRailScroll) {
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
+
+ // Get rid of touch slop.
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(5, 0),
+ kTouchId, tes.Now());
+
+ DispatchEventUsingWindowDispatcher(&move);
+ delegate->Reset();
// Move the touch-point horizontally enough that it is considered a
// horizontal scroll.
- tes.SendScrollEvent(dispatcher(), 20, 1, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 25, 0, kTouchId, delegate.get());
EXPECT_EQ(0, delegate->scroll_y());
EXPECT_EQ(20, delegate->scroll_x());
- tes.SendScrollEvent(dispatcher(), 25, 6, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 30, 6, kTouchId, delegate.get());
EXPECT_TRUE(delegate->scroll_update());
EXPECT_EQ(5, delegate->scroll_x());
// y shouldn't change, as we're on a horizontal rail.
@@ -1522,17 +1566,13 @@ TEST_F(GestureRecognizerTest, GestureEventHorizontalRailScroll) {
// Send enough information that a velocity can be calculated for the gesture,
// and we can break the rail
- tes.SendScrollEvents(dispatcher(), 1, 1,
- 1, 100, kTouchId, 1,
+ tes.SendScrollEvents(event_processor(), 1, 1,
+ 6, 100, kTouchId, 1,
ui::GestureConfiguration::points_buffered_for_velocity(),
delegate.get());
- // Since the scroll is not longer railing, the velocity should be set for both
- // axis.
- EXPECT_GT(delegate->scroll_velocity_x(), 0);
- EXPECT_GT(delegate->scroll_velocity_y(), 0);
- tes.SendScrollEvent(dispatcher(), 0, 0, kTouchId, delegate.get());
- tes.SendScrollEvent(dispatcher(), 5, 5, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 5, 0, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 10, 5, kTouchId, delegate.get());
// The rail should be broken
EXPECT_TRUE(delegate->scroll_update());
@@ -1542,7 +1582,7 @@ TEST_F(GestureRecognizerTest, GestureEventHorizontalRailScroll) {
// Check that vertical scroll gestures cause scrolls on vertical rails.
// Also tests that vertical rails can be broken.
-TEST_F(GestureRecognizerTest, GestureEventVerticalRailScroll) {
+TEST_P(GestureRecognizerTest, GestureEventVerticalRailScroll) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -1553,15 +1593,21 @@ TEST_F(GestureRecognizerTest, GestureEventVerticalRailScroll) {
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
+
+ // Get rid of touch slop.
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(0, 5),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move);
+ delegate->Reset();
// Move the touch-point vertically enough that it is considered a
// vertical scroll.
- tes.SendScrollEvent(dispatcher(), 1, 20, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 0, 25, kTouchId, delegate.get());
EXPECT_EQ(0, delegate->scroll_x());
EXPECT_EQ(20, delegate->scroll_y());
- tes.SendScrollEvent(dispatcher(), 6, 25, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 6, 30, kTouchId, delegate.get());
EXPECT_TRUE(delegate->scroll_update());
EXPECT_EQ(5, delegate->scroll_y());
// x shouldn't change, as we're on a vertical rail.
@@ -1570,15 +1616,13 @@ TEST_F(GestureRecognizerTest, GestureEventVerticalRailScroll) {
// Send enough information that a velocity can be calculated for the gesture,
// and we can break the rail
- tes.SendScrollEvents(dispatcher(), 1, 1,
+ tes.SendScrollEvents(event_processor(), 1, 6,
100, 1, kTouchId, 1,
ui::GestureConfiguration::points_buffered_for_velocity(),
delegate.get());
- EXPECT_GT(delegate->scroll_velocity_x(), 0);
- EXPECT_GT(delegate->scroll_velocity_y(), 0);
- tes.SendScrollEvent(dispatcher(), 0, 0, kTouchId, delegate.get());
- tes.SendScrollEvent(dispatcher(), 5, 5, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 0, 5, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 5, 10, kTouchId, delegate.get());
// The rail should be broken
EXPECT_TRUE(delegate->scroll_update());
@@ -1586,7 +1630,13 @@ TEST_F(GestureRecognizerTest, GestureEventVerticalRailScroll) {
EXPECT_EQ(5, delegate->scroll_y());
}
-TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
+TEST_P(GestureRecognizerTest, GestureTapFollowedByScroll) {
+ // We'll start by moving the touch point by (5, 5). We want all of that
+ // distance to be consumed by the slop, so we set the slop radius to
+ // sqrt(5 * 5 + 5 * 5).
+ ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(
+ sqrt(static_cast<double>(5 * 5 + 5 * 5)));
+
// First, tap. Then, do a scroll using the same touch-id.
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
@@ -1601,7 +1651,7 @@ TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1614,7 +1664,7 @@ TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1627,7 +1677,7 @@ TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(1000));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1635,28 +1685,40 @@ TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
EXPECT_FALSE(delegate->scroll_update());
EXPECT_FALSE(delegate->scroll_end());
+ // Get rid of touch slop.
+ ui::TouchEvent move_remove_slop(ui::ET_TOUCH_MOVED, gfx::Point(116, 216),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move_remove_slop);
+ EXPECT_TRUE(delegate->tap_cancel());
+ EXPECT_TRUE(delegate->scroll_begin());
+ EXPECT_TRUE(delegate->scroll_update());
+ EXPECT_EQ(15, delegate->scroll_x_hint());
+ EXPECT_EQ(15, delegate->scroll_y_hint());
+
+ delegate->Reset();
+
// Move the touch-point enough so that it is considered as a scroll. This
// should generate both SCROLL_BEGIN and SCROLL_UPDATE gestures.
// The first movement is diagonal, to ensure that we have a free scroll,
// and not a rail scroll.
delegate->Reset();
- ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(130, 230),
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(135, 235),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ DispatchEventUsingWindowDispatcher(&move);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
- EXPECT_TRUE(delegate->tap_cancel());
- EXPECT_TRUE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->tap_cancel());
+ EXPECT_FALSE(delegate->scroll_begin());
EXPECT_TRUE(delegate->scroll_update());
EXPECT_FALSE(delegate->scroll_end());
- EXPECT_EQ(29, delegate->scroll_x());
- EXPECT_EQ(29, delegate->scroll_y());
+ EXPECT_EQ(19, delegate->scroll_x());
+ EXPECT_EQ(19, delegate->scroll_y());
// Move some more to generate a few more scroll updates.
delegate->Reset();
- ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(110, 211),
+ ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(115, 216),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1);
+ DispatchEventUsingWindowDispatcher(&move1);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1665,11 +1727,13 @@ TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
EXPECT_FALSE(delegate->scroll_end());
EXPECT_EQ(-20, delegate->scroll_x());
EXPECT_EQ(-19, delegate->scroll_y());
+ EXPECT_EQ(0, delegate->scroll_x_hint());
+ EXPECT_EQ(0, delegate->scroll_y_hint());
delegate->Reset();
- ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(140, 215),
+ ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(145, 220),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1683,7 +1747,7 @@ TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
delegate->Reset();
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1693,9 +1757,9 @@ TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
EXPECT_TRUE(delegate->fling());
}
-TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
+TEST_P(GestureRecognizerTest, AsynchronousGestureRecognition) {
scoped_ptr<QueueTouchEventDelegate> queued_delegate(
- new QueueTouchEventDelegate(dispatcher()));
+ new QueueTouchEventDelegate(host()->dispatcher()));
const int kWindowWidth = 123;
const int kWindowHeight = 45;
const int kTouchId1 = 6;
@@ -1710,7 +1774,7 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
queued_delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(queued_delegate->tap());
EXPECT_FALSE(queued_delegate->tap_down());
EXPECT_FALSE(queued_delegate->tap_cancel());
@@ -1725,7 +1789,7 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, press.time_stamp() +
base::TimeDelta::FromMilliseconds(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_FALSE(queued_delegate->tap());
EXPECT_FALSE(queued_delegate->tap_down());
EXPECT_FALSE(queued_delegate->tap_cancel());
@@ -1744,7 +1808,7 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(10, 20),
kTouchId2, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1756,7 +1820,7 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(10, 20),
kTouchId2, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&release2);
// Process the first queued event.
queued_delegate->Reset();
@@ -1787,7 +1851,7 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
queued_delegate->Reset();
ui::TouchEvent press3(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press3);
+ DispatchEventUsingWindowDispatcher(&press3);
EXPECT_FALSE(queued_delegate->tap());
EXPECT_FALSE(queued_delegate->tap_down());
EXPECT_FALSE(queued_delegate->tap_cancel());
@@ -1803,7 +1867,7 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
delegate->Reset();
ui::TouchEvent press4(ui::ET_TOUCH_PRESSED, gfx::Point(103, 203),
kTouchId2, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press4);
+ DispatchEventUsingWindowDispatcher(&press4);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1826,9 +1890,9 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
queued_delegate->Reset();
delegate->Reset();
int x_move = ui::GestureConfiguration::max_touch_move_in_pixels_for_click();
- ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(103 + x_move, 203),
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(203 + x_move, 303),
kTouchId2, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ DispatchEventUsingWindowDispatcher(&move);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -1877,7 +1941,8 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
EXPECT_FALSE(queued_delegate->begin());
EXPECT_FALSE(queued_delegate->end());
EXPECT_TRUE(queued_delegate->scroll_begin());
- EXPECT_FALSE(queued_delegate->scroll_update());
+ // TODO(tdresser): uncomment once we've switched to the unified GR.
+ // EXPECT_TRUE(queued_delegate->scroll_update());
EXPECT_FALSE(queued_delegate->scroll_end());
EXPECT_TRUE(queued_delegate->pinch_begin());
EXPECT_FALSE(queued_delegate->pinch_update());
@@ -1885,7 +1950,12 @@ TEST_F(GestureRecognizerTest, AsynchronousGestureRecognition) {
}
// Check that appropriate touch events generate pinch gesture events.
-TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
+TEST_P(GestureRecognizerTest, GestureEventPinchFromScroll) {
+ // Disabled for unified GR due to differences in when pinch begin is sent. The
+ // Aura GR sends it earlier than is necessary.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -1897,12 +1967,10 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
delegate.get(), -1234, bounds, root_window()));
- aura::RootWindow* root = dispatcher();
-
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_BEGIN,
ui::ET_GESTURE_TAP_DOWN);
@@ -1912,7 +1980,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
delegate->Reset();
ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(130, 301),
kTouchId1, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ DispatchEventUsingWindowDispatcher(&move);
EXPECT_3_EVENTS(delegate->events(),
ui::ET_GESTURE_TAP_CANCEL,
ui::ET_GESTURE_SCROLL_BEGIN,
@@ -1923,7 +1991,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10),
kTouchId2, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_BEGIN,
ui::ET_GESTURE_PINCH_BEGIN);
@@ -1934,7 +2002,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
delegate->Reset();
ui::TouchEvent move3(ui::ET_TOUCH_MOVED, gfx::Point(95, 201),
kTouchId1, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move3);
+ DispatchEventUsingWindowDispatcher(&move3);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_PINCH_UPDATE,
ui::ET_GESTURE_SCROLL_UPDATE);
@@ -1945,7 +2013,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
delegate->Reset();
ui::TouchEvent move4(ui::ET_TOUCH_MOVED, gfx::Point(55, 15),
kTouchId2, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move4);
+ DispatchEventUsingWindowDispatcher(&move4);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_PINCH_UPDATE,
ui::ET_GESTURE_SCROLL_UPDATE);
@@ -1956,7 +2024,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_PINCH_END,
ui::ET_GESTURE_END);
@@ -1967,12 +2035,12 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
delegate->Reset();
ui::TouchEvent move5(ui::ET_TOUCH_MOVED, gfx::Point(25, 10),
kTouchId2, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move5);
+ DispatchEventUsingWindowDispatcher(&move5);
EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
EXPECT_TRUE(delegate->bounding_box().IsEmpty());
}
-TEST_F(GestureRecognizerTest, GestureEventPinchFromScrollFromPinch) {
+TEST_P(GestureRecognizerTest, GestureEventPinchFromScrollFromPinch) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -1986,20 +2054,20 @@ scoped_ptr<GestureEventConsumeDelegate> delegate(
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 301),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_FALSE(delegate->pinch_begin());
// Touch move triggers pinch begin.
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId1, delegate.get());
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId1, delegate.get());
EXPECT_TRUE(delegate->pinch_begin());
EXPECT_FALSE(delegate->pinch_update());
// Touch move triggers pinch update.
- tes.SendScrollEvent(dispatcher(), 160, 200, kTouchId1, delegate.get());
+ tes.SendScrollEvent(event_processor(), 160, 200, kTouchId1, delegate.get());
EXPECT_FALSE(delegate->pinch_begin());
EXPECT_TRUE(delegate->pinch_update());
@@ -2007,29 +2075,33 @@ scoped_ptr<GestureEventConsumeDelegate> delegate(
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->pinch_end());
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId2, delegate.get());
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId2, delegate.get());
EXPECT_TRUE(delegate->scroll_update());
// Pinch again
delegate->Reset();
ui::TouchEvent press3(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press3);
+ DispatchEventUsingWindowDispatcher(&press3);
// Now the touch points are close. So we will go into two finger tap.
// Move the touch-point enough to break two-finger-tap and enter pinch.
- ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(101, 202),
+ ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(101, 50),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
EXPECT_TRUE(delegate->pinch_begin());
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId1, delegate.get());
+ tes.SendScrollEvent(event_processor(), 350, 350, kTouchId1, delegate.get());
EXPECT_TRUE(delegate->pinch_update());
}
-TEST_F(GestureRecognizerTest, GestureEventPinchFromTap) {
+TEST_P(GestureRecognizerTest, GestureEventPinchFromTap) {
+ // TODO(tdresser): enable this test with unified GR once two finger tap.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -2041,12 +2113,10 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromTap) {
scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
delegate.get(), -1234, bounds, root_window()));
- aura::RootWindow* root = dispatcher();
-
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 301),
kTouchId1, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_BEGIN,
ui::ET_GESTURE_TAP_DOWN);
@@ -2056,7 +2126,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromTap) {
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10),
kTouchId2, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_TAP_CANCEL,
ui::ET_GESTURE_BEGIN);
@@ -2067,10 +2137,10 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromTap) {
delegate->Reset();
ui::TouchEvent move3(ui::ET_TOUCH_MOVED, gfx::Point(65, 201),
kTouchId1, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move3);
+ DispatchEventUsingWindowDispatcher(&move3);
EXPECT_2_EVENTS(delegate->events(),
- ui::ET_GESTURE_PINCH_BEGIN,
- ui::ET_GESTURE_SCROLL_BEGIN);
+ ui::ET_GESTURE_SCROLL_BEGIN,
+ ui::ET_GESTURE_PINCH_BEGIN);
EXPECT_EQ(gfx::Rect(10, 10, 55, 191).ToString(),
delegate->bounding_box().ToString());
@@ -2078,7 +2148,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromTap) {
delegate->Reset();
ui::TouchEvent move4(ui::ET_TOUCH_MOVED, gfx::Point(55, 15),
kTouchId2, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move4);
+ DispatchEventUsingWindowDispatcher(&move4);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_PINCH_UPDATE,
ui::ET_GESTURE_SCROLL_UPDATE);
@@ -2089,7 +2159,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromTap) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, tes.LeapForward(10));
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_PINCH_END,
ui::ET_GESTURE_END);
@@ -2100,26 +2170,26 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromTap) {
delegate->Reset();
ui::TouchEvent move5(ui::ET_TOUCH_MOVED, gfx::Point(25, 10),
kTouchId2, tes.Now());
- root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move5);
+ DispatchEventUsingWindowDispatcher(&move5);
EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
EXPECT_TRUE(delegate->bounding_box().IsEmpty());
}
-TEST_F(GestureRecognizerTest, GestureEventIgnoresDisconnectedEvents) {
+TEST_P(GestureRecognizerTest, GestureEventIgnoresDisconnectedEvents) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
6, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
}
// Check that a touch is locked to the window of the closest current touch
// within max_separation_for_gesture_touches_in_pixels
-TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
+TEST_P(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
ui::GestureRecognizer* gesture_recognizer = new ui::GestureRecognizerImpl();
TimedEvents tes;
ScopedGestureRecognizerSetter gr_setter(gesture_recognizer);
@@ -2150,50 +2220,50 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
windows[i]->set_id(i);
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, window_bounds[i].origin(),
i, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
}
// Touches should now be associated with the closest touch within
// ui::GestureConfiguration::max_separation_for_gesture_touches_in_pixels
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 11));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 11), -1);
EXPECT_EQ("0", WindowIDAsString(target));
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 11));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 11), -1);
EXPECT_EQ("1", WindowIDAsString(target));
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 511));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 511), -1);
EXPECT_EQ("2", WindowIDAsString(target));
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 511));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 511), -1);
EXPECT_EQ("3", WindowIDAsString(target));
// Add a touch in the middle associated with windows[2]
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 500),
kNumWindows, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(250, 250),
kNumWindows, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ DispatchEventUsingWindowDispatcher(&move);
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(250, 250));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(250, 250), -1);
EXPECT_EQ("2", WindowIDAsString(target));
// Make sure that ties are broken by distance to a current touch
// Closer to the point in the bottom right.
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(380, 380));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(380, 380), -1);
EXPECT_EQ("3", WindowIDAsString(target));
// This touch is closer to the point in the middle
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(300, 300));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(300, 300), -1);
EXPECT_EQ("2", WindowIDAsString(target));
// A touch too far from other touches won't be locked to anything
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000), -1);
EXPECT_TRUE(target == NULL);
// Move a touch associated with windows[2] to 1000, 1000
ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(1000, 1000),
kNumWindows, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
- target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000));
+ target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000), -1);
EXPECT_EQ("2", WindowIDAsString(target));
for (int i = 0; i < kNumWindows; ++i) {
@@ -2203,9 +2273,43 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
}
}
+// Check that a touch's target will not be effected by a touch on a different
+// screen.
+TEST_P(GestureRecognizerTest, GestureEventTouchLockIgnoresOtherScreens) {
+ scoped_ptr<GestureEventConsumeDelegate> delegate(
+ new GestureEventConsumeDelegate());
+ gfx::Rect bounds(0, 0, 10, 10);
+ scoped_ptr<aura::Window> window(
+ CreateTestWindowWithDelegate(delegate.get(), 0, bounds, root_window()));
+
+ const int kTouchId1 = 8;
+ const int kTouchId2 = 2;
+ TimedEvents tes;
+
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(5, 5),
+ kTouchId1, tes.Now());
+ press1.set_source_device_id(1);
+ DispatchEventUsingWindowDispatcher(&press1);
+
+ ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(20, 20),
+ kTouchId2, tes.Now());
+ press2.set_source_device_id(2);
+ DispatchEventUsingWindowDispatcher(&press2);
+
+ // The second press should not have been locked to the same target as the
+ // first, as they occured on different displays.
+ EXPECT_NE(
+ ui::GestureRecognizer::Get()->GetTouchLockedTarget(press1),
+ ui::GestureRecognizer::Get()->GetTouchLockedTarget(press2));
+}
+
// Check that touch events outside the root window are still handled
// by the root window's gesture sequence.
-TEST_F(GestureRecognizerTest, GestureEventOutsideRootWindowTap) {
+TEST_P(GestureRecognizerTest, GestureEventOutsideRootWindowTap) {
+ // TODO(tdresser): write a version of this test for the unified GR.
+ if (UsingUnifiedGR())
+ return;
+
TestGestureRecognizer* gesture_recognizer =
new TestGestureRecognizer();
TimedEvents tes;
@@ -2222,11 +2326,11 @@ TEST_F(GestureRecognizerTest, GestureEventOutsideRootWindowTap) {
gfx::Point pos1(-10, -10);
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, pos1, 0, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
gfx::Point pos2(1000, 1000);
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, pos2, 1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
// As these presses were outside the root window, they should be
// associated with the root window.
@@ -2234,9 +2338,9 @@ TEST_F(GestureRecognizerTest, GestureEventOutsideRootWindowTap) {
EXPECT_EQ(2, root_window_gesture_sequence->point_count());
}
-TEST_F(GestureRecognizerTest, NoTapWithPreventDefaultedRelease) {
+TEST_P(GestureRecognizerTest, NoTapWithPreventDefaultedRelease) {
scoped_ptr<QueueTouchEventDelegate> delegate(
- new QueueTouchEventDelegate(dispatcher()));
+ new QueueTouchEventDelegate(host()->dispatcher()));
TimedEvents tes;
const int kTouchId = 2;
gfx::Rect bounds(100, 200, 100, 100);
@@ -2247,10 +2351,10 @@ TEST_F(GestureRecognizerTest, NoTapWithPreventDefaultedRelease) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
delegate->Reset();
delegate->ReceivedAck();
@@ -2261,9 +2365,14 @@ TEST_F(GestureRecognizerTest, NoTapWithPreventDefaultedRelease) {
EXPECT_TRUE(delegate->tap_cancel());
}
-TEST_F(GestureRecognizerTest, PinchScrollWithPreventDefaultedRelease) {
+TEST_P(GestureRecognizerTest, PinchScrollWithPreventDefaultedRelease) {
+ // Disabled for unified GR due to differences in when pinch begin is sent. The
+ // Aura GR sends it earlier than is necessary.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<QueueTouchEventDelegate> delegate(
- new QueueTouchEventDelegate(dispatcher()));
+ new QueueTouchEventDelegate(host()->dispatcher()));
TimedEvents tes;
const int kTouchId1 = 7;
const int kTouchId2 = 5;
@@ -2280,9 +2389,9 @@ TEST_F(GestureRecognizerTest, PinchScrollWithPreventDefaultedRelease) {
tes.LeapForward(200));
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(15, 25), kTouchId1,
tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&press);
+ DispatchEventUsingWindowDispatcher(&move);
+ DispatchEventUsingWindowDispatcher(&release);
delegate->Reset();
// Ack the press event.
@@ -2316,12 +2425,12 @@ TEST_F(GestureRecognizerTest, PinchScrollWithPreventDefaultedRelease) {
tes.LeapForward(14));
// Do a pinch.
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&press);
+ DispatchEventUsingWindowDispatcher(&move);
+ DispatchEventUsingWindowDispatcher(&press2);
+ DispatchEventUsingWindowDispatcher(&move2);
+ DispatchEventUsingWindowDispatcher(&release);
+ DispatchEventUsingWindowDispatcher(&release2);
// Ack the press and move events.
delegate->Reset();
@@ -2355,7 +2464,25 @@ TEST_F(GestureRecognizerTest, PinchScrollWithPreventDefaultedRelease) {
EXPECT_TRUE(delegate->end());
}
-TEST_F(GestureRecognizerTest, CaptureSendsGestureEnd) {
+TEST_P(GestureRecognizerTest, GestureEndLocation) {
+ GestureEventConsumeDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, -1234, gfx::Rect(10, 10, 300, 300), root_window()));
+ EventGenerator generator(root_window(), window.get());
+ const gfx::Point begin(20, 20);
+ const gfx::Point end(150, 150);
+ const gfx::Vector2d window_offset =
+ window->bounds().origin().OffsetFromOrigin();
+ generator.GestureScrollSequence(begin, end,
+ base::TimeDelta::FromMilliseconds(20),
+ 10);
+ EXPECT_EQ((begin - window_offset).ToString(),
+ delegate.scroll_begin_position().ToString());
+ EXPECT_EQ((end - window_offset).ToString(),
+ delegate.gesture_end_location().ToString());
+}
+
+TEST_P(GestureRecognizerTest, CaptureSendsGestureEnd) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TestGestureRecognizer* gesture_recognizer =
@@ -2384,7 +2511,7 @@ TEST_F(GestureRecognizerTest, CaptureSendsGestureEnd) {
// Check that previous touch actions that are completely finished (either
// released or cancelled), do not receive extra synthetic cancels upon change of
// capture.
-TEST_F(GestureRecognizerTest, CaptureDoesNotCancelFinishedTouches) {
+TEST_P(GestureRecognizerTest, CaptureDoesNotCancelFinishedTouches) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
scoped_ptr<TestEventHandler> handler(new TestEventHandler);
@@ -2437,7 +2564,8 @@ TEST_F(GestureRecognizerTest, CaptureDoesNotCancelFinishedTouches) {
root_window()->RemovePreTargetHandler(handler.get());
}
-TEST_F(GestureRecognizerTest, PressDoesNotCrash) {
+// Tests that a press with the same touch id as an existing touch is ignored.
+TEST_P(GestureRecognizerTest, PressDoesNotCrash) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TestGestureRecognizer* gesture_recognizer =
@@ -2450,14 +2578,14 @@ TEST_F(GestureRecognizerTest, PressDoesNotCrash) {
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(45, 45), 7, tes.Now());
press.set_radius_x(40);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_TRUE(delegate->tap_down());
EXPECT_EQ(gfx::Rect(5, 5, 80, 80).ToString(),
delegate->bounding_box().ToString());
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(55, 45), 7, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
// This new press should not generate a tap-down.
EXPECT_FALSE(delegate->begin());
@@ -2466,7 +2594,12 @@ TEST_F(GestureRecognizerTest, PressDoesNotCrash) {
EXPECT_FALSE(delegate->scroll_begin());
}
-TEST_F(GestureRecognizerTest, TwoFingerTap) {
+TEST_P(GestureRecognizerTest, TwoFingerTap) {
+ // TODO(tdresser): enable this test with unified GR once two finger tap is
+ // supported. See crbug.com/354396.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -2481,7 +2614,7 @@ TEST_F(GestureRecognizerTest, TwoFingerTap) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -2494,7 +2627,7 @@ TEST_F(GestureRecognizerTest, TwoFingerTap) {
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down()); // no touch down for second tap.
EXPECT_TRUE(delegate->tap_cancel());
@@ -2508,10 +2641,10 @@ TEST_F(GestureRecognizerTest, TwoFingerTap) {
delegate->Reset();
ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(102, 202),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1);
+ DispatchEventUsingWindowDispatcher(&move1);
ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(131, 202),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -2527,11 +2660,11 @@ TEST_F(GestureRecognizerTest, TwoFingerTap) {
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
- EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_TRUE(delegate->scroll_begin());
EXPECT_FALSE(delegate->scroll_update());
EXPECT_FALSE(delegate->scroll_end());
EXPECT_TRUE(delegate->two_finger_tap());
@@ -2543,7 +2676,7 @@ TEST_F(GestureRecognizerTest, TwoFingerTap) {
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(130, 201),
kTouchId2, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&release2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -2554,7 +2687,7 @@ TEST_F(GestureRecognizerTest, TwoFingerTap) {
EXPECT_FALSE(delegate->two_finger_tap());
}
-TEST_F(GestureRecognizerTest, TwoFingerTapExpired) {
+TEST_P(GestureRecognizerTest, TwoFingerTapExpired) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -2569,19 +2702,19 @@ TEST_F(GestureRecognizerTest, TwoFingerTapExpired) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
// Send release event after sufficient delay so that two finger time expires.
delegate->Reset();
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, tes.LeapForward(1000));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->two_finger_tap());
// Lift second finger.
@@ -2591,11 +2724,11 @@ TEST_F(GestureRecognizerTest, TwoFingerTapExpired) {
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(130, 201),
kTouchId2, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&release2);
EXPECT_FALSE(delegate->two_finger_tap());
}
-TEST_F(GestureRecognizerTest, TwoFingerTapChangesToPinch) {
+TEST_P(GestureRecognizerTest, TwoFingerTapChangesToPinch) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -2613,14 +2746,14 @@ TEST_F(GestureRecognizerTest, TwoFingerTapChangesToPinch) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId1, delegate.get());
+ tes.SendScrollEvent(event_processor(), 230, 330, kTouchId1, delegate.get());
EXPECT_FALSE(delegate->two_finger_tap());
EXPECT_TRUE(delegate->pinch_begin());
@@ -2630,7 +2763,7 @@ TEST_F(GestureRecognizerTest, TwoFingerTapChangesToPinch) {
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId2, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_FALSE(delegate->two_finger_tap());
EXPECT_TRUE(delegate->pinch_end());
}
@@ -2644,14 +2777,14 @@ TEST_F(GestureRecognizerTest, TwoFingerTapChangesToPinch) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
- tes.SendScrollEvent(dispatcher(), 101, 230, kTouchId2, delegate.get());
+ tes.SendScrollEvent(event_processor(), 301, 230, kTouchId2, delegate.get());
EXPECT_FALSE(delegate->two_finger_tap());
EXPECT_TRUE(delegate->pinch_begin());
@@ -2661,13 +2794,18 @@ TEST_F(GestureRecognizerTest, TwoFingerTapChangesToPinch) {
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_FALSE(delegate->two_finger_tap());
EXPECT_TRUE(delegate->pinch_end());
}
}
-TEST_F(GestureRecognizerTest, NoTwoFingerTapWhenFirstFingerHasScrolled) {
+TEST_P(GestureRecognizerTest, NoTwoFingerTapWhenFirstFingerHasScrolled) {
+ // Disabled for unified GR due to differences in when pinch begin is sent. The
+ // Aura GR sends it earlier than is necessary.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -2683,13 +2821,13 @@ TEST_F(GestureRecognizerTest, NoTwoFingerTapWhenFirstFingerHasScrolled) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId1, delegate.get());
+ DispatchEventUsingWindowDispatcher(&press1);
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId1, delegate.get());
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_TRUE(delegate->pinch_begin());
@@ -2699,12 +2837,12 @@ TEST_F(GestureRecognizerTest, NoTwoFingerTapWhenFirstFingerHasScrolled) {
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId2, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_FALSE(delegate->two_finger_tap());
EXPECT_TRUE(delegate->pinch_end());
}
-TEST_F(GestureRecognizerTest, MultiFingerSwipe) {
+TEST_P(GestureRecognizerTest, MultiFingerSwipe) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -2725,26 +2863,33 @@ TEST_F(GestureRecognizerTest, MultiFingerSwipe) {
aura::test::EventGenerator generator(root_window(), window.get());
+ // The unified gesture recognizer assumes a finger has stopped if it hasn't
+ // moved for too long. See ui/events/gesture_detection/velocity_tracker.cc's
+ // kAssumePointerStoppedTimeMs.
for (int count = 2; count <= kTouchPoints; ++count) {
- generator.GestureMultiFingerScroll(count, points, 15, kSteps, 0, -150);
+ generator.GestureMultiFingerScroll(
+ count, points, 10, kSteps, 0, -11 * kSteps);
EXPECT_TRUE(delegate->swipe_up());
delegate->Reset();
- generator.GestureMultiFingerScroll(count, points, 15, kSteps, 0, 150);
+ generator.GestureMultiFingerScroll(
+ count, points, 10, kSteps, 0, 11 * kSteps);
EXPECT_TRUE(delegate->swipe_down());
delegate->Reset();
- generator.GestureMultiFingerScroll(count, points, 15, kSteps, -150, 0);
+ generator.GestureMultiFingerScroll(
+ count, points, 10, kSteps, -11 * kSteps, 0);
EXPECT_TRUE(delegate->swipe_left());
delegate->Reset();
- generator.GestureMultiFingerScroll(count, points, 15, kSteps, 150, 0);
+ generator.GestureMultiFingerScroll(
+ count, points, 10, kSteps, 11 * kSteps, 0);
EXPECT_TRUE(delegate->swipe_right());
delegate->Reset();
}
}
-TEST_F(GestureRecognizerTest, TwoFingerTapCancelled) {
+TEST_P(GestureRecognizerTest, TwoFingerTapCancelled) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -2762,17 +2907,17 @@ TEST_F(GestureRecognizerTest, TwoFingerTapCancelled) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
delegate->Reset();
ui::TouchEvent cancel(ui::ET_TOUCH_CANCELLED, gfx::Point(130, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&cancel);
+ DispatchEventUsingWindowDispatcher(&cancel);
EXPECT_FALSE(delegate->two_finger_tap());
// Make sure there is enough delay before the touch is released so that it
@@ -2781,7 +2926,7 @@ TEST_F(GestureRecognizerTest, TwoFingerTapCancelled) {
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId2, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_FALSE(delegate->two_finger_tap());
}
@@ -2794,17 +2939,17 @@ TEST_F(GestureRecognizerTest, TwoFingerTapCancelled) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
delegate->Reset();
ui::TouchEvent cancel(ui::ET_TOUCH_CANCELLED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&cancel);
+ DispatchEventUsingWindowDispatcher(&cancel);
EXPECT_FALSE(delegate->two_finger_tap());
// Make sure there is enough delay before the touch is released so that it
@@ -2813,12 +2958,18 @@ TEST_F(GestureRecognizerTest, TwoFingerTapCancelled) {
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId1, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_FALSE(delegate->two_finger_tap());
}
}
-TEST_F(GestureRecognizerTest, VeryWideTwoFingerTouchDownShouldBeAPinch) {
+TEST_P(GestureRecognizerTest, VeryWideTwoFingerTouchDownShouldBeAPinch) {
+ // Disabled for unified GR due to differences in when scroll update is
+ // sent. The Aura GR will never send a ScrollUpdate with a ScrollBegin, but
+ // the unified GR will.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 523;
@@ -2833,7 +2984,7 @@ TEST_F(GestureRecognizerTest, VeryWideTwoFingerTouchDownShouldBeAPinch) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -2846,7 +2997,7 @@ TEST_F(GestureRecognizerTest, VeryWideTwoFingerTouchDownShouldBeAPinch) {
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(430, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down()); // no touch down for second tap.
EXPECT_TRUE(delegate->tap_cancel());
@@ -2860,7 +3011,7 @@ TEST_F(GestureRecognizerTest, VeryWideTwoFingerTouchDownShouldBeAPinch) {
delegate->Reset();
ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(530, 301),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -2875,7 +3026,7 @@ TEST_F(GestureRecognizerTest, VeryWideTwoFingerTouchDownShouldBeAPinch) {
// Verifies if a window is the target of multiple touch-ids and we hide the
// window everything is cleaned up correctly.
-TEST_F(GestureRecognizerTest, FlushAllOnHide) {
+TEST_P(GestureRecognizerTest, FlushAllOnHide) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
gfx::Rect bounds(0, 0, 200, 200);
@@ -2887,10 +3038,10 @@ TEST_F(GestureRecognizerTest, FlushAllOnHide) {
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(20, 20),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
window->Hide();
EXPECT_EQ(NULL,
ui::GestureRecognizer::Get()->GetTouchLockedTarget(press1));
@@ -2898,9 +3049,13 @@ TEST_F(GestureRecognizerTest, FlushAllOnHide) {
ui::GestureRecognizer::Get()->GetTouchLockedTarget(press2));
}
-TEST_F(GestureRecognizerTest, LongPressTimerStopsOnPreventDefaultedTouchMoves) {
+TEST_P(GestureRecognizerTest, LongPressTimerStopsOnPreventDefaultedTouchMoves) {
+ // TODO(tdresser): write a version of this test for the unified GR.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<QueueTouchEventDelegate> delegate(
- new QueueTouchEventDelegate(dispatcher()));
+ new QueueTouchEventDelegate(host()->dispatcher()));
const int kTouchId = 2;
gfx::Rect bounds(100, 200, 100, 100);
scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
@@ -2919,9 +3074,9 @@ TEST_F(GestureRecognizerTest, LongPressTimerStopsOnPreventDefaultedTouchMoves) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
// Scroll around, to cancel the long press
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId, delegate.get());
delegate->Reset();
delegate->ReceivedAck();
@@ -2958,7 +3113,7 @@ class ConsumesTouchMovesDelegate : public GestureEventConsumeDelegate {
// Same as GestureEventScroll, but tests that the behavior is the same
// even if all the touch-move events are consumed.
-TEST_F(GestureRecognizerTest, GestureEventScrollTouchMoveConsumed) {
+TEST_P(GestureRecognizerTest, GestureEventScrollTouchMoveConsumed) {
scoped_ptr<ConsumesTouchMovesDelegate> delegate(
new ConsumesTouchMovesDelegate());
const int kWindowWidth = 123;
@@ -2972,7 +3127,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMoveConsumed) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -2984,7 +3139,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMoveConsumed) {
// Move the touch-point enough so that it would normally be considered a
// scroll. But since the touch-moves will be consumed, the scroll should not
// start.
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId, delegate.get());
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_TRUE(delegate->tap_cancel());
@@ -2998,7 +3153,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMoveConsumed) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(130, 230),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -3010,7 +3165,12 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMoveConsumed) {
}
// Tests the behavior of 2F scroll when all the touch-move events are consumed.
-TEST_F(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
+TEST_P(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
+ // TODO(tdresser): enable this test with unified GR once two finger tap is
+ // supported. See crbug.com/354396.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<ConsumesTouchMovesDelegate> delegate(
new ConsumesTouchMovesDelegate());
const int kWindowWidth = 123;
@@ -3026,8 +3186,8 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
delegate->Reset();
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
- tes.SendScrollEvent(dispatcher(), 131, 231, kTouchId1, delegate.get());
+ DispatchEventUsingWindowDispatcher(&press1);
+ tes.SendScrollEvent(event_processor(), 131, 231, kTouchId1, delegate.get());
// First finger touches down and moves.
EXPECT_FALSE(delegate->tap());
@@ -3039,8 +3199,8 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
// Second finger touches down and moves.
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(130, 201),
kTouchId2, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
- tes.SendScrollEvent(dispatcher(), 161, 231, kTouchId2, delegate.get());
+ DispatchEventUsingWindowDispatcher(&press2);
+ tes.SendScrollEvent(event_processor(), 161, 231, kTouchId2, delegate.get());
// PinchBegin & ScrollBegin were not sent if the touch-move events were
// consumed.
@@ -3058,7 +3218,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
delegate->Reset();
// Moves First finger again, no PinchUpdate & ScrollUpdate.
- tes.SendScrollEvent(dispatcher(), 161, 261, kTouchId1, delegate.get());
+ tes.SendScrollEvent(event_processor(), 161, 261, kTouchId1, delegate.get());
EXPECT_FALSE(delegate->pinch_update());
EXPECT_FALSE(delegate->pinch_end());
@@ -3070,7 +3230,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
delegate->Reset();
// Making a pinch gesture.
- tes.SendScrollEvent(dispatcher(), 161, 251, kTouchId1, delegate.get());
+ tes.SendScrollEvent(event_processor(), 161, 251, kTouchId1, delegate.get());
// If touch moves are ever consumed, we should not see PinchBegin/Update
// even touch moves become not consumed.
EXPECT_FALSE(delegate->scroll_begin());
@@ -3082,7 +3242,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
EXPECT_FALSE(delegate->pinch_end());
delegate->Reset();
- tes.SendScrollEvent(dispatcher(), 161, 241, kTouchId2, delegate.get());
+ tes.SendScrollEvent(event_processor(), 161, 241, kTouchId2, delegate.get());
EXPECT_FALSE(delegate->scroll_begin());
EXPECT_FALSE(delegate->scroll_update());
EXPECT_FALSE(delegate->scroll_end());
@@ -3096,17 +3256,18 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
kTouchId1, tes.Now());
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(130, 201),
kTouchId2, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&release1);
+ DispatchEventUsingWindowDispatcher(&release2);
EXPECT_FALSE(delegate->tap());
// Touch release is not consumed, so we still see two finger tap.
EXPECT_TRUE(delegate->two_finger_tap());
- // Should not see PinchEnd & ScrollEnd.
- EXPECT_FALSE(delegate->scroll_begin());
+ // Should not see PinchEnd.
+ EXPECT_TRUE(delegate->scroll_begin());
EXPECT_FALSE(delegate->scroll_update());
EXPECT_FALSE(delegate->scroll_end());
+ EXPECT_TRUE(delegate->fling());
EXPECT_FALSE(delegate->pinch_begin());
EXPECT_FALSE(delegate->pinch_update());
@@ -3116,7 +3277,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTwoFingerTouchMoveConsumed) {
// Like as GestureEventTouchMoveConsumed but tests the different behavior
// depending on whether the events were consumed before or after the scroll
// started.
-TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
+TEST_P(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
scoped_ptr<ConsumesTouchMovesDelegate> delegate(
new ConsumesTouchMovesDelegate());
const int kWindowWidth = 123;
@@ -3130,7 +3291,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -3142,7 +3303,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
// Move the touch-point enough so that it would normally be considered a
// scroll. But since the touch-moves will be consumed, the scroll should not
// start.
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId, delegate.get());
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_TRUE(delegate->tap_cancel());
@@ -3153,7 +3314,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
// Now, stop consuming touch-move events, and move the touch-point again.
delegate->set_consume_touch_move(false);
- tes.SendScrollEvent(dispatcher(), 159, 259, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 159, 259, kTouchId, delegate.get());
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -3171,7 +3332,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
delegate->set_consume_touch_move(true);
// Move some more to generate a few more scroll updates.
- tes.SendScrollEvent(dispatcher(), 110, 211, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 110, 211, kTouchId, delegate.get());
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -3182,7 +3343,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
EXPECT_EQ(0, delegate->scroll_x());
EXPECT_EQ(0, delegate->scroll_y());
- tes.SendScrollEvent(dispatcher(), 140, 215, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 140, 215, kTouchId, delegate.get());
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -3197,7 +3358,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_FALSE(delegate->tap_cancel());
@@ -3210,7 +3371,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
}
// Check that appropriate touch events generate double tap gesture events.
-TEST_F(GestureRecognizerTest, GestureEventDoubleTap) {
+TEST_P(GestureRecognizerTest, GestureEventDoubleTap) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -3224,19 +3385,19 @@ TEST_F(GestureRecognizerTest, GestureEventDoubleTap) {
// First tap (tested in GestureEventTap)
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(104, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(104, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
delegate->Reset();
// Second tap
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(101, 203),
kTouchId, tes.LeapForward(200));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(102, 206),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&release2);
EXPECT_TRUE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
@@ -3251,7 +3412,7 @@ TEST_F(GestureRecognizerTest, GestureEventDoubleTap) {
}
// Check that appropriate touch events generate triple tap gesture events.
-TEST_F(GestureRecognizerTest, GestureEventTripleTap) {
+TEST_P(GestureRecognizerTest, GestureEventTripleTap) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -3265,10 +3426,10 @@ TEST_F(GestureRecognizerTest, GestureEventTripleTap) {
// First tap (tested in GestureEventTap)
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(104, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(104, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_EQ(1, delegate->tap_count());
delegate->Reset();
@@ -3276,10 +3437,10 @@ TEST_F(GestureRecognizerTest, GestureEventTripleTap) {
// Second tap (tested in GestureEventDoubleTap)
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(101, 203),
kTouchId, tes.LeapForward(200));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(102, 206),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&release2);
EXPECT_EQ(2, delegate->tap_count());
delegate->Reset();
@@ -3287,26 +3448,44 @@ TEST_F(GestureRecognizerTest, GestureEventTripleTap) {
// Third tap
ui::TouchEvent press3(ui::ET_TOUCH_PRESSED, gfx::Point(102, 206),
kTouchId, tes.LeapForward(200));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press3);
+ DispatchEventUsingWindowDispatcher(&press3);
ui::TouchEvent release3(ui::ET_TOUCH_RELEASED, gfx::Point(102, 206),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release3);
-
-
- EXPECT_TRUE(delegate->tap());
- EXPECT_TRUE(delegate->tap_down());
- EXPECT_FALSE(delegate->tap_cancel());
- EXPECT_TRUE(delegate->begin());
- EXPECT_TRUE(delegate->end());
- EXPECT_FALSE(delegate->scroll_begin());
- EXPECT_FALSE(delegate->scroll_update());
- EXPECT_FALSE(delegate->scroll_end());
-
- EXPECT_EQ(3, delegate->tap_count());
+ DispatchEventUsingWindowDispatcher(&release3);
+
+ // Third, Fourth and Fifth Taps. Taps after the third should have their
+ // |tap_count| wrap around back to 1.
+ for (int i = 3; i < 5; ++i) {
+ ui::TouchEvent press3(ui::ET_TOUCH_PRESSED,
+ gfx::Point(102, 206),
+ kTouchId,
+ tes.LeapForward(200));
+ DispatchEventUsingWindowDispatcher(&press3);
+ ui::TouchEvent release3(ui::ET_TOUCH_RELEASED,
+ gfx::Point(102, 206),
+ kTouchId,
+ tes.LeapForward(50));
+ DispatchEventUsingWindowDispatcher(&release3);
+
+ EXPECT_TRUE(delegate->tap());
+ EXPECT_TRUE(delegate->tap_down());
+ EXPECT_FALSE(delegate->tap_cancel());
+ EXPECT_TRUE(delegate->begin());
+ EXPECT_TRUE(delegate->end());
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ EXPECT_FALSE(delegate->scroll_end());
+
+ // The behavior for the Aura GR is incorrect.
+ if (UsingUnifiedGR())
+ EXPECT_EQ(1 + (i % 3), delegate->tap_count());
+ else
+ EXPECT_EQ(3, delegate->tap_count());
+ }
}
// Check that we don't get a double tap when the two taps are far apart.
-TEST_F(GestureRecognizerTest, TwoTapsFarApart) {
+TEST_P(GestureRecognizerTest, TwoTapsFarApart) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -3320,19 +3499,19 @@ TEST_F(GestureRecognizerTest, TwoTapsFarApart) {
// First tap (tested in GestureEventTap)
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
delegate->Reset();
// Second tap, close in time but far in distance
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(201, 201),
kTouchId, tes.LeapForward(200));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(201, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&release2);
EXPECT_TRUE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
@@ -3348,7 +3527,7 @@ TEST_F(GestureRecognizerTest, TwoTapsFarApart) {
// Check that we don't get a double tap when the two taps have a long enough
// delay in between.
-TEST_F(GestureRecognizerTest, TwoTapsWithDelayBetween) {
+TEST_P(GestureRecognizerTest, TwoTapsWithDelayBetween) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 123;
@@ -3362,19 +3541,19 @@ TEST_F(GestureRecognizerTest, TwoTapsWithDelayBetween) {
// First tap (tested in GestureEventTap)
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
delegate->Reset();
// Second tap, close in distance but after some delay
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(2000));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release2);
+ DispatchEventUsingWindowDispatcher(&release2);
EXPECT_TRUE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
@@ -3391,7 +3570,12 @@ TEST_F(GestureRecognizerTest, TwoTapsWithDelayBetween) {
// Checks that if the bounding-box of a gesture changes because of change in
// radius of a touch-point, and not because of change in position, then there
// are not gesture events from that.
-TEST_F(GestureRecognizerTest, BoundingBoxRadiusChange) {
+TEST_P(GestureRecognizerTest, BoundingBoxRadiusChange) {
+ // TODO(tdresser): enable this test with unified GR when (if?) bounding box
+ // behavior is unified.
+ if (UsingUnifiedGR())
+ return;
+
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kWindowWidth = 234;
@@ -3404,7 +3588,7 @@ TEST_F(GestureRecognizerTest, BoundingBoxRadiusChange) {
ui::TouchEvent press1(
ui::ET_TOUCH_PRESSED, gfx::Point(101, 201), kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_TRUE(delegate->bounding_box().IsEmpty());
delegate->Reset();
@@ -3413,7 +3597,7 @@ TEST_F(GestureRecognizerTest, BoundingBoxRadiusChange) {
ui::ET_TOUCH_PRESSED, gfx::Point(201, 201), kTouchId2,
tes.LeapForward(400));
press2.set_radius_x(5);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_FALSE(delegate->pinch_begin());
EXPECT_EQ(gfx::Rect(101, 201, 100, 0).ToString(),
delegate->bounding_box().ToString());
@@ -3422,7 +3606,7 @@ TEST_F(GestureRecognizerTest, BoundingBoxRadiusChange) {
ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(141, 201), kTouchId,
tes.LeapForward(40));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1);
+ DispatchEventUsingWindowDispatcher(&move1);
EXPECT_TRUE(delegate->pinch_begin());
EXPECT_EQ(gfx::Rect(141, 201, 60, 0).ToString(),
delegate->bounding_box().ToString());
@@ -3434,7 +3618,7 @@ TEST_F(GestureRecognizerTest, BoundingBoxRadiusChange) {
tes.LeapForward(40));
move2.set_radius_x(50);
move2.set_radius_y(60);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_cancel());
EXPECT_FALSE(delegate->scroll_update());
@@ -3445,7 +3629,7 @@ TEST_F(GestureRecognizerTest, BoundingBoxRadiusChange) {
// Checks that slow scrolls deliver the correct deltas.
// In particular, fix for http;//crbug.com/150573.
-TEST_F(GestureRecognizerTest, NoDriftInScroll) {
+TEST_P(GestureRecognizerTest, NoDriftInScroll) {
ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(3);
ui::GestureConfiguration::set_min_scroll_delta_squared(9);
scoped_ptr<GestureEventConsumeDelegate> delegate(
@@ -3460,38 +3644,40 @@ TEST_F(GestureRecognizerTest, NoDriftInScroll) {
ui::TouchEvent press1(
ui::ET_TOUCH_PRESSED, gfx::Point(101, 208), kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_TRUE(delegate->begin());
delegate->Reset();
ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(101, 206), kTouchId,
tes.LeapForward(40));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1);
+ DispatchEventUsingWindowDispatcher(&move1);
EXPECT_FALSE(delegate->scroll_begin());
delegate->Reset();
ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(101, 204), kTouchId,
tes.LeapForward(40));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
EXPECT_TRUE(delegate->tap_cancel());
EXPECT_TRUE(delegate->scroll_begin());
EXPECT_TRUE(delegate->scroll_update());
- EXPECT_EQ(-4, delegate->scroll_y());
+ // 3 px consumed by touch slop region.
+ EXPECT_EQ(-1, delegate->scroll_y());
+ EXPECT_EQ(-4, delegate->scroll_y_hint());
delegate->Reset();
ui::TouchEvent move3(ui::ET_TOUCH_MOVED, gfx::Point(101, 204), kTouchId,
tes.LeapForward(40));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move3);
+ DispatchEventUsingWindowDispatcher(&move3);
EXPECT_FALSE(delegate->scroll_update());
delegate->Reset();
ui::TouchEvent move4(ui::ET_TOUCH_MOVED, gfx::Point(101, 203), kTouchId,
tes.LeapForward(40));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move4);
+ DispatchEventUsingWindowDispatcher(&move4);
EXPECT_TRUE(delegate->scroll_update());
EXPECT_EQ(-1, delegate->scroll_y());
@@ -3501,7 +3687,7 @@ TEST_F(GestureRecognizerTest, NoDriftInScroll) {
// Ensure that move events which are preventDefaulted will cause a tap
// cancel gesture event to be fired if the move would normally cause a
// scroll. See bug http://crbug.com/146397.
-TEST_F(GestureRecognizerTest, GestureEventConsumedTouchMoveCanFireTapCancel) {
+TEST_P(GestureRecognizerTest, GestureEventConsumedTouchMoveCanFireTapCancel) {
scoped_ptr<ConsumesTouchMovesDelegate> delegate(
new ConsumesTouchMovesDelegate());
const int kTouchId = 5;
@@ -3515,13 +3701,13 @@ TEST_F(GestureRecognizerTest, GestureEventConsumedTouchMoveCanFireTapCancel) {
kTouchId, tes.Now());
delegate->set_consume_touch_move(false);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
delegate->set_consume_touch_move(true);
delegate->Reset();
// Move the touch-point enough so that it would normally be considered a
// scroll. But since the touch-moves will be consumed, the scroll should not
// start.
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId, delegate.get());
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
EXPECT_TRUE(delegate->tap_cancel());
@@ -3531,7 +3717,7 @@ TEST_F(GestureRecognizerTest, GestureEventConsumedTouchMoveCanFireTapCancel) {
EXPECT_FALSE(delegate->scroll_end());
}
-TEST_F(GestureRecognizerTest,
+TEST_P(GestureRecognizerTest,
TransferEventDispatchesTouchCancel) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
@@ -3552,8 +3738,8 @@ TEST_F(GestureRecognizerTest,
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 1, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&p2);
+ DispatchEventUsingWindowDispatcher(&press);
+ DispatchEventUsingWindowDispatcher(&p2);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
EXPECT_TRUE(delegate->tap_cancel());
@@ -3574,7 +3760,7 @@ TEST_F(GestureRecognizerTest,
}
// Check that appropriate touch events generate show press events
-TEST_F(GestureRecognizerTest, GestureEventShowPress) {
+TEST_P(GestureRecognizerTest, GestureEventShowPress) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -3594,7 +3780,7 @@ TEST_F(GestureRecognizerTest, GestureEventShowPress) {
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_TRUE(delegate->tap_down());
EXPECT_TRUE(delegate->begin());
EXPECT_FALSE(delegate->tap_cancel());
@@ -3610,15 +3796,16 @@ TEST_F(GestureRecognizerTest, GestureEventShowPress) {
delegate->Reset();
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->long_press());
- // Note the tap down isn't cancelled until the release
- EXPECT_TRUE(delegate->tap_cancel());
+ // Note the tap isn't dispatched until the release
+ EXPECT_FALSE(delegate->tap_cancel());
+ EXPECT_TRUE(delegate->tap());
}
// Check that scrolling cancels a show press
-TEST_F(GestureRecognizerTest, GestureEventShowPressCancelledByScroll) {
+TEST_P(GestureRecognizerTest, GestureEventShowPressCancelledByScroll) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -3642,7 +3829,7 @@ TEST_F(GestureRecognizerTest, GestureEventShowPressCancelledByScroll) {
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_TRUE(delegate->tap_down());
// We haven't pressed long enough for a show press to occur
@@ -3650,7 +3837,7 @@ TEST_F(GestureRecognizerTest, GestureEventShowPressCancelledByScroll) {
EXPECT_FALSE(delegate->tap_cancel());
// Scroll around, to cancel the show press
- tes.SendScrollEvent(dispatcher(), 130, 230, kTouchId, delegate.get());
+ tes.SendScrollEvent(event_processor(), 130, 230, kTouchId, delegate.get());
// Wait until the timer runs out
gesture_sequence->ForceTimeout();
EXPECT_FALSE(delegate->show_press());
@@ -3659,13 +3846,13 @@ TEST_F(GestureRecognizerTest, GestureEventShowPressCancelledByScroll) {
delegate->Reset();
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(10));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_FALSE(delegate->show_press());
EXPECT_FALSE(delegate->tap_cancel());
}
// Test that show press events are sent immediately on tap
-TEST_F(GestureRecognizerTest, GestureEventShowPressSentOnTap) {
+TEST_P(GestureRecognizerTest, GestureEventShowPressSentOnTap) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
TimedEvents tes;
@@ -3680,7 +3867,7 @@ TEST_F(GestureRecognizerTest, GestureEventShowPressSentOnTap) {
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
+ DispatchEventUsingWindowDispatcher(&press1);
EXPECT_TRUE(delegate->tap_down());
// We haven't pressed long enough for a show press to occur
@@ -3690,11 +3877,516 @@ TEST_F(GestureRecognizerTest, GestureEventShowPressSentOnTap) {
delegate->Reset();
ui::TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release1);
+ DispatchEventUsingWindowDispatcher(&release1);
EXPECT_TRUE(delegate->show_press());
EXPECT_FALSE(delegate->tap_cancel());
EXPECT_TRUE(delegate->tap());
}
+// Test that consuming the first move touch event prevents a scroll.
+TEST_P(GestureRecognizerTest, GestureEventConsumedTouchMoveScrollTest) {
+ scoped_ptr<QueueTouchEventDelegate> delegate(
+ new QueueTouchEventDelegate(host()->dispatcher()));
+ TimedEvents tes;
+ const int kTouchId = 7;
+ gfx::Rect bounds(0, 0, 1000, 1000);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press);
+ delegate->ReceivedAck();
+
+ // A touch move within the slop region is never consumed in web contents. The
+ // unified GR won't prevent scroll if a touch move within the slop region is
+ // consumed, so make sure this touch move exceeds the slop region.
+ ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(10, 10),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move1);
+ delegate->ReceivedAckPreventDefaulted();
+
+ ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(20, 20),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move2);
+ delegate->ReceivedAck();
+
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+}
+
+// Test that consuming the first touch move event of a touch point doesn't
+// prevent pinching once an additional touch has been pressed.
+TEST_P(GestureRecognizerTest, GestureEventConsumedTouchMovePinchTest) {
+ // Consuming moves within the touch slop and the the disposition handling of
+ // pinch events behave differently between the Unified GR and the Aura GR.
+ if (UsingUnifiedGR())
+ return;
+
+ scoped_ptr<QueueTouchEventDelegate> delegate(
+ new QueueTouchEventDelegate(host()->dispatcher()));
+ TimedEvents tes;
+ const int kTouchId1 = 7;
+ const int kTouchId2 = 4;
+ gfx::Rect bounds(0, 0, 1000, 1000);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
+ kTouchId1, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press1);
+ delegate->ReceivedAck();
+
+ ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(2, 2),
+ kTouchId1, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move1);
+ delegate->ReceivedAckPreventDefaulted();
+
+ ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(20, 20),
+ kTouchId1, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move2);
+ delegate->ReceivedAck();
+
+ // We can't scroll, because a move has been consumed.
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ EXPECT_FALSE(delegate->pinch_begin());
+
+ // An additional press will allow us to pinch.
+ ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
+ kTouchId2, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press2);
+ delegate->ReceivedAck();
+
+ ui::TouchEvent move3(ui::ET_TOUCH_MOVED, gfx::Point(20, 20),
+ kTouchId2, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move3);
+ delegate->ReceivedAck();
+
+ EXPECT_TRUE(delegate->pinch_begin());
+ EXPECT_FALSE(delegate->pinch_update());
+
+ delegate->Reset();
+
+ ui::TouchEvent move4(ui::ET_TOUCH_MOVED, gfx::Point(40, 40),
+ kTouchId2, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move4);
+ delegate->ReceivedAck();
+
+ EXPECT_TRUE(delegate->pinch_update());
+ EXPECT_EQ(10, delegate->scroll_x());
+ EXPECT_EQ(10, delegate->scroll_y());
+}
+
+// Test that consuming the first move touch doesn't prevent a tap.
+TEST_P(GestureRecognizerTest, GestureEventConsumedTouchMoveTapTest) {
+ scoped_ptr<QueueTouchEventDelegate> delegate(
+ new QueueTouchEventDelegate(host()->dispatcher()));
+ TimedEvents tes;
+ const int kTouchId = 7;
+ gfx::Rect bounds(0, 0, 1000, 1000);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press);
+ delegate->ReceivedAck();
+
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(2, 2),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move);
+ delegate->ReceivedAckPreventDefaulted();
+
+ ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(2, 2),
+ kTouchId, tes.LeapForward(50));
+ DispatchEventUsingWindowDispatcher(&release);
+ delegate->ReceivedAck();
+
+ EXPECT_TRUE(delegate->tap());
+}
+
+// Test that consuming the first move touch doesn't prevent a long press.
+TEST_P(GestureRecognizerTest, GestureEventConsumedTouchMoveLongPressTest) {
+ scoped_ptr<QueueTouchEventDelegate> delegate(
+ new QueueTouchEventDelegate(host()->dispatcher()));
+ TimedEvents tes;
+ const int kWindowWidth = 123;
+ const int kWindowHeight = 45;
+ const int kTouchId = 2;
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ delegate->Reset();
+
+ TimerTestGestureRecognizer* gesture_recognizer =
+ new TimerTestGestureRecognizer();
+
+ ScopedGestureRecognizerSetter gr_setter(gesture_recognizer);
+
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press1);
+ delegate->ReceivedAck();
+
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(103, 203),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move);
+ delegate->ReceivedAckPreventDefaulted();
+
+ // Wait until the timer runs out
+ delegate->WaitUntilReceivedGesture(ui::ET_GESTURE_LONG_PRESS);
+ EXPECT_TRUE(delegate->long_press());
+}
+
+// Tests that the deltas are correct when leaving the slop region very slowly.
+TEST_P(GestureRecognizerTest, TestExceedingSlopSlowly) {
+ // Disabled for unified GR due to subtle differences in touch slop handling.
+ if (UsingUnifiedGR())
+ return;
+
+ ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(3);
+ scoped_ptr<GestureEventConsumeDelegate> delegate(
+ new GestureEventConsumeDelegate());
+ const int kWindowWidth = 234;
+ const int kWindowHeight = 345;
+ const int kTouchId = 5;
+ TimedEvents tes;
+ gfx::Rect bounds(0, 0, kWindowWidth, kWindowHeight);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press);
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ delegate->Reset();
+
+ ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(11, 10), kTouchId,
+ tes.LeapForward(40));
+ DispatchEventUsingWindowDispatcher(&move1);
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ EXPECT_EQ(0, delegate->scroll_x());
+ EXPECT_EQ(0, delegate->scroll_x_hint());
+ delegate->Reset();
+
+ ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(12, 10), kTouchId,
+ tes.LeapForward(40));
+ DispatchEventUsingWindowDispatcher(&move2);
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ EXPECT_EQ(0, delegate->scroll_x());
+ EXPECT_EQ(0, delegate->scroll_x_hint());
+ delegate->Reset();
+
+
+ ui::TouchEvent move3(ui::ET_TOUCH_MOVED, gfx::Point(13, 10), kTouchId,
+ tes.LeapForward(40));
+ DispatchEventUsingWindowDispatcher(&move3);
+ EXPECT_TRUE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ EXPECT_EQ(0, delegate->scroll_x());
+ EXPECT_EQ(3, delegate->scroll_x_hint());
+ delegate->Reset();
+
+
+ ui::TouchEvent move4(ui::ET_TOUCH_MOVED, gfx::Point(14, 10), kTouchId,
+ tes.LeapForward(40));
+ DispatchEventUsingWindowDispatcher(&move4);
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_TRUE(delegate->scroll_update());
+ EXPECT_EQ(1, delegate->scroll_x());
+ EXPECT_EQ(0, delegate->scroll_x_hint());
+ delegate->Reset();
+}
+
+TEST_P(GestureRecognizerTest, ScrollAlternatelyConsumedTest) {
+ scoped_ptr<QueueTouchEventDelegate> delegate(
+ new QueueTouchEventDelegate(host()->dispatcher()));
+ TimedEvents tes;
+ const int kWindowWidth = 3000;
+ const int kWindowHeight = 3000;
+ const int kTouchId = 2;
+ gfx::Rect bounds(0, 0, kWindowWidth, kWindowHeight);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ delegate->Reset();
+
+ int x = 0;
+ int y = 0;
+
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(x, y),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press1);
+ delegate->ReceivedAck();
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ delegate->Reset();
+
+ x += 100;
+ y += 100;
+ ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(x, y),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move1);
+ delegate->ReceivedAck();
+ EXPECT_TRUE(delegate->scroll_begin());
+ EXPECT_TRUE(delegate->scroll_update());
+ delegate->Reset();
+
+ for (int i = 0; i < 3; ++i) {
+ x += 10;
+ y += 10;
+ ui::TouchEvent move2(
+ ui::ET_TOUCH_MOVED, gfx::Point(x, y), kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move2);
+ delegate->ReceivedAck();
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_TRUE(delegate->scroll_update());
+ EXPECT_EQ(10, delegate->scroll_x());
+ EXPECT_EQ(10, delegate->scroll_y());
+ delegate->Reset();
+
+ x += 20;
+ y += 20;
+ ui::TouchEvent move3(
+ ui::ET_TOUCH_MOVED, gfx::Point(x, y), kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move3);
+ delegate->ReceivedAckPreventDefaulted();
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ delegate->Reset();
+ }
+}
+
+TEST_P(GestureRecognizerTest, PinchAlternatelyConsumedTest) {
+ // Disabled for unified GR due to differences in when scroll update is
+ // sent. The Aura GR will never send a ScrollUpdate with a ScrollBegin, but
+ // the unified GR will.
+ if (UsingUnifiedGR())
+ return;
+
+ scoped_ptr<QueueTouchEventDelegate> delegate(
+ new QueueTouchEventDelegate(host()->dispatcher()));
+ TimedEvents tes;
+ const int kWindowWidth = 3000;
+ const int kWindowHeight = 3000;
+ const int kTouchId1 = 5;
+ const int kTouchId2 = 7;
+ gfx::Rect bounds(0, 0, kWindowWidth, kWindowHeight);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ delegate->Reset();
+
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
+ kTouchId1, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press1);
+ delegate->ReceivedAck();
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ delegate->Reset();
+
+ int x = 0;
+ int y = 0;
+
+ ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(x, y),
+ kTouchId2, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press2);
+ delegate->ReceivedAck();
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ EXPECT_FALSE(delegate->pinch_begin());
+ EXPECT_FALSE(delegate->pinch_update());
+
+ delegate->Reset();
+
+ x += 100;
+ y += 100;
+ ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(x, y),
+ kTouchId2, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move1);
+ delegate->ReceivedAck();
+ EXPECT_TRUE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ EXPECT_TRUE(delegate->pinch_begin());
+ EXPECT_FALSE(delegate->pinch_update());
+ delegate->Reset();
+
+ const float expected_scales[] = {1.5f, 1.2f, 1.125f};
+
+ for (int i = 0; i < 3; ++i) {
+ x += 50;
+ y += 50;
+ ui::TouchEvent move2(
+ ui::ET_TOUCH_MOVED, gfx::Point(x, y), kTouchId2, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move2);
+ delegate->ReceivedAck();
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_TRUE(delegate->scroll_update());
+ EXPECT_FALSE(delegate->scroll_end());
+ EXPECT_FALSE(delegate->pinch_begin());
+ EXPECT_TRUE(delegate->pinch_update());
+ EXPECT_FALSE(delegate->pinch_end());
+ EXPECT_EQ(25, delegate->scroll_x());
+ EXPECT_EQ(25, delegate->scroll_y());
+ EXPECT_FLOAT_EQ(expected_scales[i], delegate->scale());
+ delegate->Reset();
+
+ x += 100;
+ y += 100;
+ ui::TouchEvent move3(
+ ui::ET_TOUCH_MOVED, gfx::Point(x, y), kTouchId2, tes.Now());
+ DispatchEventUsingWindowDispatcher(&move3);
+ delegate->ReceivedAckPreventDefaulted();
+ EXPECT_FALSE(delegate->scroll_begin());
+ EXPECT_FALSE(delegate->scroll_update());
+ EXPECT_FALSE(delegate->scroll_end());
+ EXPECT_FALSE(delegate->pinch_begin());
+ EXPECT_FALSE(delegate->pinch_update());
+ EXPECT_FALSE(delegate->pinch_end());
+ delegate->Reset();
+ }
+}
+
+// Test that touch event flags are passed through to the gesture event.
+TEST_P(GestureRecognizerTest, GestureEventFlagsPassedFromTouchEvent) {
+ scoped_ptr<GestureEventConsumeDelegate> delegate(
+ new GestureEventConsumeDelegate());
+ TimedEvents tes;
+ const int kWindowWidth = 123;
+ const int kWindowHeight = 45;
+ const int kTouchId = 6;
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ delegate->Reset();
+
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
+ kTouchId, tes.Now());
+ DispatchEventUsingWindowDispatcher(&press1);
+ EXPECT_TRUE(delegate->tap_down());
+
+ int default_flags = delegate->flags();
+
+ ui::TouchEvent move1(
+ ui::ET_TOUCH_MOVED, gfx::Point(397, 149), kTouchId, tes.LeapForward(50));
+ move1.set_flags(992);
+
+ DispatchEventUsingWindowDispatcher(&move1);
+ EXPECT_NE(default_flags, delegate->flags());
+}
+
+// Test that latency info is passed through to the gesture event.
+TEST_P(GestureRecognizerTest, LatencyPassedFromTouchEvent) {
+ scoped_ptr<GestureEventConsumeDelegate> delegate(
+ new GestureEventConsumeDelegate());
+ TimedEvents tes;
+ const int kWindowWidth = 123;
+ const int kWindowHeight = 45;
+ const int kTouchId = 6;
+
+ const base::TimeTicks time_original = base::TimeTicks::FromInternalValue(100);
+ const base::TimeTicks time_ui = base::TimeTicks::FromInternalValue(200);
+ const base::TimeTicks time_acked = base::TimeTicks::FromInternalValue(300);
+
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ delegate.get(), -1234, bounds, root_window()));
+
+ delegate->Reset();
+
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
+ kTouchId, tes.Now());
+
+ // Ensure the only components around are the ones we add.
+ press1.latency()->Clear();
+
+ press1.latency()->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, time_original, 1);
+
+ press1.latency()->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0, time_ui, 1);
+
+ press1.latency()->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT, 0, 0, time_acked, 1);
+
+ DispatchEventUsingWindowDispatcher(&press1);
+ EXPECT_TRUE(delegate->tap_down());
+
+ ui::LatencyInfo::LatencyComponent component;
+
+ EXPECT_EQ(3U, delegate->latency_info().latency_components.size());
+ ASSERT_TRUE(delegate->latency_info().FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, &component));
+ EXPECT_EQ(time_original, component.event_time);
+
+ ASSERT_TRUE(delegate->latency_info().FindLatency(
+ ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, &component));
+ EXPECT_EQ(time_ui, component.event_time);
+
+ ASSERT_TRUE(delegate->latency_info().FindLatency(
+ ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT, 0, &component));
+ EXPECT_EQ(time_acked, component.event_time);
+
+ delegate->WaitUntilReceivedGesture(ui::ET_GESTURE_SHOW_PRESS);
+ EXPECT_TRUE(delegate->show_press());
+ EXPECT_EQ(0U, delegate->latency_info().latency_components.size());
+}
+
+// A delegate that deletes a window on long press.
+class GestureEventDeleteWindowOnLongPress : public GestureEventConsumeDelegate {
+ public:
+ GestureEventDeleteWindowOnLongPress()
+ : window_(NULL) {}
+
+ void set_window(aura::Window** window) { window_ = window; }
+
+ virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE {
+ GestureEventConsumeDelegate::OnGestureEvent(gesture);
+ if (gesture->type() != ui::ET_GESTURE_LONG_PRESS)
+ return;
+ ui::GestureRecognizer::Get()->CleanupStateForConsumer(*window_);
+ delete *window_;
+ *window_ = NULL;
+ }
+
+ private:
+ aura::Window** window_;
+ DISALLOW_COPY_AND_ASSIGN(GestureEventDeleteWindowOnLongPress);
+};
+
+// Check that deleting the window in response to a long press gesture doesn't
+// crash.
+TEST_P(GestureRecognizerTest, GestureEventLongPressDeletingWindow) {
+ GestureEventDeleteWindowOnLongPress delegate;
+ const int kWindowWidth = 123;
+ const int kWindowHeight = 45;
+ const int kTouchId = 2;
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight);
+ aura::Window* window(CreateTestWindowWithDelegate(
+ &delegate, -1234, bounds, root_window()));
+ delegate.set_window(&window);
+
+ ui::TouchEvent press1(ui::ET_TOUCH_PRESSED,
+ gfx::Point(101, 201),
+ kTouchId,
+ ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press1);
+ EXPECT_TRUE(window != NULL);
+
+ // Wait until the timer runs out.
+ delegate.WaitUntilReceivedGesture(ui::ET_GESTURE_LONG_PRESS);
+ EXPECT_EQ(NULL, window);
+}
+
+INSTANTIATE_TEST_CASE_P(GestureRecognizer,
+ GestureRecognizerTest,
+ ::testing::Bool());
+
} // namespace test
} // namespace aura
diff --git a/chromium/ui/aura/remote_root_window_host_win.h b/chromium/ui/aura/remote_root_window_host_win.h
deleted file mode 100644
index 5c1066f80fa..00000000000
--- a/chromium/ui/aura/remote_root_window_host_win.h
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_REMOTE_ROOT_WINDOW_HOST_WIN_H_
-#define UI_AURA_REMOTE_ROOT_WINDOW_HOST_WIN_H_
-
-#include <vector>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/strings/string16.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/ime/remote_input_method_delegate_win.h"
-#include "ui/events/event.h"
-#include "ui/events/event_constants.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/metro_viewer/ime_types.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace ui {
-class RemoteInputMethodPrivateWin;
-class ViewProp;
-}
-
-namespace IPC {
-class Message;
-class Sender;
-}
-
-namespace aura {
-
-typedef base::Callback<void(const base::FilePath&, int, void*)>
- OpenFileCompletion;
-
-typedef base::Callback<void(const std::vector<base::FilePath>&, void*)>
- OpenMultipleFilesCompletion;
-
-typedef base::Callback<void(const base::FilePath&, int, void*)>
- SaveFileCompletion;
-
-typedef base::Callback<void(const base::FilePath&, int, void*)>
- SelectFolderCompletion;
-
-typedef base::Callback<void(void*)> FileSelectionCanceled;
-
-// Handles the open file operation for Metro Chrome Ash. The on_success
-// callback passed in is invoked when we receive the opened file name from
-// the metro viewer. The on failure callback is invoked on failure.
-AURA_EXPORT void HandleOpenFile(const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- const OpenFileCompletion& on_success,
- const FileSelectionCanceled& on_failure);
-
-// Handles the open multiple file operation for Metro Chrome Ash. The
-// on_success callback passed in is invoked when we receive the opened file
-// names from the metro viewer. The on failure callback is invoked on failure.
-AURA_EXPORT void HandleOpenMultipleFiles(
- const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- const OpenMultipleFilesCompletion& on_success,
- const FileSelectionCanceled& on_failure);
-
-// Handles the save file operation for Metro Chrome Ash. The on_success
-// callback passed in is invoked when we receive the saved file name from
-// the metro viewer. The on failure callback is invoked on failure.
-AURA_EXPORT void HandleSaveFile(const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- int filter_index,
- const base::string16& default_extension,
- const SaveFileCompletion& on_success,
- const FileSelectionCanceled& on_failure);
-
-// Handles the select folder for Metro Chrome Ash. The on_success
-// callback passed in is invoked when we receive the folder name from the
-// metro viewer. The on failure callback is invoked on failure.
-AURA_EXPORT void HandleSelectFolder(const base::string16& title,
- const SelectFolderCompletion& on_success,
- const FileSelectionCanceled& on_failure);
-
-// Handles the activate desktop command for Metro Chrome Ash. The |ash_exit|
-// parameter indicates whether the Ash process would be shutdown after
-// activating the desktop.
-AURA_EXPORT void HandleActivateDesktop(
- const base::FilePath& shortcut,
- bool ash_exit);
-
-// Handles the metro exit command. Notifies the metro viewer to shutdown
-// gracefully.
-AURA_EXPORT void HandleMetroExit();
-
-// RootWindowHost implementaton that receives events from a different
-// process. In the case of Windows this is the Windows 8 (aka Metro)
-// frontend process, which forwards input events to this class.
-class AURA_EXPORT RemoteRootWindowHostWin
- : public RootWindowHost,
- public ui::internal::RemoteInputMethodDelegateWin {
- public:
- // Returns the only RemoteRootWindowHostWin, if this is the first time
- // this function is called, it will call Create() wiht empty bounds.
- static RemoteRootWindowHostWin* Instance();
- static RemoteRootWindowHostWin* Create(const gfx::Rect& bounds);
-
- // Called when the remote process has established its IPC connection.
- // The |host| can be used when we need to send a message to it and
- // |remote_window| is the actual window owned by the viewer process.
- void Connected(IPC::Sender* host, HWND remote_window);
- // Called when the remote process has closed its IPC connection.
- void Disconnected();
-
- // Called when we have a message from the remote process.
- bool OnMessageReceived(const IPC::Message& message);
-
- void HandleOpenURLOnDesktop(const base::FilePath& shortcut,
- const base::string16& url);
-
- // The |ash_exit| parameter indicates whether the Ash process would be
- // shutdown after activating the desktop.
- void HandleActivateDesktop(const base::FilePath& shortcut, bool ash_exit);
-
- // Notify the metro viewer that it should shut itself down.
- void HandleMetroExit();
-
- void HandleOpenFile(const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- const OpenFileCompletion& on_success,
- const FileSelectionCanceled& on_failure);
-
- void HandleOpenMultipleFiles(const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- const OpenMultipleFilesCompletion& on_success,
- const FileSelectionCanceled& on_failure);
-
- void HandleSaveFile(const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- int filter_index,
- const base::string16& default_extension,
- const SaveFileCompletion& on_success,
- const FileSelectionCanceled& on_failure);
-
- void HandleSelectFolder(const base::string16& title,
- const SelectFolderCompletion& on_success,
- const FileSelectionCanceled& on_failure);
-
- void HandleWindowSizeChanged(uint32 width, uint32 height);
-
- // Returns the active ASH root window.
- Window* GetAshWindow();
-
- // Returns true if the remote window is the foreground window according to the
- // OS.
- bool IsForegroundWindow();
-
- private:
- explicit RemoteRootWindowHostWin(const gfx::Rect& bounds);
- virtual ~RemoteRootWindowHostWin();
-
- // IPC message handing methods:
- void OnMouseMoved(int32 x, int32 y, int32 flags);
- void OnMouseButton(int32 x,
- int32 y,
- int32 extra,
- ui::EventType type,
- ui::EventFlags flags);
- void OnKeyDown(uint32 vkey,
- uint32 repeat_count,
- uint32 scan_code,
- uint32 flags);
- void OnKeyUp(uint32 vkey,
- uint32 repeat_count,
- uint32 scan_code,
- uint32 flags);
- void OnChar(uint32 key_code,
- uint32 repeat_count,
- uint32 scan_code,
- uint32 flags);
- void OnWindowActivated();
- void OnTouchDown(int32 x, int32 y, uint64 timestamp, uint32 pointer_id);
- void OnTouchUp(int32 x, int32 y, uint64 timestamp, uint32 pointer_id);
- void OnTouchMoved(int32 x, int32 y, uint64 timestamp, uint32 pointer_id);
- void OnFileSaveAsDone(bool success,
- const base::FilePath& filename,
- int filter_index);
- void OnFileOpenDone(bool success, const base::FilePath& filename);
- void OnMultiFileOpenDone(bool success,
- const std::vector<base::FilePath>& files);
- void OnSelectFolderDone(bool success, const base::FilePath& folder);
- void OnSetCursorPosAck();
-
- // For Input Method support:
- ui::RemoteInputMethodPrivateWin* GetRemoteInputMethodPrivate();
- void OnImeCandidatePopupChanged(bool visible);
- void OnImeCompositionChanged(
- const string16& text,
- int32 selection_start,
- int32 selection_end,
- const std::vector<metro_viewer::UnderlineInfo>& underlines);
- void OnImeTextCommitted(const string16& text);
- void OnImeInputSourceChanged(uint16 language_id, bool is_ime);
-
- // RootWindowHost overrides:
- virtual RootWindow* GetRootWindow() OVERRIDE;
- virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual void ToggleFullScreen() OVERRIDE;
- virtual gfx::Rect GetBounds() const OVERRIDE;
- virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
- virtual gfx::Insets GetInsets() const OVERRIDE;
- virtual void SetInsets(const gfx::Insets& insets) OVERRIDE;
- virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
- virtual void SetCapture() OVERRIDE;
- virtual void ReleaseCapture() OVERRIDE;
- virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
- virtual bool QueryMouseLocation(gfx::Point* location_return) OVERRIDE;
- virtual bool ConfineCursorToRootWindow() OVERRIDE;
- virtual void UnConfineCursor() OVERRIDE;
- virtual void OnCursorVisibilityChanged(bool show) OVERRIDE;
- virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE;
- virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void PrepareForShutdown() OVERRIDE;
-
- // ui::internal::RemoteInputMethodDelegateWin overrides:
- virtual void CancelComposition() OVERRIDE;
- virtual void OnTextInputClientUpdated(
- const std::vector<int32>& input_scopes,
- const std::vector<gfx::Rect>& composition_character_bounds) OVERRIDE;
-
- // Helper function to dispatch a keyboard message to the desired target.
- // The default target is the RootWindowHostDelegate. For nested message loop
- // invocations we post a synthetic keyboard message directly into the message
- // loop. The dispatcher for the nested loop would then decide how this
- // message is routed.
- void DispatchKeyboardMessage(ui::EventType type,
- uint32 vkey,
- uint32 repeat_count,
- uint32 scan_code,
- uint32 flags,
- bool is_character);
-
- // Sets the event flags. |flags| is a bitmask of EventFlags. If there is a
- // change the system virtual key state is updated as well. This way if chrome
- // queries for key state it matches that of event being dispatched.
- void SetEventFlags(uint32 flags);
-
- uint32 mouse_event_flags() const {
- return event_flags_ & (ui::EF_LEFT_MOUSE_BUTTON |
- ui::EF_MIDDLE_MOUSE_BUTTON |
- ui::EF_RIGHT_MOUSE_BUTTON);
- }
-
- uint32 key_event_flags() const {
- return event_flags_ & (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
- ui::EF_ALT_DOWN | ui::EF_CAPS_LOCK_DOWN);
- }
-
- HWND remote_window_;
- IPC::Sender* host_;
- scoped_ptr<ui::ViewProp> prop_;
-
- // Saved callbacks which inform the caller about the result of the open file/
- // save file/select operations.
- OpenFileCompletion file_open_completion_callback_;
- OpenMultipleFilesCompletion multi_file_open_completion_callback_;
- SaveFileCompletion file_saveas_completion_callback_;
- SelectFolderCompletion select_folder_completion_callback_;
- FileSelectionCanceled failure_callback_;
-
- // Set to true if we need to ignore mouse messages until the SetCursorPos
- // operation is acked by the viewer.
- bool ignore_mouse_moves_until_set_cursor_ack_;
-
- // Tracking last click event for synthetically generated mouse events.
- scoped_ptr<ui::MouseEvent> last_mouse_click_event_;
-
- // State of the keyboard/mouse at the time of the last input event. See
- // description of SetEventFlags().
- uint32 event_flags_;
-
- // Current size of this root window.
- gfx::Size window_size_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoteRootWindowHostWin);
-};
-
-} // namespace aura
-
-#endif // UI_AURA_REMOTE_ROOT_WINDOW_HOST_WIN_H_
diff --git a/chromium/ui/aura/remote_root_window_host_win.cc b/chromium/ui/aura/remote_window_tree_host_win.cc
index 3dba26aacc4..0cd5ee878e9 100644
--- a/chromium/ui/aura/remote_root_window_host_win.cc
+++ b/chromium/ui/aura/remote_window_tree_host_win.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/aura/remote_root_window_host_win.h"
+#include "ui/aura/remote_window_tree_host_win.h"
#include <windows.h>
@@ -13,24 +13,25 @@
#include "ipc/ipc_sender.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
#include "ui/base/cursor/cursor_loader_win.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/remote_input_method_win.h"
#include "ui/base/ime/text_input_client.h"
+#include "ui/base/view_prop.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion_win.h"
-#include "ui/base/view_prop.h"
#include "ui/gfx/insets.h"
+#include "ui/gfx/win/dpi.h"
#include "ui/metro_viewer/metro_viewer_messages.h"
namespace aura {
namespace {
-const char* kRootWindowHostWinKey = "__AURA_REMOTE_ROOT_WINDOW_HOST_WIN__";
+const char* kWindowTreeHostWinKey = "__AURA_REMOTE_WINDOW_TREE_HOST_WIN__";
// Sets the keystate for the virtual key passed in to down or up.
void SetKeyState(uint8* key_states, bool key_down, uint32 virtual_key_code) {
@@ -61,7 +62,7 @@ void SetVirtualKeyStates(uint32 flags) {
}
void FillCompositionText(
- const string16& text,
+ const base::string16& text,
int32 selection_start,
int32 selection_end,
const std::vector<metro_viewer::UnderlineInfo>& underlines,
@@ -76,110 +77,58 @@ void FillCompositionText(
composition_text->underlines[i].end_offset = underlines[i].end_offset;
composition_text->underlines[i].color = SK_ColorBLACK;
composition_text->underlines[i].thick = underlines[i].thick;
+ composition_text->underlines[i].background_color = SK_ColorTRANSPARENT;
}
}
} // namespace
-void HandleOpenFile(const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- const OpenFileCompletion& on_success,
- const FileSelectionCanceled& on_failure) {
- DCHECK(aura::RemoteRootWindowHostWin::Instance());
- aura::RemoteRootWindowHostWin::Instance()->HandleOpenFile(title,
- default_path,
- filter,
- on_success,
- on_failure);
-}
-
-void HandleOpenMultipleFiles(const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- const OpenMultipleFilesCompletion& on_success,
- const FileSelectionCanceled& on_failure) {
- DCHECK(aura::RemoteRootWindowHostWin::Instance());
- aura::RemoteRootWindowHostWin::Instance()->HandleOpenMultipleFiles(
- title,
- default_path,
- filter,
- on_success,
- on_failure);
-}
-
-void HandleSaveFile(const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- int filter_index,
- const base::string16& default_extension,
- const SaveFileCompletion& on_success,
- const FileSelectionCanceled& on_failure) {
- DCHECK(aura::RemoteRootWindowHostWin::Instance());
- aura::RemoteRootWindowHostWin::Instance()->HandleSaveFile(title,
- default_path,
- filter,
- filter_index,
- default_extension,
- on_success,
- on_failure);
-}
-
-void HandleSelectFolder(const base::string16& title,
- const SelectFolderCompletion& on_success,
- const FileSelectionCanceled& on_failure) {
- DCHECK(aura::RemoteRootWindowHostWin::Instance());
- aura::RemoteRootWindowHostWin::Instance()->HandleSelectFolder(title,
- on_success,
- on_failure);
-}
-
-void HandleActivateDesktop(const base::FilePath& shortcut,
- bool ash_exit) {
- DCHECK(aura::RemoteRootWindowHostWin::Instance());
- aura::RemoteRootWindowHostWin::Instance()->HandleActivateDesktop(shortcut,
- ash_exit);
-}
-
-void HandleMetroExit() {
- DCHECK(aura::RemoteRootWindowHostWin::Instance());
- aura::RemoteRootWindowHostWin::Instance()->HandleMetroExit();
-}
-
-RemoteRootWindowHostWin* g_instance = NULL;
-
-RemoteRootWindowHostWin* RemoteRootWindowHostWin::Instance() {
- if (g_instance)
- return g_instance;
- return Create(gfx::Rect());
-}
-
-RemoteRootWindowHostWin* RemoteRootWindowHostWin::Create(
- const gfx::Rect& bounds) {
- g_instance = g_instance ? g_instance : new RemoteRootWindowHostWin(bounds);
+RemoteWindowTreeHostWin* g_instance = NULL;
+
+// static
+RemoteWindowTreeHostWin* RemoteWindowTreeHostWin::Instance() {
return g_instance;
}
-RemoteRootWindowHostWin::RemoteRootWindowHostWin(const gfx::Rect& bounds)
+RemoteWindowTreeHostWin::RemoteWindowTreeHostWin()
: remote_window_(NULL),
host_(NULL),
ignore_mouse_moves_until_set_cursor_ack_(false),
event_flags_(0),
- window_size_(aura::RootWindowHost::GetNativeScreenSize()) {
- prop_.reset(new ui::ViewProp(NULL, kRootWindowHostWinKey, this));
+ window_size_(aura::WindowTreeHost::GetNativeScreenSize()) {
+ CHECK(!g_instance);
+ g_instance = this;
+ prop_.reset(new ui::ViewProp(NULL, kWindowTreeHostWinKey, this));
+ CreateCompositor(GetAcceleratedWidget());
}
-RemoteRootWindowHostWin::~RemoteRootWindowHostWin() {
+RemoteWindowTreeHostWin::~RemoteWindowTreeHostWin() {
+ DestroyCompositor();
+ DestroyDispatcher();
+ DCHECK_EQ(g_instance, this);
g_instance = NULL;
}
-void RemoteRootWindowHostWin::Connected(IPC::Sender* host, HWND remote_window) {
+// static
+bool RemoteWindowTreeHostWin::IsValid() {
+ return Instance()->remote_window_ != NULL;
+}
+
+void RemoteWindowTreeHostWin::SetRemoteWindowHandle(HWND remote_window) {
+ remote_window_ = remote_window;
+}
+
+void RemoteWindowTreeHostWin::Connected(IPC::Sender* host) {
CHECK(host_ == NULL);
+ DCHECK(remote_window_);
host_ = host;
- remote_window_ = remote_window;
+ // Recreate the compositor for the target surface represented by the
+ // remote_window HWND.
+ CreateCompositor(remote_window_);
+ InitCompositor();
}
-void RemoteRootWindowHostWin::Disconnected() {
+void RemoteWindowTreeHostWin::Disconnected() {
// Don't CHECK here, Disconnected is called on a channel error which can
// happen before we're successfully Connected.
if (!host_)
@@ -192,9 +141,9 @@ void RemoteRootWindowHostWin::Disconnected() {
remote_window_ = NULL;
}
-bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message& message) {
+bool RemoteWindowTreeHostWin::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RemoteRootWindowHostWin, message)
+ IPC_BEGIN_MESSAGE_MAP(RemoteWindowTreeHostWin, message)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseMoved, OnMouseMoved)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseButton, OnMouseButton)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyDown, OnKeyDown)
@@ -202,20 +151,13 @@ bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_Character, OnChar)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowActivated,
OnWindowActivated)
+ IPC_MESSAGE_HANDLER(MetroViewerHostMsg_EdgeGesture, OnEdgeGesture)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchDown,
OnTouchDown)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchUp,
OnTouchUp)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchMoved,
OnTouchMoved)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileSaveAsDone,
- OnFileSaveAsDone)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileOpenDone,
- OnFileOpenDone)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MultiFileOpenDone,
- OnMultiFileOpenDone)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SelectFolderDone,
- OnSelectFolderDone)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPosAck,
OnSetCursorPosAck)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCandidatePopupChanged,
@@ -231,7 +173,7 @@ bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void RemoteRootWindowHostWin::HandleOpenURLOnDesktop(
+void RemoteWindowTreeHostWin::HandleOpenURLOnDesktop(
const base::FilePath& shortcut,
const base::string16& url) {
if (!host_)
@@ -239,203 +181,68 @@ void RemoteRootWindowHostWin::HandleOpenURLOnDesktop(
host_->Send(new MetroViewerHostMsg_OpenURLOnDesktop(shortcut, url));
}
-void RemoteRootWindowHostWin::HandleActivateDesktop(
- const base::FilePath& shortcut,
- bool ash_exit) {
- if (!host_)
- return;
- host_->Send(new MetroViewerHostMsg_ActivateDesktop(shortcut, ash_exit));
-}
-
-void RemoteRootWindowHostWin::HandleMetroExit() {
- if (!host_)
- return;
- host_->Send(new MetroViewerHostMsg_MetroExit());
-}
-
-void RemoteRootWindowHostWin::HandleOpenFile(
- const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- const OpenFileCompletion& on_success,
- const FileSelectionCanceled& on_failure) {
- if (!host_)
- return;
-
- // Can only have one of these operations in flight.
- DCHECK(file_open_completion_callback_.is_null());
- DCHECK(failure_callback_.is_null());
-
- file_open_completion_callback_ = on_success;
- failure_callback_ = on_failure;
-
- host_->Send(new MetroViewerHostMsg_DisplayFileOpen(title,
- filter,
- default_path,
- false));
-}
-
-void RemoteRootWindowHostWin::HandleOpenMultipleFiles(
- const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- const OpenMultipleFilesCompletion& on_success,
- const FileSelectionCanceled& on_failure) {
- if (!host_)
- return;
-
- // Can only have one of these operations in flight.
- DCHECK(multi_file_open_completion_callback_.is_null());
- DCHECK(failure_callback_.is_null());
- multi_file_open_completion_callback_ = on_success;
- failure_callback_ = on_failure;
-
- host_->Send(new MetroViewerHostMsg_DisplayFileOpen(title,
- filter,
- default_path,
- true));
-}
-
-void RemoteRootWindowHostWin::HandleSaveFile(
- const base::string16& title,
- const base::FilePath& default_path,
- const base::string16& filter,
- int filter_index,
- const base::string16& default_extension,
- const SaveFileCompletion& on_success,
- const FileSelectionCanceled& on_failure) {
- if (!host_)
- return;
-
- MetroViewerHostMsg_SaveAsDialogParams params;
- params.title = title;
- params.default_extension = default_extension;
- params.filter = filter;
- params.filter_index = filter_index;
- params.suggested_name = default_path;
-
- // Can only have one of these operations in flight.
- DCHECK(file_saveas_completion_callback_.is_null());
- DCHECK(failure_callback_.is_null());
- file_saveas_completion_callback_ = on_success;
- failure_callback_ = on_failure;
-
- host_->Send(new MetroViewerHostMsg_DisplayFileSaveAs(params));
-}
-
-void RemoteRootWindowHostWin::HandleSelectFolder(
- const base::string16& title,
- const SelectFolderCompletion& on_success,
- const FileSelectionCanceled& on_failure) {
- if (!host_)
- return;
-
- // Can only have one of these operations in flight.
- DCHECK(select_folder_completion_callback_.is_null());
- DCHECK(failure_callback_.is_null());
- select_folder_completion_callback_ = on_success;
- failure_callback_ = on_failure;
-
- host_->Send(new MetroViewerHostMsg_DisplaySelectFolder(title));
-}
-
-void RemoteRootWindowHostWin::HandleWindowSizeChanged(uint32 width,
+void RemoteWindowTreeHostWin::HandleWindowSizeChanged(uint32 width,
uint32 height) {
SetBounds(gfx::Rect(0, 0, width, height));
}
-bool RemoteRootWindowHostWin::IsForegroundWindow() {
+bool RemoteWindowTreeHostWin::IsForegroundWindow() {
return ::GetForegroundWindow() == remote_window_;
}
-Window* RemoteRootWindowHostWin::GetAshWindow() {
- return GetRootWindow()->window();
+Window* RemoteWindowTreeHostWin::GetAshWindow() {
+ return window();
}
-RootWindow* RemoteRootWindowHostWin::GetRootWindow() {
- return delegate_->AsRootWindow();
+ui::EventSource* RemoteWindowTreeHostWin::GetEventSource() {
+ return this;
}
-gfx::AcceleratedWidget RemoteRootWindowHostWin::GetAcceleratedWidget() {
+gfx::AcceleratedWidget RemoteWindowTreeHostWin::GetAcceleratedWidget() {
if (remote_window_)
return remote_window_;
// Getting here should only happen for ash_unittests.exe and related code.
return ::GetDesktopWindow();
}
-void RemoteRootWindowHostWin::Show() {
+void RemoteWindowTreeHostWin::Show() {
ui::RemoteInputMethodPrivateWin* remote_input_method_private =
GetRemoteInputMethodPrivate();
if (remote_input_method_private)
remote_input_method_private->SetRemoteDelegate(this);
}
-void RemoteRootWindowHostWin::Hide() {
+void RemoteWindowTreeHostWin::Hide() {
NOTIMPLEMENTED();
}
-void RemoteRootWindowHostWin::ToggleFullScreen() {
-}
-
-gfx::Rect RemoteRootWindowHostWin::GetBounds() const {
+gfx::Rect RemoteWindowTreeHostWin::GetBounds() const {
return gfx::Rect(window_size_);
}
-void RemoteRootWindowHostWin::SetBounds(const gfx::Rect& bounds) {
+void RemoteWindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
window_size_ = bounds.size();
- delegate_->OnHostResized(bounds.size());
+ OnHostResized(bounds.size());
}
-gfx::Insets RemoteRootWindowHostWin::GetInsets() const {
- return gfx::Insets();
+gfx::Point RemoteWindowTreeHostWin::GetLocationOnNativeScreen() const {
+ return gfx::Point(0, 0);
}
-void RemoteRootWindowHostWin::SetInsets(const gfx::Insets& insets) {
+void RemoteWindowTreeHostWin::SetCapture() {
}
-gfx::Point RemoteRootWindowHostWin::GetLocationOnNativeScreen() const {
- return gfx::Point(0, 0);
+void RemoteWindowTreeHostWin::ReleaseCapture() {
}
-void RemoteRootWindowHostWin::SetCursor(gfx::NativeCursor native_cursor) {
+void RemoteWindowTreeHostWin::SetCursorNative(gfx::NativeCursor native_cursor) {
if (!host_)
return;
host_->Send(
new MetroViewerHostMsg_SetCursor(uint64(native_cursor.platform())));
}
-void RemoteRootWindowHostWin::SetCapture() {
-}
-
-void RemoteRootWindowHostWin::ReleaseCapture() {
-}
-
-bool RemoteRootWindowHostWin::QueryMouseLocation(gfx::Point* location_return) {
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(GetRootWindow()->window());
- if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
- *location_return = gfx::Point(0, 0);
- return false;
- }
- POINT pt;
- GetCursorPos(&pt);
- *location_return =
- gfx::Point(static_cast<int>(pt.x), static_cast<int>(pt.y));
- return true;
-}
-
-bool RemoteRootWindowHostWin::ConfineCursorToRootWindow() {
- return true;
-}
-
-void RemoteRootWindowHostWin::UnConfineCursor() {
-}
-
-void RemoteRootWindowHostWin::OnCursorVisibilityChanged(bool show) {
- NOTIMPLEMENTED();
-}
-
-void RemoteRootWindowHostWin::MoveCursorTo(const gfx::Point& location) {
+void RemoteWindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
VLOG(1) << "In MoveCursorTo: " << location.x() << ", " << location.y();
if (!host_)
return;
@@ -460,25 +267,34 @@ void RemoteRootWindowHostWin::MoveCursorTo(const gfx::Point& location) {
host_->Send(new MetroViewerHostMsg_SetCursorPos(location.x(), location.y()));
}
-void RemoteRootWindowHostWin::PostNativeEvent(
+void RemoteWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
+ NOTIMPLEMENTED();
+}
+
+void RemoteWindowTreeHostWin::PostNativeEvent(
const base::NativeEvent& native_event) {
}
-void RemoteRootWindowHostWin::OnDeviceScaleFactorChanged(
+void RemoteWindowTreeHostWin::OnDeviceScaleFactorChanged(
float device_scale_factor) {
NOTIMPLEMENTED();
}
-void RemoteRootWindowHostWin::PrepareForShutdown() {
+ui::EventProcessor* RemoteWindowTreeHostWin::GetEventProcessor() {
+ return dispatcher();
}
-void RemoteRootWindowHostWin::CancelComposition() {
+void RemoteWindowTreeHostWin::CancelComposition() {
+ if (!host_)
+ return;
host_->Send(new MetroViewerHostMsg_ImeCancelComposition);
}
-void RemoteRootWindowHostWin::OnTextInputClientUpdated(
+void RemoteWindowTreeHostWin::OnTextInputClientUpdated(
const std::vector<int32>& input_scopes,
const std::vector<gfx::Rect>& composition_character_bounds) {
+ if (!host_)
+ return;
std::vector<metro_viewer::CharacterBounds> character_bounds;
for (size_t i = 0; i < composition_character_bounds.size(); ++i) {
const gfx::Rect& rect = composition_character_bounds[i];
@@ -493,29 +309,35 @@ void RemoteRootWindowHostWin::OnTextInputClientUpdated(
input_scopes, character_bounds));
}
-void RemoteRootWindowHostWin::OnMouseMoved(int32 x, int32 y, int32 flags) {
+gfx::Point PointFromNativeEvent(int32 x, int32 y) {
+ static float scale_factor = gfx::GetDPIScale();
+ gfx::Point result( x * scale_factor, y * scale_factor);
+ return result;
+}
+
+void RemoteWindowTreeHostWin::OnMouseMoved(int32 x, int32 y, int32 flags) {
if (ignore_mouse_moves_until_set_cursor_ack_)
return;
- gfx::Point location(x, y);
- ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location, flags);
- delegate_->OnHostMouseEvent(&event);
-}
-
-void RemoteRootWindowHostWin::OnMouseButton(
- int32 x,
- int32 y,
- int32 extra,
- ui::EventType type,
- ui::EventFlags flags) {
- gfx::Point location(x, y);
- ui::MouseEvent mouse_event(type, location, location, flags);
-
- SetEventFlags(flags | key_event_flags());
- if (type == ui::ET_MOUSEWHEEL) {
- ui::MouseWheelEvent wheel_event(mouse_event, 0, extra);
- delegate_->OnHostMouseEvent(&wheel_event);
- } else if (type == ui::ET_MOUSE_PRESSED) {
+ gfx::Point location = PointFromNativeEvent(x, y);
+ ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location, flags, 0);
+ SendEventToProcessor(&event);
+}
+
+void RemoteWindowTreeHostWin::OnMouseButton(
+ const MetroViewerHostMsg_MouseButtonParams& params) {
+ gfx::Point location = PointFromNativeEvent(params.x, params.y);
+ ui::MouseEvent mouse_event(params.event_type, location, location,
+ static_cast<int>(params.flags),
+ static_cast<int>(params.changed_button));
+
+ SetEventFlags(params.flags | key_event_flags());
+ if (params.event_type == ui::ET_MOUSEWHEEL) {
+ int x_offset = params.is_horizontal_wheel ? params.extra : 0;
+ int y_offset = !params.is_horizontal_wheel ? params.extra : 0;
+ ui::MouseWheelEvent wheel_event(mouse_event, x_offset, y_offset);
+ SendEventToProcessor(&wheel_event);
+ } else if (params.event_type == ui::ET_MOUSE_PRESSED) {
// TODO(shrikant): Ideally modify code in event.cc by adding automatic
// tracking of double clicks in synthetic MouseEvent constructor code.
// Non-synthetic MouseEvent constructor code does automatically track
@@ -530,13 +352,13 @@ void RemoteRootWindowHostWin::OnMouseButton(
mouse_event.SetClickCount(1);
}
last_mouse_click_event_ .reset(new ui::MouseEvent(mouse_event));
- delegate_->OnHostMouseEvent(&mouse_event);
+ SendEventToProcessor(&mouse_event);
} else {
- delegate_->OnHostMouseEvent(&mouse_event);
+ SendEventToProcessor(&mouse_event);
}
}
-void RemoteRootWindowHostWin::OnKeyDown(uint32 vkey,
+void RemoteWindowTreeHostWin::OnKeyDown(uint32 vkey,
uint32 repeat_count,
uint32 scan_code,
uint32 flags) {
@@ -544,7 +366,7 @@ void RemoteRootWindowHostWin::OnKeyDown(uint32 vkey,
flags, false);
}
-void RemoteRootWindowHostWin::OnKeyUp(uint32 vkey,
+void RemoteWindowTreeHostWin::OnKeyUp(uint32 vkey,
uint32 repeat_count,
uint32 scan_code,
uint32 flags) {
@@ -552,7 +374,7 @@ void RemoteRootWindowHostWin::OnKeyUp(uint32 vkey,
flags, false);
}
-void RemoteRootWindowHostWin::OnChar(uint32 key_code,
+void RemoteWindowTreeHostWin::OnChar(uint32 key_code,
uint32 repeat_count,
uint32 scan_code,
uint32 flags) {
@@ -560,100 +382,71 @@ void RemoteRootWindowHostWin::OnChar(uint32 key_code,
scan_code, flags, true);
}
-void RemoteRootWindowHostWin::OnWindowActivated() {
- delegate_->OnHostActivated();
+void RemoteWindowTreeHostWin::OnWindowActivated() {
+ OnHostActivated();
}
-void RemoteRootWindowHostWin::OnTouchDown(int32 x,
+void RemoteWindowTreeHostWin::OnEdgeGesture() {
+ ui::GestureEvent event(
+ ui::ET_GESTURE_WIN8_EDGE_SWIPE,
+ 0,
+ 0,
+ 0,
+ ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_WIN8_EDGE_SWIPE, 0, 0),
+ 0);
+ SendEventToProcessor(&event);
+}
+
+void RemoteWindowTreeHostWin::OnTouchDown(int32 x,
int32 y,
uint64 timestamp,
uint32 pointer_id) {
+ gfx::Point location = PointFromNativeEvent(x, y);
ui::TouchEvent event(ui::ET_TOUCH_PRESSED,
- gfx::Point(x, y),
+ location,
pointer_id,
base::TimeDelta::FromMicroseconds(timestamp));
- delegate_->OnHostTouchEvent(&event);
+ SendEventToProcessor(&event);
}
-void RemoteRootWindowHostWin::OnTouchUp(int32 x,
+void RemoteWindowTreeHostWin::OnTouchUp(int32 x,
int32 y,
uint64 timestamp,
uint32 pointer_id) {
+ gfx::Point location = PointFromNativeEvent(x, y);
ui::TouchEvent event(ui::ET_TOUCH_RELEASED,
- gfx::Point(x, y),
+ location,
pointer_id,
base::TimeDelta::FromMicroseconds(timestamp));
- delegate_->OnHostTouchEvent(&event);
+ SendEventToProcessor(&event);
}
-void RemoteRootWindowHostWin::OnTouchMoved(int32 x,
+void RemoteWindowTreeHostWin::OnTouchMoved(int32 x,
int32 y,
uint64 timestamp,
uint32 pointer_id) {
+ gfx::Point location = PointFromNativeEvent(x, y);
ui::TouchEvent event(ui::ET_TOUCH_MOVED,
- gfx::Point(x, y),
+ location,
pointer_id,
base::TimeDelta::FromMicroseconds(timestamp));
- delegate_->OnHostTouchEvent(&event);
-}
-
-void RemoteRootWindowHostWin::OnFileSaveAsDone(bool success,
- const base::FilePath& filename,
- int filter_index) {
- if (success)
- file_saveas_completion_callback_.Run(filename, filter_index, NULL);
- else
- failure_callback_.Run(NULL);
- file_saveas_completion_callback_.Reset();
- failure_callback_.Reset();
-}
-
-
-void RemoteRootWindowHostWin::OnFileOpenDone(bool success,
- const base::FilePath& filename) {
- if (success)
- file_open_completion_callback_.Run(base::FilePath(filename), 0, NULL);
- else
- failure_callback_.Run(NULL);
- file_open_completion_callback_.Reset();
- failure_callback_.Reset();
-}
-
-void RemoteRootWindowHostWin::OnMultiFileOpenDone(
- bool success,
- const std::vector<base::FilePath>& files) {
- if (success)
- multi_file_open_completion_callback_.Run(files, NULL);
- else
- failure_callback_.Run(NULL);
- multi_file_open_completion_callback_.Reset();
- failure_callback_.Reset();
-}
-
-void RemoteRootWindowHostWin::OnSelectFolderDone(
- bool success,
- const base::FilePath& folder) {
- if (success)
- select_folder_completion_callback_.Run(base::FilePath(folder), 0, NULL);
- else
- failure_callback_.Run(NULL);
- select_folder_completion_callback_.Reset();
- failure_callback_.Reset();
+ SendEventToProcessor(&event);
}
-void RemoteRootWindowHostWin::OnSetCursorPosAck() {
+void RemoteWindowTreeHostWin::OnSetCursorPosAck() {
DCHECK(ignore_mouse_moves_until_set_cursor_ack_);
ignore_mouse_moves_until_set_cursor_ack_ = false;
}
ui::RemoteInputMethodPrivateWin*
-RemoteRootWindowHostWin::GetRemoteInputMethodPrivate() {
+RemoteWindowTreeHostWin::GetRemoteInputMethodPrivate() {
ui::InputMethod* input_method = GetAshWindow()->GetProperty(
aura::client::kRootWindowInputMethodKey);
return ui::RemoteInputMethodPrivateWin::Get(input_method);
}
-void RemoteRootWindowHostWin::OnImeCandidatePopupChanged(bool visible) {
+void RemoteWindowTreeHostWin::OnImeCandidatePopupChanged(bool visible) {
ui::RemoteInputMethodPrivateWin* remote_input_method_private =
GetRemoteInputMethodPrivate();
if (!remote_input_method_private)
@@ -661,8 +454,8 @@ void RemoteRootWindowHostWin::OnImeCandidatePopupChanged(bool visible) {
remote_input_method_private->OnCandidatePopupChanged(visible);
}
-void RemoteRootWindowHostWin::OnImeCompositionChanged(
- const string16& text,
+void RemoteWindowTreeHostWin::OnImeCompositionChanged(
+ const base::string16& text,
int32 selection_start,
int32 selection_end,
const std::vector<metro_viewer::UnderlineInfo>& underlines) {
@@ -676,7 +469,7 @@ void RemoteRootWindowHostWin::OnImeCompositionChanged(
remote_input_method_private->OnCompositionChanged(composition_text);
}
-void RemoteRootWindowHostWin::OnImeTextCommitted(const string16& text) {
+void RemoteWindowTreeHostWin::OnImeTextCommitted(const base::string16& text) {
ui::RemoteInputMethodPrivateWin* remote_input_method_private =
GetRemoteInputMethodPrivate();
if (!remote_input_method_private)
@@ -684,7 +477,7 @@ void RemoteRootWindowHostWin::OnImeTextCommitted(const string16& text) {
remote_input_method_private->OnTextCommitted(text);
}
-void RemoteRootWindowHostWin::OnImeInputSourceChanged(uint16 language_id,
+void RemoteWindowTreeHostWin::OnImeInputSourceChanged(uint16 language_id,
bool is_ime) {
ui::RemoteInputMethodPrivateWin* remote_input_method_private =
GetRemoteInputMethodPrivate();
@@ -693,7 +486,7 @@ void RemoteRootWindowHostWin::OnImeInputSourceChanged(uint16 language_id,
remote_input_method_private->OnInputSourceChanged(language_id, is_ime);
}
-void RemoteRootWindowHostWin::DispatchKeyboardMessage(ui::EventType type,
+void RemoteWindowTreeHostWin::DispatchKeyboardMessage(ui::EventType type,
uint32 vkey,
uint32 repeat_count,
uint32 scan_code,
@@ -718,11 +511,11 @@ void RemoteRootWindowHostWin::DispatchKeyboardMessage(ui::EventType type,
ui::KeyboardCodeForWindowsKeyCode(vkey),
flags,
is_character);
- delegate_->OnHostKeyEvent(&event);
+ SendEventToProcessor(&event);
}
}
-void RemoteRootWindowHostWin::SetEventFlags(uint32 flags) {
+void RemoteWindowTreeHostWin::SetEventFlags(uint32 flags) {
if (flags == event_flags_)
return;
event_flags_ = flags;
diff --git a/chromium/ui/aura/remote_window_tree_host_win.h b/chromium/ui/aura/remote_window_tree_host_win.h
new file mode 100644
index 00000000000..ae63b744715
--- /dev/null
+++ b/chromium/ui/aura/remote_window_tree_host_win.h
@@ -0,0 +1,194 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_REMOTE_WINDOW_TREE_HOST_WIN_H_
+#define UI_AURA_REMOTE_WINDOW_TREE_HOST_WIN_H_
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/strings/string16.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/ime/remote_input_method_delegate_win.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/event_source.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/metro_viewer/ime_types.h"
+
+struct MetroViewerHostMsg_MouseButtonParams;
+
+namespace base {
+class FilePath;
+}
+
+namespace ui {
+class RemoteInputMethodPrivateWin;
+class ViewProp;
+}
+
+namespace IPC {
+class Message;
+class Sender;
+}
+
+namespace aura {
+
+// WindowTreeHost implementaton that receives events from a different
+// process. In the case of Windows this is the Windows 8 (aka Metro)
+// frontend process, which forwards input events to this class.
+class AURA_EXPORT RemoteWindowTreeHostWin
+ : public WindowTreeHost,
+ public ui::EventSource,
+ public ui::internal::RemoteInputMethodDelegateWin {
+ public:
+ // Returns the current RemoteWindowTreeHostWin. This does *not* create a
+ // RemoteWindowTreeHostWin.
+ static RemoteWindowTreeHostWin* Instance();
+
+ // Returns true if there is a RemoteWindowTreeHostWin and it has a valid
+ // HWND. A return value of false typically indicates we're not in metro mode.
+ static bool IsValid();
+
+ // Sets the handle to the remote window. The |remote_window| is the actual
+ // window owned by the viewer process. Call this before Connected() for some
+ // customers like input method initialization which needs the handle.
+ void SetRemoteWindowHandle(HWND remote_window);
+ HWND remote_window() { return remote_window_; }
+
+ // The |host| can be used when we need to send a message to it.
+ void Connected(IPC::Sender* host);
+ // Called when the remote process has closed its IPC connection.
+ void Disconnected();
+
+ // Called when we have a message from the remote process.
+ bool OnMessageReceived(const IPC::Message& message);
+
+ void HandleOpenURLOnDesktop(const base::FilePath& shortcut,
+ const base::string16& url);
+
+ void HandleWindowSizeChanged(uint32 width, uint32 height);
+
+ // Returns the active ASH root window.
+ Window* GetAshWindow();
+
+ // Returns true if the remote window is the foreground window according to the
+ // OS.
+ bool IsForegroundWindow();
+
+ protected:
+ RemoteWindowTreeHostWin();
+ virtual ~RemoteWindowTreeHostWin();
+
+ private:
+ // IPC message handing methods:
+ void OnMouseMoved(int32 x, int32 y, int32 flags);
+ void OnMouseButton(const MetroViewerHostMsg_MouseButtonParams& params);
+ void OnKeyDown(uint32 vkey,
+ uint32 repeat_count,
+ uint32 scan_code,
+ uint32 flags);
+ void OnKeyUp(uint32 vkey,
+ uint32 repeat_count,
+ uint32 scan_code,
+ uint32 flags);
+ void OnChar(uint32 key_code,
+ uint32 repeat_count,
+ uint32 scan_code,
+ uint32 flags);
+ void OnWindowActivated();
+ void OnEdgeGesture();
+ void OnTouchDown(int32 x, int32 y, uint64 timestamp, uint32 pointer_id);
+ void OnTouchUp(int32 x, int32 y, uint64 timestamp, uint32 pointer_id);
+ void OnTouchMoved(int32 x, int32 y, uint64 timestamp, uint32 pointer_id);
+ void OnSetCursorPosAck();
+
+ // For Input Method support:
+ ui::RemoteInputMethodPrivateWin* GetRemoteInputMethodPrivate();
+ void OnImeCandidatePopupChanged(bool visible);
+ void OnImeCompositionChanged(
+ const base::string16& text,
+ int32 selection_start,
+ int32 selection_end,
+ const std::vector<metro_viewer::UnderlineInfo>& underlines);
+ void OnImeTextCommitted(const base::string16& text);
+ void OnImeInputSourceChanged(uint16 language_id, bool is_ime);
+
+ // WindowTreeHost overrides:
+ virtual ui::EventSource* GetEventSource() OVERRIDE;
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual gfx::Rect GetBounds() const OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
+ virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
+ virtual void SetCapture() OVERRIDE;
+ virtual void ReleaseCapture() OVERRIDE;
+ virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
+ virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+ virtual void SetCursorNative(gfx::NativeCursor cursor) OVERRIDE;
+ virtual void MoveCursorToNative(const gfx::Point& location) OVERRIDE;
+ virtual void OnCursorVisibilityChangedNative(bool show) OVERRIDE;
+
+ // ui::EventSource:
+ virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
+
+ // ui::internal::RemoteInputMethodDelegateWin overrides:
+ virtual void CancelComposition() OVERRIDE;
+ virtual void OnTextInputClientUpdated(
+ const std::vector<int32>& input_scopes,
+ const std::vector<gfx::Rect>& composition_character_bounds) OVERRIDE;
+
+ // Helper function to dispatch a keyboard message to the desired target.
+ // The default target is the WindowEventDispatcher. For nested message loop
+ // invocations we post a synthetic keyboard message directly into the message
+ // loop. The dispatcher for the nested loop would then decide how this
+ // message is routed.
+ void DispatchKeyboardMessage(ui::EventType type,
+ uint32 vkey,
+ uint32 repeat_count,
+ uint32 scan_code,
+ uint32 flags,
+ bool is_character);
+
+ // Sets the event flags. |flags| is a bitmask of EventFlags. If there is a
+ // change the system virtual key state is updated as well. This way if chrome
+ // queries for key state it matches that of event being dispatched.
+ void SetEventFlags(uint32 flags);
+
+ uint32 mouse_event_flags() const {
+ return event_flags_ & (ui::EF_LEFT_MOUSE_BUTTON |
+ ui::EF_MIDDLE_MOUSE_BUTTON |
+ ui::EF_RIGHT_MOUSE_BUTTON);
+ }
+
+ uint32 key_event_flags() const {
+ return event_flags_ & (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
+ ui::EF_ALT_DOWN | ui::EF_CAPS_LOCK_DOWN);
+ }
+
+ HWND remote_window_;
+ IPC::Sender* host_;
+ scoped_ptr<ui::ViewProp> prop_;
+
+ // Set to true if we need to ignore mouse messages until the SetCursorPos
+ // operation is acked by the viewer.
+ bool ignore_mouse_moves_until_set_cursor_ack_;
+
+ // Tracking last click event for synthetically generated mouse events.
+ scoped_ptr<ui::MouseEvent> last_mouse_click_event_;
+
+ // State of the keyboard/mouse at the time of the last input event. See
+ // description of SetEventFlags().
+ uint32 event_flags_;
+
+ // Current size of this root window.
+ gfx::Size window_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoteWindowTreeHostWin);
+};
+
+} // namespace aura
+
+#endif // UI_AURA_REMOTE_WINDOW_TREE_HOST_WIN_H_
diff --git a/chromium/ui/aura/root_window.cc b/chromium/ui/aura/root_window.cc
deleted file mode 100644
index 58790da1c36..00000000000
--- a/chromium/ui/aura/root_window.cc
+++ /dev/null
@@ -1,1172 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/root_window.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/aura/client/capture_client.h"
-#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/event_client.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/root_window_observer.h"
-#include "ui/aura/root_window_transformer.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_delegate.h"
-#include "ui/aura/window_targeter.h"
-#include "ui/aura/window_tracker.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/hit_test.h"
-#include "ui/base/view_prop.h"
-#include "ui/compositor/dip_util.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animator.h"
-#include "ui/events/event.h"
-#include "ui/events/gestures/gesture_recognizer.h"
-#include "ui/events/gestures/gesture_types.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/point3_f.h"
-#include "ui/gfx/point_conversions.h"
-#include "ui/gfx/screen.h"
-#include "ui/gfx/size_conversions.h"
-
-using std::vector;
-
-typedef ui::EventDispatchDetails DispatchDetails;
-
-namespace aura {
-
-namespace {
-
-const char kRootWindowForAcceleratedWidget[] =
- "__AURA_ROOT_WINDOW_ACCELERATED_WIDGET__";
-
-// Returns true if |target| has a non-client (frame) component at |location|,
-// in window coordinates.
-bool IsNonClientLocation(Window* target, const gfx::Point& location) {
- if (!target->delegate())
- return false;
- int hit_test_code = target->delegate()->GetNonClientComponent(location);
- return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE;
-}
-
-float GetDeviceScaleFactorFromDisplay(Window* window) {
- gfx::Display display = gfx::Screen::GetScreenFor(window)->
- GetDisplayNearestWindow(window);
- DCHECK(display.is_valid());
- return display.device_scale_factor();
-}
-
-Window* ConsumerToWindow(ui::GestureConsumer* consumer) {
- return consumer ? static_cast<Window*>(consumer) : NULL;
-}
-
-void SetLastMouseLocation(const Window* root_window,
- const gfx::Point& location_in_root) {
- client::ScreenPositionClient* client =
- client::GetScreenPositionClient(root_window);
- if (client) {
- gfx::Point location_in_screen = location_in_root;
- client->ConvertPointToScreen(root_window, &location_in_screen);
- Env::GetInstance()->set_last_mouse_location(location_in_screen);
- } else {
- Env::GetInstance()->set_last_mouse_location(location_in_root);
- }
-}
-
-RootWindowHost* CreateHost(RootWindow* root_window,
- const RootWindow::CreateParams& params) {
- RootWindowHost* host = params.host ?
- params.host : RootWindowHost::Create(params.initial_bounds);
- host->set_delegate(root_window);
- return host;
-}
-
-bool IsUsingEventProcessorForDispatch(const ui::Event& event) {
- return event.IsKeyEvent() ||
- event.IsScrollEvent();
-}
-
-class SimpleRootWindowTransformer : public RootWindowTransformer {
- public:
- SimpleRootWindowTransformer(const Window* root_window,
- const gfx::Transform& transform)
- : root_window_(root_window),
- transform_(transform) {
- }
-
- // RootWindowTransformer overrides:
- virtual gfx::Transform GetTransform() const OVERRIDE {
- return transform_;
- }
-
- virtual gfx::Transform GetInverseTransform() const OVERRIDE {
- gfx::Transform invert;
- if (!transform_.GetInverse(&invert))
- return transform_;
- return invert;
- }
-
- virtual gfx::Rect GetRootWindowBounds(
- const gfx::Size& host_size) const OVERRIDE {
- gfx::Rect bounds(host_size);
- gfx::RectF new_bounds(ui::ConvertRectToDIP(root_window_->layer(), bounds));
- transform_.TransformRect(&new_bounds);
- return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
- }
-
- virtual gfx::Insets GetHostInsets() const OVERRIDE {
- return gfx::Insets();
- }
-
- private:
- virtual ~SimpleRootWindowTransformer() {}
-
- const Window* root_window_;
- const gfx::Transform transform_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer);
-};
-
-} // namespace
-
-RootWindow::CreateParams::CreateParams(const gfx::Rect& a_initial_bounds)
- : initial_bounds(a_initial_bounds),
- host(NULL) {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, public:
-
-RootWindow::RootWindow(const CreateParams& params)
- : window_(new Window(NULL)),
- host_(CreateHost(this, params)),
- touch_ids_down_(0),
- last_cursor_(ui::kCursorNull),
- mouse_pressed_handler_(NULL),
- mouse_moved_handler_(NULL),
- event_dispatch_target_(NULL),
- old_dispatch_target_(NULL),
- synthesize_mouse_move_(false),
- move_hold_count_(0),
- dispatching_held_event_(false),
- repost_event_factory_(this),
- held_event_factory_(this) {
- window()->set_dispatcher(this);
- window()->SetName("RootWindow");
- window()->set_event_targeter(
- scoped_ptr<ui::EventTargeter>(new WindowTargeter()));
-
- compositor_.reset(new ui::Compositor(host_->GetAcceleratedWidget()));
- DCHECK(compositor_.get());
-
- prop_.reset(new ui::ViewProp(host_->GetAcceleratedWidget(),
- kRootWindowForAcceleratedWidget,
- this));
- ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
-}
-
-RootWindow::~RootWindow() {
- TRACE_EVENT0("shutdown", "RootWindow::Destructor");
-
- ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
-
- // Make sure to destroy the compositor before terminating so that state is
- // cleared and we don't hit asserts.
- compositor_.reset();
-
- // An observer may have been added by an animation on the RootWindow.
- window()->layer()->GetAnimator()->RemoveObserver(this);
-
- // Destroy child windows while we're still valid. This is also done by
- // ~Window, but by that time any calls to virtual methods overriden here (such
- // as GetRootWindow()) result in Window's implementation. By destroying here
- // we ensure GetRootWindow() still returns this.
- window()->RemoveOrDestroyChildren();
-
- // Destroying/removing child windows may try to access |host_| (eg.
- // GetAcceleratedWidget())
- host_.reset(NULL);
-
- window()->set_dispatcher(NULL);
-}
-
-// static
-RootWindow* RootWindow::GetForAcceleratedWidget(
- gfx::AcceleratedWidget widget) {
- return reinterpret_cast<RootWindow*>(
- ui::ViewProp::GetValue(widget, kRootWindowForAcceleratedWidget));
-}
-
-void RootWindow::Init() {
- compositor()->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
- host_->GetBounds().size());
- window()->Init(ui::LAYER_NOT_DRAWN);
- compositor()->SetRootLayer(window()->layer());
- transformer_.reset(
- new SimpleRootWindowTransformer(window(), gfx::Transform()));
- UpdateRootWindowSize(host_->GetBounds().size());
- Env::GetInstance()->NotifyRootWindowInitialized(this);
- window()->Show();
-}
-
-void RootWindow::PrepareForShutdown() {
- host_->PrepareForShutdown();
- // discard synthesize event request as well.
- synthesize_mouse_move_ = false;
-}
-
-void RootWindow::RepostEvent(const ui::LocatedEvent& event) {
- DCHECK(event.type() == ui::ET_MOUSE_PRESSED ||
- event.type() == ui::ET_GESTURE_TAP_DOWN);
- // We allow for only one outstanding repostable event. This is used
- // in exiting context menus. A dropped repost request is allowed.
- if (event.type() == ui::ET_MOUSE_PRESSED) {
- held_repostable_event_.reset(
- new ui::MouseEvent(
- static_cast<const ui::MouseEvent&>(event),
- static_cast<aura::Window*>(event.target()),
- window()));
- base::MessageLoop::current()->PostNonNestableTask(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents),
- repost_event_factory_.GetWeakPtr()));
- } else {
- DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN);
- held_repostable_event_.reset();
- // TODO(rbyers): Reposing of gestures is tricky to get
- // right, so it's not yet supported. crbug.com/170987.
- }
-}
-
-RootWindowHostDelegate* RootWindow::AsRootWindowHostDelegate() {
- return this;
-}
-
-void RootWindow::SetHostSize(const gfx::Size& size_in_pixel) {
- DispatchDetails details = DispatchHeldEvents();
- if (details.dispatcher_destroyed)
- return;
- gfx::Rect bounds = host_->GetBounds();
- bounds.set_size(size_in_pixel);
- host_->SetBounds(bounds);
-
- // Requery the location to constrain it within the new root window size.
- gfx::Point point;
- if (host_->QueryMouseLocation(&point)) {
- SetLastMouseLocation(window(),
- ui::ConvertPointToDIP(window()->layer(), point));
- }
-
- synthesize_mouse_move_ = false;
-}
-
-void RootWindow::SetHostBounds(const gfx::Rect& bounds_in_pixel) {
- DCHECK(!bounds_in_pixel.IsEmpty());
- DispatchDetails details = DispatchHeldEvents();
- if (details.dispatcher_destroyed)
- return;
- host_->SetBounds(bounds_in_pixel);
- synthesize_mouse_move_ = false;
-}
-
-void RootWindow::SetCursor(gfx::NativeCursor cursor) {
- last_cursor_ = cursor;
- // A lot of code seems to depend on NULL cursors actually showing an arrow,
- // so just pass everything along to the host.
- host_->SetCursor(cursor);
-}
-
-void RootWindow::OnCursorVisibilityChanged(bool show) {
- // Clear any existing mouse hover effects when the cursor becomes invisible.
- // Note we do not need to dispatch a mouse enter when the cursor becomes
- // visible because that can only happen in response to a mouse event, which
- // will trigger its own mouse enter.
- if (!show)
- DispatchMouseExitAtPoint(GetLastMouseLocationInRoot());
-
- host_->OnCursorVisibilityChanged(show);
-}
-
-void RootWindow::OnMouseEventsEnableStateChanged(bool enabled) {
- // Send entered / exited so that visual state can be updated to match
- // mouse events state.
- PostMouseMoveEventAfterWindowChange();
- // TODO(mazda): Add code to disable mouse events when |enabled| == false.
-}
-
-void RootWindow::MoveCursorTo(const gfx::Point& location_in_dip) {
- gfx::Point host_location(location_in_dip);
- ConvertPointToHost(&host_location);
- MoveCursorToInternal(location_in_dip, host_location);
-}
-
-void RootWindow::MoveCursorToHostLocation(const gfx::Point& host_location) {
- gfx::Point root_location(host_location);
- ConvertPointFromHost(&root_location);
- MoveCursorToInternal(root_location, host_location);
-}
-
-void RootWindow::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
- compositor_->ScheduleRedrawRect(damage_rect);
-}
-
-Window* RootWindow::GetGestureTarget(ui::GestureEvent* event) {
- Window* target = NULL;
- if (!event->IsEndingEvent()) {
- // The window that received the start event (e.g. scroll begin) needs to
- // receive the end event (e.g. scroll end).
- target = client::GetCaptureWindow(window());
- }
- if (!target) {
- target = ConsumerToWindow(
- ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event));
- }
-
- return target;
-}
-
-void RootWindow::DispatchGestureEvent(ui::GestureEvent* event) {
- DispatchDetails details = DispatchHeldEvents();
- if (details.dispatcher_destroyed)
- return;
-
- Window* target = GetGestureTarget(event);
- if (target) {
- event->ConvertLocationToTarget(window(), target);
- DispatchDetails details = DispatchEvent(target, event);
- if (details.dispatcher_destroyed)
- return;
- }
-}
-
-void RootWindow::OnWindowDestroying(Window* window) {
- DispatchMouseExitToHidingWindow(window);
- OnWindowHidden(window, WINDOW_DESTROYED);
-
- if (window->IsVisible() &&
- window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
- PostMouseMoveEventAfterWindowChange();
- }
-}
-
-void RootWindow::OnWindowBoundsChanged(Window* window,
- bool contained_mouse_point) {
- if (contained_mouse_point ||
- (window->IsVisible() &&
- window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
- PostMouseMoveEventAfterWindowChange();
- }
-}
-
-void RootWindow::DispatchMouseExitToHidingWindow(Window* window) {
- // The mouse capture is intentionally ignored. Think that a mouse enters
- // to a window, the window sets the capture, the mouse exits the window,
- // and then it releases the capture. In that case OnMouseExited won't
- // be called. So it is natural not to emit OnMouseExited even though
- // |window| is the capture window.
- gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
- if (window->Contains(mouse_moved_handler_) &&
- window->ContainsPointInRoot(last_mouse_location))
- DispatchMouseExitAtPoint(last_mouse_location);
-}
-
-void RootWindow::DispatchMouseExitAtPoint(const gfx::Point& point) {
- ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE);
- DispatchDetails details =
- DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
- if (details.dispatcher_destroyed)
- return;
-}
-
-void RootWindow::OnWindowVisibilityChanged(Window* window, bool is_visible) {
- if (!is_visible)
- OnWindowHidden(window, WINDOW_HIDDEN);
-
- if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
- PostMouseMoveEventAfterWindowChange();
-}
-
-void RootWindow::OnWindowTransformed(Window* window, bool contained_mouse) {
- if (contained_mouse ||
- (window->IsVisible() &&
- window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
- PostMouseMoveEventAfterWindowChange();
- }
-}
-
-void RootWindow::OnKeyboardMappingChanged() {
- FOR_EACH_OBSERVER(RootWindowObserver, observers_,
- OnKeyboardMappingChanged(this));
-}
-
-void RootWindow::OnRootWindowHostCloseRequested() {
- FOR_EACH_OBSERVER(RootWindowObserver, observers_,
- OnRootWindowHostCloseRequested(this));
-}
-
-void RootWindow::AddRootWindowObserver(RootWindowObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void RootWindow::RemoveRootWindowObserver(RootWindowObserver* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void RootWindow::ConvertPointToHost(gfx::Point* point) const {
- gfx::Point3F point_3f(*point);
- GetRootTransform().TransformPoint(&point_3f);
- *point = gfx::ToFlooredPoint(point_3f.AsPointF());
-}
-
-void RootWindow::ConvertPointFromHost(gfx::Point* point) const {
- gfx::Point3F point_3f(*point);
- GetInverseRootTransform().TransformPoint(&point_3f);
- *point = gfx::ToFlooredPoint(point_3f.AsPointF());
-}
-
-void RootWindow::ProcessedTouchEvent(ui::TouchEvent* event,
- Window* window,
- ui::EventResult result) {
- scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
- gestures.reset(ui::GestureRecognizer::Get()->
- ProcessTouchEventForGesture(*event, result, window));
- DispatchDetails details = ProcessGestures(gestures.get());
- if (details.dispatcher_destroyed)
- return;
-}
-
-void RootWindow::HoldPointerMoves() {
- if (!move_hold_count_)
- held_event_factory_.InvalidateWeakPtrs();
- ++move_hold_count_;
- TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::HoldPointerMoves", this);
-}
-
-void RootWindow::ReleasePointerMoves() {
- --move_hold_count_;
- DCHECK_GE(move_hold_count_, 0);
- if (!move_hold_count_ && held_move_event_) {
- // We don't want to call DispatchHeldEvents directly, because this might be
- // called from a deep stack while another event, in which case dispatching
- // another one may not be safe/expected. Instead we post a task, that we
- // may cancel if HoldPointerMoves is called again before it executes.
- base::MessageLoop::current()->PostNonNestableTask(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents),
- held_event_factory_.GetWeakPtr()));
- }
- TRACE_EVENT_ASYNC_END0("ui", "RootWindow::HoldPointerMoves", this);
-}
-
-gfx::Point RootWindow::GetLastMouseLocationInRoot() const {
- gfx::Point location = Env::GetInstance()->last_mouse_location();
- client::ScreenPositionClient* client =
- client::GetScreenPositionClient(window());
- if (client)
- client->ConvertPointFromScreen(window(), &location);
- return location;
-}
-
-void RootWindow::SetRootWindowTransformer(
- scoped_ptr<RootWindowTransformer> transformer) {
- transformer_ = transformer.Pass();
- host_->SetInsets(transformer_->GetHostInsets());
- window()->SetTransform(transformer_->GetTransform());
- // If the layer is not animating, then we need to update the root window
- // size immediately.
- if (!window()->layer()->GetAnimator()->is_animating())
- UpdateRootWindowSize(host_->GetBounds().size());
-}
-
-gfx::Transform RootWindow::GetRootTransform() const {
- float scale = ui::GetDeviceScaleFactor(window()->layer());
- gfx::Transform transform;
- transform.Scale(scale, scale);
- transform *= transformer_->GetTransform();
- return transform;
-}
-
-void RootWindow::SetTransform(const gfx::Transform& transform) {
- scoped_ptr<RootWindowTransformer> transformer(
- new SimpleRootWindowTransformer(window(), transform));
- SetRootWindowTransformer(transformer.Pass());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, private:
-
-void RootWindow::TransformEventForDeviceScaleFactor(ui::LocatedEvent* event) {
- event->UpdateForRootTransform(GetInverseRootTransform());
-}
-
-void RootWindow::MoveCursorToInternal(const gfx::Point& root_location,
- const gfx::Point& host_location) {
- host_->MoveCursorTo(host_location);
- SetLastMouseLocation(window(), root_location);
- client::CursorClient* cursor_client = client::GetCursorClient(window());
- if (cursor_client) {
- const gfx::Display& display =
- gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
- cursor_client->SetDisplay(display);
- }
- synthesize_mouse_move_ = false;
-}
-
-ui::EventDispatchDetails RootWindow::DispatchMouseEnterOrExit(
- const ui::MouseEvent& event,
- ui::EventType type) {
- if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate())
- return DispatchDetails();
-
- ui::MouseEvent translated_event(event,
- window(),
- mouse_moved_handler_,
- type,
- event.flags() | ui::EF_IS_SYNTHESIZED);
- return DispatchEvent(mouse_moved_handler_, &translated_event);
-}
-
-ui::EventDispatchDetails RootWindow::ProcessGestures(
- ui::GestureRecognizer::Gestures* gestures) {
- DispatchDetails details;
- if (!gestures || gestures->empty())
- return details;
-
- Window* target = GetGestureTarget(gestures->get().at(0));
- for (size_t i = 0; i < gestures->size(); ++i) {
- ui::GestureEvent* event = gestures->get().at(i);
- event->ConvertLocationToTarget(window(), target);
- details = DispatchEvent(target, event);
- if (details.dispatcher_destroyed || details.target_destroyed)
- break;
- }
- return details;
-}
-
-void RootWindow::OnWindowAddedToRootWindow(Window* attached) {
- if (attached->IsVisible() &&
- attached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
- PostMouseMoveEventAfterWindowChange();
- }
-}
-
-void RootWindow::OnWindowRemovedFromRootWindow(Window* detached,
- Window* new_root) {
- DCHECK(aura::client::GetCaptureWindow(window()) != window());
-
- DispatchMouseExitToHidingWindow(detached);
- OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
-
- if (detached->IsVisible() &&
- detached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
- PostMouseMoveEventAfterWindowChange();
- }
-}
-
-void RootWindow::OnWindowHidden(Window* invisible, WindowHiddenReason reason) {
- // Do not clear the capture, and the |event_dispatch_target_| if the
- // window is moving across root windows, because the target itself
- // is actually still visible and clearing them stops further event
- // processing, which can cause unexpected behaviors. See
- // crbug.com/157583
- if (reason != WINDOW_MOVING) {
- Window* capture_window = aura::client::GetCaptureWindow(window());
- // If the ancestor of the capture window is hidden,
- // release the capture.
- if (invisible->Contains(capture_window) && invisible != window())
- capture_window->ReleaseCapture();
-
- if (invisible->Contains(event_dispatch_target_))
- event_dispatch_target_ = NULL;
-
- if (invisible->Contains(old_dispatch_target_))
- old_dispatch_target_ = NULL;
- }
-
- // If the ancestor of any event handler windows are invisible, release the
- // pointer to those windows.
- if (invisible->Contains(mouse_pressed_handler_))
- mouse_pressed_handler_ = NULL;
- if (invisible->Contains(mouse_moved_handler_))
- mouse_moved_handler_ = NULL;
-
- CleanupGestureState(invisible);
-}
-
-void RootWindow::CleanupGestureState(Window* window) {
- ui::GestureRecognizer::Get()->CancelActiveTouches(window);
- ui::GestureRecognizer::Get()->CleanupStateForConsumer(window);
- const Window::Windows& windows = window->children();
- for (Window::Windows::const_iterator iter = windows.begin();
- iter != windows.end();
- ++iter) {
- CleanupGestureState(*iter);
- }
-}
-
-void RootWindow::UpdateRootWindowSize(const gfx::Size& host_size) {
- window()->SetBounds(transformer_->GetRootWindowBounds(host_size));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, aura::client::CaptureDelegate implementation:
-
-void RootWindow::UpdateCapture(Window* old_capture,
- Window* new_capture) {
- // |mouse_moved_handler_| may have been set to a Window in a different root
- // (see below). Clear it here to ensure we don't end up referencing a stale
- // Window.
- if (mouse_moved_handler_ && !window()->Contains(mouse_moved_handler_))
- mouse_moved_handler_ = NULL;
-
- if (old_capture && old_capture->GetRootWindow() == window() &&
- old_capture->delegate()) {
- // Send a capture changed event with bogus location data.
- ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(),
- gfx::Point(), 0);
-
- DispatchDetails details = DispatchEvent(old_capture, &event);
- if (details.dispatcher_destroyed)
- return;
-
- old_capture->delegate()->OnCaptureLost();
- }
-
- if (new_capture) {
- // Make all subsequent mouse events go to the capture window. We shouldn't
- // need to send an event here as OnCaptureLost() should take care of that.
- if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown())
- mouse_moved_handler_ = new_capture;
- } else {
- // Make sure mouse_moved_handler gets updated.
- DispatchDetails details = SynthesizeMouseMoveEvent();
- if (details.dispatcher_destroyed)
- return;
- }
- mouse_pressed_handler_ = NULL;
-}
-
-void RootWindow::OnOtherRootGotCapture() {
- mouse_moved_handler_ = NULL;
- mouse_pressed_handler_ = NULL;
-}
-
-void RootWindow::SetNativeCapture() {
- host_->SetCapture();
-}
-
-void RootWindow::ReleaseNativeCapture() {
- host_->ReleaseCapture();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, ui::EventProcessor implementation:
-ui::EventTarget* RootWindow::GetRootTarget() {
- return window();
-}
-
-void RootWindow::PrepareEventForDispatch(ui::Event* event) {
- if (event->IsMouseEvent() ||
- event->IsScrollEvent() ||
- event->IsTouchEvent() ||
- event->IsGestureEvent()) {
- TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event));
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, ui::EventDispatcherDelegate implementation:
-
-bool RootWindow::CanDispatchToTarget(ui::EventTarget* target) {
- return event_dispatch_target_ == target;
-}
-
-ui::EventDispatchDetails RootWindow::PreDispatchEvent(ui::EventTarget* target,
- ui::Event* event) {
- if (!dispatching_held_event_ && IsUsingEventProcessorForDispatch(*event)) {
- DispatchDetails details = DispatchHeldEvents();
- if (details.dispatcher_destroyed || details.target_destroyed)
- return details;
-
- Window* target_window = static_cast<Window*>(target);
- if (event->IsScrollEvent()) {
- PreDispatchLocatedEvent(target_window,
- static_cast<ui::ScrollEvent*>(event));
- }
- }
- old_dispatch_target_ = event_dispatch_target_;
- event_dispatch_target_ = static_cast<Window*>(target);
- return DispatchDetails();
-}
-
-ui::EventDispatchDetails RootWindow::PostDispatchEvent(ui::EventTarget* target,
- const ui::Event& event) {
- DispatchDetails details;
- if (target != event_dispatch_target_)
- details.target_destroyed = true;
- event_dispatch_target_ = old_dispatch_target_;
- old_dispatch_target_ = NULL;
-#ifndef NDEBUG
- DCHECK(!event_dispatch_target_ || window()->Contains(event_dispatch_target_));
-#endif
- return details;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, ui::GestureEventHelper implementation:
-
-bool RootWindow::CanDispatchToConsumer(ui::GestureConsumer* consumer) {
- Window* consumer_window = ConsumerToWindow(consumer);;
- return (consumer_window && consumer_window->GetRootWindow() == window());
-}
-
-void RootWindow::DispatchPostponedGestureEvent(ui::GestureEvent* event) {
- DispatchGestureEvent(event);
-}
-
-void RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) {
- OnHostTouchEvent(event);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, ui::LayerAnimationObserver implementation:
-
-void RootWindow::OnLayerAnimationEnded(
- ui::LayerAnimationSequence* animation) {
- UpdateRootWindowSize(host_->GetBounds().size());
-}
-
-void RootWindow::OnLayerAnimationScheduled(
- ui::LayerAnimationSequence* animation) {
-}
-
-void RootWindow::OnLayerAnimationAborted(
- ui::LayerAnimationSequence* animation) {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, RootWindowHostDelegate implementation:
-
-bool RootWindow::OnHostKeyEvent(ui::KeyEvent* event) {
- DispatchDetails details = OnEventFromSource(event);
- if (details.dispatcher_destroyed)
- event->SetHandled();
- return event->handled();
-}
-
-bool RootWindow::OnHostMouseEvent(ui::MouseEvent* event) {
- DispatchDetails details = OnHostMouseEventImpl(event);
- return event->handled() || details.dispatcher_destroyed;
-}
-
-bool RootWindow::OnHostScrollEvent(ui::ScrollEvent* event) {
- DispatchDetails details = OnEventFromSource(event);
- if (details.dispatcher_destroyed)
- event->SetHandled();
- return event->handled();
-}
-
-bool RootWindow::OnHostTouchEvent(ui::TouchEvent* event) {
- if ((event->type() == ui::ET_TOUCH_MOVED)) {
- if (move_hold_count_) {
- Window* null_window = static_cast<Window*>(NULL);
- held_move_event_.reset(
- new ui::TouchEvent(*event, null_window, null_window));
- return true;
- } else {
- // We may have a held event for a period between the time move_hold_count_
- // fell to 0 and the DispatchHeldEvents executes. Since we're going to
- // dispatch the new event directly below, we can reset the old one.
- held_move_event_.reset();
- }
- }
- DispatchDetails details = DispatchHeldEvents();
- if (details.dispatcher_destroyed)
- return false;
- details = DispatchTouchEventImpl(event);
- if (details.dispatcher_destroyed)
- return true;
- return event->handled();
-}
-
-void RootWindow::OnHostCancelMode() {
- ui::CancelModeEvent event;
- Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow();
- DispatchDetails details =
- DispatchEvent(focused_window ? focused_window : window(), &event);
- if (details.dispatcher_destroyed)
- return;
-}
-
-void RootWindow::OnHostActivated() {
- Env::GetInstance()->RootWindowActivated(this);
-}
-
-void RootWindow::OnHostLostWindowCapture() {
- Window* capture_window = client::GetCaptureWindow(window());
- if (capture_window && capture_window->GetRootWindow() == window())
- capture_window->ReleaseCapture();
-}
-
-void RootWindow::OnHostLostMouseGrab() {
- mouse_pressed_handler_ = NULL;
- mouse_moved_handler_ = NULL;
-}
-
-void RootWindow::OnHostPaint(const gfx::Rect& damage_rect) {
- compositor_->ScheduleRedrawRect(damage_rect);
-}
-
-void RootWindow::OnHostMoved(const gfx::Point& origin) {
- TRACE_EVENT1("ui", "RootWindow::OnHostMoved",
- "origin", origin.ToString());
-
- FOR_EACH_OBSERVER(RootWindowObserver, observers_,
- OnRootWindowHostMoved(this, origin));
-}
-
-void RootWindow::OnHostResized(const gfx::Size& size) {
- TRACE_EVENT1("ui", "RootWindow::OnHostResized",
- "size", size.ToString());
-
- DispatchDetails details = DispatchHeldEvents();
- if (details.dispatcher_destroyed)
- return;
- // The compositor should have the same size as the native root window host.
- // Get the latest scale from display because it might have been changed.
- compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), size);
-
- // The layer, and the observers should be notified of the
- // transformed size of the root window.
- UpdateRootWindowSize(host_->GetBounds().size());
- FOR_EACH_OBSERVER(RootWindowObserver, observers_,
- OnRootWindowHostResized(this));
-}
-
-float RootWindow::GetDeviceScaleFactor() {
- return compositor()->device_scale_factor();
-}
-
-RootWindow* RootWindow::AsRootWindow() {
- return this;
-}
-
-const RootWindow* RootWindow::AsRootWindow() const {
- return this;
-}
-
-ui::EventProcessor* RootWindow::GetEventProcessor() {
- return this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindow, private:
-
-ui::EventDispatchDetails RootWindow::OnHostMouseEventImpl(
- ui::MouseEvent* event) {
- if (event->type() == ui::ET_MOUSE_DRAGGED ||
- (event->flags() & ui::EF_IS_SYNTHESIZED)) {
- if (move_hold_count_) {
- Window* null_window = static_cast<Window*>(NULL);
- held_move_event_.reset(
- new ui::MouseEvent(*event, null_window, null_window));
- event->SetHandled();
- return DispatchDetails();
- } else {
- // We may have a held event for a period between the time move_hold_count_
- // fell to 0 and the DispatchHeldEvents executes. Since we're going to
- // dispatch the new event directly below, we can reset the old one.
- held_move_event_.reset();
- }
- }
- DispatchDetails details = DispatchHeldEvents();
- if (details.dispatcher_destroyed)
- return details;
- return DispatchMouseEventImpl(event);
-}
-
-ui::EventDispatchDetails RootWindow::DispatchMouseEventImpl(
- ui::MouseEvent* event) {
- TransformEventForDeviceScaleFactor(event);
- Window* target = mouse_pressed_handler_ ?
- mouse_pressed_handler_ : client::GetCaptureWindow(window());
- if (!target)
- target = window()->GetEventHandlerForPoint(event->location());
- return DispatchMouseEventToTarget(event, target);
-}
-
-ui::EventDispatchDetails RootWindow::DispatchMouseEventRepost(
- ui::MouseEvent* event) {
- if (event->type() != ui::ET_MOUSE_PRESSED)
- return DispatchDetails();
- Window* target = client::GetCaptureWindow(window());
- WindowEventDispatcher* dispatcher = this;
- if (!target) {
- target = window()->GetEventHandlerForPoint(event->location());
- } else {
- dispatcher = target->GetDispatcher();
- CHECK(dispatcher); // Capture window better be in valid root.
- }
- dispatcher->mouse_pressed_handler_ = NULL;
- return dispatcher->DispatchMouseEventToTarget(event, target);
-}
-
-ui::EventDispatchDetails RootWindow::DispatchMouseEventToTarget(
- ui::MouseEvent* event,
- Window* target) {
- client::CursorClient* cursor_client = client::GetCursorClient(window());
- if (cursor_client &&
- !cursor_client->IsMouseEventsEnabled() &&
- (event->flags() & ui::EF_IS_SYNTHESIZED))
- return DispatchDetails();
-
- static const int kMouseButtonFlagMask =
- ui::EF_LEFT_MOUSE_BUTTON |
- ui::EF_MIDDLE_MOUSE_BUTTON |
- ui::EF_RIGHT_MOUSE_BUTTON;
- // WARNING: because of nested message loops |this| may be deleted after
- // dispatching any event. Do not use AutoReset or the like here.
- SetLastMouseLocation(window(), event->location());
- synthesize_mouse_move_ = false;
- switch (event->type()) {
- case ui::ET_MOUSE_EXITED:
- if (!target) {
- DispatchDetails details =
- DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
- if (details.dispatcher_destroyed)
- return details;
- mouse_moved_handler_ = NULL;
- }
- break;
- case ui::ET_MOUSE_MOVED:
- // Send an exit to the current |mouse_moved_handler_| and an enter to
- // |target|. Take care that both us and |target| aren't destroyed during
- // dispatch.
- if (target != mouse_moved_handler_) {
- aura::Window* old_mouse_moved_handler = mouse_moved_handler_;
- WindowTracker destroyed_tracker;
- if (target)
- destroyed_tracker.Add(target);
- DispatchDetails details =
- DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
- if (details.dispatcher_destroyed)
- return details;
- // If the |mouse_moved_handler_| changes out from under us, assume a
- // nested message loop ran and we don't need to do anything.
- if (mouse_moved_handler_ != old_mouse_moved_handler)
- return DispatchDetails();
- if (destroyed_tracker.Contains(target)) {
- destroyed_tracker.Remove(target);
- mouse_moved_handler_ = target;
- DispatchDetails details =
- DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED);
- if (details.dispatcher_destroyed)
- return details;
- } else {
- mouse_moved_handler_ = NULL;
- return DispatchDetails();
- }
- }
- break;
- case ui::ET_MOUSE_PRESSED:
- // Don't set the mouse pressed handler for non client mouse down events.
- // These are only sent by Windows and are not always followed with non
- // client mouse up events which causes subsequent mouse events to be
- // sent to the wrong target.
- if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_)
- mouse_pressed_handler_ = target;
- Env::GetInstance()->set_mouse_button_flags(
- event->flags() & kMouseButtonFlagMask);
- break;
- case ui::ET_MOUSE_RELEASED:
- mouse_pressed_handler_ = NULL;
- Env::GetInstance()->set_mouse_button_flags(event->flags() &
- kMouseButtonFlagMask & ~event->changed_button_flags());
- break;
- default:
- break;
- }
- if (target) {
- event->ConvertLocationToTarget(window(), target);
- if (IsNonClientLocation(target, event->location()))
- event->set_flags(event->flags() | ui::EF_IS_NON_CLIENT);
- return DispatchEvent(target, event);
- }
- return DispatchDetails();
-}
-
-ui::EventDispatchDetails RootWindow::DispatchTouchEventImpl(
- ui::TouchEvent* event) {
- switch (event->type()) {
- case ui::ET_TOUCH_PRESSED:
- touch_ids_down_ |= (1 << event->touch_id());
- Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
- break;
-
- // Handle ET_TOUCH_CANCELLED only if it has a native event.
- case ui::ET_TOUCH_CANCELLED:
- if (!event->HasNativeEvent())
- break;
- // fallthrough
- case ui::ET_TOUCH_RELEASED:
- touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^
- (1 << event->touch_id());
- Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
- break;
-
- default:
- break;
- }
- TransformEventForDeviceScaleFactor(event);
- Window* target = client::GetCaptureWindow(window());
- if (!target) {
- target = ConsumerToWindow(
- ui::GestureRecognizer::Get()->GetTouchLockedTarget(*event));
- if (!target) {
- target = ConsumerToWindow(ui::GestureRecognizer::Get()->
- GetTargetForLocation(event->location()));
- }
- }
-
- // The gesture recognizer processes touch events in the system coordinates. So
- // keep a copy of the touch event here before possibly converting the event to
- // a window's local coordinate system.
- ui::TouchEvent event_for_gr(*event);
-
- ui::EventResult result = ui::ER_UNHANDLED;
- if (!target && !window()->bounds().Contains(event->location())) {
- // If the initial touch is outside the root window, target the root.
- target = window();
- DispatchDetails details = DispatchEvent(target ? target : NULL, event);
- if (details.dispatcher_destroyed)
- return details;
- result = event->result();
- } else {
- // We only come here when the first contact was within the root window.
- if (!target) {
- target = window()->GetEventHandlerForPoint(event->location());
- if (!target)
- return DispatchDetails();
- }
-
- event->ConvertLocationToTarget(window(), target);
- DispatchDetails details = DispatchEvent(target, event);
- if (details.dispatcher_destroyed)
- return details;
- result = event->result();
- }
-
- // Get the list of GestureEvents from GestureRecognizer.
- scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
- gestures.reset(ui::GestureRecognizer::Get()->
- ProcessTouchEventForGesture(event_for_gr, result, target));
-
- return ProcessGestures(gestures.get());
-}
-
-ui::EventDispatchDetails RootWindow::DispatchHeldEvents() {
- if (!held_repostable_event_ && !held_move_event_)
- return DispatchDetails();
-
- CHECK(!dispatching_held_event_);
- dispatching_held_event_ = true;
-
- DispatchDetails dispatch_details;
- if (held_repostable_event_) {
- if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) {
- scoped_ptr<ui::MouseEvent> mouse_event(
- static_cast<ui::MouseEvent*>(held_repostable_event_.release()));
- dispatch_details = DispatchMouseEventRepost(mouse_event.get());
- } else {
- // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987.
- NOTREACHED();
- }
- if (dispatch_details.dispatcher_destroyed)
- return dispatch_details;
- }
-
- if (held_move_event_ && held_move_event_->IsMouseEvent()) {
- // If a mouse move has been synthesized, the target location is suspect,
- // so drop the held event.
- if (!synthesize_mouse_move_) {
- dispatch_details = DispatchMouseEventImpl(
- static_cast<ui::MouseEvent*>(held_move_event_.get()));
- }
- if (!dispatch_details.dispatcher_destroyed)
- held_move_event_.reset();
- } else if (held_move_event_ && held_move_event_->IsTouchEvent()) {
- dispatch_details = DispatchTouchEventImpl(
- static_cast<ui::TouchEvent*>(held_move_event_.get()));
- if (!dispatch_details.dispatcher_destroyed)
- held_move_event_.reset();
- }
-
- if (!dispatch_details.dispatcher_destroyed)
- dispatching_held_event_ = false;
- return dispatch_details;
-}
-
-void RootWindow::PostMouseMoveEventAfterWindowChange() {
- if (synthesize_mouse_move_)
- return;
- synthesize_mouse_move_ = true;
- base::MessageLoop::current()->PostNonNestableTask(
- FROM_HERE,
- base::Bind(&RootWindow::SynthesizeMouseMoveEventAsync,
- held_event_factory_.GetWeakPtr()));
-}
-
-ui::EventDispatchDetails RootWindow::SynthesizeMouseMoveEvent() {
- DispatchDetails details;
- if (!synthesize_mouse_move_)
- return details;
- synthesize_mouse_move_ = false;
- gfx::Point root_mouse_location = GetLastMouseLocationInRoot();
- if (!window()->bounds().Contains(root_mouse_location))
- return details;
- gfx::Point host_mouse_location = root_mouse_location;
- ConvertPointToHost(&host_mouse_location);
-
- ui::MouseEvent event(ui::ET_MOUSE_MOVED,
- host_mouse_location,
- host_mouse_location,
- ui::EF_IS_SYNTHESIZED);
- return OnHostMouseEventImpl(&event);
-}
-
-void RootWindow::SynthesizeMouseMoveEventAsync() {
- DispatchDetails details = SynthesizeMouseMoveEvent();
- if (details.dispatcher_destroyed)
- return;
-}
-
-gfx::Transform RootWindow::GetInverseRootTransform() const {
- float scale = ui::GetDeviceScaleFactor(window()->layer());
- gfx::Transform transform;
- transform.Scale(1.0f / scale, 1.0f / scale);
- return transformer_->GetInverseTransform() * transform;
-}
-
-void RootWindow::PreDispatchLocatedEvent(Window* target,
- ui::LocatedEvent* event) {
- int flags = event->flags();
- if (IsNonClientLocation(target, event->location()))
- flags |= ui::EF_IS_NON_CLIENT;
- event->set_flags(flags);
-
- if (!dispatching_held_event_) {
- SetLastMouseLocation(window(), event->location());
- synthesize_mouse_move_ = false;
- }
-}
-
-} // namespace aura
diff --git a/chromium/ui/aura/root_window.h b/chromium/ui/aura/root_window.h
deleted file mode 100644
index e6b46d0f132..00000000000
--- a/chromium/ui/aura/root_window.h
+++ /dev/null
@@ -1,401 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_ROOT_WINDOW_H_
-#define UI_AURA_ROOT_WINDOW_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/aura/aura_export.h"
-#include "ui/aura/client/capture_delegate.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/aura/window_tree_host_delegate.h"
-#include "ui/base/cursor/cursor.h"
-#include "ui/compositor/compositor.h"
-#include "ui/compositor/layer_animation_observer.h"
-#include "ui/events/event_constants.h"
-#include "ui/events/event_processor.h"
-#include "ui/events/event_targeter.h"
-#include "ui/events/gestures/gesture_recognizer.h"
-#include "ui/events/gestures/gesture_types.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/point.h"
-#include "ui/gfx/transform.h"
-
-namespace gfx {
-class Size;
-class Transform;
-}
-
-namespace ui {
-class GestureEvent;
-class GestureRecognizer;
-class KeyEvent;
-class LayerAnimationSequence;
-class MouseEvent;
-class ScrollEvent;
-class TouchEvent;
-class ViewProp;
-}
-
-namespace aura {
-class RootWindow;
-class RootWindowHost;
-class RootWindowObserver;
-class RootWindowTransformer;
-class TestScreen;
-class WindowTargeter;
-
-// RootWindow is responsible for hosting a set of windows.
-class AURA_EXPORT RootWindow : public ui::EventProcessor,
- public ui::GestureEventHelper,
- public ui::LayerAnimationObserver,
- public aura::client::CaptureDelegate,
- public aura::RootWindowHostDelegate {
- public:
- struct AURA_EXPORT CreateParams {
- // CreateParams with initial_bounds and default host in pixel.
- explicit CreateParams(const gfx::Rect& initial_bounds);
- ~CreateParams() {}
-
- gfx::Rect initial_bounds;
-
- // A host to use in place of the default one that RootWindow will create.
- // NULL by default.
- RootWindowHost* host;
- };
-
- explicit RootWindow(const CreateParams& params);
- virtual ~RootWindow();
-
- // Returns the RootWindowHost for the specified accelerated widget, or NULL
- // if there is none associated.
- static RootWindow* GetForAcceleratedWidget(gfx::AcceleratedWidget widget);
-
- Window* window() {
- return const_cast<Window*>(const_cast<const RootWindow*>(this)->window());
- }
- const Window* window() const { return window_.get(); }
- RootWindowHost* host() {
- return const_cast<RootWindowHost*>(
- const_cast<const RootWindow*>(this)->host());
- }
- const RootWindowHost* host() const { return host_.get(); }
- ui::Compositor* compositor() { return compositor_.get(); }
- gfx::NativeCursor last_cursor() const { return last_cursor_; }
- Window* mouse_pressed_handler() { return mouse_pressed_handler_; }
- Window* mouse_moved_handler() { return mouse_moved_handler_; }
-
- // Initializes the root window.
- void Init();
-
- // Stop listening events in preparation for shutdown.
- void PrepareForShutdown();
-
- // Repost event for re-processing. Used when exiting context menus.
- // We only support the ET_MOUSE_PRESSED and ET_GESTURE_TAP_DOWN event
- // types (although the latter is currently a no-op).
- void RepostEvent(const ui::LocatedEvent& event);
-
- RootWindowHostDelegate* AsRootWindowHostDelegate();
-
- // Gets/sets the size of the host window.
- void SetHostSize(const gfx::Size& size_in_pixel);
-
- // Sets the bounds of the host window.
- void SetHostBounds(const gfx::Rect& size_in_pizel);
-
- // Sets the currently-displayed cursor. If the cursor was previously hidden
- // via ShowCursor(false), it will remain hidden until ShowCursor(true) is
- // called, at which point the cursor that was last set via SetCursor() will be
- // used.
- void SetCursor(gfx::NativeCursor cursor);
-
- // Invoked when the cursor's visibility has changed.
- void OnCursorVisibilityChanged(bool visible);
-
- // Invoked when the mouse events get enabled or disabled.
- void OnMouseEventsEnableStateChanged(bool enabled);
-
- // Moves the cursor to the specified location relative to the root window.
- void MoveCursorTo(const gfx::Point& location);
-
- // Moves the cursor to the |host_location| given in host coordinates.
- void MoveCursorToHostLocation(const gfx::Point& host_location);
-
- // Draw the damage_rect.
- void ScheduleRedrawRect(const gfx::Rect& damage_rect);
-
- // Returns a target window for the given gesture event.
- Window* GetGestureTarget(ui::GestureEvent* event);
-
- // Handles a gesture event. Returns true if handled. Unlike the other
- // event-dispatching function (e.g. for touch/mouse/keyboard events), gesture
- // events are dispatched from GestureRecognizer instead of RootWindowHost.
- void DispatchGestureEvent(ui::GestureEvent* event);
-
- // Invoked when |window| is being destroyed.
- void OnWindowDestroying(Window* window);
-
- // Invoked when |window|'s bounds have changed. |contained_mouse| indicates if
- // the bounds before change contained the |last_moust_location()|.
- void OnWindowBoundsChanged(Window* window, bool contained_mouse);
-
- // Dispatches OnMouseExited to the |window| which is hiding if nessessary.
- void DispatchMouseExitToHidingWindow(Window* window);
-
- // Dispatches a ui::ET_MOUSE_EXITED event at |point|.
- void DispatchMouseExitAtPoint(const gfx::Point& point);
-
- // Invoked when |window|'s visibility has changed.
- void OnWindowVisibilityChanged(Window* window, bool is_visible);
-
- // Invoked when |window|'s tranfrom has changed. |contained_mouse|
- // indicates if the bounds before change contained the
- // |last_moust_location()|.
- void OnWindowTransformed(Window* window, bool contained_mouse);
-
- // Invoked when the keyboard mapping (in X11 terms: the mapping between
- // keycodes and keysyms) has changed.
- void OnKeyboardMappingChanged();
-
- // The system windowing system has sent a request that we close our window.
- void OnRootWindowHostCloseRequested();
-
- // Add/remove observer. There is no need to remove the observer if
- // the root window is being deleted. In particular, you SHOULD NOT remove
- // in |WindowObserver::OnWindowDestroying| of the observer observing
- // the root window because it is too late to remove it.
- void AddRootWindowObserver(RootWindowObserver* observer);
- void RemoveRootWindowObserver(RootWindowObserver* observer);
-
- // Converts |point| from the root window's coordinate system to the
- // host window's.
- void ConvertPointToHost(gfx::Point* point) const;
-
- // Converts |point| from the host window's coordinate system to the
- // root window's.
- void ConvertPointFromHost(gfx::Point* point) const;
-
- // Gesture Recognition -------------------------------------------------------
-
- // When a touch event is dispatched to a Window, it may want to process the
- // touch event asynchronously. In such cases, the window should consume the
- // event during the event dispatch. Once the event is properly processed, the
- // window should let the RootWindow know about the result of the event
- // processing, so that gesture events can be properly created and dispatched.
- void ProcessedTouchEvent(ui::TouchEvent* event,
- Window* window,
- ui::EventResult result);
-
- // These methods are used to defer the processing of mouse/touch events
- // related to resize. A client (typically a RenderWidgetHostViewAura) can call
- // HoldPointerMoves when an resize is initiated and then ReleasePointerMoves
- // once the resize is completed.
- //
- // More than one hold can be invoked and each hold must be cancelled by a
- // release before we resume normal operation.
- void HoldPointerMoves();
- void ReleasePointerMoves();
-
- // Gets the last location seen in a mouse event in this root window's
- // coordinates. This may return a point outside the root window's bounds.
- gfx::Point GetLastMouseLocationInRoot() const;
-
- void SetRootWindowTransformer(scoped_ptr<RootWindowTransformer> transformer);
- gfx::Transform GetRootTransform() const;
-
- void SetTransform(const gfx::Transform& transform);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(RootWindowTest, KeepTranslatedEventInRoot);
-
- friend class Window;
- friend class TestScreen;
-
- // The parameter for OnWindowHidden() to specify why window is hidden.
- enum WindowHiddenReason {
- WINDOW_DESTROYED, // Window is destroyed.
- WINDOW_HIDDEN, // Window is hidden.
- WINDOW_MOVING, // Window is temporarily marked as hidden due to move
- // across root windows.
- };
-
- // Updates the event with the appropriate transform for the device scale
- // factor. The RootWindowHostDelegate dispatches events in the physical pixel
- // coordinate. But the event processing from RootWindow onwards happen in
- // device-independent pixel coordinate. So it is necessary to update the event
- // received from the host.
- void TransformEventForDeviceScaleFactor(ui::LocatedEvent* event);
-
- // Moves the cursor to the specified location. This method is internally used
- // by MoveCursorTo() and MoveCursorToHostLocation().
- void MoveCursorToInternal(const gfx::Point& root_location,
- const gfx::Point& host_location);
-
- // Dispatches the specified event type (intended for enter/exit) to the
- // |mouse_moved_handler_|.
- ui::EventDispatchDetails DispatchMouseEnterOrExit(
- const ui::MouseEvent& event,
- ui::EventType type) WARN_UNUSED_RESULT;
- ui::EventDispatchDetails ProcessGestures(
- ui::GestureRecognizer::Gestures* gestures) WARN_UNUSED_RESULT;
-
- // Called when a Window is attached or detached from the RootWindow.
- void OnWindowAddedToRootWindow(Window* window);
- void OnWindowRemovedFromRootWindow(Window* window, Window* new_root);
-
- // Called when a window becomes invisible, either by being removed
- // from root window hierarchy, via SetVisible(false) or being destroyed.
- // |reason| specifies what triggered the hiding.
- void OnWindowHidden(Window* invisible, WindowHiddenReason reason);
-
- // Cleans up the state of gestures for all windows in |window| (including
- // |window| itself). This includes cancelling active touch points.
- void CleanupGestureState(Window* window);
-
- // Updates the root window's size using |host_size|, current
- // transform and insets.
- void UpdateRootWindowSize(const gfx::Size& host_size);
-
- // Overridden from aura::client::CaptureDelegate:
- virtual void UpdateCapture(Window* old_capture, Window* new_capture) OVERRIDE;
- virtual void OnOtherRootGotCapture() OVERRIDE;
- virtual void SetNativeCapture() OVERRIDE;
- virtual void ReleaseNativeCapture() OVERRIDE;
-
- // Overridden from ui::EventProcessor:
- virtual ui::EventTarget* GetRootTarget() OVERRIDE;
- virtual void PrepareEventForDispatch(ui::Event* event) OVERRIDE;
-
- // Overridden from ui::EventDispatcherDelegate.
- virtual bool CanDispatchToTarget(ui::EventTarget* target) OVERRIDE;
- virtual ui::EventDispatchDetails PreDispatchEvent(ui::EventTarget* target,
- ui::Event* event) OVERRIDE;
- virtual ui::EventDispatchDetails PostDispatchEvent(
- ui::EventTarget* target, const ui::Event& event) OVERRIDE;
-
- // Overridden from ui::GestureEventHelper.
- virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE;
- virtual void DispatchPostponedGestureEvent(ui::GestureEvent* event) OVERRIDE;
- virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
-
- // Overridden from ui::LayerAnimationObserver:
- virtual void OnLayerAnimationEnded(
- ui::LayerAnimationSequence* animation) OVERRIDE;
- virtual void OnLayerAnimationScheduled(
- ui::LayerAnimationSequence* animation) OVERRIDE;
- virtual void OnLayerAnimationAborted(
- ui::LayerAnimationSequence* animation) OVERRIDE;
-
- // Overridden from aura::RootWindowHostDelegate:
- virtual bool OnHostKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual bool OnHostMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual bool OnHostScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual bool OnHostTouchEvent(ui::TouchEvent* event) OVERRIDE;
- virtual void OnHostCancelMode() OVERRIDE;
- virtual void OnHostActivated() OVERRIDE;
- virtual void OnHostLostWindowCapture() OVERRIDE;
- virtual void OnHostLostMouseGrab() OVERRIDE;
- virtual void OnHostPaint(const gfx::Rect& damage_rect) OVERRIDE;
- virtual void OnHostMoved(const gfx::Point& origin) OVERRIDE;
- virtual void OnHostResized(const gfx::Size& size) OVERRIDE;
- virtual float GetDeviceScaleFactor() OVERRIDE;
- virtual RootWindow* AsRootWindow() OVERRIDE;
- virtual const RootWindow* AsRootWindow() const OVERRIDE;
- virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
-
- ui::EventDispatchDetails OnHostMouseEventImpl(ui::MouseEvent* event)
- WARN_UNUSED_RESULT;
-
- // We hold and aggregate mouse drags and touch moves as a way of throttling
- // resizes when HoldMouseMoves() is called. The following methods are used to
- // dispatch held and newly incoming mouse and touch events, typically when an
- // event other than one of these needs dispatching or a matching
- // ReleaseMouseMoves()/ReleaseTouchMoves() is called. NOTE: because these
- // methods dispatch events from RootWindowHost the coordinates are in terms of
- // the root.
- ui::EventDispatchDetails DispatchMouseEventImpl(ui::MouseEvent* event)
- WARN_UNUSED_RESULT;
- ui::EventDispatchDetails DispatchMouseEventRepost(ui::MouseEvent* event)
- WARN_UNUSED_RESULT;
- ui::EventDispatchDetails DispatchMouseEventToTarget(ui::MouseEvent* event,
- Window* target)
- WARN_UNUSED_RESULT;
- ui::EventDispatchDetails DispatchTouchEventImpl(ui::TouchEvent* event)
- WARN_UNUSED_RESULT;
- ui::EventDispatchDetails DispatchHeldEvents() WARN_UNUSED_RESULT;
- // Creates and dispatches synthesized mouse move event using the
- // current mouse location.
- ui::EventDispatchDetails SynthesizeMouseMoveEvent() WARN_UNUSED_RESULT;
-
- void SynthesizeMouseMoveEventAsync();
-
- // Posts a task to send synthesized mouse move event if there
- // is no a pending task.
- void PostMouseMoveEventAfterWindowChange();
-
- gfx::Transform GetInverseRootTransform() const;
-
- void PreDispatchLocatedEvent(Window* target, ui::LocatedEvent* event);
-
- // TODO(beng): evaluate the ideal ownership model.
- scoped_ptr<Window> window_;
-
- scoped_ptr<ui::Compositor> compositor_;
-
- scoped_ptr<RootWindowHost> host_;
-
- // Touch ids that are currently down.
- uint32 touch_ids_down_;
-
- // Last cursor set. Used for testing.
- gfx::NativeCursor last_cursor_;
-
- ObserverList<RootWindowObserver> observers_;
-
- Window* mouse_pressed_handler_;
- Window* mouse_moved_handler_;
- Window* event_dispatch_target_;
- Window* old_dispatch_target_;
-
- bool synthesize_mouse_move_;
- bool waiting_on_compositing_end_;
- bool draw_on_compositing_end_;
-
- bool defer_draw_scheduling_;
-
- // How many move holds are outstanding. We try to defer dispatching
- // touch/mouse moves while the count is > 0.
- int move_hold_count_;
- scoped_ptr<ui::LocatedEvent> held_move_event_;
-
- // Allowing for reposting of events. Used when exiting context menus.
- scoped_ptr<ui::LocatedEvent> held_repostable_event_;
-
- // Set when dispatching a held event.
- bool dispatching_held_event_;
-
- scoped_ptr<ui::ViewProp> prop_;
-
- scoped_ptr<RootWindowTransformer> transformer_;
-
- // Used to schedule reposting an event.
- base::WeakPtrFactory<RootWindow> repost_event_factory_;
-
- // Used to schedule DispatchHeldEvents() when |move_hold_count_| goes to 0.
- base::WeakPtrFactory<RootWindow> held_event_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(RootWindow);
-};
-
-} // namespace aura
-
-#endif // UI_AURA_ROOT_WINDOW_H_
diff --git a/chromium/ui/aura/root_window_host_ozone.cc b/chromium/ui/aura/root_window_host_ozone.cc
deleted file mode 100644
index 937b70f65be..00000000000
--- a/chromium/ui/aura/root_window_host_ozone.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/root_window_host_ozone.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/events/ozone/event_factory_ozone.h"
-#include "ui/gfx/ozone/surface_factory_ozone.h"
-#include "ui/ozone/ozone_platform.h"
-
-namespace aura {
-
-RootWindowHostOzone::RootWindowHostOzone(const gfx::Rect& bounds)
- : widget_(0),
- bounds_(bounds) {
- ui::OzonePlatform::Initialize();
-
- // EventFactoryOzone creates converters that obtain input events from the
- // underlying input system and dispatch them as |ui::Event| instances into
- // Aura.
- ui::EventFactoryOzone::GetInstance()->StartProcessingEvents();
-
- gfx::SurfaceFactoryOzone* surface_factory =
- gfx::SurfaceFactoryOzone::GetInstance();
- widget_ = surface_factory->GetAcceleratedWidget();
-
- surface_factory->AttemptToResizeAcceleratedWidget(widget_, bounds_);
-
- base::MessagePumpOzone::Current()->AddDispatcherForRootWindow(this);
-}
-
-RootWindowHostOzone::~RootWindowHostOzone() {
- base::MessagePumpOzone::Current()->RemoveDispatcherForRootWindow(0);
-}
-
-bool RootWindowHostOzone::Dispatch(const base::NativeEvent& ne) {
- ui::Event* event = static_cast<ui::Event*>(ne);
- if (event->IsTouchEvent()) {
- ui::TouchEvent* touchev = static_cast<ui::TouchEvent*>(ne);
- delegate_->OnHostTouchEvent(touchev);
- } else if (event->IsKeyEvent()) {
- ui::KeyEvent* keyev = static_cast<ui::KeyEvent*>(ne);
- delegate_->OnHostKeyEvent(keyev);
- } else if (event->IsMouseEvent()) {
- ui::MouseEvent* mouseev = static_cast<ui::MouseEvent*>(ne);
- delegate_->OnHostMouseEvent(mouseev);
- }
- return true;
-}
-
-RootWindow* RootWindowHostOzone::GetRootWindow() {
- return delegate_->AsRootWindow();
-}
-
-gfx::AcceleratedWidget RootWindowHostOzone::GetAcceleratedWidget() {
- return widget_;
-}
-
-void RootWindowHostOzone::Show() { NOTIMPLEMENTED(); }
-
-void RootWindowHostOzone::Hide() { NOTIMPLEMENTED(); }
-
-void RootWindowHostOzone::ToggleFullScreen() { NOTIMPLEMENTED(); }
-
-gfx::Rect RootWindowHostOzone::GetBounds() const { return bounds_; }
-
-void RootWindowHostOzone::SetBounds(const gfx::Rect& bounds) {
- NOTIMPLEMENTED();
-}
-
-gfx::Insets RootWindowHostOzone::GetInsets() const { return gfx::Insets(); }
-
-void RootWindowHostOzone::SetInsets(const gfx::Insets& insets) {
- NOTIMPLEMENTED();
-}
-
-gfx::Point RootWindowHostOzone::GetLocationOnNativeScreen() const {
- return bounds_.origin();
-}
-
-void RootWindowHostOzone::SetCapture() { NOTIMPLEMENTED(); }
-
-void RootWindowHostOzone::ReleaseCapture() { NOTIMPLEMENTED(); }
-
-void RootWindowHostOzone::SetCursor(gfx::NativeCursor cursor) {
- NOTIMPLEMENTED();
-}
-
-bool RootWindowHostOzone::QueryMouseLocation(gfx::Point* location_return) {
- NOTIMPLEMENTED();
- return false;
-}
-
-bool RootWindowHostOzone::ConfineCursorToRootWindow() {
- NOTIMPLEMENTED();
- return false;
-}
-
-void RootWindowHostOzone::UnConfineCursor() { NOTIMPLEMENTED(); }
-
-void RootWindowHostOzone::OnCursorVisibilityChanged(bool show) {
- NOTIMPLEMENTED();
-}
-
-void RootWindowHostOzone::MoveCursorTo(const gfx::Point& location) {
- NOTIMPLEMENTED();
-}
-
-void RootWindowHostOzone::PostNativeEvent(
- const base::NativeEvent& native_event) {
- NOTIMPLEMENTED();
-}
-
-void RootWindowHostOzone::OnDeviceScaleFactorChanged(
- float device_scale_factor) {
- NOTIMPLEMENTED();
-}
-
-void RootWindowHostOzone::PrepareForShutdown() { NOTIMPLEMENTED(); }
-
-// static
-RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
- return new RootWindowHostOzone(bounds);
-}
-
-// static
-gfx::Size RootWindowHost::GetNativeScreenSize() {
- NOTIMPLEMENTED();
- return gfx::Size();
-}
-
-} // namespace aura
diff --git a/chromium/ui/aura/root_window_host_ozone.h b/chromium/ui/aura/root_window_host_ozone.h
deleted file mode 100644
index 41f6a8e181f..00000000000
--- a/chromium/ui/aura/root_window_host_ozone.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_ROOT_WINDOW_HOST_OZONE_H_
-#define UI_AURA_ROOT_WINDOW_HOST_OZONE_H_
-
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/gfx/insets.h"
-#include "ui/gfx/rect.h"
-
-namespace aura {
-
-class RootWindowHostOzone : public RootWindowHost,
- public base::MessageLoop::Dispatcher {
- public:
- explicit RootWindowHostOzone(const gfx::Rect& bounds);
- virtual ~RootWindowHostOzone();
-
- private:
- // Overridden from Dispatcher overrides:
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
-
- // RootWindowHost Overrides.
- virtual RootWindow* GetRootWindow() OVERRIDE;
- virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual void ToggleFullScreen() OVERRIDE;
- virtual gfx::Rect GetBounds() const OVERRIDE;
- virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
- virtual gfx::Insets GetInsets() const OVERRIDE;
- virtual void SetInsets(const gfx::Insets& bounds) OVERRIDE;
- virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
- virtual void SetCapture() OVERRIDE;
- virtual void ReleaseCapture() OVERRIDE;
- virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE;
- virtual bool QueryMouseLocation(gfx::Point* location_return) OVERRIDE;
- virtual bool ConfineCursorToRootWindow() OVERRIDE;
- virtual void UnConfineCursor() OVERRIDE;
- virtual void OnCursorVisibilityChanged(bool show) OVERRIDE;
- virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE;
- virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void PrepareForShutdown() OVERRIDE;
-
- gfx::AcceleratedWidget widget_;
- gfx::Rect bounds_;
-
- DISALLOW_COPY_AND_ASSIGN(RootWindowHostOzone);
-};
-
-} // namespace aura
-
-#endif // UI_AURA_ROOT_WINDOW_HOST_OZONE_H_
diff --git a/chromium/ui/aura/root_window_host_win.cc b/chromium/ui/aura/root_window_host_win.cc
deleted file mode 100644
index 931c11e5179..00000000000
--- a/chromium/ui/aura/root_window_host_win.cc
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/root_window_host_win.h"
-
-#include <windows.h>
-
-#include <algorithm>
-
-#include "base/message_loop/message_loop.h"
-#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/base/cursor/cursor_loader_win.h"
-#include "ui/events/event.h"
-#include "ui/base/view_prop.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/insets.h"
-#include "ui/gfx/screen.h"
-
-using std::max;
-using std::min;
-
-namespace aura {
-namespace {
-
-bool use_popup_as_root_window_for_test = false;
-
-} // namespace
-
-// static
-RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
- return new RootWindowHostWin(bounds);
-}
-
-// static
-gfx::Size RootWindowHost::GetNativeScreenSize() {
- return gfx::Size(GetSystemMetrics(SM_CXSCREEN),
- GetSystemMetrics(SM_CYSCREEN));
-}
-
-RootWindowHostWin::RootWindowHostWin(const gfx::Rect& bounds)
- : fullscreen_(false),
- has_capture_(false),
- saved_window_style_(0),
- saved_window_ex_style_(0) {
- if (use_popup_as_root_window_for_test)
- set_window_style(WS_POPUP);
- Init(NULL, bounds);
- SetWindowText(hwnd(), L"aura::RootWindow!");
-}
-
-RootWindowHostWin::~RootWindowHostWin() {
- DestroyWindow(hwnd());
-}
-
-RootWindow* RootWindowHostWin::GetRootWindow() {
- return delegate_->AsRootWindow();
-}
-
-gfx::AcceleratedWidget RootWindowHostWin::GetAcceleratedWidget() {
- return hwnd();
-}
-
-void RootWindowHostWin::Show() {
- ShowWindow(hwnd(), SW_SHOWNORMAL);
-}
-
-void RootWindowHostWin::Hide() {
- NOTIMPLEMENTED();
-}
-
-void RootWindowHostWin::ToggleFullScreen() {
- gfx::Rect target_rect;
- if (!fullscreen_) {
- fullscreen_ = true;
- saved_window_style_ = GetWindowLong(hwnd(), GWL_STYLE);
- saved_window_ex_style_ = GetWindowLong(hwnd(), GWL_EXSTYLE);
- GetWindowRect(hwnd(), &saved_window_rect_);
- SetWindowLong(hwnd(), GWL_STYLE,
- saved_window_style_ & ~(WS_CAPTION | WS_THICKFRAME));
- SetWindowLong(hwnd(), GWL_EXSTYLE,
- saved_window_ex_style_ & ~(WS_EX_DLGMODALFRAME |
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
-
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST), &mi);
- target_rect = gfx::Rect(mi.rcMonitor);
- } else {
- fullscreen_ = false;
- SetWindowLong(hwnd(), GWL_STYLE, saved_window_style_);
- SetWindowLong(hwnd(), GWL_EXSTYLE, saved_window_ex_style_);
- target_rect = gfx::Rect(saved_window_rect_);
- }
- SetWindowPos(hwnd(),
- NULL,
- target_rect.x(),
- target_rect.y(),
- target_rect.width(),
- target_rect.height(),
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
-}
-
-gfx::Rect RootWindowHostWin::GetBounds() const {
- RECT r;
- GetClientRect(hwnd(), &r);
- return gfx::Rect(r);
-}
-
-void RootWindowHostWin::SetBounds(const gfx::Rect& bounds) {
- if (fullscreen_) {
- saved_window_rect_.right = saved_window_rect_.left + bounds.width();
- saved_window_rect_.bottom = saved_window_rect_.top + bounds.height();
- return;
- }
- RECT window_rect;
- window_rect.left = bounds.x();
- window_rect.top = bounds.y();
- window_rect.right = bounds.right() ;
- window_rect.bottom = bounds.bottom();
- AdjustWindowRectEx(&window_rect,
- GetWindowLong(hwnd(), GWL_STYLE),
- FALSE,
- GetWindowLong(hwnd(), GWL_EXSTYLE));
- SetWindowPos(
- hwnd(),
- NULL,
- window_rect.left,
- window_rect.top,
- window_rect.right - window_rect.left,
- window_rect.bottom - window_rect.top,
- SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOREPOSITION);
-
- // Explicity call OnHostResized when the scale has changed because
- // the window size may not have changed.
- float current_scale = delegate_->GetDeviceScaleFactor();
- float new_scale = gfx::Screen::GetScreenFor(
- delegate_->AsRootWindow()->window())->GetDisplayNearestWindow(
- delegate_->AsRootWindow()->window()).device_scale_factor();
- if (current_scale != new_scale)
- delegate_->OnHostResized(bounds.size());
-}
-
-gfx::Insets RootWindowHostWin::GetInsets() const {
- return gfx::Insets();
-}
-
-void RootWindowHostWin::SetInsets(const gfx::Insets& insets) {
-}
-
-gfx::Point RootWindowHostWin::GetLocationOnNativeScreen() const {
- RECT r;
- GetClientRect(hwnd(), &r);
- return gfx::Point(r.left, r.top);
-}
-
-
-void RootWindowHostWin::SetCursor(gfx::NativeCursor native_cursor) {
- // Custom web cursors are handled directly.
- if (native_cursor == ui::kCursorCustom)
- return;
-
- ui::CursorLoaderWin cursor_loader;
- cursor_loader.SetPlatformCursor(&native_cursor);
- ::SetCursor(native_cursor.platform());
-}
-
-void RootWindowHostWin::SetCapture() {
- if (!has_capture_) {
- has_capture_ = true;
- ::SetCapture(hwnd());
- }
-}
-
-void RootWindowHostWin::ReleaseCapture() {
- if (has_capture_) {
- has_capture_ = false;
- ::ReleaseCapture();
- }
-}
-
-bool RootWindowHostWin::QueryMouseLocation(gfx::Point* location_return) {
- client::CursorClient* cursor_client =
- client::GetCursorClient(GetRootWindow()->window());
- if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
- *location_return = gfx::Point(0, 0);
- return false;
- }
-
- POINT pt;
- GetCursorPos(&pt);
- ScreenToClient(hwnd(), &pt);
- const gfx::Size size = GetBounds().size();
- *location_return =
- gfx::Point(max(0, min(size.width(), static_cast<int>(pt.x))),
- max(0, min(size.height(), static_cast<int>(pt.y))));
- return (pt.x >= 0 && static_cast<int>(pt.x) < size.width() &&
- pt.y >= 0 && static_cast<int>(pt.y) < size.height());
-}
-
-bool RootWindowHostWin::ConfineCursorToRootWindow() {
- RECT window_rect;
- GetWindowRect(hwnd(), &window_rect);
- return ClipCursor(&window_rect) != 0;
-}
-
-void RootWindowHostWin::UnConfineCursor() {
- ClipCursor(NULL);
-}
-
-void RootWindowHostWin::OnCursorVisibilityChanged(bool show) {
- NOTIMPLEMENTED();
-}
-
-void RootWindowHostWin::MoveCursorTo(const gfx::Point& location) {
- // Deliberately not implemented.
-}
-
-void RootWindowHostWin::PostNativeEvent(const base::NativeEvent& native_event) {
- ::PostMessage(
- hwnd(), native_event.message, native_event.wParam, native_event.lParam);
-}
-
-void RootWindowHostWin::OnDeviceScaleFactorChanged(
- float device_scale_factor) {
- NOTIMPLEMENTED();
-}
-
-void RootWindowHostWin::PrepareForShutdown() {
- NOTIMPLEMENTED();
-}
-
-void RootWindowHostWin::OnClose() {
- // TODO: this obviously shouldn't be here.
- base::MessageLoopForUI::current()->Quit();
-}
-
-LRESULT RootWindowHostWin::OnKeyEvent(UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- MSG msg = { hwnd(), message, w_param, l_param };
- ui::KeyEvent keyev(msg, message == WM_CHAR);
- SetMsgHandled(delegate_->OnHostKeyEvent(&keyev));
- return 0;
-}
-
-LRESULT RootWindowHostWin::OnMouseRange(UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- MSG msg = { hwnd(), message, w_param, l_param, 0,
- { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) } };
- ui::MouseEvent event(msg);
- bool handled = false;
- if (!(event.flags() & ui::EF_IS_NON_CLIENT))
- handled = delegate_->OnHostMouseEvent(&event);
- SetMsgHandled(handled);
- return 0;
-}
-
-LRESULT RootWindowHostWin::OnCaptureChanged(UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- if (has_capture_) {
- has_capture_ = false;
- delegate_->OnHostLostWindowCapture();
- }
- return 0;
-}
-
-LRESULT RootWindowHostWin::OnNCActivate(UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- if (!!w_param)
- delegate_->OnHostActivated();
- return DefWindowProc(hwnd(), message, w_param, l_param);
-}
-
-void RootWindowHostWin::OnMove(const CPoint& point) {
- if (delegate_)
- delegate_->OnHostMoved(gfx::Point(point.x, point.y));
-}
-
-void RootWindowHostWin::OnPaint(HDC dc) {
- gfx::Rect damage_rect;
- RECT update_rect = {0};
- if (GetUpdateRect(hwnd(), &update_rect, FALSE))
- damage_rect = gfx::Rect(update_rect);
- delegate_->OnHostPaint(damage_rect);
- ValidateRect(hwnd(), NULL);
-}
-
-void RootWindowHostWin::OnSize(UINT param, const CSize& size) {
- // Minimizing resizes the window to 0x0 which causes our layout to go all
- // screwy, so we just ignore it.
- if (delegate_ && param != SIZE_MINIMIZED)
- delegate_->OnHostResized(gfx::Size(size.cx, size.cy));
-}
-
-namespace test {
-
-// static
-void SetUsePopupAsRootWindowForTest(bool use) {
- use_popup_as_root_window_for_test = use;
-}
-
-} // namespace test
-
-} // namespace aura
diff --git a/chromium/ui/aura/root_window_host_win.h b/chromium/ui/aura/root_window_host_win.h
deleted file mode 100644
index 3d99821400a..00000000000
--- a/chromium/ui/aura/root_window_host_win.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_ROOT_WINDOW_HOST_WIN_H_
-#define UI_AURA_ROOT_WINDOW_HOST_WIN_H_
-
-#include "base/compiler_specific.h"
-#include "ui/aura/aura_export.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/gfx/win/window_impl.h"
-
-namespace aura {
-
-class RootWindowHostWin : public RootWindowHost, public gfx::WindowImpl {
- public:
- RootWindowHostWin(const gfx::Rect& bounds);
- virtual ~RootWindowHostWin();
- // RootWindowHost:
- virtual RootWindow* GetRootWindow() OVERRIDE;
- virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual void ToggleFullScreen() OVERRIDE;
- virtual gfx::Rect GetBounds() const OVERRIDE;
- virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
- virtual gfx::Insets GetInsets() const OVERRIDE;
- virtual void SetInsets(const gfx::Insets& insets) OVERRIDE;
- virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
- virtual void SetCapture() OVERRIDE;
- virtual void ReleaseCapture() OVERRIDE;
- virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
- virtual bool QueryMouseLocation(gfx::Point* location_return) OVERRIDE;
- virtual bool ConfineCursorToRootWindow() OVERRIDE;
- virtual void UnConfineCursor() OVERRIDE;
- virtual void OnCursorVisibilityChanged(bool show) OVERRIDE;
- virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE;
- virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void PrepareForShutdown() OVERRIDE;
-
- private:
- BEGIN_MSG_MAP_EX(RootWindowHostWin)
- // Range handlers must go first!
- MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
- MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK, OnMouseRange)
-
- // Mouse capture events.
- MESSAGE_HANDLER_EX(WM_CAPTURECHANGED, OnCaptureChanged)
-
- // Key events.
- MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_CHAR, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_SYSCHAR, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_IME_CHAR, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_NCACTIVATE, OnNCActivate)
-
- MSG_WM_CLOSE(OnClose)
- MSG_WM_MOVE(OnMove)
- MSG_WM_PAINT(OnPaint)
- MSG_WM_SIZE(OnSize)
- END_MSG_MAP()
-
- void OnClose();
- LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param);
- LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param);
- LRESULT OnCaptureChanged(UINT message, WPARAM w_param, LPARAM l_param);
- LRESULT OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param);
- void OnMove(const CPoint& point);
- void OnPaint(HDC dc);
- void OnSize(UINT param, const CSize& size);
-
- bool fullscreen_;
- bool has_capture_;
- RECT saved_window_rect_;
- DWORD saved_window_style_;
- DWORD saved_window_ex_style_;
-
- DISALLOW_COPY_AND_ASSIGN(RootWindowHostWin);
-};
-
-namespace test {
-
-// Set true to let RootWindowHostWin use a popup window
-// with no frame/title so that the window size and test's
-// expectations matches.
-AURA_EXPORT void SetUsePopupAsRootWindowForTest(bool use);
-
-} // namespace
-
-} // namespace aura
-
-#endif // UI_AURA_ROOT_WINDOW_HOST_WIN_H_
diff --git a/chromium/ui/aura/root_window_host_x11.h b/chromium/ui/aura/root_window_host_x11.h
deleted file mode 100644
index d4b35186a8b..00000000000
--- a/chromium/ui/aura/root_window_host_x11.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_ROOT_WINDOW_HOST_X11_H_
-#define UI_AURA_ROOT_WINDOW_HOST_X11_H_
-
-#include <X11/Xlib.h>
-
-#include <vector>
-
-// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
-#undef RootWindow
-
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/aura/aura_export.h"
-#include "ui/aura/env_observer.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/x/x11_util.h"
-#include "ui/events/event_source.h"
-#include "ui/gfx/insets.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-
-namespace ui {
-class MouseEvent;
-}
-
-namespace aura {
-
-namespace internal {
-class TouchEventCalibrate;
-}
-
-class AURA_EXPORT RootWindowHostX11 : public RootWindowHost,
- public base::MessageLoop::Dispatcher,
- public ui::EventSource,
- public EnvObserver {
- public:
- explicit RootWindowHostX11(const gfx::Rect& bounds);
- virtual ~RootWindowHostX11();
-
- // Overridden from Dispatcher overrides:
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
-
- // RootWindowHost Overrides.
- virtual RootWindow* GetRootWindow() OVERRIDE;
- virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual void ToggleFullScreen() OVERRIDE;
- virtual gfx::Rect GetBounds() const OVERRIDE;
- virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
- virtual gfx::Insets GetInsets() const OVERRIDE;
- virtual void SetInsets(const gfx::Insets& insets) OVERRIDE;
- virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
- virtual void SetCapture() OVERRIDE;
- virtual void ReleaseCapture() OVERRIDE;
- virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE;
- virtual bool QueryMouseLocation(gfx::Point* location_return) OVERRIDE;
- virtual bool ConfineCursorToRootWindow() OVERRIDE;
- virtual void UnConfineCursor() OVERRIDE;
- virtual void OnCursorVisibilityChanged(bool show) OVERRIDE;
- virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE;
- virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void PrepareForShutdown() OVERRIDE;
-
- // EnvObserver overrides.
- virtual void OnWindowInitialized(Window* window) OVERRIDE;
- virtual void OnRootWindowInitialized(RootWindow* root_window) OVERRIDE;
-
- // ui::EventSource overrides.
- virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
-
- private:
- class MouseMoveFilter;
-
- bool DispatchEventForRootWindow(const base::NativeEvent& event);
-
- // Dispatches XI2 events. Note that some events targetted for the X root
- // window are dispatched to the aura root window (e.g. touch events after
- // calibration).
- void DispatchXI2Event(const base::NativeEvent& event);
-
- // Returns true if there's an X window manager present... in most cases. Some
- // window managers (notably, ion3) don't implement enough of ICCCM for us to
- // detect that they're there.
- bool IsWindowManagerPresent();
-
- // Sets the cursor on |xwindow_| to |cursor|. Does not check or update
- // |current_cursor_|.
- void SetCursorInternal(gfx::NativeCursor cursor);
-
- // Translates the native mouse location into screen coordinates and and
- // dispatches the event to RootWindowHostDelegate.
- void TranslateAndDispatchMouseEvent(ui::MouseEvent* event);
-
- // Update is_internal_display_ based on delegate_ state
- void UpdateIsInternalDisplay();
-
- // Set the CrOS touchpad "tap paused" property. It is used to temporarily
- // turn off the Tap-to-click feature when the mouse pointer is invisible.
- void SetCrOSTapPaused(bool state);
-
- // The display and the native X window hosting the root window.
- XDisplay* xdisplay_;
- ::Window xwindow_;
-
- // The native root window.
- ::Window x_root_window_;
-
- // Current Aura cursor.
- gfx::NativeCursor current_cursor_;
-
- // Is the window mapped to the screen?
- bool window_mapped_;
-
- // The bounds of |xwindow_|.
- gfx::Rect bounds_;
-
- // The insets that specifies the effective area within the |window_|.
- gfx::Insets insets_;
-
- // True if the root host resides on the internal display
- bool is_internal_display_;
-
- scoped_ptr<XID[]> pointer_barriers_;
-
- scoped_ptr<internal::TouchEventCalibrate> touch_calibrate_;
-
- scoped_ptr<MouseMoveFilter> mouse_move_filter_;
-
- ui::X11AtomCache atom_cache_;
-
- // Touch ids of which the touch press happens at side bezel region.
- uint32 bezel_tracking_ids_;
-
- DISALLOW_COPY_AND_ASSIGN(RootWindowHostX11);
-};
-
-namespace test {
-
-// Set the default value of the override redirect flag used to
-// create a X window for RootWindowHostX11.
-AURA_EXPORT void SetUseOverrideRedirectWindowByDefault(bool override_redirect);
-
-} // namespace test
-} // namespace aura
-
-#endif // UI_AURA_ROOT_WINDOW_HOST_X11_H_
diff --git a/chromium/ui/aura/root_window_host_x11_unittest.cc b/chromium/ui/aura/root_window_host_x11_unittest.cc
deleted file mode 100644
index 576707a09c7..00000000000
--- a/chromium/ui/aura/root_window_host_x11_unittest.cc
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-#include "base/sys_info.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/root_window_host_x11.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/window_tree_host_delegate.h"
-#include "ui/events/event_processor.h"
-#include "ui/events/event_target.h"
-#include "ui/events/event_target_iterator.h"
-#include "ui/events/test/events_test_utils_x11.h"
-
-namespace {
-class TestRootWindowHostDelegate : public aura::RootWindowHostDelegate,
- public ui::EventProcessor,
- public ui::EventTarget {
- public:
- TestRootWindowHostDelegate() : last_touch_type_(ui::ET_UNKNOWN),
- last_touch_id_(-1),
- last_touch_location_(0, 0) {
- }
- virtual ~TestRootWindowHostDelegate() {}
-
- // aura::RootWindowHostDelegate:
- virtual bool OnHostKeyEvent(ui::KeyEvent* event) OVERRIDE {
- return true;
- }
- virtual bool OnHostMouseEvent(ui::MouseEvent* event) OVERRIDE {
- return true;
- }
- virtual bool OnHostScrollEvent(ui::ScrollEvent* event) OVERRIDE {
- return true;
- }
- virtual bool OnHostTouchEvent(ui::TouchEvent* event) OVERRIDE {
- last_touch_id_ = event->touch_id();
- last_touch_type_ = event->type();
- last_touch_location_ = event->location();
- return true;
- }
-
- virtual void OnHostCancelMode() OVERRIDE {}
- virtual void OnHostActivated() OVERRIDE {}
- virtual void OnHostLostWindowCapture() OVERRIDE {}
- virtual void OnHostLostMouseGrab() OVERRIDE {}
- virtual void OnHostPaint(const gfx::Rect& damage_rect) OVERRIDE {}
- virtual void OnHostMoved(const gfx::Point& origin) OVERRIDE {}
- virtual void OnHostResized(const gfx::Size& size) OVERRIDE {}
- virtual float GetDeviceScaleFactor() OVERRIDE { return 1.0f; }
- virtual aura::RootWindow* AsRootWindow() OVERRIDE { return NULL; }
- virtual const aura::RootWindow* AsRootWindow() const OVERRIDE { return NULL; }
- virtual ui::EventProcessor* GetEventProcessor() OVERRIDE {
- return this;
- }
-
- // ui::EventProcessor:
- virtual ui::EventTarget* GetRootTarget() OVERRIDE { return this; }
- virtual bool CanDispatchToTarget(ui::EventTarget* target) OVERRIDE {
- return true;
- }
-
- // ui::EventHandler:
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
- last_touch_id_ = event->touch_id();
- last_touch_type_ = event->type();
- last_touch_location_ = event->location();
- }
-
- // ui::EventTarget:
- virtual bool CanAcceptEvent(const ui::Event& event) OVERRIDE {
- return true;
- }
- virtual ui::EventTarget* GetParentTarget() OVERRIDE { return NULL; }
- virtual scoped_ptr<ui::EventTargetIterator>
- GetChildIterator() const OVERRIDE {
- return scoped_ptr<ui::EventTargetIterator>();
- }
- virtual ui::EventTargeter* GetEventTargeter() OVERRIDE { return &targeter_; }
-
- ui::EventType last_touch_type() {
- return last_touch_type_;
- }
-
- int last_touch_id() {
- return last_touch_id_;
- }
-
- gfx::Point last_touch_location() {
- return last_touch_location_;
- }
-
- private:
- ui::EventType last_touch_type_;
- int last_touch_id_;
- gfx::Point last_touch_location_;
- ui::EventTargeter targeter_;
-
- DISALLOW_COPY_AND_ASSIGN(TestRootWindowHostDelegate);
-};
-
-} // namespace
-
-namespace aura {
-
-typedef test::AuraTestBase RootWindowHostX11Test;
-
-// Send X touch events to one RootWindowHost. The RootWindowHost's
-// delegate will get corresponding ui::TouchEvent if the touch events
-// are winthin the bound of the RootWindowHost.
-TEST_F(RootWindowHostX11Test, DispatchTouchEventToOneRootWindow) {
-#if defined(OS_CHROMEOS)
- // Fake a ChromeOS running env.
- const char* kLsbRelease = "CHROMEOS_RELEASE_NAME=Chromium OS\n";
- base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, base::Time());
-#endif // defined(OS_CHROMEOS)
-
- scoped_ptr<RootWindowHostX11> root_window_host(
- new RootWindowHostX11(gfx::Rect(0, 0, 2560, 1700)));
- scoped_ptr<TestRootWindowHostDelegate> delegate(
- new TestRootWindowHostDelegate());
- root_window_host->set_delegate(delegate.get());
-
- std::vector<unsigned int> devices;
- devices.push_back(0);
- ui::SetUpTouchDevicesForTest(devices);
- std::vector<ui::Valuator> valuators;
-
- EXPECT_EQ(ui::ET_UNKNOWN, delegate->last_touch_type());
- EXPECT_EQ(-1, delegate->last_touch_id());
-
- ui::ScopedXI2Event scoped_xevent;
-#if defined(OS_CHROMEOS)
- // This touch is out of bounds.
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchBegin, 5, gfx::Point(1500, 2500), valuators);
- root_window_host->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_UNKNOWN, delegate->last_touch_type());
- EXPECT_EQ(-1, delegate->last_touch_id());
- EXPECT_EQ(gfx::Point(0, 0), delegate->last_touch_location());
-#endif // defined(OS_CHROMEOS)
-
- // Following touchs are within bounds and are passed to delegate.
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchBegin, 5, gfx::Point(1500, 1500), valuators);
- root_window_host->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_TOUCH_PRESSED, delegate->last_touch_type());
- EXPECT_EQ(0, delegate->last_touch_id());
- EXPECT_EQ(gfx::Point(1500, 1500), delegate->last_touch_location());
-
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchUpdate, 5, gfx::Point(1500, 1600), valuators);
- root_window_host->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_TOUCH_MOVED, delegate->last_touch_type());
- EXPECT_EQ(0, delegate->last_touch_id());
- EXPECT_EQ(gfx::Point(1500, 1600), delegate->last_touch_location());
-
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchEnd, 5, gfx::Point(1500, 1600), valuators);
- root_window_host->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_TOUCH_RELEASED, delegate->last_touch_type());
- EXPECT_EQ(0, delegate->last_touch_id());
- EXPECT_EQ(gfx::Point(1500, 1600), delegate->last_touch_location());
-
- // Revert the CrOS testing env otherwise the following non-CrOS aura
- // tests will fail.
-#if defined(OS_CHROMEOS)
- // Fake a ChromeOS running env.
- kLsbRelease = "";
- base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, base::Time());
-#endif // defined(OS_CHROMEOS)
-}
-
-// Send X touch events to two RootWindowHost. The RootWindowHost which is
-// the event target of the X touch events should generate the corresponding
-// ui::TouchEvent for its delegate.
-#if defined(OS_CHROMEOS)
-TEST_F(RootWindowHostX11Test, DispatchTouchEventToTwoRootWindow) {
- // Fake a ChromeOS running env.
- const char* kLsbRelease = "CHROMEOS_RELEASE_NAME=Chromium OS\n";
- base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, base::Time());
-
- scoped_ptr<RootWindowHostX11> root_window_host1(
- new RootWindowHostX11(gfx::Rect(0, 0, 2560, 1700)));
- scoped_ptr<TestRootWindowHostDelegate> delegate1(
- new TestRootWindowHostDelegate());
- root_window_host1->set_delegate(delegate1.get());
-
- int host2_y_offset = 1700;
- scoped_ptr<RootWindowHostX11> root_window_host2(
- new RootWindowHostX11(gfx::Rect(0, host2_y_offset, 1920, 1080)));
- scoped_ptr<TestRootWindowHostDelegate> delegate2(
- new TestRootWindowHostDelegate());
- root_window_host2->set_delegate(delegate2.get());
-
- std::vector<unsigned int> devices;
- devices.push_back(0);
- ui::SetUpTouchDevicesForTest(devices);
- std::vector<ui::Valuator> valuators;
-
- EXPECT_EQ(ui::ET_UNKNOWN, delegate1->last_touch_type());
- EXPECT_EQ(-1, delegate1->last_touch_id());
- EXPECT_EQ(ui::ET_UNKNOWN, delegate2->last_touch_type());
- EXPECT_EQ(-1, delegate2->last_touch_id());
-
- // 2 Touch events are targeted at the second RootWindowHost.
- ui::ScopedXI2Event scoped_xevent;
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchBegin, 5, gfx::Point(1500, 2500), valuators);
- root_window_host1->Dispatch(scoped_xevent);
- root_window_host2->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_UNKNOWN, delegate1->last_touch_type());
- EXPECT_EQ(-1, delegate1->last_touch_id());
- EXPECT_EQ(gfx::Point(0, 0), delegate1->last_touch_location());
- EXPECT_EQ(ui::ET_TOUCH_PRESSED, delegate2->last_touch_type());
- EXPECT_EQ(0, delegate2->last_touch_id());
- EXPECT_EQ(gfx::Point(1500, 2500 - host2_y_offset),
- delegate2->last_touch_location());
-
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchBegin, 6, gfx::Point(1600, 2600), valuators);
- root_window_host1->Dispatch(scoped_xevent);
- root_window_host2->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_UNKNOWN, delegate1->last_touch_type());
- EXPECT_EQ(-1, delegate1->last_touch_id());
- EXPECT_EQ(gfx::Point(0, 0), delegate1->last_touch_location());
- EXPECT_EQ(ui::ET_TOUCH_PRESSED, delegate2->last_touch_type());
- EXPECT_EQ(1, delegate2->last_touch_id());
- EXPECT_EQ(gfx::Point(1600, 2600 - host2_y_offset),
- delegate2->last_touch_location());
-
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchUpdate, 5, gfx::Point(1500, 2550), valuators);
- root_window_host1->Dispatch(scoped_xevent);
- root_window_host2->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_UNKNOWN, delegate1->last_touch_type());
- EXPECT_EQ(-1, delegate1->last_touch_id());
- EXPECT_EQ(gfx::Point(0, 0), delegate1->last_touch_location());
- EXPECT_EQ(ui::ET_TOUCH_MOVED, delegate2->last_touch_type());
- EXPECT_EQ(0, delegate2->last_touch_id());
- EXPECT_EQ(gfx::Point(1500, 2550 - host2_y_offset),
- delegate2->last_touch_location());
-
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchUpdate, 6, gfx::Point(1600, 2650), valuators);
- root_window_host1->Dispatch(scoped_xevent);
- root_window_host2->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_UNKNOWN, delegate1->last_touch_type());
- EXPECT_EQ(-1, delegate1->last_touch_id());
- EXPECT_EQ(gfx::Point(0, 0), delegate1->last_touch_location());
- EXPECT_EQ(ui::ET_TOUCH_MOVED, delegate2->last_touch_type());
- EXPECT_EQ(1, delegate2->last_touch_id());
- EXPECT_EQ(gfx::Point(1600, 2650 - host2_y_offset),
- delegate2->last_touch_location());
-
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchEnd, 5, gfx::Point(1500, 2550), valuators);
- root_window_host1->Dispatch(scoped_xevent);
- root_window_host2->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_UNKNOWN, delegate1->last_touch_type());
- EXPECT_EQ(-1, delegate1->last_touch_id());
- EXPECT_EQ(gfx::Point(0, 0), delegate1->last_touch_location());
- EXPECT_EQ(ui::ET_TOUCH_RELEASED, delegate2->last_touch_type());
- EXPECT_EQ(0, delegate2->last_touch_id());
- EXPECT_EQ(gfx::Point(1500, 2550 - host2_y_offset),
- delegate2->last_touch_location());
-
- scoped_xevent.InitTouchEvent(
- 0, XI_TouchEnd, 6, gfx::Point(1600, 2650), valuators);
- root_window_host1->Dispatch(scoped_xevent);
- root_window_host2->Dispatch(scoped_xevent);
- EXPECT_EQ(ui::ET_UNKNOWN, delegate1->last_touch_type());
- EXPECT_EQ(-1, delegate1->last_touch_id());
- EXPECT_EQ(gfx::Point(0, 0), delegate1->last_touch_location());
- EXPECT_EQ(ui::ET_TOUCH_RELEASED, delegate2->last_touch_type());
- EXPECT_EQ(1, delegate2->last_touch_id());
- EXPECT_EQ(gfx::Point(1600, 2650 - host2_y_offset),
- delegate2->last_touch_location());
-
- // Revert the CrOS testing env otherwise the following non-CrOS aura
- // tests will fail.
- // Fake a ChromeOS running env.
- kLsbRelease = "";
- base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, base::Time());
-}
-#endif // defined(OS_CHROMEOS)
-
-} // namespace aura
diff --git a/chromium/ui/aura/root_window_observer.h b/chromium/ui/aura/root_window_observer.h
deleted file mode 100644
index bfb8e65c518..00000000000
--- a/chromium/ui/aura/root_window_observer.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_ROOT_WINDOW_OBSERVER_H_
-#define UI_AURA_ROOT_WINDOW_OBSERVER_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace gfx {
-class Point;
-class Size;
-}
-
-namespace aura {
-class RootWindow;
-class Window;
-
-class AURA_EXPORT RootWindowObserver {
- public:
- // Invoked after the RootWindow's host has been resized.
- virtual void OnRootWindowHostResized(const RootWindow* root) {}
-
- // Invoked after the RootWindow's host has been moved on screen.
- virtual void OnRootWindowHostMoved(const RootWindow* root,
- const gfx::Point& new_origin) {}
-
- // Invoked when the native windowing system sends us a request to close our
- // window.
- virtual void OnRootWindowHostCloseRequested(const RootWindow* root) {}
-
- // Invoked when the keyboard mapping has changed.
- virtual void OnKeyboardMappingChanged(const RootWindow* root) {}
-
- protected:
- virtual ~RootWindowObserver() {}
-};
-
-} // namespace aura
-
-#endif // UI_AURA_ROOT_WINDOW_OBSERVER_H_
diff --git a/chromium/ui/aura/root_window_transformer.h b/chromium/ui/aura/root_window_transformer.h
deleted file mode 100644
index 89d67f28e6d..00000000000
--- a/chromium/ui/aura/root_window_transformer.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_ROOT_WINDOW_TRANSFORMER_H_
-#define UI_AURA_ROOT_WINDOW_TRANSFORMER_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace gfx {
-class Insets;
-class Rect;
-class Size;
-class Transform;
-}
-
-namespace aura {
-
-// RootWindowTransformer controls how RootWindow should be placed and
-// transformed inside the host window.
-class AURA_EXPORT RootWindowTransformer {
- public:
- virtual ~RootWindowTransformer() {}
-
- // Returns the transform the root window in DIP.
- virtual gfx::Transform GetTransform() const = 0;
-
- // Returns the inverse of the transform above. This method is to
- // provie an accurate inverse of the transform because the result of
- // |gfx::Transform::GetInverse| may contains computational error.
- virtual gfx::Transform GetInverseTransform() const = 0;
-
- // Returns the root window's bounds for given host window size in DIP.
- // This is necessary to handle the case where the root window's size
- // is bigger than the host window. (Screen magnifier for example).
- virtual gfx::Rect GetRootWindowBounds(const gfx::Size& host_size) const = 0;
-
- // Returns the insets that specifies the effective area of
- // the host window.
- virtual gfx::Insets GetHostInsets() const = 0;
-};
-
-} // namespace aura
-
-#endif // UI_AURA_ROOT_WINDOW_TRANSFORMER_H_
diff --git a/chromium/ui/aura/root_window_unittest.cc b/chromium/ui/aura/root_window_unittest.cc
deleted file mode 100644
index 2d135249bc8..00000000000
--- a/chromium/ui/aura/root_window_unittest.cc
+++ /dev/null
@@ -1,1530 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/root_window.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/client/event_client.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/event_generator.h"
-#include "ui/aura/test/test_cursor_client.h"
-#include "ui/aura/test/test_event_handler.h"
-#include "ui/aura/test/test_window_delegate.h"
-#include "ui/aura/test/test_windows.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tracker.h"
-#include "ui/base/hit_test.h"
-#include "ui/events/event.h"
-#include "ui/events/event_handler.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/gestures/gesture_configuration.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/point.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/screen.h"
-#include "ui/gfx/transform.h"
-
-namespace aura {
-namespace {
-
-// A delegate that always returns a non-client component for hit tests.
-class NonClientDelegate : public test::TestWindowDelegate {
- public:
- NonClientDelegate()
- : non_client_count_(0),
- mouse_event_count_(0),
- mouse_event_flags_(0x0) {
- }
- virtual ~NonClientDelegate() {}
-
- int non_client_count() const { return non_client_count_; }
- gfx::Point non_client_location() const { return non_client_location_; }
- int mouse_event_count() const { return mouse_event_count_; }
- gfx::Point mouse_event_location() const { return mouse_event_location_; }
- int mouse_event_flags() const { return mouse_event_flags_; }
-
- virtual int GetNonClientComponent(const gfx::Point& location) const OVERRIDE {
- NonClientDelegate* self = const_cast<NonClientDelegate*>(this);
- self->non_client_count_++;
- self->non_client_location_ = location;
- return HTTOPLEFT;
- }
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- mouse_event_count_++;
- mouse_event_location_ = event->location();
- mouse_event_flags_ = event->flags();
- event->SetHandled();
- }
-
- private:
- int non_client_count_;
- gfx::Point non_client_location_;
- int mouse_event_count_;
- gfx::Point mouse_event_location_;
- int mouse_event_flags_;
-
- DISALLOW_COPY_AND_ASSIGN(NonClientDelegate);
-};
-
-// A simple event handler that consumes key events.
-class ConsumeKeyHandler : public test::TestEventHandler {
- public:
- ConsumeKeyHandler() {}
- virtual ~ConsumeKeyHandler() {}
-
- // Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
- test::TestEventHandler::OnKeyEvent(event);
- event->StopPropagation();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConsumeKeyHandler);
-};
-
-bool IsFocusedWindow(aura::Window* window) {
- return client::GetFocusClient(window)->GetFocusedWindow() == window;
-}
-
-} // namespace
-
-typedef test::AuraTestBase RootWindowTest;
-
-TEST_F(RootWindowTest, OnHostMouseEvent) {
- // Create two non-overlapping windows so we don't have to worry about which
- // is on top.
- scoped_ptr<NonClientDelegate> delegate1(new NonClientDelegate());
- scoped_ptr<NonClientDelegate> delegate2(new NonClientDelegate());
- const int kWindowWidth = 123;
- const int kWindowHeight = 45;
- gfx::Rect bounds1(100, 200, kWindowWidth, kWindowHeight);
- gfx::Rect bounds2(300, 400, kWindowWidth, kWindowHeight);
- scoped_ptr<aura::Window> window1(CreateTestWindowWithDelegate(
- delegate1.get(), -1234, bounds1, root_window()));
- scoped_ptr<aura::Window> window2(CreateTestWindowWithDelegate(
- delegate2.get(), -5678, bounds2, root_window()));
-
- // Send a mouse event to window1.
- gfx::Point point(101, 201);
- ui::MouseEvent event1(
- ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&event1);
-
- // Event was tested for non-client area for the target window.
- EXPECT_EQ(1, delegate1->non_client_count());
- EXPECT_EQ(0, delegate2->non_client_count());
- // The non-client component test was in local coordinates.
- EXPECT_EQ(gfx::Point(1, 1), delegate1->non_client_location());
- // Mouse event was received by target window.
- EXPECT_EQ(1, delegate1->mouse_event_count());
- EXPECT_EQ(0, delegate2->mouse_event_count());
- // Event was in local coordinates.
- EXPECT_EQ(gfx::Point(1, 1), delegate1->mouse_event_location());
- // Non-client flag was set.
- EXPECT_TRUE(delegate1->mouse_event_flags() & ui::EF_IS_NON_CLIENT);
-}
-
-TEST_F(RootWindowTest, RepostEvent) {
- // Test RepostEvent in RootWindow. It only works for Mouse Press.
- EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
- gfx::Point point(10, 10);
- ui::MouseEvent event(
- ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON);
- dispatcher()->RepostEvent(event);
- RunAllPendingInMessageLoop();
- EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
-}
-
-// Check that we correctly track the state of the mouse buttons in response to
-// button press and release events.
-TEST_F(RootWindowTest, MouseButtonState) {
- EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
-
- gfx::Point location;
- scoped_ptr<ui::MouseEvent> event;
-
- // Press the left button.
- event.reset(new ui::MouseEvent(
- ui::ET_MOUSE_PRESSED,
- location,
- location,
- ui::EF_LEFT_MOUSE_BUTTON));
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(event.get());
- EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
-
- // Additionally press the right.
- event.reset(new ui::MouseEvent(
- ui::ET_MOUSE_PRESSED,
- location,
- location,
- ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON));
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(event.get());
- EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
-
- // Release the left button.
- event.reset(new ui::MouseEvent(
- ui::ET_MOUSE_RELEASED,
- location,
- location,
- ui::EF_RIGHT_MOUSE_BUTTON));
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(event.get());
- EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
-
- // Release the right button. We should ignore the Shift-is-down flag.
- event.reset(new ui::MouseEvent(
- ui::ET_MOUSE_RELEASED,
- location,
- location,
- ui::EF_SHIFT_DOWN));
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(event.get());
- EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
-
- // Press the middle button.
- event.reset(new ui::MouseEvent(
- ui::ET_MOUSE_PRESSED,
- location,
- location,
- ui::EF_MIDDLE_MOUSE_BUTTON));
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(event.get());
- EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
-}
-
-TEST_F(RootWindowTest, TranslatedEvent) {
- scoped_ptr<Window> w1(test::CreateTestWindowWithDelegate(NULL, 1,
- gfx::Rect(50, 50, 100, 100), root_window()));
-
- gfx::Point origin(100, 100);
- ui::MouseEvent root(ui::ET_MOUSE_PRESSED, origin, origin, 0);
-
- EXPECT_EQ("100,100", root.location().ToString());
- EXPECT_EQ("100,100", root.root_location().ToString());
-
- ui::MouseEvent translated_event(
- root, static_cast<Window*>(root_window()), w1.get(),
- ui::ET_MOUSE_ENTERED, root.flags());
- EXPECT_EQ("50,50", translated_event.location().ToString());
- EXPECT_EQ("100,100", translated_event.root_location().ToString());
-}
-
-namespace {
-
-class TestEventClient : public client::EventClient {
- public:
- static const int kNonLockWindowId = 100;
- static const int kLockWindowId = 200;
-
- explicit TestEventClient(Window* root_window)
- : root_window_(root_window),
- lock_(false) {
- client::SetEventClient(root_window_, this);
- Window* lock_window =
- test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
- lock_window->set_id(kLockWindowId);
- Window* non_lock_window =
- test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
- non_lock_window->set_id(kNonLockWindowId);
- }
- virtual ~TestEventClient() {
- client::SetEventClient(root_window_, NULL);
- }
-
- // Starts/stops locking. Locking prevents windows other than those inside
- // the lock container from receiving events, getting focus etc.
- void Lock() {
- lock_ = true;
- }
- void Unlock() {
- lock_ = false;
- }
-
- Window* GetLockWindow() {
- return const_cast<Window*>(
- static_cast<const TestEventClient*>(this)->GetLockWindow());
- }
- const Window* GetLockWindow() const {
- return root_window_->GetChildById(kLockWindowId);
- }
- Window* GetNonLockWindow() {
- return root_window_->GetChildById(kNonLockWindowId);
- }
-
- private:
- // Overridden from client::EventClient:
- virtual bool CanProcessEventsWithinSubtree(
- const Window* window) const OVERRIDE {
- return lock_ ?
- window->Contains(GetLockWindow()) || GetLockWindow()->Contains(window) :
- true;
- }
-
- virtual ui::EventTarget* GetToplevelEventTarget() OVERRIDE {
- return NULL;
- }
-
- Window* root_window_;
- bool lock_;
-
- DISALLOW_COPY_AND_ASSIGN(TestEventClient);
-};
-
-} // namespace
-
-TEST_F(RootWindowTest, CanProcessEventsWithinSubtree) {
- TestEventClient client(root_window());
- test::TestWindowDelegate d;
-
- test::TestEventHandler* nonlock_ef = new test::TestEventHandler;
- test::TestEventHandler* lock_ef = new test::TestEventHandler;
- client.GetNonLockWindow()->SetEventFilter(nonlock_ef);
- client.GetLockWindow()->SetEventFilter(lock_ef);
-
- Window* w1 = test::CreateTestWindowWithBounds(gfx::Rect(10, 10, 20, 20),
- client.GetNonLockWindow());
- w1->set_id(1);
- Window* w2 = test::CreateTestWindowWithBounds(gfx::Rect(30, 30, 20, 20),
- client.GetNonLockWindow());
- w2->set_id(2);
- scoped_ptr<Window> w3(
- test::CreateTestWindowWithDelegate(&d, 3, gfx::Rect(30, 30, 20, 20),
- client.GetLockWindow()));
-
- w1->Focus();
- EXPECT_TRUE(IsFocusedWindow(w1));
-
- client.Lock();
-
- // Since we're locked, the attempt to focus w2 will be ignored.
- w2->Focus();
- EXPECT_TRUE(IsFocusedWindow(w1));
- EXPECT_FALSE(IsFocusedWindow(w2));
-
- {
- // Attempting to send a key event to w1 (not in the lock container) should
- // cause focus to be reset.
- test::EventGenerator generator(root_window());
- generator.PressKey(ui::VKEY_SPACE, 0);
- EXPECT_EQ(NULL, client::GetFocusClient(w1)->GetFocusedWindow());
- }
-
- {
- // Events sent to a window not in the lock container will not be processed.
- // i.e. never sent to the non-lock container's event filter.
- test::EventGenerator generator(root_window(), w1);
- generator.PressLeftButton();
- EXPECT_EQ(0, nonlock_ef->num_mouse_events());
-
- // Events sent to a window in the lock container will be processed.
- test::EventGenerator generator3(root_window(), w3.get());
- generator3.PressLeftButton();
- EXPECT_EQ(1, lock_ef->num_mouse_events());
- }
-
- // Prevent w3 from being deleted by the hierarchy since its delegate is owned
- // by this scope.
- w3->parent()->RemoveChild(w3.get());
-}
-
-TEST_F(RootWindowTest, IgnoreUnknownKeys) {
- test::TestEventHandler* filter = new ConsumeKeyHandler;
- root_window()->SetEventFilter(filter); // passes ownership
-
- ui::KeyEvent unknown_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, 0, false);
- EXPECT_FALSE(dispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(
- &unknown_event));
- EXPECT_EQ(0, filter->num_key_events());
-
- ui::KeyEvent known_event(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, false);
- EXPECT_TRUE(dispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(
- &known_event));
- EXPECT_EQ(1, filter->num_key_events());
-}
-
-TEST_F(RootWindowTest, NoDelegateWindowReceivesKeyEvents) {
- scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
- w1->Show();
- w1->Focus();
-
- test::TestEventHandler handler;
- w1->AddPreTargetHandler(&handler);
- ui::KeyEvent key_press(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, false);
- EXPECT_TRUE(dispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(
- &key_press));
- EXPECT_EQ(1, handler.num_key_events());
-
- w1->RemovePreTargetHandler(&handler);
-}
-
-// Tests that touch-events that are beyond the bounds of the root-window do get
-// propagated to the event filters correctly with the root as the target.
-TEST_F(RootWindowTest, TouchEventsOutsideBounds) {
- test::TestEventHandler* filter = new test::TestEventHandler;
- root_window()->SetEventFilter(filter); // passes ownership
-
- gfx::Point position = root_window()->bounds().origin();
- position.Offset(-10, -10);
- ui::TouchEvent press(ui::ET_TOUCH_PRESSED, position, 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
- EXPECT_EQ(1, filter->num_touch_events());
-
- position = root_window()->bounds().origin();
- position.Offset(root_window()->bounds().width() + 10,
- root_window()->bounds().height() + 10);
- ui::TouchEvent release(ui::ET_TOUCH_RELEASED, position, 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
- EXPECT_EQ(2, filter->num_touch_events());
-}
-
-// Tests that scroll events are dispatched correctly.
-TEST_F(RootWindowTest, ScrollEventDispatch) {
- base::TimeDelta now = ui::EventTimeForNow();
- test::TestEventHandler* filter = new test::TestEventHandler;
- root_window()->SetEventFilter(filter);
-
- test::TestWindowDelegate delegate;
- scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &delegate));
- w1->SetBounds(gfx::Rect(20, 20, 40, 40));
-
- // A scroll event on the root-window itself is dispatched.
- ui::ScrollEvent scroll1(ui::ET_SCROLL,
- gfx::Point(10, 10),
- now,
- 0,
- 0, -10,
- 0, -10,
- 2);
- dispatcher()->AsRootWindowHostDelegate()->OnHostScrollEvent(&scroll1);
- EXPECT_EQ(1, filter->num_scroll_events());
-
- // Scroll event on a window should be dispatched properly.
- ui::ScrollEvent scroll2(ui::ET_SCROLL,
- gfx::Point(25, 30),
- now,
- 0,
- -10, 0,
- -10, 0,
- 2);
- dispatcher()->AsRootWindowHostDelegate()->OnHostScrollEvent(&scroll2);
- EXPECT_EQ(2, filter->num_scroll_events());
-}
-
-namespace {
-
-// FilterFilter that tracks the types of events it's seen.
-class EventFilterRecorder : public ui::EventHandler {
- public:
- typedef std::vector<ui::EventType> Events;
- typedef std::vector<gfx::Point> MouseEventLocations;
-
- EventFilterRecorder() {}
-
- Events& events() { return events_; }
-
- MouseEventLocations& mouse_locations() { return mouse_locations_; }
- gfx::Point mouse_location(int i) const { return mouse_locations_[i]; }
-
-Events GetAndResetEvents() {
- Events events = events_;
- events_.clear();
- return events;
- }
-
- // ui::EventHandler overrides:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
- events_.push_back(event->type());
- }
-
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- events_.push_back(event->type());
- mouse_locations_.push_back(event->location());
- }
-
- virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
- events_.push_back(event->type());
- }
-
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
- events_.push_back(event->type());
- }
-
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
- events_.push_back(event->type());
- }
-
- private:
- Events events_;
- MouseEventLocations mouse_locations_;
-
- DISALLOW_COPY_AND_ASSIGN(EventFilterRecorder);
-};
-
-// Converts an EventType to a string.
-std::string EventTypeToString(ui::EventType type) {
- switch (type) {
- case ui::ET_TOUCH_RELEASED:
- return "TOUCH_RELEASED";
-
- case ui::ET_TOUCH_CANCELLED:
- return "TOUCH_CANCELLED";
-
- case ui::ET_TOUCH_PRESSED:
- return "TOUCH_PRESSED";
-
- case ui::ET_TOUCH_MOVED:
- return "TOUCH_MOVED";
-
- case ui::ET_MOUSE_PRESSED:
- return "MOUSE_PRESSED";
-
- case ui::ET_MOUSE_DRAGGED:
- return "MOUSE_DRAGGED";
-
- case ui::ET_MOUSE_RELEASED:
- return "MOUSE_RELEASED";
-
- case ui::ET_MOUSE_MOVED:
- return "MOUSE_MOVED";
-
- case ui::ET_MOUSE_ENTERED:
- return "MOUSE_ENTERED";
-
- case ui::ET_MOUSE_EXITED:
- return "MOUSE_EXITED";
-
- case ui::ET_GESTURE_SCROLL_BEGIN:
- return "GESTURE_SCROLL_BEGIN";
-
- case ui::ET_GESTURE_SCROLL_END:
- return "GESTURE_SCROLL_END";
-
- case ui::ET_GESTURE_SCROLL_UPDATE:
- return "GESTURE_SCROLL_UPDATE";
-
- case ui::ET_GESTURE_PINCH_BEGIN:
- return "GESTURE_PINCH_BEGIN";
-
- case ui::ET_GESTURE_PINCH_END:
- return "GESTURE_PINCH_END";
-
- case ui::ET_GESTURE_PINCH_UPDATE:
- return "GESTURE_PINCH_UPDATE";
-
- case ui::ET_GESTURE_TAP:
- return "GESTURE_TAP";
-
- case ui::ET_GESTURE_TAP_DOWN:
- return "GESTURE_TAP_DOWN";
-
- case ui::ET_GESTURE_TAP_CANCEL:
- return "GESTURE_TAP_CANCEL";
-
- case ui::ET_GESTURE_SHOW_PRESS:
- return "GESTURE_SHOW_PRESS";
-
- case ui::ET_GESTURE_BEGIN:
- return "GESTURE_BEGIN";
-
- case ui::ET_GESTURE_END:
- return "GESTURE_END";
-
- default:
- // We should explicitly require each event type.
- NOTREACHED();
- break;
- }
- return "";
-}
-
-std::string EventTypesToString(const EventFilterRecorder::Events& events) {
- std::string result;
- for (size_t i = 0; i < events.size(); ++i) {
- if (i != 0)
- result += " ";
- result += EventTypeToString(events[i]);
- }
- return result;
-}
-
-} // namespace
-
-// Verifies a repost mouse event targets the window with capture (if there is
-// one).
-TEST_F(RootWindowTest, RepostTargetsCaptureWindow) {
- // Set capture on |window| generate a mouse event (that is reposted) and not
- // over |window| and verify |window| gets it (|window| gets it because it has
- // capture).
- EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
- scoped_ptr<Window> window(CreateNormalWindow(1, root_window(), NULL));
- window->SetBounds(gfx::Rect(20, 20, 40, 30));
- EventFilterRecorder* recorder = new EventFilterRecorder;
- window->SetEventFilter(recorder); // Takes ownership.
- window->SetCapture();
- const ui::MouseEvent press_event(
- ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
- ui::EF_LEFT_MOUSE_BUTTON);
- dispatcher()->RepostEvent(press_event);
- RunAllPendingInMessageLoop(); // Necessitated by RepostEvent().
- // Mouse moves/enters may be generated. We only care about a pressed.
- EXPECT_TRUE(EventTypesToString(recorder->events()).find("MOUSE_PRESSED") !=
- std::string::npos) << EventTypesToString(recorder->events());
-}
-
-TEST_F(RootWindowTest, MouseMovesHeld) {
- EventFilterRecorder* filter = new EventFilterRecorder;
- root_window()->SetEventFilter(filter); // passes ownership
-
- test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
- &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
-
- ui::MouseEvent mouse_move_event(ui::ET_MOUSE_MOVED, gfx::Point(0, 0),
- gfx::Point(0, 0), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_move_event);
- // Discard MOUSE_ENTER.
- filter->events().clear();
-
- dispatcher()->HoldPointerMoves();
-
- // Check that we don't immediately dispatch the MOUSE_DRAGGED event.
- ui::MouseEvent mouse_dragged_event(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0),
- gfx::Point(0, 0), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_dragged_event);
- EXPECT_TRUE(filter->events().empty());
-
- // Check that we do dispatch the held MOUSE_DRAGGED event before another type
- // of event.
- ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0),
- gfx::Point(0, 0), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_pressed_event);
- EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
- EventTypesToString(filter->events()));
- filter->events().clear();
-
- // Check that we coalesce held MOUSE_DRAGGED events.
- ui::MouseEvent mouse_dragged_event2(ui::ET_MOUSE_DRAGGED, gfx::Point(1, 1),
- gfx::Point(1, 1), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_dragged_event);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_dragged_event2);
- EXPECT_TRUE(filter->events().empty());
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_pressed_event);
- EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
- EventTypesToString(filter->events()));
- filter->events().clear();
-
- // Check that on ReleasePointerMoves, held events are not dispatched
- // immediately, but posted instead.
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_dragged_event);
- dispatcher()->ReleasePointerMoves();
- EXPECT_TRUE(filter->events().empty());
- RunAllPendingInMessageLoop();
- EXPECT_EQ("MOUSE_DRAGGED", EventTypesToString(filter->events()));
- filter->events().clear();
-
- // However if another message comes in before the dispatch of the posted
- // event, check that the posted event is dispatched before this new event.
- dispatcher()->HoldPointerMoves();
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_dragged_event);
- dispatcher()->ReleasePointerMoves();
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_pressed_event);
- EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
- EventTypesToString(filter->events()));
- filter->events().clear();
- RunAllPendingInMessageLoop();
- EXPECT_TRUE(filter->events().empty());
-
- // Check that if the other message is another MOUSE_DRAGGED, we still coalesce
- // them.
- dispatcher()->HoldPointerMoves();
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_dragged_event);
- dispatcher()->ReleasePointerMoves();
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_dragged_event2);
- EXPECT_EQ("MOUSE_DRAGGED", EventTypesToString(filter->events()));
- filter->events().clear();
- RunAllPendingInMessageLoop();
- EXPECT_TRUE(filter->events().empty());
-}
-
-TEST_F(RootWindowTest, TouchMovesHeld) {
- EventFilterRecorder* filter = new EventFilterRecorder;
- root_window()->SetEventFilter(filter); // passes ownership
-
- test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
- &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
-
- // Starting the touch and throwing out the first few events, since the system
- // is going to generate synthetic mouse events that are not relevant to the
- // test.
- ui::TouchEvent touch_pressed_event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
- 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(
- &touch_pressed_event);
- RunAllPendingInMessageLoop();
- filter->events().clear();
-
- dispatcher()->HoldPointerMoves();
-
- // Check that we don't immediately dispatch the TOUCH_MOVED event.
- ui::TouchEvent touch_moved_event(ui::ET_TOUCH_MOVED, gfx::Point(0, 0),
- 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(
- &touch_moved_event);
- EXPECT_TRUE(filter->events().empty());
-
- // Check that on ReleasePointerMoves, held events are not dispatched
- // immediately, but posted instead.
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(
- &touch_moved_event);
- dispatcher()->ReleasePointerMoves();
- EXPECT_TRUE(filter->events().empty());
- RunAllPendingInMessageLoop();
- EXPECT_EQ("TOUCH_MOVED", EventTypesToString(filter->events()));
- filter->events().clear();
-
- // If another touch event occurs then the held touch should be dispatched
- // immediately before it.
- ui::TouchEvent touch_released_event(ui::ET_TOUCH_RELEASED, gfx::Point(0, 0),
- 0, base::TimeDelta());
- filter->events().clear();
- dispatcher()->HoldPointerMoves();
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(
- &touch_moved_event);
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(
- &touch_released_event);
- EXPECT_EQ("TOUCH_MOVED TOUCH_RELEASED GESTURE_TAP_CANCEL GESTURE_END",
- EventTypesToString(filter->events()));
- filter->events().clear();
- dispatcher()->ReleasePointerMoves();
- RunAllPendingInMessageLoop();
- EXPECT_TRUE(filter->events().empty());
-}
-
-// Tests that synthetic mouse events are ignored when mouse
-// events are disabled.
-TEST_F(RootWindowTest, DispatchSyntheticMouseEvents) {
- EventFilterRecorder* filter = new EventFilterRecorder;
- root_window()->SetEventFilter(filter); // passes ownership
-
- test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
- &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
- window->Show();
- window->SetCapture();
-
- test::TestCursorClient cursor_client(root_window());
-
- // Dispatch a non-synthetic mouse event when mouse events are enabled.
- ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
- gfx::Point(10, 10), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse1);
- EXPECT_FALSE(filter->events().empty());
- filter->events().clear();
-
- // Dispatch a synthetic mouse event when mouse events are enabled.
- ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
- gfx::Point(10, 10), ui::EF_IS_SYNTHESIZED);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse2);
- EXPECT_FALSE(filter->events().empty());
- filter->events().clear();
-
- // Dispatch a synthetic mouse event when mouse events are disabled.
- cursor_client.DisableMouseEvents();
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse2);
- EXPECT_TRUE(filter->events().empty());
-}
-
-// Tests that a mouse exit is dispatched to the last known cursor location
-// when the cursor becomes invisible.
-TEST_F(RootWindowTest, DispatchMouseExitWhenCursorHidden) {
- EventFilterRecorder* filter = new EventFilterRecorder;
- root_window()->SetEventFilter(filter); // passes ownership
-
- test::TestWindowDelegate delegate;
- gfx::Point window_origin(7, 18);
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
- &delegate, 1234, gfx::Rect(window_origin,
- gfx::Size(100, 100)), root_window()));
- window->Show();
-
- // Dispatch a mouse move event into the window.
- gfx::Point mouse_location(gfx::Point(15, 25));
- ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, mouse_location,
- mouse_location, 0);
- EXPECT_TRUE(filter->events().empty());
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse1);
- EXPECT_FALSE(filter->events().empty());
- filter->events().clear();
-
- // Hide the cursor and verify a mouse exit was dispatched.
- dispatcher()->OnCursorVisibilityChanged(false);
- EXPECT_FALSE(filter->events().empty());
- EXPECT_EQ("MOUSE_EXITED", EventTypesToString(filter->events()));
-
- // Verify the mouse exit was dispatched at the correct location
- // (in the correct coordinate space).
- int translated_x = mouse_location.x() - window_origin.x();
- int translated_y = mouse_location.y() - window_origin.y();
- gfx::Point translated_point(translated_x, translated_y);
- EXPECT_EQ(filter->mouse_location(0).ToString(), translated_point.ToString());
-}
-
-class DeletingEventFilter : public ui::EventHandler {
- public:
- DeletingEventFilter()
- : delete_during_pre_handle_(false) {}
- virtual ~DeletingEventFilter() {}
-
- void Reset(bool delete_during_pre_handle) {
- delete_during_pre_handle_ = delete_during_pre_handle;
- }
-
- private:
- // Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
- if (delete_during_pre_handle_)
- delete event->target();
- }
-
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- if (delete_during_pre_handle_)
- delete event->target();
- }
-
- bool delete_during_pre_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(DeletingEventFilter);
-};
-
-class DeletingWindowDelegate : public test::TestWindowDelegate {
- public:
- DeletingWindowDelegate()
- : window_(NULL),
- delete_during_handle_(false),
- got_event_(false) {}
- virtual ~DeletingWindowDelegate() {}
-
- void Reset(Window* window, bool delete_during_handle) {
- window_ = window;
- delete_during_handle_ = delete_during_handle;
- got_event_ = false;
- }
- bool got_event() const { return got_event_; }
-
- private:
- // Overridden from WindowDelegate:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
- if (delete_during_handle_)
- delete window_;
- got_event_ = true;
- }
-
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- if (delete_during_handle_)
- delete window_;
- got_event_ = true;
- }
-
- Window* window_;
- bool delete_during_handle_;
- bool got_event_;
-
- DISALLOW_COPY_AND_ASSIGN(DeletingWindowDelegate);
-};
-
-TEST_F(RootWindowTest, DeleteWindowDuringDispatch) {
- // Verifies that we can delete a window during each phase of event handling.
- // Deleting the window should not cause a crash, only prevent further
- // processing from occurring.
- scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
- DeletingWindowDelegate d11;
- Window* w11 = CreateNormalWindow(11, w1.get(), &d11);
- WindowTracker tracker;
- DeletingEventFilter* w1_filter = new DeletingEventFilter;
- w1->SetEventFilter(w1_filter);
- client::GetFocusClient(w1.get())->FocusWindow(w11);
-
- test::EventGenerator generator(root_window(), w11);
-
- // First up, no one deletes anything.
- tracker.Add(w11);
- d11.Reset(w11, false);
-
- generator.PressLeftButton();
- EXPECT_TRUE(tracker.Contains(w11));
- EXPECT_TRUE(d11.got_event());
- generator.ReleaseLeftButton();
-
- // Delegate deletes w11. This will prevent the post-handle step from applying.
- w1_filter->Reset(false);
- d11.Reset(w11, true);
- generator.PressKey(ui::VKEY_A, 0);
- EXPECT_FALSE(tracker.Contains(w11));
- EXPECT_TRUE(d11.got_event());
-
- // Pre-handle step deletes w11. This will prevent the delegate and the post-
- // handle steps from applying.
- w11 = CreateNormalWindow(11, w1.get(), &d11);
- w1_filter->Reset(true);
- d11.Reset(w11, false);
- generator.PressLeftButton();
- EXPECT_FALSE(tracker.Contains(w11));
- EXPECT_FALSE(d11.got_event());
-}
-
-namespace {
-
-// A window delegate that detaches the parent of the target's parent window when
-// it receives a tap event.
-class DetachesParentOnTapDelegate : public test::TestWindowDelegate {
- public:
- DetachesParentOnTapDelegate() {}
- virtual ~DetachesParentOnTapDelegate() {}
-
- private:
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
- if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
- event->SetHandled();
- return;
- }
-
- if (event->type() == ui::ET_GESTURE_TAP) {
- Window* parent = static_cast<Window*>(event->target())->parent();
- parent->parent()->RemoveChild(parent);
- event->SetHandled();
- }
- }
-
- DISALLOW_COPY_AND_ASSIGN(DetachesParentOnTapDelegate);
-};
-
-} // namespace
-
-// Tests that the gesture recognizer is reset for all child windows when a
-// window hides. No expectations, just checks that the test does not crash.
-TEST_F(RootWindowTest, GestureRecognizerResetsTargetWhenParentHides) {
- scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
- DetachesParentOnTapDelegate delegate;
- scoped_ptr<Window> parent(CreateNormalWindow(22, w1.get(), NULL));
- Window* child = CreateNormalWindow(11, parent.get(), &delegate);
- test::EventGenerator generator(root_window(), child);
- generator.GestureTapAt(gfx::Point(40, 40));
-}
-
-namespace {
-
-// A window delegate that processes nested gestures on tap.
-class NestedGestureDelegate : public test::TestWindowDelegate {
- public:
- NestedGestureDelegate(test::EventGenerator* generator,
- const gfx::Point tap_location)
- : generator_(generator),
- tap_location_(tap_location),
- gesture_end_count_(0) {}
- virtual ~NestedGestureDelegate() {}
-
- int gesture_end_count() const { return gesture_end_count_; }
-
- private:
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
- switch (event->type()) {
- case ui::ET_GESTURE_TAP_DOWN:
- event->SetHandled();
- break;
- case ui::ET_GESTURE_TAP:
- if (generator_)
- generator_->GestureTapAt(tap_location_);
- event->SetHandled();
- break;
- case ui::ET_GESTURE_END:
- ++gesture_end_count_;
- break;
- default:
- break;
- }
- }
-
- test::EventGenerator* generator_;
- const gfx::Point tap_location_;
- int gesture_end_count_;
- DISALLOW_COPY_AND_ASSIGN(NestedGestureDelegate);
-};
-
-} // namespace
-
-// Tests that gesture end is delivered after nested gesture processing.
-TEST_F(RootWindowTest, GestureEndDeliveredAfterNestedGestures) {
- NestedGestureDelegate d1(NULL, gfx::Point());
- scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &d1));
- w1->SetBounds(gfx::Rect(0, 0, 100, 100));
-
- test::EventGenerator nested_generator(root_window(), w1.get());
- NestedGestureDelegate d2(&nested_generator, w1->bounds().CenterPoint());
- scoped_ptr<Window> w2(CreateNormalWindow(1, root_window(), &d2));
- w2->SetBounds(gfx::Rect(100, 0, 100, 100));
-
- // Tap on w2 which triggers nested gestures for w1.
- test::EventGenerator generator(root_window(), w2.get());
- generator.GestureTapAt(w2->bounds().CenterPoint());
-
- // Both windows should get their gesture end events.
- EXPECT_EQ(1, d1.gesture_end_count());
- EXPECT_EQ(1, d2.gesture_end_count());
-}
-
-// Tests whether we can repost the Tap down gesture event.
-TEST_F(RootWindowTest, RepostTapdownGestureTest) {
- EventFilterRecorder* filter = new EventFilterRecorder;
- root_window()->SetEventFilter(filter); // passes ownership
-
- test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
- &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
-
- ui::GestureEventDetails details(ui::ET_GESTURE_TAP_DOWN, 0.0f, 0.0f);
- gfx::Point point(10, 10);
- ui::GestureEvent event(
- ui::ET_GESTURE_TAP_DOWN,
- point.x(),
- point.y(),
- 0,
- ui::EventTimeForNow(),
- details,
- 0);
- dispatcher()->RepostEvent(event);
- RunAllPendingInMessageLoop();
- // TODO(rbyers): Currently disabled - crbug.com/170987
- EXPECT_FALSE(EventTypesToString(filter->events()).find("GESTURE_TAP_DOWN") !=
- std::string::npos);
- filter->events().clear();
-}
-
-// This class inherits from the EventFilterRecorder class which provides a
-// facility to record events. This class additionally provides a facility to
-// repost the ET_GESTURE_TAP_DOWN gesture to the target window and records
-// events after that.
-class RepostGestureEventRecorder : public EventFilterRecorder {
- public:
- RepostGestureEventRecorder(aura::Window* repost_source,
- aura::Window* repost_target)
- : repost_source_(repost_source),
- repost_target_(repost_target),
- reposted_(false),
- done_cleanup_(false) {}
-
- virtual ~RepostGestureEventRecorder() {}
-
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
- if (reposted_ && event->type() == ui::ET_TOUCH_PRESSED) {
- done_cleanup_ = true;
- events().clear();
- }
- EventFilterRecorder::OnTouchEvent(event);
- }
-
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
- EXPECT_EQ(done_cleanup_ ? repost_target_ : repost_source_, event->target());
- if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
- if (!reposted_) {
- EXPECT_NE(repost_target_, event->target());
- reposted_ = true;
- repost_target_->GetDispatcher()->RepostEvent(*event);
- // Ensure that the reposted gesture event above goes to the
- // repost_target_;
- repost_source_->GetRootWindow()->RemoveChild(repost_source_);
- return;
- }
- }
- EventFilterRecorder::OnGestureEvent(event);
- }
-
- // Ignore mouse events as they don't fire at all times. This causes
- // the GestureRepostEventOrder test to fail randomly.
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {}
-
- private:
- aura::Window* repost_source_;
- aura::Window* repost_target_;
- // set to true if we reposted the ET_GESTURE_TAP_DOWN event.
- bool reposted_;
- // set true if we're done cleaning up after hiding repost_source_;
- bool done_cleanup_;
- DISALLOW_COPY_AND_ASSIGN(RepostGestureEventRecorder);
-};
-
-// Tests whether events which are generated after the reposted gesture event
-// are received after that. In this case the scroll sequence events should
-// be received after the reposted gesture event.
-TEST_F(RootWindowTest, GestureRepostEventOrder) {
- // Expected events at the end for the repost_target window defined below.
- const char kExpectedTargetEvents[] =
- // TODO)(rbyers): Gesture event reposting is disabled - crbug.com/279039.
- // "GESTURE_BEGIN GESTURE_TAP_DOWN "
- "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
- "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE TOUCH_MOVED "
- "GESTURE_SCROLL_UPDATE TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
- "GESTURE_SCROLL_END GESTURE_END";
- // We create two windows.
- // The first window (repost_source) is the one to which the initial tap
- // gesture is sent. It reposts this event to the second window
- // (repost_target).
- // We then generate the scroll sequence for repost_target and look for two
- // ET_GESTURE_TAP_DOWN events in the event list at the end.
- test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> repost_target(CreateTestWindowWithDelegate(
- &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
-
- scoped_ptr<aura::Window> repost_source(CreateTestWindowWithDelegate(
- &delegate, 1, gfx::Rect(0, 0, 50, 50), root_window()));
-
- RepostGestureEventRecorder* repost_event_recorder =
- new RepostGestureEventRecorder(repost_source.get(), repost_target.get());
- root_window()->SetEventFilter(repost_event_recorder); // passes ownership
-
- // Generate a tap down gesture for the repost_source. This will be reposted
- // to repost_target.
- test::EventGenerator repost_generator(root_window(), repost_source.get());
- repost_generator.GestureTapAt(gfx::Point(40, 40));
- RunAllPendingInMessageLoop();
-
- test::EventGenerator scroll_generator(root_window(), repost_target.get());
- scroll_generator.GestureScrollSequence(
- gfx::Point(80, 80),
- gfx::Point(100, 100),
- base::TimeDelta::FromMilliseconds(100),
- 3);
- RunAllPendingInMessageLoop();
-
- int tap_down_count = 0;
- for (size_t i = 0; i < repost_event_recorder->events().size(); ++i) {
- if (repost_event_recorder->events()[i] == ui::ET_GESTURE_TAP_DOWN)
- ++tap_down_count;
- }
-
- // We expect two tap down events. One from the repost and the other one from
- // the scroll sequence posted above.
- // TODO(rbyers): Currently disabled - crbug.com/170987
- EXPECT_EQ(1, tap_down_count);
-
- EXPECT_EQ(kExpectedTargetEvents,
- EventTypesToString(repost_event_recorder->events()));
-}
-
-class OnMouseExitDeletingEventFilter : public EventFilterRecorder {
- public:
- OnMouseExitDeletingEventFilter() : window_to_delete_(NULL) {}
- virtual ~OnMouseExitDeletingEventFilter() {}
-
- void set_window_to_delete(Window* window_to_delete) {
- window_to_delete_ = window_to_delete;
- }
-
- private:
- // Overridden from ui::EventHandler:
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- EventFilterRecorder::OnMouseEvent(event);
- if (window_to_delete_) {
- delete window_to_delete_;
- window_to_delete_ = NULL;
- }
- }
-
- Window* window_to_delete_;
-
- DISALLOW_COPY_AND_ASSIGN(OnMouseExitDeletingEventFilter);
-};
-
-// Tests that RootWindow drops mouse-moved event that is supposed to be sent to
-// a child, but the child is destroyed because of the synthesized mouse-exit
-// event generated on the previous mouse_moved_handler_.
-TEST_F(RootWindowTest, DeleteWindowDuringMouseMovedDispatch) {
- // Create window 1 and set its event filter. Window 1 will take ownership of
- // the event filter.
- scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
- OnMouseExitDeletingEventFilter* w1_filter =
- new OnMouseExitDeletingEventFilter();
- w1->SetEventFilter(w1_filter);
- w1->SetBounds(gfx::Rect(20, 20, 60, 60));
- EXPECT_EQ(NULL, dispatcher()->mouse_moved_handler());
-
- test::EventGenerator generator(root_window(), w1.get());
-
- // Move mouse over window 1 to set it as the |mouse_moved_handler_| for the
- // root window.
- generator.MoveMouseTo(51, 51);
- EXPECT_EQ(w1.get(), dispatcher()->mouse_moved_handler());
-
- // Create window 2 under the mouse cursor and stack it above window 1.
- Window* w2 = CreateNormalWindow(2, root_window(), NULL);
- w2->SetBounds(gfx::Rect(30, 30, 40, 40));
- root_window()->StackChildAbove(w2, w1.get());
-
- // Set window 2 as the window that is to be deleted when a mouse-exited event
- // happens on window 1.
- w1_filter->set_window_to_delete(w2);
-
- // Move mosue over window 2. This should generate a mouse-exited event for
- // window 1 resulting in deletion of window 2. The original mouse-moved event
- // that was targeted to window 2 should be dropped since window 2 is
- // destroyed. This test passes if no crash happens.
- generator.MoveMouseTo(52, 52);
- EXPECT_EQ(NULL, dispatcher()->mouse_moved_handler());
-
- // Check events received by window 1.
- EXPECT_EQ("MOUSE_ENTERED MOUSE_MOVED MOUSE_EXITED",
- EventTypesToString(w1_filter->events()));
-}
-
-namespace {
-
-// Used to track if OnWindowDestroying() is invoked and if there is a valid
-// RootWindow at such time.
-class ValidRootDuringDestructionWindowObserver : public aura::WindowObserver {
- public:
- ValidRootDuringDestructionWindowObserver(bool* got_destroying,
- bool* has_valid_root)
- : got_destroying_(got_destroying),
- has_valid_root_(has_valid_root) {
- }
-
- // WindowObserver:
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
- *got_destroying_ = true;
- *has_valid_root_ = (window->GetRootWindow() != NULL);
- }
-
- private:
- bool* got_destroying_;
- bool* has_valid_root_;
-
- DISALLOW_COPY_AND_ASSIGN(ValidRootDuringDestructionWindowObserver);
-};
-
-} // namespace
-
-#if defined(USE_OZONE)
-// Creating multiple RootWindowHostOzone instances is broken.
-#define MAYBE_ValidRootDuringDestruction DISABLED_ValidRootDuringDestruction
-#else
-#define MAYBE_ValidRootDuringDestruction ValidRootDuringDestruction
-#endif
-
-// Verifies GetRootWindow() from ~Window returns a valid root.
-TEST_F(RootWindowTest, MAYBE_ValidRootDuringDestruction) {
- bool got_destroying = false;
- bool has_valid_root = false;
- ValidRootDuringDestructionWindowObserver observer(&got_destroying,
- &has_valid_root);
- {
- scoped_ptr<RootWindow> root_window(
- new RootWindow(RootWindow::CreateParams(gfx::Rect(0, 0, 100, 100))));
- root_window->Init();
- // Owned by RootWindow.
- Window* w1 = CreateNormalWindow(1, root_window->window(), NULL);
- w1->AddObserver(&observer);
- }
- EXPECT_TRUE(got_destroying);
- EXPECT_TRUE(has_valid_root);
-}
-
-namespace {
-
-// See description above DontResetHeldEvent for details.
-class DontResetHeldEventWindowDelegate : public test::TestWindowDelegate {
- public:
- explicit DontResetHeldEventWindowDelegate(aura::Window* root)
- : root_(root),
- mouse_event_count_(0) {}
- virtual ~DontResetHeldEventWindowDelegate() {}
-
- int mouse_event_count() const { return mouse_event_count_; }
-
- // TestWindowDelegate:
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 &&
- mouse_event_count_++ == 0) {
- ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED,
- gfx::Point(10, 10), gfx::Point(10, 10),
- ui::EF_SHIFT_DOWN);
- root_->GetDispatcher()->RepostEvent(mouse_event);
- }
- }
-
- private:
- Window* root_;
- int mouse_event_count_;
-
- DISALLOW_COPY_AND_ASSIGN(DontResetHeldEventWindowDelegate);
-};
-
-} // namespace
-
-// Verifies RootWindow doesn't reset |RootWindow::held_repostable_event_| after
-// dispatching. This is done by using DontResetHeldEventWindowDelegate, which
-// tracks the number of events with ui::EF_SHIFT_DOWN set (all reposted events
-// have EF_SHIFT_DOWN). When the first event is seen RepostEvent() is used to
-// schedule another reposted event.
-TEST_F(RootWindowTest, DontResetHeldEvent) {
- DontResetHeldEventWindowDelegate delegate(root_window());
- scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &delegate));
- RootWindowHostDelegate* root_window_delegate =
- static_cast<RootWindowHostDelegate*>(root_window()->GetDispatcher());
- w1->SetBounds(gfx::Rect(0, 0, 40, 40));
- ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED,
- gfx::Point(10, 10), gfx::Point(10, 10),
- ui::EF_SHIFT_DOWN);
- root_window()->GetDispatcher()->RepostEvent(pressed);
- ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED,
- gfx::Point(10, 10), gfx::Point(10, 10), 0);
- // Invoke OnHostMouseEvent() to flush event scheduled by way of RepostEvent().
- root_window_delegate->OnHostMouseEvent(&pressed2);
- // Delegate should have seen reposted event (identified by way of
- // EF_SHIFT_DOWN). Invoke OnHostMouseEvent() to flush the second
- // RepostedEvent().
- EXPECT_EQ(1, delegate.mouse_event_count());
- root_window_delegate->OnHostMouseEvent(&pressed2);
- EXPECT_EQ(2, delegate.mouse_event_count());
-}
-
-namespace {
-
-// See description above DeleteRootFromHeldMouseEvent for details.
-class DeleteRootFromHeldMouseEventDelegate : public test::TestWindowDelegate {
- public:
- explicit DeleteRootFromHeldMouseEventDelegate(aura::RootWindow* root)
- : root_(root),
- got_mouse_event_(false),
- got_destroy_(false) {
- }
- virtual ~DeleteRootFromHeldMouseEventDelegate() {}
-
- bool got_mouse_event() const { return got_mouse_event_; }
- bool got_destroy() const { return got_destroy_; }
-
- // TestWindowDelegate:
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- if ((event->flags() & ui::EF_SHIFT_DOWN) != 0) {
- got_mouse_event_ = true;
- delete root_;
- }
- }
- virtual void OnWindowDestroyed() OVERRIDE {
- got_destroy_ = true;
- }
-
- private:
- RootWindow* root_;
- bool got_mouse_event_;
- bool got_destroy_;
-
- DISALLOW_COPY_AND_ASSIGN(DeleteRootFromHeldMouseEventDelegate);
-};
-
-} // namespace
-
-#if defined(USE_OZONE)
-// Creating multiple RootWindowHostOzone instances is broken.
-#define MAYBE_DeleteRootFromHeldMouseEvent DISABLED_DeleteRootFromHeldMouseEvent
-#else
-#define MAYBE_DeleteRootFromHeldMouseEvent DeleteRootFromHeldMouseEvent
-#endif
-
-// Verifies if a RootWindow is deleted from dispatching a held mouse event we
-// don't crash.
-TEST_F(RootWindowTest, MAYBE_DeleteRootFromHeldMouseEvent) {
- // Should be deleted by |delegate|.
- RootWindow* r2 =
- new RootWindow(RootWindow::CreateParams(gfx::Rect(0, 0, 100, 100)));
- r2->Init();
- DeleteRootFromHeldMouseEventDelegate delegate(r2);
- // Owned by |r2|.
- Window* w1 = CreateNormalWindow(1, r2->window(), &delegate);
- w1->SetBounds(gfx::Rect(0, 0, 40, 40));
- ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED,
- gfx::Point(10, 10), gfx::Point(10, 10),
- ui::EF_SHIFT_DOWN);
- r2->RepostEvent(pressed);
- // RunAllPendingInMessageLoop() to make sure the |pressed| is run.
- RunAllPendingInMessageLoop();
- EXPECT_TRUE(delegate.got_mouse_event());
- EXPECT_TRUE(delegate.got_destroy());
-}
-
-TEST_F(RootWindowTest, WindowHideCancelsActiveTouches) {
- EventFilterRecorder* filter = new EventFilterRecorder;
- root_window()->SetEventFilter(filter); // passes ownership
-
- test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
- &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
-
- gfx::Point position1 = root_window()->bounds().origin();
- ui::TouchEvent press(ui::ET_TOUCH_PRESSED, position1, 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
-
- EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN",
- EventTypesToString(filter->GetAndResetEvents()));
-
- window->Hide();
-
- EXPECT_EQ("TOUCH_CANCELLED GESTURE_TAP_CANCEL GESTURE_END",
- EventTypesToString(filter->events()));
-}
-
-TEST_F(RootWindowTest, WindowHideCancelsActiveGestures) {
- EventFilterRecorder* filter = new EventFilterRecorder;
- root_window()->SetEventFilter(filter); // passes ownership
-
- test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
- &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
-
- gfx::Point position1 = root_window()->bounds().origin();
- gfx::Point position2 = root_window()->bounds().CenterPoint();
- ui::TouchEvent press(ui::ET_TOUCH_PRESSED, position1, 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
-
- ui::TouchEvent move(ui::ET_TOUCH_MOVED, position2, 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
-
- ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, position1, 1, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
-
- EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
- "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
- "TOUCH_PRESSED GESTURE_BEGIN GESTURE_PINCH_BEGIN",
- EventTypesToString(filter->GetAndResetEvents()));
-
- window->Hide();
-
- EXPECT_EQ("TOUCH_CANCELLED GESTURE_PINCH_END GESTURE_END TOUCH_CANCELLED "
- "GESTURE_SCROLL_END GESTURE_END",
- EventTypesToString(filter->events()));
-}
-
-// Places two windows side by side. Presses down on one window, and starts a
-// scroll. Sets capture on the other window and ensures that the "ending" events
-// aren't sent to the window which gained capture.
-TEST_F(RootWindowTest, EndingEventDoesntRetarget) {
- scoped_ptr<Window> window1(CreateNormalWindow(1, root_window(), NULL));
- window1->SetBounds(gfx::Rect(0, 0, 40, 40));
-
- scoped_ptr<Window> window2(CreateNormalWindow(2, root_window(), NULL));
- window2->SetBounds(gfx::Rect(40, 0, 40, 40));
-
- EventFilterRecorder* filter1 = new EventFilterRecorder();
- window1->SetEventFilter(filter1); // passes ownership
- EventFilterRecorder* filter2 = new EventFilterRecorder();
- window2->SetEventFilter(filter2); // passes ownership
-
- gfx::Point position = window1->bounds().origin();
- ui::TouchEvent press(ui::ET_TOUCH_PRESSED, position, 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
-
- gfx::Point position2 = window1->bounds().CenterPoint();
- ui::TouchEvent move(ui::ET_TOUCH_MOVED, position2, 0, base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
-
- window2->SetCapture();
-
- EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
- "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
- "TOUCH_CANCELLED GESTURE_SCROLL_END GESTURE_END",
- EventTypesToString(filter1->events()));
-
- EXPECT_TRUE(filter2->events().empty());
-}
-
-class ExitMessageLoopOnMousePress : public test::TestEventHandler {
- public:
- ExitMessageLoopOnMousePress() {}
- virtual ~ExitMessageLoopOnMousePress() {}
-
- protected:
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
- test::TestEventHandler::OnMouseEvent(event);
- if (event->type() == ui::ET_MOUSE_PRESSED)
- base::MessageLoopForUI::current()->Quit();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ExitMessageLoopOnMousePress);
-};
-
-class RootWindowTestWithMessageLoop : public RootWindowTest {
- public:
- RootWindowTestWithMessageLoop() {}
- virtual ~RootWindowTestWithMessageLoop() {}
-
- void RunTest() {
- // Start a nested message-loop, post an event to be dispatched, and then
- // terminate the message-loop. When the message-loop unwinds and gets back,
- // the reposted event should not have fired.
- ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
- gfx::Point(10, 10), ui::EF_NONE);
- message_loop()->PostTask(FROM_HERE,
- base::Bind(&RootWindow::RepostEvent,
- base::Unretained(dispatcher()),
- mouse));
- message_loop()->PostTask(FROM_HERE,
- message_loop()->QuitClosure());
-
- base::MessageLoop::ScopedNestableTaskAllower allow(message_loop());
- base::RunLoop loop;
- loop.Run();
- EXPECT_EQ(0, handler_.num_mouse_events());
-
- // Let the current message-loop run. The event-handler will terminate the
- // message-loop when it receives the reposted event.
- }
-
- base::MessageLoop* message_loop() {
- return base::MessageLoopForUI::current();
- }
-
- protected:
- virtual void SetUp() OVERRIDE {
- RootWindowTest::SetUp();
- window_.reset(CreateNormalWindow(1, root_window(), NULL));
- window_->AddPreTargetHandler(&handler_);
- }
-
- virtual void TearDown() OVERRIDE {
- window_.reset();
- RootWindowTest::TearDown();
- }
-
- private:
- scoped_ptr<Window> window_;
- ExitMessageLoopOnMousePress handler_;
-
- DISALLOW_COPY_AND_ASSIGN(RootWindowTestWithMessageLoop);
-};
-
-TEST_F(RootWindowTestWithMessageLoop, EventRepostedInNonNestedLoop) {
- CHECK(!message_loop()->is_running());
- // Perform the test in a callback, so that it runs after the message-loop
- // starts.
- message_loop()->PostTask(FROM_HERE,
- base::Bind(&RootWindowTestWithMessageLoop::RunTest,
- base::Unretained(this)));
- message_loop()->Run();
-}
-
-} // namespace aura
diff --git a/chromium/ui/aura/scoped_window_targeter.cc b/chromium/ui/aura/scoped_window_targeter.cc
new file mode 100644
index 00000000000..96355246245
--- /dev/null
+++ b/chromium/ui/aura/scoped_window_targeter.cc
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/scoped_window_targeter.h"
+
+#include "ui/aura/window.h"
+
+namespace aura {
+
+ScopedWindowTargeter::ScopedWindowTargeter(
+ Window* window,
+ scoped_ptr<ui::EventTargeter> new_targeter)
+ : window_(window),
+ old_targeter_(window->SetEventTargeter(new_targeter.Pass())) {
+}
+
+ScopedWindowTargeter::~ScopedWindowTargeter() {
+ if (window_)
+ window_->SetEventTargeter(old_targeter_.Pass());
+}
+
+void ScopedWindowTargeter::OnWindowDestroyed(Window* window) {
+ CHECK_EQ(window_, window);
+ window_ = NULL;
+ old_targeter_.reset();
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/scoped_window_targeter.h b/chromium/ui/aura/scoped_window_targeter.h
new file mode 100644
index 00000000000..f8546c57d0e
--- /dev/null
+++ b/chromium/ui/aura/scoped_window_targeter.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_SCOPED_WINDOW_TARGETER_H_
+#define UI_AURA_SCOPED_WINDOW_TARGETER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/window_observer.h"
+
+namespace ui {
+class EventTargeter;
+}
+
+namespace aura {
+
+class Window;
+
+// ScopedWindowTargeter is used to temporarily replace the event-targeter for a
+// window. Upon construction, it installs a new targeter on the window, and upon
+// destruction, it restores the previous event-targeter on the window.
+class AURA_EXPORT ScopedWindowTargeter : public WindowObserver {
+ public:
+ ScopedWindowTargeter(Window* window,
+ scoped_ptr<ui::EventTargeter> new_targeter);
+
+ virtual ~ScopedWindowTargeter();
+
+ ui::EventTargeter* old_targeter() {
+ return old_targeter_.get();
+ }
+
+ private:
+ // WindowObserver:
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE;
+
+ Window* window_;
+ scoped_ptr<ui::EventTargeter> old_targeter_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedWindowTargeter);
+};
+
+} // namespace aura
+
+#endif // UI_AURA_SCOPED_WINDOW_TARGETER_H_
diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc
index 4836a15aae0..35b29245800 100644
--- a/chromium/ui/aura/window.cc
+++ b/chromium/ui/aura/window.cc
@@ -10,7 +10,6 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -23,15 +22,14 @@
#include "ui/aura/client/window_stacking_client.h"
#include "ui/aura/env.h"
#include "ui/aura/layout_manager.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window_delegate.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tracker.h"
#include "ui/aura/window_tree_host.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/events/event_target_iterator.h"
-#include "ui/gfx/animation/multi_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/path.h"
#include "ui/gfx/scoped_canvas.h"
@@ -41,19 +39,6 @@ namespace aura {
namespace {
-WindowLayerType UILayerTypeToWindowLayerType(ui::LayerType layer_type) {
- switch (layer_type) {
- case ui::LAYER_NOT_DRAWN:
- return WINDOW_LAYER_NOT_DRAWN;
- case ui::LAYER_TEXTURED:
- return WINDOW_LAYER_TEXTURED;
- case ui::LAYER_SOLID_COLOR:
- return WINDOW_LAYER_SOLID_COLOR;
- }
- NOTREACHED();
- return WINDOW_LAYER_NOT_DRAWN;
-}
-
ui::LayerType WindowLayerTypeToUILayerType(WindowLayerType window_layer_type) {
switch (window_layer_type) {
case WINDOW_LAYER_NONE:
@@ -176,7 +161,7 @@ class ScopedCursorHider {
explicit ScopedCursorHider(Window* window)
: window_(window),
hid_cursor_(false) {
- if (!window_->HasDispatcher())
+ if (!window_->IsRootWindow())
return;
const bool cursor_is_in_bounds = window_->GetBoundsInScreen().Contains(
Env::GetInstance()->last_mouse_location());
@@ -188,7 +173,7 @@ class ScopedCursorHider {
}
}
~ScopedCursorHider() {
- if (!window_->HasDispatcher())
+ if (!window_->IsRootWindow())
return;
// Update the device scale factor of the cursor client only when the last
@@ -213,12 +198,11 @@ class ScopedCursorHider {
};
Window::Window(WindowDelegate* delegate)
- : dispatcher_(NULL),
- type_(client::WINDOW_TYPE_UNKNOWN),
+ : host_(NULL),
+ type_(ui::wm::WINDOW_TYPE_UNKNOWN),
owned_by_parent_(true),
delegate_(delegate),
parent_(NULL),
- transient_parent_(NULL),
visible_(false),
id_(-1),
transparent_(false),
@@ -232,43 +216,46 @@ Window::Window(WindowDelegate* delegate)
}
Window::~Window() {
- // |layer_| can be NULL during tests, or if this Window is layerless.
- if (layer_)
- layer_->SuppressPaint();
+ // |layer()| can be NULL during tests, or if this Window is layerless.
+ if (layer()) {
+ if (layer()->owner() == this)
+ layer()->CompleteAllAnimations();
+ layer()->SuppressPaint();
+ }
// Let the delegate know we're in the processing of destroying.
if (delegate_)
- delegate_->OnWindowDestroying();
+ delegate_->OnWindowDestroying(this);
FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this));
- // Let the root know so that it can remove any references to us.
- WindowEventDispatcher* dispatcher = GetDispatcher();
- if (dispatcher)
- dispatcher->OnWindowDestroying(this);
+ // TODO(beng): See comment in window_event_dispatcher.h. This shouldn't be
+ // necessary but unfortunately is right now due to ordering
+ // peculiarities. WED must be notified _after_ other observers
+ // are notified of pending teardown but before the hierarchy
+ // is actually torn down.
+ WindowTreeHost* host = GetHost();
+ if (host)
+ host->dispatcher()->OnPostNotifiedWindowDestroying(this);
+
+ // The window should have already had its state cleaned up in
+ // WindowEventDispatcher::OnWindowHidden(), but there have been some crashes
+ // involving windows being destroyed without being hidden first. See
+ // crbug.com/342040. This should help us debug the issue. TODO(tdresser):
+ // remove this once we determine why we have windows that are destroyed
+ // without being hidden.
+ bool window_incorrectly_cleaned_up = CleanupGestureState();
+ CHECK(!window_incorrectly_cleaned_up);
// Then destroy the children.
RemoveOrDestroyChildren();
- // Removes ourselves from our transient parent (if it hasn't been done by the
- // RootWindow).
- if (transient_parent_)
- transient_parent_->RemoveTransientChild(this);
-
// The window needs to be removed from the parent before calling the
// WindowDestroyed callbacks of delegate and the observers.
if (parent_)
parent_->RemoveChild(this);
- // Destroy transient children, only after we've removed ourselves from our
- // parent, as destroying an active transient child may otherwise attempt to
- // refocus us.
- Windows transient_children(transient_children_);
- STLDeleteElements(&transient_children);
- DCHECK(transient_children_.empty());
-
- // Delegate and observers need to be notified after transients are deleted.
if (delegate_)
- delegate_->OnWindowDestroyed();
+ delegate_->OnWindowDestroyed(this);
ObserverListBase<WindowObserver>::Iterator iter(observers_);
WindowObserver* observer;
while ((observer = iter.GetNext())) {
@@ -288,83 +275,45 @@ Window::~Window() {
// If we have layer it will either be destroyed by |layer_owner_|'s dtor, or
// by whoever acquired it. We don't have a layer if Init() wasn't invoked or
// we are layerless.
- if (layer_) {
- layer_->set_delegate(NULL);
- layer_ = NULL;
- }
-}
-
-void Window::Init(ui::LayerType layer_type) {
- InitWithWindowLayerType(UILayerTypeToWindowLayerType(layer_type));
+ if (layer())
+ layer()->set_delegate(NULL);
+ DestroyLayer();
}
-void Window::InitWithWindowLayerType(WindowLayerType window_layer_type) {
+void Window::Init(WindowLayerType window_layer_type) {
if (window_layer_type != WINDOW_LAYER_NONE) {
- layer_ = new ui::Layer(WindowLayerTypeToUILayerType(window_layer_type));
- layer_owner_.reset(layer_);
- layer_->SetVisible(false);
- layer_->set_delegate(this);
- UpdateLayerName(name_);
- layer_->SetFillsBoundsOpaquely(!transparent_);
+ SetLayer(new ui::Layer(WindowLayerTypeToUILayerType(window_layer_type)));
+ layer()->SetVisible(false);
+ layer()->set_delegate(this);
+ UpdateLayerName();
+ layer()->SetFillsBoundsOpaquely(!transparent_);
}
Env::GetInstance()->NotifyWindowInitialized(this);
}
-ui::Layer* Window::RecreateLayer() {
- // Disconnect the old layer, but don't delete it.
- ui::Layer* old_layer = AcquireLayer();
- if (!old_layer)
- return NULL;
-
- old_layer->set_delegate(NULL);
-
- layer_ = new ui::Layer(old_layer->type());
- layer_owner_.reset(layer_);
- layer_->SetVisible(old_layer->visible());
- layer_->set_scale_content(old_layer->scale_content());
- layer_->set_delegate(this);
- layer_->SetMasksToBounds(old_layer->GetMasksToBounds());
-
- if (delegate_)
- delegate_->DidRecreateLayer(old_layer, layer_);
-
- UpdateLayerName(name_);
- layer_->SetFillsBoundsOpaquely(!transparent_);
- // Install new layer as a sibling of the old layer, stacked below it.
- if (old_layer->parent()) {
- old_layer->parent()->Add(layer_);
- old_layer->parent()->StackBelow(layer_, old_layer);
- }
- // Migrate all the child layers over to the new layer. Copy the list because
- // the items are removed during iteration.
- std::vector<ui::Layer*> children_copy = old_layer->children();
- for (std::vector<ui::Layer*>::const_iterator it = children_copy.begin();
- it != children_copy.end();
- ++it) {
- ui::Layer* child = *it;
- layer_->Add(child);
- }
- return old_layer;
-}
-
-void Window::SetType(client::WindowType type) {
+void Window::SetType(ui::wm::WindowType type) {
// Cannot change type after the window is initialized.
- DCHECK(!layer_);
+ DCHECK(!layer());
type_ = type;
}
void Window::SetName(const std::string& name) {
name_ = name;
- if (layer_)
- UpdateLayerName(name_);
+ if (layer())
+ UpdateLayerName();
}
void Window::SetTransparent(bool transparent) {
transparent_ = transparent;
- if (layer_)
- layer_->SetFillsBoundsOpaquely(!transparent_);
+ if (layer())
+ layer()->SetFillsBoundsOpaquely(!transparent_);
+}
+
+void Window::SetFillsBoundsCompletely(bool fills_bounds) {
+ if (layer())
+ layer()->SetFillsBoundsCompletely(fills_bounds);
}
Window* Window::GetRootWindow() {
@@ -373,30 +322,33 @@ Window* Window::GetRootWindow() {
}
const Window* Window::GetRootWindow() const {
- return dispatcher_ ? this : parent_ ? parent_->GetRootWindow() : NULL;
+ return IsRootWindow() ? this : parent_ ? parent_->GetRootWindow() : NULL;
}
-WindowEventDispatcher* Window::GetDispatcher() {
- return const_cast<WindowEventDispatcher*>(const_cast<const Window*>(this)->
- GetDispatcher());
+WindowTreeHost* Window::GetHost() {
+ return const_cast<WindowTreeHost*>(const_cast<const Window*>(this)->
+ GetHost());
}
-const WindowEventDispatcher* Window::GetDispatcher() const {
+const WindowTreeHost* Window::GetHost() const {
const Window* root_window = GetRootWindow();
- return root_window ? root_window->dispatcher_ : NULL;
+ return root_window ? root_window->host_ : NULL;
}
void Window::Show() {
+ if (layer()) {
+ DCHECK_EQ(visible_, layer()->GetTargetVisibility());
+ // It is not allowed that a window is visible but the layers alpha is fully
+ // transparent since the window would still be considered to be active but
+ // could not be seen.
+ DCHECK(!(visible_ && layer()->GetTargetOpacity() == 0.0f));
+ }
SetVisible(true);
}
void Window::Hide() {
- for (Windows::iterator it = transient_children_.begin();
- it != transient_children_.end(); ++it) {
- (*it)->Hide();
- }
+ // RootWindow::OnVisibilityChanged will call ReleaseCapture.
SetVisible(false);
- ReleaseCapture();
}
bool Window::IsVisible() const {
@@ -407,8 +359,8 @@ bool Window::IsVisible() const {
for (const Window* window = this; window; window = window->parent()) {
if (!window->visible_)
return false;
- if (window->layer_)
- return window->layer_->IsDrawn();
+ if (window->layer())
+ return window->layer()->IsDrawn();
}
return false;
}
@@ -440,17 +392,16 @@ gfx::Rect Window::GetBoundsInScreen() const {
}
void Window::SetTransform(const gfx::Transform& transform) {
- if (!layer_) {
+ if (!layer()) {
// Transforms aren't supported on layerless windows.
NOTREACHED();
return;
}
- WindowEventDispatcher* dispatcher = GetDispatcher();
- bool contained_mouse = IsVisible() && dispatcher &&
- ContainsPointInRoot(dispatcher->GetLastMouseLocationInRoot());
- layer_->SetTransform(transform);
- if (dispatcher)
- dispatcher->OnWindowTransformed(this, contained_mouse);
+ FOR_EACH_OBSERVER(WindowObserver, observers_,
+ OnWindowTransforming(this));
+ layer()->SetTransform(transform);
+ FOR_EACH_OBSERVER(WindowObserver, observers_,
+ OnWindowTransformed(this));
}
void Window::SetLayoutManager(LayoutManager* layout_manager) {
@@ -467,11 +418,27 @@ void Window::SetLayoutManager(LayoutManager* layout_manager) {
layout_manager_->OnWindowAddedToLayout(*it);
}
+scoped_ptr<ui::EventTargeter>
+Window::SetEventTargeter(scoped_ptr<ui::EventTargeter> targeter) {
+ scoped_ptr<ui::EventTargeter> old_targeter = targeter_.Pass();
+ targeter_ = targeter.Pass();
+ return old_targeter.Pass();
+}
+
void Window::SetBounds(const gfx::Rect& new_bounds) {
if (parent_ && parent_->layout_manager())
parent_->layout_manager()->SetChildBounds(this, new_bounds);
- else
- SetBoundsInternal(new_bounds);
+ else {
+ // Ensure we don't go smaller than our minimum bounds.
+ gfx::Rect final_bounds(new_bounds);
+ if (delegate_) {
+ const gfx::Size& min_size = delegate_->GetMinimumSize();
+ final_bounds.set_width(std::max(min_size.width(), final_bounds.width()));
+ final_bounds.set_height(std::max(min_size.height(),
+ final_bounds.height()));
+ }
+ SetBoundsInternal(final_bounds);
+ }
}
void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen,
@@ -488,11 +455,11 @@ void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen,
}
gfx::Rect Window::GetTargetBounds() const {
- if (!layer_)
+ if (!layer())
return bounds();
- if (!parent_ || parent_->layer_)
- return layer_->GetTargetBounds();
+ if (!parent_ || parent_->layer())
+ return layer()->GetTargetBounds();
// We have a layer but our parent (who is valid) doesn't. This means the
// coordinates of the layer are relative to the first ancestor with a layer;
@@ -501,15 +468,15 @@ gfx::Rect Window::GetTargetBounds() const {
const aura::Window* ancestor_with_layer =
parent_->GetAncestorWithLayer(&offset);
if (!ancestor_with_layer)
- return layer_->GetTargetBounds();
+ return layer()->GetTargetBounds();
- gfx::Rect layer_target_bounds = layer_->GetTargetBounds();
+ gfx::Rect layer_target_bounds = layer()->GetTargetBounds();
layer_target_bounds -= offset;
return layer_target_bounds;
}
void Window::SchedulePaintInRect(const gfx::Rect& rect) {
- if (!layer_ && parent_) {
+ if (!layer() && parent_) {
// Notification of paint scheduled happens for the window with a layer.
gfx::Rect parent_rect(bounds().size());
parent_rect.Intersect(rect);
@@ -517,7 +484,7 @@ void Window::SchedulePaintInRect(const gfx::Rect& rect) {
parent_rect.Offset(bounds().origin().OffsetFromOrigin());
parent_->SchedulePaintInRect(parent_rect);
}
- } else if (layer_ && layer_->SchedulePaint(rect)) {
+ } else if (layer() && layer()->SchedulePaint(rect)) {
FOR_EACH_OBSERVER(
WindowObserver, observers_, OnWindowPaintScheduled(this, rect));
}
@@ -560,13 +527,14 @@ void Window::AddChild(Window* child) {
gfx::Vector2d offset;
aura::Window* ancestor_with_layer = GetAncestorWithLayer(&offset);
+
+ child->parent_ = this;
+
if (ancestor_with_layer) {
offset += child->bounds().OffsetFromOrigin();
child->ReparentLayers(ancestor_with_layer->layer(), offset);
}
- child->parent_ = this;
-
children_.push_back(child);
if (layout_manager_)
layout_manager_->OnWindowAddedToLayout(child);
@@ -575,7 +543,7 @@ void Window::AddChild(Window* child) {
Window* root_window = GetRootWindow();
if (root_window && old_root != root_window) {
- root_window->GetDispatcher()->OnWindowAddedToRootWindow(child);
+ root_window->GetHost()->dispatcher()->OnWindowAddedToRootWindow(child);
child->NotifyAddedToRootWindow();
}
@@ -605,28 +573,6 @@ bool Window::Contains(const Window* other) const {
return false;
}
-void Window::AddTransientChild(Window* child) {
- if (child->transient_parent_)
- child->transient_parent_->RemoveTransientChild(child);
- DCHECK(std::find(transient_children_.begin(), transient_children_.end(),
- child) == transient_children_.end());
- transient_children_.push_back(child);
- child->transient_parent_ = this;
- FOR_EACH_OBSERVER(WindowObserver, observers_,
- OnAddTransientChild(this, child));
-}
-
-void Window::RemoveTransientChild(Window* child) {
- Windows::iterator i =
- std::find(transient_children_.begin(), transient_children_.end(), child);
- DCHECK(i != transient_children_.end());
- transient_children_.erase(i);
- if (child->transient_parent_ == this)
- child->transient_parent_ = NULL;
- FOR_EACH_OBSERVER(WindowObserver, observers_,
- OnRemoveTransientChild(this, child));
-}
-
Window* Window::GetChildById(int id) {
return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id));
}
@@ -652,53 +598,61 @@ void Window::ConvertPointToTarget(const Window* source,
if (source->GetRootWindow() != target->GetRootWindow()) {
client::ScreenPositionClient* source_client =
client::GetScreenPositionClient(source->GetRootWindow());
- source_client->ConvertPointToScreen(source, point);
+ // |source_client| can be NULL in tests.
+ if (source_client)
+ source_client->ConvertPointToScreen(source, point);
client::ScreenPositionClient* target_client =
client::GetScreenPositionClient(target->GetRootWindow());
- target_client->ConvertPointFromScreen(target, point);
- } else if ((source != target) && (!source->layer_ || !target->layer_)) {
- if (!source->layer_) {
+ // |target_client| can be NULL in tests.
+ if (target_client)
+ target_client->ConvertPointFromScreen(target, point);
+ } else if ((source != target) && (!source->layer() || !target->layer())) {
+ if (!source->layer()) {
gfx::Vector2d offset_to_layer;
source = source->GetAncestorWithLayer(&offset_to_layer);
*point += offset_to_layer;
}
- if (!target->layer_) {
+ if (!target->layer()) {
gfx::Vector2d offset_to_layer;
target = target->GetAncestorWithLayer(&offset_to_layer);
*point -= offset_to_layer;
}
- ui::Layer::ConvertPointToLayer(source->layer_, target->layer_, point);
+ ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point);
} else {
- ui::Layer::ConvertPointToLayer(source->layer_, target->layer_, point);
+ ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point);
}
}
+// static
+void Window::ConvertRectToTarget(const Window* source,
+ const Window* target,
+ gfx::Rect* rect) {
+ DCHECK(rect);
+ gfx::Point origin = rect->origin();
+ ConvertPointToTarget(source, target, &origin);
+ rect->set_origin(origin);
+}
+
void Window::MoveCursorTo(const gfx::Point& point_in_window) {
Window* root_window = GetRootWindow();
DCHECK(root_window);
gfx::Point point_in_root(point_in_window);
ConvertPointToTarget(this, root_window, &point_in_root);
- root_window->GetDispatcher()->MoveCursorTo(point_in_root);
+ root_window->GetHost()->MoveCursorTo(point_in_root);
}
gfx::NativeCursor Window::GetCursor(const gfx::Point& point) const {
return delegate_ ? delegate_->GetCursor(point) : gfx::kNullCursor;
}
-void Window::SetEventFilter(ui::EventHandler* event_filter) {
- if (event_filter_)
- RemovePreTargetHandler(event_filter_.get());
- event_filter_.reset(event_filter);
- if (event_filter)
- AddPreTargetHandler(event_filter);
-}
-
void Window::AddObserver(WindowObserver* observer) {
+ observer->OnObservingWindow(this);
observers_.AddObserver(observer);
}
void Window::RemoveObserver(WindowObserver* observer) {
+ observer->OnUnobservingWindow(this);
observers_.RemoveObserver(observer);
}
@@ -719,28 +673,6 @@ bool Window::ContainsPoint(const gfx::Point& local_point) const {
return gfx::Rect(bounds().size()).Contains(local_point);
}
-bool Window::HitTest(const gfx::Point& local_point) {
- // Expand my bounds for hit testing (override is usually zero but it's
- // probably cheaper to do the math every time than to branch).
- gfx::Rect local_bounds(gfx::Point(), bounds().size());
- local_bounds.Inset(aura::Env::GetInstance()->is_touch_down() ?
- hit_test_bounds_override_outer_touch_ :
- hit_test_bounds_override_outer_mouse_);
-
- if (!delegate_ || !delegate_->HasHitTestMask())
- return local_bounds.Contains(local_point);
-
- gfx::Path mask;
- delegate_->GetHitTestMask(&mask);
-
- SkRegion clip_region;
- clip_region.setRect(local_bounds.x(), local_bounds.y(),
- local_bounds.width(), local_bounds.height());
- SkRegion mask_region;
- return mask_region.setPath(mask, clip_region) &&
- mask_region.contains(local_point.x(), local_point.y());
-}
-
Window* Window::GetEventHandlerForPoint(const gfx::Point& local_point) {
return GetWindowForPoint(local_point, true, true);
}
@@ -776,7 +708,7 @@ bool Window::HasFocus() const {
}
bool Window::CanFocus() const {
- if (dispatcher_)
+ if (IsRootWindow())
return IsVisible();
// NOTE: as part of focusing the window the ActivationClient may make the
@@ -795,7 +727,7 @@ bool Window::CanFocus() const {
}
bool Window::CanReceiveEvents() const {
- if (dispatcher_)
+ if (IsRootWindow())
return IsVisible();
// The client may forbid certain windows from receiving events at a given
@@ -833,8 +765,8 @@ bool Window::HasCapture() {
}
void Window::SuppressPaint() {
- if (layer_)
- layer_->SuppressPaint();
+ if (layer())
+ layer()->SuppressPaint();
}
// {Set,Get,Clear}Property are implemented in window_property.h.
@@ -850,8 +782,8 @@ void* Window::GetNativeWindowProperty(const char* key) const {
void Window::OnDeviceScaleFactorChanged(float device_scale_factor) {
ScopedCursorHider hider(this);
- if (dispatcher_)
- dispatcher_->host()->OnDeviceScaleFactorChanged(device_scale_factor);
+ if (IsRootWindow())
+ host_->OnDeviceScaleFactorChanged(device_scale_factor);
if (delegate_)
delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
}
@@ -863,10 +795,10 @@ std::string Window::GetDebugInfo() const {
name().empty() ? "Unknown" : name().c_str(), id(),
bounds().x(), bounds().y(), bounds().width(), bounds().height(),
visible_ ? "WindowVisible" : "WindowHidden",
- layer_ ?
- (layer_->GetTargetVisibility() ? "LayerVisible" : "LayerHidden") :
+ layer() ?
+ (layer()->GetTargetVisibility() ? "LayerVisible" : "LayerHidden") :
"NoLayer",
- layer_ ? layer_->opacity() : 1.0f);
+ layer() ? layer()->opacity() : 1.0f);
}
void Window::PrintWindowHierarchy(int depth) const {
@@ -928,63 +860,65 @@ int64 Window::GetPropertyInternal(const void* key,
return iter->second.value;
}
-void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
- gfx::Rect actual_new_bounds(new_bounds);
+bool Window::HitTest(const gfx::Point& local_point) {
+ gfx::Rect local_bounds(bounds().size());
+ if (!delegate_ || !delegate_->HasHitTestMask())
+ return local_bounds.Contains(local_point);
- // Ensure we don't go smaller than our minimum bounds.
- if (delegate_) {
- const gfx::Size& min_size = delegate_->GetMinimumSize();
- actual_new_bounds.set_width(
- std::max(min_size.width(), actual_new_bounds.width()));
- actual_new_bounds.set_height(
- std::max(min_size.height(), actual_new_bounds.height()));
- }
+ gfx::Path mask;
+ delegate_->GetHitTestMask(&mask);
+ SkRegion clip_region;
+ clip_region.setRect(local_bounds.x(), local_bounds.y(),
+ local_bounds.width(), local_bounds.height());
+ SkRegion mask_region;
+ return mask_region.setPath(mask, clip_region) &&
+ mask_region.contains(local_point.x(), local_point.y());
+}
+
+void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
+ gfx::Rect actual_new_bounds(new_bounds);
gfx::Rect old_bounds = GetTargetBounds();
// Always need to set the layer's bounds -- even if it is to the same thing.
// This may cause important side effects such as stopping animation.
- if (!layer_) {
+ if (!layer()) {
const gfx::Vector2d origin_delta = new_bounds.OffsetFromOrigin() -
bounds_.OffsetFromOrigin();
bounds_ = new_bounds;
OffsetLayerBounds(origin_delta);
} else {
- if (parent_ && !parent_->layer_) {
+ if (parent_ && !parent_->layer()) {
gfx::Vector2d offset;
const aura::Window* ancestor_with_layer =
parent_->GetAncestorWithLayer(&offset);
if (ancestor_with_layer)
actual_new_bounds.Offset(offset);
}
- layer_->SetBounds(actual_new_bounds);
+ layer()->SetBounds(actual_new_bounds);
}
// If we are currently not the layer's delegate, we will not get bounds
// changed notification from the layer (this typically happens after animating
// hidden). We must notify ourselves.
- if (!layer_ || layer_->delegate() != this)
- OnWindowBoundsChanged(old_bounds, ContainsMouse());
+ if (!layer() || layer()->delegate() != this)
+ OnWindowBoundsChanged(old_bounds);
}
void Window::SetVisible(bool visible) {
- if ((layer_ && visible == layer_->GetTargetVisibility()) ||
- (!layer_ && visible == visible_))
+ if ((layer() && visible == layer()->GetTargetVisibility()) ||
+ (!layer() && visible == visible_))
return; // No change.
FOR_EACH_OBSERVER(WindowObserver, observers_,
OnWindowVisibilityChanging(this, visible));
- WindowEventDispatcher* dispatcher = GetDispatcher();
- if (dispatcher)
- dispatcher->DispatchMouseExitToHidingWindow(this);
-
client::VisibilityClient* visibility_client =
client::GetVisibilityClient(this);
if (visibility_client)
visibility_client->UpdateLayerVisibility(this, visible);
- else if (layer_)
- layer_->SetVisible(visible);
+ else if (layer())
+ layer()->SetVisible(visible);
visible_ = visible;
SchedulePaint();
if (parent_ && parent_->layout_manager_)
@@ -994,9 +928,6 @@ void Window::SetVisible(bool visible) {
delegate_->OnWindowTargetVisibilityChanged(visible);
NotifyWindowVisibilityChanged(this, visible);
-
- if (dispatcher)
- dispatcher->OnWindowVisibilityChanged(this, visible);
}
void Window::SchedulePaint() {
@@ -1012,9 +943,10 @@ void Window::Paint(gfx::Canvas* canvas) {
void Window::PaintLayerlessChildren(gfx::Canvas* canvas) {
for (size_t i = 0, count = children_.size(); i < count; ++i) {
Window* child = children_[i];
- if (!child->layer_ && child->visible_) {
+ if (!child->layer() && child->visible_) {
gfx::ScopedCanvas scoped_canvas(canvas);
- if (canvas->ClipRect(child->bounds())) {
+ canvas->ClipRect(child->bounds());
+ if (!canvas->IsClipEmpty()) {
canvas->Translate(child->bounds().OffsetFromOrigin());
child->Paint(canvas);
}
@@ -1083,15 +1015,12 @@ void Window::RemoveChildImpl(Window* child, Window* new_parent) {
FOR_EACH_OBSERVER(WindowObserver, observers_, OnWillRemoveWindow(child));
Window* root_window = child->GetRootWindow();
Window* new_root_window = new_parent ? new_parent->GetRootWindow() : NULL;
- if (root_window && root_window != new_root_window) {
- root_window->GetDispatcher()->OnWindowRemovedFromRootWindow(
- child, new_root_window);
- child->NotifyRemovingFromRootWindow();
- }
+ if (root_window && root_window != new_root_window)
+ child->NotifyRemovingFromRootWindow(new_root_window);
gfx::Vector2d offset;
GetAncestorWithLayer(&offset);
- child->UnparentLayers(!layer_, offset);
+ child->UnparentLayers(!layer(), offset);
child->parent_ = NULL;
Windows::iterator i = std::find(children_.begin(), children_.end(), child);
DCHECK(i != children_.end());
@@ -1103,7 +1032,7 @@ void Window::RemoveChildImpl(Window* child, Window* new_parent) {
void Window::UnparentLayers(bool has_layerless_ancestor,
const gfx::Vector2d& offset) {
- if (!layer_) {
+ if (!layer()) {
const gfx::Vector2d new_offset = offset + bounds().OffsetFromOrigin();
for (size_t i = 0; i < children_.size(); ++i) {
children_[i]->UnparentLayers(true, new_offset);
@@ -1112,14 +1041,14 @@ void Window::UnparentLayers(bool has_layerless_ancestor,
// Only remove the layer if we still own it. Someone else may have acquired
// ownership of it via AcquireLayer() and may expect the hierarchy to go
// unchanged as the Window is destroyed.
- if (layer_owner_) {
- if (layer_->parent())
- layer_->parent()->Remove(layer_);
+ if (OwnsLayer()) {
+ if (layer()->parent())
+ layer()->parent()->Remove(layer());
if (has_layerless_ancestor) {
const gfx::Rect real_bounds(bounds_);
- gfx::Rect layer_bounds(layer_->bounds());
+ gfx::Rect layer_bounds(layer()->bounds());
layer_bounds.Offset(-offset);
- layer_->SetBounds(layer_bounds);
+ layer()->SetBounds(layer_bounds);
bounds_ = real_bounds;
}
}
@@ -1128,7 +1057,7 @@ void Window::UnparentLayers(bool has_layerless_ancestor,
void Window::ReparentLayers(ui::Layer* parent_layer,
const gfx::Vector2d& offset) {
- if (!layer_) {
+ if (!layer()) {
for (size_t i = 0; i < children_.size(); ++i) {
children_[i]->ReparentLayers(
parent_layer,
@@ -1136,22 +1065,22 @@ void Window::ReparentLayers(ui::Layer* parent_layer,
}
} else {
const gfx::Rect real_bounds(bounds());
- parent_layer->Add(layer_);
- gfx::Rect layer_bounds(layer_->bounds().size());
+ parent_layer->Add(layer());
+ gfx::Rect layer_bounds(layer()->bounds().size());
layer_bounds += offset;
- layer_->SetBounds(layer_bounds);
+ layer()->SetBounds(layer_bounds);
bounds_ = real_bounds;
}
}
void Window::OffsetLayerBounds(const gfx::Vector2d& offset) {
- if (!layer_) {
+ if (!layer()) {
for (size_t i = 0; i < children_.size(); ++i)
children_[i]->OffsetLayerBounds(offset);
} else {
- gfx::Rect layer_bounds(layer_->bounds());
+ gfx::Rect layer_bounds(layer()->bounds());
layer_bounds += offset;
- layer_->SetBounds(layer_bounds);
+ layer()->SetBounds(layer_bounds);
}
}
@@ -1160,34 +1089,6 @@ void Window::OnParentChanged() {
WindowObserver, observers_, OnWindowParentChanged(this, parent_));
}
-bool Window::HasTransientAncestor(const Window* ancestor) const {
- if (transient_parent_ == ancestor)
- return true;
- return transient_parent_ ?
- transient_parent_->HasTransientAncestor(ancestor) : false;
-}
-
-void Window::SkipNullDelegatesForStacking(StackDirection direction,
- Window** target) const {
- DCHECK_EQ(this, (*target)->parent());
- size_t target_i =
- std::find(children_.begin(), children_.end(), *target) -
- children_.begin();
-
- // By convention we don't stack on top of windows with layers with NULL
- // delegates. Walk backward to find a valid target window.
- // See tests WindowTest.StackingMadrigal and StackOverClosingTransient
- // for an explanation of this.
- while (target_i > 0) {
- const size_t index = direction == STACK_ABOVE ? target_i : target_i - 1;
- if (!children_[index]->layer_ ||
- children_[index]->layer_->delegate() != NULL)
- break;
- --target_i;
- }
- *target = children_[target_i];
-}
-
void Window::StackChildRelativeTo(Window* child,
Window* target,
StackDirection direction) {
@@ -1199,47 +1100,10 @@ void Window::StackChildRelativeTo(Window* child,
client::WindowStackingClient* stacking_client =
client::GetWindowStackingClient();
- if (stacking_client)
- stacking_client->AdjustStacking(&child, &target, &direction);
-
- SkipNullDelegatesForStacking(direction, &target);
-
- // If we couldn't find a valid target position, don't move anything.
- if (direction == STACK_ABOVE &&
- (target->layer_ && target->layer_->delegate() == NULL))
+ if (stacking_client &&
+ !stacking_client->AdjustStacking(&child, &target, &direction))
return;
- // Don't try to stack a child above itself.
- if (child == target)
- return;
-
- // Move the child.
- StackChildRelativeToImpl(child, target, direction);
-
- // Stack any transient children that share the same parent to be in front of
- // 'child'. Preserve the existing stacking order by iterating in the order
- // those children appear in children_ array.
- Window* last_transient = child;
- Windows children(children_);
- for (Windows::iterator it = children.begin(); it != children.end(); ++it) {
- Window* transient_child = *it;
- if (transient_child != last_transient &&
- transient_child->HasTransientAncestor(child)) {
- StackChildRelativeToImpl(transient_child, last_transient, STACK_ABOVE);
- last_transient = transient_child;
- }
- }
-}
-
-void Window::StackChildRelativeToImpl(Window* child,
- Window* target,
- StackDirection direction) {
- DCHECK_NE(child, target);
- DCHECK(child);
- DCHECK(target);
- DCHECK_EQ(this, child->parent());
- DCHECK_EQ(this, target->parent());
-
const size_t child_i =
std::find(children_.begin(), children_.end(), child) - children_.begin();
const size_t target_i =
@@ -1271,11 +1135,11 @@ void Window::StackChildLayerRelativeTo(Window* child,
if (!ancestor_layer)
return;
- if (child->layer_ && target->layer_) {
+ if (child->layer() && target->layer()) {
if (direction == STACK_ABOVE)
- ancestor_layer->StackAbove(child->layer_, target->layer_);
+ ancestor_layer->StackAbove(child->layer(), target->layer());
else
- ancestor_layer->StackBelow(child->layer_, target->layer_);
+ ancestor_layer->StackBelow(child->layer(), target->layer());
return;
}
typedef std::vector<ui::Layer*> Layers;
@@ -1295,8 +1159,8 @@ void Window::StackChildLayerRelativeTo(Window* child,
if (!target_layer) {
if (direction == STACK_ABOVE) {
- for (Layers::const_reverse_iterator i = layers.rbegin();
- i != layers.rend(); ++i) {
+ for (Layers::const_reverse_iterator i = layers.rbegin(),
+ rend = layers.rend(); i != rend; ++i) {
ancestor_layer->StackAtBottom(*i);
}
} else {
@@ -1307,8 +1171,8 @@ void Window::StackChildLayerRelativeTo(Window* child,
}
if (direction == STACK_ABOVE) {
- for (Layers::const_reverse_iterator i = layers.rbegin();
- i != layers.rend(); ++i) {
+ for (Layers::const_reverse_iterator i = layers.rbegin(),
+ rend = layers.rend(); i != rend; ++i) {
ancestor_layer->StackAbove(*i, target_layer);
}
} else {
@@ -1321,12 +1185,12 @@ void Window::OnStackingChanged() {
FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowStackingChanged(this));
}
-void Window::NotifyRemovingFromRootWindow() {
+void Window::NotifyRemovingFromRootWindow(Window* new_root) {
FOR_EACH_OBSERVER(WindowObserver, observers_,
- OnWindowRemovingFromRootWindow(this));
+ OnWindowRemovingFromRootWindow(this, new_root));
for (Window::Windows::const_iterator it = children_.begin();
it != children_.end(); ++it) {
- (*it)->NotifyRemovingFromRootWindow();
+ (*it)->NotifyRemovingFromRootWindow(new_root);
}
}
@@ -1443,11 +1307,10 @@ void Window::NotifyWindowVisibilityChangedUp(aura::Window* target,
}
}
-void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds,
- bool contained_mouse) {
- if (layer_) {
- bounds_ = layer_->bounds();
- if (parent_ && !parent_->layer_) {
+void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds) {
+ if (layer()) {
+ bounds_ = layer()->bounds();
+ if (parent_ && !parent_->layer()) {
gfx::Vector2d offset;
aura::Window* ancestor_with_layer =
parent_->GetAncestorWithLayer(&offset);
@@ -1463,9 +1326,19 @@ void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds,
FOR_EACH_OBSERVER(WindowObserver,
observers_,
OnWindowBoundsChanged(this, old_bounds, bounds()));
- WindowEventDispatcher* dispatcher = GetDispatcher();
- if (dispatcher)
- dispatcher->OnWindowBoundsChanged(this, contained_mouse);
+}
+
+bool Window::CleanupGestureState() {
+ bool state_modified = false;
+ state_modified |= ui::GestureRecognizer::Get()->CancelActiveTouches(this);
+ state_modified |=
+ ui::GestureRecognizer::Get()->CleanupStateForConsumer(this);
+ for (Window::Windows::iterator iter = children_.begin();
+ iter != children_.end();
+ ++iter) {
+ state_modified |= (*iter)->CleanupGestureState();
+ }
+ return state_modified;
}
void Window::OnPaintLayer(gfx::Canvas* canvas) {
@@ -1474,7 +1347,7 @@ void Window::OnPaintLayer(gfx::Canvas* canvas) {
base::Closure Window::PrepareForLayerBoundsChange() {
return base::Bind(&Window::OnWindowBoundsChanged, base::Unretained(this),
- bounds(), ContainsMouse());
+ bounds());
}
bool Window::CanAcceptEvent(const ui::Event& event) {
@@ -1498,13 +1371,14 @@ bool Window::CanAcceptEvent(const ui::Event& event) {
return true;
// For located events (i.e. mouse, touch etc.), an assumption is made that
- // windows that don't have a delegate cannot process the event (see more in
- // GetWindowForPoint()). This assumption is not made for key events.
- return event.IsKeyEvent() || delegate_;
+ // windows that don't have a default event-handler cannot process the event
+ // (see more in GetWindowForPoint()). This assumption is not made for key
+ // events.
+ return event.IsKeyEvent() || target_handler();
}
ui::EventTarget* Window::GetParentTarget() {
- if (dispatcher_) {
+ if (IsRootWindow()) {
return client::GetEventClient(this) ?
client::GetEventClient(this)->GetToplevelEventTarget() :
Env::GetInstance();
@@ -1527,9 +1401,9 @@ void Window::ConvertEventToTarget(ui::EventTarget* target,
static_cast<Window*>(target));
}
-void Window::UpdateLayerName(const std::string& name) {
+void Window::UpdateLayerName() {
#if !defined(NDEBUG)
- DCHECK(layer_);
+ DCHECK(layer());
std::string layer_name(name_);
if (layer_name.empty())
@@ -1538,23 +1412,23 @@ void Window::UpdateLayerName(const std::string& name) {
if (id_ != -1)
layer_name += " " + base::IntToString(id_);
- layer_->set_name(layer_name);
+ layer()->set_name(layer_name);
#endif
}
bool Window::ContainsMouse() {
bool contains_mouse = false;
if (IsVisible()) {
- WindowEventDispatcher* dispatcher = GetDispatcher();
- contains_mouse = dispatcher &&
- ContainsPointInRoot(dispatcher->GetLastMouseLocationInRoot());
+ WindowTreeHost* host = GetHost();
+ contains_mouse = host &&
+ ContainsPointInRoot(host->dispatcher()->GetLastMouseLocationInRoot());
}
return contains_mouse;
}
const Window* Window::GetAncestorWithLayer(gfx::Vector2d* offset) const {
for (const aura::Window* window = this; window; window = window->parent()) {
- if (window->layer_)
+ if (window->layer())
return window;
if (offset)
*offset += window->bounds().OffsetFromOrigin();
diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h
index d69d88e0089..bc970f4a1f5 100644
--- a/chromium/ui/aura/window.h
+++ b/chromium/ui/aura/window.h
@@ -15,13 +15,11 @@
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "ui/aura/aura_export.h"
-#include "ui/aura/client/window_types.h"
#include "ui/aura/window_layer_type.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/layer_delegate.h"
#include "ui/compositor/layer_owner.h"
-#include "ui/compositor/layer_type.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_target.h"
#include "ui/events/event_targeter.h"
@@ -29,6 +27,7 @@
#include "ui/gfx/insets.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
+#include "ui/wm/public/window_types.h"
namespace gfx {
class Display;
@@ -45,12 +44,9 @@ class Texture;
namespace aura {
class LayoutManager;
-class RootWindow;
class WindowDelegate;
class WindowObserver;
-
-// TODO(beng): remove once RootWindow is renamed.
-typedef RootWindow WindowEventDispatcher;
+class WindowTreeHost;
// Defined in window_property.h (which we do not include)
template<typename T>
@@ -80,17 +76,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
virtual ~Window();
// Initializes the window. This creates the window's layer.
- void Init(ui::LayerType layer_type);
-
- // TODO(sky): replace other Init() with this once m32 is more baked.
- void InitWithWindowLayerType(WindowLayerType layer_type);
-
- // Creates a new layer for the window. Erases the layer-owned bounds, so the
- // caller may wish to set new bounds and other state on the window/layer.
- // Returns the old layer, which can be used for animations. Caller owns the
- // memory for the returned layer and must delete it when animation completes.
- // Returns NULL and does not recreate layer if window does not own its layer.
- ui::Layer* RecreateLayer() WARN_UNUSED_RESULT;
+ void Init(WindowLayerType layer_type);
void set_owned_by_parent(bool owned_by_parent) {
owned_by_parent_ = owned_by_parent;
@@ -100,8 +86,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// A type is used to identify a class of Windows and customize behavior such
// as event handling and parenting. This field should only be consumed by the
// shell -- Aura itself shouldn't contain type-specific logic.
- client::WindowType type() const { return type_; }
- void SetType(client::WindowType type);
+ ui::wm::WindowType type() const { return type_; }
+ void SetType(ui::wm::WindowType type);
int id() const { return id_; }
void set_id(int id) { id_ = id; }
@@ -115,6 +101,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
bool transparent() const { return transparent_; }
void SetTransparent(bool transparent);
+ // See description in Layer::SetFillsBoundsCompletely.
+ void SetFillsBoundsCompletely(bool fills_bounds);
+
WindowDelegate* delegate() { return delegate_; }
const WindowDelegate* delegate() const { return delegate_; }
@@ -127,15 +116,13 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// defined as the Window that has a dispatcher. These functions return NULL if
// the Window is contained in a hierarchy that does not have a dispatcher at
// its root.
- virtual Window* GetRootWindow();
- virtual const Window* GetRootWindow() const;
+ Window* GetRootWindow();
+ const Window* GetRootWindow() const;
- WindowEventDispatcher* GetDispatcher();
- const WindowEventDispatcher* GetDispatcher() const;
- void set_dispatcher(WindowEventDispatcher* dispatcher) {
- dispatcher_ = dispatcher;
- }
- bool HasDispatcher() const { return !!dispatcher_; }
+ WindowTreeHost* GetHost();
+ const WindowTreeHost* GetHost() const;
+ void set_host(WindowTreeHost* host) { host_ = host; }
+ bool IsRootWindow() const { return !!host_; }
// The Window does not own this object.
void set_user_data(void* user_data) { user_data_ = user_data; }
@@ -160,16 +147,17 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// |aura::client::ScreenPositionClient| interface.
gfx::Rect GetBoundsInScreen() const;
- virtual void SetTransform(const gfx::Transform& transform);
+ void SetTransform(const gfx::Transform& transform);
// Assigns a LayoutManager to size and place child windows.
// The Window takes ownership of the LayoutManager.
void SetLayoutManager(LayoutManager* layout_manager);
LayoutManager* layout_manager() { return layout_manager_.get(); }
- void set_event_targeter(scoped_ptr<ui::EventTargeter> targeter) {
- targeter_ = targeter.Pass();
- }
+ // Sets a new event-targeter for the window, and returns the previous
+ // event-targeter.
+ scoped_ptr<ui::EventTargeter> SetEventTargeter(
+ scoped_ptr<ui::EventTargeter> targeter);
// Changes the bounds of the window. If present, the window's parent's
// LayoutManager may adjust the bounds.
@@ -211,22 +199,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Returns true if this Window contains |other| somewhere in its children.
bool Contains(const Window* other) const;
- // Adds or removes |child| as a transient child of this window. Transient
- // children get the following behavior:
- // . The transient parent destroys any transient children when it is
- // destroyed. This means a transient child is destroyed if either its parent
- // or transient parent is destroyed.
- // . If a transient child and its transient parent share the same parent, then
- // transient children are always ordered above the transient parent.
- // Transient windows are typically used for popups and menus.
- void AddTransientChild(Window* child);
- void RemoveTransientChild(Window* child);
-
- const Windows& transient_children() const { return transient_children_; }
-
- Window* transient_parent() { return transient_parent_; }
- const Window* transient_parent() const { return transient_parent_; }
-
// Retrieves the first-level child with the specified id, or NULL if no first-
// level child is found matching |id|.
Window* GetChildById(int id);
@@ -238,19 +210,16 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
static void ConvertPointToTarget(const Window* source,
const Window* target,
gfx::Point* point);
+ static void ConvertRectToTarget(const Window* source,
+ const Window* target,
+ gfx::Rect* rect);
// Moves the cursor to the specified location relative to the window.
- virtual void MoveCursorTo(const gfx::Point& point_in_window);
+ void MoveCursorTo(const gfx::Point& point_in_window);
// Returns the cursor for the specified point, in window coordinates.
gfx::NativeCursor GetCursor(const gfx::Point& point) const;
- // Sets an 'event filter' for the window. An 'event filter' for a Window is
- // a pre-target event handler, where the window owns the handler. A window
- // can have only one such event filter. Setting a new filter removes and
- // destroys any previously installed filter.
- void SetEventFilter(ui::EventHandler* event_filter);
-
// Add/remove observer.
void AddObserver(WindowObserver* observer);
void RemoveObserver(WindowObserver* observer);
@@ -259,24 +228,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
void set_ignore_events(bool ignore_events) { ignore_events_ = ignore_events; }
bool ignore_events() const { return ignore_events_; }
- // Sets the window to grab hits for mouse and touch to an area extending
- // -|mouse_insets| and -|touch_insets| pixels outside its bounds. This can be
- // used to create an invisible non-client area, for example if your windows
- // have no visible frames but still need to have resize edges.
- void SetHitTestBoundsOverrideOuter(const gfx::Insets& mouse_insets,
- const gfx::Insets& touch_insets) {
- hit_test_bounds_override_outer_mouse_ = mouse_insets;
- hit_test_bounds_override_outer_touch_ = touch_insets;
- }
-
- gfx::Insets hit_test_bounds_override_outer_touch() const {
- return hit_test_bounds_override_outer_touch_;
- }
-
- gfx::Insets hit_test_bounds_override_outer_mouse() const {
- return hit_test_bounds_override_outer_mouse_;
- }
-
// Sets the window to grab hits for an area extending |insets| pixels inside
// its bounds (even if that inner region overlaps a child window). This can be
// used to create an invisible non-client area that overlaps the client area.
@@ -296,13 +247,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// within this Window's bounds.
bool ContainsPoint(const gfx::Point& local_point) const;
- // Returns true if the mouse pointer at relative-to-this-Window's-origin
- // |local_point| can trigger an event for this Window.
- // TODO(beng): A Window can supply a hit-test mask to cause some portions of
- // itself to not trigger events, causing the events to fall through to the
- // Window behind.
- bool HitTest(const gfx::Point& local_point);
-
// Returns the Window that most closely encloses |local_point| for the
// purposes of event targeting.
Window* GetEventHandlerForPoint(const gfx::Point& local_point);
@@ -322,10 +266,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
bool HasFocus() const;
// Returns true if the Window can be focused.
- virtual bool CanFocus() const;
+ bool CanFocus() const;
// Returns true if the Window can receive events.
- virtual bool CanReceiveEvents() const;
+ bool CanReceiveEvents() const;
// Does a capture on the window. This does nothing if the window isn't showing
// (VISIBILITY_SHOWN) or isn't contained in a valid window hierarchy.
@@ -376,6 +320,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
void PrintWindowHierarchy(int depth) const;
#endif
+ // Returns true if there was state needing to be cleaned up.
+ bool CleanupGestureState();
+
protected:
// Deletes (or removes if not owned by parent) all child windows. Intended for
// use from the destructor.
@@ -384,7 +331,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
private:
friend class test::WindowTestApi;
friend class LayoutManager;
- friend class RootWindow;
friend class WindowTargeter;
// Called by the public {Set,Get,Clear}Property functions.
@@ -395,6 +341,13 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
int64 default_value);
int64 GetPropertyInternal(const void* key, int64 default_value) const;
+ // Returns true if the mouse pointer at relative-to-this-Window's-origin
+ // |local_point| can trigger an event for this Window.
+ // TODO(beng): A Window can supply a hit-test mask to cause some portions of
+ // itself to not trigger events, causing the events to fall through to the
+ // Window behind.
+ bool HitTest(const gfx::Point& local_point);
+
// Changes the bounds of the window without condition.
void SetBoundsInternal(const gfx::Rect& new_bounds);
@@ -445,26 +398,12 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Called when this window's parent has changed.
void OnParentChanged();
- // Returns true when |ancestor| is a transient ancestor of |this|.
- bool HasTransientAncestor(const Window* ancestor) const;
-
- // Adjusts |target| so that we don't attempt to stack on top of a window with
- // a NULL delegate. See implementation for details.
- void SkipNullDelegatesForStacking(StackDirection direction,
- Window** target) const;
-
- // Determines the real location for stacking |child| and invokes
- // StackChildRelativeToImpl().
+ // The various stacking functions call into this to do the actual stacking.
void StackChildRelativeTo(Window* child,
Window* target,
StackDirection direction);
- // Implementation of StackChildRelativeTo().
- void StackChildRelativeToImpl(Window* child,
- Window* target,
- StackDirection direction);
-
- // Invoked from StackChildRelativeToImpl() to stack the layers appropriately
+ // Invoked from StackChildRelativeTo() to stack the layers appropriately
// when stacking |child| relative to |target|.
void StackChildLayerRelativeTo(Window* child,
Window* target,
@@ -475,7 +414,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Notifies observers registered with this Window (and its subtree) when the
// Window has been added or is about to be removed from a RootWindow.
- void NotifyRemovingFromRootWindow();
+ void NotifyRemovingFromRootWindow(Window* new_root);
void NotifyAddedToRootWindow();
// Methods implementing hierarchy change notifications. See WindowObserver for
@@ -508,10 +447,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Invoked when the bounds of the window changes. This may be invoked directly
// by us, or from the closure returned by PrepareForLayerBoundsChange() after
- // the bounds of the layer has changed. |old_bounds| is the previous bounds,
- // and |contained_mouse| is true if the mouse was previously within the
- // window's bounds.
- void OnWindowBoundsChanged(const gfx::Rect& old_bounds, bool contained_mouse);
+ // the bounds of the layer has changed. |old_bounds| is the previous bounds.
+ void OnWindowBoundsChanged(const gfx::Rect& old_bounds);
// Overridden from ui::LayerDelegate:
virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
@@ -525,8 +462,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
virtual void ConvertEventToTarget(ui::EventTarget* target,
ui::LocatedEvent* event) OVERRIDE;
- // Updates the layer name with a name based on the window's name and id.
- void UpdateLayerName(const std::string& name);
+ // Updates the layer name based on the window's name and id.
+ void UpdateLayerName();
// Returns true if the mouse is currently within our bounds.
bool ContainsMouse();
@@ -546,9 +483,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// is relative to the parent Window.
gfx::Rect bounds_;
- WindowEventDispatcher* dispatcher_;
+ WindowTreeHost* host_;
- client::WindowType type_;
+ ui::wm::WindowType type_;
// True if the Window is owned by its parent - i.e. it will be deleted by its
// parent during its parents destruction. True is the default.
@@ -562,11 +499,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Child windows. Topmost is last.
Windows children_;
- // Transient windows.
- Windows transient_children_;
-
- Window* transient_parent_;
-
// The visibility state of the window as set by Show()/Hide(). This may differ
// from the visibility of the underlying layer, which may remain visible after
// the window is hidden (e.g. to animate its disappearance).
@@ -580,7 +512,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Whether layer is initialized as non-opaque.
bool transparent_;
- scoped_ptr<ui::EventHandler> event_filter_;
scoped_ptr<LayoutManager> layout_manager_;
scoped_ptr<ui::EventTargeter> targeter_;
@@ -589,9 +520,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Makes the window pass all events through to any windows behind it.
bool ignore_events_;
- // See set_hit_test_outer_override().
- gfx::Insets hit_test_bounds_override_outer_mouse_;
- gfx::Insets hit_test_bounds_override_outer_touch_;
+ // See set_hit_test_bounds_override_inner().
gfx::Insets hit_test_bounds_override_inner_;
ObserverList<WindowObserver, true> observers_;
diff --git a/chromium/ui/aura/window_delegate.h b/chromium/ui/aura/window_delegate.h
index ff941ef95b3..90e978a39c2 100644
--- a/chromium/ui/aura/window_delegate.h
+++ b/chromium/ui/aura/window_delegate.h
@@ -73,13 +73,17 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler {
// Called from Window's destructor before OnWindowDestroyed and before the
// children have been destroyed and the window has been removed from its
// parent.
- virtual void OnWindowDestroying() = 0;
+ // This method takes the window because the delegate implementation may no
+ // longer have a route back to the window by the time this method is called.
+ virtual void OnWindowDestroying(Window* window) = 0;
// Called when the Window has been destroyed (i.e. from its destructor). This
// is called after OnWindowDestroying and after the children have been
// deleted and the window has been removed from its parent.
// The delegate can use this as an opportunity to delete itself if necessary.
- virtual void OnWindowDestroyed() = 0;
+ // This method takes the window because the delegate implementation may no
+ // longer have a route back to the window by the time this method is called.
+ virtual void OnWindowDestroyed(Window* window) = 0;
// Called when the TargetVisibility() of a Window changes. |visible|
// corresponds to the target visibility of the window. See
@@ -96,13 +100,6 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler {
// above returns true.
virtual void GetHitTestMask(gfx::Path* mask) const = 0;
- // Called from RecreateLayer() after the new layer was created. old_layer is
- // the layer that will be returned to the caller of RecreateLayer, new_layer
- // will be the layer now used on the Window. The implementation only has to do
- // anything if the layer has external content (SetExternalTexture /
- // SetTextureMailbox / SetDelegatedFrame was called).
- virtual void DidRecreateLayer(ui::Layer* old_layer, ui::Layer* new_layer) = 0;
-
protected:
virtual ~WindowDelegate() {}
};
diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc
new file mode 100644
index 00000000000..87d25b1cfd8
--- /dev/null
+++ b/chromium/ui/aura/window_event_dispatcher.cc
@@ -0,0 +1,861 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/window_event_dispatcher.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "ui/aura/client/capture_client.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/client/event_client.h"
+#include "ui/aura/client/focus_client.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
+#include "ui/aura/window_targeter.h"
+#include "ui/aura/window_tracker.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/hit_test.h"
+#include "ui/compositor/dip_util.h"
+#include "ui/events/event.h"
+#include "ui/events/gestures/gesture_recognizer.h"
+#include "ui/events/gestures/gesture_types.h"
+
+typedef ui::EventDispatchDetails DispatchDetails;
+
+namespace aura {
+
+namespace {
+
+// Returns true if |target| has a non-client (frame) component at |location|,
+// in window coordinates.
+bool IsNonClientLocation(Window* target, const gfx::Point& location) {
+ if (!target->delegate())
+ return false;
+ int hit_test_code = target->delegate()->GetNonClientComponent(location);
+ return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE;
+}
+
+Window* ConsumerToWindow(ui::GestureConsumer* consumer) {
+ return consumer ? static_cast<Window*>(consumer) : NULL;
+}
+
+void SetLastMouseLocation(const Window* root_window,
+ const gfx::Point& location_in_root) {
+ client::ScreenPositionClient* client =
+ client::GetScreenPositionClient(root_window);
+ if (client) {
+ gfx::Point location_in_screen = location_in_root;
+ client->ConvertPointToScreen(root_window, &location_in_screen);
+ Env::GetInstance()->set_last_mouse_location(location_in_screen);
+ } else {
+ Env::GetInstance()->set_last_mouse_location(location_in_root);
+ }
+}
+
+bool IsEventCandidateForHold(const ui::Event& event) {
+ if (event.type() == ui::ET_TOUCH_MOVED)
+ return true;
+ if (event.type() == ui::ET_MOUSE_DRAGGED)
+ return true;
+ if (event.IsMouseEvent() && (event.flags() & ui::EF_IS_SYNTHESIZED))
+ return true;
+ return false;
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, public:
+
+WindowEventDispatcher::WindowEventDispatcher(WindowTreeHost* host)
+ : host_(host),
+ touch_ids_down_(0),
+ mouse_pressed_handler_(NULL),
+ mouse_moved_handler_(NULL),
+ event_dispatch_target_(NULL),
+ old_dispatch_target_(NULL),
+ synthesize_mouse_move_(false),
+ move_hold_count_(0),
+ dispatching_held_event_(false),
+ observer_manager_(this),
+ repost_event_factory_(this),
+ held_event_factory_(this) {
+ ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
+ Env::GetInstance()->AddObserver(this);
+}
+
+WindowEventDispatcher::~WindowEventDispatcher() {
+ TRACE_EVENT0("shutdown", "WindowEventDispatcher::Destructor");
+ Env::GetInstance()->RemoveObserver(this);
+ ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
+}
+
+void WindowEventDispatcher::RepostEvent(const ui::LocatedEvent& event) {
+ DCHECK(event.type() == ui::ET_MOUSE_PRESSED ||
+ event.type() == ui::ET_GESTURE_TAP_DOWN);
+ // We allow for only one outstanding repostable event. This is used
+ // in exiting context menus. A dropped repost request is allowed.
+ if (event.type() == ui::ET_MOUSE_PRESSED) {
+ held_repostable_event_.reset(
+ new ui::MouseEvent(
+ static_cast<const ui::MouseEvent&>(event),
+ static_cast<aura::Window*>(event.target()),
+ window()));
+ base::MessageLoop::current()->PostNonNestableTask(
+ FROM_HERE, base::Bind(
+ base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents),
+ repost_event_factory_.GetWeakPtr()));
+ } else {
+ DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN);
+ held_repostable_event_.reset();
+ // TODO(rbyers): Reposing of gestures is tricky to get
+ // right, so it's not yet supported. crbug.com/170987.
+ }
+}
+
+void WindowEventDispatcher::OnMouseEventsEnableStateChanged(bool enabled) {
+ // Send entered / exited so that visual state can be updated to match
+ // mouse events state.
+ PostSynthesizeMouseMove();
+ // TODO(mazda): Add code to disable mouse events when |enabled| == false.
+}
+
+void WindowEventDispatcher::DispatchCancelModeEvent() {
+ ui::CancelModeEvent event;
+ Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow();
+ if (focused_window && !window()->Contains(focused_window))
+ focused_window = NULL;
+ DispatchDetails details =
+ DispatchEvent(focused_window ? focused_window : window(), &event);
+ if (details.dispatcher_destroyed)
+ return;
+}
+
+void WindowEventDispatcher::DispatchGestureEvent(ui::GestureEvent* event) {
+ DispatchDetails details = DispatchHeldEvents();
+ if (details.dispatcher_destroyed)
+ return;
+
+ Window* target = GetGestureTarget(event);
+ if (target) {
+ event->ConvertLocationToTarget(window(), target);
+ DispatchDetails details = DispatchEvent(target, event);
+ if (details.dispatcher_destroyed)
+ return;
+ }
+}
+
+void WindowEventDispatcher::DispatchMouseExitAtPoint(const gfx::Point& point) {
+ ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE,
+ ui::EF_NONE);
+ DispatchDetails details =
+ DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
+ if (details.dispatcher_destroyed)
+ return;
+}
+
+void WindowEventDispatcher::ProcessedTouchEvent(ui::TouchEvent* event,
+ Window* window,
+ ui::EventResult result) {
+ scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
+ gestures.reset(ui::GestureRecognizer::Get()->
+ ProcessTouchEventForGesture(*event, result, window));
+ DispatchDetails details = ProcessGestures(gestures.get());
+ if (details.dispatcher_destroyed)
+ return;
+}
+
+void WindowEventDispatcher::HoldPointerMoves() {
+ if (!move_hold_count_)
+ held_event_factory_.InvalidateWeakPtrs();
+ ++move_hold_count_;
+ TRACE_EVENT_ASYNC_BEGIN0("ui", "WindowEventDispatcher::HoldPointerMoves",
+ this);
+}
+
+void WindowEventDispatcher::ReleasePointerMoves() {
+ --move_hold_count_;
+ DCHECK_GE(move_hold_count_, 0);
+ if (!move_hold_count_ && held_move_event_) {
+ // We don't want to call DispatchHeldEvents directly, because this might be
+ // called from a deep stack while another event, in which case dispatching
+ // another one may not be safe/expected. Instead we post a task, that we
+ // may cancel if HoldPointerMoves is called again before it executes.
+ base::MessageLoop::current()->PostNonNestableTask(
+ FROM_HERE, base::Bind(
+ base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents),
+ held_event_factory_.GetWeakPtr()));
+ }
+ TRACE_EVENT_ASYNC_END0("ui", "WindowEventDispatcher::HoldPointerMoves", this);
+}
+
+gfx::Point WindowEventDispatcher::GetLastMouseLocationInRoot() const {
+ gfx::Point location = Env::GetInstance()->last_mouse_location();
+ client::ScreenPositionClient* client =
+ client::GetScreenPositionClient(window());
+ if (client)
+ client->ConvertPointFromScreen(window(), &location);
+ return location;
+}
+
+void WindowEventDispatcher::OnHostLostMouseGrab() {
+ mouse_pressed_handler_ = NULL;
+ mouse_moved_handler_ = NULL;
+}
+
+void WindowEventDispatcher::OnCursorMovedToRootLocation(
+ const gfx::Point& root_location) {
+ SetLastMouseLocation(window(), root_location);
+ synthesize_mouse_move_ = false;
+}
+
+void WindowEventDispatcher::OnPostNotifiedWindowDestroying(Window* window) {
+ OnWindowHidden(window, WINDOW_DESTROYED);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, private:
+
+Window* WindowEventDispatcher::window() {
+ return host_->window();
+}
+
+const Window* WindowEventDispatcher::window() const {
+ return host_->window();
+}
+
+void WindowEventDispatcher::TransformEventForDeviceScaleFactor(
+ ui::LocatedEvent* event) {
+ event->UpdateForRootTransform(host_->GetInverseRootTransform());
+}
+
+void WindowEventDispatcher::DispatchMouseExitToHidingWindow(Window* window) {
+ // The mouse capture is intentionally ignored. Think that a mouse enters
+ // to a window, the window sets the capture, the mouse exits the window,
+ // and then it releases the capture. In that case OnMouseExited won't
+ // be called. So it is natural not to emit OnMouseExited even though
+ // |window| is the capture window.
+ gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
+ if (window->Contains(mouse_moved_handler_) &&
+ window->ContainsPointInRoot(last_mouse_location))
+ DispatchMouseExitAtPoint(last_mouse_location);
+}
+
+ui::EventDispatchDetails WindowEventDispatcher::DispatchMouseEnterOrExit(
+ const ui::MouseEvent& event,
+ ui::EventType type) {
+ if (event.type() != ui::ET_MOUSE_CAPTURE_CHANGED &&
+ !(event.flags() & ui::EF_IS_SYNTHESIZED)) {
+ SetLastMouseLocation(window(), event.root_location());
+ }
+
+ if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate() ||
+ !window()->Contains(mouse_moved_handler_))
+ return DispatchDetails();
+
+ // |event| may be an event in the process of being dispatched to a target (in
+ // which case its locations will be in the event's target's coordinate
+ // system), or a synthetic event created in root-window (in which case, the
+ // event's target will be NULL, and the event will be in the root-window's
+ // coordinate system.
+ aura::Window* target = static_cast<Window*>(event.target());
+ if (!target)
+ target = window();
+ ui::MouseEvent translated_event(event,
+ target,
+ mouse_moved_handler_,
+ type,
+ event.flags() | ui::EF_IS_SYNTHESIZED);
+ return DispatchEvent(mouse_moved_handler_, &translated_event);
+}
+
+ui::EventDispatchDetails WindowEventDispatcher::ProcessGestures(
+ ui::GestureRecognizer::Gestures* gestures) {
+ DispatchDetails details;
+ if (!gestures || gestures->empty())
+ return details;
+
+ Window* target = GetGestureTarget(gestures->get().at(0));
+ for (size_t i = 0; i < gestures->size(); ++i) {
+ ui::GestureEvent* event = gestures->get().at(i);
+ event->ConvertLocationToTarget(window(), target);
+ details = DispatchEvent(target, event);
+ if (details.dispatcher_destroyed || details.target_destroyed)
+ break;
+ }
+ return details;
+}
+
+void WindowEventDispatcher::OnWindowHidden(Window* invisible,
+ WindowHiddenReason reason) {
+ // If the window the mouse was pressed in becomes invisible, it should no
+ // longer receive mouse events.
+ if (invisible->Contains(mouse_pressed_handler_))
+ mouse_pressed_handler_ = NULL;
+ if (invisible->Contains(mouse_moved_handler_))
+ mouse_moved_handler_ = NULL;
+
+ // If events are being dispatched from a nested message-loop, and the target
+ // of the outer loop is hidden or moved to another dispatcher during
+ // dispatching events in the inner loop, then reset the target for the outer
+ // loop.
+ if (invisible->Contains(old_dispatch_target_))
+ old_dispatch_target_ = NULL;
+
+ invisible->CleanupGestureState();
+
+ // Do not clear the capture, and the |event_dispatch_target_| if the
+ // window is moving across hosts, because the target itself is actually still
+ // visible and clearing them stops further event processing, which can cause
+ // unexpected behaviors. See crbug.com/157583
+ if (reason != WINDOW_MOVING) {
+ // We don't ask |invisible| here, because invisible may have been removed
+ // from the window hierarchy already by the time this function is called
+ // (OnWindowDestroyed).
+ client::CaptureClient* capture_client =
+ client::GetCaptureClient(host_->window());
+ Window* capture_window =
+ capture_client ? capture_client->GetCaptureWindow() : NULL;
+
+ if (invisible->Contains(event_dispatch_target_))
+ event_dispatch_target_ = NULL;
+
+ // If the ancestor of the capture window is hidden, release the capture.
+ // Note that this may delete the window so do not use capture_window
+ // after this.
+ if (invisible->Contains(capture_window) && invisible != window())
+ capture_window->ReleaseCapture();
+ }
+}
+
+Window* WindowEventDispatcher::GetGestureTarget(ui::GestureEvent* event) {
+ Window* target = NULL;
+ if (!event->IsEndingEvent()) {
+ // The window that received the start event (e.g. scroll begin) needs to
+ // receive the end event (e.g. scroll end).
+ target = client::GetCaptureWindow(window());
+ }
+ if (!target) {
+ target = ConsumerToWindow(
+ ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event));
+ }
+
+ return target;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, aura::client::CaptureDelegate implementation:
+
+void WindowEventDispatcher::UpdateCapture(Window* old_capture,
+ Window* new_capture) {
+ // |mouse_moved_handler_| may have been set to a Window in a different root
+ // (see below). Clear it here to ensure we don't end up referencing a stale
+ // Window.
+ if (mouse_moved_handler_ && !window()->Contains(mouse_moved_handler_))
+ mouse_moved_handler_ = NULL;
+
+ if (old_capture && old_capture->GetRootWindow() == window() &&
+ old_capture->delegate()) {
+ // Send a capture changed event with bogus location data.
+ ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(),
+ gfx::Point(), 0, 0);
+
+ DispatchDetails details = DispatchEvent(old_capture, &event);
+ if (details.dispatcher_destroyed)
+ return;
+
+ old_capture->delegate()->OnCaptureLost();
+ }
+
+ if (new_capture) {
+ // Make all subsequent mouse events go to the capture window. We shouldn't
+ // need to send an event here as OnCaptureLost() should take care of that.
+ if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown())
+ mouse_moved_handler_ = new_capture;
+ } else {
+ // Make sure mouse_moved_handler gets updated.
+ DispatchDetails details = SynthesizeMouseMoveEvent();
+ if (details.dispatcher_destroyed)
+ return;
+ }
+ mouse_pressed_handler_ = NULL;
+}
+
+void WindowEventDispatcher::OnOtherRootGotCapture() {
+ mouse_moved_handler_ = NULL;
+ mouse_pressed_handler_ = NULL;
+}
+
+void WindowEventDispatcher::SetNativeCapture() {
+ host_->SetCapture();
+}
+
+void WindowEventDispatcher::ReleaseNativeCapture() {
+ host_->ReleaseCapture();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, ui::EventProcessor implementation:
+ui::EventTarget* WindowEventDispatcher::GetRootTarget() {
+ return window();
+}
+
+void WindowEventDispatcher::PrepareEventForDispatch(ui::Event* event) {
+ if (dispatching_held_event_) {
+ // The held events are already in |window()|'s coordinate system. So it is
+ // not necessary to apply the transform to convert from the host's
+ // coordinate system to |window()|'s coordinate system.
+ return;
+ }
+ if (event->IsMouseEvent() ||
+ event->IsScrollEvent() ||
+ event->IsTouchEvent() ||
+ event->IsGestureEvent()) {
+ TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, ui::EventDispatcherDelegate implementation:
+
+bool WindowEventDispatcher::CanDispatchToTarget(ui::EventTarget* target) {
+ return event_dispatch_target_ == target;
+}
+
+ui::EventDispatchDetails WindowEventDispatcher::PreDispatchEvent(
+ ui::EventTarget* target,
+ ui::Event* event) {
+ Window* target_window = static_cast<Window*>(target);
+ CHECK(window()->Contains(target_window));
+
+ if (!dispatching_held_event_) {
+ bool can_be_held = IsEventCandidateForHold(*event);
+ if (!move_hold_count_ || !can_be_held) {
+ if (can_be_held)
+ held_move_event_.reset();
+ DispatchDetails details = DispatchHeldEvents();
+ if (details.dispatcher_destroyed || details.target_destroyed)
+ return details;
+ }
+ }
+
+ if (event->IsMouseEvent()) {
+ PreDispatchMouseEvent(target_window, static_cast<ui::MouseEvent*>(event));
+ } else if (event->IsScrollEvent()) {
+ PreDispatchLocatedEvent(target_window,
+ static_cast<ui::ScrollEvent*>(event));
+ } else if (event->IsTouchEvent()) {
+ PreDispatchTouchEvent(target_window, static_cast<ui::TouchEvent*>(event));
+ }
+ old_dispatch_target_ = event_dispatch_target_;
+ event_dispatch_target_ = static_cast<Window*>(target);
+ return DispatchDetails();
+}
+
+ui::EventDispatchDetails WindowEventDispatcher::PostDispatchEvent(
+ ui::EventTarget* target,
+ const ui::Event& event) {
+ DispatchDetails details;
+ if (!target || target != event_dispatch_target_)
+ details.target_destroyed = true;
+ event_dispatch_target_ = old_dispatch_target_;
+ old_dispatch_target_ = NULL;
+#ifndef NDEBUG
+ DCHECK(!event_dispatch_target_ || window()->Contains(event_dispatch_target_));
+#endif
+
+ if (event.IsTouchEvent() && !details.target_destroyed) {
+ // Do not let 'held' touch events contribute to any gestures unless it is
+ // being dispatched.
+ if (dispatching_held_event_ || !held_move_event_ ||
+ !held_move_event_->IsTouchEvent()) {
+ ui::TouchEvent orig_event(static_cast<const ui::TouchEvent&>(event),
+ static_cast<Window*>(event.target()), window());
+ // Get the list of GestureEvents from GestureRecognizer.
+ scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
+ gestures.reset(ui::GestureRecognizer::Get()->
+ ProcessTouchEventForGesture(orig_event, event.result(),
+ static_cast<Window*>(target)));
+ return ProcessGestures(gestures.get());
+ }
+ }
+
+ return details;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, ui::GestureEventHelper implementation:
+
+bool WindowEventDispatcher::CanDispatchToConsumer(
+ ui::GestureConsumer* consumer) {
+ Window* consumer_window = ConsumerToWindow(consumer);
+ return (consumer_window && consumer_window->GetRootWindow() == window());
+}
+
+void WindowEventDispatcher::DispatchCancelTouchEvent(ui::TouchEvent* event) {
+ DispatchDetails details = OnEventFromSource(event);
+ if (details.dispatcher_destroyed)
+ return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, WindowObserver implementation:
+
+void WindowEventDispatcher::OnWindowDestroying(Window* window) {
+ if (!host_->window()->Contains(window))
+ return;
+
+ DispatchMouseExitToHidingWindow(window);
+ SynthesizeMouseMoveAfterChangeToWindow(window);
+}
+
+void WindowEventDispatcher::OnWindowDestroyed(Window* window) {
+ // We observe all windows regardless of what root Window (if any) they're
+ // attached to.
+ observer_manager_.Remove(window);
+}
+
+void WindowEventDispatcher::OnWindowAddedToRootWindow(Window* attached) {
+ if (!observer_manager_.IsObserving(attached))
+ observer_manager_.Add(attached);
+
+ if (!host_->window()->Contains(attached))
+ return;
+
+ SynthesizeMouseMoveAfterChangeToWindow(attached);
+}
+
+void WindowEventDispatcher::OnWindowRemovingFromRootWindow(Window* detached,
+ Window* new_root) {
+ if (!host_->window()->Contains(detached))
+ return;
+
+ DCHECK(client::GetCaptureWindow(window()) != window());
+
+ DispatchMouseExitToHidingWindow(detached);
+ SynthesizeMouseMoveAfterChangeToWindow(detached);
+
+ // Hiding the window releases capture which can implicitly destroy the window
+ // so the window may no longer be valid after this call.
+ OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
+}
+
+void WindowEventDispatcher::OnWindowVisibilityChanging(Window* window,
+ bool visible) {
+ if (!host_->window()->Contains(window))
+ return;
+
+ DispatchMouseExitToHidingWindow(window);
+}
+
+void WindowEventDispatcher::OnWindowVisibilityChanged(Window* window,
+ bool visible) {
+ if (!host_->window()->Contains(window))
+ return;
+
+ if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
+ PostSynthesizeMouseMove();
+
+ // Hiding the window releases capture which can implicitly destroy the window
+ // so the window may no longer be valid after this call.
+ if (!visible)
+ OnWindowHidden(window, WINDOW_HIDDEN);
+}
+
+void WindowEventDispatcher::OnWindowBoundsChanged(Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ if (!host_->window()->Contains(window))
+ return;
+
+ if (window == host_->window()) {
+ TRACE_EVENT1("ui", "WindowEventDispatcher::OnWindowBoundsChanged(root)",
+ "size", new_bounds.size().ToString());
+
+ DispatchDetails details = DispatchHeldEvents();
+ if (details.dispatcher_destroyed)
+ return;
+
+ synthesize_mouse_move_ = false;
+ }
+
+ if (window->IsVisible() && !window->ignore_events()) {
+ gfx::Rect old_bounds_in_root = old_bounds, new_bounds_in_root = new_bounds;
+ Window::ConvertRectToTarget(window->parent(), host_->window(),
+ &old_bounds_in_root);
+ Window::ConvertRectToTarget(window->parent(), host_->window(),
+ &new_bounds_in_root);
+ gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
+ if (old_bounds_in_root.Contains(last_mouse_location) !=
+ new_bounds_in_root.Contains(last_mouse_location)) {
+ PostSynthesizeMouseMove();
+ }
+ }
+}
+
+void WindowEventDispatcher::OnWindowTransforming(Window* window) {
+ if (!host_->window()->Contains(window))
+ return;
+
+ SynthesizeMouseMoveAfterChangeToWindow(window);
+}
+
+void WindowEventDispatcher::OnWindowTransformed(Window* window) {
+ if (!host_->window()->Contains(window))
+ return;
+
+ SynthesizeMouseMoveAfterChangeToWindow(window);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, EnvObserver implementation:
+
+void WindowEventDispatcher::OnWindowInitialized(Window* window) {
+ observer_manager_.Add(window);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, private:
+
+ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() {
+ if (!held_repostable_event_ && !held_move_event_)
+ return DispatchDetails();
+
+ CHECK(!dispatching_held_event_);
+ dispatching_held_event_ = true;
+
+ DispatchDetails dispatch_details;
+ if (held_repostable_event_) {
+ if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) {
+ scoped_ptr<ui::MouseEvent> mouse_event(
+ static_cast<ui::MouseEvent*>(held_repostable_event_.release()));
+ dispatch_details = OnEventFromSource(mouse_event.get());
+ } else {
+ // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987.
+ NOTREACHED();
+ }
+ if (dispatch_details.dispatcher_destroyed)
+ return dispatch_details;
+ }
+
+ if (held_move_event_) {
+ // If a mouse move has been synthesized, the target location is suspect,
+ // so drop the held mouse event.
+ if (held_move_event_->IsTouchEvent() ||
+ (held_move_event_->IsMouseEvent() && !synthesize_mouse_move_)) {
+ dispatch_details = OnEventFromSource(held_move_event_.get());
+ }
+ if (!dispatch_details.dispatcher_destroyed)
+ held_move_event_.reset();
+ }
+
+ if (!dispatch_details.dispatcher_destroyed)
+ dispatching_held_event_ = false;
+ return dispatch_details;
+}
+
+void WindowEventDispatcher::PostSynthesizeMouseMove() {
+ if (synthesize_mouse_move_)
+ return;
+ synthesize_mouse_move_ = true;
+ base::MessageLoop::current()->PostNonNestableTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(
+ &WindowEventDispatcher::SynthesizeMouseMoveEvent),
+ held_event_factory_.GetWeakPtr()));
+}
+
+void WindowEventDispatcher::SynthesizeMouseMoveAfterChangeToWindow(
+ Window* window) {
+ if (window->IsVisible() &&
+ window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
+ PostSynthesizeMouseMove();
+ }
+}
+
+ui::EventDispatchDetails WindowEventDispatcher::SynthesizeMouseMoveEvent() {
+ DispatchDetails details;
+ if (!synthesize_mouse_move_)
+ return details;
+ synthesize_mouse_move_ = false;
+
+ // If one of the mouse buttons is currently down, then do not synthesize a
+ // mouse-move event. In such cases, aura could synthesize a DRAGGED event
+ // instead of a MOVED event, but in multi-display/multi-host scenarios, the
+ // DRAGGED event can be synthesized in the incorrect host. So avoid
+ // synthesizing any events at all.
+ if (Env::GetInstance()->mouse_button_flags())
+ return details;
+
+ gfx::Point root_mouse_location = GetLastMouseLocationInRoot();
+ if (!window()->bounds().Contains(root_mouse_location))
+ return details;
+ gfx::Point host_mouse_location = root_mouse_location;
+ host_->ConvertPointToHost(&host_mouse_location);
+ ui::MouseEvent event(ui::ET_MOUSE_MOVED,
+ host_mouse_location,
+ host_mouse_location,
+ ui::EF_IS_SYNTHESIZED,
+ 0);
+ return OnEventFromSource(&event);
+}
+
+void WindowEventDispatcher::PreDispatchLocatedEvent(Window* target,
+ ui::LocatedEvent* event) {
+ int flags = event->flags();
+ if (IsNonClientLocation(target, event->location()))
+ flags |= ui::EF_IS_NON_CLIENT;
+ event->set_flags(flags);
+
+ if (!dispatching_held_event_ &&
+ (event->IsMouseEvent() || event->IsScrollEvent()) &&
+ !(event->flags() & ui::EF_IS_SYNTHESIZED)) {
+ if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)
+ SetLastMouseLocation(window(), event->root_location());
+ synthesize_mouse_move_ = false;
+ }
+}
+
+void WindowEventDispatcher::PreDispatchMouseEvent(Window* target,
+ ui::MouseEvent* event) {
+ client::CursorClient* cursor_client = client::GetCursorClient(window());
+ // We allow synthesized mouse exit events through even if mouse events are
+ // disabled. This ensures that hover state, etc on controls like buttons is
+ // cleared.
+ if (cursor_client &&
+ !cursor_client->IsMouseEventsEnabled() &&
+ (event->flags() & ui::EF_IS_SYNTHESIZED) &&
+ (event->type() != ui::ET_MOUSE_EXITED)) {
+ event->SetHandled();
+ return;
+ }
+
+ if (IsEventCandidateForHold(*event) && !dispatching_held_event_) {
+ if (move_hold_count_) {
+ if (!(event->flags() & ui::EF_IS_SYNTHESIZED) &&
+ event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) {
+ SetLastMouseLocation(window(), event->root_location());
+ }
+ held_move_event_.reset(new ui::MouseEvent(*event, target, window()));
+ event->SetHandled();
+ return;
+ } else {
+ // We may have a held event for a period between the time move_hold_count_
+ // fell to 0 and the DispatchHeldEvents executes. Since we're going to
+ // dispatch the new event directly below, we can reset the old one.
+ held_move_event_.reset();
+ }
+ }
+
+ const int kMouseButtonFlagMask = ui::EF_LEFT_MOUSE_BUTTON |
+ ui::EF_MIDDLE_MOUSE_BUTTON |
+ ui::EF_RIGHT_MOUSE_BUTTON;
+ switch (event->type()) {
+ case ui::ET_MOUSE_EXITED:
+ if (!target || target == window()) {
+ DispatchDetails details =
+ DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
+ if (details.dispatcher_destroyed) {
+ event->SetHandled();
+ return;
+ }
+ mouse_moved_handler_ = NULL;
+ }
+ break;
+ case ui::ET_MOUSE_MOVED:
+ // Send an exit to the current |mouse_moved_handler_| and an enter to
+ // |target|. Take care that both us and |target| aren't destroyed during
+ // dispatch.
+ if (target != mouse_moved_handler_) {
+ aura::Window* old_mouse_moved_handler = mouse_moved_handler_;
+ WindowTracker live_window;
+ live_window.Add(target);
+ DispatchDetails details =
+ DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
+ if (details.dispatcher_destroyed) {
+ event->SetHandled();
+ return;
+ }
+ // If the |mouse_moved_handler_| changes out from under us, assume a
+ // nested message loop ran and we don't need to do anything.
+ if (mouse_moved_handler_ != old_mouse_moved_handler) {
+ event->SetHandled();
+ return;
+ }
+ if (!live_window.Contains(target) || details.target_destroyed) {
+ mouse_moved_handler_ = NULL;
+ event->SetHandled();
+ return;
+ }
+ live_window.Remove(target);
+
+ mouse_moved_handler_ = target;
+ details = DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED);
+ if (details.dispatcher_destroyed || details.target_destroyed) {
+ event->SetHandled();
+ return;
+ }
+ }
+ break;
+ case ui::ET_MOUSE_PRESSED:
+ // Don't set the mouse pressed handler for non client mouse down events.
+ // These are only sent by Windows and are not always followed with non
+ // client mouse up events which causes subsequent mouse events to be
+ // sent to the wrong target.
+ if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_)
+ mouse_pressed_handler_ = target;
+ Env::GetInstance()->set_mouse_button_flags(
+ event->flags() & kMouseButtonFlagMask);
+ break;
+ case ui::ET_MOUSE_RELEASED:
+ mouse_pressed_handler_ = NULL;
+ Env::GetInstance()->set_mouse_button_flags(event->flags() &
+ kMouseButtonFlagMask & ~event->changed_button_flags());
+ break;
+ default:
+ break;
+ }
+
+ PreDispatchLocatedEvent(target, event);
+}
+
+void WindowEventDispatcher::PreDispatchTouchEvent(Window* target,
+ ui::TouchEvent* event) {
+ switch (event->type()) {
+ case ui::ET_TOUCH_PRESSED:
+ touch_ids_down_ |= (1 << event->touch_id());
+ Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
+ break;
+
+ // Handle ET_TOUCH_CANCELLED only if it has a native event.
+ case ui::ET_TOUCH_CANCELLED:
+ if (!event->HasNativeEvent())
+ break;
+ // fallthrough
+ case ui::ET_TOUCH_RELEASED:
+ touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^
+ (1 << event->touch_id());
+ Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
+ break;
+
+ case ui::ET_TOUCH_MOVED:
+ if (move_hold_count_ && !dispatching_held_event_) {
+ held_move_event_.reset(new ui::TouchEvent(*event, target, window()));
+ event->SetHandled();
+ return;
+ }
+ break;
+
+ default:
+ NOTREACHED();
+ break;
+ }
+ PreDispatchLocatedEvent(target, event);
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/window_event_dispatcher.h b/chromium/ui/aura/window_event_dispatcher.h
new file mode 100644
index 00000000000..79ba3c7b2cb
--- /dev/null
+++ b/chromium/ui/aura/window_event_dispatcher.h
@@ -0,0 +1,265 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_WINDOW_EVENT_DISPATCHER_H_
+#define UI_AURA_WINDOW_EVENT_DISPATCHER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/scoped_observer.h"
+#include "ui/aura/aura_export.h"
+#include "ui/aura/client/capture_delegate.h"
+#include "ui/aura/env_observer.h"
+#include "ui/aura/window_observer.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/event_processor.h"
+#include "ui/events/event_targeter.h"
+#include "ui/events/gestures/gesture_recognizer.h"
+#include "ui/events/gestures/gesture_types.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/point.h"
+
+namespace gfx {
+class Size;
+class Transform;
+}
+
+namespace ui {
+class GestureEvent;
+class GestureRecognizer;
+class KeyEvent;
+class MouseEvent;
+class ScrollEvent;
+class TouchEvent;
+}
+
+namespace aura {
+class TestScreen;
+class WindowTargeter;
+class WindowTreeHost;
+
+// WindowEventDispatcher orchestrates event dispatch within a window tree
+// owned by WindowTreeHost. WTH also owns the WED.
+// TODO(beng): In progress, remove functionality not directly related to
+// event dispatch.
+class AURA_EXPORT WindowEventDispatcher : public ui::EventProcessor,
+ public ui::GestureEventHelper,
+ public client::CaptureDelegate,
+ public WindowObserver,
+ public EnvObserver {
+ public:
+ explicit WindowEventDispatcher(WindowTreeHost* host);
+ virtual ~WindowEventDispatcher();
+
+ Window* mouse_pressed_handler() { return mouse_pressed_handler_; }
+ Window* mouse_moved_handler() { return mouse_moved_handler_; }
+
+ // Repost event for re-processing. Used when exiting context menus.
+ // We only support the ET_MOUSE_PRESSED and ET_GESTURE_TAP_DOWN event
+ // types (although the latter is currently a no-op).
+ void RepostEvent(const ui::LocatedEvent& event);
+
+ // Invoked when the mouse events get enabled or disabled.
+ void OnMouseEventsEnableStateChanged(bool enabled);
+
+ void DispatchCancelModeEvent();
+
+ // Dispatches a ui::ET_MOUSE_EXITED event at |point|.
+ // TODO(beng): needed only for WTH::OnCursorVisibilityChanged().
+ void DispatchMouseExitAtPoint(const gfx::Point& point);
+
+ // Gesture Recognition -------------------------------------------------------
+
+ // When a touch event is dispatched to a Window, it may want to process the
+ // touch event asynchronously. In such cases, the window should consume the
+ // event during the event dispatch. Once the event is properly processed, the
+ // window should let the WindowEventDispatcher know about the result of the
+ // event processing, so that gesture events can be properly created and
+ // dispatched.
+ void ProcessedTouchEvent(ui::TouchEvent* event,
+ Window* window,
+ ui::EventResult result);
+
+ // These methods are used to defer the processing of mouse/touch events
+ // related to resize. A client (typically a RenderWidgetHostViewAura) can call
+ // HoldPointerMoves when an resize is initiated and then ReleasePointerMoves
+ // once the resize is completed.
+ //
+ // More than one hold can be invoked and each hold must be cancelled by a
+ // release before we resume normal operation.
+ void HoldPointerMoves();
+ void ReleasePointerMoves();
+
+ // Gets the last location seen in a mouse event in this root window's
+ // coordinates. This may return a point outside the root window's bounds.
+ gfx::Point GetLastMouseLocationInRoot() const;
+
+ void OnHostLostMouseGrab();
+ void OnCursorMovedToRootLocation(const gfx::Point& root_location);
+
+ // TODO(beng): This is only needed because this cleanup needs to happen after
+ // all other observers are notified of OnWindowDestroying() but
+ // before OnWindowDestroyed() is sent (i.e. while the window
+ // hierarchy is still intact). This didn't seem worth adding a
+ // generic notification for as only this class needs to implement
+ // it. I would however like to find a way to do this via an
+ // observer.
+ void OnPostNotifiedWindowDestroying(Window* window);
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(WindowEventDispatcherTest,
+ KeepTranslatedEventInRoot);
+
+ friend class Window;
+ friend class TestScreen;
+
+ // The parameter for OnWindowHidden() to specify why window is hidden.
+ enum WindowHiddenReason {
+ WINDOW_DESTROYED, // Window is destroyed.
+ WINDOW_HIDDEN, // Window is hidden.
+ WINDOW_MOVING, // Window is temporarily marked as hidden due to move
+ // across root windows.
+ };
+
+ Window* window();
+ const Window* window() const;
+
+ // Updates the event with the appropriate transform for the device scale
+ // factor. The WindowEventDispatcher dispatches events in the physical pixel
+ // coordinate. But the event processing from WindowEventDispatcher onwards
+ // happen in device-independent pixel coordinate. So it is necessary to update
+ // the event received from the host.
+ void TransformEventForDeviceScaleFactor(ui::LocatedEvent* event);
+
+ // Dispatches OnMouseExited to the |window| which is hiding if necessary.
+ void DispatchMouseExitToHidingWindow(Window* window);
+
+ // Dispatches the specified event type (intended for enter/exit) to the
+ // |mouse_moved_handler_|.
+ ui::EventDispatchDetails DispatchMouseEnterOrExit(
+ const ui::MouseEvent& event,
+ ui::EventType type) WARN_UNUSED_RESULT;
+ ui::EventDispatchDetails ProcessGestures(
+ ui::GestureRecognizer::Gestures* gestures) WARN_UNUSED_RESULT;
+
+ // Called when a window becomes invisible, either by being removed
+ // from root window hierarchy, via SetVisible(false) or being destroyed.
+ // |reason| specifies what triggered the hiding. Note that becoming invisible
+ // will cause a window to lose capture and some windows may destroy themselves
+ // on capture (like DragDropTracker).
+ void OnWindowHidden(Window* invisible, WindowHiddenReason reason);
+
+ // Returns a target window for the given gesture event.
+ Window* GetGestureTarget(ui::GestureEvent* event);
+
+ // Overridden from aura::client::CaptureDelegate:
+ virtual void UpdateCapture(Window* old_capture, Window* new_capture) OVERRIDE;
+ virtual void OnOtherRootGotCapture() OVERRIDE;
+ virtual void SetNativeCapture() OVERRIDE;
+ virtual void ReleaseNativeCapture() OVERRIDE;
+
+ // Overridden from ui::EventProcessor:
+ virtual ui::EventTarget* GetRootTarget() OVERRIDE;
+ virtual void PrepareEventForDispatch(ui::Event* event) OVERRIDE;
+
+ // Overridden from ui::EventDispatcherDelegate.
+ virtual bool CanDispatchToTarget(ui::EventTarget* target) OVERRIDE;
+ virtual ui::EventDispatchDetails PreDispatchEvent(ui::EventTarget* target,
+ ui::Event* event) OVERRIDE;
+ virtual ui::EventDispatchDetails PostDispatchEvent(
+ ui::EventTarget* target, const ui::Event& event) OVERRIDE;
+
+ // Overridden from ui::GestureEventHelper.
+ virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE;
+ virtual void DispatchGestureEvent(ui::GestureEvent* event) OVERRIDE;
+ virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
+
+ // Overridden from WindowObserver:
+ virtual void OnWindowDestroying(Window* window) OVERRIDE;
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE;
+ virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE;
+ virtual void OnWindowRemovingFromRootWindow(Window* window,
+ Window* new_root) OVERRIDE;
+ virtual void OnWindowVisibilityChanging(Window* window,
+ bool visible) OVERRIDE;
+ virtual void OnWindowVisibilityChanged(Window* window, bool visible) OVERRIDE;
+ virtual void OnWindowBoundsChanged(Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) OVERRIDE;
+ virtual void OnWindowTransforming(Window* window) OVERRIDE;
+ virtual void OnWindowTransformed(Window* window) OVERRIDE;
+
+ // Overridden from EnvObserver:
+ virtual void OnWindowInitialized(Window* window) OVERRIDE;
+
+ // We hold and aggregate mouse drags and touch moves as a way of throttling
+ // resizes when HoldMouseMoves() is called. The following methods are used to
+ // dispatch held and newly incoming mouse and touch events, typically when an
+ // event other than one of these needs dispatching or a matching
+ // ReleaseMouseMoves()/ReleaseTouchMoves() is called. NOTE: because these
+ // methods dispatch events from WindowTreeHost the coordinates are in terms of
+ // the root.
+ ui::EventDispatchDetails DispatchHeldEvents() WARN_UNUSED_RESULT;
+
+ // Posts a task to send synthesized mouse move event if there is no a pending
+ // task.
+ void PostSynthesizeMouseMove();
+
+ // Creates and dispatches synthesized mouse move event using the current mouse
+ // location.
+ ui::EventDispatchDetails SynthesizeMouseMoveEvent() WARN_UNUSED_RESULT;
+
+ // Calls SynthesizeMouseMove() if |window| is currently visible and contains
+ // the mouse cursor.
+ void SynthesizeMouseMoveAfterChangeToWindow(Window* window);
+
+ void PreDispatchLocatedEvent(Window* target, ui::LocatedEvent* event);
+ void PreDispatchMouseEvent(Window* target, ui::MouseEvent* event);
+ void PreDispatchTouchEvent(Window* target, ui::TouchEvent* event);
+
+ WindowTreeHost* host_;
+
+ // Touch ids that are currently down.
+ uint32 touch_ids_down_;
+
+ Window* mouse_pressed_handler_;
+ Window* mouse_moved_handler_;
+ Window* event_dispatch_target_;
+ Window* old_dispatch_target_;
+
+ bool synthesize_mouse_move_;
+
+ // How many move holds are outstanding. We try to defer dispatching
+ // touch/mouse moves while the count is > 0.
+ int move_hold_count_;
+ // The location of |held_move_event_| is in |window_|'s coordinate.
+ scoped_ptr<ui::LocatedEvent> held_move_event_;
+
+ // Allowing for reposting of events. Used when exiting context menus.
+ scoped_ptr<ui::LocatedEvent> held_repostable_event_;
+
+ // Set when dispatching a held event.
+ bool dispatching_held_event_;
+
+ ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_;
+
+ // Used to schedule reposting an event.
+ base::WeakPtrFactory<WindowEventDispatcher> repost_event_factory_;
+
+ // Used to schedule DispatchHeldEvents() when |move_hold_count_| goes to 0.
+ base::WeakPtrFactory<WindowEventDispatcher> held_event_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowEventDispatcher);
+};
+
+} // namespace aura
+
+#endif // UI_AURA_WINDOW_EVENT_DISPATCHER_H_
diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc
new file mode 100644
index 00000000000..11eeaa0d2c4
--- /dev/null
+++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc
@@ -0,0 +1,2219 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/window_event_dispatcher.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/client/event_client.h"
+#include "ui/aura/client/focus_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/env_test_helper.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/test/test_cursor_client.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/test/test_windows.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tracker.h"
+#include "ui/base/hit_test.h"
+#include "ui/events/event.h"
+#include "ui/events/event_handler.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/gestures/gesture_configuration.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/test/test_event_handler.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/screen.h"
+#include "ui/gfx/transform.h"
+
+namespace aura {
+namespace {
+
+// A delegate that always returns a non-client component for hit tests.
+class NonClientDelegate : public test::TestWindowDelegate {
+ public:
+ NonClientDelegate()
+ : non_client_count_(0),
+ mouse_event_count_(0),
+ mouse_event_flags_(0x0) {
+ }
+ virtual ~NonClientDelegate() {}
+
+ int non_client_count() const { return non_client_count_; }
+ gfx::Point non_client_location() const { return non_client_location_; }
+ int mouse_event_count() const { return mouse_event_count_; }
+ gfx::Point mouse_event_location() const { return mouse_event_location_; }
+ int mouse_event_flags() const { return mouse_event_flags_; }
+
+ virtual int GetNonClientComponent(const gfx::Point& location) const OVERRIDE {
+ NonClientDelegate* self = const_cast<NonClientDelegate*>(this);
+ self->non_client_count_++;
+ self->non_client_location_ = location;
+ return HTTOPLEFT;
+ }
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ mouse_event_count_++;
+ mouse_event_location_ = event->location();
+ mouse_event_flags_ = event->flags();
+ event->SetHandled();
+ }
+
+ private:
+ int non_client_count_;
+ gfx::Point non_client_location_;
+ int mouse_event_count_;
+ gfx::Point mouse_event_location_;
+ int mouse_event_flags_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonClientDelegate);
+};
+
+// A simple event handler that consumes key events.
+class ConsumeKeyHandler : public ui::test::TestEventHandler {
+ public:
+ ConsumeKeyHandler() {}
+ virtual ~ConsumeKeyHandler() {}
+
+ // Overridden from ui::EventHandler:
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
+ ui::test::TestEventHandler::OnKeyEvent(event);
+ event->StopPropagation();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ConsumeKeyHandler);
+};
+
+bool IsFocusedWindow(aura::Window* window) {
+ return client::GetFocusClient(window)->GetFocusedWindow() == window;
+}
+
+} // namespace
+
+typedef test::AuraTestBase WindowEventDispatcherTest;
+
+TEST_F(WindowEventDispatcherTest, OnHostMouseEvent) {
+ // Create two non-overlapping windows so we don't have to worry about which
+ // is on top.
+ scoped_ptr<NonClientDelegate> delegate1(new NonClientDelegate());
+ scoped_ptr<NonClientDelegate> delegate2(new NonClientDelegate());
+ const int kWindowWidth = 123;
+ const int kWindowHeight = 45;
+ gfx::Rect bounds1(100, 200, kWindowWidth, kWindowHeight);
+ gfx::Rect bounds2(300, 400, kWindowWidth, kWindowHeight);
+ scoped_ptr<aura::Window> window1(CreateTestWindowWithDelegate(
+ delegate1.get(), -1234, bounds1, root_window()));
+ scoped_ptr<aura::Window> window2(CreateTestWindowWithDelegate(
+ delegate2.get(), -5678, bounds2, root_window()));
+
+ // Send a mouse event to window1.
+ gfx::Point point(101, 201);
+ ui::MouseEvent event1(
+ ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ DispatchEventUsingWindowDispatcher(&event1);
+
+ // Event was tested for non-client area for the target window.
+ EXPECT_EQ(1, delegate1->non_client_count());
+ EXPECT_EQ(0, delegate2->non_client_count());
+ // The non-client component test was in local coordinates.
+ EXPECT_EQ(gfx::Point(1, 1), delegate1->non_client_location());
+ // Mouse event was received by target window.
+ EXPECT_EQ(1, delegate1->mouse_event_count());
+ EXPECT_EQ(0, delegate2->mouse_event_count());
+ // Event was in local coordinates.
+ EXPECT_EQ(gfx::Point(1, 1), delegate1->mouse_event_location());
+ // Non-client flag was set.
+ EXPECT_TRUE(delegate1->mouse_event_flags() & ui::EF_IS_NON_CLIENT);
+}
+
+TEST_F(WindowEventDispatcherTest, RepostEvent) {
+ // Test RepostEvent in RootWindow. It only works for Mouse Press.
+ EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
+ gfx::Point point(10, 10);
+ ui::MouseEvent event(
+ ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ host()->dispatcher()->RepostEvent(event);
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
+}
+
+// Check that we correctly track the state of the mouse buttons in response to
+// button press and release events.
+TEST_F(WindowEventDispatcherTest, MouseButtonState) {
+ EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
+
+ gfx::Point location;
+ scoped_ptr<ui::MouseEvent> event;
+
+ // Press the left button.
+ event.reset(new ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED,
+ location,
+ location,
+ ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON));
+ DispatchEventUsingWindowDispatcher(event.get());
+ EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
+
+ // Additionally press the right.
+ event.reset(new ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED,
+ location,
+ location,
+ ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
+ ui::EF_RIGHT_MOUSE_BUTTON));
+ DispatchEventUsingWindowDispatcher(event.get());
+ EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
+
+ // Release the left button.
+ event.reset(new ui::MouseEvent(
+ ui::ET_MOUSE_RELEASED,
+ location,
+ location,
+ ui::EF_RIGHT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON));
+ DispatchEventUsingWindowDispatcher(event.get());
+ EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
+
+ // Release the right button. We should ignore the Shift-is-down flag.
+ event.reset(new ui::MouseEvent(
+ ui::ET_MOUSE_RELEASED,
+ location,
+ location,
+ ui::EF_SHIFT_DOWN,
+ ui::EF_RIGHT_MOUSE_BUTTON));
+ DispatchEventUsingWindowDispatcher(event.get());
+ EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
+
+ // Press the middle button.
+ event.reset(new ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED,
+ location,
+ location,
+ ui::EF_MIDDLE_MOUSE_BUTTON,
+ ui::EF_MIDDLE_MOUSE_BUTTON));
+ DispatchEventUsingWindowDispatcher(event.get());
+ EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
+}
+
+TEST_F(WindowEventDispatcherTest, TranslatedEvent) {
+ scoped_ptr<Window> w1(test::CreateTestWindowWithDelegate(NULL, 1,
+ gfx::Rect(50, 50, 100, 100), root_window()));
+
+ gfx::Point origin(100, 100);
+ ui::MouseEvent root(ui::ET_MOUSE_PRESSED, origin, origin, 0, 0);
+
+ EXPECT_EQ("100,100", root.location().ToString());
+ EXPECT_EQ("100,100", root.root_location().ToString());
+
+ ui::MouseEvent translated_event(
+ root, static_cast<Window*>(root_window()), w1.get(),
+ ui::ET_MOUSE_ENTERED, root.flags());
+ EXPECT_EQ("50,50", translated_event.location().ToString());
+ EXPECT_EQ("100,100", translated_event.root_location().ToString());
+}
+
+namespace {
+
+class TestEventClient : public client::EventClient {
+ public:
+ static const int kNonLockWindowId = 100;
+ static const int kLockWindowId = 200;
+
+ explicit TestEventClient(Window* root_window)
+ : root_window_(root_window),
+ lock_(false) {
+ client::SetEventClient(root_window_, this);
+ Window* lock_window =
+ test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
+ lock_window->set_id(kLockWindowId);
+ Window* non_lock_window =
+ test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
+ non_lock_window->set_id(kNonLockWindowId);
+ }
+ virtual ~TestEventClient() {
+ client::SetEventClient(root_window_, NULL);
+ }
+
+ // Starts/stops locking. Locking prevents windows other than those inside
+ // the lock container from receiving events, getting focus etc.
+ void Lock() {
+ lock_ = true;
+ }
+ void Unlock() {
+ lock_ = false;
+ }
+
+ Window* GetLockWindow() {
+ return const_cast<Window*>(
+ static_cast<const TestEventClient*>(this)->GetLockWindow());
+ }
+ const Window* GetLockWindow() const {
+ return root_window_->GetChildById(kLockWindowId);
+ }
+ Window* GetNonLockWindow() {
+ return root_window_->GetChildById(kNonLockWindowId);
+ }
+
+ private:
+ // Overridden from client::EventClient:
+ virtual bool CanProcessEventsWithinSubtree(
+ const Window* window) const OVERRIDE {
+ return lock_ ?
+ window->Contains(GetLockWindow()) || GetLockWindow()->Contains(window) :
+ true;
+ }
+
+ virtual ui::EventTarget* GetToplevelEventTarget() OVERRIDE {
+ return NULL;
+ }
+
+ Window* root_window_;
+ bool lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestEventClient);
+};
+
+} // namespace
+
+TEST_F(WindowEventDispatcherTest, CanProcessEventsWithinSubtree) {
+ TestEventClient client(root_window());
+ test::TestWindowDelegate d;
+
+ ui::test::TestEventHandler nonlock_ef;
+ ui::test::TestEventHandler lock_ef;
+ client.GetNonLockWindow()->AddPreTargetHandler(&nonlock_ef);
+ client.GetLockWindow()->AddPreTargetHandler(&lock_ef);
+
+ Window* w1 = test::CreateTestWindowWithBounds(gfx::Rect(10, 10, 20, 20),
+ client.GetNonLockWindow());
+ w1->set_id(1);
+ Window* w2 = test::CreateTestWindowWithBounds(gfx::Rect(30, 30, 20, 20),
+ client.GetNonLockWindow());
+ w2->set_id(2);
+ scoped_ptr<Window> w3(
+ test::CreateTestWindowWithDelegate(&d, 3, gfx::Rect(30, 30, 20, 20),
+ client.GetLockWindow()));
+
+ w1->Focus();
+ EXPECT_TRUE(IsFocusedWindow(w1));
+
+ client.Lock();
+
+ // Since we're locked, the attempt to focus w2 will be ignored.
+ w2->Focus();
+ EXPECT_TRUE(IsFocusedWindow(w1));
+ EXPECT_FALSE(IsFocusedWindow(w2));
+
+ {
+ // Attempting to send a key event to w1 (not in the lock container) should
+ // cause focus to be reset.
+ test::EventGenerator generator(root_window());
+ generator.PressKey(ui::VKEY_SPACE, 0);
+ EXPECT_EQ(NULL, client::GetFocusClient(w1)->GetFocusedWindow());
+ EXPECT_FALSE(IsFocusedWindow(w1));
+ }
+
+ {
+ // Events sent to a window not in the lock container will not be processed.
+ // i.e. never sent to the non-lock container's event filter.
+ test::EventGenerator generator(root_window(), w1);
+ generator.ClickLeftButton();
+ EXPECT_EQ(0, nonlock_ef.num_mouse_events());
+
+ // Events sent to a window in the lock container will be processed.
+ test::EventGenerator generator3(root_window(), w3.get());
+ generator3.PressLeftButton();
+ EXPECT_EQ(1, lock_ef.num_mouse_events());
+ }
+
+ // Prevent w3 from being deleted by the hierarchy since its delegate is owned
+ // by this scope.
+ w3->parent()->RemoveChild(w3.get());
+}
+
+TEST_F(WindowEventDispatcherTest, IgnoreUnknownKeys) {
+ ConsumeKeyHandler handler;
+ root_window()->AddPreTargetHandler(&handler);
+
+ ui::KeyEvent unknown_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, 0, false);
+ DispatchEventUsingWindowDispatcher(&unknown_event);
+ EXPECT_FALSE(unknown_event.handled());
+ EXPECT_EQ(0, handler.num_key_events());
+
+ handler.Reset();
+ ui::KeyEvent known_event(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, false);
+ DispatchEventUsingWindowDispatcher(&known_event);
+ EXPECT_TRUE(known_event.handled());
+ EXPECT_EQ(1, handler.num_key_events());
+
+ handler.Reset();
+ ui::KeyEvent ime_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
+ ui::EF_IME_FABRICATED_KEY, false);
+ DispatchEventUsingWindowDispatcher(&ime_event);
+ EXPECT_TRUE(ime_event.handled());
+ EXPECT_EQ(1, handler.num_key_events());
+
+ handler.Reset();
+ ui::KeyEvent unknown_key_with_char_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
+ 0, false);
+ unknown_key_with_char_event.set_character(0x00e4 /* "ä" */);
+ DispatchEventUsingWindowDispatcher(&unknown_key_with_char_event);
+ EXPECT_TRUE(unknown_key_with_char_event.handled());
+ EXPECT_EQ(1, handler.num_key_events());
+}
+
+TEST_F(WindowEventDispatcherTest, NoDelegateWindowReceivesKeyEvents) {
+ scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
+ w1->Show();
+ w1->Focus();
+
+ ui::test::TestEventHandler handler;
+ w1->AddPreTargetHandler(&handler);
+ ui::KeyEvent key_press(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, false);
+ DispatchEventUsingWindowDispatcher(&key_press);
+ EXPECT_TRUE(key_press.handled());
+ EXPECT_EQ(1, handler.num_key_events());
+
+ w1->RemovePreTargetHandler(&handler);
+}
+
+// Tests that touch-events that are beyond the bounds of the root-window do get
+// propagated to the event filters correctly with the root as the target.
+TEST_F(WindowEventDispatcherTest, TouchEventsOutsideBounds) {
+ ui::test::TestEventHandler handler;
+ root_window()->AddPreTargetHandler(&handler);
+
+ gfx::Point position = root_window()->bounds().origin();
+ position.Offset(-10, -10);
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED, position, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press);
+ EXPECT_EQ(1, handler.num_touch_events());
+
+ position = root_window()->bounds().origin();
+ position.Offset(root_window()->bounds().width() + 10,
+ root_window()->bounds().height() + 10);
+ ui::TouchEvent release(
+ ui::ET_TOUCH_RELEASED, position, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&release);
+ EXPECT_EQ(2, handler.num_touch_events());
+}
+
+// Tests that scroll events are dispatched correctly.
+TEST_F(WindowEventDispatcherTest, ScrollEventDispatch) {
+ base::TimeDelta now = ui::EventTimeForNow();
+ ui::test::TestEventHandler handler;
+ root_window()->AddPreTargetHandler(&handler);
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &delegate));
+ w1->SetBounds(gfx::Rect(20, 20, 40, 40));
+
+ // A scroll event on the root-window itself is dispatched.
+ ui::ScrollEvent scroll1(ui::ET_SCROLL,
+ gfx::Point(10, 10),
+ now,
+ 0,
+ 0, -10,
+ 0, -10,
+ 2);
+ DispatchEventUsingWindowDispatcher(&scroll1);
+ EXPECT_EQ(1, handler.num_scroll_events());
+
+ // Scroll event on a window should be dispatched properly.
+ ui::ScrollEvent scroll2(ui::ET_SCROLL,
+ gfx::Point(25, 30),
+ now,
+ 0,
+ -10, 0,
+ -10, 0,
+ 2);
+ DispatchEventUsingWindowDispatcher(&scroll2);
+ EXPECT_EQ(2, handler.num_scroll_events());
+ root_window()->RemovePreTargetHandler(&handler);
+}
+
+namespace {
+
+// FilterFilter that tracks the types of events it's seen.
+class EventFilterRecorder : public ui::EventHandler {
+ public:
+ typedef std::vector<ui::EventType> Events;
+ typedef std::vector<gfx::Point> EventLocations;
+ typedef std::vector<int> EventFlags;
+
+ EventFilterRecorder()
+ : wait_until_event_(ui::ET_UNKNOWN) {
+ }
+
+ const Events& events() const { return events_; }
+
+ const EventLocations& mouse_locations() const { return mouse_locations_; }
+ gfx::Point mouse_location(int i) const { return mouse_locations_[i]; }
+ const EventLocations& touch_locations() const { return touch_locations_; }
+ const EventFlags& mouse_event_flags() const { return mouse_event_flags_; }
+
+ void WaitUntilReceivedEvent(ui::EventType type) {
+ wait_until_event_ = type;
+ run_loop_.reset(new base::RunLoop());
+ run_loop_->Run();
+ }
+
+ Events GetAndResetEvents() {
+ Events events = events_;
+ Reset();
+ return events;
+ }
+
+ void Reset() {
+ events_.clear();
+ mouse_locations_.clear();
+ touch_locations_.clear();
+ mouse_event_flags_.clear();
+ }
+
+ // ui::EventHandler overrides:
+ virtual void OnEvent(ui::Event* event) OVERRIDE {
+ ui::EventHandler::OnEvent(event);
+ events_.push_back(event->type());
+ if (wait_until_event_ == event->type() && run_loop_) {
+ run_loop_->Quit();
+ wait_until_event_ = ui::ET_UNKNOWN;
+ }
+ }
+
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ mouse_locations_.push_back(event->location());
+ mouse_event_flags_.push_back(event->flags());
+ }
+
+ virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
+ touch_locations_.push_back(event->location());
+ }
+
+ bool HasReceivedEvent(ui::EventType type) {
+ return std::find(events_.begin(), events_.end(), type) != events_.end();
+ }
+
+ private:
+ scoped_ptr<base::RunLoop> run_loop_;
+ ui::EventType wait_until_event_;
+
+ Events events_;
+ EventLocations mouse_locations_;
+ EventLocations touch_locations_;
+ EventFlags mouse_event_flags_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventFilterRecorder);
+};
+
+// Converts an EventType to a string.
+std::string EventTypeToString(ui::EventType type) {
+ switch (type) {
+ case ui::ET_TOUCH_RELEASED:
+ return "TOUCH_RELEASED";
+
+ case ui::ET_TOUCH_CANCELLED:
+ return "TOUCH_CANCELLED";
+
+ case ui::ET_TOUCH_PRESSED:
+ return "TOUCH_PRESSED";
+
+ case ui::ET_TOUCH_MOVED:
+ return "TOUCH_MOVED";
+
+ case ui::ET_MOUSE_PRESSED:
+ return "MOUSE_PRESSED";
+
+ case ui::ET_MOUSE_DRAGGED:
+ return "MOUSE_DRAGGED";
+
+ case ui::ET_MOUSE_RELEASED:
+ return "MOUSE_RELEASED";
+
+ case ui::ET_MOUSE_MOVED:
+ return "MOUSE_MOVED";
+
+ case ui::ET_MOUSE_ENTERED:
+ return "MOUSE_ENTERED";
+
+ case ui::ET_MOUSE_EXITED:
+ return "MOUSE_EXITED";
+
+ case ui::ET_GESTURE_SCROLL_BEGIN:
+ return "GESTURE_SCROLL_BEGIN";
+
+ case ui::ET_GESTURE_SCROLL_END:
+ return "GESTURE_SCROLL_END";
+
+ case ui::ET_GESTURE_SCROLL_UPDATE:
+ return "GESTURE_SCROLL_UPDATE";
+
+ case ui::ET_GESTURE_PINCH_BEGIN:
+ return "GESTURE_PINCH_BEGIN";
+
+ case ui::ET_GESTURE_PINCH_END:
+ return "GESTURE_PINCH_END";
+
+ case ui::ET_GESTURE_PINCH_UPDATE:
+ return "GESTURE_PINCH_UPDATE";
+
+ case ui::ET_GESTURE_TAP:
+ return "GESTURE_TAP";
+
+ case ui::ET_GESTURE_TAP_DOWN:
+ return "GESTURE_TAP_DOWN";
+
+ case ui::ET_GESTURE_TAP_CANCEL:
+ return "GESTURE_TAP_CANCEL";
+
+ case ui::ET_GESTURE_SHOW_PRESS:
+ return "GESTURE_SHOW_PRESS";
+
+ case ui::ET_GESTURE_BEGIN:
+ return "GESTURE_BEGIN";
+
+ case ui::ET_GESTURE_END:
+ return "GESTURE_END";
+
+ default:
+ // We should explicitly require each event type.
+ NOTREACHED() << "Received unexpected event: " << type;
+ break;
+ }
+ return "";
+}
+
+std::string EventTypesToString(const EventFilterRecorder::Events& events) {
+ std::string result;
+ for (size_t i = 0; i < events.size(); ++i) {
+ if (i != 0)
+ result += " ";
+ result += EventTypeToString(events[i]);
+ }
+ return result;
+}
+
+} // namespace
+
+// Verifies a repost mouse event targets the window with capture (if there is
+// one).
+TEST_F(WindowEventDispatcherTest, RepostTargetsCaptureWindow) {
+ // Set capture on |window| generate a mouse event (that is reposted) and not
+ // over |window| and verify |window| gets it (|window| gets it because it has
+ // capture).
+ EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
+ EventFilterRecorder recorder;
+ scoped_ptr<Window> window(CreateNormalWindow(1, root_window(), NULL));
+ window->SetBounds(gfx::Rect(20, 20, 40, 30));
+ window->AddPreTargetHandler(&recorder);
+ window->SetCapture();
+ const ui::MouseEvent press_event(
+ ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ host()->dispatcher()->RepostEvent(press_event);
+ RunAllPendingInMessageLoop(); // Necessitated by RepostEvent().
+ // Mouse moves/enters may be generated. We only care about a pressed.
+ EXPECT_TRUE(EventTypesToString(recorder.events()).find("MOUSE_PRESSED") !=
+ std::string::npos) << EventTypesToString(recorder.events());
+}
+
+TEST_F(WindowEventDispatcherTest, MouseMovesHeld) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
+
+ ui::MouseEvent mouse_move_event(ui::ET_MOUSE_MOVED, gfx::Point(0, 0),
+ gfx::Point(0, 0), 0, 0);
+ DispatchEventUsingWindowDispatcher(&mouse_move_event);
+ // Discard MOUSE_ENTER.
+ recorder.Reset();
+
+ host()->dispatcher()->HoldPointerMoves();
+
+ // Check that we don't immediately dispatch the MOUSE_DRAGGED event.
+ ui::MouseEvent mouse_dragged_event(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0),
+ gfx::Point(0, 0), 0, 0);
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
+ EXPECT_TRUE(recorder.events().empty());
+
+ // Check that we do dispatch the held MOUSE_DRAGGED event before another type
+ // of event.
+ ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0),
+ gfx::Point(0, 0), 0, 0);
+ DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
+ EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
+ EventTypesToString(recorder.events()));
+ recorder.Reset();
+
+ // Check that we coalesce held MOUSE_DRAGGED events.
+ ui::MouseEvent mouse_dragged_event2(ui::ET_MOUSE_DRAGGED, gfx::Point(10, 10),
+ gfx::Point(10, 10), 0, 0);
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
+ EXPECT_TRUE(recorder.events().empty());
+ DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
+ EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
+ EventTypesToString(recorder.events()));
+ recorder.Reset();
+
+ // Check that on ReleasePointerMoves, held events are not dispatched
+ // immediately, but posted instead.
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
+ host()->dispatcher()->ReleasePointerMoves();
+ EXPECT_TRUE(recorder.events().empty());
+ RunAllPendingInMessageLoop();
+ EXPECT_EQ("MOUSE_DRAGGED", EventTypesToString(recorder.events()));
+ recorder.Reset();
+
+ // However if another message comes in before the dispatch of the posted
+ // event, check that the posted event is dispatched before this new event.
+ host()->dispatcher()->HoldPointerMoves();
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
+ host()->dispatcher()->ReleasePointerMoves();
+ DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
+ EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
+ EventTypesToString(recorder.events()));
+ recorder.Reset();
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+
+ // Check that if the other message is another MOUSE_DRAGGED, we still coalesce
+ // them.
+ host()->dispatcher()->HoldPointerMoves();
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
+ host()->dispatcher()->ReleasePointerMoves();
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
+ EXPECT_EQ("MOUSE_DRAGGED", EventTypesToString(recorder.events()));
+ recorder.Reset();
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+
+ // Check that synthetic mouse move event has a right location when issued
+ // while holding pointer moves.
+ ui::MouseEvent mouse_dragged_event3(ui::ET_MOUSE_DRAGGED, gfx::Point(28, 28),
+ gfx::Point(28, 28), 0, 0);
+ host()->dispatcher()->HoldPointerMoves();
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
+ window->SetBounds(gfx::Rect(15, 15, 80, 80));
+ DispatchEventUsingWindowDispatcher(&mouse_dragged_event3);
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+ host()->dispatcher()->ReleasePointerMoves();
+ RunAllPendingInMessageLoop();
+ EXPECT_EQ("MOUSE_MOVED", EventTypesToString(recorder.events()));
+ EXPECT_EQ(gfx::Point(13, 13), recorder.mouse_location(0));
+ recorder.Reset();
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+TEST_F(WindowEventDispatcherTest, TouchMovesHeld) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
+
+ const gfx::Point touch_location(60, 60);
+ // Starting the touch and throwing out the first few events, since the system
+ // is going to generate synthetic mouse events that are not relevant to the
+ // test.
+ ui::TouchEvent touch_pressed_event(
+ ui::ET_TOUCH_PRESSED, touch_location, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&touch_pressed_event);
+ recorder.WaitUntilReceivedEvent(ui::ET_GESTURE_SHOW_PRESS);
+ recorder.Reset();
+
+ host()->dispatcher()->HoldPointerMoves();
+
+ // Check that we don't immediately dispatch the TOUCH_MOVED event.
+ ui::TouchEvent touch_moved_event(
+ ui::ET_TOUCH_MOVED, touch_location, 0, ui::EventTimeForNow());
+ ui::TouchEvent touch_moved_event2 = touch_moved_event;
+ ui::TouchEvent touch_moved_event3 = touch_moved_event;
+
+ DispatchEventUsingWindowDispatcher(&touch_moved_event);
+ EXPECT_TRUE(recorder.events().empty());
+
+ // Check that on ReleasePointerMoves, held events are not dispatched
+ // immediately, but posted instead.
+ DispatchEventUsingWindowDispatcher(&touch_moved_event2);
+ host()->dispatcher()->ReleasePointerMoves();
+ EXPECT_TRUE(recorder.events().empty());
+
+ RunAllPendingInMessageLoop();
+ EXPECT_EQ("TOUCH_MOVED", EventTypesToString(recorder.events()));
+ recorder.Reset();
+
+ // If another touch event occurs then the held touch should be dispatched
+ // immediately before it.
+ ui::TouchEvent touch_released_event(
+ ui::ET_TOUCH_RELEASED, touch_location, 0, ui::EventTimeForNow());
+ recorder.Reset();
+ host()->dispatcher()->HoldPointerMoves();
+ DispatchEventUsingWindowDispatcher(&touch_moved_event3);
+ DispatchEventUsingWindowDispatcher(&touch_released_event);
+ EXPECT_EQ("TOUCH_MOVED TOUCH_RELEASED GESTURE_TAP GESTURE_END",
+ EventTypesToString(recorder.events()));
+ recorder.Reset();
+ host()->dispatcher()->ReleasePointerMoves();
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+}
+
+// This event handler requests the dispatcher to start holding pointer-move
+// events when it receives the first scroll-update gesture.
+class HoldPointerOnScrollHandler : public ui::test::TestEventHandler {
+ public:
+ HoldPointerOnScrollHandler(WindowEventDispatcher* dispatcher,
+ EventFilterRecorder* filter)
+ : dispatcher_(dispatcher),
+ filter_(filter),
+ holding_moves_(false) {}
+ virtual ~HoldPointerOnScrollHandler() {}
+
+ private:
+ // ui::test::TestEventHandler:
+ virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE {
+ if (!holding_moves_ && gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
+ holding_moves_ = true;
+ dispatcher_->HoldPointerMoves();
+ filter_->Reset();
+ } else if (gesture->type() == ui::ET_GESTURE_SCROLL_END) {
+ dispatcher_->ReleasePointerMoves();
+ holding_moves_ = false;
+ }
+ }
+
+ WindowEventDispatcher* dispatcher_;
+ EventFilterRecorder* filter_;
+ bool holding_moves_;
+
+ DISALLOW_COPY_AND_ASSIGN(HoldPointerOnScrollHandler);
+};
+
+// Tests that touch-move events don't contribute to an in-progress scroll
+// gesture if touch-move events are being held by the dispatcher.
+TEST_F(WindowEventDispatcherTest, TouchMovesHeldOnScroll) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+ test::TestWindowDelegate delegate;
+ HoldPointerOnScrollHandler handler(host()->dispatcher(), &recorder);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
+ window->AddPreTargetHandler(&handler);
+
+ test::EventGenerator generator(root_window());
+ generator.GestureScrollSequence(
+ gfx::Point(60, 60), gfx::Point(10, 60),
+ base::TimeDelta::FromMilliseconds(100), 25);
+
+ // |handler| will have reset |filter| and started holding the touch-move
+ // events when scrolling started. At the end of the scroll (i.e. upon
+ // touch-release), the held touch-move event will have been dispatched first,
+ // along with the subsequent events (i.e. touch-release, scroll-end, and
+ // gesture-end).
+ const EventFilterRecorder::Events& events = recorder.events();
+ EXPECT_EQ(
+ "TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
+ "GESTURE_SCROLL_END GESTURE_END",
+ EventTypesToString(events));
+ ASSERT_EQ(2u, recorder.touch_locations().size());
+ EXPECT_EQ(gfx::Point(-40, 10).ToString(),
+ recorder.touch_locations()[0].ToString());
+ EXPECT_EQ(gfx::Point(-40, 10).ToString(),
+ recorder.touch_locations()[1].ToString());
+}
+
+// Tests that a 'held' touch-event does contribute to gesture event when it is
+// dispatched.
+TEST_F(WindowEventDispatcherTest, HeldTouchMoveContributesToGesture) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ const gfx::Point location(20, 20);
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED, location, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press);
+ EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_PRESSED));
+ recorder.Reset();
+
+ host()->dispatcher()->HoldPointerMoves();
+
+ ui::TouchEvent move(ui::ET_TOUCH_MOVED,
+ location + gfx::Vector2d(100, 100),
+ 0,
+ ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&move);
+ EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
+ EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_BEGIN));
+ recorder.Reset();
+
+ host()->dispatcher()->ReleasePointerMoves();
+ EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
+ EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_BEGIN));
+ EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_UPDATE));
+
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+// Tests that synthetic mouse events are ignored when mouse
+// events are disabled.
+TEST_F(WindowEventDispatcherTest, DispatchSyntheticMouseEvents) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
+ window->Show();
+ window->SetCapture();
+
+ test::TestCursorClient cursor_client(root_window());
+
+ // Dispatch a non-synthetic mouse event when mouse events are enabled.
+ ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
+ gfx::Point(10, 10), 0, 0);
+ DispatchEventUsingWindowDispatcher(&mouse1);
+ EXPECT_FALSE(recorder.events().empty());
+ recorder.Reset();
+
+ // Dispatch a synthetic mouse event when mouse events are enabled.
+ ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
+ gfx::Point(10, 10), ui::EF_IS_SYNTHESIZED, 0);
+ DispatchEventUsingWindowDispatcher(&mouse2);
+ EXPECT_FALSE(recorder.events().empty());
+ recorder.Reset();
+
+ // Dispatch a synthetic mouse event when mouse events are disabled.
+ cursor_client.DisableMouseEvents();
+ DispatchEventUsingWindowDispatcher(&mouse2);
+ EXPECT_TRUE(recorder.events().empty());
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+// Tests that a mouse-move event is not synthesized when a mouse-button is down.
+TEST_F(WindowEventDispatcherTest, DoNotSynthesizeWhileButtonDown) {
+ EventFilterRecorder recorder;
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
+ window->Show();
+
+ window->AddPreTargetHandler(&recorder);
+ // Dispatch a non-synthetic mouse event when mouse events are enabled.
+ ui::MouseEvent mouse1(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
+ gfx::Point(10, 10), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ DispatchEventUsingWindowDispatcher(&mouse1);
+ ASSERT_EQ(1u, recorder.events().size());
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, recorder.events()[0]);
+ window->RemovePreTargetHandler(&recorder);
+ recorder.Reset();
+
+ // Move |window| away from underneath the cursor.
+ root_window()->AddPreTargetHandler(&recorder);
+ window->SetBounds(gfx::Rect(30, 30, 100, 100));
+ EXPECT_TRUE(recorder.events().empty());
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+// Tests synthetic mouse events generated when window bounds changes such that
+// the cursor previously outside the window becomes inside, or vice versa.
+// Do not synthesize events if the window ignores events or is invisible.
+TEST_F(WindowEventDispatcherTest, SynthesizeMouseEventsOnWindowBoundsChanged) {
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
+ window->Show();
+ window->SetCapture();
+
+ EventFilterRecorder recorder;
+ window->AddPreTargetHandler(&recorder);
+
+ // Dispatch a non-synthetic mouse event to place cursor inside window bounds.
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
+ gfx::Point(10, 10), 0, 0);
+ DispatchEventUsingWindowDispatcher(&mouse);
+ EXPECT_FALSE(recorder.events().empty());
+ recorder.Reset();
+
+ // Update the window bounds so that cursor is now outside the window.
+ // This should trigger a synthetic MOVED event.
+ gfx::Rect bounds1(20, 20, 100, 100);
+ window->SetBounds(bounds1);
+ RunAllPendingInMessageLoop();
+ ASSERT_FALSE(recorder.events().empty());
+ ASSERT_FALSE(recorder.mouse_event_flags().empty());
+ EXPECT_EQ(ui::ET_MOUSE_MOVED, recorder.events().back());
+ EXPECT_EQ(ui::EF_IS_SYNTHESIZED, recorder.mouse_event_flags().back());
+ recorder.Reset();
+
+ // Set window to ignore events.
+ window->set_ignore_events(true);
+
+ // Update the window bounds so that cursor is back inside the window.
+ // This should not trigger a synthetic event.
+ gfx::Rect bounds2(5, 5, 100, 100);
+ window->SetBounds(bounds2);
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+ recorder.Reset();
+
+ // Set window to accept events but invisible.
+ window->set_ignore_events(false);
+ window->Hide();
+ recorder.Reset();
+
+ // Update the window bounds so that cursor is outside the window.
+ // This should not trigger a synthetic event.
+ window->SetBounds(bounds1);
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+}
+
+// Tests that a mouse exit is dispatched to the last known cursor location
+// when the cursor becomes invisible.
+TEST_F(WindowEventDispatcherTest, DispatchMouseExitWhenCursorHidden) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ test::TestWindowDelegate delegate;
+ gfx::Point window_origin(7, 18);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1234, gfx::Rect(window_origin, gfx::Size(100, 100)),
+ root_window()));
+ window->Show();
+
+ // Dispatch a mouse move event into the window.
+ gfx::Point mouse_location(gfx::Point(15, 25));
+ ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, mouse_location,
+ mouse_location, 0, 0);
+ EXPECT_TRUE(recorder.events().empty());
+ DispatchEventUsingWindowDispatcher(&mouse1);
+ EXPECT_FALSE(recorder.events().empty());
+ recorder.Reset();
+
+ // Hide the cursor and verify a mouse exit was dispatched.
+ host()->OnCursorVisibilityChanged(false);
+ EXPECT_FALSE(recorder.events().empty());
+ EXPECT_EQ("MOUSE_EXITED", EventTypesToString(recorder.events()));
+
+ // Verify the mouse exit was dispatched at the correct location
+ // (in the correct coordinate space).
+ int translated_x = mouse_location.x() - window_origin.x();
+ int translated_y = mouse_location.y() - window_origin.y();
+ gfx::Point translated_point(translated_x, translated_y);
+ EXPECT_EQ(recorder.mouse_location(0).ToString(), translated_point.ToString());
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+// Tests that a synthetic mouse exit is dispatched to the last known cursor
+// location after mouse events are disabled on the cursor client.
+TEST_F(WindowEventDispatcherTest,
+ DispatchSyntheticMouseExitAfterMouseEventsDisabled) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ test::TestWindowDelegate delegate;
+ gfx::Point window_origin(7, 18);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1234, gfx::Rect(window_origin, gfx::Size(100, 100)),
+ root_window()));
+ window->Show();
+
+ // Dispatch a mouse move event into the window.
+ gfx::Point mouse_location(gfx::Point(15, 25));
+ ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, mouse_location,
+ mouse_location, 0, 0);
+ EXPECT_TRUE(recorder.events().empty());
+ DispatchEventUsingWindowDispatcher(&mouse1);
+ EXPECT_FALSE(recorder.events().empty());
+ recorder.Reset();
+
+ test::TestCursorClient cursor_client(root_window());
+ cursor_client.DisableMouseEvents();
+
+ gfx::Point mouse_exit_location(gfx::Point(150, 150));
+ ui::MouseEvent mouse2(ui::ET_MOUSE_EXITED, gfx::Point(150, 150),
+ gfx::Point(150, 150), ui::EF_IS_SYNTHESIZED, 0);
+ DispatchEventUsingWindowDispatcher(&mouse2);
+
+ EXPECT_FALSE(recorder.events().empty());
+ // We get the mouse exited event twice in our filter. Once during the
+ // predispatch phase and during the actual dispatch.
+ EXPECT_EQ("MOUSE_EXITED MOUSE_EXITED", EventTypesToString(recorder.events()));
+
+ // Verify the mouse exit was dispatched at the correct location
+ // (in the correct coordinate space).
+ int translated_x = mouse_exit_location.x() - window_origin.x();
+ int translated_y = mouse_exit_location.y() - window_origin.y();
+ gfx::Point translated_point(translated_x, translated_y);
+ EXPECT_EQ(recorder.mouse_location(0).ToString(), translated_point.ToString());
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+class DeletingEventFilter : public ui::EventHandler {
+ public:
+ DeletingEventFilter()
+ : delete_during_pre_handle_(false) {}
+ virtual ~DeletingEventFilter() {}
+
+ void Reset(bool delete_during_pre_handle) {
+ delete_during_pre_handle_ = delete_during_pre_handle;
+ }
+
+ private:
+ // Overridden from ui::EventHandler:
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
+ if (delete_during_pre_handle_)
+ delete event->target();
+ }
+
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ if (delete_during_pre_handle_)
+ delete event->target();
+ }
+
+ bool delete_during_pre_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeletingEventFilter);
+};
+
+class DeletingWindowDelegate : public test::TestWindowDelegate {
+ public:
+ DeletingWindowDelegate()
+ : window_(NULL),
+ delete_during_handle_(false),
+ got_event_(false) {}
+ virtual ~DeletingWindowDelegate() {}
+
+ void Reset(Window* window, bool delete_during_handle) {
+ window_ = window;
+ delete_during_handle_ = delete_during_handle;
+ got_event_ = false;
+ }
+ bool got_event() const { return got_event_; }
+
+ private:
+ // Overridden from WindowDelegate:
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
+ if (delete_during_handle_)
+ delete window_;
+ got_event_ = true;
+ }
+
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ if (delete_during_handle_)
+ delete window_;
+ got_event_ = true;
+ }
+
+ Window* window_;
+ bool delete_during_handle_;
+ bool got_event_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeletingWindowDelegate);
+};
+
+TEST_F(WindowEventDispatcherTest, DeleteWindowDuringDispatch) {
+ // Verifies that we can delete a window during each phase of event handling.
+ // Deleting the window should not cause a crash, only prevent further
+ // processing from occurring.
+ scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
+ DeletingWindowDelegate d11;
+ Window* w11 = CreateNormalWindow(11, w1.get(), &d11);
+ WindowTracker tracker;
+ DeletingEventFilter w1_filter;
+ w1->AddPreTargetHandler(&w1_filter);
+ client::GetFocusClient(w1.get())->FocusWindow(w11);
+
+ test::EventGenerator generator(root_window(), w11);
+
+ // First up, no one deletes anything.
+ tracker.Add(w11);
+ d11.Reset(w11, false);
+
+ generator.PressLeftButton();
+ EXPECT_TRUE(tracker.Contains(w11));
+ EXPECT_TRUE(d11.got_event());
+ generator.ReleaseLeftButton();
+
+ // Delegate deletes w11. This will prevent the post-handle step from applying.
+ w1_filter.Reset(false);
+ d11.Reset(w11, true);
+ generator.PressKey(ui::VKEY_A, 0);
+ EXPECT_FALSE(tracker.Contains(w11));
+ EXPECT_TRUE(d11.got_event());
+
+ // Pre-handle step deletes w11. This will prevent the delegate and the post-
+ // handle steps from applying.
+ w11 = CreateNormalWindow(11, w1.get(), &d11);
+ w1_filter.Reset(true);
+ d11.Reset(w11, false);
+ generator.PressLeftButton();
+ EXPECT_FALSE(tracker.Contains(w11));
+ EXPECT_FALSE(d11.got_event());
+}
+
+namespace {
+
+// A window delegate that detaches the parent of the target's parent window when
+// it receives a tap event.
+class DetachesParentOnTapDelegate : public test::TestWindowDelegate {
+ public:
+ DetachesParentOnTapDelegate() {}
+ virtual ~DetachesParentOnTapDelegate() {}
+
+ private:
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
+ if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
+ event->SetHandled();
+ return;
+ }
+
+ if (event->type() == ui::ET_GESTURE_TAP) {
+ Window* parent = static_cast<Window*>(event->target())->parent();
+ parent->parent()->RemoveChild(parent);
+ event->SetHandled();
+ }
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(DetachesParentOnTapDelegate);
+};
+
+} // namespace
+
+// Tests that the gesture recognizer is reset for all child windows when a
+// window hides. No expectations, just checks that the test does not crash.
+TEST_F(WindowEventDispatcherTest,
+ GestureRecognizerResetsTargetWhenParentHides) {
+ scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
+ DetachesParentOnTapDelegate delegate;
+ scoped_ptr<Window> parent(CreateNormalWindow(22, w1.get(), NULL));
+ Window* child = CreateNormalWindow(11, parent.get(), &delegate);
+ test::EventGenerator generator(root_window(), child);
+ generator.GestureTapAt(gfx::Point(40, 40));
+}
+
+namespace {
+
+// A window delegate that processes nested gestures on tap.
+class NestedGestureDelegate : public test::TestWindowDelegate {
+ public:
+ NestedGestureDelegate(test::EventGenerator* generator,
+ const gfx::Point tap_location)
+ : generator_(generator),
+ tap_location_(tap_location),
+ gesture_end_count_(0) {}
+ virtual ~NestedGestureDelegate() {}
+
+ int gesture_end_count() const { return gesture_end_count_; }
+
+ private:
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
+ switch (event->type()) {
+ case ui::ET_GESTURE_TAP_DOWN:
+ event->SetHandled();
+ break;
+ case ui::ET_GESTURE_TAP:
+ if (generator_)
+ generator_->GestureTapAt(tap_location_);
+ event->SetHandled();
+ break;
+ case ui::ET_GESTURE_END:
+ ++gesture_end_count_;
+ break;
+ default:
+ break;
+ }
+ }
+
+ test::EventGenerator* generator_;
+ const gfx::Point tap_location_;
+ int gesture_end_count_;
+ DISALLOW_COPY_AND_ASSIGN(NestedGestureDelegate);
+};
+
+} // namespace
+
+// Tests that gesture end is delivered after nested gesture processing.
+TEST_F(WindowEventDispatcherTest, GestureEndDeliveredAfterNestedGestures) {
+ NestedGestureDelegate d1(NULL, gfx::Point());
+ scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &d1));
+ w1->SetBounds(gfx::Rect(0, 0, 100, 100));
+
+ test::EventGenerator nested_generator(root_window(), w1.get());
+ NestedGestureDelegate d2(&nested_generator, w1->bounds().CenterPoint());
+ scoped_ptr<Window> w2(CreateNormalWindow(1, root_window(), &d2));
+ w2->SetBounds(gfx::Rect(100, 0, 100, 100));
+
+ // Tap on w2 which triggers nested gestures for w1.
+ test::EventGenerator generator(root_window(), w2.get());
+ generator.GestureTapAt(w2->bounds().CenterPoint());
+
+ // Both windows should get their gesture end events.
+ EXPECT_EQ(1, d1.gesture_end_count());
+ EXPECT_EQ(1, d2.gesture_end_count());
+}
+
+// Tests whether we can repost the Tap down gesture event.
+TEST_F(WindowEventDispatcherTest, RepostTapdownGestureTest) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
+
+ ui::GestureEventDetails details(ui::ET_GESTURE_TAP_DOWN, 0.0f, 0.0f);
+ gfx::Point point(10, 10);
+ ui::GestureEvent event(ui::ET_GESTURE_TAP_DOWN,
+ point.x(),
+ point.y(),
+ 0,
+ ui::EventTimeForNow(),
+ details,
+ 0);
+ host()->dispatcher()->RepostEvent(event);
+ RunAllPendingInMessageLoop();
+ // TODO(rbyers): Currently disabled - crbug.com/170987
+ EXPECT_FALSE(EventTypesToString(recorder.events()).find("GESTURE_TAP_DOWN") !=
+ std::string::npos);
+ recorder.Reset();
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+// This class inherits from the EventFilterRecorder class which provides a
+// facility to record events. This class additionally provides a facility to
+// repost the ET_GESTURE_TAP_DOWN gesture to the target window and records
+// events after that.
+class RepostGestureEventRecorder : public EventFilterRecorder {
+ public:
+ RepostGestureEventRecorder(aura::Window* repost_source,
+ aura::Window* repost_target)
+ : repost_source_(repost_source),
+ repost_target_(repost_target),
+ reposted_(false),
+ done_cleanup_(false) {}
+
+ virtual ~RepostGestureEventRecorder() {}
+
+ virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
+ if (reposted_ && event->type() == ui::ET_TOUCH_PRESSED) {
+ done_cleanup_ = true;
+ Reset();
+ }
+ EventFilterRecorder::OnTouchEvent(event);
+ }
+
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
+ EXPECT_EQ(done_cleanup_ ? repost_target_ : repost_source_, event->target());
+ if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
+ if (!reposted_) {
+ EXPECT_NE(repost_target_, event->target());
+ reposted_ = true;
+ repost_target_->GetHost()->dispatcher()->RepostEvent(*event);
+ // Ensure that the reposted gesture event above goes to the
+ // repost_target_;
+ repost_source_->GetRootWindow()->RemoveChild(repost_source_);
+ return;
+ }
+ }
+ EventFilterRecorder::OnGestureEvent(event);
+ }
+
+ // Ignore mouse events as they don't fire at all times. This causes
+ // the GestureRepostEventOrder test to fail randomly.
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {}
+
+ private:
+ aura::Window* repost_source_;
+ aura::Window* repost_target_;
+ // set to true if we reposted the ET_GESTURE_TAP_DOWN event.
+ bool reposted_;
+ // set true if we're done cleaning up after hiding repost_source_;
+ bool done_cleanup_;
+ DISALLOW_COPY_AND_ASSIGN(RepostGestureEventRecorder);
+};
+
+// Tests whether events which are generated after the reposted gesture event
+// are received after that. In this case the scroll sequence events should
+// be received after the reposted gesture event.
+TEST_F(WindowEventDispatcherTest, GestureRepostEventOrder) {
+ // Expected events at the end for the repost_target window defined below.
+ const char kExpectedTargetEvents[] =
+ // TODO)(rbyers): Gesture event reposting is disabled - crbug.com/279039.
+ // "GESTURE_BEGIN GESTURE_TAP_DOWN "
+ "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
+ "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE TOUCH_MOVED "
+ "GESTURE_SCROLL_UPDATE TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
+ "GESTURE_SCROLL_END GESTURE_END";
+ // We create two windows.
+ // The first window (repost_source) is the one to which the initial tap
+ // gesture is sent. It reposts this event to the second window
+ // (repost_target).
+ // We then generate the scroll sequence for repost_target and look for two
+ // ET_GESTURE_TAP_DOWN events in the event list at the end.
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> repost_target(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
+
+ scoped_ptr<aura::Window> repost_source(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(0, 0, 50, 50), root_window()));
+
+ RepostGestureEventRecorder repost_event_recorder(repost_source.get(),
+ repost_target.get());
+ root_window()->AddPreTargetHandler(&repost_event_recorder);
+
+ // Generate a tap down gesture for the repost_source. This will be reposted
+ // to repost_target.
+ test::EventGenerator repost_generator(root_window(), repost_source.get());
+ repost_generator.GestureTapAt(gfx::Point(40, 40));
+ RunAllPendingInMessageLoop();
+
+ test::EventGenerator scroll_generator(root_window(), repost_target.get());
+ scroll_generator.GestureScrollSequence(
+ gfx::Point(80, 80),
+ gfx::Point(100, 100),
+ base::TimeDelta::FromMilliseconds(100),
+ 3);
+ RunAllPendingInMessageLoop();
+
+ int tap_down_count = 0;
+ for (size_t i = 0; i < repost_event_recorder.events().size(); ++i) {
+ if (repost_event_recorder.events()[i] == ui::ET_GESTURE_TAP_DOWN)
+ ++tap_down_count;
+ }
+
+ // We expect two tap down events. One from the repost and the other one from
+ // the scroll sequence posted above.
+ // TODO(rbyers): Currently disabled - crbug.com/170987
+ EXPECT_EQ(1, tap_down_count);
+
+ EXPECT_EQ(kExpectedTargetEvents,
+ EventTypesToString(repost_event_recorder.events()));
+ root_window()->RemovePreTargetHandler(&repost_event_recorder);
+}
+
+class OnMouseExitDeletingEventFilter : public EventFilterRecorder {
+ public:
+ OnMouseExitDeletingEventFilter() : window_to_delete_(NULL) {}
+ virtual ~OnMouseExitDeletingEventFilter() {}
+
+ void set_window_to_delete(Window* window_to_delete) {
+ window_to_delete_ = window_to_delete;
+ }
+
+ private:
+ // Overridden from ui::EventHandler:
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ EventFilterRecorder::OnMouseEvent(event);
+ if (window_to_delete_) {
+ delete window_to_delete_;
+ window_to_delete_ = NULL;
+ }
+ }
+
+ Window* window_to_delete_;
+
+ DISALLOW_COPY_AND_ASSIGN(OnMouseExitDeletingEventFilter);
+};
+
+// Tests that RootWindow drops mouse-moved event that is supposed to be sent to
+// a child, but the child is destroyed because of the synthesized mouse-exit
+// event generated on the previous mouse_moved_handler_.
+TEST_F(WindowEventDispatcherTest, DeleteWindowDuringMouseMovedDispatch) {
+ // Create window 1 and set its event filter. Window 1 will take ownership of
+ // the event filter.
+ scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
+ OnMouseExitDeletingEventFilter w1_filter;
+ w1->AddPreTargetHandler(&w1_filter);
+ w1->SetBounds(gfx::Rect(20, 20, 60, 60));
+ EXPECT_EQ(NULL, host()->dispatcher()->mouse_moved_handler());
+
+ test::EventGenerator generator(root_window(), w1.get());
+
+ // Move mouse over window 1 to set it as the |mouse_moved_handler_| for the
+ // root window.
+ generator.MoveMouseTo(51, 51);
+ EXPECT_EQ(w1.get(), host()->dispatcher()->mouse_moved_handler());
+
+ // Create window 2 under the mouse cursor and stack it above window 1.
+ Window* w2 = CreateNormalWindow(2, root_window(), NULL);
+ w2->SetBounds(gfx::Rect(30, 30, 40, 40));
+ root_window()->StackChildAbove(w2, w1.get());
+
+ // Set window 2 as the window that is to be deleted when a mouse-exited event
+ // happens on window 1.
+ w1_filter.set_window_to_delete(w2);
+
+ // Move mosue over window 2. This should generate a mouse-exited event for
+ // window 1 resulting in deletion of window 2. The original mouse-moved event
+ // that was targeted to window 2 should be dropped since window 2 is
+ // destroyed. This test passes if no crash happens.
+ generator.MoveMouseTo(52, 52);
+ EXPECT_EQ(NULL, host()->dispatcher()->mouse_moved_handler());
+
+ // Check events received by window 1.
+ EXPECT_EQ("MOUSE_ENTERED MOUSE_MOVED MOUSE_EXITED",
+ EventTypesToString(w1_filter.events()));
+}
+
+namespace {
+
+// Used to track if OnWindowDestroying() is invoked and if there is a valid
+// RootWindow at such time.
+class ValidRootDuringDestructionWindowObserver : public aura::WindowObserver {
+ public:
+ ValidRootDuringDestructionWindowObserver(bool* got_destroying,
+ bool* has_valid_root)
+ : got_destroying_(got_destroying),
+ has_valid_root_(has_valid_root) {
+ }
+
+ // WindowObserver:
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
+ *got_destroying_ = true;
+ *has_valid_root_ = (window->GetRootWindow() != NULL);
+ }
+
+ private:
+ bool* got_destroying_;
+ bool* has_valid_root_;
+
+ DISALLOW_COPY_AND_ASSIGN(ValidRootDuringDestructionWindowObserver);
+};
+
+} // namespace
+
+// Verifies GetRootWindow() from ~Window returns a valid root.
+TEST_F(WindowEventDispatcherTest, ValidRootDuringDestruction) {
+ bool got_destroying = false;
+ bool has_valid_root = false;
+ ValidRootDuringDestructionWindowObserver observer(&got_destroying,
+ &has_valid_root);
+ {
+ scoped_ptr<WindowTreeHost> host(
+ WindowTreeHost::Create(gfx::Rect(0, 0, 100, 100)));
+ host->InitHost();
+ // Owned by WindowEventDispatcher.
+ Window* w1 = CreateNormalWindow(1, host->window(), NULL);
+ w1->AddObserver(&observer);
+ }
+ EXPECT_TRUE(got_destroying);
+ EXPECT_TRUE(has_valid_root);
+}
+
+namespace {
+
+// See description above DontResetHeldEvent for details.
+class DontResetHeldEventWindowDelegate : public test::TestWindowDelegate {
+ public:
+ explicit DontResetHeldEventWindowDelegate(aura::Window* root)
+ : root_(root),
+ mouse_event_count_(0) {}
+ virtual ~DontResetHeldEventWindowDelegate() {}
+
+ int mouse_event_count() const { return mouse_event_count_; }
+
+ // TestWindowDelegate:
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 &&
+ mouse_event_count_++ == 0) {
+ ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED,
+ gfx::Point(10, 10), gfx::Point(10, 10),
+ ui::EF_SHIFT_DOWN, 0);
+ root_->GetHost()->dispatcher()->RepostEvent(mouse_event);
+ }
+ }
+
+ private:
+ Window* root_;
+ int mouse_event_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(DontResetHeldEventWindowDelegate);
+};
+
+} // namespace
+
+// Verifies RootWindow doesn't reset |RootWindow::held_repostable_event_| after
+// dispatching. This is done by using DontResetHeldEventWindowDelegate, which
+// tracks the number of events with ui::EF_SHIFT_DOWN set (all reposted events
+// have EF_SHIFT_DOWN). When the first event is seen RepostEvent() is used to
+// schedule another reposted event.
+TEST_F(WindowEventDispatcherTest, DontResetHeldEvent) {
+ DontResetHeldEventWindowDelegate delegate(root_window());
+ scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), &delegate));
+ w1->SetBounds(gfx::Rect(0, 0, 40, 40));
+ ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED,
+ gfx::Point(10, 10), gfx::Point(10, 10),
+ ui::EF_SHIFT_DOWN, 0);
+ root_window()->GetHost()->dispatcher()->RepostEvent(pressed);
+ ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED,
+ gfx::Point(10, 10), gfx::Point(10, 10), 0, 0);
+ // Dispatch an event to flush event scheduled by way of RepostEvent().
+ DispatchEventUsingWindowDispatcher(&pressed2);
+ // Delegate should have seen reposted event (identified by way of
+ // EF_SHIFT_DOWN). Dispatch another event to flush the second
+ // RepostedEvent().
+ EXPECT_EQ(1, delegate.mouse_event_count());
+ DispatchEventUsingWindowDispatcher(&pressed2);
+ EXPECT_EQ(2, delegate.mouse_event_count());
+}
+
+namespace {
+
+// See description above DeleteHostFromHeldMouseEvent for details.
+class DeleteHostFromHeldMouseEventDelegate
+ : public test::TestWindowDelegate {
+ public:
+ explicit DeleteHostFromHeldMouseEventDelegate(WindowTreeHost* host)
+ : host_(host),
+ got_mouse_event_(false),
+ got_destroy_(false) {
+ }
+ virtual ~DeleteHostFromHeldMouseEventDelegate() {}
+
+ bool got_mouse_event() const { return got_mouse_event_; }
+ bool got_destroy() const { return got_destroy_; }
+
+ // TestWindowDelegate:
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ if ((event->flags() & ui::EF_SHIFT_DOWN) != 0) {
+ got_mouse_event_ = true;
+ delete host_;
+ }
+ }
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE {
+ got_destroy_ = true;
+ }
+
+ private:
+ WindowTreeHost* host_;
+ bool got_mouse_event_;
+ bool got_destroy_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeleteHostFromHeldMouseEventDelegate);
+};
+
+} // namespace
+
+// Verifies if a WindowTreeHost is deleted from dispatching a held mouse event
+// we don't crash.
+TEST_F(WindowEventDispatcherTest, DeleteHostFromHeldMouseEvent) {
+ // Should be deleted by |delegate|.
+ WindowTreeHost* h2 = WindowTreeHost::Create(gfx::Rect(0, 0, 100, 100));
+ h2->InitHost();
+ DeleteHostFromHeldMouseEventDelegate delegate(h2);
+ // Owned by |h2|.
+ Window* w1 = CreateNormalWindow(1, h2->window(), &delegate);
+ w1->SetBounds(gfx::Rect(0, 0, 40, 40));
+ ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED,
+ gfx::Point(10, 10), gfx::Point(10, 10),
+ ui::EF_SHIFT_DOWN, 0);
+ h2->dispatcher()->RepostEvent(pressed);
+ // RunAllPendingInMessageLoop() to make sure the |pressed| is run.
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(delegate.got_mouse_event());
+ EXPECT_TRUE(delegate.got_destroy());
+}
+
+TEST_F(WindowEventDispatcherTest, WindowHideCancelsActiveTouches) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
+
+ gfx::Point position1 = root_window()->bounds().origin();
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED, position1, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press);
+
+ EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN",
+ EventTypesToString(recorder.GetAndResetEvents()));
+
+ window->Hide();
+
+ EXPECT_EQ(ui::ET_TOUCH_CANCELLED, recorder.events()[0]);
+ EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_TAP_CANCEL));
+ EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_END));
+ EXPECT_EQ(3U, recorder.events().size());
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+TEST_F(WindowEventDispatcherTest, WindowHideCancelsActiveGestures) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));
+
+ gfx::Point position1 = root_window()->bounds().origin();
+ gfx::Point position2 = root_window()->bounds().CenterPoint();
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED, position1, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press);
+
+ ui::TouchEvent move(
+ ui::ET_TOUCH_MOVED, position2, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&move);
+
+ ui::TouchEvent press2(
+ ui::ET_TOUCH_PRESSED, position1, 1, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press2);
+
+ // TODO(tdresser): once the unified Gesture Recognizer has stuck, remove the
+ // special casing here. See crbug.com/332418 for details.
+ std::string expected =
+ "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
+ "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
+ "TOUCH_PRESSED GESTURE_BEGIN GESTURE_PINCH_BEGIN";
+
+ std::string expected_ugr =
+ "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
+ "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
+ "TOUCH_PRESSED GESTURE_BEGIN";
+
+ std::string events_string = EventTypesToString(recorder.GetAndResetEvents());
+ EXPECT_TRUE((expected == events_string) || (expected_ugr == events_string));
+
+ window->Hide();
+
+ expected =
+ "TOUCH_CANCELLED GESTURE_PINCH_END GESTURE_END TOUCH_CANCELLED "
+ "GESTURE_SCROLL_END GESTURE_END";
+ expected_ugr =
+ "TOUCH_CANCELLED GESTURE_SCROLL_END GESTURE_END GESTURE_END "
+ "TOUCH_CANCELLED";
+
+ events_string = EventTypesToString(recorder.GetAndResetEvents());
+ EXPECT_TRUE((expected == events_string) || (expected_ugr == events_string));
+
+ root_window()->RemovePreTargetHandler(&recorder);
+}
+
+// Places two windows side by side. Presses down on one window, and starts a
+// scroll. Sets capture on the other window and ensures that the "ending" events
+// aren't sent to the window which gained capture.
+TEST_F(WindowEventDispatcherTest, EndingEventDoesntRetarget) {
+ EventFilterRecorder recorder1;
+ EventFilterRecorder recorder2;
+ scoped_ptr<Window> window1(CreateNormalWindow(1, root_window(), NULL));
+ window1->SetBounds(gfx::Rect(0, 0, 40, 40));
+
+ scoped_ptr<Window> window2(CreateNormalWindow(2, root_window(), NULL));
+ window2->SetBounds(gfx::Rect(40, 0, 40, 40));
+
+ window1->AddPreTargetHandler(&recorder1);
+ window2->AddPreTargetHandler(&recorder2);
+
+ gfx::Point position = window1->bounds().origin();
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED, position, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&press);
+
+ gfx::Point position2 = window1->bounds().CenterPoint();
+ ui::TouchEvent move(
+ ui::ET_TOUCH_MOVED, position2, 0, ui::EventTimeForNow());
+ DispatchEventUsingWindowDispatcher(&move);
+
+ window2->SetCapture();
+
+ EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
+ "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
+ "TOUCH_CANCELLED GESTURE_SCROLL_END GESTURE_END",
+ EventTypesToString(recorder1.events()));
+
+ EXPECT_TRUE(recorder2.events().empty());
+}
+
+namespace {
+
+// This class creates and manages a window which is destroyed as soon as
+// capture is lost. This is the case for the drag and drop capture window.
+class CaptureWindowTracker : public test::TestWindowDelegate {
+ public:
+ CaptureWindowTracker() {}
+ virtual ~CaptureWindowTracker() {}
+
+ void CreateCaptureWindow(aura::Window* root_window) {
+ capture_window_.reset(test::CreateTestWindowWithDelegate(
+ this, -1234, gfx::Rect(20, 20, 20, 20), root_window));
+ capture_window_->SetCapture();
+ }
+
+ void reset() {
+ capture_window_.reset();
+ }
+
+ virtual void OnCaptureLost() OVERRIDE {
+ capture_window_.reset();
+ }
+
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE {
+ TestWindowDelegate::OnWindowDestroyed(window);
+ capture_window_.reset();
+ }
+
+ aura::Window* capture_window() { return capture_window_.get(); }
+
+ private:
+ scoped_ptr<aura::Window> capture_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(CaptureWindowTracker);
+};
+
+}
+
+// Verifies handling loss of capture by the capture window being hidden.
+TEST_F(WindowEventDispatcherTest, CaptureWindowHidden) {
+ CaptureWindowTracker capture_window_tracker;
+ capture_window_tracker.CreateCaptureWindow(root_window());
+ capture_window_tracker.capture_window()->Hide();
+ EXPECT_EQ(NULL, capture_window_tracker.capture_window());
+}
+
+// Verifies handling loss of capture by the capture window being destroyed.
+TEST_F(WindowEventDispatcherTest, CaptureWindowDestroyed) {
+ CaptureWindowTracker capture_window_tracker;
+ capture_window_tracker.CreateCaptureWindow(root_window());
+ capture_window_tracker.reset();
+ EXPECT_EQ(NULL, capture_window_tracker.capture_window());
+}
+
+class ExitMessageLoopOnMousePress : public ui::test::TestEventHandler {
+ public:
+ ExitMessageLoopOnMousePress() {}
+ virtual ~ExitMessageLoopOnMousePress() {}
+
+ protected:
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ ui::test::TestEventHandler::OnMouseEvent(event);
+ if (event->type() == ui::ET_MOUSE_PRESSED)
+ base::MessageLoopForUI::current()->Quit();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ExitMessageLoopOnMousePress);
+};
+
+class WindowEventDispatcherTestWithMessageLoop
+ : public WindowEventDispatcherTest {
+ public:
+ WindowEventDispatcherTestWithMessageLoop() {}
+ virtual ~WindowEventDispatcherTestWithMessageLoop() {}
+
+ void RunTest() {
+ // Reset any event the window may have received when bringing up the window
+ // (e.g. mouse-move events if the mouse cursor is over the window).
+ handler_.Reset();
+
+ // Start a nested message-loop, post an event to be dispatched, and then
+ // terminate the message-loop. When the message-loop unwinds and gets back,
+ // the reposted event should not have fired.
+ scoped_ptr<ui::MouseEvent> mouse(new ui::MouseEvent(ui::ET_MOUSE_PRESSED,
+ gfx::Point(10, 10),
+ gfx::Point(10, 10),
+ ui::EF_NONE,
+ ui::EF_NONE));
+ message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&WindowEventDispatcherTestWithMessageLoop::RepostEventHelper,
+ host()->dispatcher(),
+ base::Passed(&mouse)));
+ message_loop()->PostTask(FROM_HERE, message_loop()->QuitClosure());
+
+ base::MessageLoop::ScopedNestableTaskAllower allow(message_loop());
+ base::RunLoop loop;
+ loop.Run();
+ EXPECT_EQ(0, handler_.num_mouse_events());
+
+ // Let the current message-loop run. The event-handler will terminate the
+ // message-loop when it receives the reposted event.
+ }
+
+ base::MessageLoop* message_loop() {
+ return base::MessageLoopForUI::current();
+ }
+
+ protected:
+ virtual void SetUp() OVERRIDE {
+ WindowEventDispatcherTest::SetUp();
+ window_.reset(CreateNormalWindow(1, root_window(), NULL));
+ window_->AddPreTargetHandler(&handler_);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ window_.reset();
+ WindowEventDispatcherTest::TearDown();
+ }
+
+ private:
+ // Used to avoid a copying |event| when binding to a closure.
+ static void RepostEventHelper(WindowEventDispatcher* dispatcher,
+ scoped_ptr<ui::MouseEvent> event) {
+ dispatcher->RepostEvent(*event);
+ }
+
+ scoped_ptr<Window> window_;
+ ExitMessageLoopOnMousePress handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowEventDispatcherTestWithMessageLoop);
+};
+
+TEST_F(WindowEventDispatcherTestWithMessageLoop, EventRepostedInNonNestedLoop) {
+ CHECK(!message_loop()->is_running());
+ // Perform the test in a callback, so that it runs after the message-loop
+ // starts.
+ message_loop()->PostTask(
+ FROM_HERE, base::Bind(
+ &WindowEventDispatcherTestWithMessageLoop::RunTest,
+ base::Unretained(this)));
+ message_loop()->Run();
+}
+
+class WindowEventDispatcherTestInHighDPI : public WindowEventDispatcherTest {
+ public:
+ WindowEventDispatcherTestInHighDPI() {}
+ virtual ~WindowEventDispatcherTestInHighDPI() {}
+
+ protected:
+ virtual void SetUp() OVERRIDE {
+ WindowEventDispatcherTest::SetUp();
+ test_screen()->SetDeviceScaleFactor(2.f);
+ }
+};
+
+TEST_F(WindowEventDispatcherTestInHighDPI, EventLocationTransform) {
+ test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> child(test::CreateTestWindowWithDelegate(&delegate,
+ 1234, gfx::Rect(20, 20, 100, 100), root_window()));
+ child->Show();
+
+ ui::test::TestEventHandler handler_child;
+ ui::test::TestEventHandler handler_root;
+ root_window()->AddPreTargetHandler(&handler_root);
+ child->AddPreTargetHandler(&handler_child);
+
+ {
+ ui::MouseEvent move(ui::ET_MOUSE_MOVED,
+ gfx::Point(30, 30), gfx::Point(30, 30),
+ ui::EF_NONE, ui::EF_NONE);
+ DispatchEventUsingWindowDispatcher(&move);
+ EXPECT_EQ(0, handler_child.num_mouse_events());
+ EXPECT_EQ(1, handler_root.num_mouse_events());
+ }
+
+ {
+ ui::MouseEvent move(ui::ET_MOUSE_MOVED,
+ gfx::Point(50, 50), gfx::Point(50, 50),
+ ui::EF_NONE, ui::EF_NONE);
+ DispatchEventUsingWindowDispatcher(&move);
+ // The child receives an ENTER, and a MOVED event.
+ EXPECT_EQ(2, handler_child.num_mouse_events());
+ // The root receives both the ENTER and the MOVED events dispatched to
+ // |child|, as well as an EXIT event.
+ EXPECT_EQ(3, handler_root.num_mouse_events());
+ }
+
+ child->RemovePreTargetHandler(&handler_child);
+ root_window()->RemovePreTargetHandler(&handler_root);
+}
+
+TEST_F(WindowEventDispatcherTestInHighDPI, TouchMovesHeldOnScroll) {
+ EventFilterRecorder recorder;
+ root_window()->AddPreTargetHandler(&recorder);
+ test::TestWindowDelegate delegate;
+ HoldPointerOnScrollHandler handler(host()->dispatcher(), &recorder);
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
+ window->AddPreTargetHandler(&handler);
+
+ test::EventGenerator generator(root_window());
+ generator.GestureScrollSequence(
+ gfx::Point(120, 120), gfx::Point(20, 120),
+ base::TimeDelta::FromMilliseconds(100), 25);
+
+ // |handler| will have reset |filter| and started holding the touch-move
+ // events when scrolling started. At the end of the scroll (i.e. upon
+ // touch-release), the held touch-move event will have been dispatched first,
+ // along with the subsequent events (i.e. touch-release, scroll-end, and
+ // gesture-end).
+ const EventFilterRecorder::Events& events = recorder.events();
+ EXPECT_EQ(
+ "TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
+ "GESTURE_SCROLL_END GESTURE_END",
+ EventTypesToString(events));
+ ASSERT_EQ(2u, recorder.touch_locations().size());
+ EXPECT_EQ(gfx::Point(-40, 10).ToString(),
+ recorder.touch_locations()[0].ToString());
+ EXPECT_EQ(gfx::Point(-40, 10).ToString(),
+ recorder.touch_locations()[1].ToString());
+}
+
+class SelfDestructDelegate : public test::TestWindowDelegate {
+ public:
+ SelfDestructDelegate() {}
+ virtual ~SelfDestructDelegate() {}
+
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ window_.reset();
+ }
+
+ void set_window(scoped_ptr<aura::Window> window) {
+ window_ = window.Pass();
+ }
+ bool has_window() const { return !!window_.get(); }
+
+ private:
+ scoped_ptr<aura::Window> window_;
+ DISALLOW_COPY_AND_ASSIGN(SelfDestructDelegate);
+};
+
+TEST_F(WindowEventDispatcherTest, SynthesizedLocatedEvent) {
+ test::EventGenerator generator(root_window());
+ generator.MoveMouseTo(10, 10);
+ EXPECT_EQ("10,10",
+ Env::GetInstance()->last_mouse_location().ToString());
+
+ // Synthesized event should not update the mouse location.
+ ui::MouseEvent mouseev(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
+ ui::EF_IS_SYNTHESIZED, 0);
+ generator.Dispatch(&mouseev);
+ EXPECT_EQ("10,10",
+ Env::GetInstance()->last_mouse_location().ToString());
+
+ generator.MoveMouseTo(0, 0);
+ EXPECT_EQ("0,0",
+ Env::GetInstance()->last_mouse_location().ToString());
+
+ // Make sure the location gets updated when a syntheiszed enter
+ // event destroyed the window.
+ SelfDestructDelegate delegate;
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
+ delegate.set_window(window.Pass());
+ EXPECT_TRUE(delegate.has_window());
+
+ generator.MoveMouseTo(100, 100);
+ EXPECT_FALSE(delegate.has_window());
+ EXPECT_EQ("100,100",
+ Env::GetInstance()->last_mouse_location().ToString());
+}
+
+class StaticFocusClient : public client::FocusClient {
+ public:
+ explicit StaticFocusClient(Window* focused)
+ : focused_(focused) {}
+ virtual ~StaticFocusClient() {}
+
+ private:
+ // client::FocusClient:
+ virtual void AddObserver(client::FocusChangeObserver* observer) OVERRIDE {}
+ virtual void RemoveObserver(client::FocusChangeObserver* observer) OVERRIDE {}
+ virtual void FocusWindow(Window* window) OVERRIDE {}
+ virtual void ResetFocusWithinActiveWindow(Window* window) OVERRIDE {}
+ virtual Window* GetFocusedWindow() OVERRIDE { return focused_; }
+
+ Window* focused_;
+
+ DISALLOW_COPY_AND_ASSIGN(StaticFocusClient);
+};
+
+// Tests that host-cancel-mode event can be dispatched to a dispatcher safely
+// when the focused window does not live in the dispatcher's tree.
+TEST_F(WindowEventDispatcherTest, HostCancelModeWithFocusedWindowOutside) {
+ test::TestWindowDelegate delegate;
+ scoped_ptr<Window> focused(CreateTestWindowWithDelegate(&delegate, 123,
+ gfx::Rect(20, 30, 100, 50), NULL));
+ StaticFocusClient focus_client(focused.get());
+ client::SetFocusClient(root_window(), &focus_client);
+ EXPECT_FALSE(root_window()->Contains(focused.get()));
+ EXPECT_EQ(focused.get(),
+ client::GetFocusClient(root_window())->GetFocusedWindow());
+ host()->dispatcher()->DispatchCancelModeEvent();
+ EXPECT_EQ(focused.get(),
+ client::GetFocusClient(root_window())->GetFocusedWindow());
+}
+
+// Dispatches a mouse-move event to |target| when it receives a mouse-move
+// event.
+class DispatchEventHandler : public ui::EventHandler {
+ public:
+ explicit DispatchEventHandler(Window* target)
+ : target_(target),
+ dispatched_(false) {}
+ virtual ~DispatchEventHandler() {}
+
+ bool dispatched() const { return dispatched_; }
+ private:
+ // ui::EventHandler:
+ virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
+ if (mouse->type() == ui::ET_MOUSE_MOVED) {
+ ui::MouseEvent move(ui::ET_MOUSE_MOVED, target_->bounds().CenterPoint(),
+ target_->bounds().CenterPoint(), ui::EF_NONE, ui::EF_NONE);
+ ui::EventDispatchDetails details =
+ target_->GetHost()->dispatcher()->OnEventFromSource(&move);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+ EXPECT_EQ(target_, move.target());
+ dispatched_ = true;
+ }
+ ui::EventHandler::OnMouseEvent(mouse);
+ }
+
+ Window* target_;
+ bool dispatched_;
+
+ DISALLOW_COPY_AND_ASSIGN(DispatchEventHandler);
+};
+
+// Moves |window| to |root_window| when it receives a mouse-move event.
+class MoveWindowHandler : public ui::EventHandler {
+ public:
+ MoveWindowHandler(Window* window, Window* root_window)
+ : window_to_move_(window),
+ root_window_to_move_to_(root_window) {}
+ virtual ~MoveWindowHandler() {}
+
+ private:
+ // ui::EventHandler:
+ virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
+ if (mouse->type() == ui::ET_MOUSE_MOVED) {
+ root_window_to_move_to_->AddChild(window_to_move_);
+ }
+ ui::EventHandler::OnMouseEvent(mouse);
+ }
+
+ Window* window_to_move_;
+ Window* root_window_to_move_to_;
+
+ DISALLOW_COPY_AND_ASSIGN(MoveWindowHandler);
+};
+
+// Tests that nested event dispatch works correctly if the target of the older
+// event being dispatched is moved to a different dispatcher in response to an
+// event in the inner loop.
+TEST_F(WindowEventDispatcherTest, NestedEventDispatchTargetMoved) {
+ scoped_ptr<WindowTreeHost> second_host(
+ WindowTreeHost::Create(gfx::Rect(20, 30, 100, 50)));
+ second_host->InitHost();
+ Window* second_root = second_host->window();
+
+ // Create two windows parented to |root_window()|.
+ test::TestWindowDelegate delegate;
+ scoped_ptr<Window> first(CreateTestWindowWithDelegate(&delegate, 123,
+ gfx::Rect(20, 10, 10, 20), root_window()));
+ scoped_ptr<Window> second(CreateTestWindowWithDelegate(&delegate, 234,
+ gfx::Rect(40, 10, 50, 20), root_window()));
+
+ // Setup a handler on |first| so that it dispatches an event to |second| when
+ // |first| receives an event.
+ DispatchEventHandler dispatch_event(second.get());
+ first->AddPreTargetHandler(&dispatch_event);
+
+ // Setup a handler on |second| so that it moves |first| into |second_root|
+ // when |second| receives an event.
+ MoveWindowHandler move_window(first.get(), second_root);
+ second->AddPreTargetHandler(&move_window);
+
+ // Some sanity checks: |first| is inside |root_window()|'s tree.
+ EXPECT_EQ(root_window(), first->GetRootWindow());
+ // The two root windows are different.
+ EXPECT_NE(root_window(), second_root);
+
+ // Dispatch an event to |first|.
+ ui::MouseEvent move(ui::ET_MOUSE_MOVED, first->bounds().CenterPoint(),
+ first->bounds().CenterPoint(), ui::EF_NONE, ui::EF_NONE);
+ ui::EventDispatchDetails details =
+ host()->dispatcher()->OnEventFromSource(&move);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ EXPECT_TRUE(details.target_destroyed);
+ EXPECT_EQ(first.get(), move.target());
+ EXPECT_TRUE(dispatch_event.dispatched());
+ EXPECT_EQ(second_root, first->GetRootWindow());
+
+ first->RemovePreTargetHandler(&dispatch_event);
+ second->RemovePreTargetHandler(&move_window);
+}
+
+class AlwaysMouseDownInputStateLookup : public InputStateLookup {
+ public:
+ AlwaysMouseDownInputStateLookup() {}
+ virtual ~AlwaysMouseDownInputStateLookup() {}
+
+ private:
+ // InputStateLookup:
+ virtual bool IsMouseButtonDown() const OVERRIDE { return true; }
+
+ DISALLOW_COPY_AND_ASSIGN(AlwaysMouseDownInputStateLookup);
+};
+
+TEST_F(WindowEventDispatcherTest,
+ CursorVisibilityChangedWhileCaptureWindowInAnotherDispatcher) {
+ test::EventCountDelegate delegate;
+ scoped_ptr<Window> window(CreateTestWindowWithDelegate(&delegate, 123,
+ gfx::Rect(20, 10, 10, 20), root_window()));
+ window->Show();
+
+ scoped_ptr<WindowTreeHost> second_host(
+ WindowTreeHost::Create(gfx::Rect(20, 30, 100, 50)));
+ second_host->InitHost();
+ WindowEventDispatcher* second_dispatcher = second_host->dispatcher();
+
+ // Install an InputStateLookup on the Env that always claims that a
+ // mouse-button is down.
+ test::EnvTestHelper(Env::GetInstance()).SetInputStateLookup(
+ scoped_ptr<InputStateLookup>(new AlwaysMouseDownInputStateLookup()));
+
+ window->SetCapture();
+
+ // Because the mouse button is down, setting the capture on |window| will set
+ // it as the mouse-move handler for |root_window()|.
+ EXPECT_EQ(window.get(), host()->dispatcher()->mouse_moved_handler());
+
+ // This does not set |window| as the mouse-move handler for the second
+ // dispatcher.
+ EXPECT_EQ(NULL, second_dispatcher->mouse_moved_handler());
+
+ // However, some capture-client updates the capture in each root-window on a
+ // capture. Emulate that here. Because of this, the second dispatcher also has
+ // |window| as the mouse-move handler.
+ client::CaptureDelegate* second_capture_delegate = second_dispatcher;
+ second_capture_delegate->UpdateCapture(NULL, window.get());
+ EXPECT_EQ(window.get(), second_dispatcher->mouse_moved_handler());
+
+ // Reset the mouse-event counts for |window|.
+ delegate.GetMouseMotionCountsAndReset();
+
+ // Notify both hosts that the cursor is now hidden. This should send a single
+ // mouse-exit event to |window|.
+ host()->OnCursorVisibilityChanged(false);
+ second_host->OnCursorVisibilityChanged(false);
+ EXPECT_EQ("0 0 1", delegate.GetMouseMotionCountsAndReset());
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/window_observer.cc b/chromium/ui/aura/window_observer.cc
new file mode 100644
index 00000000000..24d51d47df0
--- /dev/null
+++ b/chromium/ui/aura/window_observer.cc
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/window_observer.h"
+
+#include "base/logging.h"
+#include "ui/aura/window.h"
+
+namespace aura {
+
+WindowObserver::WindowObserver() : observing_(0) {
+}
+
+WindowObserver::~WindowObserver() {
+ // TODO(flackr): Remove this check and observing_ counter when the cause of
+ // http://crbug.com/365364 is discovered.
+ CHECK_EQ(0, observing_);
+}
+
+void WindowObserver::OnObservingWindow(aura::Window* window) {
+ if (!window->HasObserver(this))
+ observing_++;
+}
+
+void WindowObserver::OnUnobservingWindow(aura::Window* window) {
+ if (window->HasObserver(this))
+ observing_--;
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/window_observer.h b/chromium/ui/aura/window_observer.h
index 9408ee831dd..ef1259a234d 100644
--- a/chromium/ui/aura/window_observer.h
+++ b/chromium/ui/aura/window_observer.h
@@ -31,6 +31,8 @@ class AURA_EXPORT WindowObserver {
Window* receiver; // The window receiving the notification.
};
+ WindowObserver();
+
// Called when a window is added or removed. Notifications are sent to the
// following hierarchies in this order:
// 1. |target|.
@@ -75,6 +77,10 @@ class AURA_EXPORT WindowObserver {
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {}
+ // Invoked when SetTransform() is invoked on |window|.
+ virtual void OnWindowTransforming(Window* window) {}
+ virtual void OnWindowTransformed(Window* window) {}
+
// Invoked when |window|'s position among its siblings in the stacking order
// has changed.
virtual void OnWindowStackingChanged(Window* window) {}
@@ -100,17 +106,29 @@ class AURA_EXPORT WindowObserver {
// Called when a Window has been added to a RootWindow.
virtual void OnWindowAddedToRootWindow(Window* window) {}
- // Called when a Window is about to be removed from a RootWindow.
- virtual void OnWindowRemovingFromRootWindow(Window* window) {}
+ // Called when a Window is about to be removed from a root Window.
+ // |new_root| contains the new root Window if it is being added to one
+ // atomically.
+ virtual void OnWindowRemovingFromRootWindow(Window* window,
+ Window* new_root) {}
- // Called when a transient child is added to |window|.
- virtual void OnAddTransientChild(Window* window, Window* transient) {}
+ protected:
+ virtual ~WindowObserver();
- // Called when a transient child is removed from |window|.
- virtual void OnRemoveTransientChild(Window* window, Window* transient) {}
+ private:
+ friend class Window;
- protected:
- virtual ~WindowObserver() {}
+ // Called when this is added as an observer on |window|.
+ void OnObservingWindow(Window* window);
+
+ // Called when this is removed from the observers on |window|.
+ void OnUnobservingWindow(Window* window);
+
+ // Tracks the number of windows being observed to track down
+ // http://crbug.com/365364.
+ int observing_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowObserver);
};
} // namespace aura
diff --git a/chromium/ui/aura/window_targeter.cc b/chromium/ui/aura/window_targeter.cc
index 586392bcdc8..601321525e8 100644
--- a/chromium/ui/aura/window_targeter.cc
+++ b/chromium/ui/aura/window_targeter.cc
@@ -7,9 +7,10 @@
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/event_client.h"
#include "ui/aura/client/focus_client.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/events/event_target.h"
namespace aura {
@@ -19,29 +20,28 @@ WindowTargeter::~WindowTargeter() {}
ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
ui::Event* event) {
- if (event->IsKeyEvent()) {
- Window* window = static_cast<Window*>(root);
- Window* root_window = window->GetRootWindow();
- const ui::KeyEvent& key = static_cast<const ui::KeyEvent&>(*event);
- if (key.key_code() == ui::VKEY_UNKNOWN)
- return NULL;
- client::EventClient* event_client = client::GetEventClient(root_window);
- client::FocusClient* focus_client = client::GetFocusClient(root_window);
- Window* focused_window = focus_client->GetFocusedWindow();
- if (event_client &&
- !event_client->CanProcessEventsWithinSubtree(focused_window)) {
- focus_client->FocusWindow(NULL);
- return NULL;
+ Window* window = static_cast<Window*>(root);
+ Window* target = event->IsKeyEvent() ?
+ FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event)) :
+ static_cast<Window*>(EventTargeter::FindTargetForEvent(root, event));
+ if (target && !window->parent()) {
+ // |window| is the root window.
+ if (!window->Contains(target)) {
+ // |target| is not a descendent of |window|. So do not allow dispatching
+ // from here. Instead, dispatch the event through the
+ // WindowEventDispatcher that owns |target|.
+ ui::EventDispatchDetails details ALLOW_UNUSED =
+ target->GetHost()->event_processor()->OnEventFromSource(event);
+ target = NULL;
}
- return focused_window ? focused_window : window;
}
- return EventTargeter::FindTargetForEvent(root, event);
+ return target;
}
-bool WindowTargeter::SubtreeShouldBeExploredForEvent(
- ui::EventTarget* root,
- const ui::LocatedEvent& event) {
- Window* window = static_cast<Window*>(root);
+bool WindowTargeter::SubtreeCanAcceptEvent(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const {
+ aura::Window* window = static_cast<aura::Window*>(target);
if (!window->IsVisible())
return false;
if (window->ignore_events())
@@ -55,7 +55,17 @@ bool WindowTargeter::SubtreeShouldBeExploredForEvent(
ShouldDescendIntoChildForEventHandling(window, event.location())) {
return false;
}
- return window->bounds().Contains(event.location());
+ return true;
+}
+
+bool WindowTargeter::EventLocationInsideBounds(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const {
+ aura::Window* window = static_cast<aura::Window*>(target);
+ gfx::Point point = event.location();
+ if (window->parent())
+ aura::Window::ConvertPointToTarget(window->parent(), window, &point);
+ return gfx::Rect(window->bounds().size()).Contains(point);
}
ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent(
@@ -72,6 +82,27 @@ ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent(
return EventTargeter::FindTargetForLocatedEvent(root, event);
}
+Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
+ const ui::KeyEvent& key) {
+ Window* root_window = window->GetRootWindow();
+ if (key.key_code() == ui::VKEY_UNKNOWN &&
+ (key.flags() & ui::EF_IME_FABRICATED_KEY) == 0 &&
+ key.GetCharacter() == 0)
+ return NULL;
+ client::FocusClient* focus_client = client::GetFocusClient(root_window);
+ Window* focused_window = focus_client->GetFocusedWindow();
+ if (!focused_window)
+ return window;
+
+ client::EventClient* event_client = client::GetEventClient(root_window);
+ if (event_client &&
+ !event_client->CanProcessEventsWithinSubtree(focused_window)) {
+ focus_client->FocusWindow(NULL);
+ return NULL;
+ }
+ return focused_window ? focused_window : window;
+}
+
Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
const ui::LocatedEvent& event) {
DCHECK_EQ(root_window, root_window->GetRootWindow());
@@ -79,7 +110,7 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
// Mouse events should be dispatched to the window that processed the
// mouse-press events (if any).
if (event.IsScrollEvent() || event.IsMouseEvent()) {
- WindowEventDispatcher* dispatcher = root_window->GetDispatcher();
+ WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher();
if (dispatcher->mouse_pressed_handler())
return dispatcher->mouse_pressed_handler();
}
@@ -89,6 +120,24 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
if (capture_window)
return capture_window;
+ if (event.IsTouchEvent()) {
+ // Query the gesture-recognizer to find targets for touch events.
+ const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event);
+ ui::GestureConsumer* consumer =
+ ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch);
+ if (consumer)
+ return static_cast<Window*>(consumer);
+ consumer =
+ ui::GestureRecognizer::Get()->GetTargetForLocation(
+ event.location(), touch.source_device_id());
+ if (consumer)
+ return static_cast<Window*>(consumer);
+
+ // If the initial touch is outside the root window, target the root.
+ if (!root_window->bounds().Contains(event.location()))
+ return root_window;
+ }
+
return NULL;
}
diff --git a/chromium/ui/aura/window_targeter.h b/chromium/ui/aura/window_targeter.h
index 4457f77c371..e64ef75f807 100644
--- a/chromium/ui/aura/window_targeter.h
+++ b/chromium/ui/aura/window_targeter.h
@@ -2,13 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef UI_AURA_WINDOW_TARGETER_H_
+#define UI_AURA_WINDOW_TARGETER_H_
+
+#include "ui/aura/aura_export.h"
#include "ui/events/event_targeter.h"
namespace aura {
class Window;
-class WindowTargeter : public ui::EventTargeter {
+class AURA_EXPORT WindowTargeter : public ui::EventTargeter {
public:
WindowTargeter();
virtual ~WindowTargeter();
@@ -20,11 +24,16 @@ class WindowTargeter : public ui::EventTargeter {
virtual ui::EventTarget* FindTargetForLocatedEvent(
ui::EventTarget* root,
ui::LocatedEvent* event) OVERRIDE;
- virtual bool SubtreeShouldBeExploredForEvent(
+ virtual bool SubtreeCanAcceptEvent(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const OVERRIDE;
+ virtual bool EventLocationInsideBounds(
ui::EventTarget* target,
- const ui::LocatedEvent& event) OVERRIDE;
+ const ui::LocatedEvent& event) const OVERRIDE;
private:
+ Window* FindTargetForKeyEvent(Window* root_window,
+ const ui::KeyEvent& event);
Window* FindTargetInRootWindow(Window* root_window,
const ui::LocatedEvent& event);
@@ -32,3 +41,5 @@ class WindowTargeter : public ui::EventTargeter {
};
} // namespace aura
+
+#endif // UI_AURA_WINDOW_TARGETER_H_
diff --git a/chromium/ui/aura/window_targeter_unittest.cc b/chromium/ui/aura/window_targeter_unittest.cc
index 396c805353f..f14d3379ea3 100644
--- a/chromium/ui/aura/window_targeter_unittest.cc
+++ b/chromium/ui/aura/window_targeter_unittest.cc
@@ -4,13 +4,34 @@
#include "ui/aura/window_targeter.h"
+#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/test_event_handler.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
+#include "ui/events/test/test_event_handler.h"
namespace aura {
+// Always returns the same window.
+class StaticWindowTargeter : public ui::EventTargeter {
+ public:
+ explicit StaticWindowTargeter(aura::Window* window)
+ : window_(window) {}
+ virtual ~StaticWindowTargeter() {}
+
+ private:
+ // ui::EventTargeter:
+ virtual ui::EventTarget* FindTargetForLocatedEvent(
+ ui::EventTarget* root,
+ ui::LocatedEvent* event) OVERRIDE {
+ return window_;
+ }
+
+ Window* window_;
+
+ DISALLOW_COPY_AND_ASSIGN(StaticWindowTargeter);
+};
+
class WindowTargeterTest : public test::AuraTestBase {
public:
WindowTargeterTest() {}
@@ -19,6 +40,18 @@ class WindowTargeterTest : public test::AuraTestBase {
Window* root_window() { return AuraTestBase::root_window(); }
};
+gfx::RectF GetEffectiveVisibleBoundsInRootWindow(Window* window) {
+ gfx::RectF bounds = gfx::Rect(window->bounds().size());
+ Window* root = window->GetRootWindow();
+ CHECK(window->layer());
+ CHECK(root->layer());
+ gfx::Transform transform;
+ if (!window->layer()->GetTargetTransformRelativeTo(root->layer(), &transform))
+ return gfx::RectF();
+ transform.TransformRect(&bounds);
+ return bounds;
+}
+
TEST_F(WindowTargeterTest, Basic) {
test::TestWindowDelegate delegate;
scoped_ptr<Window> window(CreateNormalWindow(1, root_window(), &delegate));
@@ -31,24 +64,102 @@ TEST_F(WindowTargeterTest, Basic) {
root_window()->Show();
- test::TestEventHandler handler;
+ ui::test::TestEventHandler handler;
one->AddPreTargetHandler(&handler);
ui::MouseEvent press(ui::ET_MOUSE_PRESSED,
gfx::Point(20, 20),
gfx::Point(20, 20),
+ ui::EF_NONE,
ui::EF_NONE);
- root_window()->GetDispatcher()->AsRootWindowHostDelegate()->
- OnHostMouseEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_EQ(1, handler.num_mouse_events());
handler.Reset();
- ui::EventDispatchDetails details =
- root_window()->GetDispatcher()->OnEventFromSource(&press);
- EXPECT_FALSE(details.dispatcher_destroyed);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_EQ(1, handler.num_mouse_events());
one->RemovePreTargetHandler(&handler);
}
+TEST_F(WindowTargeterTest, ScopedWindowTargeter) {
+ test::TestWindowDelegate delegate;
+ scoped_ptr<Window> window(CreateNormalWindow(1, root_window(), &delegate));
+ Window* child = CreateNormalWindow(2, window.get(), &delegate);
+
+ window->SetBounds(gfx::Rect(30, 30, 100, 100));
+ child->SetBounds(gfx::Rect(20, 20, 50, 50));
+ root_window()->Show();
+
+ ui::EventTarget* root = root_window();
+ ui::EventTargeter* targeter = root->GetEventTargeter();
+
+ gfx::Point event_location(60, 60);
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(child, targeter->FindTargetForEvent(root, &mouse));
+ }
+
+ // Install a targeter on |window| so that the events never reach the child.
+ scoped_ptr<ScopedWindowTargeter> scoped_targeter(
+ new ScopedWindowTargeter(window.get(), scoped_ptr<ui::EventTargeter>(
+ new StaticWindowTargeter(window.get()))));
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root, &mouse));
+ }
+ scoped_targeter.reset();
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(child, targeter->FindTargetForEvent(root, &mouse));
+ }
+}
+
+TEST_F(WindowTargeterTest, TargetTransformedWindow) {
+ root_window()->Show();
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<Window> window(CreateNormalWindow(2, root_window(), &delegate));
+
+ const gfx::Rect window_bounds(100, 20, 400, 80);
+ window->SetBounds(window_bounds);
+
+ ui::EventTarget* root_target = root_window();
+ ui::EventTargeter* targeter = root_target->GetEventTargeter();
+ gfx::Point event_location(490, 50);
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
+ }
+
+ // Scale |window| by 50%. This should move it away from underneath
+ // |event_location|, so an event in that location will not be targeted to it.
+ gfx::Transform transform;
+ transform.Scale(0.5, 0.5);
+ window->SetTransform(transform);
+ EXPECT_EQ(gfx::RectF(100, 20, 200, 40).ToString(),
+ GetEffectiveVisibleBoundsInRootWindow(window.get()).ToString());
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(root_window(), targeter->FindTargetForEvent(root_target, &mouse));
+ }
+
+ transform = gfx::Transform();
+ transform.Translate(200, 10);
+ transform.Scale(0.5, 0.5);
+ window->SetTransform(transform);
+ EXPECT_EQ(gfx::RectF(300, 30, 200, 40).ToString(),
+ GetEffectiveVisibleBoundsInRootWindow(window.get()).ToString());
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
+ }
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc
index 1bee9231a0a..9ac7cf7ab01 100644
--- a/chromium/ui/aura/window_tree_host.cc
+++ b/chromium/ui/aura/window_tree_host.cc
@@ -4,36 +4,270 @@
#include "ui/aura/window_tree_host.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window_tree_host_delegate.h"
+#include "base/debug/trace_event.h"
+#include "ui/aura/client/capture_client.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_targeter.h"
+#include "ui/aura/window_tree_host_observer.h"
+#include "ui/base/view_prop.h"
+#include "ui/compositor/dip_util.h"
+#include "ui/compositor/layer.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/insets.h"
#include "ui/gfx/point.h"
+#include "ui/gfx/point3_f.h"
+#include "ui/gfx/point_conversions.h"
+#include "ui/gfx/screen.h"
+#include "ui/gfx/size_conversions.h"
namespace aura {
+const char kWindowTreeHostForAcceleratedWidget[] =
+ "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
+
+float GetDeviceScaleFactorFromDisplay(Window* window) {
+ gfx::Display display = gfx::Screen::GetScreenFor(window)->
+ GetDisplayNearestWindow(window);
+ DCHECK(display.is_valid());
+ return display.device_scale_factor();
+}
+
////////////////////////////////////////////////////////////////////////////////
-// RootWindowHost, public:
+// WindowTreeHost, public:
+
+WindowTreeHost::~WindowTreeHost() {
+ DCHECK(!compositor_) << "compositor must be destroyed before root window";
+}
+
+#if defined(OS_ANDROID)
+// static
+WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
+ // This is only hit for tests and ash, right now these aren't an issue so
+ // adding the CHECK.
+ // TODO(sky): decide if we want a factory.
+ CHECK(false);
+ return NULL;
+}
+#endif
+
+// static
+WindowTreeHost* WindowTreeHost::GetForAcceleratedWidget(
+ gfx::AcceleratedWidget widget) {
+ return reinterpret_cast<WindowTreeHost*>(
+ ui::ViewProp::GetValue(widget, kWindowTreeHostForAcceleratedWidget));
+}
+
+void WindowTreeHost::InitHost() {
+ InitCompositor();
+ UpdateRootWindowSize(GetBounds().size());
+ Env::GetInstance()->NotifyHostInitialized(this);
+ window()->Show();
+}
+
+void WindowTreeHost::InitCompositor() {
+ compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
+ GetBounds().size());
+ compositor_->SetRootLayer(window()->layer());
+}
+
+void WindowTreeHost::AddObserver(WindowTreeHostObserver* observer) {
+ observers_.AddObserver(observer);
+}
-RootWindowHost::~RootWindowHost() {
+void WindowTreeHost::RemoveObserver(WindowTreeHostObserver* observer) {
+ observers_.RemoveObserver(observer);
}
-void RootWindowHost::ConvertPointToNativeScreen(gfx::Point* point) const {
- delegate_->AsRootWindow()->ConvertPointToHost(point);
+ui::EventProcessor* WindowTreeHost::event_processor() {
+ return dispatcher();
+}
+
+gfx::Transform WindowTreeHost::GetRootTransform() const {
+ float scale = ui::GetDeviceScaleFactor(window()->layer());
+ gfx::Transform transform;
+ transform.Scale(scale, scale);
+ transform *= window()->layer()->transform();
+ return transform;
+}
+
+void WindowTreeHost::SetRootTransform(const gfx::Transform& transform) {
+ window()->SetTransform(transform);
+ UpdateRootWindowSize(GetBounds().size());
+}
+
+gfx::Transform WindowTreeHost::GetInverseRootTransform() const {
+ gfx::Transform invert;
+ gfx::Transform transform = GetRootTransform();
+ if (!transform.GetInverse(&invert))
+ return transform;
+ return invert;
+}
+
+void WindowTreeHost::UpdateRootWindowSize(const gfx::Size& host_size) {
+ gfx::Rect bounds(host_size);
+ gfx::RectF new_bounds(ui::ConvertRectToDIP(window()->layer(), bounds));
+ window()->layer()->transform().TransformRect(&new_bounds);
+ window()->SetBounds(gfx::Rect(gfx::ToFlooredSize(new_bounds.size())));
+}
+
+void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point* point) const {
+ ConvertPointToHost(point);
gfx::Point location = GetLocationOnNativeScreen();
point->Offset(location.x(), location.y());
}
-void RootWindowHost::ConvertPointFromNativeScreen(gfx::Point* point) const {
+void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point* point) const {
gfx::Point location = GetLocationOnNativeScreen();
point->Offset(-location.x(), -location.y());
- delegate_->AsRootWindow()->ConvertPointFromHost(point);
+ ConvertPointFromHost(point);
+}
+
+void WindowTreeHost::ConvertPointToHost(gfx::Point* point) const {
+ gfx::Point3F point_3f(*point);
+ GetRootTransform().TransformPoint(&point_3f);
+ *point = gfx::ToFlooredPoint(point_3f.AsPointF());
+}
+
+void WindowTreeHost::ConvertPointFromHost(gfx::Point* point) const {
+ gfx::Point3F point_3f(*point);
+ GetInverseRootTransform().TransformPoint(&point_3f);
+ *point = gfx::ToFlooredPoint(point_3f.AsPointF());
+}
+
+void WindowTreeHost::SetCursor(gfx::NativeCursor cursor) {
+ last_cursor_ = cursor;
+ // A lot of code seems to depend on NULL cursors actually showing an arrow,
+ // so just pass everything along to the host.
+ SetCursorNative(cursor);
+}
+
+void WindowTreeHost::OnCursorVisibilityChanged(bool show) {
+ // Clear any existing mouse hover effects when the cursor becomes invisible.
+ // Note we do not need to dispatch a mouse enter when the cursor becomes
+ // visible because that can only happen in response to a mouse event, which
+ // will trigger its own mouse enter.
+ if (!show) {
+ dispatcher()->DispatchMouseExitAtPoint(
+ dispatcher()->GetLastMouseLocationInRoot());
+ }
+
+ OnCursorVisibilityChangedNative(show);
+}
+
+void WindowTreeHost::MoveCursorTo(const gfx::Point& location_in_dip) {
+ gfx::Point host_location(location_in_dip);
+ ConvertPointToHost(&host_location);
+ MoveCursorToInternal(location_in_dip, host_location);
+}
+
+void WindowTreeHost::MoveCursorToHostLocation(const gfx::Point& host_location) {
+ gfx::Point root_location(host_location);
+ ConvertPointFromHost(&root_location);
+ MoveCursorToInternal(root_location, host_location);
}
////////////////////////////////////////////////////////////////////////////////
-// RootWindowHost, protected:
+// WindowTreeHost, protected:
+
+WindowTreeHost::WindowTreeHost()
+ : window_(new Window(NULL)),
+ last_cursor_(ui::kCursorNull) {
+}
+
+void WindowTreeHost::DestroyCompositor() {
+ compositor_.reset();
+}
+
+void WindowTreeHost::DestroyDispatcher() {
+ delete window_;
+ window_ = NULL;
+ dispatcher_.reset();
+
+ // TODO(beng): this comment is no longer quite valid since this function
+ // isn't called from WED, and WED isn't a subclass of Window. So it seems
+ // like we could just rely on ~Window now.
+ // Destroy child windows while we're still valid. This is also done by
+ // ~Window, but by that time any calls to virtual methods overriden here (such
+ // as GetRootWindow()) result in Window's implementation. By destroying here
+ // we ensure GetRootWindow() still returns this.
+ //window()->RemoveOrDestroyChildren();
+}
-RootWindowHost::RootWindowHost()
- : delegate_(NULL) {
+void WindowTreeHost::CreateCompositor(
+ gfx::AcceleratedWidget accelerated_widget) {
+ DCHECK(Env::GetInstance());
+ ui::ContextFactory* context_factory = Env::GetInstance()->context_factory();
+ DCHECK(context_factory);
+ compositor_.reset(
+ new ui::Compositor(GetAcceleratedWidget(), context_factory));
+ // TODO(beng): I think this setup should probably all move to a "accelerated
+ // widget available" function.
+ if (!dispatcher()) {
+ window()->Init(WINDOW_LAYER_NOT_DRAWN);
+ window()->set_host(this);
+ window()->SetName("RootWindow");
+ window()->SetEventTargeter(
+ scoped_ptr<ui::EventTargeter>(new WindowTargeter()));
+ prop_.reset(new ui::ViewProp(GetAcceleratedWidget(),
+ kWindowTreeHostForAcceleratedWidget,
+ this));
+ dispatcher_.reset(new WindowEventDispatcher(this));
+ }
}
+void WindowTreeHost::OnHostMoved(const gfx::Point& new_location) {
+ TRACE_EVENT1("ui", "WindowTreeHost::OnHostMoved",
+ "origin", new_location.ToString());
+
+ FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_,
+ OnHostMoved(this, new_location));
+}
+
+void WindowTreeHost::OnHostResized(const gfx::Size& new_size) {
+ // The compositor should have the same size as the native root window host.
+ // Get the latest scale from display because it might have been changed.
+ compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
+ new_size);
+
+ gfx::Size layer_size = GetBounds().size();
+ // The layer, and the observers should be notified of the
+ // transformed size of the root window.
+ UpdateRootWindowSize(layer_size);
+ FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, OnHostResized(this));
+}
+
+void WindowTreeHost::OnHostCloseRequested() {
+ FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_,
+ OnHostCloseRequested(this));
+}
+
+void WindowTreeHost::OnHostActivated() {
+ Env::GetInstance()->NotifyHostActivated(this);
+}
+
+void WindowTreeHost::OnHostLostWindowCapture() {
+ Window* capture_window = client::GetCaptureWindow(window());
+ if (capture_window && capture_window->GetRootWindow() == window())
+ capture_window->ReleaseCapture();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WindowTreeHost, private:
+
+void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location,
+ const gfx::Point& host_location) {
+ last_cursor_request_position_in_host_ = host_location;
+ MoveCursorToNative(host_location);
+ client::CursorClient* cursor_client = client::GetCursorClient(window());
+ if (cursor_client) {
+ const gfx::Display& display =
+ gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
+ cursor_client->SetDisplay(display);
+ }
+ dispatcher()->OnCursorMovedToRootLocation(root_location);
+}
} // namespace aura
diff --git a/chromium/ui/aura/window_tree_host.h b/chromium/ui/aura/window_tree_host.h
index 5aaa65c3116..9d54944777f 100644
--- a/chromium/ui/aura/window_tree_host.h
+++ b/chromium/ui/aura/window_tree_host.h
@@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_AURA_ROOT_WINDOW_HOST_H_
-#define UI_AURA_ROOT_WINDOW_HOST_H_
+#ifndef UI_AURA_WINDOW_TREE_HOST_H_
+#define UI_AURA_WINDOW_TREE_HOST_H_
#include <vector>
+#include "base/event_types.h"
#include "base/message_loop/message_loop.h"
#include "ui/aura/aura_export.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/events/event_source.h"
#include "ui/gfx/native_widget_types.h"
namespace gfx {
@@ -17,53 +19,69 @@ class Insets;
class Point;
class Rect;
class Size;
+class Transform;
+}
+
+namespace ui {
+class Compositor;
+class EventProcessor;
+class ViewProp;
}
namespace aura {
+namespace test {
+class WindowTreeHostTestApi;
+}
-class RootWindow;
-class RootWindowHostDelegate;
+class WindowEventDispatcher;
+class WindowTreeHostObserver;
-// RootWindowHost bridges between a native window and the embedded RootWindow.
+// WindowTreeHost bridges between a native window and the embedded RootWindow.
// It provides the accelerated widget and maps events from the native os to
// aura.
-class AURA_EXPORT RootWindowHost {
+class AURA_EXPORT WindowTreeHost {
public:
- virtual ~RootWindowHost();
+ virtual ~WindowTreeHost();
- // Creates a new RootWindowHost. The caller owns the returned value.
- static RootWindowHost* Create(const gfx::Rect& bounds);
+ // Creates a new WindowTreeHost. The caller owns the returned value.
+ static WindowTreeHost* Create(const gfx::Rect& bounds);
- // Returns the actual size of the screen.
- // (gfx::Screen only reports on the virtual desktop exposed by Aura.)
- static gfx::Size GetNativeScreenSize();
+ // Returns the WindowTreeHost for the specified accelerated widget, or NULL
+ // if there is none associated.
+ static WindowTreeHost* GetForAcceleratedWidget(gfx::AcceleratedWidget widget);
- void set_delegate(RootWindowHostDelegate* delegate) {
- delegate_ = delegate;
- }
+ void InitHost();
- virtual RootWindow* GetRootWindow() = 0;
+ void InitCompositor();
- // Returns the accelerated widget.
- virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0;
+ void AddObserver(WindowTreeHostObserver* observer);
+ void RemoveObserver(WindowTreeHostObserver* observer);
- // Shows the RootWindowHost.
- virtual void Show() = 0;
+ Window* window() { return window_; }
+ const Window* window() const { return window_; }
- // Hides the RootWindowHost.
- virtual void Hide() = 0;
+ ui::EventProcessor* event_processor();
- // Toggles the host's full screen state.
- virtual void ToggleFullScreen() = 0;
+ WindowEventDispatcher* dispatcher() {
+ return const_cast<WindowEventDispatcher*>(
+ const_cast<const WindowTreeHost*>(this)->dispatcher());
+ }
+ const WindowEventDispatcher* dispatcher() const { return dispatcher_.get(); }
- // Gets/Sets the size of the RootWindowHost.
- virtual gfx::Rect GetBounds() const = 0;
- virtual void SetBounds(const gfx::Rect& bounds) = 0;
+ ui::Compositor* compositor() { return compositor_.get(); }
+
+ // Gets/Sets the root window's transform.
+ virtual gfx::Transform GetRootTransform() const;
+ virtual void SetRootTransform(const gfx::Transform& transform);
+ virtual gfx::Transform GetInverseRootTransform() const;
- // Sets/Gets the insets that specifies the effective root window area
- // in the host window.
- virtual gfx::Insets GetInsets() const = 0;
- virtual void SetInsets(const gfx::Insets& insets) = 0;
+ // Updates the root window's size using |host_size|, current
+ // transform and insets.
+ virtual void UpdateRootWindowSize(const gfx::Size& host_size);
+
+ // Returns the actual size of the screen.
+ // (gfx::Screen only reports on the virtual desktop exposed by Aura.)
+ static gfx::Size GetNativeScreenSize();
// Converts |point| from the root window's coordinate system to native
// screen's.
@@ -72,58 +90,117 @@ class AURA_EXPORT RootWindowHost {
// Converts |point| from native screen coordinate system to the root window's.
void ConvertPointFromNativeScreen(gfx::Point* point) const;
+ // Converts |point| from the root window's coordinate system to the
+ // host window's.
+ void ConvertPointToHost(gfx::Point* point) const;
+
+ // Converts |point| from the host window's coordinate system to the
+ // root window's.
+ void ConvertPointFromHost(gfx::Point* point) const;
+
+ // Cursor.
+ // Sets the currently-displayed cursor. If the cursor was previously hidden
+ // via ShowCursor(false), it will remain hidden until ShowCursor(true) is
+ // called, at which point the cursor that was last set via SetCursor() will be
+ // used.
+ void SetCursor(gfx::NativeCursor cursor);
+
+ // Invoked when the cursor's visibility has changed.
+ void OnCursorVisibilityChanged(bool visible);
+
+ // Moves the cursor to the specified location relative to the root window.
+ void MoveCursorTo(const gfx::Point& location);
+
+ // Moves the cursor to the |host_location| given in host coordinates.
+ void MoveCursorToHostLocation(const gfx::Point& host_location);
+
+ gfx::NativeCursor last_cursor() const { return last_cursor_; }
+
+ // Returns the EventSource responsible for dispatching events to the window
+ // tree.
+ virtual ui::EventSource* GetEventSource() = 0;
+
+ // Returns the accelerated widget.
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0;
+
+ // Shows the WindowTreeHost.
+ virtual void Show() = 0;
+
+ // Hides the WindowTreeHost.
+ virtual void Hide() = 0;
+
+ // Gets/Sets the size of the WindowTreeHost.
+ virtual gfx::Rect GetBounds() const = 0;
+ virtual void SetBounds(const gfx::Rect& bounds) = 0;
+
// Sets the OS capture to the root window.
virtual void SetCapture() = 0;
// Releases OS capture of the root window.
virtual void ReleaseCapture() = 0;
- // Sets the currently displayed cursor.
- virtual void SetCursor(gfx::NativeCursor cursor) = 0;
-
- // Queries the mouse's current position relative to the host window and sets
- // it in |location_return|. Returns true if the cursor is within the host
- // window. The position set to |location_return| is constrained within the
- // host window. If the cursor is disabled, returns false and (0, 0) is set to
- // |location_return|.
- // This method is expensive, instead use gfx::Screen::GetCursorScreenPoint().
- virtual bool QueryMouseLocation(gfx::Point* location_return) = 0;
-
- // Clips the cursor to the bounds of the root window until UnConfineCursor().
- // We would like to be able to confine the cursor to that window. However,
- // currently, we do not have such functionality in X. So we just confine
- // to the root window. This is ok because this option is currently only
- // being used in fullscreen mode, so root_window bounds = window bounds.
- virtual bool ConfineCursorToRootWindow() = 0;
- virtual void UnConfineCursor() = 0;
-
- // Called when the cursor visibility has changed.
- virtual void OnCursorVisibilityChanged(bool show) = 0;
-
- // Moves the cursor to the specified location relative to the root window.
- virtual void MoveCursorTo(const gfx::Point& location) = 0;
-
// Posts |native_event| to the platform's event queue.
virtual void PostNativeEvent(const base::NativeEvent& native_event) = 0;
// Called when the device scale factor of the root window has chagned.
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) = 0;
- // Stop listening events in preparation for shutdown.
- virtual void PrepareForShutdown() = 0;
-
protected:
- RootWindowHost();
+ friend class TestScreen; // TODO(beng): see if we can remove/consolidate.
+
+ WindowTreeHost();
+ void DestroyCompositor();
+ void DestroyDispatcher();
+
+ void CreateCompositor(gfx::AcceleratedWidget accelerated_widget);
// Returns the location of the RootWindow on native screen.
virtual gfx::Point GetLocationOnNativeScreen() const = 0;
- RootWindowHostDelegate* delegate_;
+ void OnHostMoved(const gfx::Point& new_location);
+ void OnHostResized(const gfx::Size& new_size);
+ void OnHostCloseRequested();
+ void OnHostActivated();
+ void OnHostLostWindowCapture();
+
+ // Sets the currently displayed cursor.
+ virtual void SetCursorNative(gfx::NativeCursor cursor) = 0;
+
+ // Moves the cursor to the specified location relative to the root window.
+ virtual void MoveCursorToNative(const gfx::Point& location) = 0;
+
+ // kCalled when the cursor visibility has changed.
+ virtual void OnCursorVisibilityChangedNative(bool show) = 0;
private:
- DISALLOW_COPY_AND_ASSIGN(RootWindowHost);
+ friend class test::WindowTreeHostTestApi;
+
+ // Moves the cursor to the specified location. This method is internally used
+ // by MoveCursorTo() and MoveCursorToHostLocation().
+ void MoveCursorToInternal(const gfx::Point& root_location,
+ const gfx::Point& host_location);
+
+ // We don't use a scoped_ptr for |window_| since we need this ptr to be valid
+ // during its deletion. (Window's dtor notifies observers that may attempt to
+ // reach back up to access this object which will be valid until the end of
+ // the dtor).
+ Window* window_; // Owning.
+
+ ObserverList<WindowTreeHostObserver> observers_;
+
+ scoped_ptr<WindowEventDispatcher> dispatcher_;
+
+ scoped_ptr<ui::Compositor> compositor_;
+
+ // Last cursor set. Used for testing.
+ gfx::NativeCursor last_cursor_;
+ gfx::Point last_cursor_request_position_in_host_;
+
+ scoped_ptr<ui::ViewProp> prop_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowTreeHost);
};
} // namespace aura
-#endif // UI_AURA_ROOT_WINDOW_HOST_H_
+#endif // UI_AURA_WINDOW_TREE_HOST_H_
diff --git a/chromium/ui/aura/window_tree_host_delegate.h b/chromium/ui/aura/window_tree_host_delegate.h
deleted file mode 100644
index ad08039d627..00000000000
--- a/chromium/ui/aura/window_tree_host_delegate.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_ROOT_WINDOW_HOST_DELEGATE_H_
-#define UI_AURA_ROOT_WINDOW_HOST_DELEGATE_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace gfx {
-class Point;
-class Rect;
-class Size;
-}
-
-namespace ui {
-class Event;
-class EventProcessor;
-class KeyEvent;
-class MouseEvent;
-class ScrollEvent;
-class TouchEvent;
-}
-
-namespace aura {
-
-class RootWindow;
-
-// A private interface used by RootWindowHost implementations to communicate
-// with their owning RootWindow.
-class AURA_EXPORT RootWindowHostDelegate {
- public:
- virtual bool OnHostKeyEvent(ui::KeyEvent* event) = 0;
- virtual bool OnHostMouseEvent(ui::MouseEvent* event) = 0;
- virtual bool OnHostScrollEvent(ui::ScrollEvent* event) = 0;
- virtual bool OnHostTouchEvent(ui::TouchEvent* event) = 0;
- virtual void OnHostCancelMode() = 0;
-
- // Called when the windowing system activates the window.
- virtual void OnHostActivated() = 0;
-
- // Called when system focus is changed to another window.
- virtual void OnHostLostWindowCapture() = 0;
-
- // Called when the windowing system has mouse grab because it's performing a
- // window move on our behalf, but we should still paint as if we're active.
- virtual void OnHostLostMouseGrab() = 0;
-
- virtual void OnHostPaint(const gfx::Rect& damage_rect) = 0;
-
- virtual void OnHostMoved(const gfx::Point& origin) = 0;
- virtual void OnHostResized(const gfx::Size& size) = 0;
-
- virtual float GetDeviceScaleFactor() = 0;
-
- virtual RootWindow* AsRootWindow() = 0;
- virtual const RootWindow* AsRootWindow() const = 0;
-
- virtual ui::EventProcessor* GetEventProcessor() = 0;
-
- protected:
- virtual ~RootWindowHostDelegate() {}
-};
-
-} // namespace aura
-
-#endif // UI_AURA_ROOT_WINDOW_HOST_DELEGATE_H_
diff --git a/chromium/ui/aura/window_tree_host_mac.h b/chromium/ui/aura/window_tree_host_mac.h
new file mode 100644
index 00000000000..8fbf4ec81bb
--- /dev/null
+++ b/chromium/ui/aura/window_tree_host_mac.h
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_WINDOW_TREE_HOST_MAC_H_
+#define UI_AURA_WINDOW_TREE_HOST_MAC_H_
+
+#include <vector>
+
+#include "base/mac/scoped_nsobject.h"
+#include "ui/aura/aura_export.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/rect.h"
+
+namespace ui {
+class MouseEvent;
+}
+
+namespace aura {
+
+namespace internal {
+class TouchEventCalibrate;
+}
+
+class AURA_EXPORT WindowTreeHostMac : public WindowTreeHost {
+ public:
+ explicit WindowTreeHostMac(const gfx::Rect& bounds);
+ virtual ~WindowTreeHostMac();
+
+ private:
+ // WindowTreeHost Overrides.
+ virtual ui::EventSource* GetEventSource() OVERRIDE;
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual void ToggleFullScreen() OVERRIDE;
+ virtual gfx::Rect GetBounds() const OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
+ virtual gfx::Insets GetInsets() const OVERRIDE;
+ virtual void SetInsets(const gfx::Insets& insets) OVERRIDE;
+ virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
+ virtual void SetCapture() OVERRIDE;
+ virtual void ReleaseCapture() OVERRIDE;
+ virtual bool ConfineCursorToRootWindow() OVERRIDE;
+ virtual void UnConfineCursor() OVERRIDE;
+ virtual void SetCursorNative(gfx::NativeCursor cursor_type) OVERRIDE;
+ virtual void MoveCursorToNative(const gfx::Point& location) OVERRIDE;
+ virtual void OnCursorVisibilityChangedNative(bool show) OVERRIDE;
+ virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
+ virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+
+ private:
+ base::scoped_nsobject<NSWindow> window_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowTreeHostMac);
+};
+
+} // namespace aura
+
+#endif // UI_AURA_WINDOW_TREE_HOST_MAC_H_
diff --git a/chromium/ui/aura/window_tree_host_mac.mm b/chromium/ui/aura/window_tree_host_mac.mm
new file mode 100644
index 00000000000..7fb3f82a2ec
--- /dev/null
+++ b/chromium/ui/aura/window_tree_host_mac.mm
@@ -0,0 +1,114 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <Cocoa/Cocoa.h>
+
+#include "ui/aura/window_tree_host_mac.h"
+#include "ui/aura/window_tree_host.h"
+
+namespace aura {
+
+WindowTreeHostMac::WindowTreeHostMac(const gfx::Rect& bounds) {
+ window_.reset(
+ [[NSWindow alloc]
+ initWithContentRect:NSRectFromCGRect(bounds.ToCGRect())
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO]);
+ CreateCompositor(GetAcceleratedWidget());
+}
+
+WindowTreeHostMac::~WindowTreeHostMac() {
+ DestroyDispatcher();
+}
+
+EventSource* WindowTreeHostMac::GetEventSource() {
+ NOTIMPLEMENTED();
+ return nil;
+}
+
+gfx::AcceleratedWidget WindowTreeHostMac::GetAcceleratedWidget() {
+ return [window_ contentView];
+}
+void WindowTreeHostMac::Show() {
+ [window_ makeKeyAndOrderFront:nil];
+}
+
+void WindowTreeHostMac::Hide() {
+ [window_ orderOut:nil];
+}
+
+void WindowTreeHostMac::ToggleFullScreen() {
+}
+
+gfx::Rect WindowTreeHostMac::GetBounds() const {
+ return gfx::Rect(NSRectToCGRect([window_ frame]));
+}
+
+void WindowTreeHostMac::SetBounds(const gfx::Rect& bounds) {
+ [window_ setFrame:NSRectFromCGRect(bounds.ToCGRect()) display:YES animate:NO];
+}
+
+gfx::Insets WindowTreeHostMac::GetInsets() const {
+ NOTIMPLEMENTED();
+ return gfx::Insets();
+}
+
+void WindowTreeHostMac::SetInsets(const gfx::Insets& insets) {
+ NOTIMPLEMENTED();
+}
+
+gfx::Point WindowTreeHostMac::GetLocationOnNativeScreen() const {
+ NOTIMPLEMENTED();
+ return gfx::Point(0, 0);
+}
+
+void WindowTreeHostMac::SetCapture() {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostMac::ReleaseCapture() {
+ NOTIMPLEMENTED();
+}
+
+bool WindowTreeHostMac::ConfineCursorToRootWindow() {
+ return false;
+}
+
+void WindowTreeHostMac::UnConfineCursor() {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostMac::SetCursorNative(gfx::NativeCursor cursor_type) {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostMac::MoveCursorToNative(const gfx::Point& location) {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostMac::OnCursorVisibilityChangedNative(bool show) {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostMac::PostNativeEvent(const base::NativeEvent& event) {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostMac::OnDeviceScaleFactorChanged(float device_scale_factor) {
+ NOTIMPLEMENTED();
+}
+
+// static
+WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
+ return new WindowTreeHostMac(bounds);
+}
+
+// static
+gfx::Size WindowTreeHost::GetNativeScreenSize() {
+ NOTIMPLEMENTED();
+ return gfx::Size(1024, 768);
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/window_tree_host_observer.h b/chromium/ui/aura/window_tree_host_observer.h
new file mode 100644
index 00000000000..d96e9d3b24d
--- /dev/null
+++ b/chromium/ui/aura/window_tree_host_observer.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_WINDOW_TREE_HOST_OBSERVER_H_
+#define UI_AURA_WINDOW_TREE_HOST_OBSERVER_H_
+
+#include "ui/aura/aura_export.h"
+
+namespace gfx {
+class Point;
+}
+
+namespace aura {
+class Window;
+class WindowTreeHost;
+
+class AURA_EXPORT WindowTreeHostObserver {
+ public:
+ // Called when the host's client size has changed.
+ virtual void OnHostResized(const WindowTreeHost* host) {}
+
+ // Called when the host is moved on screen.
+ virtual void OnHostMoved(const WindowTreeHost* host,
+ const gfx::Point& new_origin) {}
+
+ // Called when the native window system sends the host request to close.
+ virtual void OnHostCloseRequested(const WindowTreeHost* host) {}
+
+ protected:
+ virtual ~WindowTreeHostObserver() {}
+};
+
+} // namespace aura
+
+#endif // UI_AURA_WINDOW_TREE_HOST_OBSERVER_H_
diff --git a/chromium/ui/aura/window_tree_host_ozone.cc b/chromium/ui/aura/window_tree_host_ozone.cc
new file mode 100644
index 00000000000..d247734940e
--- /dev/null
+++ b/chromium/ui/aura/window_tree_host_ozone.cc
@@ -0,0 +1,118 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/window_tree_host_ozone.h"
+
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/ozone/public/cursor_factory_ozone.h"
+#include "ui/ozone/public/event_factory_ozone.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+namespace aura {
+
+WindowTreeHostOzone::WindowTreeHostOzone(const gfx::Rect& bounds)
+ : widget_(0),
+ bounds_(bounds) {
+ ui::SurfaceFactoryOzone* surface_factory =
+ ui::SurfaceFactoryOzone::GetInstance();
+ widget_ = surface_factory->GetAcceleratedWidget();
+
+ ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
+ CreateCompositor(GetAcceleratedWidget());
+}
+
+WindowTreeHostOzone::~WindowTreeHostOzone() {
+ ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
+ DestroyCompositor();
+ DestroyDispatcher();
+}
+
+bool WindowTreeHostOzone::CanDispatchEvent(const ui::PlatformEvent& ne) {
+ CHECK(ne);
+ ui::Event* event = static_cast<ui::Event*>(ne);
+ if (event->IsMouseEvent() || event->IsScrollEvent())
+ return ui::CursorFactoryOzone::GetInstance()->GetCursorWindow() == widget_;
+
+ return true;
+}
+
+uint32_t WindowTreeHostOzone::DispatchEvent(const ui::PlatformEvent& ne) {
+ ui::Event* event = static_cast<ui::Event*>(ne);
+ ui::EventDispatchDetails details ALLOW_UNUSED = SendEventToProcessor(event);
+ return ui::POST_DISPATCH_STOP_PROPAGATION;
+}
+
+ui::EventSource* WindowTreeHostOzone::GetEventSource() {
+ return this;
+}
+
+gfx::AcceleratedWidget WindowTreeHostOzone::GetAcceleratedWidget() {
+ return widget_;
+}
+
+void WindowTreeHostOzone::Show() { NOTIMPLEMENTED(); }
+
+void WindowTreeHostOzone::Hide() { NOTIMPLEMENTED(); }
+
+gfx::Rect WindowTreeHostOzone::GetBounds() const { return bounds_; }
+
+void WindowTreeHostOzone::SetBounds(const gfx::Rect& bounds) {
+ bool origin_changed = bounds_.origin() != bounds.origin();
+ bool size_changed = bounds_.size() != bounds.size();
+ bounds_ = bounds;
+ if (size_changed)
+ OnHostResized(bounds_.size());
+ if (origin_changed)
+ OnHostMoved(bounds_.origin());
+}
+
+gfx::Point WindowTreeHostOzone::GetLocationOnNativeScreen() const {
+ return bounds_.origin();
+}
+
+void WindowTreeHostOzone::SetCapture() { NOTIMPLEMENTED(); }
+
+void WindowTreeHostOzone::ReleaseCapture() { NOTIMPLEMENTED(); }
+
+void WindowTreeHostOzone::PostNativeEvent(
+ const base::NativeEvent& native_event) {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostOzone::OnDeviceScaleFactorChanged(
+ float device_scale_factor) {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostOzone::SetCursorNative(gfx::NativeCursor cursor) {
+ ui::CursorFactoryOzone::GetInstance()->SetCursor(GetAcceleratedWidget(),
+ cursor.platform());
+}
+
+void WindowTreeHostOzone::MoveCursorToNative(const gfx::Point& location) {
+ ui::EventFactoryOzone::GetInstance()->WarpCursorTo(GetAcceleratedWidget(),
+ location);
+}
+
+void WindowTreeHostOzone::OnCursorVisibilityChangedNative(bool show) {
+ NOTIMPLEMENTED();
+}
+
+ui::EventProcessor* WindowTreeHostOzone::GetEventProcessor() {
+ return dispatcher();
+}
+
+// static
+WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
+ return new WindowTreeHostOzone(bounds);
+}
+
+// static
+gfx::Size WindowTreeHost::GetNativeScreenSize() {
+ NOTIMPLEMENTED();
+ return gfx::Size();
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/window_tree_host_ozone.h b/chromium/ui/aura/window_tree_host_ozone.h
new file mode 100644
index 00000000000..f7ea6227996
--- /dev/null
+++ b/chromium/ui/aura/window_tree_host_ozone.h
@@ -0,0 +1,58 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_WINDOW_TREE_HOST_OZONE_H_
+#define UI_AURA_WINDOW_TREE_HOST_OZONE_H_
+
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event_source.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/rect.h"
+
+namespace aura {
+
+class AURA_EXPORT WindowTreeHostOzone : public WindowTreeHost,
+ public ui::EventSource,
+ public ui::PlatformEventDispatcher {
+ public:
+ explicit WindowTreeHostOzone(const gfx::Rect& bounds);
+ virtual ~WindowTreeHostOzone();
+
+ private:
+ // ui::PlatformEventDispatcher:
+ virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+ virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+
+ // WindowTreeHost:
+ virtual ui::EventSource* GetEventSource() OVERRIDE;
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual gfx::Rect GetBounds() const OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
+ virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
+ virtual void SetCapture() OVERRIDE;
+ virtual void ReleaseCapture() OVERRIDE;
+ virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
+ virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+ virtual void SetCursorNative(gfx::NativeCursor cursor_type) OVERRIDE;
+ virtual void MoveCursorToNative(const gfx::Point& location) OVERRIDE;
+ virtual void OnCursorVisibilityChangedNative(bool show) OVERRIDE;
+
+ // ui::EventSource overrides.
+ virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
+
+ gfx::AcceleratedWidget widget_;
+ gfx::Rect bounds_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowTreeHostOzone);
+};
+
+} // namespace aura
+
+#endif // UI_AURA_WINDOW_TREE_HOST_OZONE_H_
diff --git a/chromium/ui/aura/window_tree_host_win.cc b/chromium/ui/aura/window_tree_host_win.cc
new file mode 100644
index 00000000000..adf56e91ac7
--- /dev/null
+++ b/chromium/ui/aura/window_tree_host_win.cc
@@ -0,0 +1,238 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/window_tree_host_win.h"
+
+#include <windows.h>
+
+#include <algorithm>
+
+#include "base/message_loop/message_loop.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/cursor/cursor_loader_win.h"
+#include "ui/base/view_prop.h"
+#include "ui/compositor/compositor.h"
+#include "ui/events/event.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/screen.h"
+
+using std::max;
+using std::min;
+
+namespace aura {
+namespace {
+
+bool use_popup_as_root_window_for_test = false;
+
+} // namespace
+
+// static
+WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
+ return new WindowTreeHostWin(bounds);
+}
+
+// static
+gfx::Size WindowTreeHost::GetNativeScreenSize() {
+ return gfx::Size(GetSystemMetrics(SM_CXSCREEN),
+ GetSystemMetrics(SM_CYSCREEN));
+}
+
+WindowTreeHostWin::WindowTreeHostWin(const gfx::Rect& bounds)
+ : has_capture_(false) {
+ if (use_popup_as_root_window_for_test)
+ set_window_style(WS_POPUP);
+ Init(NULL, bounds);
+ SetWindowText(hwnd(), L"aura::RootWindow!");
+ CreateCompositor(GetAcceleratedWidget());
+}
+
+WindowTreeHostWin::~WindowTreeHostWin() {
+ DestroyCompositor();
+ DestroyDispatcher();
+ DestroyWindow(hwnd());
+}
+
+ui::EventSource* WindowTreeHostWin::GetEventSource() {
+ return this;
+}
+
+gfx::AcceleratedWidget WindowTreeHostWin::GetAcceleratedWidget() {
+ return hwnd();
+}
+
+void WindowTreeHostWin::Show() {
+ ShowWindow(hwnd(), SW_SHOWNORMAL);
+}
+
+void WindowTreeHostWin::Hide() {
+ NOTIMPLEMENTED();
+}
+
+gfx::Rect WindowTreeHostWin::GetBounds() const {
+ RECT r;
+ GetClientRect(hwnd(), &r);
+ return gfx::Rect(r);
+}
+
+void WindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
+ RECT window_rect;
+ window_rect.left = bounds.x();
+ window_rect.top = bounds.y();
+ window_rect.right = bounds.right() ;
+ window_rect.bottom = bounds.bottom();
+ AdjustWindowRectEx(&window_rect,
+ GetWindowLong(hwnd(), GWL_STYLE),
+ FALSE,
+ GetWindowLong(hwnd(), GWL_EXSTYLE));
+ SetWindowPos(
+ hwnd(),
+ NULL,
+ window_rect.left,
+ window_rect.top,
+ window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top,
+ SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOREPOSITION);
+
+ // Explicity call OnHostResized when the scale has changed because
+ // the window size may not have changed.
+ float current_scale = compositor()->device_scale_factor();
+ float new_scale = gfx::Screen::GetScreenFor(window())->
+ GetDisplayNearestWindow(window()).device_scale_factor();
+ if (current_scale != new_scale)
+ OnHostResized(bounds.size());
+}
+
+gfx::Point WindowTreeHostWin::GetLocationOnNativeScreen() const {
+ RECT r;
+ GetClientRect(hwnd(), &r);
+ return gfx::Point(r.left, r.top);
+}
+
+
+void WindowTreeHostWin::SetCapture() {
+ if (!has_capture_) {
+ has_capture_ = true;
+ ::SetCapture(hwnd());
+ }
+}
+
+void WindowTreeHostWin::ReleaseCapture() {
+ if (has_capture_) {
+ has_capture_ = false;
+ ::ReleaseCapture();
+ }
+}
+
+void WindowTreeHostWin::SetCursorNative(gfx::NativeCursor native_cursor) {
+ // Custom web cursors are handled directly.
+ if (native_cursor == ui::kCursorCustom)
+ return;
+
+ ui::CursorLoaderWin cursor_loader;
+ cursor_loader.SetPlatformCursor(&native_cursor);
+ ::SetCursor(native_cursor.platform());
+}
+
+void WindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
+ // Deliberately not implemented.
+}
+
+void WindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
+ NOTIMPLEMENTED();
+}
+
+void WindowTreeHostWin::PostNativeEvent(const base::NativeEvent& native_event) {
+ ::PostMessage(
+ hwnd(), native_event.message, native_event.wParam, native_event.lParam);
+}
+
+void WindowTreeHostWin::OnDeviceScaleFactorChanged(
+ float device_scale_factor) {
+ NOTIMPLEMENTED();
+}
+
+ui::EventProcessor* WindowTreeHostWin::GetEventProcessor() {
+ return dispatcher();
+}
+
+void WindowTreeHostWin::OnClose() {
+ // TODO: this obviously shouldn't be here.
+ base::MessageLoopForUI::current()->Quit();
+}
+
+LRESULT WindowTreeHostWin::OnKeyEvent(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ MSG msg = { hwnd(), message, w_param, l_param };
+ ui::KeyEvent keyev(msg, message == WM_CHAR);
+ ui::EventDispatchDetails details = SendEventToProcessor(&keyev);
+ SetMsgHandled(keyev.handled() || details.dispatcher_destroyed);
+ return 0;
+}
+
+LRESULT WindowTreeHostWin::OnMouseRange(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ MSG msg = { hwnd(), message, w_param, l_param, 0,
+ { CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param) } };
+ ui::MouseEvent event(msg);
+ bool handled = false;
+ if (!(event.flags() & ui::EF_IS_NON_CLIENT)) {
+ ui::EventDispatchDetails details = SendEventToProcessor(&event);
+ handled = event.handled() || details.dispatcher_destroyed;
+ }
+ SetMsgHandled(handled);
+ return 0;
+}
+
+LRESULT WindowTreeHostWin::OnCaptureChanged(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ if (has_capture_) {
+ has_capture_ = false;
+ OnHostLostWindowCapture();
+ }
+ return 0;
+}
+
+LRESULT WindowTreeHostWin::OnNCActivate(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ if (!!w_param)
+ OnHostActivated();
+ return DefWindowProc(hwnd(), message, w_param, l_param);
+}
+
+void WindowTreeHostWin::OnMove(const gfx::Point& point) {
+ OnHostMoved(point);
+}
+
+void WindowTreeHostWin::OnPaint(HDC dc) {
+ gfx::Rect damage_rect;
+ RECT update_rect = {0};
+ if (GetUpdateRect(hwnd(), &update_rect, FALSE))
+ damage_rect = gfx::Rect(update_rect);
+ compositor()->ScheduleRedrawRect(damage_rect);
+ ValidateRect(hwnd(), NULL);
+}
+
+void WindowTreeHostWin::OnSize(UINT param, const gfx::Size& size) {
+ // Minimizing resizes the window to 0x0 which causes our layout to go all
+ // screwy, so we just ignore it.
+ if (dispatcher() && param != SIZE_MINIMIZED)
+ OnHostResized(size);
+}
+
+namespace test {
+
+// static
+void SetUsePopupAsRootWindowForTest(bool use) {
+ use_popup_as_root_window_for_test = use;
+}
+
+} // namespace test
+
+} // namespace aura
diff --git a/chromium/ui/aura/window_tree_host_win.h b/chromium/ui/aura/window_tree_host_win.h
new file mode 100644
index 00000000000..64648510927
--- /dev/null
+++ b/chromium/ui/aura/window_tree_host_win.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_WINDOW_TREE_HOST_WIN_H_
+#define UI_AURA_WINDOW_TREE_HOST_WIN_H_
+
+#include "base/compiler_specific.h"
+#include "ui/aura/aura_export.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event_source.h"
+#include "ui/gfx/win/window_impl.h"
+
+namespace aura {
+
+class AURA_EXPORT WindowTreeHostWin : public WindowTreeHost,
+ public ui::EventSource,
+ public gfx::WindowImpl {
+ public:
+ explicit WindowTreeHostWin(const gfx::Rect& bounds);
+ virtual ~WindowTreeHostWin();
+ // WindowTreeHost:
+ virtual ui::EventSource* GetEventSource() OVERRIDE;
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual gfx::Rect GetBounds() const OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
+ virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
+ virtual void SetCapture() OVERRIDE;
+ virtual void ReleaseCapture() OVERRIDE;
+ virtual void SetCursorNative(gfx::NativeCursor cursor) OVERRIDE;
+ virtual void MoveCursorToNative(const gfx::Point& location) OVERRIDE;
+ virtual void OnCursorVisibilityChangedNative(bool show) OVERRIDE;
+ virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
+ virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+
+ // ui::EventSource:
+ virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
+
+ private:
+ CR_BEGIN_MSG_MAP_EX(WindowTreeHostWin)
+ // Range handlers must go first!
+ CR_MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
+ CR_MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE,
+ WM_NCXBUTTONDBLCLK,
+ OnMouseRange)
+
+ // Mouse capture events.
+ CR_MESSAGE_HANDLER_EX(WM_CAPTURECHANGED, OnCaptureChanged)
+
+ // Key events.
+ CR_MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_CHAR, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_SYSCHAR, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_IME_CHAR, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_NCACTIVATE, OnNCActivate)
+
+ CR_MSG_WM_CLOSE(OnClose)
+ CR_MSG_WM_MOVE(OnMove)
+ CR_MSG_WM_PAINT(OnPaint)
+ CR_MSG_WM_SIZE(OnSize)
+ CR_END_MSG_MAP()
+
+ void OnClose();
+ LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param);
+ LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param);
+ LRESULT OnCaptureChanged(UINT message, WPARAM w_param, LPARAM l_param);
+ LRESULT OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param);
+ void OnMove(const gfx::Point& point);
+ void OnPaint(HDC dc);
+ void OnSize(UINT param, const gfx::Size& size);
+
+ bool has_capture_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowTreeHostWin);
+};
+
+namespace test {
+
+// Set true to let WindowTreeHostWin use a popup window
+// with no frame/title so that the window size and test's
+// expectations matches.
+AURA_EXPORT void SetUsePopupAsRootWindowForTest(bool use);
+
+} // namespace
+
+} // namespace aura
+
+#endif // UI_AURA_WINDOW_TREE_HOST_WIN_H_
diff --git a/chromium/ui/aura/root_window_host_x11.cc b/chromium/ui/aura/window_tree_host_x11.cc
index 4fb00471332..c3dcb19f151 100644
--- a/chromium/ui/aura/root_window_host_x11.cc
+++ b/chromium/ui/aura/window_tree_host_x11.cc
@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/aura/root_window_host_x11.h"
+#include "ui/aura/window_tree_host_x11.h"
#include <strings.h>
#include <X11/cursorfont.h>
-#include <X11/extensions/Xfixes.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xrandr.h>
#include <X11/Xatom.h>
@@ -20,27 +19,28 @@
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_pump_x11.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/user_action_client.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/view_prop.h"
#include "ui/base/x/x11_util.h"
+#include "ui/compositor/compositor.h"
#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
+#include "ui/events/event_switches.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/platform/platform_event_observer.h"
+#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/events/x/device_data_manager.h"
#include "ui/events/x/device_list_cache_x.h"
#include "ui/events/x/touch_factory_x11.h"
@@ -53,18 +53,10 @@ namespace aura {
namespace {
-// Standard Linux mouse buttons for going back and forward.
-const int kBackMouseButton = 8;
-const int kForwardMouseButton = 9;
-
const char* kAtomsToCache[] = {
"WM_DELETE_WINDOW",
"_NET_WM_PING",
"_NET_WM_PID",
- "WM_S0",
-#if defined(OS_CHROMEOS)
- "Tap Paused", // Defined in the gestures library.
-#endif
NULL
};
@@ -75,15 +67,6 @@ const char* kAtomsToCache[] = {
return target;
}
-#if defined(USE_XI2_MT)
-bool IsSideBezelsEnabled() {
- static bool side_bezels_enabled =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTouchSideBezels) != "0";
- return side_bezels_enabled;
-}
-#endif
-
void SelectXInput2EventsForRootWindow(XDisplay* display, ::Window root_window) {
CHECK(ui::IsXInput2Available());
unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {};
@@ -122,24 +105,24 @@ bool default_override_redirect = false;
namespace internal {
+// TODO(miletus) : Move this into DeviceDataManager.
// Accomplishes 2 tasks concerning touch event calibration:
// 1. Being a message-pump observer,
// routes all the touch events to the X root window,
// where they can be calibrated later.
// 2. Has the Calibrate method that does the actual bezel calibration,
// when invoked from X root window's event dispatcher.
-class TouchEventCalibrate : public base::MessagePumpObserver {
+class TouchEventCalibrate : public ui::PlatformEventObserver {
public:
- TouchEventCalibrate()
- : left_(0),
- right_(0),
- top_(0),
- bottom_(0) {
- base::MessageLoopForUI::current()->AddObserver(this);
+ TouchEventCalibrate() : left_(0), right_(0), top_(0), bottom_(0) {
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
#if defined(USE_XI2_MT)
std::vector<std::string> parts;
if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTouchCalibration), ",", &parts) >= 4) {
+ switches::kTouchCalibration),
+ ",",
+ &parts) >= 4) {
if (!base::StringToInt(parts[0], &left_))
DLOG(ERROR) << "Incorrect left border calibration value passed.";
if (!base::StringToInt(parts[1], &right_))
@@ -153,22 +136,10 @@ class TouchEventCalibrate : public base::MessagePumpObserver {
}
virtual ~TouchEventCalibrate() {
- base::MessageLoopForUI::current()->RemoveObserver(this);
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
}
-#if defined(USE_XI2_MT)
- bool IsEventOnSideBezels(
- const base::NativeEvent& xev,
- const gfx::Rect& bounds) {
- if (!left_ && !right_)
- return false;
-
- gfx::Point location = ui::EventLocationFromNative(xev);
- int x = location.x();
- return x < left_ || x > bounds.width() - right_;
- }
-#endif // defined(USE_XI2_MT)
-
// Modify the location of the |event|,
// expanding it from |bounds| to (|bounds| + bezels).
// Required when touchscreen is bigger than screen (i.e. has bezels),
@@ -232,9 +203,8 @@ class TouchEventCalibrate : public base::MessagePumpObserver {
}
private:
- // Overridden from base::MessagePumpObserver:
- virtual base::EventStatus WillProcessEvent(
- const base::NativeEvent& event) OVERRIDE {
+ // ui::PlatformEventObserver:
+ virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE {
#if defined(USE_XI2_MT)
if (event->type == GenericEvent &&
(event->xgeneric.evtype == XI_TouchBegin ||
@@ -246,11 +216,9 @@ class TouchEventCalibrate : public base::MessagePumpObserver {
xievent->event_y = xievent->root_y;
}
#endif // defined(USE_XI2_MT)
- return base::EVENT_CONTINUE;
}
- virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
- }
+ virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE {}
// The difference in screen's native resolution pixels between
// the border of the touchscreen and the border of the screen,
@@ -266,61 +234,17 @@ class TouchEventCalibrate : public base::MessagePumpObserver {
} // namespace internal
////////////////////////////////////////////////////////////////////////////////
-// RootWindowHostX11::MouseMoveFilter filters out the move events that
-// jump back and forth between two points. This happens when sub pixel mouse
-// move is enabled and mouse move events could be jumping between two neighbor
-// pixels, e.g. move(0,0), move(1,0), move(0,0), move(1,0) and on and on.
-// The filtering is done by keeping track of the last two event locations and
-// provides a Filter method to find out whether a mouse event is in a different
-// location and should be processed.
-
-class RootWindowHostX11::MouseMoveFilter {
- public:
- MouseMoveFilter() : insert_index_(0) {
- for (size_t i = 0; i < kMaxEvents; ++i) {
- const int int_max = std::numeric_limits<int>::max();
- recent_locations_[i] = gfx::Point(int_max, int_max);
- }
- }
- ~MouseMoveFilter() {}
-
- // Returns true if |event| is known and should be ignored.
- bool Filter(const base::NativeEvent& event) {
- const gfx::Point& location = ui::EventLocationFromNative(event);
- for (size_t i = 0; i < kMaxEvents; ++i) {
- if (location == recent_locations_[i])
- return true;
- }
-
- recent_locations_[insert_index_] = location;
- insert_index_ = (insert_index_ + 1) % kMaxEvents;
- return false;
- }
-
- private:
- static const size_t kMaxEvents = 2;
-
- gfx::Point recent_locations_[kMaxEvents];
- size_t insert_index_;
-
- DISALLOW_COPY_AND_ASSIGN(MouseMoveFilter);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// RootWindowHostX11
+// WindowTreeHostX11
-RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds)
+WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds)
: xdisplay_(gfx::GetXDisplay()),
xwindow_(0),
x_root_window_(DefaultRootWindow(xdisplay_)),
current_cursor_(ui::kCursorNull),
window_mapped_(false),
bounds_(bounds),
- is_internal_display_(false),
touch_calibrate_(new internal::TouchEventCalibrate),
- mouse_move_filter_(new MouseMoveFilter),
- atom_cache_(xdisplay_, kAtomsToCache),
- bezel_tracking_ids_(0) {
+ atom_cache_(xdisplay_, kAtomsToCache) {
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
swa.background_pixmap = None;
@@ -334,8 +258,8 @@ RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds)
CopyFromParent, // visual
CWBackPixmap | CWOverrideRedirect,
&swa);
- base::MessagePumpX11::Current()->AddDispatcherForWindow(this, xwindow_);
- base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this);
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
KeyPressMask | KeyReleaseMask |
@@ -376,30 +300,46 @@ RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds)
PropModeReplace,
reinterpret_cast<unsigned char*>(&pid), 1);
+ // Allow subclasses to create and cache additional atoms.
+ atom_cache_.allow_uncached_atoms();
+
XRRSelectInput(xdisplay_, x_root_window_,
RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
- Env::GetInstance()->AddObserver(this);
+ CreateCompositor(GetAcceleratedWidget());
}
-RootWindowHostX11::~RootWindowHostX11() {
- Env::GetInstance()->RemoveObserver(this);
- base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this);
- base::MessagePumpX11::Current()->RemoveDispatcherForWindow(xwindow_);
-
- UnConfineCursor();
+WindowTreeHostX11::~WindowTreeHostX11() {
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
+ DestroyCompositor();
+ DestroyDispatcher();
XDestroyWindow(xdisplay_, xwindow_);
}
-bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
- XEvent* xev = event;
+bool WindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent& event) {
+ ::Window target = FindEventTarget(event);
+ return target == xwindow_ || target == x_root_window_;
+}
- if (FindEventTarget(event) == x_root_window_)
- return DispatchEventForRootWindow(event);
+uint32_t WindowTreeHostX11::DispatchEvent(const ui::PlatformEvent& event) {
+ XEvent* xev = event;
+ if (FindEventTarget(xev) == x_root_window_) {
+ if (xev->type == GenericEvent)
+ DispatchXI2Event(xev);
+ return ui::POST_DISPATCH_NONE;
+ }
switch (xev->type) {
case EnterNotify: {
- aura::Window* root_window = GetRootWindow()->window();
+ // Ignore EventNotify events from children of |xwindow_|.
+ // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
+ // TODO(pkotwicz|tdanderson): Figure out whether the suppression is
+ // necessary. crbug.com/385716
+ if (xev->xcrossing.detail == NotifyInferior)
+ break;
+
+ aura::Window* root_window = window();
client::CursorClient* cursor_client =
client::GetCursorClient(root_window);
if (cursor_client) {
@@ -411,55 +351,49 @@ bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
// EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is not
// real mouse move event.
mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED);
- TranslateAndDispatchMouseEvent(&mouse_event);
+ TranslateAndDispatchLocatedEvent(&mouse_event);
break;
}
case LeaveNotify: {
+ // Ignore LeaveNotify events from children of |xwindow_|.
+ // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
+ // TODO(pkotwicz|tdanderson): Figure out whether the suppression is
+ // necessary. crbug.com/385716
+ if (xev->xcrossing.detail == NotifyInferior)
+ break;
+
ui::MouseEvent mouse_event(xev);
- TranslateAndDispatchMouseEvent(&mouse_event);
+ TranslateAndDispatchLocatedEvent(&mouse_event);
break;
}
case Expose: {
gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
xev->xexpose.width, xev->xexpose.height);
- delegate_->AsRootWindow()->ScheduleRedrawRect(damage_rect);
+ compositor()->ScheduleRedrawRect(damage_rect);
break;
}
case KeyPress: {
ui::KeyEvent keydown_event(xev, false);
- delegate_->OnHostKeyEvent(&keydown_event);
+ SendEventToProcessor(&keydown_event);
break;
}
case KeyRelease: {
ui::KeyEvent keyup_event(xev, false);
- delegate_->OnHostKeyEvent(&keyup_event);
+ SendEventToProcessor(&keyup_event);
break;
}
- case ButtonPress: {
- if (static_cast<int>(xev->xbutton.button) == kBackMouseButton ||
- static_cast<int>(xev->xbutton.button) == kForwardMouseButton) {
- client::UserActionClient* gesture_client =
- client::GetUserActionClient(delegate_->AsRootWindow()->window());
- if (gesture_client) {
- gesture_client->OnUserAction(
- static_cast<int>(xev->xbutton.button) == kBackMouseButton ?
- client::UserActionClient::BACK :
- client::UserActionClient::FORWARD);
- }
- break;
- }
- } // fallthrough
+ case ButtonPress:
case ButtonRelease: {
switch (ui::EventTypeFromNative(xev)) {
case ui::ET_MOUSEWHEEL: {
ui::MouseWheelEvent mouseev(xev);
- TranslateAndDispatchMouseEvent(&mouseev);
+ TranslateAndDispatchLocatedEvent(&mouseev);
break;
}
case ui::ET_MOUSE_PRESSED:
case ui::ET_MOUSE_RELEASED: {
ui::MouseEvent mouseev(xev);
- TranslateAndDispatchMouseEvent(&mouseev);
+ TranslateAndDispatchLocatedEvent(&mouseev);
break;
}
case ui::ET_UNKNOWN:
@@ -472,7 +406,7 @@ bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
}
case FocusOut:
if (xev->xfocus.mode != NotifyGrab)
- delegate_->OnHostLostWindowCapture();
+ OnHostLostWindowCapture();
break;
case ConfigureNotify: {
DCHECK_EQ(xwindow_, xev->xconfigure.event);
@@ -485,27 +419,21 @@ bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
bool size_changed = bounds_.size() != bounds.size();
bool origin_changed = bounds_.origin() != bounds.origin();
bounds_ = bounds;
- UpdateIsInternalDisplay();
- // Always update barrier and mouse location because |bounds_| might
- // have already been updated in |SetBounds|.
- if (pointer_barriers_) {
- UnConfineCursor();
- ConfineCursorToRootWindow();
- }
+ OnConfigureNotify();
if (size_changed)
- delegate_->OnHostResized(bounds.size());
+ OnHostResized(bounds.size());
if (origin_changed)
- delegate_->OnHostMoved(bounds_.origin());
+ OnHostMoved(bounds_.origin());
break;
}
case GenericEvent:
- DispatchXI2Event(event);
+ DispatchXI2Event(xev);
break;
case ClientMessage: {
Atom message_type = static_cast<Atom>(xev->xclient.data.l[0]);
if (message_type == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
// We have received a close message from the window manager.
- delegate_->AsRootWindow()->OnRootWindowHostCloseRequested();
+ OnHostCloseRequested();
} else if (message_type == atom_cache_.GetAtom("_NET_WM_PING")) {
XEvent reply_event = *xev;
reply_event.xclient.window = x_root_window_;
@@ -515,6 +443,7 @@ bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&reply_event);
+ XFlush(xdisplay_);
}
break;
}
@@ -523,7 +452,6 @@ bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
case MappingModifier:
case MappingKeyboard:
XRefreshKeyboardMapping(&xev->xmapping);
- delegate_->AsRootWindow()->OnKeyboardMappingChanged();
break;
case MappingPointer:
ui::DeviceDataManager::GetInstance()->UpdateButtonMap();
@@ -553,22 +481,22 @@ bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
}
ui::MouseEvent mouseev(xev);
- TranslateAndDispatchMouseEvent(&mouseev);
+ TranslateAndDispatchLocatedEvent(&mouseev);
break;
}
}
- return true;
+ return ui::POST_DISPATCH_STOP_PROPAGATION;
}
-RootWindow* RootWindowHostX11::GetRootWindow() {
- return delegate_->AsRootWindow();
+ui::EventSource* WindowTreeHostX11::GetEventSource() {
+ return this;
}
-gfx::AcceleratedWidget RootWindowHostX11::GetAcceleratedWidget() {
+gfx::AcceleratedWidget WindowTreeHostX11::GetAcceleratedWidget() {
return xwindow_;
}
-void RootWindowHostX11::Show() {
+void WindowTreeHostX11::Show() {
if (!window_mapped_) {
// Before we map the window, set size hints. Otherwise, some window managers
// will ignore toplevel XMoveWindow commands.
@@ -586,33 +514,29 @@ void RootWindowHostX11::Show() {
// We now block until our window is mapped. Some X11 APIs will crash and
// burn if passed |xwindow_| before the window is mapped, and XMapWindow is
// asynchronous.
- base::MessagePumpX11::Current()->BlockUntilWindowMapped(xwindow_);
+ if (ui::X11EventSource::GetInstance())
+ ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
window_mapped_ = true;
}
}
-void RootWindowHostX11::Hide() {
+void WindowTreeHostX11::Hide() {
if (window_mapped_) {
XWithdrawWindow(xdisplay_, xwindow_, 0);
window_mapped_ = false;
}
}
-void RootWindowHostX11::ToggleFullScreen() {
- NOTIMPLEMENTED();
-}
-
-gfx::Rect RootWindowHostX11::GetBounds() const {
+gfx::Rect WindowTreeHostX11::GetBounds() const {
return bounds_;
}
-void RootWindowHostX11::SetBounds(const gfx::Rect& bounds) {
+void WindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
// Even if the host window's size doesn't change, aura's root window
// size, which is in DIP, changes when the scale changes.
- float current_scale = delegate_->GetDeviceScaleFactor();
- float new_scale = gfx::Screen::GetScreenFor(
- delegate_->AsRootWindow()->window())->GetDisplayNearestWindow(
- delegate_->AsRootWindow()->window()).device_scale_factor();
+ float current_scale = compositor()->device_scale_factor();
+ float new_scale = gfx::Screen::GetScreenFor(window())->
+ GetDisplayNearestWindow(window()).device_scale_factor();
bool origin_changed = bounds_.origin() != bounds.origin();
bool size_changed = bounds_.size() != bounds.size();
XWindowChanges changes = {0};
@@ -638,131 +562,28 @@ void RootWindowHostX11::SetBounds(const gfx::Rect& bounds) {
// (possibly synthetic) ConfigureNotify about the actual size and correct
// |bounds_| later.
bounds_ = bounds;
- UpdateIsInternalDisplay();
if (origin_changed)
- delegate_->OnHostMoved(bounds.origin());
+ OnHostMoved(bounds.origin());
if (size_changed || current_scale != new_scale) {
- delegate_->OnHostResized(bounds.size());
+ OnHostResized(bounds.size());
} else {
- delegate_->AsRootWindow()->window()->SchedulePaintInRect(
- delegate_->AsRootWindow()->window()->bounds());
+ window()->SchedulePaintInRect(window()->bounds());
}
}
-gfx::Insets RootWindowHostX11::GetInsets() const {
- return insets_;
-}
-
-void RootWindowHostX11::SetInsets(const gfx::Insets& insets) {
- insets_ = insets;
- if (pointer_barriers_) {
- UnConfineCursor();
- ConfineCursorToRootWindow();
- }
-}
-
-gfx::Point RootWindowHostX11::GetLocationOnNativeScreen() const {
+gfx::Point WindowTreeHostX11::GetLocationOnNativeScreen() const {
return bounds_.origin();
}
-void RootWindowHostX11::SetCapture() {
+void WindowTreeHostX11::SetCapture() {
// TODO(oshima): Grab x input.
}
-void RootWindowHostX11::ReleaseCapture() {
+void WindowTreeHostX11::ReleaseCapture() {
// TODO(oshima): Release x input.
}
-void RootWindowHostX11::SetCursor(gfx::NativeCursor cursor) {
- if (cursor == current_cursor_)
- return;
- current_cursor_ = cursor;
- SetCursorInternal(cursor);
-}
-
-bool RootWindowHostX11::QueryMouseLocation(gfx::Point* location_return) {
- client::CursorClient* cursor_client =
- client::GetCursorClient(GetRootWindow()->window());
- if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
- *location_return = gfx::Point(0, 0);
- return false;
- }
-
- ::Window root_return, child_return;
- int root_x_return, root_y_return, win_x_return, win_y_return;
- unsigned int mask_return;
- XQueryPointer(xdisplay_,
- xwindow_,
- &root_return,
- &child_return,
- &root_x_return, &root_y_return,
- &win_x_return, &win_y_return,
- &mask_return);
- *location_return = gfx::Point(max(0, min(bounds_.width(), win_x_return)),
- max(0, min(bounds_.height(), win_y_return)));
- return (win_x_return >= 0 && win_x_return < bounds_.width() &&
- win_y_return >= 0 && win_y_return < bounds_.height());
-}
-
-bool RootWindowHostX11::ConfineCursorToRootWindow() {
-#if XFIXES_MAJOR >= 5
- DCHECK(!pointer_barriers_.get());
- if (pointer_barriers_)
- return false;
- pointer_barriers_.reset(new XID[4]);
- gfx::Rect bounds(bounds_);
- bounds.Inset(insets_);
- // Horizontal, top barriers.
- pointer_barriers_[0] = XFixesCreatePointerBarrier(
- xdisplay_, x_root_window_,
- bounds.x(), bounds.y(), bounds.right(), bounds.y(),
- BarrierPositiveY,
- 0, XIAllDevices);
- // Horizontal, bottom barriers.
- pointer_barriers_[1] = XFixesCreatePointerBarrier(
- xdisplay_, x_root_window_,
- bounds.x(), bounds.bottom(), bounds.right(), bounds.bottom(),
- BarrierNegativeY,
- 0, XIAllDevices);
- // Vertical, left barriers.
- pointer_barriers_[2] = XFixesCreatePointerBarrier(
- xdisplay_, x_root_window_,
- bounds.x(), bounds.y(), bounds.x(), bounds.bottom(),
- BarrierPositiveX,
- 0, XIAllDevices);
- // Vertical, right barriers.
- pointer_barriers_[3] = XFixesCreatePointerBarrier(
- xdisplay_, x_root_window_,
- bounds.right(), bounds.y(), bounds.right(), bounds.bottom(),
- BarrierNegativeX,
- 0, XIAllDevices);
-#endif
- return true;
-}
-
-void RootWindowHostX11::UnConfineCursor() {
-#if XFIXES_MAJOR >= 5
- if (pointer_barriers_) {
- XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[0]);
- XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[1]);
- XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[2]);
- XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[3]);
- pointer_barriers_.reset();
- }
-#endif
-}
-
-void RootWindowHostX11::OnCursorVisibilityChanged(bool show) {
- SetCrOSTapPaused(!show);
-}
-
-void RootWindowHostX11::MoveCursorTo(const gfx::Point& location) {
- XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
- bounds_.x() + location.x(),
- bounds_.y() + location.y());
-}
-
-void RootWindowHostX11::PostNativeEvent(
+void WindowTreeHostX11::PostNativeEvent(
const base::NativeEvent& native_event) {
DCHECK(xwindow_);
DCHECK(xdisplay_);
@@ -785,7 +606,7 @@ void RootWindowHostX11::PostNativeEvent(
xevent.xmotion.time = CurrentTime;
gfx::Point point(xevent.xmotion.x, xevent.xmotion.y);
- delegate_->AsRootWindow()->host()->ConvertPointToNativeScreen(&point);
+ ConvertPointToNativeScreen(&point);
xevent.xmotion.x_root = point.x();
xevent.xmotion.y_root = point.y();
}
@@ -793,57 +614,41 @@ void RootWindowHostX11::PostNativeEvent(
break;
}
XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
+ XFlush(xdisplay_);
}
-void RootWindowHostX11::OnDeviceScaleFactorChanged(
+void WindowTreeHostX11::OnDeviceScaleFactorChanged(
float device_scale_factor) {
}
-void RootWindowHostX11::PrepareForShutdown() {
- base::MessagePumpX11::Current()->RemoveDispatcherForWindow(xwindow_);
-}
-
-void RootWindowHostX11::OnWindowInitialized(Window* window) {
-}
-
-void RootWindowHostX11::OnRootWindowInitialized(RootWindow* root_window) {
- // UpdateIsInternalDisplay relies on:
- // 1. delegate_ pointing to RootWindow - available after SetDelegate.
- // 2. RootWindow's kDisplayIdKey property set - available by the time
- // RootWindow::Init is called.
- // (set in DisplayManager::CreateRootWindowForDisplay)
- // Ready when NotifyRootWindowInitialized is called from RootWindow::Init.
- if (!delegate_ || root_window != GetRootWindow())
+void WindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) {
+ if (cursor == current_cursor_)
return;
- UpdateIsInternalDisplay();
-
- // We have to enable Tap-to-click by default because the cursor is set to
- // visible in Shell::InitRootWindowController.
- SetCrOSTapPaused(false);
+ current_cursor_ = cursor;
+ SetCursorInternal(cursor);
}
-ui::EventProcessor* RootWindowHostX11::GetEventProcessor() {
- return delegate_->GetEventProcessor();
+void WindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) {
+ XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
+ bounds_.x() + location.x(),
+ bounds_.y() + location.y());
}
-bool RootWindowHostX11::DispatchEventForRootWindow(
- const base::NativeEvent& event) {
- switch (event->type) {
- case GenericEvent:
- DispatchXI2Event(event);
- break;
- }
+void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
+}
- return true;
+ui::EventProcessor* WindowTreeHostX11::GetEventProcessor() {
+ return dispatcher();
}
-void RootWindowHostX11::DispatchXI2Event(const base::NativeEvent& event) {
+void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) {
ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
XEvent* xev = event;
+ XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
if (!factory->ShouldProcessXI2Event(xev))
return;
- TRACE_EVENT1("input", "RootWindowHostX11::DispatchXI2Event",
+ TRACE_EVENT1("input", "WindowTreeHostX11::DispatchXI2Event",
"event_latency_us",
(ui::EventTimeForNow() - ui::EventTimeFromNative(event)).
InMicroseconds());
@@ -857,50 +662,12 @@ void RootWindowHostX11::DispatchXI2Event(const base::NativeEvent& event) {
case ui::ET_TOUCH_PRESSED:
case ui::ET_TOUCH_CANCELLED:
case ui::ET_TOUCH_RELEASED: {
-#if defined(OS_CHROMEOS)
- // Bail out early before generating a ui::TouchEvent if this event
- // is not within the range of this RootWindow. Converting an xevent
- // to ui::TouchEvent might change the state of the global touch tracking
- // state, e.g. touch release event can remove the touch id from the
- // record, and doing this multiple time when there are multiple
- // RootWindow will cause problem. So only generate the ui::TouchEvent
- // when we are sure it belongs to this RootWindow.
- if (base::SysInfo::IsRunningOnChromeOS() &&
- !bounds_.Contains(ui::EventLocationFromNative(xev)))
- break;
-#endif // defined(OS_CHROMEOS)
ui::TouchEvent touchev(xev);
-#if defined(USE_XI2_MT)
- // Ignore touch events with touch press happening on the side bezel.
- if (!IsSideBezelsEnabled()) {
- uint32 tracking_id = (1 << touchev.touch_id());
- if (type == ui::ET_TOUCH_PRESSED &&
- touch_calibrate_->IsEventOnSideBezels(xev, bounds_))
- bezel_tracking_ids_ |= tracking_id;
- if (bezel_tracking_ids_ & tracking_id) {
- if (type == ui::ET_TOUCH_CANCELLED || type == ui::ET_TOUCH_RELEASED)
- bezel_tracking_ids_ =
- (bezel_tracking_ids_ | tracking_id) ^ tracking_id;
- return;
- }
+ if (ui::DeviceDataManager::GetInstance()->TouchEventNeedsCalibrate(
+ xiev->deviceid)) {
+ touch_calibrate_->Calibrate(&touchev, bounds_);
}
-#endif // defined(USE_XI2_MT)
-#if defined(OS_CHROMEOS)
- if (base::SysInfo::IsRunningOnChromeOS()) {
- // X maps the touch-surface to the size of the X root-window.
- // In multi-monitor setup, Coordinate Transformation Matrix
- // repositions the touch-surface onto part of X root-window
- // containing aura root-window corresponding to the touchscreen.
- // However, if aura root-window has non-zero origin,
- // we need to relocate the event into aura root-window coordinates.
- touchev.Relocate(bounds_.origin());
-#if defined(USE_XI2_MT)
- if (is_internal_display_)
- touch_calibrate_->Calibrate(&touchev, bounds_);
-#endif // defined(USE_XI2_MT)
- }
-#endif // defined(OS_CHROMEOS)
- delegate_->OnHostTouchEvent(&touchev);
+ TranslateAndDispatchLocatedEvent(&touchev);
break;
}
case ui::ET_MOUSE_MOVED:
@@ -915,45 +682,21 @@ void RootWindowHostX11::DispatchXI2Event(const base::NativeEvent& event) {
num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
if (num_coalesced > 0)
xev = &last_event;
-
- if (mouse_move_filter_ && mouse_move_filter_->Filter(xev))
- break;
- } else if (type == ui::ET_MOUSE_PRESSED ||
- type == ui::ET_MOUSE_RELEASED) {
- XIDeviceEvent* xievent =
- static_cast<XIDeviceEvent*>(xev->xcookie.data);
- int button = xievent->detail;
- if (button == kBackMouseButton || button == kForwardMouseButton) {
- if (type == ui::ET_MOUSE_RELEASED)
- break;
- client::UserActionClient* gesture_client =
- client::GetUserActionClient(delegate_->AsRootWindow()->window());
- if (gesture_client) {
- bool reverse_direction =
- ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
- gesture_client->OnUserAction(
- (button == kBackMouseButton && !reverse_direction) ||
- (button == kForwardMouseButton && reverse_direction) ?
- client::UserActionClient::BACK :
- client::UserActionClient::FORWARD);
- }
- break;
- }
}
ui::MouseEvent mouseev(xev);
- TranslateAndDispatchMouseEvent(&mouseev);
+ TranslateAndDispatchLocatedEvent(&mouseev);
break;
}
case ui::ET_MOUSEWHEEL: {
ui::MouseWheelEvent mouseev(xev);
- TranslateAndDispatchMouseEvent(&mouseev);
+ TranslateAndDispatchLocatedEvent(&mouseev);
break;
}
case ui::ET_SCROLL_FLING_START:
case ui::ET_SCROLL_FLING_CANCEL:
case ui::ET_SCROLL: {
ui::ScrollEvent scrollev(xev);
- delegate_->OnHostScrollEvent(&scrollev);
+ SendEventToProcessor(&scrollev);
break;
}
case ui::ET_UMA_DATA:
@@ -969,83 +712,24 @@ void RootWindowHostX11::DispatchXI2Event(const base::NativeEvent& event) {
XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
}
-bool RootWindowHostX11::IsWindowManagerPresent() {
- // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
- // of WM_Sn selections (where n is a screen number).
- return XGetSelectionOwner(
- xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
-}
-
-void RootWindowHostX11::SetCursorInternal(gfx::NativeCursor cursor) {
+void WindowTreeHostX11::SetCursorInternal(gfx::NativeCursor cursor) {
XDefineCursor(xdisplay_, xwindow_, cursor.platform());
}
-void RootWindowHostX11::TranslateAndDispatchMouseEvent(
- ui::MouseEvent* event) {
- Window* root_window = GetRootWindow()->window();
- client::ScreenPositionClient* screen_position_client =
- client::GetScreenPositionClient(root_window);
- gfx::Rect local(bounds_.size());
-
- if (screen_position_client && !local.Contains(event->location())) {
- gfx::Point location(event->location());
- // In order to get the correct point in screen coordinates
- // during passive grab, we first need to find on which host window
- // the mouse is on, and find out the screen coordinates on that
- // host window, then convert it back to this host window's coordinate.
- screen_position_client->ConvertHostPointToScreen(root_window, &location);
- screen_position_client->ConvertPointFromScreen(root_window, &location);
- root_window->GetDispatcher()->ConvertPointToHost(&location);
- event->set_location(location);
- event->set_root_location(location);
- }
- delegate_->OnHostMouseEvent(event);
-}
-
-void RootWindowHostX11::UpdateIsInternalDisplay() {
- Window* root_window = GetRootWindow()->window();
- gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window);
- gfx::Display display = screen->GetDisplayNearestWindow(root_window);
- is_internal_display_ = display.IsInternal();
-}
+void WindowTreeHostX11::OnConfigureNotify() {}
-void RootWindowHostX11::SetCrOSTapPaused(bool state) {
-#if defined(OS_CHROMEOS)
- if (!ui::IsXInput2Available())
- return;
- // Temporarily pause tap-to-click when the cursor is hidden.
- Atom prop = atom_cache_.GetAtom("Tap Paused");
- unsigned char value = state;
- XIDeviceList dev_list =
- ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(xdisplay_);
-
- // Only slave pointer devices could possibly have tap-paused property.
- for (int i = 0; i < dev_list.count; i++) {
- if (dev_list[i].use == XISlavePointer) {
- Atom old_type;
- int old_format;
- unsigned long old_nvalues, bytes;
- unsigned char* data;
- int result = XIGetProperty(xdisplay_, dev_list[i].deviceid, prop, 0, 0,
- False, AnyPropertyType, &old_type, &old_format,
- &old_nvalues, &bytes, &data);
- if (result != Success)
- continue;
- XFree(data);
- XIChangeProperty(xdisplay_, dev_list[i].deviceid, prop, XA_INTEGER, 8,
- PropModeReplace, &value, 1);
- }
- }
-#endif
+void WindowTreeHostX11::TranslateAndDispatchLocatedEvent(
+ ui::LocatedEvent* event) {
+ SendEventToProcessor(event);
}
// static
-RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
- return new RootWindowHostX11(bounds);
+WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
+ return new WindowTreeHostX11(bounds);
}
// static
-gfx::Size RootWindowHost::GetNativeScreenSize() {
+gfx::Size WindowTreeHost::GetNativeScreenSize() {
::XDisplay* xdisplay = gfx::GetXDisplay();
return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
}
diff --git a/chromium/ui/aura/window_tree_host_x11.h b/chromium/ui/aura/window_tree_host_x11.h
new file mode 100644
index 00000000000..1db9f675684
--- /dev/null
+++ b/chromium/ui/aura/window_tree_host_x11.h
@@ -0,0 +1,118 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_WINDOW_TREE_HOST_X11_H_
+#define UI_AURA_WINDOW_TREE_HOST_X11_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/aura_export.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event_source.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+
+// X forward decls to avoid including Xlib.h in a header file.
+typedef struct _XDisplay XDisplay;
+typedef unsigned long XID;
+typedef XID Window;
+
+namespace ui {
+class MouseEvent;
+}
+
+namespace aura {
+
+namespace internal {
+class TouchEventCalibrate;
+}
+
+class AURA_EXPORT WindowTreeHostX11 : public WindowTreeHost,
+ public ui::EventSource,
+ public ui::PlatformEventDispatcher {
+
+ public:
+ explicit WindowTreeHostX11(const gfx::Rect& bounds);
+ virtual ~WindowTreeHostX11();
+
+ // ui::PlatformEventDispatcher:
+ virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+ virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+
+ // WindowTreeHost:
+ virtual ui::EventSource* GetEventSource() OVERRIDE;
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual gfx::Rect GetBounds() const OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
+ virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
+ virtual void SetCapture() OVERRIDE;
+ virtual void ReleaseCapture() OVERRIDE;
+ virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
+ virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+ virtual void SetCursorNative(gfx::NativeCursor cursor_type) OVERRIDE;
+ virtual void MoveCursorToNative(const gfx::Point& location) OVERRIDE;
+ virtual void OnCursorVisibilityChangedNative(bool show) OVERRIDE;
+
+ // ui::EventSource overrides.
+ virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
+
+ protected:
+ // Called when X Configure Notify event is recevied.
+ virtual void OnConfigureNotify();
+
+ // Translates the native mouse location into screen coordinates and
+ // dispatches the event via WindowEventDispatcher.
+ virtual void TranslateAndDispatchLocatedEvent(ui::LocatedEvent* event);
+
+ ::Window x_root_window() { return x_root_window_; }
+ XDisplay* xdisplay() { return xdisplay_; }
+ const gfx::Rect bounds() const { return bounds_; }
+ ui::X11AtomCache* atom_cache() { return &atom_cache_; }
+
+ private:
+ // Dispatches XI2 events. Note that some events targetted for the X root
+ // window are dispatched to the aura root window (e.g. touch events after
+ // calibration).
+ void DispatchXI2Event(const base::NativeEvent& event);
+
+ // Sets the cursor on |xwindow_| to |cursor|. Does not check or update
+ // |current_cursor_|.
+ void SetCursorInternal(gfx::NativeCursor cursor);
+
+ // The display and the native X window hosting the root window.
+ XDisplay* xdisplay_;
+ ::Window xwindow_;
+
+ // The native root window.
+ ::Window x_root_window_;
+
+ // Current Aura cursor.
+ gfx::NativeCursor current_cursor_;
+
+ // Is the window mapped to the screen?
+ bool window_mapped_;
+
+ // The bounds of |xwindow_|.
+ gfx::Rect bounds_;
+
+ scoped_ptr<internal::TouchEventCalibrate> touch_calibrate_;
+
+ ui::X11AtomCache atom_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowTreeHostX11);
+};
+
+namespace test {
+
+// Set the default value of the override redirect flag used to
+// create a X window for WindowTreeHostX11.
+AURA_EXPORT void SetUseOverrideRedirectWindowByDefault(bool override_redirect);
+
+} // namespace test
+} // namespace aura
+
+#endif // UI_AURA_WINDOW_TREE_HOST_X11_H_
diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc
index b79143113b7..37cf5edca78 100644
--- a/chromium/ui/aura/window_unittest.cc
+++ b/chromium/ui/aura/window_unittest.cc
@@ -18,20 +18,20 @@
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/client/visibility_client.h"
#include "ui/aura/client/window_tree_client.h"
-#include "ui/aura/layout_manager.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/root_window_observer.h"
#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/aura_test_utils.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/test/window_test_api.h"
#include "ui/aura/window_delegate.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_observer.h"
#include "ui/aura/window_property.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/compositor/test/test_layers.h"
@@ -94,13 +94,13 @@ class DestroyTrackingDelegateImpl : public TestWindowDelegate {
bool in_destroying() const { return in_destroying_; }
- virtual void OnWindowDestroying() OVERRIDE {
+ virtual void OnWindowDestroying(Window* window) OVERRIDE {
EXPECT_FALSE(in_destroying_);
in_destroying_ = true;
destroying_count_++;
}
- virtual void OnWindowDestroyed() OVERRIDE {
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE {
EXPECT_TRUE(in_destroying_);
in_destroying_ = false;
destroyed_count_++;
@@ -123,9 +123,9 @@ class ChildWindowDelegateImpl : public DestroyTrackingDelegateImpl {
: parent_delegate_(parent_delegate) {
}
- virtual void OnWindowDestroying() OVERRIDE {
+ virtual void OnWindowDestroying(Window* window) OVERRIDE {
EXPECT_TRUE(parent_delegate_->in_destroying());
- DestroyTrackingDelegateImpl::OnWindowDestroying();
+ DestroyTrackingDelegateImpl::OnWindowDestroying(window);
}
private:
@@ -143,7 +143,7 @@ class DestroyOrphanDelegate : public TestWindowDelegate {
void set_window(Window* window) { window_ = window; }
- virtual void OnWindowDestroyed() OVERRIDE {
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE {
EXPECT_FALSE(window_->parent());
}
@@ -245,7 +245,7 @@ class DestroyWindowDelegate : public TestWindowDelegate {
virtual ~DestroyWindowDelegate() {}
// Overridden from WindowDelegate.
- virtual void OnWindowDestroyed() OVERRIDE {
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE {
delete this;
}
@@ -269,11 +269,11 @@ TEST_F(WindowTest, GetChildById) {
// and not containing NULL or parents.
TEST_F(WindowTest, Contains) {
Window parent(NULL);
- parent.Init(ui::LAYER_NOT_DRAWN);
+ parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window child1(NULL);
- child1.Init(ui::LAYER_NOT_DRAWN);
+ child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window child2(NULL);
- child2.Init(ui::LAYER_NOT_DRAWN);
+ child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent.AddChild(&child1);
child1.AddChild(&child2);
@@ -372,13 +372,11 @@ TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
transform.Translate(100.0, 100.0);
transform.Rotate(90.0);
transform.Scale(2.0, 5.0);
- dispatcher()->SetTransform(transform);
- dispatcher()->MoveCursorTo(gfx::Point(10, 10));
+ host()->SetRootTransform(transform);
+ host()->MoveCursorTo(gfx::Point(10, 10));
#if !defined(OS_WIN)
- gfx::Point mouse_location;
- EXPECT_TRUE(dispatcher()->host()->QueryMouseLocation(&mouse_location));
// TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
- EXPECT_EQ("50,120", mouse_location.ToString());
+ EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
#endif
EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
root_window())->GetCursorScreenPoint().ToString());
@@ -453,7 +451,7 @@ TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
transform.Translate(10.0, 20.0);
transform.Rotate(10.0);
transform.Scale(0.3f, 0.5f);
- dispatcher()->SetTransform(root_transform);
+ host()->SetRootTransform(root_transform);
w1->SetTransform(transform);
w11->SetTransform(transform);
w111->SetTransform(transform);
@@ -463,67 +461,12 @@ TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
#if !defined(OS_WIN)
// TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
- gfx::Point mouse_location;
- EXPECT_TRUE(dispatcher()->host()->QueryMouseLocation(&mouse_location));
- EXPECT_EQ("169,80", mouse_location.ToString());
+ EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
#endif
EXPECT_EQ("20,53",
gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
}
-TEST_F(WindowTest, HitTest) {
- Window w1(new ColorTestWindowDelegate(SK_ColorWHITE));
- w1.set_id(1);
- w1.Init(ui::LAYER_TEXTURED);
- w1.SetBounds(gfx::Rect(10, 20, 50, 60));
- w1.Show();
- ParentWindow(&w1);
-
- // Points are in the Window's coordinates.
- EXPECT_TRUE(w1.HitTest(gfx::Point(1, 1)));
- EXPECT_FALSE(w1.HitTest(gfx::Point(-1, -1)));
-
- // We can expand the bounds slightly to track events outside our border.
- w1.SetHitTestBoundsOverrideOuter(gfx::Insets(-1, -1, -1, -1),
- gfx::Insets(-5, -5, -5, -5));
- EXPECT_TRUE(w1.HitTest(gfx::Point(-1, -1)));
- EXPECT_FALSE(w1.HitTest(gfx::Point(-2, -2)));
-
- ui::TouchEvent pressed(
- ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&pressed);
- EXPECT_TRUE(w1.HitTest(gfx::Point(-2, -2)));
- EXPECT_TRUE(w1.HitTest(gfx::Point(-5, -5)));
- EXPECT_FALSE(w1.HitTest(gfx::Point(-5, -6)));
- ui::TouchEvent released(
- ui::ET_TOUCH_RELEASED, gfx::Point(50, 50), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&released);
- EXPECT_FALSE(w1.HitTest(gfx::Point(-2, -2)));
-
- // TODO(beng): clip Window to parent.
-}
-
-TEST_F(WindowTest, HitTestMask) {
- MaskedWindowDelegate d1(gfx::Rect(5, 6, 20, 30));
- Window w1(&d1);
- w1.Init(ui::LAYER_NOT_DRAWN);
- w1.SetBounds(gfx::Rect(10, 20, 50, 60));
- w1.Show();
- ParentWindow(&w1);
-
- // Points inside the mask.
- EXPECT_TRUE(w1.HitTest(gfx::Point(5, 6))); // top-left
- EXPECT_TRUE(w1.HitTest(gfx::Point(15, 21))); // center
- EXPECT_TRUE(w1.HitTest(gfx::Point(24, 35))); // bottom-right
-
- // Points outside the mask.
- EXPECT_FALSE(w1.HitTest(gfx::Point(0, 0)));
- EXPECT_FALSE(w1.HitTest(gfx::Point(60, 80)));
- EXPECT_FALSE(w1.HitTest(gfx::Point(4, 6)));
- EXPECT_FALSE(w1.HitTest(gfx::Point(5, 5)));
- EXPECT_FALSE(w1.HitTest(gfx::Point(25, 36)));
-}
-
TEST_F(WindowTest, GetEventHandlerForPoint) {
scoped_ptr<Window> w1(
CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
@@ -660,7 +603,7 @@ TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
AddedToRootWindowObserver child_observer;
scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
scoped_ptr<Window> child_window(new Window(NULL));
- child_window->Init(ui::LAYER_TEXTURED);
+ child_window->Init(aura::WINDOW_LAYER_TEXTURED);
child_window->Show();
parent_window->AddObserver(&parent_observer);
@@ -709,11 +652,11 @@ TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
// Make sure StackChildAtTop moves both the window and layer to the front.
TEST_F(WindowTest, StackChildAtTop) {
Window parent(NULL);
- parent.Init(ui::LAYER_NOT_DRAWN);
+ parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window child1(NULL);
- child1.Init(ui::LAYER_NOT_DRAWN);
+ child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window child2(NULL);
- child2.Init(ui::LAYER_NOT_DRAWN);
+ child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent.AddChild(&child1);
parent.AddChild(&child2);
@@ -736,15 +679,15 @@ TEST_F(WindowTest, StackChildAtTop) {
// Make sure StackChildBelow works.
TEST_F(WindowTest, StackChildBelow) {
Window parent(NULL);
- parent.Init(ui::LAYER_NOT_DRAWN);
+ parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window child1(NULL);
- child1.Init(ui::LAYER_NOT_DRAWN);
+ child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
child1.set_id(1);
Window child2(NULL);
- child2.Init(ui::LAYER_NOT_DRAWN);
+ child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
child2.set_id(2);
Window child3(NULL);
- child3.Init(ui::LAYER_NOT_DRAWN);
+ child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
child3.set_id(3);
parent.AddChild(&child1);
@@ -768,13 +711,13 @@ TEST_F(WindowTest, StackChildBelow) {
// Various assertions for StackChildAbove.
TEST_F(WindowTest, StackChildAbove) {
Window parent(NULL);
- parent.Init(ui::LAYER_NOT_DRAWN);
+ parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window child1(NULL);
- child1.Init(ui::LAYER_NOT_DRAWN);
+ child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window child2(NULL);
- child2.Init(ui::LAYER_NOT_DRAWN);
+ child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window child3(NULL);
- child3.Init(ui::LAYER_NOT_DRAWN);
+ child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent.AddChild(&child1);
parent.AddChild(&child2);
@@ -848,7 +791,7 @@ TEST_F(WindowTest, CaptureTests) {
ui::TouchEvent touchev(
ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev);
+ DispatchEventUsingWindowDispatcher(&touchev);
EXPECT_EQ(1, delegate.touch_event_count());
delegate.ResetCounts();
@@ -864,7 +807,7 @@ TEST_F(WindowTest, CaptureTests) {
ui::TouchEvent touchev2(
ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev2);
+ DispatchEventUsingWindowDispatcher(&touchev2);
EXPECT_EQ(0, delegate.touch_event_count());
// Removing the capture window from parent should reset the capture window
@@ -887,7 +830,7 @@ TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
// Press on w1.
ui::TouchEvent press(
ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
// We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
EXPECT_EQ(2, delegate1.gesture_event_count());
delegate1.ResetCounts();
@@ -901,7 +844,7 @@ TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
// Events now go to w2.
ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ DispatchEventUsingWindowDispatcher(&move);
EXPECT_EQ(0, delegate1.gesture_event_count());
EXPECT_EQ(0, delegate1.touch_event_count());
EXPECT_EQ(0, delegate2.gesture_event_count());
@@ -909,14 +852,14 @@ TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
ui::TouchEvent release(
ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_EQ(0, delegate1.gesture_event_count());
EXPECT_EQ(0, delegate2.gesture_event_count());
// A new press is captured by w2.
ui::TouchEvent press2(
ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
+ DispatchEventUsingWindowDispatcher(&press2);
EXPECT_EQ(0, delegate1.gesture_event_count());
// We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
EXPECT_EQ(2, delegate2.gesture_event_count());
@@ -938,7 +881,7 @@ TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
ui::TouchEvent press(
ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
// We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
EXPECT_EQ(2, delegate.gesture_event_count());
@@ -953,7 +896,7 @@ TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
// On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
// GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
+ DispatchEventUsingWindowDispatcher(&move);
EXPECT_EQ(1, delegate.touch_event_count());
EXPECT_EQ(3, delegate.gesture_event_count());
delegate.ResetCounts();
@@ -966,7 +909,7 @@ TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
// On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
+ DispatchEventUsingWindowDispatcher(&move2);
EXPECT_EQ(1, delegate.touch_event_count());
EXPECT_EQ(1, delegate.gesture_event_count());
delegate.ResetCounts();
@@ -974,7 +917,7 @@ TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
// And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
ui::TouchEvent release(
ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ DispatchEventUsingWindowDispatcher(&release);
EXPECT_EQ(1, delegate.touch_event_count());
EXPECT_EQ(2, delegate.gesture_event_count());
}
@@ -987,7 +930,7 @@ TEST_F(WindowTest, TransferCaptureTouchEvents) {
scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
&d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&p1);
+ DispatchEventUsingWindowDispatcher(&p1);
// We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
EXPECT_EQ(1, d1.touch_event_count());
EXPECT_EQ(2, d1.gesture_event_count());
@@ -998,7 +941,7 @@ TEST_F(WindowTest, TransferCaptureTouchEvents) {
scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
&d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&p2);
+ DispatchEventUsingWindowDispatcher(&p2);
EXPECT_EQ(0, d1.touch_event_count());
EXPECT_EQ(0, d1.gesture_event_count());
// We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
@@ -1034,7 +977,7 @@ TEST_F(WindowTest, TransferCaptureTouchEvents) {
// Move touch id originally associated with |w2|. Since capture was transfered
// from 2 to 3 only |w3| should get the event.
ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&m3);
+ DispatchEventUsingWindowDispatcher(&m3);
EXPECT_EQ(0, d1.touch_event_count());
EXPECT_EQ(0, d1.gesture_event_count());
EXPECT_EQ(0, d2.touch_event_count());
@@ -1057,7 +1000,7 @@ TEST_F(WindowTest, TransferCaptureTouchEvents) {
// And when we move the touch again, |w3| still gets the events.
ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&m4);
+ DispatchEventUsingWindowDispatcher(&m4);
EXPECT_EQ(0, d1.touch_event_count());
EXPECT_EQ(0, d1.gesture_event_count());
EXPECT_EQ(0, d2.touch_event_count());
@@ -1123,7 +1066,7 @@ TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
window.reset();
// Make sure the root window doesn't reference the window anymore.
- EXPECT_EQ(NULL, dispatcher()->mouse_pressed_handler());
+ EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler());
EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
}
@@ -1208,7 +1151,7 @@ TEST_F(WindowTest, MouseEnterExit) {
}
// Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
-TEST_F(WindowTest, RootWindowHostExit) {
+TEST_F(WindowTest, WindowTreeHostExit) {
MouseEnterExitWindowDelegate d1;
scoped_ptr<Window> w1(
CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
@@ -1221,8 +1164,8 @@ TEST_F(WindowTest, RootWindowHostExit) {
d1.ResetExpectations();
ui::MouseEvent exit_event(
- ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&exit_event);
+ ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0, 0);
+ DispatchEventUsingWindowDispatcher(&exit_event);
EXPECT_FALSE(d1.entered());
EXPECT_TRUE(d1.exited());
}
@@ -1298,21 +1241,23 @@ TEST_F(WindowTest, MouseEnterExitWithDelete) {
generator.MoveMouseToCenterOf(w1.get());
EXPECT_TRUE(d1.entered());
EXPECT_FALSE(d1.exited());
+ d1.ResetExpectations();
MouseEnterExitWindowDelegate d2;
{
scoped_ptr<Window> w2(
CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
root_window()));
- // Enters / exits can be send asynchronously.
+ // Enters / exits can be sent asynchronously.
RunAllPendingInMessageLoop();
- EXPECT_TRUE(d1.entered());
+ EXPECT_FALSE(d1.entered());
EXPECT_TRUE(d1.exited());
EXPECT_TRUE(d2.entered());
EXPECT_FALSE(d2.exited());
d1.ResetExpectations();
+ d2.ResetExpectations();
}
- // Enters / exits can be send asynchronously.
+ // Enters / exits can be sent asynchronously.
RunAllPendingInMessageLoop();
EXPECT_TRUE(d2.exited());
EXPECT_TRUE(d1.entered());
@@ -1538,7 +1483,7 @@ TEST_F(WindowTest, IgnoreEventsTest) {
// Tests transformation on the root window.
TEST_F(WindowTest, Transform) {
- gfx::Size size = dispatcher()->host()->GetBounds().size();
+ gfx::Size size = host()->GetBounds().size();
EXPECT_EQ(gfx::Rect(size),
gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
gfx::Point()).bounds());
@@ -1547,7 +1492,7 @@ TEST_F(WindowTest, Transform) {
gfx::Transform transform;
transform.Translate(size.height(), 0);
transform.Rotate(90.0);
- dispatcher()->SetTransform(transform);
+ host()->SetRootTransform(transform);
// The size should be the transformed size.
gfx::Size transformed_size(size.height(), size.width());
@@ -1559,12 +1504,11 @@ TEST_F(WindowTest, Transform) {
gfx::Point()).bounds().ToString());
// Host size shouldn't change.
- EXPECT_EQ(size.ToString(),
- dispatcher()->host()->GetBounds().size().ToString());
+ EXPECT_EQ(size.ToString(), host()->GetBounds().size().ToString());
}
TEST_F(WindowTest, TransformGesture) {
- gfx::Size size = dispatcher()->host()->GetBounds().size();
+ gfx::Size size = host()->GetBounds().size();
scoped_ptr<GestureTrackPositionDelegate> delegate(
new GestureTrackPositionDelegate);
@@ -1575,49 +1519,14 @@ TEST_F(WindowTest, TransformGesture) {
gfx::Transform transform;
transform.Translate(size.height(), 0.0);
transform.Rotate(90.0);
- dispatcher()->SetTransform(transform);
+ host()->SetRootTransform(transform);
ui::TouchEvent press(
ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ DispatchEventUsingWindowDispatcher(&press);
EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
}
-// Various assertions for transient children.
-TEST_F(WindowTest, TransientChildren) {
- scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
- scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get()));
- scoped_ptr<Window> w3(CreateTestWindowWithId(3, parent.get()));
- Window* w2 = CreateTestWindowWithId(2, parent.get());
- w1->AddTransientChild(w2); // w2 is now owned by w1.
- // Stack w1 at the top (end), this should force w2 to be last (on top of w1).
- parent->StackChildAtTop(w1.get());
- ASSERT_EQ(3u, parent->children().size());
- EXPECT_EQ(w2, parent->children().back());
-
- // Destroy w1, which should also destroy w3 (since it's a transient child).
- w1.reset();
- w2 = NULL;
- ASSERT_EQ(1u, parent->children().size());
- EXPECT_EQ(w3.get(), parent->children()[0]);
-
- w1.reset(CreateTestWindowWithId(4, parent.get()));
- w2 = CreateTestWindowWithId(5, w3.get());
- w1->AddTransientChild(w2);
- parent->StackChildAtTop(w3.get());
- // Stack w1 at the top (end), this shouldn't affect w2 since it has a
- // different parent.
- parent->StackChildAtTop(w1.get());
- ASSERT_EQ(2u, parent->children().size());
- EXPECT_EQ(w3.get(), parent->children()[0]);
- EXPECT_EQ(w1.get(), parent->children()[1]);
-
- // Hiding parent should hide transient children.
- EXPECT_TRUE(w2->IsVisible());
- w1->Hide();
- EXPECT_FALSE(w2->IsVisible());
-}
-
namespace {
DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
@@ -1717,7 +1626,7 @@ TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
EXPECT_FALSE(!w1->layer());
w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
- gfx::AnimationContainerElement* element = w1->layer()->GetAnimator();
+ ui::LayerAnimator* animator = w1->layer()->GetAnimator();
EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
@@ -1747,7 +1656,7 @@ TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
base::TimeTicks start_time =
w1->layer()->GetAnimator()->last_step_time();
- element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
+ animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
}
@@ -1971,6 +1880,12 @@ TEST_F(WindowTest, AcquireLayer) {
EXPECT_FALSE(window1_test_api.OwnsLayer());
EXPECT_TRUE(window1_layer.get() == window1->layer());
+ // The acquired layer's owner should be set NULL and re-acquring
+ // should return NULL.
+ EXPECT_FALSE(window1_layer->owner());
+ scoped_ptr<ui::Layer> window1_layer_reacquired(window1->AcquireLayer());
+ EXPECT_FALSE(window1_layer_reacquired.get());
+
// Upon destruction, window1's layer should still be valid, and in the layer
// hierarchy, but window2's should be gone, and no longer in the hierarchy.
window1.reset();
@@ -1987,11 +1902,10 @@ TEST_F(WindowTest, RecreateLayer) {
// Set properties to non default values.
Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
w.set_id(1);
- w.Init(ui::LAYER_SOLID_COLOR);
+ w.Init(aura::WINDOW_LAYER_SOLID_COLOR);
w.SetBounds(gfx::Rect(0, 0, 100, 100));
ui::Layer* layer = w.layer();
- layer->set_scale_content(false);
layer->SetVisible(false);
layer->SetMasksToBounds(true);
@@ -2001,10 +1915,11 @@ TEST_F(WindowTest, RecreateLayer) {
scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
layer = w.layer();
EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
- EXPECT_FALSE(layer->scale_content());
EXPECT_FALSE(layer->visible());
EXPECT_EQ(1u, layer->children().size());
EXPECT_TRUE(layer->GetMasksToBounds());
+ EXPECT_EQ("0,0 100x100", w.bounds().ToString());
+ EXPECT_EQ("0,0 100x100", layer->bounds().ToString());
}
// Verify that RecreateLayer() stacks the old layer above the newly creatd
@@ -2028,8 +1943,8 @@ TEST_F(WindowTest, AcquireThenRecreateLayer) {
scoped_ptr<Window> w(
CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
root_window()));
- scoped_ptr<ui::Layer>acquired_layer(w->AcquireLayer());
- scoped_ptr<ui::Layer>doubly_acquired_layer(w->RecreateLayer());
+ scoped_ptr<ui::Layer> acquired_layer(w->AcquireLayer());
+ scoped_ptr<ui::Layer> doubly_acquired_layer(w->RecreateLayer());
EXPECT_EQ(NULL, doubly_acquired_layer.get());
// Destroy window before layer gets destroyed.
@@ -2056,66 +1971,6 @@ TEST_F(WindowTest, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate) {
ui::test::ChildLayerNamesAsString(*root_window()->layer()));
}
-TEST_F(WindowTest, StackWindowsWhoseLayersHaveNoDelegate) {
- scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
- window1->layer()->set_name("1");
- scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
- window2->layer()->set_name("2");
- scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
- window3->layer()->set_name("3");
-
- // This brings |window1| (and its layer) to the front.
- root_window()->StackChildAbove(window1.get(), window3.get());
- EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window()));
- EXPECT_EQ("2 3 1",
- ui::test::ChildLayerNamesAsString(*root_window()->layer()));
-
- // Since |window1| does not have a delegate, |window2| should not move in
- // front of it, nor should its layer.
- window1->layer()->set_delegate(NULL);
- root_window()->StackChildAbove(window2.get(), window1.get());
- EXPECT_EQ("3 2 1", ChildWindowIDsAsString(root_window()));
- EXPECT_EQ("3 2 1",
- ui::test::ChildLayerNamesAsString(*root_window()->layer()));
-
- // It should still be possible to stack |window3| immediately below |window1|.
- root_window()->StackChildBelow(window3.get(), window1.get());
- EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window()));
- EXPECT_EQ("2 3 1",
- ui::test::ChildLayerNamesAsString(*root_window()->layer()));
-
- // Since neither |window3| nor |window1| have a delegate, |window2| should
- // not move in front of either.
- window3->layer()->set_delegate(NULL);
- root_window()->StackChildBelow(window2.get(), window1.get());
- EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window()));
- EXPECT_EQ("2 3 1",
- ui::test::ChildLayerNamesAsString(*root_window()->layer()));
-}
-
-TEST_F(WindowTest, StackTransientsWhoseLayersHaveNoDelegate) {
- // Create a window with several transients, then a couple windows on top.
- scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
- scoped_ptr<Window> window11(CreateTransientChild(11, window1.get()));
- scoped_ptr<Window> window12(CreateTransientChild(12, window1.get()));
- scoped_ptr<Window> window13(CreateTransientChild(13, window1.get()));
- scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
- scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
-
- EXPECT_EQ("1 11 12 13 2 3", ChildWindowIDsAsString(root_window()));
-
- // Remove the delegates of a couple of transients, as if they are closing
- // and animating out.
- window11->layer()->set_delegate(NULL);
- window13->layer()->set_delegate(NULL);
-
- // Move window1 to the front. All transients should move with it, and their
- // order should be preserved.
- root_window()->StackChildAtTop(window1.get());
-
- EXPECT_EQ("2 3 1 11 12 13", ChildWindowIDsAsString(root_window()));
-}
-
class TestVisibilityClient : public client::VisibilityClient {
public:
explicit TestVisibilityClient(Window* root_window)
@@ -2161,7 +2016,7 @@ TEST_F(WindowTest, VisibilityClientIsVisible) {
// Tests mouse events on window change.
TEST_F(WindowTest, MouseEventsOnWindowChange) {
- gfx::Size size = dispatcher()->host()->GetBounds().size();
+ gfx::Size size = host()->GetBounds().size();
EventGenerator generator(root_window());
generator.MoveMouseTo(50, 50);
@@ -2253,240 +2108,6 @@ TEST_F(WindowTest, MouseEventsOnWindowChange) {
EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
}
-class StackingMadrigalLayoutManager : public LayoutManager {
- public:
- explicit StackingMadrigalLayoutManager(Window* root_window)
- : root_window_(root_window) {
- root_window_->SetLayoutManager(this);
- }
- virtual ~StackingMadrigalLayoutManager() {
- }
-
- private:
- // Overridden from LayoutManager:
- virtual void OnWindowResized() OVERRIDE {}
- virtual void OnWindowAddedToLayout(Window* child) OVERRIDE {}
- virtual void OnWillRemoveWindowFromLayout(Window* child) OVERRIDE {}
- virtual void OnWindowRemovedFromLayout(Window* child) OVERRIDE {}
- virtual void OnChildWindowVisibilityChanged(Window* child,
- bool visible) OVERRIDE {
- Window::Windows::const_iterator it = root_window_->children().begin();
- Window* last_window = NULL;
- for (; it != root_window_->children().end(); ++it) {
- if (*it == child && last_window) {
- if (!visible)
- root_window_->StackChildAbove(last_window, *it);
- else
- root_window_->StackChildAbove(*it, last_window);
- break;
- }
- last_window = *it;
- }
- }
- virtual void SetChildBounds(Window* child,
- const gfx::Rect& requested_bounds) OVERRIDE {
- SetChildBoundsDirect(child, requested_bounds);
- }
-
- Window* root_window_;
-
- DISALLOW_COPY_AND_ASSIGN(StackingMadrigalLayoutManager);
-};
-
-class StackingMadrigalVisibilityClient : public client::VisibilityClient {
- public:
- explicit StackingMadrigalVisibilityClient(Window* root_window)
- : ignored_window_(NULL) {
- client::SetVisibilityClient(root_window, this);
- }
- virtual ~StackingMadrigalVisibilityClient() {
- }
-
- void set_ignored_window(Window* ignored_window) {
- ignored_window_ = ignored_window;
- }
-
- private:
- // Overridden from client::VisibilityClient:
- virtual void UpdateLayerVisibility(Window* window, bool visible) OVERRIDE {
- if (!visible) {
- if (window == ignored_window_)
- window->layer()->set_delegate(NULL);
- else
- window->layer()->SetVisible(visible);
- } else {
- window->layer()->SetVisible(visible);
- }
- }
-
- Window* ignored_window_;
-
- DISALLOW_COPY_AND_ASSIGN(StackingMadrigalVisibilityClient);
-};
-
-// This test attempts to reconstruct a circumstance that can happen when the
-// aura client attempts to manipulate the visibility and delegate of a layer
-// independent of window visibility.
-// A use case is where the client attempts to keep a window visible onscreen
-// even after code has called Hide() on the window. The use case for this would
-// be that window hides are animated (e.g. the window fades out). To prevent
-// spurious updating the client code may also clear window's layer's delegate,
-// so that the window cannot attempt to paint or update it further. The window
-// uses the presence of a NULL layer delegate as a signal in stacking to note
-// that the window is being manipulated by such a use case and its stacking
-// should not be adjusted.
-// One issue that can arise when a window opens two transient children, and the
-// first is hidden. Subsequent attempts to activate the transient parent can
-// result in the transient parent being stacked above the second transient
-// child. A fix is made to Window::StackAbove to prevent this, and this test
-// verifies this fix.
-TEST_F(WindowTest, StackingMadrigal) {
- new StackingMadrigalLayoutManager(root_window());
- StackingMadrigalVisibilityClient visibility_client(root_window());
-
- scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
- scoped_ptr<Window> window11(CreateTransientChild(11, window1.get()));
-
- visibility_client.set_ignored_window(window11.get());
-
- window11->Show();
- window11->Hide();
-
- // As a transient, window11 should still be stacked above window1, even when
- // hidden.
- EXPECT_TRUE(WindowIsAbove(window11.get(), window1.get()));
- EXPECT_TRUE(LayerIsAbove(window11.get(), window1.get()));
-
- // A new transient should still be above window1. It will appear behind
- // window11 because we don't stack windows on top of targets with NULL
- // delegates.
- scoped_ptr<Window> window12(CreateTransientChild(12, window1.get()));
- window12->Show();
-
- EXPECT_TRUE(WindowIsAbove(window12.get(), window1.get()));
- EXPECT_TRUE(LayerIsAbove(window12.get(), window1.get()));
-
- // In earlier versions of the StackChildAbove() method, attempting to stack
- // window1 above window12 at this point would actually restack the layers
- // resulting in window12's layer being below window1's layer (though the
- // windows themselves would still be correctly stacked, so events would pass
- // through.)
- root_window()->StackChildAbove(window1.get(), window12.get());
-
- // Both window12 and its layer should be stacked above window1.
- EXPECT_TRUE(WindowIsAbove(window12.get(), window1.get()));
- EXPECT_TRUE(LayerIsAbove(window12.get(), window1.get()));
-}
-
-// Test for an issue where attempting to stack a primary window on top of a
-// transient with a NULL layer delegate causes that primary window to be moved,
-// but the layer order not changed to match. http://crbug.com/112562
-TEST_F(WindowTest, StackOverClosingTransient) {
- scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
- scoped_ptr<Window> transient1(CreateTransientChild(11, window1.get()));
- scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
- scoped_ptr<Window> transient2(CreateTransientChild(21, window2.get()));
-
- // Both windows and layers are stacked in creation order.
- Window* root = root_window();
- ASSERT_EQ(4u, root->children().size());
- EXPECT_EQ(root->children()[0], window1.get());
- EXPECT_EQ(root->children()[1], transient1.get());
- EXPECT_EQ(root->children()[2], window2.get());
- EXPECT_EQ(root->children()[3], transient2.get());
- ASSERT_EQ(4u, root->layer()->children().size());
- EXPECT_EQ(root->layer()->children()[0], window1->layer());
- EXPECT_EQ(root->layer()->children()[1], transient1->layer());
- EXPECT_EQ(root->layer()->children()[2], window2->layer());
- EXPECT_EQ(root->layer()->children()[3], transient2->layer());
- EXPECT_EQ("1 11 2 21", ChildWindowIDsAsString(root_window()));
-
- // This brings window1 and its transient to the front.
- root->StackChildAtTop(window1.get());
- EXPECT_EQ("2 21 1 11", ChildWindowIDsAsString(root_window()));
-
- EXPECT_EQ(root->children()[0], window2.get());
- EXPECT_EQ(root->children()[1], transient2.get());
- EXPECT_EQ(root->children()[2], window1.get());
- EXPECT_EQ(root->children()[3], transient1.get());
- EXPECT_EQ(root->layer()->children()[0], window2->layer());
- EXPECT_EQ(root->layer()->children()[1], transient2->layer());
- EXPECT_EQ(root->layer()->children()[2], window1->layer());
- EXPECT_EQ(root->layer()->children()[3], transient1->layer());
-
- // Pretend we're closing the top-most transient, then bring window2 to the
- // front. This mimics activating a browser window while the status bubble
- // is fading out. The transient should stay topmost.
- transient1->layer()->set_delegate(NULL);
- root->StackChildAtTop(window2.get());
-
- EXPECT_EQ(root->children()[0], window1.get());
- EXPECT_EQ(root->children()[1], window2.get());
- EXPECT_EQ(root->children()[2], transient2.get());
- EXPECT_EQ(root->children()[3], transient1.get());
- EXPECT_EQ(root->layer()->children()[0], window1->layer());
- EXPECT_EQ(root->layer()->children()[1], window2->layer());
- EXPECT_EQ(root->layer()->children()[2], transient2->layer());
- EXPECT_EQ(root->layer()->children()[3], transient1->layer());
-
- // Close the transient. Remaining windows are stable.
- transient1.reset();
-
- ASSERT_EQ(3u, root->children().size());
- EXPECT_EQ(root->children()[0], window1.get());
- EXPECT_EQ(root->children()[1], window2.get());
- EXPECT_EQ(root->children()[2], transient2.get());
- ASSERT_EQ(3u, root->layer()->children().size());
- EXPECT_EQ(root->layer()->children()[0], window1->layer());
- EXPECT_EQ(root->layer()->children()[1], window2->layer());
- EXPECT_EQ(root->layer()->children()[2], transient2->layer());
-
- // Open another window on top.
- scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
-
- ASSERT_EQ(4u, root->children().size());
- EXPECT_EQ(root->children()[0], window1.get());
- EXPECT_EQ(root->children()[1], window2.get());
- EXPECT_EQ(root->children()[2], transient2.get());
- EXPECT_EQ(root->children()[3], window3.get());
- ASSERT_EQ(4u, root->layer()->children().size());
- EXPECT_EQ(root->layer()->children()[0], window1->layer());
- EXPECT_EQ(root->layer()->children()[1], window2->layer());
- EXPECT_EQ(root->layer()->children()[2], transient2->layer());
- EXPECT_EQ(root->layer()->children()[3], window3->layer());
-
- // Pretend we're closing the topmost non-transient window, then bring
- // window2 to the top. It should not move.
- window3->layer()->set_delegate(NULL);
- root->StackChildAtTop(window2.get());
-
- ASSERT_EQ(4u, root->children().size());
- EXPECT_EQ(root->children()[0], window1.get());
- EXPECT_EQ(root->children()[1], window2.get());
- EXPECT_EQ(root->children()[2], transient2.get());
- EXPECT_EQ(root->children()[3], window3.get());
- ASSERT_EQ(4u, root->layer()->children().size());
- EXPECT_EQ(root->layer()->children()[0], window1->layer());
- EXPECT_EQ(root->layer()->children()[1], window2->layer());
- EXPECT_EQ(root->layer()->children()[2], transient2->layer());
- EXPECT_EQ(root->layer()->children()[3], window3->layer());
-
- // Bring window1 to the top. It should move ahead of window2, but not
- // ahead of window3 (with NULL delegate).
- root->StackChildAtTop(window1.get());
-
- ASSERT_EQ(4u, root->children().size());
- EXPECT_EQ(root->children()[0], window2.get());
- EXPECT_EQ(root->children()[1], transient2.get());
- EXPECT_EQ(root->children()[2], window1.get());
- EXPECT_EQ(root->children()[3], window3.get());
- ASSERT_EQ(4u, root->layer()->children().size());
- EXPECT_EQ(root->layer()->children()[0], window2->layer());
- EXPECT_EQ(root->layer()->children()[1], transient2->layer());
- EXPECT_EQ(root->layer()->children()[2], window1->layer());
- EXPECT_EQ(root->layer()->children()[3], window3->layer());
-}
-
class RootWindowAttachmentObserver : public WindowObserver {
public:
RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
@@ -2504,7 +2125,8 @@ class RootWindowAttachmentObserver : public WindowObserver {
virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
++added_count_;
}
- virtual void OnWindowRemovingFromRootWindow(Window* window) OVERRIDE {
+ virtual void OnWindowRemovingFromRootWindow(Window* window,
+ Window* new_root) OVERRIDE {
++removed_count_;
}
@@ -2520,7 +2142,7 @@ TEST_F(WindowTest, RootWindowAttachment) {
// Test a direct add/remove from the RootWindow.
scoped_ptr<Window> w1(new Window(NULL));
- w1->Init(ui::LAYER_NOT_DRAWN);
+ w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
w1->AddObserver(&observer);
ParentWindow(w1.get());
@@ -2535,9 +2157,9 @@ TEST_F(WindowTest, RootWindowAttachment) {
// Test an indirect add/remove from the RootWindow.
w1.reset(new Window(NULL));
- w1->Init(ui::LAYER_NOT_DRAWN);
+ w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
Window* w11 = new Window(NULL);
- w11->Init(ui::LAYER_NOT_DRAWN);
+ w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
w11->AddObserver(&observer);
w1->AddChild(w11);
EXPECT_EQ(0, observer.added_count());
@@ -2556,13 +2178,13 @@ TEST_F(WindowTest, RootWindowAttachment) {
// Test an indirect add/remove with nested observers.
w1.reset(new Window(NULL));
- w1->Init(ui::LAYER_NOT_DRAWN);
+ w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
w11 = new Window(NULL);
- w11->Init(ui::LAYER_NOT_DRAWN);
+ w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
w11->AddObserver(&observer);
w1->AddChild(w11);
Window* w111 = new Window(NULL);
- w111->Init(ui::LAYER_NOT_DRAWN);
+ w111->Init(aura::WINDOW_LAYER_NOT_DRAWN);
w111->AddObserver(&observer);
w11->AddChild(w111);
@@ -2580,15 +2202,71 @@ TEST_F(WindowTest, RootWindowAttachment) {
EXPECT_EQ(2, observer.removed_count());
}
+class BoundsChangedWindowObserver : public WindowObserver {
+ public:
+ BoundsChangedWindowObserver() : root_set_(false) {}
+
+ virtual void OnWindowBoundsChanged(Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) OVERRIDE {
+ root_set_ = window->GetRootWindow() != NULL;
+ }
+
+ bool root_set() const { return root_set_; }
+
+ private:
+ bool root_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver);
+};
+
+TEST_F(WindowTest, RootWindowSetWhenReparenting) {
+ Window parent1(NULL);
+ parent1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
+ Window parent2(NULL);
+ parent2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
+ ParentWindow(&parent1);
+ ParentWindow(&parent2);
+ parent1.SetBounds(gfx::Rect(10, 10, 300, 300));
+ parent2.SetBounds(gfx::Rect(20, 20, 300, 300));
+
+ BoundsChangedWindowObserver observer;
+ Window child(NULL);
+ child.Init(aura::WINDOW_LAYER_NOT_DRAWN);
+ child.SetBounds(gfx::Rect(5, 5, 100, 100));
+ parent1.AddChild(&child);
+
+ // We need animations to start in order to observe the bounds changes.
+ ui::ScopedAnimationDurationScaleMode animation_duration_mode(
+ ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+ ui::ScopedLayerAnimationSettings settings1(child.layer()->GetAnimator());
+ settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
+ gfx::Rect new_bounds(gfx::Rect(35, 35, 50, 50));
+ child.SetBounds(new_bounds);
+
+ child.AddObserver(&observer);
+
+ // Reparenting the |child| will cause it to get moved. During this move
+ // the window should still have root window set.
+ parent2.AddChild(&child);
+ EXPECT_TRUE(observer.root_set());
+
+ // Animations should stop and the bounds should be as set before the |child|
+ // got reparented.
+ EXPECT_EQ(new_bounds.ToString(), child.GetTargetBounds().ToString());
+ EXPECT_EQ(new_bounds.ToString(), child.bounds().ToString());
+ EXPECT_EQ("55,55 50x50", child.GetBoundsInRootWindow().ToString());
+}
+
TEST_F(WindowTest, OwnedByParentFalse) {
// By default, a window is owned by its parent. If this is set to false, the
// window will not be destroyed when its parent is.
scoped_ptr<Window> w1(new Window(NULL));
- w1->Init(ui::LAYER_NOT_DRAWN);
+ w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
scoped_ptr<Window> w2(new Window(NULL));
w2->set_owned_by_parent(false);
- w2->Init(ui::LAYER_NOT_DRAWN);
+ w2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
w1->AddChild(w2.get());
w1.reset();
@@ -2609,7 +2287,7 @@ class OwningWindowDelegate : public TestWindowDelegate {
owned_window_.reset(window);
}
- virtual void OnWindowDestroyed() OVERRIDE {
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE {
owned_window_.reset(NULL);
}
@@ -2628,13 +2306,13 @@ class OwningWindowDelegate : public TestWindowDelegate {
// bubble.
TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
scoped_ptr<Window> parent(new Window(NULL));
- parent->Init(ui::LAYER_NOT_DRAWN);
+ parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
OwningWindowDelegate delegate;
Window* c1 = new Window(&delegate);
- c1->Init(ui::LAYER_NOT_DRAWN);
+ c1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent->AddChild(c1);
Window* c2 = new Window(NULL);
- c2->Init(ui::LAYER_NOT_DRAWN);
+ c2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent->AddChild(c2);
delegate.SetOwnedWindow(c2);
parent.reset();
@@ -2697,8 +2375,8 @@ TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
// Animate to the end, which should notify of the change.
base::TimeTicks start_time =
window->layer()->GetAnimator()->last_step_time();
- gfx::AnimationContainerElement* element = window->layer()->GetAnimator();
- element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
+ ui::LayerAnimator* animator = window->layer()->GetAnimator();
+ animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
EXPECT_TRUE(delegate.bounds_changed());
EXPECT_NE("0,0 100x100", window->bounds().ToString());
}
@@ -2739,8 +2417,8 @@ TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
// Animate to the end: will *not* notify of the change since we are hidden.
base::TimeTicks start_time =
window->layer()->GetAnimator()->last_step_time();
- gfx::AnimationContainerElement* element = window->layer()->GetAnimator();
- element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
+ ui::LayerAnimator* animator = window->layer()->GetAnimator();
+ animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
// No bounds changed notification at the end of animation since layer
// delegate is NULL.
@@ -2766,7 +2444,8 @@ class AddChildNotificationsObserver : public WindowObserver {
virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
added_count_++;
}
- virtual void OnWindowRemovingFromRootWindow(Window* window) OVERRIDE {
+ virtual void OnWindowRemovingFromRootWindow(Window* window,
+ Window* new_root) OVERRIDE {
removed_count_++;
}
@@ -3007,59 +2686,15 @@ TEST_F(WindowTest, OnWindowHierarchyChange) {
}
-namespace {
-
-// Used by NotifyDelegateAfterDeletingTransients. Adds a string to a vector when
-// OnWindowDestroyed() is invoked so that destruction order can be verified.
-class DestroyedTrackingDelegate : public TestWindowDelegate {
- public:
- explicit DestroyedTrackingDelegate(const std::string& name,
- std::vector<std::string>* results)
- : name_(name),
- results_(results) {}
-
- virtual void OnWindowDestroyed() OVERRIDE {
- results_->push_back(name_);
- }
-
- private:
- const std::string name_;
- std::vector<std::string>* results_;
-
- DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingDelegate);
-};
-
-} // namespace
-
-// Verifies the delegate is notified of destruction after transients are
-// destroyed.
-TEST_F(WindowTest, NotifyDelegateAfterDeletingTransients) {
- std::vector<std::string> destruction_order;
-
- DestroyedTrackingDelegate parent_delegate("parent", &destruction_order);
- scoped_ptr<Window> parent(new Window(&parent_delegate));
- parent->Init(ui::LAYER_NOT_DRAWN);
-
- DestroyedTrackingDelegate transient_delegate("transient", &destruction_order);
- Window* transient = new Window(&transient_delegate); // Owned by |parent|.
- transient->Init(ui::LAYER_NOT_DRAWN);
- parent->AddTransientChild(transient);
- parent.reset();
-
- ASSERT_EQ(2u, destruction_order.size());
- EXPECT_EQ("transient", destruction_order[0]);
- EXPECT_EQ("parent", destruction_order[1]);
-}
-
// Verifies SchedulePaint() on a layerless window results in damaging the right
// thing.
TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
Window root(NULL);
- root.Init(ui::LAYER_NOT_DRAWN);
+ root.Init(aura::WINDOW_LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
Window* layerless_window = new Window(NULL); // Owned by |root|.
- layerless_window->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ layerless_window->Init(WINDOW_LAYER_NONE);
layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13));
root.AddChild(layerless_window);
@@ -3071,7 +2706,7 @@ TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
ToString());
Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|.
- layerless_window2->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ layerless_window2->Init(WINDOW_LAYER_NONE);
layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4));
layerless_window->AddChild(layerless_window2);
@@ -3097,30 +2732,30 @@ TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) {
//
// ll: layer less, eg no layer
Window root(NULL);
- root.InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ root.Init(WINDOW_LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
Window* w1ll = new Window(NULL);
- w1ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ w1ll->Init(WINDOW_LAYER_NONE);
w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
Window* w11ll = new Window(NULL);
- w11ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ w11ll->Init(WINDOW_LAYER_NONE);
w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
w1ll->AddChild(w11ll);
Window* w111 = new Window(NULL);
- w111->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w111->Init(WINDOW_LAYER_NOT_DRAWN);
w111->SetBounds(gfx::Rect(5, 6, 100, 100));
w11ll->AddChild(w111);
Window* w12 = new Window(NULL);
- w12->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w12->Init(WINDOW_LAYER_NOT_DRAWN);
w12->SetBounds(gfx::Rect(7, 8, 100, 100));
w1ll->AddChild(w12);
Window* w121 = new Window(NULL);
- w121->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w121->Init(WINDOW_LAYER_NOT_DRAWN);
w121->SetBounds(gfx::Rect(9, 10, 100, 100));
w12->AddChild(w121);
@@ -3177,30 +2812,30 @@ TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) {
//
// ll: layer less, eg no layer
Window root(NULL);
- root.InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ root.Init(WINDOW_LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
Window* w1ll = new Window(NULL);
- w1ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ w1ll->Init(WINDOW_LAYER_NONE);
w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
Window* w11ll = new Window(NULL);
- w11ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ w11ll->Init(WINDOW_LAYER_NONE);
w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
w1ll->AddChild(w11ll);
Window* w111 = new Window(NULL);
- w111->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w111->Init(WINDOW_LAYER_NOT_DRAWN);
w111->SetBounds(gfx::Rect(5, 6, 100, 100));
w11ll->AddChild(w111);
Window* w12 = new Window(NULL);
- w12->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w12->Init(WINDOW_LAYER_NOT_DRAWN);
w12->SetBounds(gfx::Rect(7, 8, 100, 100));
w1ll->AddChild(w12);
Window* w121 = new Window(NULL);
- w121->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w121->Init(WINDOW_LAYER_NOT_DRAWN);
w121->SetBounds(gfx::Rect(9, 10, 100, 100));
w12->AddChild(w121);
@@ -3291,23 +2926,23 @@ TEST_F(WindowTest, PaintLayerless) {
PaintWindowDelegate w111_delegate;
Window root(NULL);
- root.InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ root.Init(WINDOW_LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
Window* w1ll = new Window(&w1ll_delegate);
- w1ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ w1ll->Init(WINDOW_LAYER_NONE);
w1ll->SetBounds(gfx::Rect(1, 2, 40, 50));
w1ll->Show();
root.AddChild(w1ll);
Window* w11ll = new Window(&w11ll_delegate);
- w11ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ w11ll->Init(WINDOW_LAYER_NONE);
w11ll->SetBounds(gfx::Rect(3, 4, 11, 12));
w11ll->Show();
w1ll->AddChild(w11ll);
Window* w111 = new Window(&w111_delegate);
- w111->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w111->Init(WINDOW_LAYER_NOT_DRAWN);
w111->SetBounds(gfx::Rect(5, 6, 100, 100));
w111->Show();
w11ll->AddChild(w111);
@@ -3359,30 +2994,30 @@ TEST_F(WindowTest, ConvertPointToTargetLayerless) {
//
// ll: layer less, eg no layer
Window root(NULL);
- root.InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ root.Init(WINDOW_LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
Window* w1ll = new Window(NULL);
- w1ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ w1ll->Init(WINDOW_LAYER_NONE);
w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
Window* w11ll = new Window(NULL);
- w11ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ w11ll->Init(WINDOW_LAYER_NONE);
w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
w1ll->AddChild(w11ll);
Window* w111 = new Window(NULL);
- w111->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w111->Init(WINDOW_LAYER_NOT_DRAWN);
w111->SetBounds(gfx::Rect(5, 6, 100, 100));
w11ll->AddChild(w111);
Window* w12 = new Window(NULL);
- w12->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w12->Init(WINDOW_LAYER_NOT_DRAWN);
w12->SetBounds(gfx::Rect(7, 8, 100, 100));
w1ll->AddChild(w12);
Window* w121 = new Window(NULL);
- w121->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ w121->Init(WINDOW_LAYER_NOT_DRAWN);
w121->SetBounds(gfx::Rect(9, 10, 100, 100));
w12->AddChild(w121);
@@ -3420,7 +3055,7 @@ TEST_F(WindowTest, ConvertPointToTargetLayerless) {
// Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
TEST_F(WindowTest, PrintWindowHierarchyNotCrashLayerless) {
Window root(NULL);
- root.InitWithWindowLayerType(WINDOW_LAYER_NONE);
+ root.Init(WINDOW_LAYER_NONE);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
root.PrintWindowHierarchy(0);
}
@@ -3446,7 +3081,7 @@ aura::Window* CreateWindowFromDescription(const std::string& description,
<< description;
}
Window* window = new Window(delegate);
- window->InitWithWindowLayerType(window_type);
+ window->Init(window_type);
window->SetName(name);
// Window name is only propagated to layer in debug builds.
if (window->layer())
@@ -3676,7 +3311,7 @@ TEST_F(WindowTest, StackChildAtLayerless) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
test::TestWindowDelegate delegate;
Window root(NULL);
- root.InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
+ root.Init(WINDOW_LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
AddWindowsFromString(
&root,
@@ -3713,5 +3348,95 @@ TEST_F(WindowTest, StackChildAtLayerless) {
}
}
+namespace {
+
+class TestLayerAnimationObserver : public ui::LayerAnimationObserver {
+ public:
+ TestLayerAnimationObserver()
+ : animation_completed_(false),
+ animation_aborted_(false) {}
+ virtual ~TestLayerAnimationObserver() {}
+
+ bool animation_completed() const { return animation_completed_; }
+ bool animation_aborted() const { return animation_aborted_; }
+
+ void Reset() {
+ animation_completed_ = false;
+ animation_aborted_ = false;
+ }
+
+ private:
+ // ui::LayerAnimationObserver:
+ virtual void OnLayerAnimationEnded(
+ ui::LayerAnimationSequence* sequence) OVERRIDE {
+ animation_completed_ = true;
+ }
+
+ virtual void OnLayerAnimationAborted(
+ ui::LayerAnimationSequence* sequence) OVERRIDE {
+ animation_aborted_ = true;
+ }
+
+ virtual void OnLayerAnimationScheduled(
+ ui::LayerAnimationSequence* sequence) OVERRIDE {
+ }
+
+ bool animation_completed_;
+ bool animation_aborted_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver);
+};
+
+}
+
+TEST_F(WindowTest, WindowDestroyCompletesAnimations) {
+ ui::ScopedAnimationDurationScaleMode normal_duration_mode(
+ ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+ scoped_refptr<ui::LayerAnimator> animator =
+ ui::LayerAnimator::CreateImplicitAnimator();
+ TestLayerAnimationObserver observer;
+ animator->AddObserver(&observer);
+ // Make sure destroying a Window completes the animation.
+ {
+ scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
+ window->layer()->SetAnimator(animator);
+
+ gfx::Transform transform;
+ transform.Scale(0.5f, 0.5f);
+ window->SetTransform(transform);
+
+ EXPECT_TRUE(animator->is_animating());
+ EXPECT_FALSE(observer.animation_completed());
+ }
+ EXPECT_TRUE(animator);
+ EXPECT_FALSE(animator->is_animating());
+ EXPECT_TRUE(observer.animation_completed());
+ EXPECT_FALSE(observer.animation_aborted());
+ animator->RemoveObserver(&observer);
+ observer.Reset();
+
+ animator = ui::LayerAnimator::CreateImplicitAnimator();
+ animator->AddObserver(&observer);
+ ui::Layer layer;
+ layer.SetAnimator(animator);
+ {
+ scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
+ window->layer()->Add(&layer);
+
+ gfx::Transform transform;
+ transform.Scale(0.5f, 0.5f);
+ layer.SetTransform(transform);
+
+ EXPECT_TRUE(animator->is_animating());
+ EXPECT_FALSE(observer.animation_completed());
+ }
+
+ EXPECT_TRUE(animator);
+ EXPECT_FALSE(animator->is_animating());
+ EXPECT_TRUE(observer.animation_completed());
+ EXPECT_FALSE(observer.animation_aborted());
+ animator->RemoveObserver(&observer);
+}
+
} // namespace test
} // namespace aura