1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/wm/core/compound_event_filter.h"
7 #include "ui/aura/client/cursor_client.h"
8 #include "ui/aura/env.h"
9 #include "ui/aura/test/aura_test_base.h"
10 #include "ui/aura/test/test_cursor_client.h"
11 #include "ui/aura/test/test_windows.h"
12 #include "ui/aura/window.h"
13 #include "ui/aura/window_event_dispatcher.h"
14 #include "ui/events/event.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/events/test/event_generator.h"
17 #include "ui/wm/core/default_activation_client.h"
18 #include "ui/wm/public/activation_client.h"
22 #if defined(OS_CHROMEOS) || defined(OS_WIN)
23 base::TimeDelta GetTime() {
24 return ui::EventTimeForNow();
26 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
34 // An event filter that consumes all gesture events.
35 class ConsumeGestureEventFilter : public ui::EventHandler {
37 ConsumeGestureEventFilter() {}
38 virtual ~ConsumeGestureEventFilter() {}
41 // Overridden from ui::EventHandler:
42 virtual void OnGestureEvent(ui::GestureEvent* e) OVERRIDE {
46 DISALLOW_COPY_AND_ASSIGN(ConsumeGestureEventFilter);
51 typedef aura::test::AuraTestBase CompoundEventFilterTest;
53 #if defined(OS_CHROMEOS)
54 // A keypress only hides the cursor on ChromeOS (crbug.com/304296).
55 TEST_F(CompoundEventFilterTest, CursorVisibilityChange) {
56 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
57 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
58 aura::test::TestWindowDelegate delegate;
59 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
60 gfx::Rect(5, 5, 100, 100), root_window()));
64 aura::test::TestCursorClient cursor_client(root_window());
66 // Send key event to hide the cursor.
67 ui::KeyEvent key('a', ui::VKEY_A, ui::EF_NONE);
68 DispatchEventUsingWindowDispatcher(&key);
69 EXPECT_FALSE(cursor_client.IsCursorVisible());
71 // Synthesized mouse event should not show the cursor.
72 ui::MouseEvent enter(ui::ET_MOUSE_ENTERED, gfx::Point(10, 10),
73 gfx::Point(10, 10), 0, 0);
74 enter.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
75 DispatchEventUsingWindowDispatcher(&enter);
76 EXPECT_FALSE(cursor_client.IsCursorVisible());
78 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
79 gfx::Point(10, 10), 0, 0);
80 move.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
81 DispatchEventUsingWindowDispatcher(&move);
82 EXPECT_FALSE(cursor_client.IsCursorVisible());
84 // A real mouse event should show the cursor.
85 ui::MouseEvent real_move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
86 gfx::Point(10, 10), 0, 0);
87 DispatchEventUsingWindowDispatcher(&real_move);
88 EXPECT_TRUE(cursor_client.IsCursorVisible());
90 // Disallow hiding the cursor on keypress.
91 cursor_client.set_should_hide_cursor_on_key_event(false);
92 key = ui::KeyEvent('a', ui::VKEY_A, ui::EF_NONE);
93 DispatchEventUsingWindowDispatcher(&key);
94 EXPECT_TRUE(cursor_client.IsCursorVisible());
96 // Allow hiding the cursor on keypress.
97 cursor_client.set_should_hide_cursor_on_key_event(true);
98 key = ui::KeyEvent('a', ui::VKEY_A, ui::EF_NONE);
99 DispatchEventUsingWindowDispatcher(&key);
100 EXPECT_FALSE(cursor_client.IsCursorVisible());
102 // Mouse synthesized exit event should not show the cursor.
103 ui::MouseEvent exit(ui::ET_MOUSE_EXITED, gfx::Point(10, 10),
104 gfx::Point(10, 10), 0, 0);
105 exit.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
106 DispatchEventUsingWindowDispatcher(&exit);
107 EXPECT_FALSE(cursor_client.IsCursorVisible());
109 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
111 #endif // defined(OS_CHROMEOS)
113 #if defined(OS_CHROMEOS) || defined(OS_WIN)
114 // Touch visually hides the cursor on ChromeOS and Windows.
115 TEST_F(CompoundEventFilterTest, TouchHidesCursor) {
116 new wm::DefaultActivationClient(root_window());
117 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
118 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
119 aura::test::TestWindowDelegate delegate;
120 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
121 gfx::Rect(5, 5, 100, 100), root_window()));
123 window->SetCapture();
125 aura::test::TestCursorClient cursor_client(root_window());
127 ui::MouseEvent mouse0(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
128 gfx::Point(10, 10), 0, 0);
129 DispatchEventUsingWindowDispatcher(&mouse0);
130 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
132 // This press is required for the GestureRecognizer to associate a target
134 ui::TouchEvent press0(
135 ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime());
136 DispatchEventUsingWindowDispatcher(&press0);
137 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
139 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 10), 1, GetTime());
140 DispatchEventUsingWindowDispatcher(&move);
141 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
143 ui::TouchEvent release(
144 ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), 1, GetTime());
145 DispatchEventUsingWindowDispatcher(&release);
146 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
148 ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
149 gfx::Point(10, 10), 0, 0);
150 // Move the cursor again. The cursor should be visible.
151 DispatchEventUsingWindowDispatcher(&mouse1);
152 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
154 // Now activate the window and press on it again.
155 ui::TouchEvent press1(
156 ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime());
157 aura::client::GetActivationClient(
158 root_window())->ActivateWindow(window.get());
159 DispatchEventUsingWindowDispatcher(&press1);
160 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
161 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
163 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
165 // Tests that if an event filter consumes a gesture, then it doesn't focus the
167 TEST_F(CompoundEventFilterTest, FilterConsumedGesture) {
168 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
169 scoped_ptr<ui::EventHandler> gesure_handler(new ConsumeGestureEventFilter);
170 compound_filter->AddHandler(gesure_handler.get());
171 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
172 aura::test::TestWindowDelegate delegate;
173 DCHECK(root_window());
174 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
175 gfx::Rect(5, 5, 100, 100), root_window()));
178 EXPECT_TRUE(window->CanFocus());
179 EXPECT_FALSE(window->HasFocus());
181 // Tap on the window should not focus it since the filter will be consuming
183 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
184 generator.PressTouch();
185 EXPECT_FALSE(window->HasFocus());
187 compound_filter->RemoveHandler(gesure_handler.get());
188 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
191 // Verifies we don't attempt to hide the mouse when the mouse is down and a
192 // touch event comes in.
193 TEST_F(CompoundEventFilterTest, DontHideWhenMouseDown) {
194 ui::test::EventGenerator event_generator(root_window());
196 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
197 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
198 aura::test::TestWindowDelegate delegate;
199 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
200 gfx::Rect(5, 5, 100, 100), root_window()));
203 aura::test::TestCursorClient cursor_client(root_window());
205 // Move and press the mouse over the window.
206 event_generator.MoveMouseTo(10, 10);
207 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
208 event_generator.PressLeftButton();
209 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
210 EXPECT_TRUE(aura::Env::GetInstance()->IsMouseButtonDown());
212 // Do a touch event. As the mouse button is down this should not disable mouse
214 event_generator.PressTouch();
215 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
216 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
220 // Windows synthesizes mouse messages for touch events. We should not be
221 // showing the cursor when we receive such messages.
222 TEST_F(CompoundEventFilterTest, DontShowCursorOnMouseMovesFromTouch) {
223 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
224 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
225 aura::test::TestWindowDelegate delegate;
226 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
227 gfx::Rect(5, 5, 100, 100), root_window()));
229 window->SetCapture();
231 aura::test::TestCursorClient cursor_client(root_window());
232 cursor_client.DisableMouseEvents();
233 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
235 ui::MouseEvent mouse0(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
236 gfx::Point(10, 10), 0, 0);
237 mouse0.set_flags(mouse0.flags() | ui::EF_FROM_TOUCH);
239 DispatchEventUsingWindowDispatcher(&mouse0);
240 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
242 mouse0.set_flags(mouse0.flags() & ~ui::EF_FROM_TOUCH);
243 DispatchEventUsingWindowDispatcher(&mouse0);
244 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
246 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());