| 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 |