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 "ash/wm/system_gesture_event_filter.h"
7 #include "ash/accelerators/accelerator_controller.h"
8 #include "ash/ash_switches.h"
9 #include "ash/display/display_manager.h"
10 #include "ash/shelf/shelf.h"
11 #include "ash/shelf/shelf_model.h"
12 #include "ash/shell.h"
13 #include "ash/system/tray/system_tray_delegate.h"
14 #include "ash/test/ash_test_base.h"
15 #include "ash/test/display_manager_test_api.h"
16 #include "ash/test/shell_test_api.h"
17 #include "ash/test/test_shelf_delegate.h"
18 #include "ash/wm/gestures/long_press_affordance_handler.h"
19 #include "ash/wm/window_state.h"
20 #include "ash/wm/window_util.h"
21 #include "base/command_line.h"
22 #include "base/time/time.h"
23 #include "base/timer/timer.h"
24 #include "ui/aura/env.h"
25 #include "ui/aura/test/event_generator.h"
26 #include "ui/aura/test/test_window_delegate.h"
27 #include "ui/aura/test/test_windows.h"
28 #include "ui/aura/window_event_dispatcher.h"
29 #include "ui/base/hit_test.h"
30 #include "ui/base/ui_base_switches.h"
31 #include "ui/events/event.h"
32 #include "ui/events/event_handler.h"
33 #include "ui/events/event_utils.h"
34 #include "ui/events/gestures/gesture_configuration.h"
35 #include "ui/events/test/test_event_handler.h"
36 #include "ui/gfx/screen.h"
37 #include "ui/gfx/size.h"
38 #include "ui/views/widget/widget_delegate.h"
45 class ResizableWidgetDelegate : public views::WidgetDelegateView {
47 ResizableWidgetDelegate() {}
48 virtual ~ResizableWidgetDelegate() {}
51 virtual bool CanResize() const OVERRIDE { return true; }
52 virtual bool CanMaximize() const OVERRIDE { return true; }
53 virtual void DeleteDelegate() OVERRIDE { delete this; }
55 DISALLOW_COPY_AND_ASSIGN(ResizableWidgetDelegate);
58 // Support class for testing windows with a maximum size.
59 class MaxSizeNCFV : public views::NonClientFrameView {
63 virtual gfx::Size GetMaximumSize() OVERRIDE {
64 return gfx::Size(200, 200);
66 virtual gfx::Rect GetBoundsForClientView() const OVERRIDE {
70 virtual gfx::Rect GetWindowBoundsForClientBounds(
71 const gfx::Rect& client_bounds) const OVERRIDE {
75 // This function must ask the ClientView to do a hittest. We don't do this in
76 // the parent NonClientView because that makes it more difficult to calculate
77 // hittests for regions that are partially obscured by the ClientView, e.g.
79 virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
82 virtual void GetWindowMask(const gfx::Size& size,
83 gfx::Path* window_mask) OVERRIDE {}
84 virtual void ResetWindowControls() OVERRIDE {}
85 virtual void UpdateWindowIcon() OVERRIDE {}
86 virtual void UpdateWindowTitle() OVERRIDE {}
88 DISALLOW_COPY_AND_ASSIGN(MaxSizeNCFV);
91 class MaxSizeWidgetDelegate : public views::WidgetDelegateView {
93 MaxSizeWidgetDelegate() {}
94 virtual ~MaxSizeWidgetDelegate() {}
97 virtual bool CanResize() const OVERRIDE { return true; }
98 virtual bool CanMaximize() const OVERRIDE { return false; }
99 virtual void DeleteDelegate() OVERRIDE { delete this; }
100 virtual views::NonClientFrameView* CreateNonClientFrameView(
101 views::Widget* widget) OVERRIDE {
102 return new MaxSizeNCFV;
105 DISALLOW_COPY_AND_ASSIGN(MaxSizeWidgetDelegate);
110 class SystemGestureEventFilterTest
111 : public AshTestBase,
112 public testing::WithParamInterface<bool> {
114 SystemGestureEventFilterTest() : AshTestBase(), docked_enabled_(GetParam()) {}
115 virtual ~SystemGestureEventFilterTest() {}
117 LongPressAffordanceHandler* GetLongPressAffordance() {
118 ShellTestApi shell_test(Shell::GetInstance());
119 return shell_test.system_gesture_event_filter()->
120 long_press_affordance_.get();
123 base::OneShotTimer<LongPressAffordanceHandler>*
124 GetLongPressAffordanceTimer() {
125 return &GetLongPressAffordance()->timer_;
128 aura::Window* GetLongPressAffordanceTarget() {
129 return GetLongPressAffordance()->tap_down_target_;
132 views::View* GetLongPressAffordanceView() {
133 return reinterpret_cast<views::View*>(
134 GetLongPressAffordance()->view_.get());
137 // Overridden from AshTestBase:
138 virtual void SetUp() OVERRIDE {
139 if (!docked_enabled_) {
140 CommandLine::ForCurrentProcess()->AppendSwitch(
141 ash::switches::kAshDisableDockedWindows);
143 test::AshTestBase::SetUp();
144 // Enable brightness key.
145 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
146 SetFirstDisplayAsInternalDisplay();
150 // true if docked windows are enabled with a flag.
151 bool docked_enabled_;
153 DISALLOW_COPY_AND_ASSIGN(SystemGestureEventFilterTest);
156 ui::GestureEvent* CreateGesture(ui::EventType type,
162 return new ui::GestureEvent(type, x, y, 0,
163 base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000),
164 ui::GestureEventDetails(type, delta_x, delta_y), 1 << touch_id);
167 TEST_P(SystemGestureEventFilterTest, LongPressAffordanceStateOnCaptureLoss) {
168 aura::Window* root_window = Shell::GetPrimaryRootWindow();
170 aura::test::TestWindowDelegate delegate;
171 scoped_ptr<aura::Window> window0(
172 aura::test::CreateTestWindowWithDelegate(
173 &delegate, 9, gfx::Rect(0, 0, 100, 100), root_window));
174 scoped_ptr<aura::Window> window1(
175 aura::test::CreateTestWindowWithDelegate(
176 &delegate, 10, gfx::Rect(0, 0, 100, 50), window0.get()));
177 scoped_ptr<aura::Window> window2(
178 aura::test::CreateTestWindowWithDelegate(
179 &delegate, 11, gfx::Rect(0, 50, 100, 50), window0.get()));
181 const int kTouchId = 5;
183 // Capture first window.
184 window1->SetCapture();
185 EXPECT_TRUE(window1->HasCapture());
187 // Send touch event to first window.
188 ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
191 ui::EventTimeForNow());
192 ui::EventDispatchDetails details =
193 root_window->GetHost()->dispatcher()->OnEventFromSource(&press);
194 ASSERT_FALSE(details.dispatcher_destroyed);
195 EXPECT_TRUE(window1->HasCapture());
197 base::OneShotTimer<LongPressAffordanceHandler>* timer =
198 GetLongPressAffordanceTimer();
199 EXPECT_TRUE(timer->IsRunning());
200 EXPECT_EQ(window1, GetLongPressAffordanceTarget());
202 // Force timeout so that the affordance animation can start.
203 timer->user_task().Run();
205 EXPECT_TRUE(GetLongPressAffordance()->is_animating());
208 window2->SetCapture();
209 EXPECT_TRUE(window2->HasCapture());
211 EXPECT_TRUE(GetLongPressAffordance()->is_animating());
212 EXPECT_EQ(window1, GetLongPressAffordanceTarget());
214 // Animate to completion.
215 GetLongPressAffordance()->End(); // end grow animation.
216 // Force timeout to start shrink animation.
217 EXPECT_TRUE(timer->IsRunning());
218 timer->user_task().Run();
220 EXPECT_TRUE(GetLongPressAffordance()->is_animating());
221 GetLongPressAffordance()->End(); // end shrink animation.
223 // Check if state has reset.
224 EXPECT_EQ(NULL, GetLongPressAffordanceTarget());
225 EXPECT_EQ(NULL, GetLongPressAffordanceView());
228 TEST_P(SystemGestureEventFilterTest, TwoFingerDrag) {
229 gfx::Rect bounds(0, 0, 600, 600);
230 aura::Window* root_window = Shell::GetPrimaryRootWindow();
231 views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
232 new ResizableWidgetDelegate, root_window, bounds);
235 const int kSteps = 15;
236 const int kTouchPoints = 2;
237 gfx::Point points[kTouchPoints] = {
238 gfx::Point(250, 250),
239 gfx::Point(350, 350),
242 aura::test::EventGenerator generator(root_window,
243 toplevel->GetNativeWindow());
245 wm::WindowState* toplevel_state =
246 wm::GetWindowState(toplevel->GetNativeWindow());
247 // Swipe down to minimize.
248 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
249 EXPECT_TRUE(toplevel_state->IsMinimized());
252 toplevel->GetNativeWindow()->SetBounds(bounds);
254 // Swipe up to maximize.
255 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
256 EXPECT_TRUE(toplevel_state->IsMaximized());
259 toplevel->GetNativeWindow()->SetBounds(bounds);
261 // Swipe right to snap.
262 gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
263 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
264 gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen();
265 EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString());
267 // Swipe left to snap.
268 gfx::Point left_points[kTouchPoints];
269 for (int i = 0; i < kTouchPoints; ++i) {
270 left_points[i] = points[i];
271 left_points[i].Offset(right_tile_bounds.x(), right_tile_bounds.y());
273 generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps,
275 gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen();
276 EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString());
277 EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString());
279 // Swipe right again.
280 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
281 gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen();
282 EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString());
283 EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString());
286 TEST_P(SystemGestureEventFilterTest, TwoFingerDragTwoWindows) {
287 aura::Window* root_window = Shell::GetPrimaryRootWindow();
288 ui::GestureConfiguration::set_max_separation_for_gesture_touches_in_pixels(0);
289 views::Widget* first = views::Widget::CreateWindowWithContextAndBounds(
290 new ResizableWidgetDelegate, root_window, gfx::Rect(10, 0, 50, 100));
292 views::Widget* second = views::Widget::CreateWindowWithContextAndBounds(
293 new ResizableWidgetDelegate, root_window, gfx::Rect(100, 0, 100, 100));
296 // Start a two-finger drag on |first|, and then try to use another two-finger
297 // drag to move |second|. The attempt to move |second| should fail.
298 const gfx::Rect& first_bounds = first->GetWindowBoundsInScreen();
299 const gfx::Rect& second_bounds = second->GetWindowBoundsInScreen();
300 const int kSteps = 15;
301 const int kTouchPoints = 4;
302 gfx::Point points[kTouchPoints] = {
303 first_bounds.origin() + gfx::Vector2d(5, 5),
304 first_bounds.origin() + gfx::Vector2d(30, 10),
305 second_bounds.origin() + gfx::Vector2d(5, 5),
306 second_bounds.origin() + gfx::Vector2d(40, 20)
309 aura::test::EventGenerator generator(root_window);
310 // Do not drag too fast to avoid fling.
311 generator.GestureMultiFingerScroll(kTouchPoints, points,
314 EXPECT_NE(first_bounds.ToString(),
315 first->GetWindowBoundsInScreen().ToString());
316 EXPECT_EQ(second_bounds.ToString(),
317 second->GetWindowBoundsInScreen().ToString());
320 TEST_P(SystemGestureEventFilterTest, WindowsWithMaxSizeDontSnap) {
321 gfx::Rect bounds(250, 150, 100, 100);
322 aura::Window* root_window = Shell::GetPrimaryRootWindow();
323 views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
324 new MaxSizeWidgetDelegate, root_window, bounds);
327 const int kSteps = 15;
328 const int kTouchPoints = 2;
329 gfx::Point points[kTouchPoints] = {
330 gfx::Point(bounds.x() + 10, bounds.y() + 30),
331 gfx::Point(bounds.x() + 30, bounds.y() + 20),
334 aura::test::EventGenerator generator(root_window,
335 toplevel->GetNativeWindow());
337 // Swipe down to minimize.
338 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
339 wm::WindowState* toplevel_state =
340 wm::GetWindowState(toplevel->GetNativeWindow());
341 EXPECT_TRUE(toplevel_state->IsMinimized());
344 toplevel->GetNativeWindow()->SetBounds(bounds);
346 // Check that swiping up doesn't maximize.
347 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
348 EXPECT_FALSE(toplevel_state->IsMaximized());
351 toplevel->GetNativeWindow()->SetBounds(bounds);
353 // Check that swiping right doesn't snap.
354 gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
355 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
356 normal_bounds.set_x(normal_bounds.x() + 150);
357 EXPECT_EQ(normal_bounds.ToString(),
358 toplevel->GetWindowBoundsInScreen().ToString());
360 toplevel->GetNativeWindow()->SetBounds(bounds);
362 // Check that swiping left doesn't snap.
363 normal_bounds = toplevel->GetWindowBoundsInScreen();
364 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, -150, 0);
365 normal_bounds.set_x(normal_bounds.x() - 150);
366 EXPECT_EQ(normal_bounds.ToString(),
367 toplevel->GetWindowBoundsInScreen().ToString());
369 toplevel->GetNativeWindow()->SetBounds(bounds);
371 // Swipe right again, make sure the window still doesn't snap.
372 normal_bounds = toplevel->GetWindowBoundsInScreen();
373 normal_bounds.set_x(normal_bounds.x() + 150);
374 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
375 EXPECT_EQ(normal_bounds.ToString(),
376 toplevel->GetWindowBoundsInScreen().ToString());
379 TEST_P(SystemGestureEventFilterTest, TwoFingerDragEdge) {
380 gfx::Rect bounds(0, 0, 100, 100);
381 aura::Window* root_window = Shell::GetPrimaryRootWindow();
382 views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
383 new ResizableWidgetDelegate, root_window, bounds);
386 const int kSteps = 15;
387 const int kTouchPoints = 2;
388 gfx::Point points[kTouchPoints] = {
389 gfx::Point(30, 20), // Caption
390 gfx::Point(0, 40), // Left edge
393 EXPECT_EQ(HTLEFT, toplevel->GetNativeWindow()->delegate()->
394 GetNonClientComponent(points[1]));
396 aura::test::EventGenerator generator(root_window,
397 toplevel->GetNativeWindow());
399 bounds = toplevel->GetNativeWindow()->bounds();
400 // Swipe down. Nothing should happen.
401 generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
402 EXPECT_EQ(bounds.ToString(),
403 toplevel->GetNativeWindow()->bounds().ToString());
406 // We do not allow resizing a window via multiple edges simultaneously. Test
407 // that the behavior is reasonable if a user attempts to resize a window via
409 TEST_P(SystemGestureEventFilterTest,
410 TwoFingerAttemptResizeLeftAndRightEdgesSimultaneously) {
411 gfx::Rect initial_bounds(0, 0, 400, 400);
412 views::Widget* toplevel =
413 views::Widget::CreateWindowWithContextAndBounds(
414 new ResizableWidgetDelegate, CurrentContext(), initial_bounds);
417 const int kSteps = 15;
418 const int kTouchPoints = 2;
419 gfx::Point points[kTouchPoints] = {
420 gfx::Point(0, 40), // Left edge
421 gfx::Point(399, 40), // Right edge
423 int delays[kTouchPoints] = {0, 120};
425 EXPECT_EQ(HTLEFT, toplevel->GetNonClientComponent(points[0]));
426 EXPECT_EQ(HTRIGHT, toplevel->GetNonClientComponent(points[1]));
428 GetEventGenerator().GestureMultiFingerScrollWithDelays(
429 kTouchPoints, points, delays, 15, kSteps, 0, 40);
431 // The window bounds should not have changed because neither of the fingers
432 // moved horizontally.
433 EXPECT_EQ(initial_bounds.ToString(),
434 toplevel->GetNativeWindow()->bounds().ToString());
437 TEST_P(SystemGestureEventFilterTest, TwoFingerDragDelayed) {
438 gfx::Rect bounds(0, 0, 100, 100);
439 aura::Window* root_window = Shell::GetPrimaryRootWindow();
440 views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
441 new ResizableWidgetDelegate, root_window, bounds);
444 const int kSteps = 15;
445 const int kTouchPoints = 2;
446 gfx::Point points[kTouchPoints] = {
447 gfx::Point(30, 20), // Caption
448 gfx::Point(34, 20), // Caption
450 int delays[kTouchPoints] = {0, 120};
452 EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
453 GetNonClientComponent(points[0]));
454 EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
455 GetNonClientComponent(points[1]));
457 aura::test::EventGenerator generator(root_window,
458 toplevel->GetNativeWindow());
460 bounds = toplevel->GetNativeWindow()->bounds();
461 // Swipe right and down starting with one finger.
462 // Add another finger after 120ms and continue dragging.
463 // The window should move and the drag should be determined by the center
464 // point between the fingers.
465 generator.GestureMultiFingerScrollWithDelays(
466 kTouchPoints, points, delays, 15, kSteps, 150, 150);
467 bounds += gfx::Vector2d(150 + (points[1].x() - points[0].x()) / 2, 150);
468 EXPECT_EQ(bounds.ToString(),
469 toplevel->GetNativeWindow()->bounds().ToString());
472 TEST_P(SystemGestureEventFilterTest, ThreeFingerGestureStopsDrag) {
473 gfx::Rect bounds(0, 0, 100, 100);
474 aura::Window* root_window = Shell::GetPrimaryRootWindow();
475 views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
476 new ResizableWidgetDelegate, root_window, bounds);
479 const int kSteps = 10;
480 const int kTouchPoints = 3;
481 gfx::Point points[kTouchPoints] = {
482 gfx::Point(30, 20), // Caption
483 gfx::Point(34, 20), // Caption
484 gfx::Point(38, 20), // Caption
486 int delays[kTouchPoints] = {0, 0, 120};
488 EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
489 GetNonClientComponent(points[0]));
490 EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
491 GetNonClientComponent(points[1]));
493 aura::test::EventGenerator generator(root_window,
494 toplevel->GetNativeWindow());
496 bounds = toplevel->GetNativeWindow()->bounds();
497 // Swipe right and down starting with two fingers.
498 // Add third finger after 120ms and continue dragging.
499 // The window should start moving but stop when the 3rd finger touches down.
500 const int kEventSeparation = 15;
501 generator.GestureMultiFingerScrollWithDelays(
502 kTouchPoints, points, delays, kEventSeparation, kSteps, 150, 150);
503 int expected_drag = 150 / kSteps * 120 / kEventSeparation;
504 bounds += gfx::Vector2d(expected_drag, expected_drag);
505 EXPECT_EQ(bounds.ToString(),
506 toplevel->GetNativeWindow()->bounds().ToString());
509 TEST_P(SystemGestureEventFilterTest, DragLeftNearEdgeSnaps) {
510 gfx::Rect bounds(200, 150, 400, 100);
511 aura::Window* root_window = Shell::GetPrimaryRootWindow();
512 views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
513 new ResizableWidgetDelegate, root_window, bounds);
516 const int kSteps = 15;
517 const int kTouchPoints = 2;
518 gfx::Point points[kTouchPoints] = {
519 gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
520 gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
522 aura::Window* toplevel_window = toplevel->GetNativeWindow();
523 aura::test::EventGenerator generator(root_window, toplevel_window);
525 // Check that dragging left snaps before reaching the screen edge.
526 gfx::Rect work_area =
527 Shell::GetScreen()->GetDisplayNearestWindow(root_window).work_area();
528 int drag_x = work_area.x() + 20 - points[0].x();
529 generator.GestureMultiFingerScroll(
530 kTouchPoints, points, 120, kSteps, drag_x, 0);
532 EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(
533 toplevel_window).ToString(),
534 toplevel_window->bounds().ToString());
537 TEST_P(SystemGestureEventFilterTest, DragRightNearEdgeSnaps) {
538 gfx::Rect bounds(200, 150, 400, 100);
539 aura::Window* root_window = Shell::GetPrimaryRootWindow();
540 views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
541 new ResizableWidgetDelegate, root_window, bounds);
544 const int kSteps = 15;
545 const int kTouchPoints = 2;
546 gfx::Point points[kTouchPoints] = {
547 gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
548 gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
550 aura::Window* toplevel_window = toplevel->GetNativeWindow();
551 aura::test::EventGenerator generator(root_window, toplevel_window);
553 // Check that dragging right snaps before reaching the screen edge.
554 gfx::Rect work_area =
555 Shell::GetScreen()->GetDisplayNearestWindow(root_window).work_area();
556 int drag_x = work_area.right() - 20 - points[0].x();
557 generator.GestureMultiFingerScroll(
558 kTouchPoints, points, 120, kSteps, drag_x, 0);
559 EXPECT_EQ(wm::GetDefaultRightSnappedWindowBoundsInParent(
560 toplevel_window).ToString(),
561 toplevel_window->bounds().ToString());
564 // Tests that the window manager does not consume gesture events targetted to
565 // windows of type WINDOW_TYPE_CONTROL. This is important because the web
566 // contents are often (but not always) of type WINDOW_TYPE_CONTROL.
567 TEST_P(SystemGestureEventFilterTest,
568 ControlWindowGetsMultiFingerGestureEvents) {
569 scoped_ptr<aura::Window> parent(
570 CreateTestWindowInShellWithBounds(gfx::Rect(100, 100)));
572 aura::test::EventCountDelegate delegate;
573 delegate.set_window_component(HTCLIENT);
574 scoped_ptr<aura::Window> child(new aura::Window(&delegate));
575 child->SetType(ui::wm::WINDOW_TYPE_CONTROL);
576 child->Init(aura::WINDOW_LAYER_TEXTURED);
577 parent->AddChild(child.get());
578 child->SetBounds(gfx::Rect(100, 100));
581 ui::test::TestEventHandler event_handler;
582 aura::Env::GetInstance()->PrependPreTargetHandler(&event_handler);
584 GetEventGenerator().MoveMouseTo(0, 0);
585 for (int i = 1; i <= 3; ++i)
586 GetEventGenerator().PressTouchId(i);
587 for (int i = 1; i <= 3; ++i)
588 GetEventGenerator().ReleaseTouchId(i);
589 EXPECT_EQ(event_handler.num_gesture_events(),
590 delegate.GetGestureCountAndReset());
592 aura::Env::GetInstance()->RemovePreTargetHandler(&event_handler);
595 // Tests run twice - with docked windows disabled or enabled.
596 INSTANTIATE_TEST_CASE_P(DockedWindowsDisabledOrEnabled,
597 SystemGestureEventFilterTest,