Index: services/ui/ws/window_tree.cc |
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc |
index d25ce00a41e3b706328990879d2b9761ef6edbc1..4af13d6344f88bff5fe8d9d25d18bb83540519eb 100644 |
--- a/services/ui/ws/window_tree.cc |
+++ b/services/ui/ws/window_tree.cc |
@@ -1388,6 +1388,16 @@ void WindowTree::SetHitTestMask(Id transport_window_id, |
window->ClearHitTestMask(); |
} |
+void WindowTree::SetCanAcceptDrops(Id window_id, bool accepts_drops) { |
+ ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id)); |
+ if (!window || !access_policy_->CanSetAcceptDrops(window)) { |
+ DVLOG(1) << "SetAcceptsDrops failed"; |
+ return; |
+ } |
+ |
+ window->SetCanAcceptDrops(accepts_drops); |
+} |
+ |
void WindowTree::Embed(Id transport_window_id, |
mojom::WindowTreeClientPtr client, |
uint32_t flags, |
@@ -1453,6 +1463,50 @@ void WindowTree::GetCursorLocationMemory( |
GetCursorLocationMemory()); |
} |
+void WindowTree::PerformDragDrop( |
+ uint32_t change_id, |
+ Id source_window_id, |
+ int32_t drag_pointer, |
+ mojo::Map<mojo::String, mojo::Array<uint8_t>> drag_data, |
+ uint32_t drag_operation) { |
+ ServerWindow* window = GetWindowByClientId(ClientWindowId(source_window_id)); |
+ bool success = window && access_policy_->CanInitiateDragLoop(window); |
+ if (!success || !ShouldRouteToWindowManager(window)) { |
+ // We need to fail this move loop change, otherwise the client will just be |
+ // waiting for |change_id|. |
+ DVLOG(1) << "PerformDragDrop failed (access denied)."; |
+ OnChangeCompleted(change_id, false); |
+ return; |
+ } |
+ |
+ WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); |
+ if (!display_root) { |
+ // The window isn't parented. There's nothing to do. |
+ DVLOG(1) << "PerformDragDrop failed (window unparented)."; |
+ 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. |
+ DVLOG(1) << "PerformDragDrop failed (already performing a 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, window, this); |
+ wms->SetDragDropSourceWindow(this, window, this, drag_pointer, |
+ std::move(drag_data), drag_operation); |
+} |
+ |
void WindowTree::PerformWindowMove(uint32_t change_id, |
Id window_id, |
ui::mojom::MoveLoopSource source, |
@@ -1462,6 +1516,7 @@ void WindowTree::PerformWindowMove(uint32_t change_id, |
if (!success || !ShouldRouteToWindowManager(window)) { |
// We need to fail this move loop change, otherwise the client will just be |
// waiting for |change_id|. |
+ DVLOG(1) << "PerformWindowMove failed (access denied)."; |
OnChangeCompleted(change_id, false); |
return; |
} |
@@ -1469,13 +1524,15 @@ void WindowTree::PerformWindowMove(uint32_t change_id, |
WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); |
if (!display_root) { |
// The window isn't parented. There's nothing to do. |
+ DVLOG(1) << "PerformWindowMove failed (window unparented)."; |
OnChangeCompleted(change_id, false); |
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. |
+ DVLOG(1) << "PerformWindowMove failed (already performing a drag)."; |
OnChangeCompleted(change_id, false); |
return; |
} |
@@ -1682,5 +1739,104 @@ bool WindowTree::IsWindowRootOfAnotherTreeForAccessPolicy( |
return tree && tree != this; |
} |
+void WindowTree::OnDragCompleted(bool success) { |
+ DCHECK(window_server_->in_drag_loop()); |
+ |
+ if (window_server_->GetCurrentDragLoopInitiator() != this) |
+ return; |
+ |
+ uint32_t change_id = window_server_->GetCurrentDragLoopChangeId(); |
+ ServerWindow* window = window_server_->GetCurrentDragLoopWindow(); |
+ WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); |
+ if (!display_root) |
+ return; |
+ |
+ window_server_->EndDragLoop(); |
+ WindowManagerState* wms = display_root->window_manager_state(); |
+ wms->EndDragDrop(); |
+ |
+ client()->OnChangeCompleted(change_id, success); |
+} |
+ |
+ServerWindow* WindowTree::GetWindowById(const WindowId& id) { |
+ return GetWindow(id); |
+} |
+ |
+DragTargetConnection* WindowTree::GetDragTargetForWindow( |
+ const ServerWindow* window) { |
+ if (!window) |
+ return nullptr; |
+ DragTargetConnection* connection = window_server_->GetTreeWithRoot(window); |
+ if (connection) |
+ return connection; |
+ return window_server_->GetTreeWithId(window->id().client_id); |
+} |
+ |
+void WindowTree::PerformOnDragDropStart( |
+ mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data) { |
+ client()->OnDragDropStart(std::move(mime_data)); |
+} |
+ |
+void WindowTree::PerformOnDragEnter( |
+ const ServerWindow* window, |
+ uint32_t event_flags, |
+ 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, event_flags, cursor_offset, |
+ effect_bitmask, callback); |
+} |
+ |
+void WindowTree::PerformOnDragOver( |
+ const ServerWindow* window, |
+ uint32_t event_flags, |
+ 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, event_flags, 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::PerformOnCompleteDrop( |
+ const ServerWindow* window, |
+ uint32_t event_flags, |
+ 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()->OnCompleteDrop(client_window_id.id, event_flags, cursor_offset, |
+ effect_bitmask, callback); |
+} |
+ |
+void WindowTree::PerformOnDragDropDone() { |
+ client()->OnDragDropDone(); |
+} |
+ |
} // namespace ws |
} // namespace ui |