diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-28 16:29:20 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-28 16:29:20 +0000 |
commit | d5e3c65c19d58df811c624c8736e0aff7b1ad3cb (patch) | |
tree | e6df64ce7282f2fc397d466ac6afbb15384a7876 /ui/aura/window_event_dispatcher_unittest.cc | |
parent | ffa95137c87a13264831d6038db4600368495c9e (diff) | |
download | chromium_src-d5e3c65c19d58df811c624c8736e0aff7b1ad3cb.zip chromium_src-d5e3c65c19d58df811c624c8736e0aff7b1ad3cb.tar.gz chromium_src-d5e3c65c19d58df811c624c8736e0aff7b1ad3cb.tar.bz2 |
aura: Fix a crash related to nested event-dispatch.
If events are being dispatched from a nested message-loop, and the target of the
outer loop is hidden or moved to another dispatcher during dispatching events in
the inner loop, then reset the target for the outer loop.
BUG=347012
R=sky@chromium.org
Review URL: https://codereview.chromium.org/180973007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254150 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/aura/window_event_dispatcher_unittest.cc')
-rw-r--r-- | ui/aura/window_event_dispatcher_unittest.cc | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc index 87e6193..e320d87 100644 --- a/ui/aura/window_event_dispatcher_unittest.cc +++ b/ui/aura/window_event_dispatcher_unittest.cc @@ -1836,4 +1836,99 @@ TEST_F(WindowEventDispatcherTest, HostCancelModeWithFocusedWindowOutside) { client::GetFocusClient(root_window())->GetFocusedWindow()); } +// Dispatches a mouse-move event to |target| when it receives a mouse-move +// event. +class DispatchEventHandler : public ui::EventHandler { + public: + explicit DispatchEventHandler(Window* target) + : target_(target), + dispatched_(false) {} + virtual ~DispatchEventHandler() {} + + bool dispatched() const { return dispatched_; } + private: + // ui::EventHandler: + virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE { + if (mouse->type() == ui::ET_MOUSE_MOVED) { + ui::MouseEvent move(ui::ET_MOUSE_MOVED, target_->bounds().CenterPoint(), + target_->bounds().CenterPoint(), ui::EF_NONE, ui::EF_NONE); + target_->GetDispatcher()->OnEventFromSource(&move); + EXPECT_EQ(target_, move.target()); + dispatched_ = true; + } + ui::EventHandler::OnMouseEvent(mouse); + } + + Window* target_; + bool dispatched_; + + DISALLOW_COPY_AND_ASSIGN(DispatchEventHandler); +}; + +// Moves |window| to |root_window| when it receives a mouse-move event. +class MoveWindowHandler : public ui::EventHandler { + public: + MoveWindowHandler(Window* window, Window* root_window) + : window_to_move_(window), + root_window_to_move_to_(root_window) {} + virtual ~MoveWindowHandler() {} + + private: + // ui::EventHandler: + virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE { + if (mouse->type() == ui::ET_MOUSE_MOVED) { + root_window_to_move_to_->AddChild(window_to_move_); + } + ui::EventHandler::OnMouseEvent(mouse); + } + + Window* window_to_move_; + Window* root_window_to_move_to_; + + DISALLOW_COPY_AND_ASSIGN(MoveWindowHandler); +}; + +// Tests that nested event dispatch works correctly if the target of the older +// event being dispatched is moved to a different dispatcher in response to an +// event in the inner loop. +TEST_F(WindowEventDispatcherTest, NestedEventDispatchTargetMoved) { + scoped_ptr<WindowTreeHost> second_host( + WindowTreeHost::Create(gfx::Rect(20, 30, 100, 50))); + second_host->InitHost(); + Window* second_root = second_host->window(); + + // Create two windows parented to |root_window()|. + test::TestWindowDelegate delegate; + scoped_ptr<Window> first(CreateTestWindowWithDelegate(&delegate, 123, + gfx::Rect(20, 10, 10, 20), root_window())); + scoped_ptr<Window> second(CreateTestWindowWithDelegate(&delegate, 234, + gfx::Rect(40, 10, 50, 20), root_window())); + + // Setup a handler on |first| so that it dispatches an event to |second| when + // |first| receives an event. + DispatchEventHandler dispatch_event(second.get()); + first->AddPreTargetHandler(&dispatch_event); + + // Setup a handler on |second| so that it moves |first| into |second_root| + // when |second| receives an event. + MoveWindowHandler move_window(first.get(), second_root); + second->AddPreTargetHandler(&move_window); + + // Some sanity checks: |first| is inside |root_window()|'s tree. + EXPECT_EQ(root_window(), first->GetRootWindow()); + // The two root windows are different. + EXPECT_NE(root_window(), second_root); + + // Dispatch an event to |first|. + ui::MouseEvent move(ui::ET_MOUSE_MOVED, first->bounds().CenterPoint(), + first->bounds().CenterPoint(), ui::EF_NONE, ui::EF_NONE); + dispatcher()->OnEventFromSource(&move); + EXPECT_EQ(first.get(), move.target()); + EXPECT_TRUE(dispatch_event.dispatched()); + EXPECT_EQ(second_root, first->GetRootWindow()); + + first->RemovePreTargetHandler(&dispatch_event); + second->RemovePreTargetHandler(&move_window); +} + } // namespace aura |