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 ~ConsumeGestureEventFilter() override {}
41 // Overridden from ui::EventHandler:
42 void OnGestureEvent(ui::GestureEvent* e) override { e->StopPropagation(); }
44 DISALLOW_COPY_AND_ASSIGN(ConsumeGestureEventFilter);
49 typedef aura::test::AuraTestBase CompoundEventFilterTest;
51 #if defined(OS_CHROMEOS)
52 // A keypress only hides the cursor on ChromeOS (crbug.com/304296).
53 TEST_F(CompoundEventFilterTest, CursorVisibilityChange) {
54 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
55 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
56 aura::test::TestWindowDelegate delegate;
57 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
58 gfx::Rect(5, 5, 100, 100), root_window()));
62 aura::test::TestCursorClient cursor_client(root_window());
64 // Send key event to hide the cursor.
65 ui::KeyEvent key('a', ui::VKEY_A, ui::EF_NONE);
66 DispatchEventUsingWindowDispatcher(&key);
67 EXPECT_FALSE(cursor_client.IsCursorVisible());
69 // Synthesized mouse event should not show the cursor.
70 ui::MouseEvent enter(ui::ET_MOUSE_ENTERED, gfx::Point(10, 10),
71 gfx::Point(10, 10), 0, 0);
72 enter.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
73 DispatchEventUsingWindowDispatcher(&enter);
74 EXPECT_FALSE(cursor_client.IsCursorVisible());
76 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
77 gfx::Point(10, 10), 0, 0);
78 move.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
79 DispatchEventUsingWindowDispatcher(&move);
80 EXPECT_FALSE(cursor_client.IsCursorVisible());
82 // A real mouse event should show the cursor.
83 ui::MouseEvent real_move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
84 gfx::Point(10, 10), 0, 0);
85 DispatchEventUsingWindowDispatcher(&real_move);
86 EXPECT_TRUE(cursor_client.IsCursorVisible());
88 // Disallow hiding the cursor on keypress.
89 cursor_client.set_should_hide_cursor_on_key_event(false);
90 key = ui::KeyEvent('a', ui::VKEY_A, ui::EF_NONE);
91 DispatchEventUsingWindowDispatcher(&key);
92 EXPECT_TRUE(cursor_client.IsCursorVisible());
94 // Allow hiding the cursor on keypress.
95 cursor_client.set_should_hide_cursor_on_key_event(true);
96 key = ui::KeyEvent('a', ui::VKEY_A, ui::EF_NONE);
97 DispatchEventUsingWindowDispatcher(&key);
98 EXPECT_FALSE(cursor_client.IsCursorVisible());
100 // Mouse synthesized exit event should not show the cursor.
101 ui::MouseEvent exit(ui::ET_MOUSE_EXITED, gfx::Point(10, 10),
102 gfx::Point(10, 10), 0, 0);
103 exit.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
104 DispatchEventUsingWindowDispatcher(&exit);
105 EXPECT_FALSE(cursor_client.IsCursorVisible());
107 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
109 #endif // defined(OS_CHROMEOS)
111 #if defined(OS_CHROMEOS) || defined(OS_WIN)
112 // Touch visually hides the cursor on ChromeOS and Windows.
113 TEST_F(CompoundEventFilterTest, TouchHidesCursor) {
114 new wm::DefaultActivationClient(root_window());
115 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
116 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
117 aura::test::TestWindowDelegate delegate;
118 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
119 gfx::Rect(5, 5, 100, 100), root_window()));
121 window->SetCapture();
123 aura::test::TestCursorClient cursor_client(root_window());
125 ui::MouseEvent mouse0(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
126 gfx::Point(10, 10), 0, 0);
127 DispatchEventUsingWindowDispatcher(&mouse0);
128 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
130 // This press is required for the GestureRecognizer to associate a target
132 ui::TouchEvent press0(
133 ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime());
134 DispatchEventUsingWindowDispatcher(&press0);
135 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
137 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 10), 1, GetTime());
138 DispatchEventUsingWindowDispatcher(&move);
139 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
141 ui::TouchEvent release(
142 ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), 1, GetTime());
143 DispatchEventUsingWindowDispatcher(&release);
144 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
146 ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
147 gfx::Point(10, 10), 0, 0);
148 // Move the cursor again. The cursor should be visible.
149 DispatchEventUsingWindowDispatcher(&mouse1);
150 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
152 // Now activate the window and press on it again.
153 ui::TouchEvent press1(
154 ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime());
155 aura::client::GetActivationClient(
156 root_window())->ActivateWindow(window.get());
157 DispatchEventUsingWindowDispatcher(&press1);
158 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
159 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
161 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
163 // Tests that if an event filter consumes a gesture, then it doesn't focus the
165 TEST_F(CompoundEventFilterTest, FilterConsumedGesture) {
166 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
167 scoped_ptr<ui::EventHandler> gesure_handler(new ConsumeGestureEventFilter);
168 compound_filter->AddHandler(gesure_handler.get());
169 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
170 aura::test::TestWindowDelegate delegate;
171 DCHECK(root_window());
172 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
173 gfx::Rect(5, 5, 100, 100), root_window()));
176 EXPECT_TRUE(window->CanFocus());
177 EXPECT_FALSE(window->HasFocus());
179 // Tap on the window should not focus it since the filter will be consuming
181 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
182 generator.PressTouch();
183 EXPECT_FALSE(window->HasFocus());
185 compound_filter->RemoveHandler(gesure_handler.get());
186 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
189 // Verifies we don't attempt to hide the mouse when the mouse is down and a
190 // touch event comes in.
191 TEST_F(CompoundEventFilterTest, DontHideWhenMouseDown) {
192 ui::test::EventGenerator event_generator(root_window());
194 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
195 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
196 aura::test::TestWindowDelegate delegate;
197 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
198 gfx::Rect(5, 5, 100, 100), root_window()));
201 aura::test::TestCursorClient cursor_client(root_window());
203 // Move and press the mouse over the window.
204 event_generator.MoveMouseTo(10, 10);
205 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
206 event_generator.PressLeftButton();
207 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
208 EXPECT_TRUE(aura::Env::GetInstance()->IsMouseButtonDown());
210 // Do a touch event. As the mouse button is down this should not disable mouse
212 event_generator.PressTouch();
213 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
214 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
218 // Windows synthesizes mouse messages for touch events. We should not be
219 // showing the cursor when we receive such messages.
220 TEST_F(CompoundEventFilterTest, DontShowCursorOnMouseMovesFromTouch) {
221 scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
222 aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
223 aura::test::TestWindowDelegate delegate;
224 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
225 gfx::Rect(5, 5, 100, 100), root_window()));
227 window->SetCapture();
229 aura::test::TestCursorClient cursor_client(root_window());
230 cursor_client.DisableMouseEvents();
231 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
233 ui::MouseEvent mouse0(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
234 gfx::Point(10, 10), 0, 0);
235 mouse0.set_flags(mouse0.flags() | ui::EF_FROM_TOUCH);
237 DispatchEventUsingWindowDispatcher(&mouse0);
238 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
240 mouse0.set_flags(mouse0.flags() & ~ui::EF_FROM_TOUCH);
241 DispatchEventUsingWindowDispatcher(&mouse0);
242 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
244 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());