Index: services/ui/ws/event_dispatcher.cc |
diff --git a/services/ui/ws/event_dispatcher.cc b/services/ui/ws/event_dispatcher.cc |
index 3890db7bb4bc43bd2fa893296d11ec19d1e64634..a917e9065c870ea12ee50a7433baf02543cd0d09 100644 |
--- a/services/ui/ws/event_dispatcher.cc |
+++ b/services/ui/ws/event_dispatcher.cc |
@@ -9,6 +9,8 @@ |
#include "base/time/time.h" |
#include "services/ui/ws/accelerator.h" |
#include "services/ui/ws/display.h" |
+#include "services/ui/ws/drag_controller.h" |
+#include "services/ui/ws/drag_source.h" |
#include "services/ui/ws/event_dispatcher_delegate.h" |
#include "services/ui/ws/server_window.h" |
#include "services/ui/ws/server_window_delegate.h" |
@@ -123,35 +125,17 @@ bool EventDispatcher::SetCaptureWindow(ServerWindow* window, |
if (window && modal_window_controller_.IsWindowBlocked(window)) |
return false; |
+ // If we're currently performing a drag and drop, reject setting the capture |
+ // window. |
+ if (drag_controller_) |
+ return false; |
+ |
if (capture_window_) { |
// Stop observing old capture window. |pointer_targets_| are cleared on |
// initial setting of a capture window. |
UnobserveWindow(capture_window_); |
} else { |
- // Cancel implicit capture to all other windows. |
- for (const auto& pair : pointer_targets_) { |
- ServerWindow* target = pair.second.window; |
- if (!target) |
- continue; |
- UnobserveWindow(target); |
- if (target == window) |
- continue; |
- |
- ui::EventType event_type = pair.second.is_mouse_event |
- ? ui::ET_POINTER_EXITED |
- : ui::ET_POINTER_CANCELLED; |
- ui::EventPointerType pointer_type = |
- pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE |
- : ui::EventPointerType::POINTER_TYPE_TOUCH; |
- // TODO(jonross): Track previous location in PointerTarget for sending |
- // cancels. |
- ui::PointerEvent event( |
- event_type, gfx::Point(), gfx::Point(), ui::EF_NONE, pair.first, |
- 0 /* changed_button_flags */, ui::PointerDetails(pointer_type), |
- ui::EventTimeForNow()); |
- DispatchToPointerTarget(pair.second, event); |
- } |
- pointer_targets_.clear(); |
+ CancelImplicitCaptureExcept(window); |
} |
// Set the capture before changing native capture; otherwise, the callback |
@@ -179,6 +163,29 @@ bool EventDispatcher::SetCaptureWindow(ServerWindow* window, |
return true; |
} |
+void EventDispatcher::SetDragDropSourceWindow( |
+ DragSource* drag_source, |
+ ServerWindow* window, |
+ DragTargetConnection* source_connection, |
+ int32_t drag_pointer, |
+ mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data, |
+ uint32_t drag_operations) { |
+ CancelImplicitCaptureExcept(nullptr); |
+ drag_controller_ = base::MakeUnique<DragController>( |
+ drag_source, window, source_connection, drag_pointer, |
+ std::move(mime_data), drag_operations); |
+} |
+ |
+void EventDispatcher::EndDragDrop() { |
+ drag_controller_.reset(); |
+} |
+ |
+void EventDispatcher::OnWillDestroyDragTargetConnection( |
+ DragTargetConnection* connection) { |
+ if (drag_controller_) |
+ drag_controller_->OnWillDestroyDragTargetConnection(connection); |
+} |
+ |
void EventDispatcher::AddSystemModalWindow(ServerWindow* window) { |
modal_window_controller_.AddSystemModalWindow(window); |
} |
@@ -287,6 +294,11 @@ void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event, |
AcceleratorMatchPhase match_phase) { |
Accelerator* post_target = |
FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET); |
+ if (drag_controller_ && event.type() == ui::ET_KEY_PRESSED && |
+ event.key_code() == ui::VKEY_ESCAPE) { |
+ drag_controller_->Cancel(); |
+ return; |
+ } |
ServerWindow* focused_window = |
delegate_->GetFocusedWindowForEventDispatcher(); |
if (focused_window) { |
@@ -328,6 +340,12 @@ void EventDispatcher::ProcessPointerEvent(const ui::PointerEvent& event) { |
mouse_button_down_ = false; |
} |
+ if (drag_controller_) { |
+ const PointerTarget target = PointerTargetForEvent(event); |
+ if (drag_controller_->DispatchPointerEvent(event, target.window)) |
+ return; |
+ } |
+ |
if (capture_window_) { |
mouse_cursor_source_window_ = capture_window_; |
DispatchToClient(capture_window_, capture_window_client_id_, event); |
@@ -535,6 +553,32 @@ ServerWindow* EventDispatcher::FindDeepestVisibleWindowForEvents( |
return ui::ws::FindDeepestVisibleWindowForEvents(root, location); |
} |
+void EventDispatcher::CancelImplicitCaptureExcept(ServerWindow* window) { |
+ for (const auto& pair : pointer_targets_) { |
+ ServerWindow* target = pair.second.window; |
+ if (!target) |
+ continue; |
+ UnobserveWindow(target); |
+ if (target == window) |
+ continue; |
+ |
+ ui::EventType event_type = pair.second.is_mouse_event |
+ ? ui::ET_POINTER_EXITED |
+ : ui::ET_POINTER_CANCELLED; |
+ ui::EventPointerType pointer_type = |
+ pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE |
+ : ui::EventPointerType::POINTER_TYPE_TOUCH; |
+ // TODO(jonross): Track previous location in PointerTarget for sending |
+ // cancels. |
+ ui::PointerEvent event(event_type, gfx::Point(), gfx::Point(), ui::EF_NONE, |
+ pair.first, 0 /* changed_button_flags */, |
+ ui::PointerDetails(pointer_type), |
+ ui::EventTimeForNow()); |
+ DispatchToPointerTarget(pair.second, event); |
+ } |
+ pointer_targets_.clear(); |
+} |
+ |
void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, |
ServerWindow* new_parent, |
ServerWindow* old_parent) { |