15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/system_gesture_event_filter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/accelerators/accelerator_controller.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/display/display_manager.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_model.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray/system_tray_delegate.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/test/ash_test_base.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/test/display_manager_test_api.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/test/shell_test_api.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ash/test/test_shelf_delegate.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/gestures/long_press_affordance_handler.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_state.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/env.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/test/test_window_delegate.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/test_windows.h"
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h"
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/events/event_handler.h"
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_utils.h"
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/gestures/gesture_configuration.h"
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/events/test/event_generator.h"
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/events/test/test_event_handler.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/widget/widget.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h"
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/window/non_client_view.h"
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/window/window_button_order_provider.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace test {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResizableWidgetDelegate : public views::WidgetDelegateView {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResizableWidgetDelegate() {}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ResizableWidgetDelegate() {}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool CanResize() const OVERRIDE { return true; }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool CanMaximize() const OVERRIDE { return true; }
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual bool CanMinimize() const OVERRIDE { return true; }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DeleteDelegate() OVERRIDE { delete this; }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ResizableWidgetDelegate);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Support class for testing windows with a maximum size.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MaxSizeNCFV : public views::NonClientFrameView {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaxSizeNCFV() {}
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetMaximumSize() const OVERRIDE {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Size(200, 200);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::Rect GetBoundsForClientView() const OVERRIDE {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Rect();
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::Rect GetWindowBoundsForClientBounds(
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const gfx::Rect& client_bounds) const OVERRIDE {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Rect();
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This function must ask the ClientView to do a hittest.  We don't do this in
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the parent NonClientView because that makes it more difficult to calculate
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // hittests for regions that are partially obscured by the ClientView, e.g.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // HTSYSMENU.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HTNOWHERE;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void GetWindowMask(const gfx::Size& size,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             gfx::Path* window_mask) OVERRIDE {}
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ResetWindowControls() OVERRIDE {}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void UpdateWindowIcon() OVERRIDE {}
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void UpdateWindowTitle() OVERRIDE {}
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void SizeConstraintsChanged() OVERRIDE {}
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MaxSizeNCFV);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MaxSizeWidgetDelegate : public views::WidgetDelegateView {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaxSizeWidgetDelegate() {}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~MaxSizeWidgetDelegate() {}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool CanResize() const OVERRIDE { return true; }
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool CanMaximize() const OVERRIDE { return false; }
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void DeleteDelegate() OVERRIDE { delete this; }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual views::NonClientFrameView* CreateNonClientFrameView(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      views::Widget* widget) OVERRIDE {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return new MaxSizeNCFV;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MaxSizeWidgetDelegate);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class SystemGestureEventFilterTest : public AshTestBase {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SystemGestureEventFilterTest() : AshTestBase() {}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SystemGestureEventFilterTest() {}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  LongPressAffordanceHandler* GetLongPressAffordance() {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ShellTestApi shell_test(Shell::GetInstance());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return shell_test.system_gesture_event_filter()->
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        long_press_affordance_.get();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::OneShotTimer<LongPressAffordanceHandler>*
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  GetLongPressAffordanceTimer() {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &GetLongPressAffordance()->timer_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window* GetLongPressAffordanceTarget() {
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return GetLongPressAffordance()->tap_down_target_;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* GetLongPressAffordanceView() {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<views::View*>(
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetLongPressAffordance()->view_.get());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from AshTestBase:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(jonross): TwoFingerDragDelayed() and ThreeFingerGestureStopsDrag()
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // both use hardcoded touch points, assuming that they target empty header
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // space. Window control order now reflects configuration files and can
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // change. The tests should be improved to dynamically decide touch points.
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // To address this we specify the originally expected window control
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // positions to be consistent across tests.
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<views::FrameButton> leading;
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<views::FrameButton> trailing;
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    trailing.push_back(views::FRAME_BUTTON_MINIMIZE);
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    trailing.push_back(views::FRAME_BUTTON_MAXIMIZE);
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    trailing.push_back(views::FRAME_BUTTON_CLOSE);
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    views::WindowButtonOrderProvider::GetInstance()->
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        SetWindowButtonOrder(leading, trailing);
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test::AshTestBase::SetUp();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Enable brightness key.
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SetFirstDisplayAsInternalDisplay();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SystemGestureEventFilterTest);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::GestureEvent* CreateGesture(ui::EventType type,
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                int x,
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                int y,
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                float delta_x,
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                float delta_y,
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                int touch_id) {
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::GestureEventDetails details =
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ui::GestureEventDetails(type, delta_x, delta_y);
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  details.set_oldest_touch_id(touch_id);
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return new ui::GestureEvent(x, y, 0,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000),
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ui::GestureEventDetails(type, delta_x, delta_y));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, LongPressAffordanceStateOnCaptureLoss) {
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::TestWindowDelegate delegate;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window0(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 9, gfx::Rect(0, 0, 100, 100), root_window));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window1(
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 10, gfx::Rect(0, 0, 100, 50), window0.get()));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window2(
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 11, gfx::Rect(0, 50, 100, 50), window0.get()));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchId = 5;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Capture first window.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetCapture();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window1->HasCapture());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send touch event to first window.
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       gfx::Point(10, 10),
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       kTouchId,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       ui::EventTimeForNow());
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::EventDispatchDetails details =
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      root_window->GetHost()->dispatcher()->OnEventFromSource(&press);
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(details.dispatcher_destroyed);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window1->HasCapture());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::OneShotTimer<LongPressAffordanceHandler>* timer =
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetLongPressAffordanceTimer();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(timer->IsRunning());
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(window1, GetLongPressAffordanceTarget());
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force timeout so that the affordance animation can start.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->user_task().Run();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->Stop();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change capture.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetCapture();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window2->HasCapture());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(window1, GetLongPressAffordanceTarget());
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Animate to completion.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetLongPressAffordance()->End();  // end grow animation.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force timeout to start shrink animation.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(timer->IsRunning());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->user_task().Run();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->Stop();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetLongPressAffordance()->End();  // end shrink animation.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if state has reset.
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(NULL, GetLongPressAffordanceTarget());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NULL, GetLongPressAffordanceView());
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, TwoFingerDrag) {
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect bounds(0, 0, 600, 600);
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Show();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 15;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchPoints = 2;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point(250, 250),
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point(350, 350),
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(root_window, toplevel->GetNativeWindow());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* toplevel_state =
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      wm::GetWindowState(toplevel->GetNativeWindow());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe down to minimize.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(toplevel_state->IsMinimized());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe up to maximize.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(toplevel_state->IsMaximized());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right to snap.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe left to snap.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point left_points[kTouchPoints];
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kTouchPoints; ++i) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i] = points[i];
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i].Offset(right_tile_bounds.x(), right_tile_bounds.y());
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      -150, 0);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString());
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right again.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString());
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, TwoFingerDragTwoWindows) {
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::GestureConfiguration::set_max_separation_for_gesture_touches_in_pixels(0);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* first = views::Widget::CreateWindowWithContextAndBounds(
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new ResizableWidgetDelegate, root_window, gfx::Rect(10, 0, 50, 100));
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first->Show();
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* second = views::Widget::CreateWindowWithContextAndBounds(
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, gfx::Rect(100, 0, 100, 100));
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second->Show();
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start a two-finger drag on |first|, and then try to use another two-finger
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // drag to move |second|. The attempt to move |second| should fail.
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Rect& first_bounds = first->GetWindowBoundsInScreen();
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Rect& second_bounds = second->GetWindowBoundsInScreen();
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kSteps = 15;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kTouchPoints = 4;
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Point points[kTouchPoints] = {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    first_bounds.origin() + gfx::Vector2d(5, 5),
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    first_bounds.origin() + gfx::Vector2d(30, 10),
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    second_bounds.origin() + gfx::Vector2d(5, 5),
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    second_bounds.origin() + gfx::Vector2d(40, 20)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(root_window);
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Do not drag too fast to avoid fling.
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points,
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      50, kSteps, 0, 150);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_NE(first_bounds.ToString(),
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            first->GetWindowBoundsInScreen().ToString());
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(second_bounds.ToString(),
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            second->GetWindowBoundsInScreen().ToString());
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, WindowsWithMaxSizeDontSnap) {
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bounds(250, 150, 100, 100);
3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new MaxSizeWidgetDelegate, root_window, bounds);
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->Show();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kSteps = 15;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kTouchPoints = 2;
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Point points[kTouchPoints] = {
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + 10, bounds.y() + 30),
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + 30, bounds.y() + 20),
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(root_window, toplevel->GetNativeWindow());
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Swipe down to minimize.
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* toplevel_state =
35068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      wm::GetWindowState(toplevel->GetNativeWindow());
35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(toplevel_state->IsMinimized());
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->Restore();
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that swiping up doesn't maximize.
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
35868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(toplevel_state->IsMaximized());
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->Restore();
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that swiping right doesn't snap.
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds.set_x(normal_bounds.x() + 150);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(normal_bounds.ToString(),
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      toplevel->GetWindowBoundsInScreen().ToString());
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that swiping left doesn't snap.
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds = toplevel->GetWindowBoundsInScreen();
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, -150, 0);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds.set_x(normal_bounds.x() - 150);
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(normal_bounds.ToString(),
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      toplevel->GetWindowBoundsInScreen().ToString());
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Swipe right again, make sure the window still doesn't snap.
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds = toplevel->GetWindowBoundsInScreen();
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds.set_x(normal_bounds.x() + 150);
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(normal_bounds.ToString(),
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      toplevel->GetWindowBoundsInScreen().ToString());
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, DISABLED_TwoFingerDragEdge) {
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  gfx::Rect bounds(0, 0, 200, 100);
3911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Show();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 15;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchPoints = 2;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(30, 20),  // Caption
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(0, 40),   // Left edge
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      GetNonClientComponent(points[0]));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(HTLEFT, toplevel->GetNativeWindow()->delegate()->
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetNonClientComponent(points[1]));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(root_window, toplevel->GetNativeWindow());
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds = toplevel->GetNativeWindow()->bounds();
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe down. Nothing should happen.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(bounds.ToString(),
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            toplevel->GetNativeWindow()->bounds().ToString());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// We do not allow resizing a window via multiple edges simultaneously. Test
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// that the behavior is reasonable if a user attempts to resize a window via
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// several edges.
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest,
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       TwoFingerAttemptResizeLeftAndRightEdgesSimultaneously) {
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect initial_bounds(0, 0, 400, 400);
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  views::Widget* toplevel =
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      views::Widget::CreateWindowWithContextAndBounds(
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          new ResizableWidgetDelegate, CurrentContext(), initial_bounds);
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  toplevel->Show();
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int kSteps = 15;
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int kTouchPoints = 2;
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Point(0, 40),    // Left edge
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Point(399, 40),  // Right edge
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int delays[kTouchPoints] = {0, 120};
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(HTLEFT, toplevel->GetNonClientComponent(points[0]));
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(HTRIGHT, toplevel->GetNonClientComponent(points[1]));
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetEventGenerator().GestureMultiFingerScrollWithDelays(
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      kTouchPoints, points, delays, 15, kSteps, 0, 40);
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The window bounds should not have changed because neither of the fingers
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // moved horizontally.
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(initial_bounds.ToString(),
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            toplevel->GetNativeWindow()->bounds().ToString());
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, TwoFingerDragDelayed) {
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gfx::Rect bounds(0, 0, 200, 100);
4501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
4511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
4521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
4531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  toplevel->Show();
4541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kSteps = 15;
4561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kTouchPoints = 2;
4571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
4581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(30, 20),  // Caption
4591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(34, 20),  // Caption
4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  };
4611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int delays[kTouchPoints] = {0, 120};
4621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
4641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetNonClientComponent(points[0]));
4651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
4661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetNonClientComponent(points[1]));
4671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(root_window, toplevel->GetNativeWindow());
4691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds = toplevel->GetNativeWindow()->bounds();
4711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Swipe right and down starting with one finger.
4721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Add another finger after 120ms and continue dragging.
4731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The window should move and the drag should be determined by the center
4741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // point between the fingers.
4751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  generator.GestureMultiFingerScrollWithDelays(
4761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      kTouchPoints, points, delays, 15, kSteps, 150, 150);
4771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds += gfx::Vector2d(150 + (points[1].x() - points[0].x()) / 2, 150);
4781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(bounds.ToString(),
4791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            toplevel->GetNativeWindow()->bounds().ToString());
4801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, ThreeFingerGestureStopsDrag) {
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gfx::Rect bounds(0, 0, 200, 100);
4841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
4851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
4861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
4871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  toplevel->Show();
4881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kSteps = 10;
4901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kTouchPoints = 3;
4911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
4921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(30, 20),  // Caption
4931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(34, 20),  // Caption
4941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(38, 20),  // Caption
4951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  };
4961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int delays[kTouchPoints] = {0, 0, 120};
4971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
4991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetNonClientComponent(points[0]));
5001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
5011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetNonClientComponent(points[1]));
5021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(root_window, toplevel->GetNativeWindow());
5041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds = toplevel->GetNativeWindow()->bounds();
5061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Swipe right and down starting with two fingers.
5071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Add third finger after 120ms and continue dragging.
5081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The window should start moving but stop when the 3rd finger touches down.
5091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kEventSeparation = 15;
5101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  generator.GestureMultiFingerScrollWithDelays(
5111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      kTouchPoints, points, delays, kEventSeparation, kSteps, 150, 150);
5121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int expected_drag = 150 / kSteps * 120 / kEventSeparation;
5131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds += gfx::Vector2d(expected_drag, expected_drag);
5141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(bounds.ToString(),
5151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            toplevel->GetNativeWindow()->bounds().ToString());
5161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, DragLeftNearEdgeSnaps) {
519f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bounds(200, 150, 400, 100);
520f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
521f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
523f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  toplevel->Show();
524f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kSteps = 15;
526f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kTouchPoints = 2;
527f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point points[kTouchPoints] = {
528f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
529f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  aura::Window* toplevel_window = toplevel->GetNativeWindow();
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(root_window, toplevel_window);
533f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
534f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Check that dragging left snaps before reaching the screen edge.
535f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect work_area =
536f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      Shell::GetScreen()->GetDisplayNearestWindow(root_window).work_area();
537f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int drag_x = work_area.x() + 20 - points[0].x();
538f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  generator.GestureMultiFingerScroll(
539f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kTouchPoints, points, 120, kSteps, drag_x, 0);
540f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(
542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                toplevel_window).ToString(),
543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            toplevel_window->bounds().ToString());
544f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
545f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, DragRightNearEdgeSnaps) {
547f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bounds(200, 150, 400, 100);
548f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
549f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
550f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
551f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  toplevel->Show();
552f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
553f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kSteps = 15;
554f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kTouchPoints = 2;
555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point points[kTouchPoints] = {
556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
557f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
558f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  aura::Window* toplevel_window = toplevel->GetNativeWindow();
5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(root_window, toplevel_window);
561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Check that dragging right snaps before reaching the screen edge.
563f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect work_area =
564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      Shell::GetScreen()->GetDisplayNearestWindow(root_window).work_area();
565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int drag_x = work_area.right() - 20 - points[0].x();
566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  generator.GestureMultiFingerScroll(
567f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kTouchPoints, points, 120, kSteps, drag_x, 0);
568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(wm::GetDefaultRightSnappedWindowBoundsInParent(
569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                toplevel_window).ToString(),
570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            toplevel_window->bounds().ToString());
571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Tests that the window manager does not consume gesture events targeted to
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// windows of type WINDOW_TYPE_CONTROL. This is important because the web
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// contents are often (but not always) of type WINDOW_TYPE_CONTROL.
576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest,
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ControlWindowGetsMultiFingerGestureEvents) {
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<aura::Window> parent(
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateTestWindowInShellWithBounds(gfx::Rect(100, 100)));
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::test::EventCountDelegate delegate;
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate.set_window_component(HTCLIENT);
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<aura::Window> child(new aura::Window(&delegate));
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetType(ui::wm::WINDOW_TYPE_CONTROL);
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->Init(aura::WINDOW_LAYER_TEXTURED);
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parent->AddChild(child.get());
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetBounds(gfx::Rect(100, 100));
5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->Show();
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
59023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ui::test::TestEventHandler event_handler;
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::Env::GetInstance()->PrependPreTargetHandler(&event_handler);
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetEventGenerator().MoveMouseTo(0, 0);
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 1; i <= 3; ++i)
5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GetEventGenerator().PressTouchId(i);
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 1; i <= 3; ++i)
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GetEventGenerator().ReleaseTouchId(i);
5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(event_handler.num_gesture_events(),
5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            delegate.GetGestureCountAndReset());
6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::Env::GetInstance()->RemovePreTargetHandler(&event_handler);
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace test
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
606