diff options
author | varunjain@chromium.org <varunjain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-21 13:31:45 +0000 |
---|---|---|
committer | varunjain@chromium.org <varunjain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-21 13:31:45 +0000 |
commit | 64a5a8cb4268b15ea6ec734a00114ef30f9381fb (patch) | |
tree | acf46e4070851d9be1ca5dfcd01d0ac0af557f71 | |
parent | 676c561eae941ee83445be73fb9148859bfcdf64 (diff) | |
download | chromium_src-64a5a8cb4268b15ea6ec734a00114ef30f9381fb.zip chromium_src-64a5a8cb4268b15ea6ec734a00114ef30f9381fb.tar.gz chromium_src-64a5a8cb4268b15ea6ec734a00114ef30f9381fb.tar.bz2 |
Gesture recognizer must be a singleton accross all aura::RootWindows
BUG=279317
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=229753
R=sadrul@chromium.org, sky@chromium.org
Review URL: https://codereview.chromium.org/25350006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229796 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 251 insertions, 122 deletions
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index 48e7c35..d335465 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc @@ -181,7 +181,7 @@ int DragDropController::StartDragAndDrop( // We need to transfer the current gesture sequence and the GR's touch event // queue to the |drag_drop_tracker_|'s capture window so that when it takes // capture, it still gets a valid gesture state. - root_window->gesture_recognizer()->TransferEventsTo(source_window, + ui::GestureRecognizer::Get()->TransferEventsTo(source_window, tracker->capture_window()); // We also send a gesture end to the source window so it can clear state. // TODO(varunjain): Remove this whole block when gesture sequence diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc index f76d33d..f6d5902 100644 --- a/ash/wm/toplevel_window_event_handler.cc +++ b/ash/wm/toplevel_window_event_handler.cc @@ -341,7 +341,7 @@ aura::client::WindowMoveResult ToplevelWindowEventHandler::RunMoveLoop( if (move_source == aura::client::WINDOW_MOVE_SOURCE_TOUCH && aura::Env::GetInstance()->is_touch_down()) { in_gesture_drag_ = true; - bool has_point = root_window->gesture_recognizer()-> + bool has_point = ui::GestureRecognizer::Get()-> GetLastTouchPointForTarget(source, &drag_location); DCHECK(has_point); } else { diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 6f13d81..ba0564b 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc @@ -59,6 +59,11 @@ #include "ui/events/gestures/gesture_recognizer.h" #endif +#if defined(OS_WIN) && defined(USE_AURA) +#include "ui/aura/window.h" +#include "ui/events/gestures/gesture_recognizer.h" +#endif + using content::OpenURLParams; using content::UserMetricsAction; using content::WebContents; @@ -897,6 +902,18 @@ TabDragController::DragBrowserToNewTabStrip( target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); else browser_widget->ReleaseCapture(); +#if defined(OS_WIN) && defined(USE_AURA) + // The Gesture recognizer does not work well currently when capture changes + // while a touch gesture is in progress. So we need to manually transfer + // gesture sequence and the GR's touch events queue to the new window. This + // should really be done somewhere in capture change code and or inside the + // GR. But we currently do not have a consistent way for doing it that would + // work in all cases. Hence this hack. + ui::GestureRecognizer::Get()->TransferEventsTo( + browser_widget->GetNativeView(), + target_tabstrip->GetWidget()->GetNativeView()); +#endif + // The window is going away. Since the drag is still on going we don't want // that to effect the position of any windows. SetWindowPositionManaged(browser_widget->GetNativeView(), false); @@ -2227,9 +2244,8 @@ gfx::Point TabDragController::GetCursorScreenPoint() { aura::Window* widget_window = widget->GetNativeWindow(); DCHECK(widget_window->GetRootWindow()); gfx::Point touch_point; - bool got_touch_point = widget_window->GetRootWindow()-> - gesture_recognizer()->GetLastTouchPointForTarget(widget_window, - &touch_point); + bool got_touch_point = ui::GestureRecognizer::Get()-> + GetLastTouchPointForTarget(widget_window, &touch_point); DCHECK(got_touch_point); ash::wm::ConvertPointToScreen(widget_window->GetRootWindow(), &touch_point); return touch_point; diff --git a/content/browser/renderer_host/render_widget_host_view_guest.cc b/content/browser/renderer_host/render_widget_host_view_guest.cc index 05730b9..a339329 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest.cc +++ b/content/browser/renderer_host/render_widget_host_view_guest.cc @@ -54,12 +54,16 @@ RenderWidgetHostViewGuest::RenderWidgetHostViewGuest( is_hidden_(host_->is_hidden()), platform_view_(static_cast<RenderWidgetHostViewPort*>(platform_view)) { #if defined(OS_WIN) || defined(USE_AURA) - gesture_recognizer_.reset(ui::GestureRecognizer::Create(this)); + gesture_recognizer_.reset(ui::GestureRecognizer::Create()); + gesture_recognizer_->AddGestureEventHelper(this); #endif // defined(OS_WIN) || defined(USE_AURA) host_->SetView(this); } RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() { +#if defined(OS_WIN) || defined(USE_AURA) + gesture_recognizer_->RemoveGestureEventHelper(this); +#endif // defined(OS_WIN) || defined(USE_AURA) } RenderWidgetHost* RenderWidgetHostViewGuest::GetRenderWidgetHost() const { @@ -507,21 +511,26 @@ void RenderWidgetHostViewGuest::DestroyGuestView() { base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); } -bool RenderWidgetHostViewGuest::DispatchLongPressGestureEvent( +bool RenderWidgetHostViewGuest::CanDispatchToConsumer( + ui::GestureConsumer* consumer) { + CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this); + return true; +} + +void RenderWidgetHostViewGuest::DispatchLongPressGestureEvent( ui::GestureEvent* event) { - return ForwardGestureEventToRenderer(event); + ForwardGestureEventToRenderer(event); } -bool RenderWidgetHostViewGuest::DispatchCancelTouchEvent( +void RenderWidgetHostViewGuest::DispatchCancelTouchEvent( ui::TouchEvent* event) { if (!host_) - return false; + return; WebKit::WebTouchEvent cancel_event; cancel_event.type = WebKit::WebInputEvent::TouchCancel; cancel_event.timeStampSeconds = event->time_stamp().InSecondsF(); host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency()); - return true; } bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer( diff --git a/content/browser/renderer_host/render_widget_host_view_guest.h b/content/browser/renderer_host/render_widget_host_view_guest.h index 079410b..84435e4 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest.h +++ b/content/browser/renderer_host/render_widget_host_view_guest.h @@ -186,8 +186,9 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest #endif // Overridden from ui::GestureEventHelper. - virtual bool DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE; - virtual bool DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE; + virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE; + virtual void DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE; + virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE; protected: friend class RenderWidgetHostView; diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc index 0694e10..a440e6b 100644 --- a/content/browser/renderer_host/render_widget_host_view_win.cc +++ b/content/browser/renderer_host/render_widget_host_view_win.cc @@ -411,14 +411,16 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget) pointer_down_context_(false), last_touch_location_(-1, -1), touch_events_enabled_(ui::AreTouchEventsEnabled()), - gesture_recognizer_(ui::GestureRecognizer::Create(this)) { + gesture_recognizer_(ui::GestureRecognizer::Create()) { render_widget_host_->SetView(this); registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, NotificationService::AllBrowserContextsAndSources()); + gesture_recognizer_->AddGestureEventHelper(this); } RenderWidgetHostViewWin::~RenderWidgetHostViewWin() { + gesture_recognizer_->RemoveGestureEventHelper(this); UnlockMouse(); ResetTooltip(); } @@ -944,16 +946,22 @@ void RenderWidgetHostViewWin::UpdateDesiredTouchMode() { } } -bool RenderWidgetHostViewWin::DispatchLongPressGestureEvent( +bool RenderWidgetHostViewWin::CanDispatchToConsumer( + ui::GestureConsumer* consumer) { + CHECK_EQ(static_cast<RenderWidgetHostViewWin*>(consumer), this); + return true; +} + +void RenderWidgetHostViewWin::DispatchLongPressGestureEvent( ui::GestureEvent* event) { - return ForwardGestureEventToRenderer(event); + ForwardGestureEventToRenderer(event); } -bool RenderWidgetHostViewWin::DispatchCancelTouchEvent( +void RenderWidgetHostViewWin::DispatchCancelTouchEvent( ui::TouchEvent* event) { if (!render_widget_host_ || !touch_events_enabled_ || !render_widget_host_->ShouldForwardTouchEvent()) { - return false; + return; } DCHECK(event->type() == WebKit::WebInputEvent::TouchCancel); WebKit::WebTouchEvent cancel_event; @@ -961,7 +969,6 @@ bool RenderWidgetHostViewWin::DispatchCancelTouchEvent( cancel_event.timeStampSeconds = event->time_stamp().InSecondsF(); render_widget_host_->ForwardTouchEventWithLatencyInfo( cancel_event, *event->latency()); - return true; } void RenderWidgetHostViewWin::SetHasHorizontalScrollbar( diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h index 84705bb..c9eca60 100644 --- a/content/browser/renderer_host/render_widget_host_view_win.h +++ b/content/browser/renderer_host/render_widget_host_view_win.h @@ -259,8 +259,9 @@ class RenderWidgetHostViewWin virtual void FatalAccessibilityTreeError() OVERRIDE; // Overridden from ui::GestureEventHelper. - virtual bool DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE; - virtual bool DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE; + virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE; + virtual void DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE; + virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE; // Overridden from ui::TextInputClient for Win8/metro TSF support. // Following methods are not used in existing IMM32 related implementation. diff --git a/ui/aura/client/default_capture_client.cc b/ui/aura/client/default_capture_client.cc index 9b5fff5..dae3b7d 100644 --- a/ui/aura/client/default_capture_client.cc +++ b/ui/aura/client/default_capture_client.cc @@ -23,8 +23,8 @@ void DefaultCaptureClient::SetCapture(Window* window) { if (capture_window_ == window) return; if (window) { - root_window_->gesture_recognizer()-> - TransferEventsTo(capture_window_, window); + ui::GestureRecognizer::Get()->TransferEventsTo( + capture_window_, window); } Window* old_capture_window = capture_window_; diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc index 38aca7f..a8db300 100644 --- a/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/ui/aura/gestures/gesture_recognizer_unittest.cc @@ -453,8 +453,8 @@ class TestOneShotGestureSequenceTimer class TimerTestGestureSequence : public ui::GestureSequence { public: - explicit TimerTestGestureSequence(ui::GestureEventHelper* helper) - : ui::GestureSequence(helper) { + explicit TimerTestGestureSequence(ui::GestureSequenceDelegate* delegate) + : ui::GestureSequence(delegate) { } void ForceTimeout() { @@ -476,8 +476,7 @@ class TimerTestGestureSequence : public ui::GestureSequence { class TestGestureRecognizer : public ui::GestureRecognizerImpl { public: - explicit TestGestureRecognizer(RootWindow* root_window) - : GestureRecognizerImpl(root_window) { + TestGestureRecognizer() : GestureRecognizerImpl() { } ui::GestureSequence* GetGestureSequenceForTesting(Window* window) { @@ -490,13 +489,12 @@ class TestGestureRecognizer : public ui::GestureRecognizerImpl { class TimerTestGestureRecognizer : public TestGestureRecognizer { public: - explicit TimerTestGestureRecognizer(RootWindow* root_window) - : TestGestureRecognizer(root_window) { + TimerTestGestureRecognizer() : TestGestureRecognizer() { } virtual ui::GestureSequence* CreateSequence( - ui::GestureEventHelper* helper) OVERRIDE { - return new TimerTestGestureSequence(helper); + ui::GestureSequenceDelegate* delegate) OVERRIDE { + return new TimerTestGestureSequence(delegate); } private: @@ -507,6 +505,26 @@ base::TimeDelta GetTime() { return ui::EventTimeForNow(); } +class ScopedGestureRecognizerSetter { + public: + // Takes ownership of |new_gr|. + explicit ScopedGestureRecognizerSetter(ui::GestureRecognizer* new_gr) + : new_gr_(new_gr) { + original_gr_ = ui::GestureRecognizer::Get(); + ui::SetGestureRecognizerForTesting(new_gr_.get()); + } + + virtual ~ScopedGestureRecognizerSetter() { + ui::SetGestureRecognizerForTesting(original_gr_); + } + + private: + ui::GestureRecognizer* original_gr_; + scoped_ptr<ui::GestureRecognizer> new_gr_; + + DISALLOW_COPY_AND_ASSIGN(ScopedGestureRecognizerSetter); +}; + class TimedEvents { private: int simulated_now_; @@ -1254,9 +1272,9 @@ TEST_F(GestureRecognizerTest, GestureEventLongPress) { delegate->Reset(); TimerTestGestureRecognizer* gesture_recognizer = - new TimerTestGestureRecognizer(root_window()); + new TimerTestGestureRecognizer(); - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201), kTouchId, tes.Now()); @@ -1300,12 +1318,12 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledByScroll) { delegate->Reset(); TimerTestGestureRecognizer* gesture_recognizer = - new TimerTestGestureRecognizer(root_window()); + new TimerTestGestureRecognizer(); TimerTestGestureSequence* gesture_sequence = static_cast<TimerTestGestureSequence*>( gesture_recognizer->GetGestureSequenceForTesting(window.get())); - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201), kTouchId, tes.Now()); @@ -1346,9 +1364,9 @@ TEST_F(GestureRecognizerTest, GestureEventLongTap) { delegate->Reset(); TimerTestGestureRecognizer* gesture_recognizer = - new TimerTestGestureRecognizer(root_window()); + new TimerTestGestureRecognizer(); - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201), kTouchId, tes.Now()); @@ -1392,12 +1410,12 @@ TEST_F(GestureRecognizerTest, GestureEventLongPressCancelledBySecondTap) { delegate.get(), -1234, bounds, root_window())); TimerTestGestureRecognizer* gesture_recognizer = - new TimerTestGestureRecognizer(root_window()); + new TimerTestGestureRecognizer(); TimerTestGestureSequence* gesture_sequence = static_cast<TimerTestGestureSequence*>( gesture_recognizer->GetGestureSequenceForTesting(window.get())); - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); delegate->Reset(); ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201), @@ -2058,10 +2076,9 @@ TEST_F(GestureRecognizerTest, GestureEventIgnoresDisconnectedEvents) { // Check that a touch is locked to the window of the closest current touch // within max_separation_for_gesture_touches_in_pixels TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) { - ui::GestureRecognizer* gesture_recognizer = - new ui::GestureRecognizerImpl(root_window()); + ui::GestureRecognizer* gesture_recognizer = new ui::GestureRecognizerImpl(); TimedEvents tes; - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); ui::GestureConsumer* target; const int kNumWindows = 4; @@ -2146,9 +2163,9 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) { // by the root window's gesture sequence. TEST_F(GestureRecognizerTest, GestureEventOutsideRootWindowTap) { TestGestureRecognizer* gesture_recognizer = - new TestGestureRecognizer(root_window()); + new TestGestureRecognizer(); TimedEvents tes; - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); scoped_ptr<aura::Window> window(CreateTestWindowWithBounds( gfx::Rect(-100, -100, 2000, 2000), root_window())); @@ -2298,8 +2315,8 @@ TEST_F(GestureRecognizerTest, CaptureSendsGestureEnd) { scoped_ptr<GestureEventConsumeDelegate> delegate( new GestureEventConsumeDelegate()); TestGestureRecognizer* gesture_recognizer = - new TestGestureRecognizer(root_window()); - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + new TestGestureRecognizer(); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( delegate.get(), -1234, gfx::Rect(10, 10, 300, 300), root_window())); @@ -2378,8 +2395,8 @@ TEST_F(GestureRecognizerTest, PressDoesNotCrash) { scoped_ptr<GestureEventConsumeDelegate> delegate( new GestureEventConsumeDelegate()); TestGestureRecognizer* gesture_recognizer = - new TestGestureRecognizer(root_window()); - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + new TestGestureRecognizer(); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); TimedEvents tes; scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( @@ -2815,9 +2832,9 @@ TEST_F(GestureRecognizerTest, FlushAllOnHide) { root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2); window->Hide(); EXPECT_EQ(NULL, - root_window()->gesture_recognizer()->GetTouchLockedTarget(&press1)); + ui::GestureRecognizer::Get()->GetTouchLockedTarget(&press1)); EXPECT_EQ(NULL, - root_window()->gesture_recognizer()->GetTouchLockedTarget(&press2)); + ui::GestureRecognizer::Get()->GetTouchLockedTarget(&press2)); } TEST_F(GestureRecognizerTest, LongPressTimerStopsOnPreventDefaultedTouchMoves) { @@ -2831,12 +2848,12 @@ TEST_F(GestureRecognizerTest, LongPressTimerStopsOnPreventDefaultedTouchMoves) { TimedEvents tes; TimerTestGestureRecognizer* gesture_recognizer = - new TimerTestGestureRecognizer(root_window()); + new TimerTestGestureRecognizer(); TimerTestGestureSequence* gesture_sequence = static_cast<TimerTestGestureSequence*>( gesture_recognizer->GetGestureSequenceForTesting(window.get())); - root_window()->SetGestureRecognizerForTesting(gesture_recognizer); + ScopedGestureRecognizerSetter gr_setter(gesture_recognizer); delegate->Reset(); ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201), diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 9014524..500f307 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -145,7 +145,6 @@ RootWindow::RootWindow(const CreateParams& params) mouse_pressed_handler_(NULL), mouse_moved_handler_(NULL), event_dispatch_target_(NULL), - gesture_recognizer_(ui::GestureRecognizer::Create(this)), synthesize_mouse_move_(false), move_hold_count_(0), event_factory_(this), @@ -159,11 +158,14 @@ RootWindow::RootWindow(const CreateParams& params) prop_.reset(new ui::ViewProp(host_->GetAcceleratedWidget(), kRootWindowForAcceleratedWidget, this)); + ui::GestureRecognizer::Get()->AddGestureEventHelper(this); } RootWindow::~RootWindow() { TRACE_EVENT0("shutdown", "RootWindow::Destructor"); + ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this); + // Make sure to destroy the compositor before terminating so that state is // cleared and we don't hit asserts. compositor_.reset(); @@ -324,7 +326,7 @@ Window* RootWindow::GetGestureTarget(ui::GestureEvent* event) { Window* target = client::GetCaptureWindow(this); if (!target) { target = ConsumerToWindow( - gesture_recognizer_->GetTargetForGestureEvent(event)); + ui::GestureRecognizer::Get()->GetTargetForGestureEvent(event)); } return target; @@ -445,15 +447,11 @@ void RootWindow::ProcessedTouchEvent(ui::TouchEvent* event, Window* window, ui::EventResult result) { scoped_ptr<ui::GestureRecognizer::Gestures> gestures; - gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture( - *event, result, window)); + gestures.reset(ui::GestureRecognizer::Get()-> + ProcessTouchEventForGesture(*event, result, window)); ProcessGestures(gestures.get()); } -void RootWindow::SetGestureRecognizerForTesting(ui::GestureRecognizer* gr) { - gesture_recognizer_.reset(gr); -} - gfx::AcceleratedWidget RootWindow::GetAcceleratedWidget() { return host_->GetAcceleratedWidget(); } @@ -656,7 +654,7 @@ void RootWindow::OnWindowHidden(Window* invisible, WindowHiddenReason reason) { } void RootWindow::CleanupGestureRecognizerState(Window* window) { - gesture_recognizer_->CleanupStateForConsumer(window); + ui::GestureRecognizer::Get()->CleanupStateForConsumer(window); const Windows& windows = window->children(); for (Windows::const_iterator iter = windows.begin(); iter != windows.end(); @@ -712,14 +710,6 @@ void RootWindow::OnDeviceScaleFactorChanged( void RootWindow::UpdateCapture(Window* old_capture, Window* new_capture) { - if (!new_capture && old_capture && old_capture->GetRootWindow() != this) { - // If we no longer contain the window that had capture make sure we clean - // state in the GestureRecognizer. Since we don't contain the window we'll - // never get notification of its destruction and clean up state. - // We do this early on as OnCaptureLost() may delete |old_capture|. - gesture_recognizer_->CleanupStateForConsumer(old_capture); - } - // |mouse_moved_handler_| may have been set to a Window in a different root // (see below). Clear it here to ensure we don't end up referencing a stale // Window. @@ -767,12 +757,17 @@ bool RootWindow::CanDispatchToTarget(ui::EventTarget* target) { //////////////////////////////////////////////////////////////////////////////// // RootWindow, ui::GestureEventHelper implementation: -bool RootWindow::DispatchLongPressGestureEvent(ui::GestureEvent* event) { - return DispatchGestureEvent(event); +bool RootWindow::CanDispatchToConsumer(ui::GestureConsumer* consumer) { + Window* window = ConsumerToWindow(consumer);; + return (window && window->GetRootWindow() == this); +} + +void RootWindow::DispatchLongPressGestureEvent(ui::GestureEvent* event) { + DispatchGestureEvent(event); } -bool RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) { - return OnHostTouchEvent(event); +void RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) { + OnHostTouchEvent(event); } //////////////////////////////////////////////////////////////////////////////// @@ -1062,10 +1057,10 @@ bool RootWindow::DispatchTouchEventImpl(ui::TouchEvent* event) { Window* target = client::GetCaptureWindow(this); if (!target) { target = ConsumerToWindow( - gesture_recognizer_->GetTouchLockedTarget(event)); + ui::GestureRecognizer::Get()->GetTouchLockedTarget(event)); if (!target) { - target = ConsumerToWindow( - gesture_recognizer_->GetTargetForLocation(event->location())); + target = ConsumerToWindow(ui::GestureRecognizer::Get()-> + GetTargetForLocation(event->location())); } } @@ -1096,8 +1091,8 @@ bool RootWindow::DispatchTouchEventImpl(ui::TouchEvent* event) { // Get the list of GestureEvents from GestureRecognizer. scoped_ptr<ui::GestureRecognizer::Gestures> gestures; - gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture( - event_for_gr, result, target)); + gestures.reset(ui::GestureRecognizer::Get()-> + ProcessTouchEventForGesture(event_for_gr, result, target)); return ProcessGestures(gestures.get()) ? true : handled; } diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index b8c4455..7c84fa7 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -208,13 +208,6 @@ class AURA_EXPORT RootWindow : public Window, Window* window, ui::EventResult result); - ui::GestureRecognizer* gesture_recognizer() const { - return gesture_recognizer_.get(); - } - - // Provided only for testing: - void SetGestureRecognizerForTesting(ui::GestureRecognizer* gr); - // Returns the accelerated widget from the RootWindowHost. gfx::AcceleratedWidget GetAcceleratedWidget(); @@ -318,8 +311,9 @@ class AURA_EXPORT RootWindow : public Window, virtual bool CanDispatchToTarget(EventTarget* target) OVERRIDE; // Overridden from ui::GestureEventHelper. - virtual bool DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE; - virtual bool DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE; + virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE; + virtual void DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE; + virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE; // Overridden from ui::LayerAnimationObserver: virtual void OnLayerAnimationEnded( @@ -386,9 +380,6 @@ class AURA_EXPORT RootWindow : public Window, Window* mouse_moved_handler_; Window* event_dispatch_target_; - // The gesture_recognizer_ for this. - scoped_ptr<ui::GestureRecognizer> gesture_recognizer_; - bool synthesize_mouse_move_; bool waiting_on_compositing_end_; bool draw_on_compositing_end_; diff --git a/ui/events/gestures/gesture_recognizer.h b/ui/events/gestures/gesture_recognizer.h index 604dd41..fd5136d 100644 --- a/ui/events/gestures/gesture_recognizer.h +++ b/ui/events/gestures/gesture_recognizer.h @@ -17,7 +17,8 @@ namespace ui { // into gestures. class EVENTS_EXPORT GestureRecognizer { public: - static GestureRecognizer* Create(GestureEventHelper* helper); + static GestureRecognizer* Create(); + static GestureRecognizer* Get(); // List of GestureEvent*. typedef ScopedVector<GestureEvent> Gestures; @@ -64,6 +65,17 @@ class EVENTS_EXPORT GestureRecognizer { // |consumer| false is returned and |point| is untouched. virtual bool GetLastTouchPointForTarget(GestureConsumer* consumer, gfx::Point* point) = 0; + + // Subscribes |helper| for dispatching async gestures such as long press. + // The Gesture Recognizer does NOT take ownership of |helper| and it is the + // responsibility of the |helper| to call |RemoveGestureEventHelper()| on + // destruction. + virtual void AddGestureEventHelper(GestureEventHelper* helper) = 0; + + // Unsubscribes |helper| from async gesture dispatch. + // Since the GestureRecognizer does not own the |helper|, it is not deleted + // and must be cleaned up appropriately by the caller. + virtual void RemoveGestureEventHelper(GestureEventHelper* helper) = 0; }; } // namespace ui diff --git a/ui/events/gestures/gesture_recognizer_impl.cc b/ui/events/gestures/gesture_recognizer_impl.cc index a472a0c..3e1d02a 100644 --- a/ui/events/gestures/gesture_recognizer_impl.cc +++ b/ui/events/gestures/gesture_recognizer_impl.cc @@ -99,8 +99,7 @@ void TransferTouchIdToConsumerMap( //////////////////////////////////////////////////////////////////////////////// // GestureRecognizerImpl, public: -GestureRecognizerImpl::GestureRecognizerImpl(GestureEventHelper* helper) - : helper_(helper) { +GestureRecognizerImpl::GestureRecognizerImpl() { gesture_consumer_ignorer_.reset(new GestureConsumerIgnorer()); } @@ -159,13 +158,15 @@ void GestureRecognizerImpl::TransferEventsTo(GestureConsumer* current_consumer, // Don't send a cancel to |current_consumer|, unless |new_consumer| is NULL. for (TouchIdToConsumerMap::iterator i = touch_id_target_.begin(); i != touch_id_target_.end(); ++i) { - if (i->second != new_consumer && + if (i->second && i->second != new_consumer && (i->second != current_consumer || new_consumer == NULL) && i->second != gesture_consumer_ignorer_.get()) { TouchEvent touch_event(ui::ET_TOUCH_CANCELLED, gfx::Point(0, 0), ui::EF_IS_SYNTHESIZED, i->first, ui::EventTimeForNow(), 0.0f, 0.0f, 0.0f, 0.0f); - helper_->DispatchCancelTouchEvent(&touch_event); + GestureEventHelper* helper = FindDispatchHelperForConsumer(i->second); + if (helper) + helper->DispatchCancelTouchEvent(&touch_event); DCHECK_EQ(gesture_consumer_ignorer_.get(), i->second); } } @@ -194,8 +195,8 @@ bool GestureRecognizerImpl::GetLastTouchPointForTarget( // GestureRecognizerImpl, protected: GestureSequence* GestureRecognizerImpl::CreateSequence( - GestureEventHelper* helper) { - return new GestureSequence(helper); + GestureSequenceDelegate* delegate) { + return new GestureSequence(delegate); } //////////////////////////////////////////////////////////////////////////////// @@ -205,7 +206,7 @@ GestureSequence* GestureRecognizerImpl::GetGestureSequenceForConsumer( GestureConsumer* consumer) { GestureSequence* gesture_sequence = consumer_sequence_[consumer]; if (!gesture_sequence) { - gesture_sequence = CreateSequence(helper_); + gesture_sequence = CreateSequence(this); consumer_sequence_[consumer] = gesture_sequence; } return gesture_sequence; @@ -243,9 +244,62 @@ void GestureRecognizerImpl::CleanupStateForConsumer(GestureConsumer* consumer) { RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); } +void GestureRecognizerImpl::AddGestureEventHelper(GestureEventHelper* helper) { + helpers_.push_back(helper); +} + +void GestureRecognizerImpl::RemoveGestureEventHelper( + GestureEventHelper* helper) { + std::vector<GestureEventHelper*>::iterator it = std::find(helpers_.begin(), + helpers_.end(), helper); + if (it != helpers_.end()) + helpers_.erase(it); +} + +void GestureRecognizerImpl::DispatchLongPressGestureEvent(GestureEvent* event) { + GestureConsumer* consumer = GetTargetForGestureEvent(event); + if (consumer) { + GestureEventHelper* helper = FindDispatchHelperForConsumer(consumer); + if (helper) + helper->DispatchLongPressGestureEvent(event); + } +} + +GestureEventHelper* GestureRecognizerImpl::FindDispatchHelperForConsumer( + GestureConsumer* consumer) { + std::vector<GestureEventHelper*>::iterator it; + for (it = helpers_.begin(); it != helpers_.end(); ++it) { + if ((*it)->CanDispatchToConsumer(consumer)) + return (*it); + } + return NULL; +} + // GestureRecognizer, static -GestureRecognizer* GestureRecognizer::Create(GestureEventHelper* helper) { - return new GestureRecognizerImpl(helper); +GestureRecognizer* GestureRecognizer::Create() { + return new GestureRecognizerImpl(); +} + +static GestureRecognizerImpl* g_gesture_recognizer_instance = NULL; + +// GestureRecognizer, static +GestureRecognizer* GestureRecognizer::Get() { + if (!g_gesture_recognizer_instance) + g_gesture_recognizer_instance = new GestureRecognizerImpl(); + return g_gesture_recognizer_instance; +} + +void SetGestureRecognizerForTesting(GestureRecognizer* gesture_recognizer) { + // Transfer helpers to the new GR. + std::vector<GestureEventHelper*>& helpers = + g_gesture_recognizer_instance->helpers(); + std::vector<GestureEventHelper*>::iterator it; + for (it = helpers.begin(); it != helpers.end(); ++it) + gesture_recognizer->AddGestureEventHelper(*it); + + helpers.clear(); + g_gesture_recognizer_instance = + static_cast<GestureRecognizerImpl*>(gesture_recognizer); } } // namespace ui diff --git a/ui/events/gestures/gesture_recognizer_impl.h b/ui/events/gestures/gesture_recognizer_impl.h index 2ede77d5..35ddaac 100644 --- a/ui/events/gestures/gesture_recognizer_impl.h +++ b/ui/events/gestures/gesture_recognizer_impl.h @@ -13,6 +13,7 @@ #include "ui/events/event_constants.h" #include "ui/events/events_export.h" #include "ui/events/gestures/gesture_recognizer.h" +#include "ui/events/gestures/gesture_sequence.h" #include "ui/gfx/point.h" namespace ui { @@ -22,13 +23,16 @@ class GestureEventHelper; class GestureSequence; class TouchEvent; -class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer { +class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer, + public GestureSequenceDelegate { public: typedef std::map<int, GestureConsumer*> TouchIdToConsumerMap; - explicit GestureRecognizerImpl(GestureEventHelper* helper); + GestureRecognizerImpl(); virtual ~GestureRecognizerImpl(); + std::vector<GestureEventHelper*>& helpers() { return helpers_; } + // Overridden from GestureRecognizer virtual GestureConsumer* GetTouchLockedTarget(TouchEvent* event) OVERRIDE; virtual GestureConsumer* GetTargetForGestureEvent( @@ -41,7 +45,7 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer { gfx::Point* point) OVERRIDE; protected: - virtual GestureSequence* CreateSequence(GestureEventHelper* helper); + virtual GestureSequence* CreateSequence(GestureSequenceDelegate* delegate); virtual GestureSequence* GetGestureSequenceForConsumer(GestureConsumer* c); private: @@ -54,6 +58,15 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer { ui::EventResult result, GestureConsumer* target) OVERRIDE; virtual void CleanupStateForConsumer(GestureConsumer* consumer) OVERRIDE; + virtual void AddGestureEventHelper(GestureEventHelper* helper) OVERRIDE; + virtual void RemoveGestureEventHelper(GestureEventHelper* helper) OVERRIDE; + + // Overridden from ui::GestureSequenceDelegate. + virtual void DispatchLongPressGestureEvent(GestureEvent* event) OVERRIDE; + + // Convenience method to find the GestureEventHelper that can dispatch events + // to a specific |consumer|. + GestureEventHelper* FindDispatchHelperForConsumer(GestureConsumer* consumer); std::map<GestureConsumer*, GestureSequence*> consumer_sequence_; @@ -67,11 +80,16 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer { // Touches cancelled by touch capture are routed to the // gesture_consumer_ignorer_. scoped_ptr<GestureConsumer> gesture_consumer_ignorer_; - GestureEventHelper* helper_; + + std::vector<GestureEventHelper*> helpers_; DISALLOW_COPY_AND_ASSIGN(GestureRecognizerImpl); }; +// Provided only for testing: +EVENTS_EXPORT void SetGestureRecognizerForTesting( + GestureRecognizer* gesture_recognizer); + } // namespace ui #endif // UI_EVENTS_GESTURES_GESTURE_RECOGNIZER_IMPL_H_ diff --git a/ui/events/gestures/gesture_sequence.cc b/ui/events/gestures/gesture_sequence.cc index d364ed2..e728cbc 100644 --- a/ui/events/gestures/gesture_sequence.cc +++ b/ui/events/gestures/gesture_sequence.cc @@ -381,14 +381,15 @@ void UpdateGestureEventLatencyInfo(const TouchEvent& event, //////////////////////////////////////////////////////////////////////////////// // GestureSequence Public: -GestureSequence::GestureSequence(GestureEventHelper* helper) +GestureSequence::GestureSequence(GestureSequenceDelegate* delegate) : state_(GS_NO_GESTURE), flags_(0), pinch_distance_start_(0.f), pinch_distance_current_(0.f), scroll_type_(ST_FREE), point_count_(0), - helper_(helper) { + delegate_(delegate) { + CHECK(delegate_); } GestureSequence::~GestureSequence() { @@ -1057,7 +1058,7 @@ void GestureSequence::AppendLongPressGestureEvent() { flags_, base::Time::FromDoubleT(point->last_touch_time()), 1 << point->touch_id())); - helper_->DispatchLongPressGestureEvent(gesture.get()); + delegate_->DispatchLongPressGestureEvent(gesture.get()); } void GestureSequence::AppendLongTapGestureEvent(const GesturePoint& point, diff --git a/ui/events/gestures/gesture_sequence.h b/ui/events/gestures/gesture_sequence.h index 50d9000..9715194 100644 --- a/ui/events/gestures/gesture_sequence.h +++ b/ui/events/gestures/gesture_sequence.h @@ -31,13 +31,23 @@ enum ScrollType { ST_VERTICAL, }; +// Delegates dispatch of gesture events for which the GestureSequence does not +// have enough context to dispatch itself. +class EVENTS_EXPORT GestureSequenceDelegate { + public: + virtual void DispatchLongPressGestureEvent(GestureEvent* event) = 0; + + protected: + virtual ~GestureSequenceDelegate() {} +}; + // A GestureSequence recognizes gestures from touch sequences. class EVENTS_EXPORT GestureSequence { public: // Maximum number of points in a single gesture. static const int kMaxGesturePoints = 12; - explicit GestureSequence(GestureEventHelper* consumer); + explicit GestureSequence(GestureSequenceDelegate* delegate); virtual ~GestureSequence(); typedef GestureRecognizer::Gestures Gestures; @@ -219,7 +229,7 @@ class EVENTS_EXPORT GestureSequence { // Location of the last touch event. gfx::Point last_touch_location_; - GestureEventHelper* helper_; + GestureSequenceDelegate* delegate_; DISALLOW_COPY_AND_ASSIGN(GestureSequence); }; diff --git a/ui/events/gestures/gesture_types.h b/ui/events/gestures/gesture_types.h index e87a219..b15788a 100644 --- a/ui/events/gestures/gesture_types.h +++ b/ui/events/gestures/gesture_types.h @@ -206,8 +206,10 @@ class EVENTS_EXPORT GestureEventHelper { virtual ~GestureEventHelper() { } - virtual bool DispatchLongPressGestureEvent(GestureEvent* event) = 0; - virtual bool DispatchCancelTouchEvent(TouchEvent* event) = 0; + // Returns true if this helper can dispatch events to |consumer|. + virtual bool CanDispatchToConsumer(GestureConsumer* consumer) = 0; + virtual void DispatchLongPressGestureEvent(GestureEvent* event) = 0; + virtual void DispatchCancelTouchEvent(TouchEvent* event) = 0; }; } // namespace ui diff --git a/ui/views/corewm/capture_controller.cc b/ui/views/corewm/capture_controller.cc index c39a9ab..1276c82b 100644 --- a/ui/views/corewm/capture_controller.cc +++ b/ui/views/corewm/capture_controller.cc @@ -49,11 +49,8 @@ void CaptureController::SetCapture(aura::Window* new_capture_window) { // along (and so shouldn't be canceled) and those that got moved, so // just leave them all where they are. if (new_capture_window) { - for (RootWindows::const_iterator i = root_windows.begin(); - i != root_windows.end(); ++i) { - (*i)->gesture_recognizer()->TransferEventsTo( - old_capture_window, new_capture_window); - } + ui::GestureRecognizer::Get()->TransferEventsTo(old_capture_window, + new_capture_window); } capture_window_ = new_capture_window; diff --git a/ui/views/corewm/capture_controller_unittest.cc b/ui/views/corewm/capture_controller_unittest.cc index 46a8a2e..edb2410 100644 --- a/ui/views/corewm/capture_controller_unittest.cc +++ b/ui/views/corewm/capture_controller_unittest.cc @@ -161,8 +161,8 @@ TEST_F(CaptureControllerTest, TouchTargetResetOnCaptureChange) { ui::TouchEvent touch_event( ui::ET_TOUCH_PRESSED, gfx::Point(), 0, 0, ui::EventTimeForNow(), 1.0f, 1.0f, 1.0f, 1.0f); - EXPECT_EQ(static_cast<ui::GestureConsumer*>(NULL), - root_window()->gesture_recognizer()->GetTouchLockedTarget( + EXPECT_EQ(static_cast<ui::GestureConsumer*>(w2.get()), + ui::GestureRecognizer::Get()->GetTouchLockedTarget( &touch_event)); } diff --git a/ui/views/widget/desktop_aura/desktop_capture_client.cc b/ui/views/widget/desktop_aura/desktop_capture_client.cc index 118b5f2..5a5ec4e 100644 --- a/ui/views/widget/desktop_aura/desktop_capture_client.cc +++ b/ui/views/widget/desktop_aura/desktop_capture_client.cc @@ -48,10 +48,8 @@ void DesktopCaptureClient::SetCapture(aura::Window* new_capture_window) { // along (and so shouldn't be canceled) and those that got moved, so // just leave them all where they are. if (new_capture_window) { - for (Roots::const_iterator i = roots.begin(); i != roots.end(); ++i) { - (*i)->gesture_recognizer()->TransferEventsTo( - old_capture_window, new_capture_window); - } + ui::GestureRecognizer::Get()->TransferEventsTo(old_capture_window, + new_capture_window); } capture_window_ = new_capture_window; |