system_gesture_event_filter_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/multi_display_manager.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/launcher/launcher.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/launcher/launcher_model.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/brightness/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"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/test/test_launcher_delegate.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/volume_control_delegate.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/gestures/long_press_affordance_handler.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/timer.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/env.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/event_generator.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/test_windows.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/events/event.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ui_base_switches.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace test {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DelegatePercentTracker {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DelegatePercentTracker()
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : handle_percent_count_(0),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handle_percent_(0){
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int handle_percent_count() const {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return handle_percent_count_;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double handle_percent() const {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return handle_percent_;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetPercent(double percent) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handle_percent_ = percent;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handle_percent_count_++;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int handle_percent_count_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int handle_percent_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DelegatePercentTracker);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummyVolumeControlDelegate : public VolumeControlDelegate,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   public DelegatePercentTracker {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DummyVolumeControlDelegate() {}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DummyVolumeControlDelegate() {}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleVolumeMute(const ui::Accelerator& accelerator) OVERRIDE {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleVolumeDown(const ui::Accelerator& accelerator) OVERRIDE {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleVolumeUp(const ui::Accelerator& accelerator) OVERRIDE {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetVolumePercent(double percent) OVERRIDE {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetPercent(percent);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsAudioMuted() const OVERRIDE {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetAudioMuted(bool muted) OVERRIDE {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual float GetVolumeLevel() const OVERRIDE {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0.0;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetVolumeLevel(float level) OVERRIDE {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DummyVolumeControlDelegate);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummyBrightnessControlDelegate : public BrightnessControlDelegate,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       public DelegatePercentTracker {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DummyBrightnessControlDelegate() {}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DummyBrightnessControlDelegate() {}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleBrightnessDown(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ui::Accelerator& accelerator) OVERRIDE { return true; }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleBrightnessUp(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ui::Accelerator& accelerator) OVERRIDE { return true; }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetBrightnessPercent(double percent, bool gradual) OVERRIDE {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetPercent(percent);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetBrightnessPercent(
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(double)>& callback) OVERRIDE {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(100.0);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResizableWidgetDelegate : public views::WidgetDelegateView {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResizableWidgetDelegate() {}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ResizableWidgetDelegate() {}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool CanResize() const OVERRIDE { return true; }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DeleteDelegate() OVERRIDE { delete this; }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ResizableWidgetDelegate);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SystemGestureEventFilterTest : public AshTestBase {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SystemGestureEventFilterTest() : AshTestBase() {}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SystemGestureEventFilterTest() {}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::LongPressAffordanceHandler* GetLongPressAffordance() {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Shell::TestApi shell_test(Shell::GetInstance());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return shell_test.system_gesture_event_filter()->
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        long_press_affordance_.get();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<internal::LongPressAffordanceHandler>*
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetLongPressAffordanceTimer() {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &GetLongPressAffordance()->timer_;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetLongPressAffordanceTouchId() {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetLongPressAffordance()->tap_down_touch_id_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* GetLongPressAffordanceView() {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<views::View*>(
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetLongPressAffordance()->view_.get());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from AshTestBase:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine::ForCurrentProcess()->AppendSwitch(
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ash::switches::kAshEnableAdvancedGestures);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine::ForCurrentProcess()->AppendSwitch(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ::switches::kEnableBezelTouch);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test::AshTestBase::SetUp();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Enable brightness key.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static_cast<internal::MultiDisplayManager*>(
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aura::Env::GetInstance()->display_manager())->
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetFirstDisplayAsInternalDisplayForTest();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SystemGestureEventFilterTest);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::GestureEvent* CreateGesture(ui::EventType type,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int x,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int y,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    float delta_x,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    float delta_y,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int touch_id) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ui::GestureEvent(type, x, y, 0,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000),
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::GestureEventDetails(type, delta_x, delta_y), 1 << touch_id);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure that events targeted at the root window are consumed by the
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// system event handler.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, TapOutsideRootWindow) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shell::TestApi shell_test(Shell::GetInstance());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchId = 5;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A touch outside the root window will be associated with the root window
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(-10, -10), kTouchId,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::NowFromSystemTime() - base::Time());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::GestureEvent> event(CreateGesture(
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::ET_GESTURE_TAP, 0, 0, 0, 0, kTouchId));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool consumed = root_window->DispatchGestureEvent(event.get());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(consumed);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Without the event filter, the touch shouldn't be consumed by the
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // system event handler.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shell::GetInstance()->RemoveEnvEventFilter(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shell_test.system_gesture_event_filter());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::GestureEvent> event2(CreateGesture(
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::ET_GESTURE_TAP, 0, 0, 0, 0, kTouchId));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  consumed = root_window->DispatchGestureEvent(event2.get());
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The event filter doesn't exist, so the touch won't be consumed.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(consumed);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MoveToDeviceControlBezelStartPosition(
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::RootWindow* root_window,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelegatePercentTracker* delegate,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double expected_value,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int xpos,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ypos,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ypos_half,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int touch_id) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get a target for kTouchId
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::TouchEvent press1(ui::ET_TOUCH_PRESSED,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        gfx::Point(-10, ypos + ypos_half),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        touch_id,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        base::Time::NowFromSystemTime() - base::Time());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is a noise filter which will require several calls before it
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allows the touch event through.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int initial_count = delegate->handle_percent_count();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Position the initial touch down slightly underneath the position of
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // interest to avoid a conflict with the noise filter.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::GestureEvent> event1(CreateGesture(
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::ET_GESTURE_SCROLL_BEGIN, xpos, ypos + ypos_half - 10,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, 0, touch_id));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool consumed = root_window->DispatchGestureEvent(event1.get());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(consumed);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(initial_count, delegate->handle_percent_count());
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No move at the beginning will produce no events.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::GestureEvent> event2(CreateGesture(
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::ET_GESTURE_SCROLL_UPDATE,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xpos, ypos + ypos_half - 10, 0, 0, touch_id));
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  consumed = root_window->DispatchGestureEvent(event2.get());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(consumed);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(initial_count, delegate->handle_percent_count());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A move to a new Y location will produce an event.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::GestureEvent> event3(CreateGesture(
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::ET_GESTURE_SCROLL_UPDATE, xpos, ypos + ypos_half,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, 10, touch_id));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = initial_count;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int loop_counter = 0;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (count == initial_count && loop_counter++ < 100) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(root_window->DispatchGestureEvent(event3.get()));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = delegate->handle_percent_count();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(loop_counter && loop_counter < 100);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(initial_count + 1, count);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(expected_value, delegate->handle_percent());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure that the device control operation gets properly handled.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, DeviceControl) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect screen = Shell::GetScreen()->GetPrimaryDisplay().bounds();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ypos_half = screen.height() / 2;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ash::AcceleratorController* accelerator =
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ash::Shell::GetInstance()->accelerator_controller();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DummyBrightnessControlDelegate* delegateBrightness =
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DummyBrightnessControlDelegate();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  accelerator->SetBrightnessControlDelegate(
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<BrightnessControlDelegate>(delegateBrightness).Pass());
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DummyVolumeControlDelegate* delegateVolume =
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DummyVolumeControlDelegate();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ash::Shell::GetInstance()->tray_delegate()->SetVolumeControlDelegate(
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<VolumeControlDelegate>(delegateVolume).Pass());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchId = 5;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int pass = 0; pass < 2; pass++) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelegatePercentTracker* delegate =
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<DelegatePercentTracker*>(delegateBrightness);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int xpos = screen.x() - 10;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int invalid_xpos_direction = 1;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ypos = screen.y();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The expected (middle) value. Note that brightness (first pass) is
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // slightly higher then 50% since its slider range is 4%..100%.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double value = 52.0;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pass) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // On the second pass the volume will be tested.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate = static_cast<DelegatePercentTracker*>(delegateVolume);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xpos = screen.right() + 10;  // Make sure it is out of the screen.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      invalid_xpos_direction = -1;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value = 50.0;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MoveToDeviceControlBezelStartPosition(
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        root_window, delegate, value, xpos, ypos, ypos_half, kTouchId);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A move towards the screen is fine as long as we do not go inside it.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event4(CreateGesture(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_UPDATE,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xpos + invalid_xpos_direction,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ypos + ypos_half,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        invalid_xpos_direction, 0, kTouchId));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool consumed = root_window->DispatchGestureEvent(event4.get());
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2, delegate->handle_percent_count());
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A move into the screen will cancel the gesture.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event5(CreateGesture(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_UPDATE,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xpos + 20 * invalid_xpos_direction,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ypos + ypos_half,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        20 * invalid_xpos_direction, 0, kTouchId));
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumed = root_window->DispatchGestureEvent(event5.get());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2, delegate->handle_percent_count());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Finishing the gesture should not change anything.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event6(CreateGesture(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_END, xpos, ypos + ypos_half,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0, 0, kTouchId));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumed = root_window->DispatchGestureEvent(event6.get());
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2, delegate->handle_percent_count());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Another event after this one should get ignored.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event7(CreateGesture(
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_UPDATE, xpos, ypos_half,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0, 0, kTouchId));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumed = root_window->DispatchGestureEvent(event7.get());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(2, delegate->handle_percent_count());
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::TouchEvent release(
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_TOUCH_RELEASED, gfx::Point(2 * xpos, ypos + ypos_half), kTouchId,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Time::NowFromSystemTime() - base::Time());
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that huge changes will be interpreted as noise as well.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MoveToDeviceControlBezelStartPosition(
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        root_window, delegate, value, xpos, ypos, ypos_half, kTouchId);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note: The counter is with this call at 3.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event8(CreateGesture(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_UPDATE, xpos, ypos / 10,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0, ypos / 10 - ypos, kTouchId));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumed = root_window->DispatchGestureEvent(event8.get());
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(3, delegate->handle_percent_count());
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Release the system.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure that the application control operations gets properly handled.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, ApplicationControl) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect screen = Shell::GetScreen()->GetPrimaryDisplay().bounds();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ypos_half = screen.height() / 2;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::TestWindowDelegate delegate;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window0(
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 9, gfx::Rect(0, 0, 100, 100), root_window));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window1(
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 10, gfx::Rect(0, 0, 100, 100), window0.get()));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window2(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 11, gfx::Rect(0, 0, 100, 100), window0.get()));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchId = 5;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int pass = 0; pass < 2; pass++) {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add the launcher items and make sure the first item is the active one.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestLauncherDelegate::instance()->AddLauncherItem(window1.get(),
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      ash::STATUS_ACTIVE);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestLauncherDelegate::instance()->AddLauncherItem(window2.get(),
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      ash::STATUS_RUNNING);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ash::wm::ActivateWindow(window1.get());
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int xpos = screen.x() - 10;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int delta_x = 100;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ypos = screen.y();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pass) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xpos = screen.right() + 40;  // Make sure the touch is out of the screen.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta_x = -100;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::Window* active_window = ash::wm::GetActiveWindow();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Get a target for kTouchId
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             gfx::Point(-10, ypos + ypos_half),
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kTouchId,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base::Time::NowFromSystemTime() - base::Time());
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event1(CreateGesture(
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_BEGIN, xpos, ypos,
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0, 0, kTouchId));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool consumed = root_window->DispatchGestureEvent(event1.get());
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ash::wm::GetActiveWindow(), active_window);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No move at the beginning will produce no events.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event2(CreateGesture(
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_UPDATE,
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xpos, ypos, 0, 0, kTouchId));
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumed = root_window->DispatchGestureEvent(event2.get());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ash::wm::GetActiveWindow(), active_window);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A move further to the outside will not trigger an action.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event3(CreateGesture(
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_UPDATE, xpos - delta_x, ypos,
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        -delta_x, 0, kTouchId));
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumed = root_window->DispatchGestureEvent(event3.get());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ash::wm::GetActiveWindow(), active_window);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A move to the proper side will trigger an action.
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent> event4(CreateGesture(
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_UPDATE, xpos + delta_x, ypos,
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        2 * delta_x, 0, kTouchId));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumed = root_window->DispatchGestureEvent(event4.get());
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(ash::wm::GetActiveWindow(), active_window);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_window = ash::wm::GetActiveWindow();
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A second move to the proper side will not trigger an action.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ui::GestureEvent>  event5(CreateGesture(
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_GESTURE_SCROLL_UPDATE, xpos + 2 * delta_x, ypos,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delta_x, 0, kTouchId));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumed = root_window->DispatchGestureEvent(event5.get());
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumed);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ash::wm::GetActiveWindow(), active_window);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::TouchEvent release(
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::ET_TOUCH_RELEASED, gfx::Point(2 * xpos, ypos + ypos_half), kTouchId,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Time::NowFromSystemTime() - base::Time());
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove the launcher items again.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestLauncherDelegate::instance()->OnWillRemoveWindow(window1.get());
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestLauncherDelegate::instance()->OnWillRemoveWindow(window2.get());
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, LongPressAffordanceStateOnCaptureLoss) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::TestWindowDelegate delegate;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window0(
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 9, gfx::Rect(0, 0, 100, 100), root_window));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window1(
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 10, gfx::Rect(0, 0, 100, 50), window0.get()));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<aura::Window> window2(
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &delegate, 11, gfx::Rect(0, 50, 100, 50), window0.get()));
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchId = 5;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Capture first window.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetCapture();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window1->HasCapture());
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send touch event to first window.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), kTouchId,
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::NowFromSystemTime() - base::Time());
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window1->HasCapture());
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<internal::LongPressAffordanceHandler>* timer =
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetLongPressAffordanceTimer();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(timer->IsRunning());
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kTouchId, GetLongPressAffordanceTouchId());
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force timeout so that the affordance animation can start.
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->user_task().Run();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->Stop();
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change capture.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetCapture();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window2->HasCapture());
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kTouchId, GetLongPressAffordanceTouchId());
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Animate to completion.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetLongPressAffordance()->End();  // end grow animation.
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force timeout to start shrink animation.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(timer->IsRunning());
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->user_task().Run();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer->Stop();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetLongPressAffordance()->is_animating());
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetLongPressAffordance()->End();  // end shrink animation.
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if state has reset.
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-1, GetLongPressAffordanceTouchId());
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NULL, GetLongPressAffordanceView());
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, MultiFingerSwipeGestures) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithBounds(
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ResizableWidgetDelegate, gfx::Rect(0, 0, 100, 100));
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Show();
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 15;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchPoints = 4;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(10, 30),
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(30, 20),
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(50, 30),
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(80, 50)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::EventGenerator generator(root_window,
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       toplevel->GetNativeWindow());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe down to minimize.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wm::IsWindowMinimized(toplevel->GetNativeWindow()));
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe up to maximize.
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wm::IsWindowMaximized(toplevel->GetNativeWindow()));
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right to snap.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen();
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString());
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe left to snap.
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point left_points[kTouchPoints];
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kTouchPoints; ++i) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i] = points[i];
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i].Offset(right_tile_bounds.x(), right_tile_bounds.y());
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps,
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      -150, 0);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen();
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString());
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right again.
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen();
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString());
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString());
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, TwoFingerDrag) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds(0, 0, 100, 100);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithBounds(
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ResizableWidgetDelegate, bounds);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Show();
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 15;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchPoints = 2;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(10, 30),
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(30, 20),
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::EventGenerator generator(root_window,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       toplevel->GetNativeWindow());
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe down to minimize.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wm::IsWindowMinimized(toplevel->GetNativeWindow()));
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe up to maximize.
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, -150);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wm::IsWindowMaximized(toplevel->GetNativeWindow()));
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Restore();
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->GetNativeWindow()->SetBounds(bounds);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right to snap.
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen();
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString());
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe left to snap.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point left_points[kTouchPoints];
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kTouchPoints; ++i) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i] = points[i];
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    left_points[i].Offset(right_tile_bounds.x(), right_tile_bounds.y());
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps,
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      -150, 0);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen();
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString());
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString());
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe right again.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 150, 0);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen();
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString());
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SystemGestureEventFilterTest, TwoFingerDragEdge) {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds(0, 0, 100, 100);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Widget* toplevel = views::Widget::CreateWindowWithBounds(
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ResizableWidgetDelegate, bounds);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  toplevel->Show();
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 15;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTouchPoints = 2;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point points[kTouchPoints] = {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(30, 20),  // Caption
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point(0, 40),   // Left edge
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(HTLEFT, toplevel->GetNativeWindow()->delegate()->
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetNonClientComponent(points[1]));
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::test::EventGenerator generator(root_window,
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       toplevel->GetNativeWindow());
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds = toplevel->GetNativeWindow()->bounds();
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Swipe down. Nothing should happen.
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.GestureMultiFingerScroll(kTouchPoints, points, 15, kSteps, 0, 150);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(bounds.ToString(),
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            toplevel->GetNativeWindow()->bounds().ToString());
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace test
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
674