Chromium Code Reviews| Index: components/mus/ws/event_dispatcher.cc |
| diff --git a/components/mus/ws/event_dispatcher.cc b/components/mus/ws/event_dispatcher.cc |
| index 71dea6063039e8877df57d356e8f2ba37b6b7f36..368567b2f9a091b58477d01ef74fa5f8cc3bc744 100644 |
| --- a/components/mus/ws/event_dispatcher.cc |
| +++ b/components/mus/ws/event_dispatcher.cc |
| @@ -52,6 +52,23 @@ bool IsLocationInNonclientArea(const ServerWindow* target, |
| return true; |
| } |
| +ServerWindow* GetClosestModalTargetForWindow(ServerWindow* target) { |
|
sky
2016/03/08 17:07:53
Add description as closest isn't clear in this con
mohsen
2016/03/09 08:26:48
Renamed to GetModalChildForWindowAncestor() (also
|
| + for (ServerWindow* window = target; window; window = window->parent()) { |
| + for (const auto& transient_child : window->transient_children()) { |
| + if (transient_child->is_modal() && transient_child->IsDrawn()) |
| + return transient_child; |
| + } |
| + } |
| + return target; |
| +} |
| + |
| +ServerWindow* GetModalTargetForWindow(ServerWindow* target) { |
| + ServerWindow* closest_target = GetClosestModalTargetForWindow(target); |
| + if (closest_target == target) |
| + return target; |
| + return GetModalTargetForWindow(closest_target); |
| +} |
| + |
| } // namespace |
| class EventMatcher { |
| @@ -216,14 +233,18 @@ EventDispatcher::~EventDispatcher() { |
| pointer_targets_.clear(); |
| } |
| -void EventDispatcher::SetCaptureWindow(ServerWindow* window, |
| +bool EventDispatcher::SetCaptureWindow(ServerWindow* window, |
| bool in_nonclient_area) { |
| if (window == capture_window_) |
| - return; |
| + return true; |
| + |
| + // A window that is blocked by a modal window cannot gain capture. |
| + if (window && GetClosestModalTargetForWindow(window) != window) |
| + return false; |
| if (capture_window_) { |
| // Stop observing old capture window. |pointer_targets_| are cleared on |
| - // intial setting of a capture window. |
| + // initial setting of a capture window. |
| delegate_->OnServerWindowCaptureLost(capture_window_); |
| capture_window_->RemoveObserver(this); |
| } else { |
| @@ -245,7 +266,7 @@ void EventDispatcher::SetCaptureWindow(ServerWindow* window, |
| pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE |
| : ui::EventPointerType::POINTER_TYPE_TOUCH; |
| // TODO(jonross): Track previous location in PointerTarget for sending |
| - // cancels |
| + // cancels. |
| ui::PointerEvent event(event_type, pointer_type, gfx::Point(), |
| gfx::Point(), ui::EF_NONE, pair.first, |
| ui::EventTimeForNow()); |
| @@ -267,6 +288,7 @@ void EventDispatcher::SetCaptureWindow(ServerWindow* window, |
| capture_window_ = window; |
| capture_window_in_nonclient_area_ = in_nonclient_area; |
| + return true; |
| } |
| void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { |
| @@ -451,10 +473,12 @@ EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent( |
| const ui::PointerEvent& event) const { |
| PointerTarget pointer_target; |
| gfx::Point location(event.location()); |
| - pointer_target.window = |
| + ServerWindow* target_window = |
| FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); |
| + pointer_target.window = GetModalTargetForWindow(target_window); |
| pointer_target.is_mouse_event = event.IsMousePointerEvent(); |
| pointer_target.in_nonclient_area = |
| + target_window != pointer_target.window || |
| IsLocationInNonclientArea(pointer_target.window, location); |
| pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN; |
| return pointer_target; |