diff options
author | tdresser@chromium.org <tdresser@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-17 19:25:25 +0000 |
---|---|---|
committer | tdresser@chromium.org <tdresser@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-17 19:25:25 +0000 |
commit | cc1fad52a7d5f4317d63404022a251724e13f667 (patch) | |
tree | a64da9f22c64fdd6c000d01983049e7fd029cab0 /ui/aura | |
parent | a58c97e519a34d9d48d6154f37e7d44346ada85e (diff) | |
download | chromium_src-cc1fad52a7d5f4317d63404022a251724e13f667.zip chromium_src-cc1fad52a7d5f4317d63404022a251724e13f667.tar.gz chromium_src-cc1fad52a7d5f4317d63404022a251724e13f667.tar.bz2 |
On touch capture, cancel non-captured touches.
When a touch capture occurs, any touches locked to other windows are cancelled.
These touches are then locked to a GestureConsumer which ignores all
further events, until the touch is released.
BUG=123211
TEST=WindowTest.TouchCaptureCancelsOtherTouches, TouchCaptureDoesntCancelCapturedTouches
Review URL: http://codereview.chromium.org/10038030
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132619 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/aura')
-rw-r--r-- | ui/aura/root_window.cc | 78 | ||||
-rw-r--r-- | ui/aura/root_window.h | 7 | ||||
-rw-r--r-- | ui/aura/window_unittest.cc | 76 |
3 files changed, 134 insertions, 27 deletions
diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 2254ff4..d443d62 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -268,39 +268,45 @@ bool RootWindow::DispatchTouchEvent(TouchEvent* event) { event->UpdateForRootTransform(layer()->transform()); bool handled = false; - Window* target = NULL; - if (HasCapture(capture_window_, ui::CW_LOCK_TOUCH)) - target = capture_window_; - - if (!target) - target = static_cast<Window*>( - gesture_recognizer_->GetTargetForTouchEvent(event)); - + GestureConsumer* consumer = gesture_recognizer_->GetTouchLockedTarget(event); ui::TouchStatus status = ui::TOUCH_STATUS_UNKNOWN; - if (!target && !bounds().Contains(event->location())) { - // If the touch is outside the root window, set its target to the - // root window. - target = this; - } else { - if (!target) - target = GetEventHandlerForPoint(event->location()); - if (!target) - return false; + if (!consumer || !consumer->ignores_events()) { + Window* target = static_cast<Window*>(consumer); - TouchEvent translated_event(*event, this, target); - status = ProcessTouchEvent(target, &translated_event); - handled = status != ui::TOUCH_STATUS_UNKNOWN; + if (!target && HasCapture(capture_window_, ui::CW_LOCK_TOUCH)) + target = capture_window_; + + if (!target) { + target = static_cast<Window*>( + gesture_recognizer_->GetTargetForLocation(event->GetLocation())); + } - if (status == ui::TOUCH_STATUS_QUEUED || - status == ui::TOUCH_STATUS_QUEUED_END) - gesture_recognizer_->QueueTouchEventForGesture(target, *event); + if (!target && !bounds().Contains(event->location())) { + // If the touch is outside the root window, set its target to the + // root window. + target = this; + } else { + if (!target) + target = GetEventHandlerForPoint(event->location()); + if (!target) + return false; + + TouchEvent translated_event(*event, this, target); + status = ProcessTouchEvent(target, &translated_event); + handled = status != ui::TOUCH_STATUS_UNKNOWN; + + if (status == ui::TOUCH_STATUS_QUEUED || + status == ui::TOUCH_STATUS_QUEUED_END) + gesture_recognizer_->QueueTouchEventForGesture(target, *event); + } + consumer = target; } // Get the list of GestureEvents from GestureRecognizer. scoped_ptr<ui::GestureRecognizer::Gestures> gestures; gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture( - *event, status, target)); + *event, status, consumer)); if (ProcessGestures(gestures.get())) handled = true; @@ -313,9 +319,13 @@ bool RootWindow::DispatchGestureEvent(GestureEvent* event) { Window* target = NULL; if (HasCapture(capture_window_, ui::CW_LOCK_TOUCH)) target = capture_window_; - if (!target) - target = static_cast<Window*>( - gesture_recognizer_->GetTargetForGestureEvent(event)); + if (!target) { + GestureConsumer* consumer = + gesture_recognizer_->GetTargetForGestureEvent(event); + if (consumer->ignores_events()) + return false; + target = static_cast<Window*>(consumer); + } if (target) { GestureEvent translated_event(*event, this, target); @@ -407,6 +417,9 @@ void RootWindow::SetCapture(Window* window, unsigned int flags) { if (capture_window_ == window && flags == capture_window_flags_) return; + if (flags & ui::CW_LOCK_TOUCH) + gesture_recognizer_->CancelNonCapturedTouches(window); + aura::Window* old_capture_window = capture_window_; capture_window_ = window; capture_window_flags_ = flags; @@ -782,6 +795,10 @@ bool RootWindow::DispatchLongPressGestureEvent(ui::GestureEvent* event) { return DispatchGestureEvent(static_cast<GestureEvent*>(event)); } +bool RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) { + return DispatchTouchEvent(static_cast<TouchEvent*>(event)); +} + ui::GestureEvent* RootWindow::CreateGestureEvent(ui::EventType type, const gfx::Point& location, int flags, @@ -793,6 +810,13 @@ ui::GestureEvent* RootWindow::CreateGestureEvent(ui::EventType type, param_first, param_second, touch_id_bitfield); } +ui::TouchEvent* RootWindow::CreateTouchEvent(ui::EventType type, + const gfx::Point& location, + int touch_id, + base::TimeDelta time_stamp) { + return new TouchEvent(type, location, touch_id, time_stamp); +} + void RootWindow::OnLayerAnimationEnded( ui::LayerAnimationSequence* animation) { OnHostResized(host_->GetBounds().size()); diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index 140543e..dd6f533 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -294,7 +294,14 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, float param_first, float param_second, unsigned int touch_id_bitfield) OVERRIDE; + + virtual ui::TouchEvent* CreateTouchEvent(ui::EventType type, + const gfx::Point& location, + int touch_id, + base::TimeDelta time_stamp) OVERRIDE; + virtual bool DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE; + virtual bool DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE; // Overridden from ui::LayerAnimationObserver: virtual void OnLayerAnimationEnded( diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index dd95610..30c5dd0 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -125,6 +125,7 @@ class CaptureWindowDelegateImpl : public TestWindowDelegate { capture_lost_count_ = 0; mouse_event_count_ = 0; touch_event_count_ = 0; + gesture_event_count_ = 0; } int capture_changed_event_count() const { @@ -133,6 +134,7 @@ class CaptureWindowDelegateImpl : public TestWindowDelegate { int capture_lost_count() const { return capture_lost_count_; } int mouse_event_count() const { return mouse_event_count_; } int touch_event_count() const { return touch_event_count_; } + int gesture_event_count() const { return gesture_event_count_; } virtual bool OnMouseEvent(MouseEvent* event) OVERRIDE { if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED) @@ -145,6 +147,7 @@ class CaptureWindowDelegateImpl : public TestWindowDelegate { return ui::TOUCH_STATUS_UNKNOWN; } virtual ui::GestureStatus OnGestureEvent(GestureEvent* event) OVERRIDE { + gesture_event_count_++; return ui::GESTURE_STATUS_UNKNOWN; } virtual void OnCaptureLost() OVERRIDE { @@ -156,6 +159,7 @@ class CaptureWindowDelegateImpl : public TestWindowDelegate { int capture_lost_count_; int mouse_event_count_; int touch_event_count_; + int gesture_event_count_; DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl); }; @@ -626,6 +630,78 @@ TEST_F(WindowTest, CaptureTests) { EXPECT_EQ(NULL, root_window()->capture_window()); } +TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) { + CaptureWindowDelegateImpl delegate1; + scoped_ptr<Window> w1(CreateTestWindowWithDelegate( + &delegate1, 0, gfx::Rect(0, 0, 20, 20), NULL)); + CaptureWindowDelegateImpl delegate2; + scoped_ptr<Window> w2(CreateTestWindowWithDelegate( + &delegate2, 0, gfx::Rect(20, 20, 20, 20), NULL)); + + // Press on w1. + TouchEvent press(ui::ET_TOUCH_PRESSED, + gfx::Point(10, 10), 0, getTime()); + root_window()->DispatchTouchEvent(&press); + EXPECT_EQ(1, delegate1.gesture_event_count()); + delegate1.ResetCounts(); + w2->SetCapture(ui::CW_LOCK_TOUCH); + + // The touch was cancelled when the other window + // attained a touch lock. + EXPECT_EQ(1, delegate1.touch_event_count()); + EXPECT_EQ(0, delegate2.touch_event_count()); + + delegate1.ResetCounts(); + delegate2.ResetCounts(); + + TouchEvent move(ui::ET_TOUCH_MOVED, + gfx::Point(10, 10), 0, getTime()); + root_window()->DispatchTouchEvent(&move); + + // This touch id is now ignored, no scroll fired. + EXPECT_EQ(0, delegate1.gesture_event_count()); + EXPECT_EQ(0, delegate2.gesture_event_count()); + + TouchEvent release(ui::ET_TOUCH_RELEASED, + gfx::Point(10, 10), 0, getTime()); + root_window()->DispatchTouchEvent(&release); + EXPECT_EQ(0, delegate1.gesture_event_count()); + EXPECT_EQ(0, delegate2.gesture_event_count()); + + // A new press is captured by w2. + + TouchEvent press2(ui::ET_TOUCH_PRESSED, + gfx::Point(10, 10), 0, getTime()); + root_window()->DispatchTouchEvent(&press2); + EXPECT_EQ(0, delegate1.gesture_event_count()); + EXPECT_EQ(1, delegate2.gesture_event_count()); +} + +TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) { + CaptureWindowDelegateImpl delegate; + scoped_ptr<Window> window(CreateTestWindowWithDelegate( + &delegate, 0, gfx::Rect(0, 0, 20, 20), NULL)); + + TouchEvent press(ui::ET_TOUCH_PRESSED, + gfx::Point(10, 10), 0, getTime()); + root_window()->DispatchTouchEvent(&press); + + EXPECT_EQ(1, delegate.gesture_event_count()); + delegate.ResetCounts(); + + window->SetCapture(ui::CW_LOCK_TOUCH); + EXPECT_EQ(0, delegate.gesture_event_count()); + delegate.ResetCounts(); + + // The move event should still create a gesture, as this touch was + // on the window which was captured. + TouchEvent release(ui::ET_TOUCH_RELEASED, + gfx::Point(10, 10), 0, getTime() + + base::TimeDelta::FromMilliseconds(50)); + root_window()->DispatchTouchEvent(&release); + EXPECT_EQ(1, delegate.gesture_event_count()); +} + // Changes capture while capture is already ongoing. TEST_F(WindowTest, ChangeCaptureWhileMouseDown) { CaptureWindowDelegateImpl delegate; |