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/event_dispatcher.h" | 5 #include "services/ui/ws/event_dispatcher.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
10 #include "services/ui/ws/accelerator.h" | 10 #include "services/ui/ws/accelerator.h" |
11 #include "services/ui/ws/display.h" | 11 #include "services/ui/ws/display.h" |
| 12 #include "services/ui/ws/drag_controller.h" |
| 13 #include "services/ui/ws/drag_source.h" |
12 #include "services/ui/ws/event_dispatcher_delegate.h" | 14 #include "services/ui/ws/event_dispatcher_delegate.h" |
13 #include "services/ui/ws/server_window.h" | 15 #include "services/ui/ws/server_window.h" |
14 #include "services/ui/ws/server_window_delegate.h" | 16 #include "services/ui/ws/server_window_delegate.h" |
15 #include "services/ui/ws/window_coordinate_conversions.h" | 17 #include "services/ui/ws/window_coordinate_conversions.h" |
16 #include "services/ui/ws/window_finder.h" | 18 #include "services/ui/ws/window_finder.h" |
17 #include "ui/events/event_utils.h" | 19 #include "ui/events/event_utils.h" |
18 #include "ui/gfx/geometry/point.h" | 20 #include "ui/gfx/geometry/point.h" |
19 #include "ui/gfx/geometry/point_conversions.h" | 21 #include "ui/gfx/geometry/point_conversions.h" |
20 | 22 |
21 namespace ui { | 23 namespace ui { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 if (!window) | 118 if (!window) |
117 client_id = kInvalidClientId; | 119 client_id = kInvalidClientId; |
118 | 120 |
119 if (window == capture_window_ && client_id == capture_window_client_id_) | 121 if (window == capture_window_ && client_id == capture_window_client_id_) |
120 return true; | 122 return true; |
121 | 123 |
122 // A window that is blocked by a modal window cannot gain capture. | 124 // A window that is blocked by a modal window cannot gain capture. |
123 if (window && modal_window_controller_.IsWindowBlocked(window)) | 125 if (window && modal_window_controller_.IsWindowBlocked(window)) |
124 return false; | 126 return false; |
125 | 127 |
| 128 // If we're currently performing a drag and drop, reject setting the capture |
| 129 // window. |
| 130 if (drag_controller_) |
| 131 return false; |
| 132 |
126 if (capture_window_) { | 133 if (capture_window_) { |
127 // Stop observing old capture window. |pointer_targets_| are cleared on | 134 // Stop observing old capture window. |pointer_targets_| are cleared on |
128 // initial setting of a capture window. | 135 // initial setting of a capture window. |
129 UnobserveWindow(capture_window_); | 136 UnobserveWindow(capture_window_); |
130 } else { | 137 } else { |
131 // Cancel implicit capture to all other windows. | 138 CancelImplicitCaptureExcept(window); |
132 for (const auto& pair : pointer_targets_) { | |
133 ServerWindow* target = pair.second.window; | |
134 if (!target) | |
135 continue; | |
136 UnobserveWindow(target); | |
137 if (target == window) | |
138 continue; | |
139 | |
140 ui::EventType event_type = pair.second.is_mouse_event | |
141 ? ui::ET_POINTER_EXITED | |
142 : ui::ET_POINTER_CANCELLED; | |
143 ui::EventPointerType pointer_type = | |
144 pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE | |
145 : ui::EventPointerType::POINTER_TYPE_TOUCH; | |
146 // TODO(jonross): Track previous location in PointerTarget for sending | |
147 // cancels. | |
148 ui::PointerEvent event( | |
149 event_type, gfx::Point(), gfx::Point(), ui::EF_NONE, pair.first, | |
150 0 /* changed_button_flags */, ui::PointerDetails(pointer_type), | |
151 ui::EventTimeForNow()); | |
152 DispatchToPointerTarget(pair.second, event); | |
153 } | |
154 pointer_targets_.clear(); | |
155 } | 139 } |
156 | 140 |
157 // Set the capture before changing native capture; otherwise, the callback | 141 // Set the capture before changing native capture; otherwise, the callback |
158 // from native platform might try to set the capture again. | 142 // from native platform might try to set the capture again. |
159 const bool had_capture_window = capture_window_ != nullptr; | 143 const bool had_capture_window = capture_window_ != nullptr; |
160 ServerWindow* old_capture_window = capture_window_; | 144 ServerWindow* old_capture_window = capture_window_; |
161 capture_window_ = window; | 145 capture_window_ = window; |
162 capture_window_client_id_ = client_id; | 146 capture_window_client_id_ = client_id; |
163 | 147 |
164 delegate_->OnCaptureChanged(capture_window_, old_capture_window); | 148 delegate_->OnCaptureChanged(capture_window_, old_capture_window); |
165 | 149 |
166 // Begin tracking the capture window if it is not yet being observed. | 150 // Begin tracking the capture window if it is not yet being observed. |
167 if (window) { | 151 if (window) { |
168 ObserveWindow(window); | 152 ObserveWindow(window); |
169 // TODO(sky): this conditional is problematic for the case of capture moving | 153 // TODO(sky): this conditional is problematic for the case of capture moving |
170 // to a different display. | 154 // to a different display. |
171 if (!had_capture_window) | 155 if (!had_capture_window) |
172 delegate_->SetNativeCapture(window); | 156 delegate_->SetNativeCapture(window); |
173 } else { | 157 } else { |
174 delegate_->ReleaseNativeCapture(); | 158 delegate_->ReleaseNativeCapture(); |
175 if (!mouse_button_down_) | 159 if (!mouse_button_down_) |
176 UpdateCursorProviderByLastKnownLocation(); | 160 UpdateCursorProviderByLastKnownLocation(); |
177 } | 161 } |
178 | 162 |
179 return true; | 163 return true; |
180 } | 164 } |
181 | 165 |
| 166 void EventDispatcher::SetDragDropSourceWindow( |
| 167 DragSource* drag_source, |
| 168 ServerWindow* window, |
| 169 DragTargetConnection* source_connection, |
| 170 int32_t drag_pointer, |
| 171 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data, |
| 172 uint32_t drag_operations) { |
| 173 CancelImplicitCaptureExcept(nullptr); |
| 174 drag_controller_ = base::MakeUnique<DragController>( |
| 175 drag_source, window, source_connection, drag_pointer, |
| 176 std::move(mime_data), drag_operations); |
| 177 } |
| 178 |
| 179 void EventDispatcher::EndDragDrop() { |
| 180 drag_controller_.reset(); |
| 181 } |
| 182 |
| 183 void EventDispatcher::OnWillDestroyDragTargetConnection( |
| 184 DragTargetConnection* connection) { |
| 185 if (drag_controller_) |
| 186 drag_controller_->OnWillDestroyDragTargetConnection(connection); |
| 187 } |
| 188 |
182 void EventDispatcher::AddSystemModalWindow(ServerWindow* window) { | 189 void EventDispatcher::AddSystemModalWindow(ServerWindow* window) { |
183 modal_window_controller_.AddSystemModalWindow(window); | 190 modal_window_controller_.AddSystemModalWindow(window); |
184 } | 191 } |
185 | 192 |
186 void EventDispatcher::ReleaseCaptureBlockedByModalWindow( | 193 void EventDispatcher::ReleaseCaptureBlockedByModalWindow( |
187 const ServerWindow* modal_window) { | 194 const ServerWindow* modal_window) { |
188 if (!capture_window_) | 195 if (!capture_window_) |
189 return; | 196 return; |
190 | 197 |
191 if (modal_window_controller_.IsWindowBlockedBy(capture_window_, | 198 if (modal_window_controller_.IsWindowBlockedBy(capture_window_, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 287 |
281 DCHECK(event.IsPointerEvent()); | 288 DCHECK(event.IsPointerEvent()); |
282 ProcessPointerEvent(*event.AsPointerEvent()); | 289 ProcessPointerEvent(*event.AsPointerEvent()); |
283 return; | 290 return; |
284 } | 291 } |
285 | 292 |
286 void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event, | 293 void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event, |
287 AcceleratorMatchPhase match_phase) { | 294 AcceleratorMatchPhase match_phase) { |
288 Accelerator* post_target = | 295 Accelerator* post_target = |
289 FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET); | 296 FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET); |
| 297 if (drag_controller_ && event.type() == ui::ET_KEY_PRESSED && |
| 298 event.key_code() == ui::VKEY_ESCAPE) { |
| 299 drag_controller_->Cancel(); |
| 300 return; |
| 301 } |
290 ServerWindow* focused_window = | 302 ServerWindow* focused_window = |
291 delegate_->GetFocusedWindowForEventDispatcher(); | 303 delegate_->GetFocusedWindowForEventDispatcher(); |
292 if (focused_window) { | 304 if (focused_window) { |
293 // Assume key events are for the client area. | 305 // Assume key events are for the client area. |
294 const bool in_nonclient_area = false; | 306 const bool in_nonclient_area = false; |
295 const ClientSpecificId client_id = | 307 const ClientSpecificId client_id = |
296 delegate_->GetEventTargetClientId(focused_window, in_nonclient_area); | 308 delegate_->GetEventTargetClientId(focused_window, in_nonclient_area); |
297 delegate_->DispatchInputEventToWindow(focused_window, client_id, event, | 309 delegate_->DispatchInputEventToWindow(focused_window, client_id, event, |
298 post_target); | 310 post_target); |
299 return; | 311 return; |
(...skipping 21 matching lines...) Expand all Loading... |
321 (!is_mouse_event || IsOnlyOneMouseButtonDown(event.flags())); | 333 (!is_mouse_event || IsOnlyOneMouseButtonDown(event.flags())); |
322 | 334 |
323 // Update mouse down state upon events which change it. | 335 // Update mouse down state upon events which change it. |
324 if (is_mouse_event) { | 336 if (is_mouse_event) { |
325 if (event.type() == ui::ET_POINTER_DOWN) | 337 if (event.type() == ui::ET_POINTER_DOWN) |
326 mouse_button_down_ = true; | 338 mouse_button_down_ = true; |
327 else if (is_pointer_going_up) | 339 else if (is_pointer_going_up) |
328 mouse_button_down_ = false; | 340 mouse_button_down_ = false; |
329 } | 341 } |
330 | 342 |
| 343 if (drag_controller_) { |
| 344 const PointerTarget target = PointerTargetForEvent(event); |
| 345 if (drag_controller_->DispatchPointerEvent(event, target.window)) |
| 346 return; |
| 347 } |
| 348 |
331 if (capture_window_) { | 349 if (capture_window_) { |
332 mouse_cursor_source_window_ = capture_window_; | 350 mouse_cursor_source_window_ = capture_window_; |
333 DispatchToClient(capture_window_, capture_window_client_id_, event); | 351 DispatchToClient(capture_window_, capture_window_client_id_, event); |
334 return; | 352 return; |
335 } | 353 } |
336 | 354 |
337 const int32_t pointer_id = event.pointer_id(); | 355 const int32_t pointer_id = event.pointer_id(); |
338 if (!IsTrackingPointer(pointer_id) || | 356 if (!IsTrackingPointer(pointer_id) || |
339 !pointer_targets_[pointer_id].is_pointer_down) { | 357 !pointer_targets_[pointer_id].is_pointer_down) { |
340 const bool any_pointers_down = AreAnyPointersDown(); | 358 const bool any_pointers_down = AreAnyPointersDown(); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 | 546 |
529 ServerWindow* EventDispatcher::FindDeepestVisibleWindowForEvents( | 547 ServerWindow* EventDispatcher::FindDeepestVisibleWindowForEvents( |
530 gfx::Point* location) { | 548 gfx::Point* location) { |
531 ServerWindow* root = delegate_->GetRootWindowContaining(location); | 549 ServerWindow* root = delegate_->GetRootWindowContaining(location); |
532 if (!root) | 550 if (!root) |
533 return nullptr; | 551 return nullptr; |
534 | 552 |
535 return ui::ws::FindDeepestVisibleWindowForEvents(root, location); | 553 return ui::ws::FindDeepestVisibleWindowForEvents(root, location); |
536 } | 554 } |
537 | 555 |
| 556 void EventDispatcher::CancelImplicitCaptureExcept(ServerWindow* window) { |
| 557 for (const auto& pair : pointer_targets_) { |
| 558 ServerWindow* target = pair.second.window; |
| 559 if (!target) |
| 560 continue; |
| 561 UnobserveWindow(target); |
| 562 if (target == window) |
| 563 continue; |
| 564 |
| 565 ui::EventType event_type = pair.second.is_mouse_event |
| 566 ? ui::ET_POINTER_EXITED |
| 567 : ui::ET_POINTER_CANCELLED; |
| 568 ui::EventPointerType pointer_type = |
| 569 pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE |
| 570 : ui::EventPointerType::POINTER_TYPE_TOUCH; |
| 571 // TODO(jonross): Track previous location in PointerTarget for sending |
| 572 // cancels. |
| 573 ui::PointerEvent event(event_type, gfx::Point(), gfx::Point(), ui::EF_NONE, |
| 574 pair.first, 0 /* changed_button_flags */, |
| 575 ui::PointerDetails(pointer_type), |
| 576 ui::EventTimeForNow()); |
| 577 DispatchToPointerTarget(pair.second, event); |
| 578 } |
| 579 pointer_targets_.clear(); |
| 580 } |
| 581 |
538 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, | 582 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, |
539 ServerWindow* new_parent, | 583 ServerWindow* new_parent, |
540 ServerWindow* old_parent) { | 584 ServerWindow* old_parent) { |
541 // TODO(sky): moving to a different root likely needs to transfer capture. | 585 // TODO(sky): moving to a different root likely needs to transfer capture. |
542 // TODO(sky): this isn't quite right, I think the logic should be (assuming | 586 // TODO(sky): this isn't quite right, I think the logic should be (assuming |
543 // moving in same root and still drawn): | 587 // moving in same root and still drawn): |
544 // . if there is capture and window is still in the same root, continue | 588 // . if there is capture and window is still in the same root, continue |
545 // sending to it. | 589 // sending to it. |
546 // . if there isn't capture, then reevaluate each of the pointer targets | 590 // . if there isn't capture, then reevaluate each of the pointer targets |
547 // sending exit as necessary. | 591 // sending exit as necessary. |
(...skipping 10 matching lines...) Expand all Loading... |
558 | 602 |
559 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { | 603 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { |
560 CancelPointerEventsToTarget(window); | 604 CancelPointerEventsToTarget(window); |
561 | 605 |
562 if (mouse_cursor_source_window_ == window) | 606 if (mouse_cursor_source_window_ == window) |
563 mouse_cursor_source_window_ = nullptr; | 607 mouse_cursor_source_window_ = nullptr; |
564 } | 608 } |
565 | 609 |
566 } // namespace ws | 610 } // namespace ws |
567 } // namespace ui | 611 } // namespace ui |
OLD | NEW |