system_gesture_event_filter_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/accelerators/accelerator_controller.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/ash_switches.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/display/display_manager.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/launcher/launcher.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_model.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/system/brightness_control_delegate.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"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/test/test_launcher_delegate.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/volume_control_delegate.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/gestures/long_press_affordance_handler.h"
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_state.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/wm/workspace/snap_sizer.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/event_generator.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/test_windows.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ui_base_switches.h"
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_utils.h"
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/gestures/gesture_configuration.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace test {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DelegatePercentTracker {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DelegatePercentTracker()
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : handle_percent_count_(0),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handle_percent_(0){
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int handle_percent_count() const {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return handle_percent_count_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double handle_percent() const {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return handle_percent_;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetPercent(double percent) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handle_percent_ = percent;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handle_percent_count_++;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int handle_percent_count_;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int handle_percent_;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DelegatePercentTracker);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummyVolumeControlDelegate : public VolumeControlDelegate,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   public DelegatePercentTracker {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DummyVolumeControlDelegate() {}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DummyVolumeControlDelegate() {}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleVolumeMute(const ui::Accelerator& accelerator) OVERRIDE {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleVolumeDown(const ui::Accelerator& accelerator) OVERRIDE {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleVolumeUp(const ui::Accelerator& accelerator) OVERRIDE {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DummyVolumeControlDelegate);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummyBrightnessControlDelegate : public BrightnessControlDelegate,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       public DelegatePercentTracker {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DummyBrightnessControlDelegate() {}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DummyBrightnessControlDelegate() {}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleBrightnessDown(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ui::Accelerator& accelerator) OVERRIDE { return true; }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleBrightnessUp(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ui::Accelerator& accelerator) OVERRIDE { return true; }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetBrightnessPercent(double percent, bool gradual) OVERRIDE {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetPercent(percent);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetBrightnessPercent(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(double)>& callback) OVERRIDE {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(100.0);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResizableWidgetDelegate : public views::WidgetDelegateView {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResizableWidgetDelegate() {}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ResizableWidgetDelegate() {}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool CanResize() const OVERRIDE { return true; }
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool CanMaximize() const OVERRIDE { return true; }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DeleteDelegate() OVERRIDE { delete this; }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ResizableWidgetDelegate);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Support class for testing windows with a maximum size.
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MaxSizeNCFV : public views::NonClientFrameView {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaxSizeNCFV() {}
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::Size GetMaximumSize() OVERRIDE {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Size(200, 200);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::Rect GetBoundsForClientView() const OVERRIDE {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Rect();
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::Rect GetWindowBoundsForClientBounds(
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const gfx::Rect& client_bounds) const OVERRIDE {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Rect();
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This function must ask the ClientView to do a hittest.  We don't do this in
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the parent NonClientView because that makes it more difficult to calculate
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // hittests for regions that are partially obscured by the ClientView, e.g.
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // HTSYSMENU.
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HTNOWHERE;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void GetWindowMask(const gfx::Size& size,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             gfx::Path* window_mask) OVERRIDE {}
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ResetWindowControls() OVERRIDE {}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void UpdateWindowIcon() OVERRIDE {}
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void UpdateWindowTitle() OVERRIDE {}
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MaxSizeNCFV);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MaxSizeWidgetDelegate : public views::WidgetDelegateView {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaxSizeWidgetDelegate() {}
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~MaxSizeWidgetDelegate() {}
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool CanResize() const OVERRIDE { return true; }
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool CanMaximize() const OVERRIDE { return false; }
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void DeleteDelegate() OVERRIDE { delete this; }
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual views::NonClientFrameView* CreateNonClientFrameView(
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      views::Widget* widget) OVERRIDE {
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return new MaxSizeNCFV;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MaxSizeWidgetDelegate);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class SystemGestureEventFilterTest
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : public AshTestBase,
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      public testing::WithParamInterface<bool> {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SystemGestureEventFilterTest() : AshTestBase(), docked_enabled_(GetParam()) {}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SystemGestureEventFilterTest() {}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::LongPressAffordanceHandler* GetLongPressAffordance() {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ShellTestApi shell_test(Shell::GetInstance());
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return shell_test.system_gesture_event_filter()->
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        long_press_affordance_.get();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<internal::LongPressAffordanceHandler>*
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetLongPressAffordanceTimer() {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &GetLongPressAffordance()->timer_;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window* GetLongPressAffordanceTarget() {
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return GetLongPressAffordance()->tap_down_target_;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* GetLongPressAffordanceView() {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<views::View*>(
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetLongPressAffordance()->view_.get());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from AshTestBase:
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine::ForCurrentProcess()->AppendSwitch(
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ash::switches::kAshEnableAdvancedGestures);
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!docked_enabled_) {
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      CommandLine::ForCurrentProcess()->AppendSwitch(
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          ash::switches::kAshDisableDockedWindows);
2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test::AshTestBase::SetUp();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Enable brightness key.
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SetFirstDisplayAsInternalDisplay();
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // true if docked windows are enabled with a flag.
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool docked_enabled_;
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SystemGestureEventFilterTest);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::GestureEvent* CreateGesture(ui::EventType type,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int x,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int y,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    float delta_x,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    float delta_y,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int touch_id) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ui::GestureEvent(type, x, y, 0,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000),
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::GestureEventDetails(type, delta_x, delta_y), 1 << touch_id);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_P(SystemGestureEventFilterTest, LongPressAffordanceStateOnCaptureLoss) {
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::TestWindowDelegate delegate;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window0(
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 9, gfx::Rect(0, 0, 100, 100), root_window));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window1(
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 10, gfx::Rect(0, 0, 100, 50), window0.get()));
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window2(
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 11, gfx::Rect(0, 50, 100, 50), window0.get()));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchId = 5;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Capture first window.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetCapture();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window1->HasCapture());
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send touch event to first window.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       gfx::Point(10, 10),
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       kTouchId,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       ui::EventTimeForNow());
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  root_window->GetDispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      &press);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window1->HasCapture());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<internal::LongPressAffordanceHandler>* timer =
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetLongPressAffordanceTimer();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(timer->IsRunning());
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(window1, GetLongPressAffordanceTarget());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force timeout so that the affordance animation can start.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->user_task().Run();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->Stop();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change capture.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetCapture();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window2->HasCapture());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(window1, GetLongPressAffordanceTarget());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Animate to completion.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetLongPressAffordance()->End();  // end grow animation.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force timeout to start shrink animation.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(timer->IsRunning());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->user_task().Run();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->Stop();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetLongPressAffordance()->End();  // end shrink animation.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if state has reset.
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(NULL, GetLongPressAffordanceTarget());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NULL, GetLongPressAffordanceView());
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_P(SystemGestureEventFilterTest, MultiFingerSwipeGestures) {
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, gfx::Rect(0, 0, 600, 600));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Show();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 15;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchPoints = 4;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point(250, 250),
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point(250, 350),
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point(350, 250),
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point(350, 350)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::EventGenerator generator(root_window,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       toplevel->GetNativeWindow());
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe down to minimize.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* toplevel_state =
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      wm::GetWindowState(toplevel->GetNativeWindow());
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(toplevel_state->IsMinimized());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe up to maximize.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(toplevel_state->IsMaximized());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right to snap.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString());
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe left to snap.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point left_points[kTouchPoints];
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kTouchPoints; ++i) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i] = points[i];
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i].Offset(right_tile_bounds.x(), right_tile_bounds.y());
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      -150, 0);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString());
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right again.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_P(SystemGestureEventFilterTest, TwoFingerDrag) {
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect bounds(0, 0, 600, 600);
3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Show();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 15;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchPoints = 2;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point(250, 250),
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Point(350, 350),
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::EventGenerator generator(root_window,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       toplevel->GetNativeWindow());
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* toplevel_state =
37068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      wm::GetWindowState(toplevel->GetNativeWindow());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe down to minimize.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
37368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(toplevel_state->IsMinimized());
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe up to maximize.
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(toplevel_state->IsMaximized());
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right to snap.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString());
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe left to snap.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point left_points[kTouchPoints];
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kTouchPoints; ++i) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i] = points[i];
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i].Offset(right_tile_bounds.x(), right_tile_bounds.y());
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      -150, 0);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString());
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString());
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right again.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_P(SystemGestureEventFilterTest, TwoFingerDragTwoWindows) {
4111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::GestureConfiguration::set_max_separation_for_gesture_touches_in_pixels(0);
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* first = views::Widget::CreateWindowWithContextAndBounds(
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, gfx::Rect(0, 0, 50, 100));
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first->Show();
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* second = views::Widget::CreateWindowWithContextAndBounds(
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, gfx::Rect(100, 0, 100, 100));
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second->Show();
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start a two-finger drag on |first|, and then try to use another two-finger
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // drag to move |second|. The attempt to move |second| should fail.
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Rect& first_bounds = first->GetWindowBoundsInScreen();
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Rect& second_bounds = second->GetWindowBoundsInScreen();
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kSteps = 15;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kTouchPoints = 4;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Point points[kTouchPoints] = {
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    first_bounds.origin() + gfx::Vector2d(5, 5),
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    first_bounds.origin() + gfx::Vector2d(30, 10),
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    second_bounds.origin() + gfx::Vector2d(5, 5),
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    second_bounds.origin() + gfx::Vector2d(40, 20)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::test::EventGenerator generator(root_window);
4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Do not drag too fast to avoid fling.
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points,
4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      50, kSteps, 0, 150);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_NE(first_bounds.ToString(),
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            first->GetWindowBoundsInScreen().ToString());
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(second_bounds.ToString(),
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            second->GetWindowBoundsInScreen().ToString());
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_P(SystemGestureEventFilterTest, WindowsWithMaxSizeDontSnap) {
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bounds(250, 150, 100, 100);
4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new MaxSizeWidgetDelegate, root_window, bounds);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->Show();
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kSteps = 15;
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kTouchPoints = 2;
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Point points[kTouchPoints] = {
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + 10, bounds.y() + 30),
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + 30, bounds.y() + 20),
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::test::EventGenerator generator(root_window,
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       toplevel->GetNativeWindow());
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Swipe down to minimize.
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
46368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* toplevel_state =
46468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      wm::GetWindowState(toplevel->GetNativeWindow());
46568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(toplevel_state->IsMinimized());
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->Restore();
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that swiping up doesn't maximize.
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
47268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(toplevel_state->IsMaximized());
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->Restore();
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that swiping right doesn't snap.
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds.set_x(normal_bounds.x() + 150);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(normal_bounds.ToString(),
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      toplevel->GetWindowBoundsInScreen().ToString());
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that swiping left doesn't snap.
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds = toplevel->GetWindowBoundsInScreen();
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, -150, 0);
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds.set_x(normal_bounds.x() - 150);
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(normal_bounds.ToString(),
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      toplevel->GetWindowBoundsInScreen().ToString());
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Swipe right again, make sure the window still doesn't snap.
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds = toplevel->GetWindowBoundsInScreen();
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  normal_bounds.set_x(normal_bounds.x() + 150);
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(normal_bounds.ToString(),
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      toplevel->GetWindowBoundsInScreen().ToString());
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_P(SystemGestureEventFilterTest, TwoFingerDragEdge) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds(0, 0, 100, 100);
5051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Show();
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 15;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchPoints = 2;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(30, 20),  // Caption
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(0, 40),   // Left edge
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(HTLEFT, toplevel->GetNativeWindow()->delegate()->
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetNonClientComponent(points[1]));
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::EventGenerator generator(root_window,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       toplevel->GetNativeWindow());
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds = toplevel->GetNativeWindow()->bounds();
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe down. Nothing should happen.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(bounds.ToString(),
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            toplevel->GetNativeWindow()->bounds().ToString());
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_P(SystemGestureEventFilterTest, TwoFingerDragDelayed) {
5311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  gfx::Rect bounds(0, 0, 100, 100);
5321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
5331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
5341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
5351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  toplevel->Show();
5361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kSteps = 15;
5381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kTouchPoints = 2;
5391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
5401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(30, 20),  // Caption
5411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(34, 20),  // Caption
5421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  };
5431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int delays[kTouchPoints] = {0, 120};
5441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
5461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetNonClientComponent(points[0]));
5471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
5481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetNonClientComponent(points[1]));
5491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::test::EventGenerator generator(root_window,
5511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                       toplevel->GetNativeWindow());
5521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds = toplevel->GetNativeWindow()->bounds();
5541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Swipe right and down starting with one finger.
5551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Add another finger after 120ms and continue dragging.
5561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The window should move and the drag should be determined by the center
5571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // point between the fingers.
5581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  generator.GestureMultiFingerScrollWithDelays(
5591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      kTouchPoints, points, delays, 15, kSteps, 150, 150);
5601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds += gfx::Vector2d(150 + (points[1].x() - points[0].x()) / 2, 150);
5611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(bounds.ToString(),
5621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            toplevel->GetNativeWindow()->bounds().ToString());
5631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_P(SystemGestureEventFilterTest, ThreeFingerGestureStopsDrag) {
5661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  gfx::Rect bounds(0, 0, 100, 100);
5671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
5681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
5691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
5701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  toplevel->Show();
5711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kSteps = 10;
5731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kTouchPoints = 3;
5741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
5751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(30, 20),  // Caption
5761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(34, 20),  // Caption
5771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::Point(38, 20),  // Caption
5781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  };
5791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int delays[kTouchPoints] = {0, 0, 120};
5801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
5821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetNonClientComponent(points[0]));
5831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(HTCAPTION, toplevel->GetNativeWindow()->delegate()->
5841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetNonClientComponent(points[1]));
5851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::test::EventGenerator generator(root_window,
5871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                       toplevel->GetNativeWindow());
5881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds = toplevel->GetNativeWindow()->bounds();
5901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Swipe right and down starting with two fingers.
5911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Add third finger after 120ms and continue dragging.
5921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The window should start moving but stop when the 3rd finger touches down.
5931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kEventSeparation = 15;
5941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  generator.GestureMultiFingerScrollWithDelays(
5951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      kTouchPoints, points, delays, kEventSeparation, kSteps, 150, 150);
5961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int expected_drag = 150 / kSteps * 120 / kEventSeparation;
5971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds += gfx::Vector2d(expected_drag, expected_drag);
5981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(bounds.ToString(),
5991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            toplevel->GetNativeWindow()->bounds().ToString());
6001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
6011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_P(SystemGestureEventFilterTest, DragLeftNearEdgeSnaps) {
603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bounds(200, 150, 400, 100);
604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  toplevel->Show();
608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kSteps = 15;
610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kTouchPoints = 2;
611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point points[kTouchPoints] = {
612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::test::EventGenerator generator(root_window,
616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       toplevel->GetNativeWindow());
617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Check that dragging left snaps before reaching the screen edge.
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect work_area =
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      Shell::GetScreen()->GetDisplayNearestWindow(root_window).work_area();
621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int drag_x = work_area.x() + 20 - points[0].x();
622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  generator.GestureMultiFingerScroll(
623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kTouchPoints, points, 120, kSteps, drag_x, 0);
624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  internal::SnapSizer snap_sizer(
626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      wm::GetWindowState(toplevel->GetNativeWindow()),
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      gfx::Point(),
628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      internal::SnapSizer::LEFT_EDGE,
629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      internal::SnapSizer::OTHER_INPUT);
630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect expected_bounds(snap_sizer.target_bounds());
631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(expected_bounds.ToString(),
632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            toplevel->GetWindowBoundsInScreen().ToString());
633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_P(SystemGestureEventFilterTest, DragRightNearEdgeSnaps) {
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bounds(200, 150, 400, 100);
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window* root_window = Shell::GetPrimaryRootWindow();
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithContextAndBounds(
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new ResizableWidgetDelegate, root_window, bounds);
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  toplevel->Show();
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kSteps = 15;
643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kTouchPoints = 2;
644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point points[kTouchPoints] = {
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::test::EventGenerator generator(root_window,
649f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       toplevel->GetNativeWindow());
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
651f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Check that dragging right snaps before reaching the screen edge.
652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect work_area =
653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      Shell::GetScreen()->GetDisplayNearestWindow(root_window).work_area();
654f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int drag_x = work_area.right() - 20 - points[0].x();
655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  generator.GestureMultiFingerScroll(
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kTouchPoints, points, 120, kSteps, drag_x, 0);
657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  internal::SnapSizer snap_sizer(
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      wm::GetWindowState(toplevel->GetNativeWindow()),
659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      gfx::Point(),
660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      internal::SnapSizer::RIGHT_EDGE,
661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      internal::SnapSizer::OTHER_INPUT);
662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect expected_bounds(snap_sizer.target_bounds());
663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(expected_bounds.ToString(),
664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            toplevel->GetWindowBoundsInScreen().ToString());
665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Tests run twice - with docked windows disabled or enabled.
6681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(DockedWindowsDisabledOrEnabled,
6691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                        SystemGestureEventFilterTest,
6701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                        testing::Bool());
6711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace test
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
674