Index: services/ui/ws/window_tree.cc |
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc |
index 7780d57fe07600d53bc4349aea0e04805ad1d170..30245666b2e9d927296b1e9c5c7f9743f14cdc14 100644 |
--- a/services/ui/ws/window_tree.cc |
+++ b/services/ui/ws/window_tree.cc |
@@ -455,6 +455,11 @@ void WindowTree::AddActivationParent(const ClientWindowId& window_id) { |
} |
void WindowTree::OnChangeCompleted(uint32_t change_id, bool success) { |
+ if (window_server_->in_drag_loop() && |
+ change_id == window_server_->GetCurrentDragLoopChangeId()) { |
+ window_server_->EndDragLoop(); |
+ } |
+ |
client()->OnChangeCompleted(change_id, success); |
} |
@@ -482,6 +487,64 @@ void WindowTree::ClientJankinessChanged(WindowTree* tree) { |
} |
} |
+void WindowTree::PerformOnDragEnter( |
+ const ServerWindow* window, |
+ mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data, |
+ uint32_t key_state, |
+ const gfx::Point& cursor_offset, |
+ uint32_t effect_bitmask, |
+ const base::Callback<void(uint32_t)>& callback) { |
+ ClientWindowId client_window_id; |
+ if (!IsWindowKnown(window, &client_window_id)) { |
+ NOTREACHED(); |
+ callback.Run(0); |
+ return; |
+ } |
+ client()->OnDragEnter(client_window_id.id, std::move(mime_data), key_state, |
+ cursor_offset, effect_bitmask, callback); |
+} |
+ |
+void WindowTree::PerformOnDragOver( |
+ const ServerWindow* window, |
+ uint32_t key_state, |
+ const gfx::Point& cursor_offset, |
+ uint32_t effect_bitmask, |
+ const base::Callback<void(uint32_t)>& callback) { |
+ ClientWindowId client_window_id; |
+ if (!IsWindowKnown(window, &client_window_id)) { |
+ NOTREACHED(); |
+ callback.Run(0); |
+ return; |
+ } |
+ client()->OnDragOver(client_window_id.id, key_state, cursor_offset, |
+ effect_bitmask, callback); |
+} |
+ |
+void WindowTree::PerformOnDragLeave(const ServerWindow* window) { |
+ ClientWindowId client_window_id; |
+ if (!IsWindowKnown(window, &client_window_id)) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ client()->OnDragLeave(client_window_id.id); |
+} |
+ |
+void WindowTree::PerformOnDragDrop( |
+ const ServerWindow* window, |
+ uint32_t key_state, |
+ const gfx::Point& cursor_offset, |
+ uint32_t effect_bitmask, |
+ const base::Callback<void(uint32_t)>& callback) { |
+ ClientWindowId client_window_id; |
+ if (!IsWindowKnown(window, &client_window_id)) { |
+ NOTREACHED(); |
+ callback.Run(0); |
+ return; |
+ } |
+ client()->OnDragDrop(client_window_id.id, key_state, cursor_offset, |
+ effect_bitmask, callback); |
+} |
+ |
void WindowTree::ProcessWindowBoundsChanged(const ServerWindow* window, |
const gfx::Rect& old_bounds, |
const gfx::Rect& new_bounds, |
@@ -1385,6 +1448,16 @@ void WindowTree::SetHitTestMask(Id transport_window_id, |
window->ClearHitTestMask(); |
} |
+void WindowTree::SetCanAcceptDrags(Id window_id, bool accepts_drags) { |
+ ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id)); |
+ if (!window || !access_policy_->CanSetAcceptDrags(window)) { |
+ DVLOG(1) << "SetAcceptsDrags failed"; |
+ return; |
+ } |
+ |
+ window->SetCanAcceptDrags(accepts_drags); |
+} |
+ |
void WindowTree::Embed(Id transport_window_id, |
mojom::WindowTreeClientPtr client, |
uint32_t flags, |
@@ -1450,6 +1523,48 @@ void WindowTree::GetCursorLocationMemory( |
GetCursorLocationMemory()); |
} |
+void WindowTree::PerformDragDrop( |
+ uint32_t change_id, |
+ uint32_t source_window_id, |
+ mojo::Map<mojo::String, mojo::Array<uint8_t>> drag_data, |
+ uint32_t drag_operation, |
+ const gfx::Point& cursor_offset, |
+ const SkBitmap& drag_representation) { |
+ ServerWindow* window = GetWindowByClientId(ClientWindowId(source_window_id)); |
+ bool success = window && access_policy_->CanInitiateMoveLoop(window); |
+ if (!success || !ShouldRouteToWindowManager(window)) { |
+ // We need to fail this move loop change, otherwise the client will just be |
+ // waiting for |change_id|. |
+ OnChangeCompleted(change_id, false); |
+ return; |
+ } |
+ |
+ WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); |
+ if (!display_root) { |
+ // The window isn't parented. There's nothing to do. |
+ OnChangeCompleted(change_id, false); |
+ return; |
+ } |
+ |
+ if (window_server_->in_move_loop() || window_server_->in_drag_loop()) { |
+ // Either the window manager is servicing a window drag or we're servicing |
+ // a drag and drop operation. We can't start a second drag. |
+ OnChangeCompleted(change_id, false); |
+ return; |
+ } |
+ |
+ // TODO(erg): Dealing with |drag_representation| is hard, so we're going to |
+ // deal with that later. |
+ |
+ // Here, we need to dramatically change how the mouse pointer works. Once |
+ // we've started a drag drop operation, cursor events don't go to windows as |
+ // normal. |
+ WindowManagerState* wms = display_root->window_manager_state(); |
+ window_server_->StartDragLoop(change_id); |
+ wms->SetDragDropSourceWindow(change_id, std::move(drag_data), drag_operation, |
+ this, window); |
+} |
+ |
void WindowTree::PerformWindowMove(uint32_t change_id, |
Id window_id, |
ui::mojom::MoveLoopSource source, |
@@ -1470,9 +1585,9 @@ void WindowTree::PerformWindowMove(uint32_t change_id, |
return; |
} |
- if (window_server_->in_move_loop()) { |
- // A window manager is already servicing a move loop; we can't start a |
- // second one. |
+ if (window_server_->in_move_loop() || window_server_->in_drag_loop()) { |
+ // Either the window manager is servicing a window drag or we're servicing |
+ // a drag and drop operation. We can't start a second drag. |
OnChangeCompleted(change_id, false); |
return; |
} |