Index: components/mus/ws/event_dispatcher.cc |
diff --git a/components/mus/ws/event_dispatcher.cc b/components/mus/ws/event_dispatcher.cc |
index 384f9ba81f95b1c2d41d364a79a8a2653dabbe13..a9413f51738bcebf0777fda2d7f02bc1f1c296ce 100644 |
--- a/components/mus/ws/event_dispatcher.cc |
+++ b/components/mus/ws/event_dispatcher.cc |
@@ -139,7 +139,10 @@ class EventMatcher { |
//////////////////////////////////////////////////////////////////////////////// |
EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) |
- : delegate_(delegate), root_(nullptr) {} |
+ : delegate_(delegate), |
+ root_(nullptr), |
+ mouse_button_down_(false), |
+ mouse_cursor_source_window_(nullptr) {} |
EventDispatcher::~EventDispatcher() { |
std::set<ServerWindow*> pointer_targets; |
@@ -203,6 +206,10 @@ void EventDispatcher::ProcessKeyEvent(mojom::EventPtr event) { |
} |
void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { |
+ bool is_mouse_event = |
+ event->pointer_data && |
+ event->pointer_data->kind == mojom::PointerKind::POINTER_KIND_MOUSE; |
+ |
const int32_t pointer_id = event->pointer_data->pointer_id; |
if (event->action == mojom::EVENT_TYPE_WHEEL || |
(event->action == mojom::EVENT_TYPE_POINTER_MOVE && |
@@ -215,6 +222,8 @@ void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { |
pointer_target.window = |
FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); |
} |
+ if (is_mouse_event && !mouse_button_down_) |
+ mouse_cursor_source_window_ = pointer_target.window; |
DispatchToPointerTarget(pointer_target, event.Pass()); |
return; |
} |
@@ -230,6 +239,11 @@ void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { |
if (!IsObservingWindow(target)) |
target->AddObserver(this); |
+ if (is_mouse_event) { |
+ mouse_button_down_ = true; |
+ mouse_cursor_source_window_ = target; |
+ } |
+ |
pointer_targets_[pointer_id].window = target; |
pointer_targets_[pointer_id].in_nonclient_area = |
IsLocationInNonclientArea(target, location); |
@@ -246,6 +260,18 @@ void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { |
(event->pointer_data->kind != mojom::POINTER_KIND_MOUSE || |
IsOnlyOneMouseButtonDown(event->flags)); |
+ if (should_reset_target && is_mouse_event) { |
+ // When we release the mouse button, we want the cursor to be sourced from |
+ // the window under the mouse pointer, even though we're sending the button |
+ // up event to the window that had implicit capture. We have to set this |
+ // before we perform dispatch because the Delegate is going to read this |
+ // information from us. |
+ mouse_button_down_ = false; |
+ gfx::Point location(EventLocationToPoint(*event)); |
+ mouse_cursor_source_window_ = |
+ FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); |
+ } |
+ |
DispatchToPointerTarget(pointer_targets_[pointer_id], event.Pass()); |
if (should_reset_target) { |
@@ -311,6 +337,9 @@ void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) { |
void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { |
CancelPointerEventsToTarget(window); |
+ |
+ if (mouse_cursor_source_window_ == window) |
+ mouse_cursor_source_window_ = nullptr; |
} |
} // namespace ws |