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