Index: components/mus/ws/event_dispatcher_unittest.cc |
diff --git a/components/mus/ws/event_dispatcher_unittest.cc b/components/mus/ws/event_dispatcher_unittest.cc |
index 2cfbf29a42a0ff3266146396d42871c4a4fe244e..7313a057dd9ebae78ef82ab4d43ffc6651d43b6b 100644 |
--- a/components/mus/ws/event_dispatcher_unittest.cc |
+++ b/components/mus/ws/event_dispatcher_unittest.cc |
@@ -67,6 +67,7 @@ class TestEventDispatcherDelegate : public EventDispatcherDelegate { |
ServerWindow* GetFocusedWindowForEventDispatcher() override { |
return focused_window_; |
} |
+ void OnLostCapture(ServerWindow* window) override {} |
void DispatchInputEventToWindow(ServerWindow* target, |
bool in_nonclient_area, |
mojom::EventPtr event) override { |
@@ -500,5 +501,119 @@ TEST(EventDispatcherTest, DestroyWindowWhileGettingEvents) { |
event_dispatcher_delegate.GetAndClearLastDispatchedEvent().get()); |
} |
+TEST(EventDispatcherTest, SetExplictCapture) { |
+ TestServerWindowDelegate window_delegate; |
+ ServerWindow root(&window_delegate, WindowId(1, 2)); |
+ window_delegate.set_root_window(&root); |
+ root.SetVisible(true); |
+ |
+ ServerWindow child(&window_delegate, WindowId(1, 3)); |
+ root.Add(&child); |
+ child.SetVisible(true); |
+ |
+ root.SetBounds(gfx::Rect(0, 0, 100, 100)); |
+ child.SetBounds(gfx::Rect(10, 10, 20, 20)); |
+ |
+ TestEventDispatcherDelegate event_dispatcher_delegate(&root); |
+ EventDispatcher dispatcher(&event_dispatcher_delegate); |
+ dispatcher.set_root(&root); |
+ |
+ { |
+ // Send all pointer events to the child. |
+ dispatcher.SetCaptureWindow(&child); |
+ |
+ // The mouse press should go to the child even though its outside its |
+ // bounds. |
+ const ui::MouseEvent press_event( |
+ ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5), |
+ base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
+ dispatcher.OnEvent( |
+ mojom::Event::From(static_cast<const ui::Event&>(press_event))); |
+ |
+ // Events should target child. |
+ ASSERT_EQ(&child, event_dispatcher_delegate.last_target()); |
+ } |
+ |
+ { |
+ // Releasing capture and sending the same event will go to the root. |
+ dispatcher.SetCaptureWindow(nullptr); |
+ const ui::MouseEvent press_event( |
+ ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5), |
+ base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
+ dispatcher.OnEvent( |
+ mojom::Event::From(static_cast<const ui::Event&>(press_event))); |
+ |
+ // Events should target the root. |
+ ASSERT_EQ(&root, event_dispatcher_delegate.last_target()); |
+ } |
+} |
+ |
+// This test verifies that explicit capture overrides and resets implicit |
+// capture. |
+TEST(EventDispatcherTest, ExplicitCaptureOverridesImplicitCapture) { |
+ TestServerWindowDelegate window_delegate; |
+ ServerWindow root(&window_delegate, WindowId(1, 2)); |
+ window_delegate.set_root_window(&root); |
+ root.SetVisible(true); |
+ |
+ ServerWindow child(&window_delegate, WindowId(1, 3)); |
+ root.Add(&child); |
+ child.SetVisible(true); |
+ |
+ root.SetBounds(gfx::Rect(0, 0, 100, 100)); |
+ child.SetBounds(gfx::Rect(10, 10, 20, 20)); |
+ |
+ TestEventDispatcherDelegate event_dispatcher_delegate(&root); |
+ EventDispatcher dispatcher(&event_dispatcher_delegate); |
+ dispatcher.set_root(&root); |
+ |
+ // Run some implicit capture tests. |
+ MouseEventTest tests[] = { |
+ // Send a mouse down event over child with a left mouse button |
+ {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), |
+ gfx::Point(20, 25), base::TimeDelta(), |
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON), |
+ &child, gfx::Point(20, 25), gfx::Point(10, 15)}, |
+ // Capture should be activated. Let's send a mouse move outside the bounds |
+ // of the child and press the right mouse button too. |
+ {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), |
+ gfx::Point(50, 50), base::TimeDelta(), |
+ ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 0), |
+ &child, gfx::Point(50, 50), gfx::Point(40, 40)}, |
+ // Release the left mouse button and verify that the mouse up event goes |
+ // to the child. |
+ {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50), |
+ gfx::Point(50, 50), base::TimeDelta(), |
+ ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, |
+ ui::EF_RIGHT_MOUSE_BUTTON), |
+ &child, gfx::Point(50, 50), gfx::Point(40, 40)}, |
+ // A mouse move at (50, 50) should still go to the child. |
+ {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), |
+ gfx::Point(50, 50), base::TimeDelta(), |
+ ui::EF_LEFT_MOUSE_BUTTON, 0), |
+ &child, gfx::Point(50, 50), gfx::Point(40, 40)}, |
+ |
+ }; |
+ RunMouseEventTests(&dispatcher, &event_dispatcher_delegate, tests, |
+ arraysize(tests)); |
+ ASSERT_EQ(&child, event_dispatcher_delegate.last_target()); |
+ |
+ // Verify that no window has explicit capture and hence we did indeed do |
+ // implicit capture. |
+ ASSERT_EQ(nullptr, dispatcher.capture_window()); |
+ |
+ // Give the root window explicit capture and verify input evnets over the |
+ // child go to the root instead. |
+ dispatcher.SetCaptureWindow(&root); |
+ const ui::MouseEvent press_event( |
+ ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15), |
+ base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
+ dispatcher.OnEvent( |
+ mojom::Event::From(static_cast<const ui::Event&>(press_event))); |
+ |
+ // Events should target the root. |
+ ASSERT_EQ(&root, event_dispatcher_delegate.last_target()); |
+} |
+ |
} // namespace ws |
} // namespace mus |