Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "services/ui/ws/window_finder.h" | 5 #include "services/ui/ws/window_finder.h" |
| 6 | 6 |
| 7 #include "base/containers/adapters.h" | 7 #include "base/containers/adapters.h" |
| 8 #include "services/ui/ws/server_window.h" | 8 #include "services/ui/ws/server_window.h" |
| 9 #include "services/ui/ws/server_window_compositor_frame_sink_manager.h" | |
| 10 #include "services/ui/ws/server_window_delegate.h" | 9 #include "services/ui/ws/server_window_delegate.h" |
| 11 #include "services/ui/ws/window_coordinate_conversions.h" | 10 #include "services/ui/ws/window_coordinate_conversions.h" |
| 12 #include "ui/gfx/geometry/point.h" | 11 #include "ui/gfx/geometry/point.h" |
| 13 #include "ui/gfx/geometry/point_f.h" | 12 #include "ui/gfx/geometry/point_f.h" |
| 14 #include "ui/gfx/transform.h" | 13 #include "ui/gfx/transform.h" |
| 15 | 14 |
| 16 namespace ui { | 15 namespace ui { |
| 17 namespace ws { | 16 namespace ws { |
| 18 namespace { | 17 namespace { |
| 19 | 18 |
| 20 bool IsValidWindowForEvents(ServerWindow* window) { | |
| 21 ServerWindowCompositorFrameSinkManager* compositor_frame_sink_manager = | |
| 22 window->compositor_frame_sink_manager(); | |
| 23 // Valid windows have at least one of the two surface types. Only an underlay | |
| 24 // is valid as we assume the window manager will likely get the event in this | |
| 25 // case. | |
| 26 return compositor_frame_sink_manager && | |
| 27 compositor_frame_sink_manager->HasCompositorFrameSink(); | |
| 28 } | |
| 29 | |
| 30 bool IsLocationInNonclientArea(const ServerWindow* target, | 19 bool IsLocationInNonclientArea(const ServerWindow* target, |
| 31 const gfx::Point& location) { | 20 const gfx::Point& location) { |
| 32 if (!target->parent()) | 21 if (!target->parent() || target->bounds().size().IsEmpty()) |
| 33 return false; | 22 return false; |
| 34 | 23 |
| 35 gfx::Rect client_area(target->bounds().size()); | 24 gfx::Rect client_area(target->bounds().size()); |
| 36 client_area.Inset(target->client_area()); | 25 client_area.Inset(target->client_area()); |
| 37 if (client_area.Contains(location)) | 26 if (client_area.Contains(location)) |
| 38 return false; | 27 return false; |
| 39 | 28 |
| 40 for (const auto& rect : target->additional_client_areas()) { | 29 for (const auto& rect : target->additional_client_areas()) { |
| 41 if (rect.Contains(location)) | 30 if (rect.Contains(location)) |
| 42 return false; | 31 return false; |
| 43 } | 32 } |
| 44 | 33 |
| 45 return true; | 34 return true; |
| 46 } | 35 } |
| 47 | 36 |
| 48 bool FindDeepestVisibleWindowForEventsImpl(ServerWindow* window, | 37 bool FindDeepestVisibleWindowForEventsImpl(ServerWindow* window, |
| 49 const gfx::Point& location, | 38 const gfx::Point& location, |
| 50 DeepestWindow* deepest_window) { | 39 DeepestWindow* deepest_window) { |
| 51 if (!window->can_accept_events()) { | 40 // The non-client area takes precedence over descendants, as otherwise the |
| 52 if (!IsLocationInNonclientArea(window, location) || | 41 // user would likely not be able to hit the non-client area as it's common |
| 53 !IsValidWindowForEvents(window)) { | 42 // for descendants to go into the non-client area. |
| 54 return false; | 43 if (IsLocationInNonclientArea(window, location)) { |
| 55 } | |
| 56 deepest_window->window = window; | 44 deepest_window->window = window; |
| 57 deepest_window->in_non_client_area = true; | 45 deepest_window->in_non_client_area = true; |
| 58 return true; | 46 return true; |
| 59 } | 47 } |
| 48 const mojom::EventTargetingPolicy event_targeting_policy = | |
| 49 window->event_targeting_policy(); | |
| 60 | 50 |
| 61 const ServerWindow::Windows& children = window->children(); | 51 if (event_targeting_policy == ui::mojom::EventTargetingPolicy::NONE) |
| 62 for (ServerWindow* child : base::Reversed(children)) { | 52 return false; |
|
sadrul
2017/02/01 20:42:00
Should this go first? I see that that would be dif
sky
2017/02/01 21:13:50
This needs to be after the non-client area hit tes
sadrul
2017/02/01 21:28:29
Ah, of course.
| |
| 63 if (!child->visible()) | |
| 64 continue; | |
| 65 | 53 |
| 66 // TODO(sky): support transform. | 54 if (event_targeting_policy == |
| 67 gfx::Point location_in_child(location.x() - child->bounds().x(), | 55 mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS || |
| 68 location.y() - child->bounds().y()); | 56 event_targeting_policy == mojom::EventTargetingPolicy::DESCENDANTS_ONLY) { |
| 69 gfx::Rect child_bounds(child->bounds().size()); | 57 const ServerWindow::Windows& children = window->children(); |
| 70 child_bounds.Inset(-child->extended_hit_test_region().left(), | 58 for (ServerWindow* child : base::Reversed(children)) { |
| 71 -child->extended_hit_test_region().top(), | 59 if (!child->visible()) |
| 72 -child->extended_hit_test_region().right(), | 60 continue; |
| 73 -child->extended_hit_test_region().bottom()); | |
| 74 if (!child_bounds.Contains(location_in_child) || | |
| 75 (child->hit_test_mask() && | |
| 76 !child->hit_test_mask()->Contains(location_in_child))) { | |
| 77 continue; | |
| 78 } | |
| 79 | 61 |
| 80 if (FindDeepestVisibleWindowForEventsImpl(child, location_in_child, | 62 // TODO(sky): support transform. |
| 81 deepest_window)) { | 63 gfx::Point location_in_child(location.x() - child->bounds().x(), |
| 82 return true; | 64 location.y() - child->bounds().y()); |
| 65 gfx::Rect child_bounds(child->bounds().size()); | |
| 66 child_bounds.Inset(-child->extended_hit_test_region().left(), | |
| 67 -child->extended_hit_test_region().top(), | |
| 68 -child->extended_hit_test_region().right(), | |
| 69 -child->extended_hit_test_region().bottom()); | |
| 70 if (!child_bounds.Contains(location_in_child) || | |
| 71 (child->hit_test_mask() && | |
| 72 !child->hit_test_mask()->Contains(location_in_child))) { | |
| 73 continue; | |
| 74 } | |
| 75 | |
| 76 if (FindDeepestVisibleWindowForEventsImpl(child, location_in_child, | |
| 77 deepest_window)) { | |
| 78 return true; | |
| 79 } | |
| 83 } | 80 } |
| 84 } | 81 } |
| 85 | 82 |
| 86 if (!IsValidWindowForEvents(window)) | 83 if (event_targeting_policy == mojom::EventTargetingPolicy::DESCENDANTS_ONLY) |
| 87 return false; | 84 return false; |
| 88 | 85 |
| 89 deepest_window->window = window; | 86 deepest_window->window = window; |
| 90 deepest_window->in_non_client_area = | 87 deepest_window->in_non_client_area = false; |
| 91 IsLocationInNonclientArea(window, location); | |
| 92 return true; | 88 return true; |
| 93 } | 89 } |
| 94 | 90 |
| 95 } // namespace | 91 } // namespace |
| 96 | 92 |
| 97 DeepestWindow FindDeepestVisibleWindowForEvents(ServerWindow* root_window, | 93 DeepestWindow FindDeepestVisibleWindowForEvents(ServerWindow* root_window, |
| 98 const gfx::Point& location) { | 94 const gfx::Point& location) { |
| 99 DeepestWindow result; | 95 DeepestWindow result; |
| 100 FindDeepestVisibleWindowForEventsImpl(root_window, location, &result); | 96 FindDeepestVisibleWindowForEventsImpl(root_window, location, &result); |
| 101 return result; | 97 return result; |
| 102 } | 98 } |
| 103 | 99 |
| 104 gfx::Transform GetTransformToWindow(ServerWindow* window) { | 100 gfx::Transform GetTransformToWindow(ServerWindow* window) { |
| 105 gfx::Transform transform; | 101 gfx::Transform transform; |
| 106 ServerWindow* current = window; | 102 ServerWindow* current = window; |
| 107 while (current->parent()) { | 103 while (current->parent()) { |
| 108 transform.Translate(-current->bounds().x(), -current->bounds().y()); | 104 transform.Translate(-current->bounds().x(), -current->bounds().y()); |
| 109 current = current->parent(); | 105 current = current->parent(); |
| 110 } | 106 } |
| 111 return transform; | 107 return transform; |
| 112 } | 108 } |
| 113 | 109 |
| 114 } // namespace ws | 110 } // namespace ws |
| 115 } // namespace ui | 111 } // namespace ui |
| OLD | NEW |