Chromium Code Reviews| 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)."; |
|
sky
2016/09/15 18:10:47
Thanks for adding the logs. I think they're helpfu
|
| + 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 |