Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ash / wm / system_gesture_event_filter_unittest.cc
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 "ash/wm/system_gesture_event_filter.h"
6
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"
39
40 namespace ash {
41 namespace test {
42
43 namespace {
44
45 class ResizableWidgetDelegate : public views::WidgetDelegateView {
46  public:
47   ResizableWidgetDelegate() {}
48   virtual ~ResizableWidgetDelegate() {}
49
50  private:
51   virtual bool CanResize() const OVERRIDE { return true; }
52   virtual bool CanMaximize() const OVERRIDE { return true; }
53   virtual void DeleteDelegate() OVERRIDE { delete this; }
54
55   DISALLOW_COPY_AND_ASSIGN(ResizableWidgetDelegate);
56 };
57
58 // Support class for testing windows with a maximum size.
59 class MaxSizeNCFV : public views::NonClientFrameView {
60  public:
61   MaxSizeNCFV() {}
62  private:
63   virtual gfx::Size GetMaximumSize() OVERRIDE {
64     return gfx::Size(200, 200);
65   }
66   virtual gfx::Rect GetBoundsForClientView() const OVERRIDE {
67     return gfx::Rect();
68   };
69
70   virtual gfx::Rect GetWindowBoundsForClientBounds(
71       const gfx::Rect& client_bounds) const OVERRIDE {
72     return gfx::Rect();
73   };
74
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.
78   // HTSYSMENU.
79   virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
80     return HTNOWHERE;
81   }
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 {}
87
88   DISALLOW_COPY_AND_ASSIGN(MaxSizeNCFV);
89 };
90
91 class MaxSizeWidgetDelegate : public views::WidgetDelegateView {
92  public:
93   MaxSizeWidgetDelegate() {}
94   virtual ~MaxSizeWidgetDelegate() {}
95
96  private:
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;
103   }
104
105   DISALLOW_COPY_AND_ASSIGN(MaxSizeWidgetDelegate);
106 };
107
108 } // namespace
109
110 class SystemGestureEventFilterTest
111     : public AshTestBase,
112       public testing::WithParamInterface<bool> {
113  public:
114   SystemGestureEventFilterTest() : AshTestBase(), docked_enabled_(GetParam()) {}
115   virtual ~SystemGestureEventFilterTest() {}
116
117   LongPressAffordanceHandler* GetLongPressAffordance() {
118     ShellTestApi shell_test(Shell::GetInstance());
119     return shell_test.system_gesture_event_filter()->
120         long_press_affordance_.get();
121   }
122
123   base::OneShotTimer<LongPressAffordanceHandler>*
124   GetLongPressAffordanceTimer() {
125     return &GetLongPressAffordance()->timer_;
126   }
127
128   aura::Window* GetLongPressAffordanceTarget() {
129     return GetLongPressAffordance()->tap_down_target_;
130   }
131
132   views::View* GetLongPressAffordanceView() {
133     return reinterpret_cast<views::View*>(
134         GetLongPressAffordance()->view_.get());
135   }
136
137   // Overridden from AshTestBase:
138   virtual void SetUp() OVERRIDE {
139     if (!docked_enabled_) {
140       CommandLine::ForCurrentProcess()->AppendSwitch(
141           ash::switches::kAshDisableDockedWindows);
142     }
143     test::AshTestBase::SetUp();
144     // Enable brightness key.
145     test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
146         SetFirstDisplayAsInternalDisplay();
147   }
148
149  private:
150   // true if docked windows are enabled with a flag.
151   bool docked_enabled_;
152
153   DISALLOW_COPY_AND_ASSIGN(SystemGestureEventFilterTest);
154 };
155
156 ui::GestureEvent* CreateGesture(ui::EventType type,
157                                     int x,
158                                     int y,
159                                     float delta_x,
160                                     float delta_y,
161                                     int touch_id) {
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);
165 }
166
167 TEST_P(SystemGestureEventFilterTest, LongPressAffordanceStateOnCaptureLoss) {
168   aura::Window* root_window = Shell::GetPrimaryRootWindow();
169
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()));
180
181   const int kTouchId = 5;
182
183   // Capture first window.
184   window1->SetCapture();
185   EXPECT_TRUE(window1->HasCapture());
186
187   // Send touch event to first window.
188   ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
189                        gfx::Point(10, 10),
190                        kTouchId,
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());
196
197   base::OneShotTimer<LongPressAffordanceHandler>* timer =
198       GetLongPressAffordanceTimer();
199   EXPECT_TRUE(timer->IsRunning());
200   EXPECT_EQ(window1, GetLongPressAffordanceTarget());
201
202   // Force timeout so that the affordance animation can start.
203   timer->user_task().Run();
204   timer->Stop();
205   EXPECT_TRUE(GetLongPressAffordance()->is_animating());
206
207   // Change capture.
208   window2->SetCapture();
209   EXPECT_TRUE(window2->HasCapture());
210
211   EXPECT_TRUE(GetLongPressAffordance()->is_animating());
212   EXPECT_EQ(window1, GetLongPressAffordanceTarget());
213
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();
219   timer->Stop();
220   EXPECT_TRUE(GetLongPressAffordance()->is_animating());
221   GetLongPressAffordance()->End();  // end shrink animation.
222
223   // Check if state has reset.
224   EXPECT_EQ(NULL, GetLongPressAffordanceTarget());
225   EXPECT_EQ(NULL, GetLongPressAffordanceView());
226 }
227
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);
233   toplevel->Show();
234
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),
240   };
241
242   aura::test::EventGenerator generator(root_window,
243                                        toplevel->GetNativeWindow());
244
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());
250
251   toplevel->Restore();
252   toplevel->GetNativeWindow()->SetBounds(bounds);
253
254   // Swipe up to maximize.
255   generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
256   EXPECT_TRUE(toplevel_state->IsMaximized());
257
258   toplevel->Restore();
259   toplevel->GetNativeWindow()->SetBounds(bounds);
260
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());
266
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());
272   }
273   generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps,
274       -150, 0);
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());
278
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());
284 }
285
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));
291   first->Show();
292   views::Widget* second = views::Widget::CreateWindowWithContextAndBounds(
293       new ResizableWidgetDelegate, root_window, gfx::Rect(100, 0, 100, 100));
294   second->Show();
295
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)
307   };
308
309   aura::test::EventGenerator generator(root_window);
310   // Do not drag too fast to avoid fling.
311   generator.GestureMultiFingerScroll(kTouchPoints, points,
312       50, kSteps, 0, 150);
313
314   EXPECT_NE(first_bounds.ToString(),
315             first->GetWindowBoundsInScreen().ToString());
316   EXPECT_EQ(second_bounds.ToString(),
317             second->GetWindowBoundsInScreen().ToString());
318 }
319
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);
325   toplevel->Show();
326
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),
332   };
333
334   aura::test::EventGenerator generator(root_window,
335                                        toplevel->GetNativeWindow());
336
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());
342
343   toplevel->Restore();
344   toplevel->GetNativeWindow()->SetBounds(bounds);
345
346   // Check that swiping up doesn't maximize.
347   generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
348   EXPECT_FALSE(toplevel_state->IsMaximized());
349
350   toplevel->Restore();
351   toplevel->GetNativeWindow()->SetBounds(bounds);
352
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());
359
360   toplevel->GetNativeWindow()->SetBounds(bounds);
361
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());
368
369   toplevel->GetNativeWindow()->SetBounds(bounds);
370
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());
377 }
378
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);
384   toplevel->Show();
385
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
391   };
392
393   EXPECT_EQ(HTLEFT, toplevel->GetNativeWindow()->delegate()->
394         GetNonClientComponent(points[1]));
395
396   aura::test::EventGenerator generator(root_window,
397                                        toplevel->GetNativeWindow());
398
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());
404 }
405
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
408 // several edges.
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);
415   toplevel->Show();
416
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
422   };
423   int delays[kTouchPoints] = {0, 120};
424
425   EXPECT_EQ(HTLEFT, toplevel->GetNonClientComponent(points[0]));
426   EXPECT_EQ(HTRIGHT, toplevel->GetNonClientComponent(points[1]));
427
428   GetEventGenerator().GestureMultiFingerScrollWithDelays(
429       kTouchPoints, points, delays, 15, kSteps, 0, 40);
430
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());
435 }
436
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);
442   toplevel->Show();
443
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
449   };
450   int delays[kTouchPoints] = {0, 120};
451
452   EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
453         GetNonClientComponent(points[0]));
454   EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
455         GetNonClientComponent(points[1]));
456
457   aura::test::EventGenerator generator(root_window,
458                                        toplevel->GetNativeWindow());
459
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());
470 }
471
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);
477   toplevel->Show();
478
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
485   };
486   int delays[kTouchPoints] = {0, 0, 120};
487
488   EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
489         GetNonClientComponent(points[0]));
490   EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
491         GetNonClientComponent(points[1]));
492
493   aura::test::EventGenerator generator(root_window,
494                                        toplevel->GetNativeWindow());
495
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());
507 }
508
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);
514   toplevel->Show();
515
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),
521   };
522   aura::Window* toplevel_window = toplevel->GetNativeWindow();
523   aura::test::EventGenerator generator(root_window, toplevel_window);
524
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);
531
532   EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(
533                 toplevel_window).ToString(),
534             toplevel_window->bounds().ToString());
535 }
536
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);
542   toplevel->Show();
543
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),
549   };
550   aura::Window* toplevel_window = toplevel->GetNativeWindow();
551   aura::test::EventGenerator generator(root_window, toplevel_window);
552
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());
562 }
563
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)));
571
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));
579   child->Show();
580
581   ui::test::TestEventHandler event_handler;
582   aura::Env::GetInstance()->PrependPreTargetHandler(&event_handler);
583
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());
591
592   aura::Env::GetInstance()->RemovePreTargetHandler(&event_handler);
593 }
594
595 // Tests run twice - with docked windows disabled or enabled.
596 INSTANTIATE_TEST_CASE_P(DockedWindowsDisabledOrEnabled,
597                         SystemGestureEventFilterTest,
598                         testing::Bool());
599
600 }  // namespace test
601 }  // namespace ash