Index: ui/aura/gestures/gesture_recognizer_grail_unittest.cc |
=================================================================== |
--- ui/aura/gestures/gesture_recognizer_grail_unittest.cc (revision 0) |
+++ ui/aura/gestures/gesture_recognizer_grail_unittest.cc (revision 0) |
@@ -0,0 +1,581 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/at_exit.h" |
+#include "base/message_loop.h" |
+#include "base/timer.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/xorg-gtest/include/xorg/gtest/environment.h" |
+#include "third_party/xorg-gtest/include/xorg/gtest/evemu/device.h" |
+#include "third_party/xorg-gtest/include/xorg/gtest/test.h" |
+#include "ui/aura/event.h" |
+#include "ui/aura/gestures/gesture_recognizer_grail.h" |
+#include "ui/aura/root_window.h" |
+#include "ui/aura/test/aura_test_base.h" |
+#include "ui/aura/test/test_stacking_client.h" |
+#include "ui/aura/test/test_window_delegate.h" |
+#include "ui/aura/test/test_windows.h" |
+#include "ui/base/hit_test.h" |
+#include "ui/gfx/point.h" |
+#include "ui/gfx/rect.h" |
+ |
+// Starts and sets up a dummy (read: headless) xserver on display port 133. |
+// Log of the server can be found at /tmp/Xorg.GTest.log. |
+::testing::Environment* const foo_env = |
+ ::testing::AddGlobalTestEnvironment(new ::xorg::testing::Environment()); |
+ |
+namespace aura { |
+namespace test { |
+ |
+namespace { |
+ |
+// A delegate that keeps track of gesture events. |
+class GestureEventConsumeDelegate : public TestWindowDelegate { |
+ public: |
+ GestureEventConsumeDelegate() |
+ : tap_(false), |
+ tap_down_(false), |
+ double_tap_(false), |
+ scroll_begin_(false), |
+ scroll_update_(false), |
+ scroll_end_(false), |
+ pinch_begin_(false), |
+ pinch_update_(false), |
+ pinch_end_(false), |
+ long_press_(false), |
+ scroll_x_(0), |
+ scroll_y_(0), |
+ velocity_x_(0), |
+ velocity_y_(0) { |
+ } |
+ |
+ virtual ~GestureEventConsumeDelegate() {} |
+ |
+ void Reset() { |
+ tap_ = false; |
+ tap_down_ = false; |
+ double_tap_ = false; |
+ scroll_begin_ = false; |
+ scroll_update_ = false; |
+ scroll_end_ = false; |
+ pinch_begin_ = false; |
+ pinch_update_ = false; |
+ pinch_end_ = false; |
+ long_press_ = false; |
+ |
+ scroll_begin_position_.SetPoint(0, 0); |
+ |
+ scroll_x_ = 0; |
+ scroll_y_ = 0; |
+ velocity_x_ = 0; |
+ velocity_y_ = 0; |
+ } |
+ |
+ bool tap() const { return tap_; } |
+ bool tap_down() const { return tap_down_; } |
+ bool double_tap() const { return double_tap_; } |
+ bool scroll_begin() const { return scroll_begin_; } |
+ bool scroll_update() const { return scroll_update_; } |
+ bool scroll_end() const { return scroll_end_; } |
+ bool pinch_begin() const { return pinch_begin_; } |
+ bool pinch_update() const { return pinch_update_; } |
+ bool pinch_end() const { return pinch_end_; } |
+ bool long_press() const { return long_press_; } |
+ |
+ const gfx::Point scroll_begin_position() const { |
+ return scroll_begin_position_; |
+ } |
+ |
+ float scroll_x() const { return scroll_x_; } |
+ float scroll_y() const { return scroll_y_; } |
+ int touch_id() const { return touch_id_; } |
+ float velocity_x() const { return velocity_x_; } |
+ float velocity_y() const { return velocity_y_; } |
+ |
+ virtual ui::GestureStatus OnGestureEvent(GestureEvent* gesture) OVERRIDE { |
+ switch (gesture->type()) { |
+ case ui::ET_GESTURE_TAP: |
+ tap_ = true; |
+ break; |
+ case ui::ET_GESTURE_TAP_DOWN: |
+ tap_down_ = true; |
+ break; |
+ case ui::ET_GESTURE_DOUBLE_TAP: |
+ double_tap_ = true; |
+ break; |
+ case ui::ET_GESTURE_SCROLL_BEGIN: |
+ scroll_begin_ = true; |
+ scroll_begin_position_ = gesture->location(); |
+ break; |
+ case ui::ET_GESTURE_SCROLL_UPDATE: |
+ scroll_update_ = true; |
+ scroll_x_ += gesture->delta_x(); |
+ scroll_y_ += gesture->delta_y(); |
+ break; |
+ case ui::ET_GESTURE_SCROLL_END: |
+ velocity_x_ = gesture->delta_x(); |
+ velocity_y_ = gesture->delta_y(); |
+ scroll_end_ = true; |
+ break; |
+ case ui::ET_GESTURE_PINCH_BEGIN: |
+ pinch_begin_ = true; |
+ break; |
+ case ui::ET_GESTURE_PINCH_UPDATE: |
+ pinch_update_ = true; |
+ break; |
+ case ui::ET_GESTURE_PINCH_END: |
+ pinch_end_ = true; |
+ break; |
+ case ui::ET_GESTURE_LONG_PRESS: |
+ long_press_ = true; |
+ touch_id_ = gesture->point_id(); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ return ui::GESTURE_STATUS_CONSUMED; |
+ } |
+ |
+ private: |
+ bool tap_; |
+ bool tap_down_; |
+ bool double_tap_; |
+ bool scroll_begin_; |
+ bool scroll_update_; |
+ bool scroll_end_; |
+ bool pinch_begin_; |
+ bool pinch_update_; |
+ bool pinch_end_; |
+ bool long_press_; |
+ |
+ gfx::Point scroll_begin_position_; |
+ |
+ float scroll_x_; |
+ float scroll_y_; |
+ float velocity_x_; |
+ float velocity_y_; |
+ int touch_id_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GestureEventConsumeDelegate); |
+}; |
+ |
+// A delegate that ignores gesture events but keeps track of [synthetic] mouse |
+// events. |
+class GestureEventSynthDelegate : public TestWindowDelegate { |
+ public: |
+ GestureEventSynthDelegate() |
+ : mouse_enter_(false), |
+ mouse_exit_(false), |
+ mouse_press_(false), |
+ mouse_release_(false), |
+ mouse_move_(false), |
+ double_click_(false) { |
+ } |
+ |
+ void Reset() { |
+ mouse_enter_ = false; |
+ mouse_exit_ = false; |
+ mouse_press_ = false; |
+ mouse_release_ = false; |
+ mouse_move_ = false; |
+ double_click_ = false; |
+ } |
+ |
+ bool mouse_enter() const { return mouse_enter_; } |
+ bool mouse_exit() const { return mouse_exit_; } |
+ bool mouse_press() const { return mouse_press_; } |
+ bool mouse_move() const { return mouse_move_; } |
+ bool mouse_release() const { return mouse_release_; } |
+ bool double_click() const { return double_click_; } |
+ |
+ virtual bool OnMouseEvent(MouseEvent* event) OVERRIDE { |
+ switch (event->type()) { |
+ case ui::ET_MOUSE_PRESSED: |
+ double_click_ = event->flags() & ui::EF_IS_DOUBLE_CLICK; |
+ mouse_press_ = true; |
+ break; |
+ case ui::ET_MOUSE_RELEASED: |
+ mouse_release_ = true; |
+ break; |
+ case ui::ET_MOUSE_MOVED: |
+ mouse_move_ = true; |
+ break; |
+ case ui::ET_MOUSE_ENTERED: |
+ mouse_enter_ = true; |
+ break; |
+ case ui::ET_MOUSE_EXITED: |
+ mouse_exit_ = true; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ return true; |
+ } |
+ |
+ private: |
+ bool mouse_enter_; |
+ bool mouse_exit_; |
+ bool mouse_press_; |
+ bool mouse_release_; |
+ bool mouse_move_; |
+ bool double_click_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GestureEventSynthDelegate); |
+}; |
+ |
+// Establishes a connection to an existing (dummy) xserver, |
+// and initializes an aura root window. A device is created and |
+// set up to replay sequences of touches from different devices. |
+// The template-argument DeviceType is a means for injecting |
+// paths to touch-sequence recordings in a device-dependent manner. |
+template<typename DeviceType> |
+class GestureRecognizerGrailTest : public xorg::testing::Test { |
+ public: |
+ GestureRecognizerGrailTest() |
+ : device_(DeviceType::DeviceFilePath()) { |
+ } |
+ |
+ virtual ~GestureRecognizerGrailTest() {} |
+ |
+ protected: |
+ void RunAllPendingInMessageLoop() { |
+ helper_.RunAllPendingInMessageLoop(root_window()); |
+ } |
+ |
+ RootWindow * root_window() { |
+ return root_window_.get(); |
+ } |
+ |
+ virtual void SetUp() OVERRIDE { |
+ xorg::testing::Test::SetUp(); |
+ root_window_.reset(new aura::RootWindow); |
+ helper_.InitRootWindow(root_window()); |
+ helper_.SetUp(); |
+ stacking_client_.reset(new TestStackingClient(root_window())); |
+ |
+ // Issue an inital touch to make sure that everything is setup correctly. |
+ TouchEvent touchev(ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0); |
+ root_window()->DispatchTouchEvent(&touchev); |
+ } |
+ |
+ virtual void TearDown() OVERRIDE { |
+ // Flush the message loop because we have pending release tasks |
+ // and these tasks if un-executed would upset Valgrind. |
+ RunAllPendingInMessageLoop(); |
+ |
+ stacking_client_.reset(); |
+ helper_.TearDown(); |
+ root_window_.reset(); |
+ |
+ xorg::testing::Test::TearDown(); |
+ } |
+ |
+ base::AtExitManager exit_manager_; |
+ AuraTestHelper helper_; |
+ scoped_ptr<RootWindow> root_window_; |
+ scoped_ptr<TestStackingClient> stacking_client_; |
+ ::xorg::testing::evemu::Device device_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GestureRecognizerGrailTest); |
+}; |
+ |
+// Model of DeviceType summarizing paths to |
+// touch-sequences recorded with an apple magic trackpad. |
+struct Trackpad { |
+ static const char * DeviceFilePath() { |
+ return "apple_magic_trackpad/device.prop"; |
+ } |
+ |
+ static const char * OneFingerTapRecording() { |
+ return "apple_magic_trackpad/one_finger_tap.record"; |
+ } |
+ |
+ static const char * TwoFingerTapRecording() { |
+ return "apple_magic_trackpad/two_finger_tap.record"; |
+ } |
+ |
+ static const char * OneFingerLongPressRecording() { |
+ return "apple_magic_trackpad/one_finger_long_press.record"; |
+ } |
+ |
+ static const char * TwoFingerLongPressRecording() { |
+ return "apple_magic_trackpad/two_finger_long_press.record"; |
+ } |
+ |
+ static const char * OneFingerDoubleTapRecording() { |
+ return "apple_magic_trackpad/one_finger_double_tap.record"; |
+ } |
+ |
+ static const char * TwoFingerDoubleTapRecording() { |
+ return "apple_magic_trackpad/two_finger_double_tap.record"; |
+ } |
+ |
+ static const char * TwoFingerDragRecording() { |
+ return "apple_magic_trackpad/two_finger_drag.record"; |
+ } |
+ |
+ static const char * TwoFingerPinchRecording() { |
+ return "apple_magic_trackpad/two_finger_pinch.record"; |
+ } |
+}; |
+ |
+// Model of DeviceType summarizing paths to |
+// touch-sequences recorded on a dell touch screen. |
+// |
+// TODO(tvoss): Add required files here. |
+struct TouchScreen { |
+ static const char * DeviceFilePath() { |
+ return "ntrig_dell_xt2/device.prop"; |
+ } |
+}; |
+ |
+} // namespace |
+ |
+typedef AuraTestBase GestureRecognizerTest; |
+ |
+typedef GestureRecognizerGrailTest<Trackpad> TrackpadTest; |
+ |
+// Check that appropriate touch events generate tap gesture events. |
+TEST_F(TrackpadTest, GestureEventOneFingerTap) { |
+ scoped_ptr<GestureEventConsumeDelegate> delegate( |
+ new GestureEventConsumeDelegate()); |
+ const int kWindowWidth = 1280; |
+ const int kWindowHeight = 800; |
+ |
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); |
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
+ delegate.get(), 0, bounds, root_window())); |
+ |
+ delegate->Reset(); |
+ |
+ device_.Play(Trackpad::OneFingerTapRecording()); |
+ RunAllPendingInMessageLoop(); |
+ |
+ EXPECT_TRUE(delegate->tap()); |
+ EXPECT_FALSE(delegate->tap_down()); |
+ EXPECT_FALSE(delegate->double_tap()); |
+ EXPECT_FALSE(delegate->scroll_begin()); |
+ EXPECT_FALSE(delegate->scroll_update()); |
+ EXPECT_FALSE(delegate->scroll_end()); |
+ EXPECT_FALSE(delegate->pinch_begin()); |
+ EXPECT_FALSE(delegate->pinch_update()); |
+ EXPECT_FALSE(delegate->pinch_end()); |
+ EXPECT_FALSE(delegate->long_press()); |
+ |
+ delegate->Reset(); |
+} |
+ |
+// Check that appropriate touch events generate tap gesture events. |
+TEST_F(TrackpadTest, GestureEventTwoFingerTap) { |
+ scoped_ptr<GestureEventConsumeDelegate> delegate( |
+ new GestureEventConsumeDelegate()); |
+ const int kWindowWidth = 1280; |
+ const int kWindowHeight = 800; |
+ |
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); |
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
+ delegate.get(), -1234, bounds, NULL)); |
+ |
+ delegate->Reset(); |
+ |
+ device_.Play(Trackpad::TwoFingerTapRecording()); |
+ RunAllPendingInMessageLoop(); |
+ |
+ EXPECT_TRUE(delegate->tap()); |
+ EXPECT_FALSE(delegate->tap_down()); |
+ EXPECT_FALSE(delegate->double_tap()); |
+ EXPECT_FALSE(delegate->scroll_begin()); |
+ EXPECT_FALSE(delegate->scroll_update()); |
+ EXPECT_FALSE(delegate->scroll_end()); |
+ EXPECT_FALSE(delegate->pinch_begin()); |
+ EXPECT_FALSE(delegate->pinch_update()); |
+ EXPECT_FALSE(delegate->pinch_end()); |
+ EXPECT_FALSE(delegate->long_press()); |
+ |
+ delegate->Reset(); |
+} |
+ |
+// Check that appropriate touch events generate long-press gesture events. |
+TEST_F(TrackpadTest, GestureEventOneFingerLongPress) { |
+ scoped_ptr<GestureEventConsumeDelegate> delegate( |
+ new GestureEventConsumeDelegate()); |
+ const int kWindowWidth = 1280; |
+ const int kWindowHeight = 800; |
+ |
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); |
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
+ delegate.get(), -1234, bounds, NULL)); |
+ |
+ delegate->Reset(); |
+ |
+ device_.Play(Trackpad::OneFingerLongPressRecording()); |
+ RunAllPendingInMessageLoop(); |
+ |
+ EXPECT_FALSE(delegate->tap()); |
+ EXPECT_FALSE(delegate->tap_down()); |
+ EXPECT_FALSE(delegate->double_tap()); |
+ EXPECT_FALSE(delegate->scroll_begin()); |
+ EXPECT_FALSE(delegate->scroll_update()); |
+ EXPECT_FALSE(delegate->scroll_end()); |
+ EXPECT_FALSE(delegate->pinch_begin()); |
+ EXPECT_FALSE(delegate->pinch_update()); |
+ EXPECT_FALSE(delegate->pinch_end()); |
+ EXPECT_TRUE(delegate->long_press()); |
+ |
+ delegate->Reset(); |
+} |
+ |
+// Check that appropriate touch events generate long-press gesture events. |
+TEST_F(TrackpadTest, GestureEventTwoFingerLongPress) { |
+ scoped_ptr<GestureEventConsumeDelegate> delegate( |
+ new GestureEventConsumeDelegate()); |
+ const int kWindowWidth = 1280; |
+ const int kWindowHeight = 800; |
+ |
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); |
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
+ delegate.get(), -1234, bounds, NULL)); |
+ |
+ delegate->Reset(); |
+ |
+ device_.Play(Trackpad::TwoFingerLongPressRecording()); |
+ RunAllPendingInMessageLoop(); |
+ |
+ EXPECT_FALSE(delegate->tap()); |
+ EXPECT_FALSE(delegate->tap_down()); |
+ EXPECT_FALSE(delegate->double_tap()); |
+ EXPECT_FALSE(delegate->scroll_begin()); |
+ EXPECT_FALSE(delegate->scroll_update()); |
+ EXPECT_FALSE(delegate->scroll_end()); |
+ EXPECT_FALSE(delegate->pinch_begin()); |
+ EXPECT_FALSE(delegate->pinch_update()); |
+ EXPECT_FALSE(delegate->pinch_end()); |
+ EXPECT_TRUE(delegate->long_press()); |
+ |
+ delegate->Reset(); |
+} |
+ |
+// Check that appropriate touch events generate double tap gesture events. |
+TEST_F(TrackpadTest, GestureEventOneFingerDoubleTap) { |
+ scoped_ptr<GestureEventConsumeDelegate> delegate( |
+ new GestureEventConsumeDelegate()); |
+ const int kWindowWidth = 1280; |
+ const int kWindowHeight = 800; |
+ |
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); |
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
+ delegate.get(), -1234, bounds, NULL)); |
+ |
+ delegate->Reset(); |
+ |
+ device_.Play(Trackpad::OneFingerDoubleTapRecording()); |
+ RunAllPendingInMessageLoop(); |
+ |
+ EXPECT_TRUE(delegate->tap()); |
+ EXPECT_FALSE(delegate->tap_down()); |
+ EXPECT_TRUE(delegate->double_tap()); |
+ EXPECT_FALSE(delegate->scroll_begin()); |
+ EXPECT_FALSE(delegate->scroll_update()); |
+ EXPECT_FALSE(delegate->scroll_end()); |
+ EXPECT_FALSE(delegate->pinch_begin()); |
+ EXPECT_FALSE(delegate->pinch_update()); |
+ EXPECT_FALSE(delegate->pinch_end()); |
+ EXPECT_FALSE(delegate->long_press()); |
+ |
+ delegate->Reset(); |
+} |
+ |
+// Check that appropriate touch events generate double tap gesture events. |
+TEST_F(TrackpadTest, GestureEventTwoFingerDoubleTap) { |
+ scoped_ptr<GestureEventConsumeDelegate> delegate( |
+ new GestureEventConsumeDelegate()); |
+ const int kWindowWidth = 1280; |
+ const int kWindowHeight = 800; |
+ |
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); |
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
+ delegate.get(), -1234, bounds, NULL)); |
+ |
+ delegate->Reset(); |
+ |
+ device_.Play(Trackpad::TwoFingerDoubleTapRecording()); |
+ RunAllPendingInMessageLoop(); |
+ |
+ EXPECT_TRUE(delegate->tap()); |
+ EXPECT_FALSE(delegate->tap_down()); |
+ EXPECT_TRUE(delegate->double_tap()); |
+ EXPECT_FALSE(delegate->scroll_begin()); |
+ EXPECT_FALSE(delegate->scroll_update()); |
+ EXPECT_FALSE(delegate->scroll_end()); |
+ EXPECT_FALSE(delegate->pinch_begin()); |
+ EXPECT_FALSE(delegate->pinch_update()); |
+ EXPECT_FALSE(delegate->pinch_end()); |
+ EXPECT_FALSE(delegate->long_press()); |
+ |
+ delegate->Reset(); |
+} |
+ |
+// Check that appropriate touch events generate drag gesture events. |
+TEST_F(TrackpadTest, GestureEventTwoFingerDrag) { |
+ scoped_ptr<GestureEventConsumeDelegate> delegate( |
+ new GestureEventConsumeDelegate()); |
+ const int kWindowWidth = 1280; |
+ const int kWindowHeight = 800; |
+ |
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); |
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
+ delegate.get(), -1234, bounds, NULL)); |
+ |
+ delegate->Reset(); |
+ |
+ device_.Play(Trackpad::TwoFingerDragRecording()); |
+ RunAllPendingInMessageLoop(); |
+ |
+ EXPECT_FALSE(delegate->tap()); |
+ EXPECT_FALSE(delegate->tap_down()); |
+ EXPECT_FALSE(delegate->double_tap()); |
+ EXPECT_TRUE(delegate->scroll_begin()); |
+ EXPECT_TRUE(delegate->scroll_update()); |
+ EXPECT_TRUE(delegate->scroll_end()); |
+ EXPECT_FALSE(delegate->pinch_begin()); |
+ EXPECT_FALSE(delegate->pinch_update()); |
+ EXPECT_FALSE(delegate->pinch_end()); |
+ EXPECT_FALSE(delegate->long_press()); |
+ |
+ delegate->Reset(); |
+} |
+ |
+// Check that appropriate touch events generate pinch gesture events. |
+TEST_F(TrackpadTest, GestureEventTwoFingerPinch) { |
+ scoped_ptr<GestureEventConsumeDelegate> delegate( |
+ new GestureEventConsumeDelegate()); |
+ const int kWindowWidth = 1280; |
+ const int kWindowHeight = 800; |
+ |
+ gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); |
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
+ delegate.get(), -1234, bounds, NULL)); |
+ |
+ delegate->Reset(); |
+ |
+ device_.Play(Trackpad::TwoFingerPinchRecording()); |
+ RunAllPendingInMessageLoop(); |
+ |
+ EXPECT_FALSE(delegate->tap()); |
+ EXPECT_FALSE(delegate->tap_down()); |
+ EXPECT_FALSE(delegate->double_tap()); |
+ EXPECT_FALSE(delegate->scroll_begin()); |
+ EXPECT_FALSE(delegate->scroll_update()); |
+ EXPECT_FALSE(delegate->scroll_end()); |
+ EXPECT_TRUE(delegate->pinch_begin()); |
+ EXPECT_TRUE(delegate->pinch_update()); |
+ EXPECT_TRUE(delegate->pinch_end()); |
+ EXPECT_FALSE(delegate->long_press()); |
+ |
+ delegate->Reset(); |
+} |
+ |
+} // namespace test |
+} // namespace aura |
+ |
Property changes on: ui/aura/gestures/gesture_recognizer_grail_unittest.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |