diff options
-rw-r--r-- | ui/aura/root_window.cc | 13 | ||||
-rw-r--r-- | ui/aura/root_window.h | 4 | ||||
-rw-r--r-- | ui/aura/root_window_unittest.cc | 38 |
3 files changed, 54 insertions, 1 deletions
diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 8e96cba..aba54cb 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -747,7 +747,18 @@ void RootWindow::OnWindowHidden(Window* invisible, bool destroyed) { mouse_event_dispatch_target_ = NULL; if (invisible->Contains(event_dispatch_target_)) event_dispatch_target_ = NULL; - gesture_recognizer_->FlushTouchQueue(invisible); + + CleanupGestureRecognizerState(invisible); +} + +void RootWindow::CleanupGestureRecognizerState(Window* window) { + gesture_recognizer_->FlushTouchQueue(window); + Windows windows = window->children(); + for (Windows::const_iterator iter = windows.begin(); + iter != windows.end(); + ++iter) { + CleanupGestureRecognizerState(*iter); + } } void RootWindow::OnWindowAddedToRootWindow(Window* attached) { diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index 9db3aa4..3dac081 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -293,6 +293,10 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // |destroyed| is set to true when the window is being destroyed. void OnWindowHidden(Window* invisible, bool destroyed); + // Cleans up the gesture recognizer for all windows in |window| (including + // |window| itself). + void CleanupGestureRecognizerState(Window* window); + // Overridden from ui::EventDispatcher. virtual bool CanDispatchToTarget(EventTarget* target) OVERRIDE; virtual void ProcessPreTargetList(ui::EventHandlerList* list) OVERRIDE; diff --git a/ui/aura/root_window_unittest.cc b/ui/aura/root_window_unittest.cc index 7e9e093..cc7a729 100644 --- a/ui/aura/root_window_unittest.cc +++ b/ui/aura/root_window_unittest.cc @@ -742,4 +742,42 @@ TEST_F(RootWindowTest, DeleteWindowDuringDispatch) { EXPECT_FALSE(d11.got_event()); } +namespace { + +// A window delegate that detaches the parent of the target's parent window when +// it receives a tap event. +class DetachesParentOnTapDelegate : public test::TestWindowDelegate { + public: + DetachesParentOnTapDelegate() {} + virtual ~DetachesParentOnTapDelegate() {} + + private: + virtual ui::EventResult OnGestureEvent(ui::GestureEvent* event) OVERRIDE { + if (event->type() == ui::ET_GESTURE_TAP_DOWN) + return ui::ER_HANDLED; + + if (event->type() == ui::ET_GESTURE_TAP) { + Window* parent = static_cast<Window*>(event->target())->parent(); + parent->parent()->RemoveChild(parent); + return ui::ER_HANDLED; + } + return ui::ER_UNHANDLED; + } + + DISALLOW_COPY_AND_ASSIGN(DetachesParentOnTapDelegate); +}; + +} // namespace + +// Tests that the gesture recognizer is reset for all child windows when a +// window hides. No expectations, just checks that the test does not crash. +TEST_F(RootWindowTest, GestureRecognizerResetsTargetWhenParentHides) { + scoped_ptr<Window> w1(CreateWindow(1, root_window(), NULL)); + DetachesParentOnTapDelegate delegate; + scoped_ptr<Window> parent(CreateWindow(22, w1.get(), NULL)); + Window* child = CreateWindow(11, parent.get(), &delegate); + test::EventGenerator generator(root_window(), child); + generator.GestureTapAt(gfx::Point(40, 40)); +} + } // namespace aura |