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 "components/mus/ws/event_dispatcher.h" | 5 #include "components/mus/ws/event_dispatcher.h" |
6 | 6 |
| 7 #include <set> |
| 8 |
7 #include "cc/surfaces/surface_hittest.h" | 9 #include "cc/surfaces/surface_hittest.h" |
8 #include "components/mus/surfaces/surfaces_state.h" | 10 #include "components/mus/surfaces/surfaces_state.h" |
9 #include "components/mus/ws/event_dispatcher_delegate.h" | 11 #include "components/mus/ws/event_dispatcher_delegate.h" |
10 #include "components/mus/ws/server_window.h" | 12 #include "components/mus/ws/server_window.h" |
11 #include "components/mus/ws/server_window_delegate.h" | 13 #include "components/mus/ws/server_window_delegate.h" |
12 #include "components/mus/ws/window_coordinate_conversions.h" | 14 #include "components/mus/ws/window_coordinate_conversions.h" |
13 #include "components/mus/ws/window_finder.h" | 15 #include "components/mus/ws/window_finder.h" |
14 #include "components/mus/ws/window_tree_host_impl.h" | 16 #include "components/mus/ws/window_tree_host_impl.h" |
15 #include "mojo/converters/geometry/geometry_type_converters.h" | 17 #include "mojo/converters/geometry/geometry_type_converters.h" |
16 #include "ui/gfx/geometry/point.h" | 18 #include "ui/gfx/geometry/point.h" |
17 #include "ui/gfx/geometry/point_conversions.h" | 19 #include "ui/gfx/geometry/point_conversions.h" |
18 | 20 |
19 namespace mus { | 21 namespace mus { |
20 namespace ws { | 22 namespace ws { |
21 namespace { | 23 namespace { |
22 | 24 |
23 bool IsMouseEventFlag(int32_t event_flags) { | |
24 return !!(event_flags & (mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON | | |
25 mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON | | |
26 mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON)); | |
27 } | |
28 | |
29 bool IsOnlyOneMouseButtonDown(mojom::EventFlags flags) { | 25 bool IsOnlyOneMouseButtonDown(mojom::EventFlags flags) { |
30 const uint32_t mouse_only_flags = | 26 const uint32_t mouse_only_flags = |
31 flags & (mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON | | 27 flags & (mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON | |
32 mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON | | 28 mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON | |
33 mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON); | 29 mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON); |
34 return mouse_only_flags == mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON || | 30 return mouse_only_flags == mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON || |
35 mouse_only_flags == mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON || | 31 mouse_only_flags == mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON || |
36 mouse_only_flags == mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON; | 32 mouse_only_flags == mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON; |
37 } | 33 } |
38 | 34 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 mojom::EventType event_type_; | 130 mojom::EventType event_type_; |
135 mojom::EventFlags event_flags_; | 131 mojom::EventFlags event_flags_; |
136 mojom::KeyboardCode keyboard_code_; | 132 mojom::KeyboardCode keyboard_code_; |
137 mojom::PointerKind pointer_kind_; | 133 mojom::PointerKind pointer_kind_; |
138 gfx::RectF pointer_region_; | 134 gfx::RectF pointer_region_; |
139 }; | 135 }; |
140 | 136 |
141 //////////////////////////////////////////////////////////////////////////////// | 137 //////////////////////////////////////////////////////////////////////////////// |
142 | 138 |
143 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) | 139 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) |
144 : delegate_(delegate), | 140 : delegate_(delegate), root_(nullptr) {} |
145 root_(nullptr), | |
146 capture_window_(nullptr), | |
147 capture_in_nonclient_area_(false) {} | |
148 | 141 |
149 EventDispatcher::~EventDispatcher() {} | 142 EventDispatcher::~EventDispatcher() { |
| 143 std::set<ServerWindow*> pointer_targets; |
| 144 for (const auto& pair : pointer_targets_) { |
| 145 if (pair.second.window && |
| 146 pointer_targets.insert(pair.second.window).second) { |
| 147 pair.second.window->RemoveObserver(this); |
| 148 } |
| 149 } |
| 150 } |
150 | 151 |
151 void EventDispatcher::AddAccelerator(uint32_t id, | 152 void EventDispatcher::AddAccelerator(uint32_t id, |
152 mojom::EventMatcherPtr event_matcher) { | 153 mojom::EventMatcherPtr event_matcher) { |
153 EventMatcher matcher(*event_matcher); | 154 EventMatcher matcher(*event_matcher); |
154 #if !defined(NDEBUG) | 155 #if !defined(NDEBUG) |
155 for (const auto& pair : accelerators_) { | 156 for (const auto& pair : accelerators_) { |
156 DCHECK_NE(pair.first, id); | 157 DCHECK_NE(pair.first, id); |
157 DCHECK(!matcher.Equals(pair.second)); | 158 DCHECK(!matcher.Equals(pair.second)); |
158 } | 159 } |
159 #endif | 160 #endif |
(...skipping 12 matching lines...) Expand all Loading... |
172 | 173 |
173 if (event->action == mojom::EVENT_TYPE_KEY_PRESSED && | 174 if (event->action == mojom::EVENT_TYPE_KEY_PRESSED && |
174 !event->key_data->is_char) { | 175 !event->key_data->is_char) { |
175 uint32_t accelerator = 0u; | 176 uint32_t accelerator = 0u; |
176 if (FindAccelerator(*event, &accelerator)) { | 177 if (FindAccelerator(*event, &accelerator)) { |
177 delegate_->OnAccelerator(accelerator, event.Pass()); | 178 delegate_->OnAccelerator(accelerator, event.Pass()); |
178 return; | 179 return; |
179 } | 180 } |
180 } | 181 } |
181 | 182 |
182 ServerWindow* target = FindEventTarget(event.get()); | 183 if (event->key_data) { |
183 bool in_nonclient_area = false; | 184 ProcessKeyEvent(event.Pass()); |
184 | 185 return; |
185 if (IsMouseEventFlag(event->flags)) { | |
186 if (!capture_window_ && target && | |
187 (event->action == mojom::EVENT_TYPE_POINTER_DOWN)) { | |
188 // TODO(sky): |capture_window_| needs to be reset when window removed | |
189 // from hierarchy. | |
190 capture_window_ = target; | |
191 // TODO(sky): this needs to happen for pointer down events too. | |
192 capture_in_nonclient_area_ = | |
193 IsLocationInNonclientArea(target, EventLocationToPoint(*event)); | |
194 in_nonclient_area = capture_in_nonclient_area_; | |
195 } else if (event->action == mojom::EVENT_TYPE_POINTER_UP && | |
196 IsOnlyOneMouseButtonDown(event->flags)) { | |
197 capture_window_ = nullptr; | |
198 } | |
199 in_nonclient_area = capture_in_nonclient_area_; | |
200 } | 186 } |
201 | 187 |
202 if (target) { | 188 if (event->pointer_data.get()) { |
203 if (event->action == mojom::EVENT_TYPE_POINTER_DOWN) | 189 ProcessPointerEvent(event.Pass()); |
| 190 return; |
| 191 } |
| 192 |
| 193 NOTREACHED(); |
| 194 } |
| 195 |
| 196 void EventDispatcher::ProcessKeyEvent(mojom::EventPtr event) { |
| 197 ServerWindow* focused_window = |
| 198 delegate_->GetFocusedWindowForEventDispatcher(); |
| 199 if (focused_window) |
| 200 delegate_->DispatchInputEventToWindow(focused_window, false, event.Pass()); |
| 201 } |
| 202 |
| 203 void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { |
| 204 const int32_t pointer_id = event->pointer_data->pointer_id; |
| 205 if (event->action == mojom::EVENT_TYPE_WHEEL || |
| 206 (event->action == mojom::EVENT_TYPE_POINTER_MOVE && |
| 207 pointer_targets_.count(pointer_id) == 0)) { |
| 208 PointerTarget pointer_target; |
| 209 if (pointer_targets_.count(pointer_id) != 0) { |
| 210 pointer_target = pointer_targets_[pointer_id]; |
| 211 } else { |
| 212 gfx::Point location(EventLocationToPoint(*event)); |
| 213 pointer_target.window = |
| 214 FindDeepestVisibleWindow(root_, surface_id_, &location); |
| 215 } |
| 216 DispatchToPointerTarget(pointer_target, event.Pass()); |
| 217 return; |
| 218 } |
| 219 |
| 220 // Pointer down implicitly captures. |
| 221 if (pointer_targets_.count(pointer_id) == 0) { |
| 222 DCHECK(event->action == mojom::EVENT_TYPE_POINTER_DOWN); |
| 223 const bool is_first_pointer_down = pointer_targets_.empty(); |
| 224 gfx::Point location(EventLocationToPoint(*event)); |
| 225 ServerWindow* target = |
| 226 FindDeepestVisibleWindow(root_, surface_id_, &location); |
| 227 DCHECK(target); |
| 228 if (!IsObservingWindow(target)) |
| 229 target->AddObserver(this); |
| 230 |
| 231 pointer_targets_[pointer_id].window = target; |
| 232 pointer_targets_[pointer_id].in_nonclient_area = |
| 233 IsLocationInNonclientArea(target, location); |
| 234 |
| 235 if (is_first_pointer_down) |
204 delegate_->SetFocusedWindowFromEventDispatcher(target); | 236 delegate_->SetFocusedWindowFromEventDispatcher(target); |
| 237 } |
205 | 238 |
206 delegate_->DispatchInputEventToWindow(target, in_nonclient_area, | 239 // Release capture on pointer up. For mouse we only release if there are |
207 event.Pass()); | 240 // no buttons down. |
| 241 const bool should_reset_target = |
| 242 (event->action == mojom::EVENT_TYPE_POINTER_UP || |
| 243 event->action == mojom::EVENT_TYPE_POINTER_CANCEL) && |
| 244 (event->pointer_data->kind != mojom::POINTER_KIND_MOUSE || |
| 245 IsOnlyOneMouseButtonDown(event->flags)); |
| 246 |
| 247 DispatchToPointerTarget(pointer_targets_[pointer_id], event.Pass()); |
| 248 |
| 249 if (should_reset_target) { |
| 250 ServerWindow* target = pointer_targets_[pointer_id].window; |
| 251 pointer_targets_.erase(pointer_id); |
| 252 if (target && !IsObservingWindow(target)) |
| 253 target->RemoveObserver(this); |
208 } | 254 } |
209 } | 255 } |
210 | 256 |
| 257 void EventDispatcher::DispatchToPointerTarget(const PointerTarget& target, |
| 258 mojom::EventPtr event) { |
| 259 if (!target.window) |
| 260 return; |
| 261 |
| 262 gfx::Point location(EventLocationToPoint(*event)); |
| 263 gfx::Transform transform(GetTransformToWindow(surface_id_, target.window)); |
| 264 transform.TransformPoint(&location); |
| 265 event->pointer_data->location->x = location.x(); |
| 266 event->pointer_data->location->y = location.y(); |
| 267 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, |
| 268 event.Pass()); |
| 269 } |
| 270 |
| 271 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { |
| 272 window->RemoveObserver(this); |
| 273 |
| 274 for (auto& pair : pointer_targets_) { |
| 275 if (pair.second.window == window) |
| 276 pair.second.window = nullptr; |
| 277 } |
| 278 } |
| 279 |
| 280 bool EventDispatcher::IsObservingWindow(ServerWindow* window) { |
| 281 for (const auto& pair : pointer_targets_) { |
| 282 if (pair.second.window == window) |
| 283 return true; |
| 284 } |
| 285 return false; |
| 286 } |
| 287 |
211 bool EventDispatcher::FindAccelerator(const mojom::Event& event, | 288 bool EventDispatcher::FindAccelerator(const mojom::Event& event, |
212 uint32_t* accelerator_id) { | 289 uint32_t* accelerator_id) { |
213 DCHECK(event.key_data); | 290 DCHECK(event.key_data); |
214 for (const auto& pair : accelerators_) { | 291 for (const auto& pair : accelerators_) { |
215 if (pair.second.MatchesEvent(event)) { | 292 if (pair.second.MatchesEvent(event)) { |
216 *accelerator_id = pair.first; | 293 *accelerator_id = pair.first; |
217 return true; | 294 return true; |
218 } | 295 } |
219 } | 296 } |
220 return false; | 297 return false; |
221 } | 298 } |
222 | 299 |
223 ServerWindow* EventDispatcher::FindEventTarget(mojom::Event* event) { | 300 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, |
224 ServerWindow* focused_window = | 301 ServerWindow* new_parent, |
225 delegate_->GetFocusedWindowForEventDispatcher(); | 302 ServerWindow* old_parent) { |
226 if (event->key_data) | 303 CancelPointerEventsToTarget(window); |
227 return focused_window; | 304 } |
228 | 305 |
229 DCHECK(event->pointer_data) << "Unknown event type: " << event->action; | 306 void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) { |
230 mojom::LocationData* event_location = event->pointer_data->location.get(); | 307 CancelPointerEventsToTarget(window); |
231 DCHECK(event_location); | 308 } |
232 gfx::Point location(static_cast<int>(event_location->x), | |
233 static_cast<int>(event_location->y)); | |
234 | 309 |
235 ServerWindow* target = capture_window_; | 310 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { |
236 | 311 CancelPointerEventsToTarget(window); |
237 if (!target) { | |
238 target = FindDeepestVisibleWindow(root_, surface_id_, &location); | |
239 } else { | |
240 gfx::Transform transform(GetTransformToWindow(surface_id_, target)); | |
241 transform.TransformPoint(&location); | |
242 } | |
243 | |
244 event_location->x = location.x(); | |
245 event_location->y = location.y(); | |
246 | |
247 return target; | |
248 } | 312 } |
249 | 313 |
250 } // namespace ws | 314 } // namespace ws |
251 } // namespace mus | 315 } // namespace mus |
OLD | NEW |