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. 4 5#include "ui/wm/core/compound_event_filter.h" 6 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" 19 20namespace { 21 22#if defined(OS_CHROMEOS) || defined(OS_WIN) 23base::TimeDelta GetTime() { 24 return ui::EventTimeForNow(); 25} 26#endif // defined(OS_CHROMEOS) || defined(OS_WIN) 27 28} 29 30namespace wm { 31 32namespace { 33 34// An event filter that consumes all gesture events. 35class ConsumeGestureEventFilter : public ui::EventHandler { 36 public: 37 ConsumeGestureEventFilter() {} 38 virtual ~ConsumeGestureEventFilter() {} 39 40 private: 41 // Overridden from ui::EventHandler: 42 virtual void OnGestureEvent(ui::GestureEvent* e) OVERRIDE { 43 e->StopPropagation(); 44 } 45 46 DISALLOW_COPY_AND_ASSIGN(ConsumeGestureEventFilter); 47}; 48 49} // namespace 50 51typedef aura::test::AuraTestBase CompoundEventFilterTest; 52 53#if defined(OS_CHROMEOS) 54// A keypress only hides the cursor on ChromeOS (crbug.com/304296). 55TEST_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())); 61 window->Show(); 62 window->SetCapture(); 63 64 aura::test::TestCursorClient cursor_client(root_window()); 65 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()); 70 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()); 77 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()); 83 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()); 89 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()); 95 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()); 101 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()); 108 109 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get()); 110} 111#endif // defined(OS_CHROMEOS) 112 113#if defined(OS_CHROMEOS) || defined(OS_WIN) 114// Touch visually hides the cursor on ChromeOS and Windows. 115TEST_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())); 122 window->Show(); 123 window->SetCapture(); 124 125 aura::test::TestCursorClient cursor_client(root_window()); 126 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()); 131 132 // This press is required for the GestureRecognizer to associate a target 133 // with kTouchId 134 ui::TouchEvent press0( 135 ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime()); 136 DispatchEventUsingWindowDispatcher(&press0); 137 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); 138 139 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 10), 1, GetTime()); 140 DispatchEventUsingWindowDispatcher(&move); 141 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); 142 143 ui::TouchEvent release( 144 ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), 1, GetTime()); 145 DispatchEventUsingWindowDispatcher(&release); 146 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); 147 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()); 153 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()); 162} 163#endif // defined(OS_CHROMEOS) || defined(OS_WIN) 164 165// Tests that if an event filter consumes a gesture, then it doesn't focus the 166// window. 167TEST_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())); 176 window->Show(); 177 178 EXPECT_TRUE(window->CanFocus()); 179 EXPECT_FALSE(window->HasFocus()); 180 181 // Tap on the window should not focus it since the filter will be consuming 182 // the gestures. 183 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50)); 184 generator.PressTouch(); 185 EXPECT_FALSE(window->HasFocus()); 186 187 compound_filter->RemoveHandler(gesure_handler.get()); 188 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get()); 189} 190 191// Verifies we don't attempt to hide the mouse when the mouse is down and a 192// touch event comes in. 193TEST_F(CompoundEventFilterTest, DontHideWhenMouseDown) { 194 ui::test::EventGenerator event_generator(root_window()); 195 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())); 201 window->Show(); 202 203 aura::test::TestCursorClient cursor_client(root_window()); 204 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()); 211 212 // Do a touch event. As the mouse button is down this should not disable mouse 213 // events. 214 event_generator.PressTouch(); 215 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled()); 216 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get()); 217} 218 219#if defined(OS_WIN) 220// Windows synthesizes mouse messages for touch events. We should not be 221// showing the cursor when we receive such messages. 222TEST_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())); 228 window->Show(); 229 window->SetCapture(); 230 231 aura::test::TestCursorClient cursor_client(root_window()); 232 cursor_client.DisableMouseEvents(); 233 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); 234 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); 238 239 DispatchEventUsingWindowDispatcher(&mouse0); 240 EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); 241 242 mouse0.set_flags(mouse0.flags() & ~ui::EF_FROM_TOUCH); 243 DispatchEventUsingWindowDispatcher(&mouse0); 244 EXPECT_TRUE(cursor_client.IsMouseEventsEnabled()); 245 246 aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get()); 247} 248#endif 249 250} // namespace wm 251