diff options
-rw-r--r-- | ash/wm/system_gesture_event_filter.cc | 129 | ||||
-rw-r--r-- | ash/wm/system_gesture_event_filter.h | 21 | ||||
-rw-r--r-- | ash/wm/system_gesture_event_filter_unittest.cc | 27 | ||||
-rw-r--r-- | ui/aura/gestures/gesture_recognizer_unittest.cc | 232 | ||||
-rw-r--r-- | ui/aura/root_window_unittest.cc | 11 | ||||
-rw-r--r-- | ui/aura/window_unittest.cc | 2 | ||||
-rw-r--r-- | ui/base/events.h | 5 | ||||
-rw-r--r-- | ui/base/gestures/gesture_point.cc | 6 | ||||
-rw-r--r-- | ui/base/gestures/gesture_point.h | 4 | ||||
-rw-r--r-- | ui/base/gestures/gesture_sequence.cc | 364 | ||||
-rw-r--r-- | ui/base/gestures/gesture_sequence.h | 47 |
11 files changed, 447 insertions, 401 deletions
diff --git a/ash/wm/system_gesture_event_filter.cc b/ash/wm/system_gesture_event_filter.cc index 7cd673e..639a216 100644 --- a/ash/wm/system_gesture_event_filter.cc +++ b/ash/wm/system_gesture_event_filter.cc @@ -4,101 +4,17 @@ #include "ash/wm/system_gesture_event_filter.h" -#include "ash/accelerators/accelerator_controller.h" #include "ash/shell.h" +#include "ash/accelerators/accelerator_controller.h" #include "ash/system/brightness/brightness_control_delegate.h" #include "ash/volume_control_delegate.h" -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/snap_sizer.h" #include "ui/aura/event.h" #include "ui/aura/root_window.h" #include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace { - -const int kSystemPinchPoints = 4; - -enum SystemGestureStatus { - SYSTEM_GESTURE_PROCESSED, // The system gesture has been processed. - SYSTEM_GESTURE_IGNORED, // The system gesture was ignored. - SYSTEM_GESTURE_END, // Marks the end of the sytem gesture. -}; - -aura::Window* GetTargetForSystemGestureEvent(aura::Window* target) { - aura::Window* system_target = target; - if (!system_target || system_target == ash::Shell::GetPrimaryRootWindow()) - system_target = ash::wm::GetActiveWindow(); - if (system_target) - system_target = system_target->GetToplevelWindow(); - return system_target; -} - -} namespace ash { namespace internal { -class SystemPinchHandler { - public: - explicit SystemPinchHandler(aura::Window* target) - : target_(target) { - widget_ = views::Widget::GetWidgetForNativeWindow(target_); - } - - ~SystemPinchHandler() { - } - - SystemGestureStatus ProcessGestureEvent(const aura::GestureEvent& event) { - // The target has changed, somehow. Let's bale. - if (!widget_) - return SYSTEM_GESTURE_END; - - switch (event.type()) { - case ui::ET_GESTURE_TAP_UP: - if (event.delta_x() == kSystemPinchPoints) { - gfx::Rect bounds = target_->bounds(); - int grid = Shell::GetInstance()->GetGridSize(); - bounds.set_x(WindowResizer::AlignToGridRoundUp(bounds.x(), grid)); - bounds.set_y(WindowResizer::AlignToGridRoundUp(bounds.y(), grid)); - target_->SetBounds(bounds); - return SYSTEM_GESTURE_END; - } - break; - - case ui::ET_GESTURE_SCROLL_UPDATE: { - if (wm::IsWindowFullscreen(target_) || - !widget_->widget_delegate()->CanResize()) - break; - - gfx::Rect bounds = target_->bounds(); - bounds.set_x(static_cast<int>(bounds.x() + event.delta_x())); - bounds.set_y(static_cast<int>(bounds.y() + event.delta_y())); - target_->SetBounds(bounds); - break; - } - - case ui::ET_GESTURE_PINCH_UPDATE: { - // TODO(sad): Process PINCH_UPDATEs too. - break; - } - - default: - break; - } - - return SYSTEM_GESTURE_PROCESSED; - } - - private: - aura::Window* target_; - views::Widget* widget_; - - DISALLOW_COPY_AND_ASSIGN(SystemPinchHandler); -}; - SystemGestureEventFilter::SystemGestureEventFilter() : aura::EventFilter(), overlap_percent_(5), @@ -128,6 +44,9 @@ ui::TouchStatus SystemGestureEventFilter::PreHandleTouchEvent( ui::GestureStatus SystemGestureEventFilter::PreHandleGestureEvent( aura::Window* target, aura::GestureEvent* event) { + // TODO(tdresser) handle system level gesture events + if (event->type() == ui::ET_GESTURE_THREE_FINGER_SWIPE) + return ui::GESTURE_STATUS_CONSUMED; if (!target || target == Shell::GetPrimaryRootWindow()) { switch (event->type()) { case ui::ET_GESTURE_SCROLL_BEGIN: { @@ -183,49 +102,9 @@ ui::GestureStatus SystemGestureEventFilter::PreHandleGestureEvent( } return ui::GESTURE_STATUS_CONSUMED; } - - aura::Window* system_target = GetTargetForSystemGestureEvent(target); - if (!system_target) - return ui::GESTURE_STATUS_UNKNOWN; - - WindowPinchHandlerMap::iterator find = pinch_handlers_.find(system_target); - if (find != pinch_handlers_.end()) { - SystemGestureStatus status = - (*find).second->ProcessGestureEvent(*event); - if (status == SYSTEM_GESTURE_END) - ClearGestureHandlerForWindow(system_target); - return ui::GESTURE_STATUS_CONSUMED; - } else { - if (event->type() == ui::ET_GESTURE_TAP_DOWN && - event->delta_x() >= kSystemPinchPoints) { - pinch_handlers_[system_target] = new SystemPinchHandler(system_target); - system_target->AddObserver(this); - return ui::GESTURE_STATUS_CONSUMED; - } - } - return ui::GESTURE_STATUS_UNKNOWN; } -void SystemGestureEventFilter::OnWindowVisibilityChanged(aura::Window* window, - bool visible) { - if (!visible) - ClearGestureHandlerForWindow(window); -} - -void SystemGestureEventFilter::OnWindowDestroying(aura::Window* window) { - ClearGestureHandlerForWindow(window); -} - -void SystemGestureEventFilter::ClearGestureHandlerForWindow( - aura::Window* window) { - WindowPinchHandlerMap::iterator find = pinch_handlers_.find(window); - DCHECK(find != pinch_handlers_.end()); - delete (*find).second; - pinch_handlers_.erase(find); - window->RemoveObserver(this); -} - bool SystemGestureEventFilter::HandleDeviceControl(aura::GestureEvent* event) { gfx::Rect screen = gfx::Screen::GetPrimaryMonitor().bounds(); double percent = 100.0 * (event->y() - screen.y()) / screen.height(); diff --git a/ash/wm/system_gesture_event_filter.h b/ash/wm/system_gesture_event_filter.h index 08a692c..f240691 100644 --- a/ash/wm/system_gesture_event_filter.h +++ b/ash/wm/system_gesture_event_filter.h @@ -8,9 +8,6 @@ #include "ash/shell.h" #include "ui/aura/event_filter.h" -#include "ui/aura/window_observer.h" - -#include <map> namespace aura { class MouseEvent; @@ -21,8 +18,6 @@ class Window; namespace ash { namespace internal { -class SystemPinchHandler; - enum BezelStart { BEZEL_START_UNSET = 0, BEZEL_START_TOP, @@ -38,8 +33,7 @@ enum ScrollOrientation { }; // An event filter which handles system level gesture events. -class SystemGestureEventFilter : public aura::EventFilter, - public aura::WindowObserver { +class SystemGestureEventFilter : public aura::EventFilter { public: SystemGestureEventFilter(); virtual ~SystemGestureEventFilter(); @@ -55,15 +49,7 @@ class SystemGestureEventFilter : public aura::EventFilter, aura::Window* target, aura::GestureEvent* event) OVERRIDE; - // Overridden from aura::WindowObserver. - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - private: - // Removes system-gesture handlers for a window. - void ClearGestureHandlerForWindow(aura::Window* window); - // Handle events meant for volume / brightness. Returns true when no further // events from this gesture should be sent. bool HandleDeviceControl(aura::GestureEvent* event); @@ -76,11 +62,6 @@ class SystemGestureEventFilter : public aura::EventFilter, // further events from this gesture should be sent. bool HandleApplicationControl(aura::GestureEvent* event); - typedef std::map<aura::Window*, SystemPinchHandler*> WindowPinchHandlerMap; - // Created on demand when a system-level pinch gesture is initiated. Destroyed - // when the system-level pinch gesture ends for the window. - WindowPinchHandlerMap pinch_handlers_; - // The percentage of the screen to the left and right which belongs to // device gestures. const int overlap_percent_; diff --git a/ash/wm/system_gesture_event_filter_unittest.cc b/ash/wm/system_gesture_event_filter_unittest.cc index c22b168..ed2fcb8 100644 --- a/ash/wm/system_gesture_event_filter_unittest.cc +++ b/ash/wm/system_gesture_event_filter_unittest.cc @@ -130,6 +130,33 @@ TEST_F(SystemGestureEventFilterTest, TapOutsideRootWindow) { EXPECT_FALSE(consumed); } +// Ensure that a three fingered swipe is consumed by the system event handler. +TEST_F(SystemGestureEventFilterTest, ThreeFingerSwipe) { + aura::RootWindow* root_window = Shell::GetPrimaryRootWindow(); + + const int kTouchId = 5; + + // Get a target for kTouchId + aura::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(100, 100), kTouchId, + base::Time::NowFromSystemTime() - base::Time()); + root_window->DispatchTouchEvent(&press); + + aura::GestureEvent* event = new aura::GestureEvent( + ui::ET_GESTURE_THREE_FINGER_SWIPE, 0, 0, 0, base::Time::Now(), + 0, 0, 1 << kTouchId); + bool consumed = root_window->DispatchGestureEvent(event); + + EXPECT_TRUE(consumed); + + // The system event filter shouldn't filter out events like tap downs. + aura::GestureEvent* event2 = new aura::GestureEvent( + ui::ET_GESTURE_TAP_DOWN, 0, 0, 0, base::Time::Now(), + 0, 0, 1 << kTouchId); + consumed = root_window->DispatchGestureEvent(event2); + + EXPECT_FALSE(consumed); +} + // Ensure that the device control operation gets properly handled. TEST_F(SystemGestureEventFilterTest, DeviceControl) { aura::RootWindow* root_window = Shell::GetPrimaryRootWindow(); diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc index 27f64501..be0d51f 100644 --- a/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/ui/aura/gestures/gesture_recognizer_unittest.cc @@ -44,6 +44,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate { pinch_end_(false), long_press_(false), fling_(false), + three_finger_swipe_(false), scroll_x_(0), scroll_y_(0), velocity_x_(0), @@ -66,6 +67,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate { pinch_end_ = false; long_press_ = false; fling_ = false; + three_finger_swipe_ = false; scroll_begin_position_.SetPoint(0, 0); tap_location_.SetPoint(0, 0); @@ -89,6 +91,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate { bool pinch_end() const { return pinch_end_; } bool long_press() const { return long_press_; } bool fling() const { return fling_; } + bool three_finger_swipe() const { return three_finger_swipe_; } const gfx::Point scroll_begin_position() const { return scroll_begin_position_; @@ -152,7 +155,10 @@ class GestureEventConsumeDelegate : public TestWindowDelegate { EXPECT_TRUE(velocity_x_ != 0 || velocity_y_ != 0); fling_ = true; break; - case ui::ET_GESTURE_TAP_UP: + case ui::ET_GESTURE_THREE_FINGER_SWIPE: + three_finger_swipe_ = true; + velocity_x_ = gesture->delta_x(); + velocity_y_ = gesture->delta_y(); break; default: NOTREACHED(); @@ -172,6 +178,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate { bool pinch_end_; bool long_press_; bool fling_; + bool three_finger_swipe_; gfx::Point scroll_begin_position_; gfx::Point tap_location_; @@ -1560,6 +1567,45 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromTap) { EXPECT_FALSE(delegate->pinch_update()); } +TEST_F(GestureRecognizerTest, GestureEventPinchScrollOnlyWhenBothFingersMove) { + scoped_ptr<GestureEventConsumeDelegate> delegate( + new GestureEventConsumeDelegate()); + const int kWindowWidth = 1000; + const int kWindowHeight = 1000; + const int kTouchId1 = 3; + const int kTouchId2 = 5; + gfx::Rect bounds(0, 0, kWindowWidth, kWindowHeight); + scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( + delegate.get(), -1234, bounds, NULL)); + + delegate->Reset(); + TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(100, 100), + kTouchId1, GetTime()); + + root_window()->DispatchTouchEvent(&press1); + + delegate->Reset(); + TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(110, 110), + kTouchId2, GetTime()); + root_window()->DispatchTouchEvent(&press2); + + SendScrollEvents(root_window(), 100, 100, press1.time_stamp(), + 1, 10, kTouchId1, 1, + ui::GestureConfiguration::points_buffered_for_velocity(), + delegate.get()); + + SendScrollEvents(root_window(), 110, 110, press1.time_stamp() + + base::TimeDelta::FromMilliseconds(1000), + 1, 10, kTouchId2, 1, + ui::GestureConfiguration::points_buffered_for_velocity(), + delegate.get()); + // At no point were both fingers moving at the same time, + // so no scrolling should have occurred + + EXPECT_EQ(0, delegate->scroll_x()); + EXPECT_EQ(0, delegate->scroll_y()); +} + TEST_F(GestureRecognizerTest, GestureEventIgnoresDisconnectedEvents) { scoped_ptr<GestureEventConsumeDelegate> delegate( new GestureEventConsumeDelegate()); @@ -1707,5 +1753,189 @@ TEST_F(GestureRecognizerTest, NoTapWithPreventDefaultedRelease) { EXPECT_FALSE(delegate->tap()); } +TEST_F(GestureRecognizerTest, GestureEventThreeFingerSwipe) { + scoped_ptr<GestureEventConsumeDelegate> delegate( + new GestureEventConsumeDelegate()); + const int kTouchId1 = 7; + const int kTouchId2 = 2; + const int kTouchId3 = 9; + gfx::Rect bounds(0, 0, 1000, 1000); + scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( + delegate.get(), -1234, bounds, NULL)); + + TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), + kTouchId1, GetTime()); + TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), + kTouchId2, GetTime()); + TouchEvent press3(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), + kTouchId3, GetTime()); + + TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(0, 0), + kTouchId1, GetTime()); + TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(0, 0), + kTouchId2, GetTime()); + TouchEvent release3(ui::ET_TOUCH_RELEASED, gfx::Point(0, 0), + kTouchId3, GetTime()); + + root_window()->DispatchTouchEvent(&press1); + root_window()->DispatchTouchEvent(&press2); + root_window()->DispatchTouchEvent(&press3); + + delegate->Reset(); + + // Start by testing all four directions + + int kBufferedPoints = + ui::GestureConfiguration::points_buffered_for_velocity(); + + // Swipe right + SendScrollEvents(root_window(), 1, 1, press1.time_stamp(), + 100, 10, kTouchId1, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, press2.time_stamp(), + 100, 10, kTouchId2, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, press3.time_stamp(), + 100, 10, kTouchId3, 1, kBufferedPoints, delegate.get()); + + EXPECT_TRUE(delegate->three_finger_swipe()); + EXPECT_EQ(1, delegate->velocity_x()); + EXPECT_EQ(0, delegate->velocity_y()); + + root_window()->DispatchTouchEvent(&release1); + root_window()->DispatchTouchEvent(&release2); + root_window()->DispatchTouchEvent(&release3); + + root_window()->DispatchTouchEvent(&press1); + root_window()->DispatchTouchEvent(&press2); + root_window()->DispatchTouchEvent(&press3); + + delegate->Reset(); + + // Swipe left + SendScrollEvents(root_window(), 1, 1, + press1.time_stamp(), + -100, 10, kTouchId1, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press2.time_stamp(), + -100, 10, kTouchId2, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press3.time_stamp(), + -100, 10, kTouchId3, 1, kBufferedPoints, delegate.get()); + + EXPECT_TRUE(delegate->three_finger_swipe()); + EXPECT_EQ(-1, delegate->velocity_x()); + EXPECT_EQ(0, delegate->velocity_y()); + + root_window()->DispatchTouchEvent(&release1); + root_window()->DispatchTouchEvent(&release2); + root_window()->DispatchTouchEvent(&release3); + + root_window()->DispatchTouchEvent(&press1); + root_window()->DispatchTouchEvent(&press2); + root_window()->DispatchTouchEvent(&press3); + + delegate->Reset(); + + // Swipe down + SendScrollEvents(root_window(), 1, 1, + press1.time_stamp(), + 10, 100, kTouchId1, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press2.time_stamp(), + 10, 100, kTouchId2, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press3.time_stamp(), + 10, 100, kTouchId3, 1, kBufferedPoints, delegate.get()); + + EXPECT_TRUE(delegate->three_finger_swipe()); + EXPECT_EQ(0, delegate->velocity_x()); + EXPECT_EQ(1, delegate->velocity_y()); + + root_window()->DispatchTouchEvent(&release1); + root_window()->DispatchTouchEvent(&release2); + root_window()->DispatchTouchEvent(&release3); + + root_window()->DispatchTouchEvent(&press1); + root_window()->DispatchTouchEvent(&press2); + root_window()->DispatchTouchEvent(&press3); + + delegate->Reset(); + + // Swipe up + SendScrollEvents(root_window(), 1, 1, + press1.time_stamp(), + 10, -100, kTouchId1, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press2.time_stamp(), + 10, -100, kTouchId2, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press3.time_stamp(), + 10, -100, kTouchId3, 1, kBufferedPoints, delegate.get()); + + EXPECT_TRUE(delegate->three_finger_swipe()); + EXPECT_EQ(0, delegate->velocity_x()); + EXPECT_EQ(-1, delegate->velocity_y()); + + // Only one swipe can occur per press of three fingers + delegate->Reset(); + + SendScrollEvents(root_window(), 1, 1, + press1.time_stamp(), + 10, -100, kTouchId1, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press2.time_stamp(), + 10, -100, kTouchId2, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press3.time_stamp(), + 10, -100, kTouchId3, 1, kBufferedPoints, delegate.get()); + + EXPECT_FALSE(delegate->three_finger_swipe()); + + root_window()->DispatchTouchEvent(&release1); + root_window()->DispatchTouchEvent(&release2); + root_window()->DispatchTouchEvent(&release3); + + root_window()->DispatchTouchEvent(&press1); + root_window()->DispatchTouchEvent(&press2); + root_window()->DispatchTouchEvent(&press3); + + delegate->Reset(); + + // Swiping diagonally doesn't fire an event + SendScrollEvents(root_window(), 1, 1, + press1.time_stamp(), + 100, -100, kTouchId1, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press2.time_stamp(), + 100, -100, kTouchId2, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press3.time_stamp(), + 100, -100, kTouchId3, 1, kBufferedPoints, delegate.get()); + + EXPECT_FALSE(delegate->three_finger_swipe()); + + root_window()->DispatchTouchEvent(&release1); + root_window()->DispatchTouchEvent(&release2); + root_window()->DispatchTouchEvent(&release3); + + root_window()->DispatchTouchEvent(&press1); + root_window()->DispatchTouchEvent(&press2); + root_window()->DispatchTouchEvent(&press3); + + delegate->Reset(); + + // Have to swipe in a consistent direction + SendScrollEvents(root_window(), 1, 1, + press1.time_stamp(), + 100, 10, kTouchId1, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press2.time_stamp(), + 100, 10, kTouchId2, 1, kBufferedPoints, delegate.get()); + SendScrollEvents(root_window(), 1, 1, + press3.time_stamp(), + -100, 10, kTouchId3, 1, kBufferedPoints, delegate.get()); + + EXPECT_FALSE(delegate->three_finger_swipe()); +} + } // namespace test } // namespace aura diff --git a/ui/aura/root_window_unittest.cc b/ui/aura/root_window_unittest.cc index 904ff5f..45b16a7 100644 --- a/ui/aura/root_window_unittest.cc +++ b/ui/aura/root_window_unittest.cc @@ -424,9 +424,6 @@ std::string EventTypeToString(ui::EventType type) { case ui::ET_GESTURE_TAP_DOWN: return "GESTURE_TAP_DOWN"; - case ui::ET_GESTURE_TAP_UP: - return "GESTURE_TAP_UP"; - case ui::ET_GESTURE_DOUBLE_TAP: return "GESTURE_DOUBLE_TAP"; @@ -470,8 +467,7 @@ TEST_F(RootWindowTest, GestureToMouseEventTest) { root_window()->DispatchTouchEvent(&touch_pressed_event); root_window()->DispatchTouchEvent(&touch_released_event); EXPECT_EQ("TOUCH_PRESSED GESTURE_TAP_DOWN TOUCH_RELEASED GESTURE_TAP " - "MOUSE_ENTERED MOUSE_MOVED MOUSE_PRESSED MOUSE_RELEASED " - "GESTURE_TAP_UP", + "MOUSE_ENTERED MOUSE_MOVED MOUSE_PRESSED MOUSE_RELEASED", EventTypesToString(filter->events())); filter->events().clear(); } @@ -516,8 +512,7 @@ TEST_F(RootWindowTest, GestureToMouseEventTest) { TouchEvent touch_event(ui::ET_TOUCH_RELEASED, gfx::Point(300, 201), 1, base::TimeDelta()); root_window()->DispatchTouchEvent(&touch_event); - EXPECT_EQ("TOUCH_RELEASED GESTURE_SCROLL_END MOUSE_DRAGGED MOUSE_RELEASED " - "GESTURE_TAP_UP", + EXPECT_EQ("TOUCH_RELEASED GESTURE_SCROLL_END MOUSE_DRAGGED MOUSE_RELEASED", EventTypesToString(filter->events())); filter->events().clear(); } @@ -557,7 +552,7 @@ TEST_F(RootWindowTest, MouseMoveThenTouch) { root_window()->DispatchTouchEvent(&touch_released_event); EXPECT_EQ("TOUCH_PRESSED GESTURE_TAP_DOWN TOUCH_RELEASED GESTURE_TAP " "MOUSE_EXITED MOUSE_ENTERED MOUSE_MOVED MOUSE_PRESSED " - "MOUSE_RELEASED GESTURE_TAP_UP", + "MOUSE_RELEASED", EventTypesToString(filter->events())); filter->events().clear(); } diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index 6e5bcbe..6fa116e 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -659,7 +659,7 @@ TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) { gfx::Point(10, 10), 0, getTime() + base::TimeDelta::FromMilliseconds(50)); root_window()->DispatchTouchEvent(&release); - EXPECT_EQ(2, delegate.gesture_event_count()); + EXPECT_EQ(1, delegate.gesture_event_count()); } // Changes capture while capture is already ongoing. diff --git a/ui/base/events.h b/ui/base/events.h index 6c9f271..e779dbf 100644 --- a/ui/base/events.h +++ b/ui/base/events.h @@ -53,15 +53,12 @@ enum EventType { ET_GESTURE_SCROLL_UPDATE, ET_GESTURE_TAP, ET_GESTURE_TAP_DOWN, - ET_GESTURE_TAP_UP, ET_GESTURE_DOUBLE_TAP, ET_GESTURE_PINCH_BEGIN, ET_GESTURE_PINCH_END, ET_GESTURE_PINCH_UPDATE, ET_GESTURE_LONG_PRESS, - // A SWIPE gesture can happen at the end of a TAP_UP gesture if the - // finger(s) were moving quickly before they are released. - ET_GESTURE_MULTIFINGER_SWIPE, + ET_GESTURE_THREE_FINGER_SWIPE, // Scroll support. // TODO[davemoore] we need to unify these events w/ touch and gestures. diff --git a/ui/base/gestures/gesture_point.cc b/ui/base/gestures/gesture_point.cc index d75250a..6b7dbf1 100644 --- a/ui/base/gestures/gesture_point.cc +++ b/ui/base/gestures/gesture_point.cc @@ -99,6 +99,12 @@ bool GesturePoint::DidScroll(const TouchEvent& event, int dist) const { abs(last_touch_position_.y() - first_touch_position_.y()) > dist; } +float GesturePoint::Distance(const GesturePoint& point) const { + float x_diff = point.last_touch_position_.x() - last_touch_position_.x(); + float y_diff = point.last_touch_position_.y() - last_touch_position_.y(); + return sqrt(x_diff * x_diff + y_diff * y_diff); +} + bool GesturePoint::HasEnoughDataToEstablishRail() const { int dx = x_delta(); int dy = y_delta(); diff --git a/ui/base/gestures/gesture_point.h b/ui/base/gestures/gesture_point.h index 19a8a3c..871427b 100644 --- a/ui/base/gestures/gesture_point.h +++ b/ui/base/gestures/gesture_point.h @@ -55,8 +55,6 @@ class GesturePoint { double last_touch_time() const { return last_touch_time_; } const gfx::Point& last_touch_position() const { return last_touch_position_; } - int x() const { return last_touch_position_.x(); } - int y() const { return last_touch_position_.y(); } // point_id_ is used to drive GestureSequence::ProcessTouchEventForGesture. // point_ids are maintained such that the set of point_ids is always @@ -83,6 +81,8 @@ class GesturePoint { float XVelocity() { return velocity_calculator_.XVelocity(); } float YVelocity() { return velocity_calculator_.YVelocity(); } + float Distance(const GesturePoint& point) const; + const gfx::Rect& enclosing_rectangle() const { return enclosing_rect_; } private: diff --git a/ui/base/gestures/gesture_sequence.cc b/ui/base/gestures/gesture_sequence.cc index 5e74aff..02d4b4e 100644 --- a/ui/base/gestures/gesture_sequence.cc +++ b/ui/base/gestures/gesture_sequence.cc @@ -109,38 +109,32 @@ enum EdgeStateSignatureType { GST_PINCH_THIRD_PRESSED = G(GS_PINCH, 2, TS_PRESSED, false), - GST_PINCH_THIRD_MOVED = - G(GS_PINCH, 2, TS_MOVED, false), + GST_THREE_FINGER_SWIPE_FIRST_RELEASED = + G(GS_THREE_FINGER_SWIPE, 0, TS_RELEASED, false), - GST_PINCH_THIRD_RELEASED = - G(GS_PINCH, 2, TS_RELEASED, false), + GST_THREE_FINGER_SWIPE_SECOND_RELEASED = + G(GS_THREE_FINGER_SWIPE, 1, TS_RELEASED, false), - GST_PINCH_THIRD_CANCELLED = - G(GS_PINCH, 2, TS_CANCELLED, false), + GST_THREE_FINGER_SWIPE_THIRD_RELEASED = + G(GS_THREE_FINGER_SWIPE, 2, TS_RELEASED, false), - GST_PINCH_FOURTH_PRESSED = - G(GS_PINCH, 3, TS_PRESSED, false), + GST_THREE_FINGER_SWIPE_FIRST_MOVED = + G(GS_THREE_FINGER_SWIPE, 0, TS_MOVED, false), - GST_PINCH_FOURTH_MOVED = - G(GS_PINCH, 3, TS_MOVED, false), + GST_THREE_FINGER_SWIPE_SECOND_MOVED = + G(GS_THREE_FINGER_SWIPE, 1, TS_MOVED, false), - GST_PINCH_FOURTH_RELEASED = - G(GS_PINCH, 3, TS_RELEASED, false), + GST_THREE_FINGER_SWIPE_THIRD_MOVED = + G(GS_THREE_FINGER_SWIPE, 2, TS_MOVED, false), - GST_PINCH_FOURTH_CANCELLED = - G(GS_PINCH, 3, TS_CANCELLED, false), + GST_THREE_FINGER_SWIPE_FIRST_CANCELLED = + G(GS_THREE_FINGER_SWIPE, 0, TS_CANCELLED, false), - GST_PINCH_FIFTH_PRESSED = - G(GS_PINCH, 4, TS_PRESSED, false), + GST_THREE_FINGER_SWIPE_SECOND_CANCELLED = + G(GS_THREE_FINGER_SWIPE, 1, TS_CANCELLED, false), - GST_PINCH_FIFTH_MOVED = - G(GS_PINCH, 4, TS_MOVED, false), - - GST_PINCH_FIFTH_RELEASED = - G(GS_PINCH, 4, TS_RELEASED, false), - - GST_PINCH_FIFTH_CANCELLED = - G(GS_PINCH, 4, TS_CANCELLED, false), + GST_THREE_FINGER_SWIPE_THIRD_CANCELLED = + G(GS_THREE_FINGER_SWIPE, 2, TS_CANCELLED, false), }; // Builds a signature. Signatures are assembled by joining together @@ -161,21 +155,6 @@ EdgeStateSignatureType Signature(GestureState gesture_state, } #undef G -float BoundingBoxDiagonal(const gfx::Rect& rect) { - float width = rect.width() * rect.width(); - float height = rect.height() * rect.height(); - return sqrt(width + height); -} - -unsigned int ComputeTouchBitmask(const GesturePoint* points) { - unsigned int touch_bitmask = 0; - for (int i = 0; i < GestureSequence::kMaxGesturePoints; ++i) { - if (points[i].in_use()) - touch_bitmask |= 1 << points[i].touch_id(); - } - return touch_bitmask; -} - } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -187,6 +166,7 @@ GestureSequence::GestureSequence(GestureEventHelper* helper) pinch_distance_start_(0.f), pinch_distance_current_(0.f), scroll_type_(ST_FREE), + three_finger_swipe_has_fired_(false), long_press_timer_(CreateTimer()), point_count_(0), helper_(helper) { @@ -222,7 +202,6 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( scoped_ptr<Gestures> gestures(new Gestures()); GesturePoint& point = GesturePointForEvent(event); point.UpdateValues(event); - RecreateBoundingBox(); flags_ = event.GetEventFlags(); const int point_id = points_[event.GetTouchId()].point_id(); if (point_id < 0) @@ -262,62 +241,54 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( break; case GST_SCROLL_SECOND_PRESSED: case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: - // Once pinch starts, we immediately break rail scroll. - scroll_type_ = ST_FREE; PinchStart(event, point, gestures.get()); set_state(GS_PINCH); break; case GST_PINCH_FIRST_MOVED: case GST_PINCH_SECOND_MOVED: - case GST_PINCH_THIRD_MOVED: - case GST_PINCH_FOURTH_MOVED: - case GST_PINCH_FIFTH_MOVED: if (PinchUpdate(event, point, gestures.get())) { - for (int i = 0; i < point_count_; ++i) - GetPointByPointId(i)->UpdateForScroll(); + GetPointByPointId(0)->UpdateForScroll(); + GetPointByPointId(1)->UpdateForScroll(); } break; case GST_PINCH_FIRST_RELEASED: case GST_PINCH_SECOND_RELEASED: - case GST_PINCH_THIRD_RELEASED: - case GST_PINCH_FOURTH_RELEASED: - case GST_PINCH_FIFTH_RELEASED: case GST_PINCH_FIRST_CANCELLED: case GST_PINCH_SECOND_CANCELLED: - case GST_PINCH_THIRD_CANCELLED: - case GST_PINCH_FOURTH_CANCELLED: - case GST_PINCH_FIFTH_CANCELLED: - if (point_count_ == 2) { - PinchEnd(event, point, gestures.get()); - - // Once pinch ends, it should still be possible to scroll with the - // remaining finger on the screen. - set_state(GS_SCROLL); - } else { - // Was it a swipe? i.e. were all the fingers moving in the same - // direction? - MaybeSwipe(event, point, gestures.get()); - - // Nothing else to do if we have more than 2 fingers active, since after - // the release/cancel, there are still enough fingers to do pinch. - // pinch_distance_current_ and pinch_distance_start_ will be updated - // when the bounding-box is updated. - } - ResetVelocities(); + PinchEnd(event, point, gestures.get()); + + // Once pinch ends, it should still be possible to scroll with the + // remaining finger on the screen. + scroll_type_ = ST_FREE; + set_state(GS_SCROLL); break; case GST_PINCH_THIRD_PRESSED: - case GST_PINCH_FOURTH_PRESSED: - case GST_PINCH_FIFTH_PRESSED: - AppendTapDownGestureEvent(point, gestures.get()); - pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); - pinch_distance_start_ = pinch_distance_current_; + three_finger_swipe_has_fired_ = false; + set_state(GS_THREE_FINGER_SWIPE); + break; + case GST_THREE_FINGER_SWIPE_FIRST_RELEASED: + case GST_THREE_FINGER_SWIPE_SECOND_RELEASED: + case GST_THREE_FINGER_SWIPE_THIRD_RELEASED: + case GST_THREE_FINGER_SWIPE_FIRST_CANCELLED: + case GST_THREE_FINGER_SWIPE_SECOND_CANCELLED: + case GST_THREE_FINGER_SWIPE_THIRD_CANCELLED: + GetPointByPointId(0)->ResetVelocity(); + GetPointByPointId(1)->ResetVelocity(); + GetPointByPointId(2)->ResetVelocity(); + set_state(GS_PINCH); + break; + case GST_THREE_FINGER_SWIPE_FIRST_MOVED: + case GST_THREE_FINGER_SWIPE_SECOND_MOVED: + case GST_THREE_FINGER_SWIPE_THIRD_MOVED: + if (!three_finger_swipe_has_fired_) { + ThreeFingerSwipeUpdate(event, point, gestures.get()); + GetPointByPointId(0)->UpdateForScroll(); + GetPointByPointId(1)->UpdateForScroll(); + GetPointByPointId(2)->UpdateForScroll(); + } break; } - if (event.GetEventType() == ui::ET_TOUCH_RELEASED || - event.GetEventType() == ui::ET_TOUCH_CANCELLED) - AppendTapUpGestureEvent(point, gestures.get()); - if (state_ != last_state) DVLOG(4) << "Gesture Sequence" << " State: " << state_ @@ -338,16 +309,10 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( if (point.point_id() > old_point.point_id()) point.set_point_id(point.point_id() - 1); } - if (old_point.in_use()) { old_point.Reset(); --point_count_; DCHECK_GE(point_count_, 0); - RecreateBoundingBox(); - if (state_ == GS_PINCH) { - pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); - pinch_distance_start_ = pinch_distance_current_; - } } } @@ -361,33 +326,6 @@ void GestureSequence::Reset() { point_count_ = 0; } -void GestureSequence::RecreateBoundingBox() { - // TODO(sad): Recreating the bounding box at every touch-event is not very - // efficient. This should be made better. - int left = INT_MAX, top = INT_MAX, right = INT_MIN, bottom = INT_MIN; - for (int i = 0; i < kMaxGesturePoints; ++i) { - if (!points_[i].in_use()) - continue; - if (left > points_[i].x()) - left = points_[i].x(); - if (right < points_[i].x()) - right = points_[i].x(); - if (top > points_[i].y()) - top = points_[i].y(); - if (bottom < points_[i].y()) - bottom = points_[i].y(); - } - bounding_box_last_center_ = bounding_box_.CenterPoint(); - bounding_box_.SetRect(left, top, right - left, bottom - top); -} - -void GestureSequence::ResetVelocities() { - for (int i = 0; i < kMaxGesturePoints; ++i) { - if (points_[i].in_use()) - points_[i].ResetVelocity(); - } -} - //////////////////////////////////////////////////////////////////////////////// // GestureSequence Protected: @@ -421,17 +359,7 @@ void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point, point.first_touch_position(), flags_, base::Time::FromDoubleT(point.last_touch_time()), - point_count_, 0.f, 1 << point.touch_id())); -} - -void GestureSequence::AppendTapUpGestureEvent(const GesturePoint& point, - Gestures* gestures) { - gestures->push_back(helper_->CreateGestureEvent( - ui::ET_GESTURE_TAP_UP, - point.first_touch_position(), - flags_, - base::Time::FromDoubleT(point.last_touch_time()), - point_count_, 0.f, 1 << point.touch_id())); + 0.f, 0.f, 1 << point.touch_id())); } void GestureSequence::AppendClickGestureEvent(const GesturePoint& point, @@ -508,10 +436,9 @@ void GestureSequence::AppendScrollGestureEnd(const GesturePoint& point, void GestureSequence::AppendScrollGestureUpdate(const GesturePoint& point, const gfx::Point& location, Gestures* gestures) { - int dx = location.x() - bounding_box_last_center_.x(); - int dy = location.y() - bounding_box_last_center_.y(); - if (dx == 0 && dy == 0) - return; + int dx = point.x_delta(); + int dy = point.y_delta(); + if (scroll_type_ == ST_HORIZONTAL) dy = 0; else if (scroll_type_ == ST_VERTICAL) @@ -522,13 +449,13 @@ void GestureSequence::AppendScrollGestureUpdate(const GesturePoint& point, location, flags_, base::Time::FromDoubleT(point.last_touch_time()), - dx, dy, ComputeTouchBitmask(points_))); + dx, dy, 1 << point.touch_id())); } void GestureSequence::AppendPinchGestureBegin(const GesturePoint& p1, const GesturePoint& p2, Gestures* gestures) { - gfx::Point center = bounding_box_.CenterPoint(); + gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); gestures->push_back(helper_->CreateGestureEvent( ui::ET_GESTURE_PINCH_BEGIN, center, @@ -541,40 +468,52 @@ void GestureSequence::AppendPinchGestureEnd(const GesturePoint& p1, const GesturePoint& p2, float scale, Gestures* gestures) { - gfx::Point center = bounding_box_.CenterPoint(); + gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); gestures->push_back(helper_->CreateGestureEvent( ui::ET_GESTURE_PINCH_END, center, flags_, base::Time::FromDoubleT(p1.last_touch_time()), - 0.f, 0.f, - 1 << p1.touch_id() | 1 << p2.touch_id())); + scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id())); } -void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& point, +void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& p1, + const GesturePoint& p2, float scale, Gestures* gestures) { // TODO(sad): Compute rotation and include it in delta_y. // http://crbug.com/113145 + gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); gestures->push_back(helper_->CreateGestureEvent( ui::ET_GESTURE_PINCH_UPDATE, - bounding_box_.CenterPoint(), + center, flags_, - base::Time::FromDoubleT(point.last_touch_time()), - scale, 0.f, - ComputeTouchBitmask(points_))); -} - -void GestureSequence::AppendSwipeGesture(const GesturePoint& point, - int swipe_x, - int swipe_y, - Gestures* gestures) { + base::Time::FromDoubleT(p1.last_touch_time()), + scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id())); +} + +void GestureSequence::AppendThreeFingerSwipeGestureEvent(const GesturePoint& p1, + const GesturePoint& p2, + const GesturePoint& p3, + float x_velocity, + float y_velocity, + Gestures* gestures) { + int x = ( + p1.last_touch_position().x() + + p2.last_touch_position().x() + + p3.last_touch_position().x()) / 3; + int y = ( + p1.last_touch_position().y() + + p2.last_touch_position().y() + + p3.last_touch_position().y()) / 3; + gfx::Point center(x, y); gestures->push_back(helper_->CreateGestureEvent( - ui::ET_GESTURE_MULTIFINGER_SWIPE, - bounding_box_.CenterPoint(), + ui::ET_GESTURE_THREE_FINGER_SWIPE, + center, flags_, - base::Time::FromDoubleT(point.last_touch_time()), - swipe_x, swipe_y, ComputeTouchBitmask(points_))); + base::Time::FromDoubleT(p1.last_touch_time()), + x_velocity, y_velocity, + 1 << p1.touch_id() | 1 << p2.touch_id() | 1 << p3.touch_id())); } bool GestureSequence::Click(const TouchEvent& event, @@ -678,12 +617,13 @@ bool GestureSequence::PinchStart(const TouchEvent& event, const GesturePoint* point1 = GetPointByPointId(0); const GesturePoint* point2 = GetPointByPointId(1); - pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); + pinch_distance_current_ = point1->Distance(*point2); pinch_distance_start_ = pinch_distance_current_; AppendPinchGestureBegin(*point1, *point2, gestures); if (state_ == GS_PENDING_SYNTHETIC_CLICK) { - gfx::Point center = bounding_box_.CenterPoint(); + gfx::Point center = point1->last_touch_position().Middle( + point2->last_touch_position()); AppendScrollGestureBegin(point, center, gestures); } @@ -694,18 +634,29 @@ bool GestureSequence::PinchUpdate(const TouchEvent& event, const GesturePoint& point, Gestures* gestures) { DCHECK(state_ == GS_PINCH); - float distance = BoundingBoxDiagonal(bounding_box_); + const GesturePoint* point1 = GetPointByPointId(0); + const GesturePoint* point2 = GetPointByPointId(1); - if (abs(distance - pinch_distance_current_) >= + float distance = point1->Distance(*point2); + if (abs(distance - pinch_distance_current_) < GestureConfiguration::min_pinch_update_distance_in_pixels()) { - AppendPinchGestureUpdate(point, + // The fingers didn't move towards each other, or away from each other, + // enough to constitute a pinch. But perhaps they moved enough in the same + // direction to do a two-finger scroll. + if (!point1->DidScroll(event, + GestureConfiguration::min_distance_for_pinch_scroll_in_pixels()) || + !point2->DidScroll(event, + GestureConfiguration::min_distance_for_pinch_scroll_in_pixels())) + return false; + + gfx::Point center = point1->last_touch_position().Middle( + point2->last_touch_position()); + AppendScrollGestureUpdate(point, center, gestures); + } else { + AppendPinchGestureUpdate(*point1, *point2, distance / pinch_distance_current_, gestures); pinch_distance_current_ = distance; - } else { - gfx::Point center = bounding_box_.CenterPoint(); - AppendScrollGestureUpdate(point, center, gestures); } - return true; } @@ -716,79 +667,70 @@ bool GestureSequence::PinchEnd(const TouchEvent& event, GesturePoint* point1 = GetPointByPointId(0); GesturePoint* point2 = GetPointByPointId(1); - float distance = BoundingBoxDiagonal(bounding_box_); + float distance = point1->Distance(*point2); AppendPinchGestureEnd(*point1, *point2, distance / pinch_distance_start_, gestures); + point1->ResetVelocity(); + point2->ResetVelocity(); + pinch_distance_start_ = 0; pinch_distance_current_ = 0; return true; } -bool GestureSequence::MaybeSwipe(const TouchEvent& event, - const GesturePoint& point, - Gestures* gestures) { - DCHECK(state_ == GS_PINCH); - float velocity_x = 0.f, velocity_y = 0.f; - bool swipe_x = true, swipe_y = true; - int sign_x = 0, sign_y = 0; - int i = 0; - - for (i = 0; i < kMaxGesturePoints; ++i) { - if (points_[i].in_use()) - break; - } - DCHECK(i < kMaxGesturePoints); - - velocity_x = points_[i].XVelocity(); - velocity_y = points_[i].YVelocity(); - sign_x = velocity_x < 0 ? -1 : 1; - sign_y = velocity_y < 0 ? -1 : 1; - - for (++i; i < kMaxGesturePoints; ++i) { - if (!points_[i].in_use()) - continue; - - if (sign_x * points_[i].XVelocity() < 0) - swipe_x = false; +bool GestureSequence::ThreeFingerSwipeUpdate(const TouchEvent& event, + const GesturePoint& point, Gestures* gestures) { + DCHECK(state_ == GS_THREE_FINGER_SWIPE); - if (sign_y * points_[i].YVelocity() < 0) - swipe_y = false; + GesturePoint* point1 = GetPointByPointId(0); + GesturePoint* point2 = GetPointByPointId(1); + GesturePoint* point3 = GetPointByPointId(2); - velocity_x += points_[i].XVelocity(); - velocity_y += points_[i].YVelocity(); - } + int min_velocity = GestureConfiguration::min_swipe_speed(); - float min_velocity = GestureConfiguration::min_swipe_speed(); - min_velocity *= min_velocity; + float vx1 = point1->XVelocity(); + float vx2 = point2->XVelocity(); + float vx3 = point3->XVelocity(); + float vy1 = point1->YVelocity(); + float vy2 = point2->YVelocity(); + float vy3 = point3->YVelocity(); - velocity_x = fabs(velocity_x / point_count_); - velocity_y = fabs(velocity_y / point_count_); - if (velocity_x < min_velocity) - swipe_x = false; - if (velocity_y < min_velocity) - swipe_y = false; + float vx = (vx1 + vx2 + vx3) / 3; + float vy = (vy1 + vy2 + vy3) / 3; - if (!swipe_x && !swipe_y) + // Not moving fast enough + if (fabs(vx) < min_velocity && fabs(vy) < min_velocity) return false; - if (!swipe_x) - velocity_x = 0.001f; - if (!swipe_y) - velocity_y = 0.001f; - - float ratio = velocity_x > velocity_y ? velocity_x / velocity_y : - velocity_y / velocity_x; + // Diagonal swipe, no event fired + // TODO(tdresser|sadrul): consider adding diagonal swipes + float ratio = fabs(vx) > fabs(vy) ? fabs(vx / vy) : fabs(vy / vx); if (ratio < GestureConfiguration::max_swipe_deviation_ratio()) return false; - if (velocity_x > velocity_y) - sign_y = 0; - else - sign_x = 0; - - AppendSwipeGesture(point, sign_x, sign_y, gestures); - + if (fabs(vx) > fabs(vy)) { + int sign = vx > 0 ? 1 : -1; + // ensure all touches are moving in the same direction, and are + // all moving faster than min_velocity. + if (vx1 * sign < min_velocity || + vx2 * sign < min_velocity || + vx3 * sign < min_velocity) + return false; + AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, + sign, 0, gestures); + } else { + int sign = vy > 0 ? 1 : -1; + // ensure all touches are moving in the same direction, and are + // all moving faster than min_velocity. + if (vy1 * sign < min_velocity || + vy2 * sign < min_velocity || + vy3 * sign < min_velocity) + return false; + AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, + 0, sign, gestures); + } + three_finger_swipe_has_fired_ = true; return true; } diff --git a/ui/base/gestures/gesture_sequence.h b/ui/base/gestures/gesture_sequence.h index b8a9a02..e8d7aab 100644 --- a/ui/base/gestures/gesture_sequence.h +++ b/ui/base/gestures/gesture_sequence.h @@ -10,7 +10,6 @@ #include "ui/base/events.h" #include "ui/base/gestures/gesture_point.h" #include "ui/base/gestures/gesture_recognizer.h" -#include "ui/gfx/rect.h" namespace ui { class TouchEvent; @@ -22,6 +21,7 @@ enum GestureState { GS_PENDING_SYNTHETIC_CLICK, GS_SCROLL, GS_PINCH, + GS_THREE_FINGER_SWIPE }; enum ScrollType { @@ -59,12 +59,6 @@ class UI_EXPORT GestureSequence { private: void Reset(); - // Recreates the axis-aligned bounding box that contains all the touch-points - // at their most recent position. - void RecreateBoundingBox(); - - void ResetVelocities(); - GesturePoint& GesturePointForEvent(const TouchEvent& event); // Do a linear scan through points_ to find the GesturePoint @@ -75,7 +69,6 @@ class UI_EXPORT GestureSequence { // Tap gestures. void AppendTapDownGestureEvent(const GesturePoint& point, Gestures* gestures); - void AppendTapUpGestureEvent(const GesturePoint& point, Gestures* gestures); void AppendClickGestureEvent(const GesturePoint& point, Gestures* gestures); void AppendDoubleClickGestureEvent(const GesturePoint& point, Gestures* gestures); @@ -102,13 +95,17 @@ class UI_EXPORT GestureSequence { const GesturePoint& p2, float scale, Gestures* gestures); - void AppendPinchGestureUpdate(const GesturePoint& point, + void AppendPinchGestureUpdate(const GesturePoint& p1, + const GesturePoint& p2, float scale, Gestures* gestures); - void AppendSwipeGesture(const GesturePoint& point, - int swipe_x, - int swipe_y, - Gestures* gestures); + + void AppendThreeFingerSwipeGestureEvent(const GesturePoint& p1, + const GesturePoint& p2, + const GesturePoint& p3, + float x_velocity, + float y_velocity, + Gestures* gestures); void set_state(const GestureState state ) { state_ = state; } @@ -119,11 +116,11 @@ class UI_EXPORT GestureSequence { const GesturePoint& point, Gestures* gestures); bool ScrollStart(const TouchEvent& event, - GesturePoint& point, - Gestures* gestures); + GesturePoint& point, + Gestures* gestures); void BreakRailScroll(const TouchEvent& event, - GesturePoint& point, - Gestures* gestures); + GesturePoint& point, + Gestures* gestures); bool ScrollUpdate(const TouchEvent& event, const GesturePoint& point, Gestures* gestures); @@ -145,9 +142,9 @@ class UI_EXPORT GestureSequence { bool PinchEnd(const TouchEvent& event, const GesturePoint& point, Gestures* gestures); - bool MaybeSwipe(const TouchEvent& event, - const GesturePoint& point, - Gestures* gestures); + bool ThreeFingerSwipeUpdate(const TouchEvent& event, + const GesturePoint& point, + Gestures* gestures); // Current state of gesture recognizer. GestureState state_; @@ -155,15 +152,6 @@ class UI_EXPORT GestureSequence { // ui::EventFlags. int flags_; - // We maintain the smallest axis-aligned rectangle that contains all the - // current touch-points. The 'distance' represents the diagonal distance. - // This box is updated after every touch-event. - gfx::Rect bounding_box_; - gfx::Point bounding_box_last_center_; - - // For pinch, the 'distance' represents the diagonal distance of - // |bounding_box_|. - // The distance between the two points at PINCH_START. float pinch_distance_start_; @@ -171,6 +159,7 @@ class UI_EXPORT GestureSequence { float pinch_distance_current_; ScrollType scroll_type_; + bool three_finger_swipe_has_fired_; scoped_ptr<base::OneShotTimer<GestureSequence> > long_press_timer_; GesturePoint points_[kMaxGesturePoints]; |