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> | 7 #include <set> |
8 | 8 |
| 9 #include "base/time/time.h" |
9 #include "cc/surfaces/surface_hittest.h" | 10 #include "cc/surfaces/surface_hittest.h" |
10 #include "components/mus/surfaces/surfaces_state.h" | 11 #include "components/mus/surfaces/surfaces_state.h" |
11 #include "components/mus/ws/event_dispatcher_delegate.h" | 12 #include "components/mus/ws/event_dispatcher_delegate.h" |
12 #include "components/mus/ws/server_window.h" | 13 #include "components/mus/ws/server_window.h" |
13 #include "components/mus/ws/server_window_delegate.h" | 14 #include "components/mus/ws/server_window_delegate.h" |
14 #include "components/mus/ws/window_coordinate_conversions.h" | 15 #include "components/mus/ws/window_coordinate_conversions.h" |
15 #include "components/mus/ws/window_finder.h" | 16 #include "components/mus/ws/window_finder.h" |
16 #include "components/mus/ws/window_tree_host_impl.h" | 17 #include "components/mus/ws/window_tree_host_impl.h" |
17 #include "mojo/converters/geometry/geometry_type_converters.h" | 18 #include "mojo/converters/geometry/geometry_type_converters.h" |
18 #include "ui/gfx/geometry/point.h" | 19 #include "ui/gfx/geometry/point.h" |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 mojom::KeyboardCode keyboard_code_; | 151 mojom::KeyboardCode keyboard_code_; |
151 mojom::PointerKind pointer_kind_; | 152 mojom::PointerKind pointer_kind_; |
152 gfx::RectF pointer_region_; | 153 gfx::RectF pointer_region_; |
153 }; | 154 }; |
154 | 155 |
155 //////////////////////////////////////////////////////////////////////////////// | 156 //////////////////////////////////////////////////////////////////////////////// |
156 | 157 |
157 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) | 158 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) |
158 : delegate_(delegate), | 159 : delegate_(delegate), |
159 root_(nullptr), | 160 root_(nullptr), |
| 161 capture_window_(nullptr), |
| 162 capture_window_in_nonclient_area_(false), |
160 mouse_button_down_(false), | 163 mouse_button_down_(false), |
161 mouse_cursor_source_window_(nullptr) {} | 164 mouse_cursor_source_window_(nullptr) {} |
162 | 165 |
163 EventDispatcher::~EventDispatcher() { | 166 EventDispatcher::~EventDispatcher() { |
164 std::set<ServerWindow*> pointer_targets; | 167 std::set<ServerWindow*> pointer_targets; |
| 168 if (capture_window_) { |
| 169 pointer_targets.insert(capture_window_); |
| 170 capture_window_->RemoveObserver(this); |
| 171 capture_window_ = nullptr; |
| 172 } |
165 for (const auto& pair : pointer_targets_) { | 173 for (const auto& pair : pointer_targets_) { |
166 if (pair.second.window && | 174 if (pair.second.window && |
167 pointer_targets.insert(pair.second.window).second) { | 175 pointer_targets.insert(pair.second.window).second) { |
168 pair.second.window->RemoveObserver(this); | 176 pair.second.window->RemoveObserver(this); |
169 } | 177 } |
170 } | 178 } |
| 179 pointer_targets_.clear(); |
| 180 } |
| 181 |
| 182 void EventDispatcher::SetCaptureWindow(ServerWindow* window, |
| 183 bool in_nonclient_area) { |
| 184 if (window == capture_window_) |
| 185 return; |
| 186 |
| 187 if (capture_window_) { |
| 188 // Stop observing old capture window. |pointer_targets_| are cleared on |
| 189 // intial setting of a capture window. |
| 190 delegate_->OnLostCapture(capture_window_); |
| 191 capture_window_->RemoveObserver(this); |
| 192 } else { |
| 193 // Cancel implicit capture to all other windows. |
| 194 std::set<ServerWindow*> unobserved_windows; |
| 195 for (const auto& pair : pointer_targets_) { |
| 196 ServerWindow* target = pair.second.window; |
| 197 if (!target) |
| 198 continue; |
| 199 if (unobserved_windows.insert(target).second) |
| 200 target->RemoveObserver(this); |
| 201 if (target == window) |
| 202 continue; |
| 203 mojom::EventPtr cancel_event = mojom::Event::New(); |
| 204 cancel_event->action = mojom::EventType::POINTER_CANCEL; |
| 205 cancel_event->flags = mojom::kEventFlagNone; |
| 206 cancel_event->time_stamp = base::TimeTicks::Now().ToInternalValue(); |
| 207 cancel_event->pointer_data = mojom::PointerData::New(); |
| 208 // TODO(jonross): Track previous location in PointerTarget for sending |
| 209 // cancels |
| 210 cancel_event->pointer_data->location = mojom::LocationData::New(); |
| 211 cancel_event->pointer_data->pointer_id = pair.first; |
| 212 DispatchToPointerTarget(pair.second, std::move(cancel_event)); |
| 213 } |
| 214 pointer_targets_.clear(); |
| 215 } |
| 216 capture_window_ = window; |
| 217 capture_window_in_nonclient_area_ = in_nonclient_area; |
| 218 // Begin tracking the capture window if it is not yet being observed. |
| 219 if (window) |
| 220 window->AddObserver(this); |
| 221 else if (!mouse_button_down_) |
| 222 UpdateCursorProviderByLastKnownLocation(); |
171 } | 223 } |
172 | 224 |
173 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { | 225 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { |
174 if (!mouse_button_down_) { | 226 if (!mouse_button_down_) { |
175 gfx::Point location = mouse_pointer_last_location_; | 227 gfx::Point location = mouse_pointer_last_location_; |
176 mouse_cursor_source_window_ = | 228 mouse_cursor_source_window_ = |
177 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); | 229 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); |
178 } | 230 } |
179 } | 231 } |
180 | 232 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 std::move(event)); | 282 std::move(event)); |
231 } | 283 } |
232 | 284 |
233 void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { | 285 void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { |
234 const bool is_mouse_event = event->pointer_data && | 286 const bool is_mouse_event = event->pointer_data && |
235 event->pointer_data->kind == mojom::PointerKind::MOUSE; | 287 event->pointer_data->kind == mojom::PointerKind::MOUSE; |
236 | 288 |
237 if (is_mouse_event) | 289 if (is_mouse_event) |
238 mouse_pointer_last_location_ = EventLocationToPoint(*event); | 290 mouse_pointer_last_location_ = EventLocationToPoint(*event); |
239 | 291 |
| 292 // Release capture on pointer up. For mouse we only release if there are |
| 293 // no buttons down. |
| 294 const bool is_pointer_going_up = |
| 295 (event->action == mojom::EventType::POINTER_UP || |
| 296 event->action == mojom::EventType::POINTER_CANCEL) && |
| 297 (event->pointer_data->kind != mojom::PointerKind::MOUSE || |
| 298 IsOnlyOneMouseButtonDown(event->flags)); |
| 299 |
| 300 // Update mouse down state upon events which change it. |
| 301 if (is_mouse_event) { |
| 302 if (event->action == mojom::EventType::POINTER_DOWN) |
| 303 mouse_button_down_ = true; |
| 304 else if (is_pointer_going_up) |
| 305 mouse_button_down_ = false; |
| 306 } |
| 307 |
| 308 if (capture_window_) { |
| 309 mouse_cursor_source_window_ = capture_window_; |
| 310 PointerTarget pointer_target; |
| 311 pointer_target.window = capture_window_; |
| 312 pointer_target.in_nonclient_area = capture_window_in_nonclient_area_; |
| 313 DispatchToPointerTarget(pointer_target, std::move(event)); |
| 314 return; |
| 315 } |
| 316 |
240 const int32_t pointer_id = event->pointer_data->pointer_id; | 317 const int32_t pointer_id = event->pointer_data->pointer_id; |
241 if (!IsTrackingPointer(pointer_id) || | 318 if (!IsTrackingPointer(pointer_id) || |
242 !pointer_targets_[pointer_id].is_pointer_down) { | 319 !pointer_targets_[pointer_id].is_pointer_down) { |
243 const bool any_pointers_down = AreAnyPointersDown(); | 320 const bool any_pointers_down = AreAnyPointersDown(); |
244 UpdateTargetForPointer(*event); | 321 UpdateTargetForPointer(*event); |
245 if (is_mouse_event) | 322 if (is_mouse_event) |
246 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window; | 323 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window; |
247 | 324 |
248 PointerTarget& pointer_target = pointer_targets_[pointer_id]; | 325 PointerTarget& pointer_target = pointer_targets_[pointer_id]; |
249 if (pointer_target.is_pointer_down) { | 326 if (pointer_target.is_pointer_down) { |
250 if (is_mouse_event) { | 327 if (is_mouse_event) |
251 mouse_button_down_ = true; | |
252 mouse_cursor_source_window_ = pointer_target.window; | 328 mouse_cursor_source_window_ = pointer_target.window; |
253 } | |
254 if (!any_pointers_down) | 329 if (!any_pointers_down) |
255 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window); | 330 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window); |
256 } | 331 } |
257 } | 332 } |
258 | 333 |
259 // Release capture on pointer up. For mouse we only release if there are | 334 // When we release the mouse button, we want the cursor to be sourced from |
260 // no buttons down. | 335 // the window under the mouse pointer, even though we're sending the button |
261 const bool is_pointer_going_up = | 336 // up event to the window that had implicit capture. We have to set this |
262 (event->action == mojom::EventType::POINTER_UP || | 337 // before we perform dispatch because the Delegate is going to read this |
263 event->action == mojom::EventType::POINTER_CANCEL) && | 338 // information from us. |
264 (event->pointer_data->kind != mojom::PointerKind::MOUSE || | 339 if (is_pointer_going_up && is_mouse_event) |
265 IsOnlyOneMouseButtonDown(event->flags)); | 340 UpdateCursorProviderByLastKnownLocation(); |
266 | |
267 if (is_pointer_going_up && is_mouse_event) { | |
268 // When we release the mouse button, we want the cursor to be sourced from | |
269 // the window under the mouse pointer, even though we're sending the button | |
270 // up event to the window that had implicit capture. We have to set this | |
271 // before we perform dispatch because the Delegate is going to read this | |
272 // information from us. | |
273 mouse_button_down_ = false; | |
274 gfx::Point location(EventLocationToPoint(*event)); | |
275 mouse_cursor_source_window_ = | |
276 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); | |
277 } | |
278 | 341 |
279 DispatchToPointerTarget(pointer_targets_[pointer_id], std::move(event)); | 342 DispatchToPointerTarget(pointer_targets_[pointer_id], std::move(event)); |
280 | 343 |
281 if (is_pointer_going_up) { | 344 if (is_pointer_going_up) { |
282 if (is_mouse_event) | 345 if (is_mouse_event) |
283 pointer_targets_[pointer_id].is_pointer_down = false; | 346 pointer_targets_[pointer_id].is_pointer_down = false; |
284 else | 347 else |
285 StopTrackingPointer(pointer_id); | 348 StopTrackingPointer(pointer_id); |
286 } | 349 } |
287 } | 350 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 transform.TransformPoint(&location); | 436 transform.TransformPoint(&location); |
374 event->pointer_data->location->x = location.x(); | 437 event->pointer_data->location->x = location.x(); |
375 event->pointer_data->location->y = location.y(); | 438 event->pointer_data->location->y = location.y(); |
376 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, | 439 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, |
377 std::move(event)); | 440 std::move(event)); |
378 } | 441 } |
379 | 442 |
380 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { | 443 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { |
381 window->RemoveObserver(this); | 444 window->RemoveObserver(this); |
382 | 445 |
| 446 if (capture_window_ == window) { |
| 447 capture_window_ = nullptr; |
| 448 // A window only cares to be informed that it lost capture if it explicitly |
| 449 // requested capture. A window can lose capture if another window gains |
| 450 // explicit capture. |
| 451 delegate_->OnLostCapture(window); |
| 452 mouse_button_down_ = false; |
| 453 UpdateCursorProviderByLastKnownLocation(); |
| 454 return; |
| 455 } |
| 456 |
383 for (auto& pair : pointer_targets_) { | 457 for (auto& pair : pointer_targets_) { |
384 if (pair.second.window == window) | 458 if (pair.second.window == window) |
385 pair.second.window = nullptr; | 459 pair.second.window = nullptr; |
386 } | 460 } |
387 } | 461 } |
388 | 462 |
389 bool EventDispatcher::IsObservingWindow(ServerWindow* window) { | 463 bool EventDispatcher::IsObservingWindow(ServerWindow* window) { |
390 for (const auto& pair : pointer_targets_) { | 464 for (const auto& pair : pointer_targets_) { |
391 if (pair.second.window == window) | 465 if (pair.second.window == window) |
392 return true; | 466 return true; |
(...skipping 25 matching lines...) Expand all Loading... |
418 | 492 |
419 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { | 493 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { |
420 CancelPointerEventsToTarget(window); | 494 CancelPointerEventsToTarget(window); |
421 | 495 |
422 if (mouse_cursor_source_window_ == window) | 496 if (mouse_cursor_source_window_ == window) |
423 mouse_cursor_source_window_ = nullptr; | 497 mouse_cursor_source_window_ = nullptr; |
424 } | 498 } |
425 | 499 |
426 } // namespace ws | 500 } // namespace ws |
427 } // namespace mus | 501 } // namespace mus |
OLD | NEW |