Index: ui/aura/root_window_unittest.cc |
diff --git a/ui/aura/root_window_unittest.cc b/ui/aura/root_window_unittest.cc |
index c8fa601335af29bb6e6d54d973ac52e290c6deef..f10a23877791ee6581c949bd50d55b3e3446280a 100644 |
--- a/ui/aura/root_window_unittest.cc |
+++ b/ui/aura/root_window_unittest.cc |
@@ -1047,4 +1047,69 @@ TEST_F(RootWindowTest, GestureRepostEventOrder) { |
EventTypesToString(repost_event_recorder->events())); |
} |
+class OnMouseExitDeletingEventFilter : public EventFilterRecorder { |
+ public: |
+ OnMouseExitDeletingEventFilter() : window_to_delete_(NULL) {} |
+ virtual ~OnMouseExitDeletingEventFilter() {} |
+ |
+ void set_window_to_delete(Window* window_to_delete) { |
+ window_to_delete_ = window_to_delete; |
+ } |
+ |
+ private: |
+ // Overridden from ui::EventHandler: |
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { |
+ EventFilterRecorder::OnMouseEvent(event); |
+ if (window_to_delete_) { |
+ delete window_to_delete_; |
+ window_to_delete_ = NULL; |
+ } |
+ } |
+ |
+ Window* window_to_delete_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(OnMouseExitDeletingEventFilter); |
+}; |
+ |
+// Tests that RootWindow drops mouse-moved event that is supposed to be sent to |
+// a child, but the child is destroyed because of the synthesized mouse-exit |
+// event generated on the previous mouse_moved_handler_. |
+TEST_F(RootWindowTest, DeleteWindowDuringMouseMovedDispatch) { |
+ // Create window 1 and set its event filter. Window 1 will take ownership of |
+ // the event filter. |
+ scoped_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL)); |
+ OnMouseExitDeletingEventFilter* w1_filter = |
+ new OnMouseExitDeletingEventFilter(); |
+ w1->SetEventFilter(w1_filter); |
+ w1->SetBounds(gfx::Rect(20, 20, 60, 60)); |
+ EXPECT_EQ(NULL, root_window()->mouse_moved_handler()); |
+ |
+ test::EventGenerator generator(root_window(), w1.get()); |
+ |
+ // Move mouse over window 1 to set it as the |mouse_moved_handler_| for the |
+ // root window. |
+ generator.MoveMouseTo(51, 51); |
+ EXPECT_EQ(w1.get(), root_window()->mouse_moved_handler()); |
+ |
+ // Create window 2 under the mouse cursor and stack it above window 1. |
+ Window* w2 = CreateNormalWindow(2, root_window(), NULL); |
+ w2->SetBounds(gfx::Rect(30, 30, 40, 40)); |
+ root_window()->StackChildAbove(w2, w1.get()); |
+ |
+ // Set window 2 as the window that is to be deleted when a mouse-exited event |
+ // happens on window 1. |
+ w1_filter->set_window_to_delete(w2); |
+ |
+ // Move mosue over window 2. This should generate a mouse-exited event for |
+ // window 1 resulting in deletion of window 2. The original mouse-moved event |
+ // that was targeted to window 2 should be dropped since window 2 is |
+ // destroyed. This test passes if no crash happens. |
+ generator.MoveMouseTo(52, 52); |
+ EXPECT_EQ(NULL, root_window()->mouse_moved_handler()); |
+ |
+ // Check events received by window 1. |
+ EXPECT_EQ("MOUSE_ENTERED MOUSE_MOVED MOUSE_EXITED", |
+ EventTypesToString(w1_filter->events())); |
+} |
+ |
} // namespace aura |