| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ui/aura/mus/drag_drop_controller_mus.h" |
| 6 |
| 7 #include <map> |
| 8 #include <string> |
| 9 #include <vector> |
| 10 |
| 11 #include "base/auto_reset.h" |
| 12 #include "base/message_loop/message_loop.h" |
| 13 #include "base/run_loop.h" |
| 14 #include "services/ui/public/interfaces/window_tree.mojom.h" |
| 15 #include "services/ui/public/interfaces/window_tree_constants.mojom.h" |
| 16 #include "ui/aura/client/drag_drop_delegate.h" |
| 17 #include "ui/aura/mus/drag_drop_controller_host.h" |
| 18 #include "ui/aura/mus/mus_types.h" |
| 19 #include "ui/aura/mus/os_exchange_data_provider_mus.h" |
| 20 #include "ui/aura/mus/window_mus.h" |
| 21 #include "ui/aura/window.h" |
| 22 #include "ui/aura/window_tree_host.h" |
| 23 #include "ui/base/dragdrop/drop_target_event.h" |
| 24 |
| 25 // Interaction with DragDropDelegate assumes constants are the same. |
| 26 static_assert(ui::DragDropTypes::DRAG_NONE == ui::mojom::kDropEffectNone, |
| 27 "Drag constants must be the same"); |
| 28 static_assert(ui::DragDropTypes::DRAG_MOVE == ui::mojom::kDropEffectMove, |
| 29 "Drag constants must be the same"); |
| 30 static_assert(ui::DragDropTypes::DRAG_COPY == ui::mojom::kDropEffectCopy, |
| 31 "Drag constants must be the same"); |
| 32 static_assert(ui::DragDropTypes::DRAG_LINK == ui::mojom::kDropEffectLink, |
| 33 "Drag constants must be the same"); |
| 34 |
| 35 namespace aura { |
| 36 |
| 37 // State related to a drag initiated by this client. |
| 38 struct DragDropControllerMus::CurrentDragState { |
| 39 Id window_id; |
| 40 |
| 41 // The change id of the drag. Used to identify the drag on the server. |
| 42 uint32_t change_id; |
| 43 |
| 44 // The result of the drag. This is set on completion and returned to the |
| 45 // caller. |
| 46 uint32_t completed_action; |
| 47 |
| 48 // OSExchangeData supplied to StartDragAndDrop(). |
| 49 const ui::OSExchangeData& drag_data; |
| 50 |
| 51 // StartDragDrop() runs a nested message loop. This closure is used to quit |
| 52 // the run loop when the drag completes. |
| 53 base::Closure runloop_quit_closure; |
| 54 }; |
| 55 |
| 56 DragDropControllerMus::DragDropControllerMus( |
| 57 DragDropControllerHost* drag_drop_controller_host, |
| 58 ui::mojom::WindowTree* window_tree) |
| 59 : drag_drop_controller_host_(drag_drop_controller_host), |
| 60 window_tree_(window_tree) {} |
| 61 |
| 62 DragDropControllerMus::~DragDropControllerMus() {} |
| 63 |
| 64 bool DragDropControllerMus::DoesChangeIdMatchDragChangeId(uint32_t id) const { |
| 65 return current_drag_state_ && current_drag_state_->change_id == id; |
| 66 } |
| 67 |
| 68 void DragDropControllerMus::OnDragDropStart( |
| 69 std::map<std::string, std::vector<uint8_t>> data) { |
| 70 os_exchange_data_ = base::MakeUnique<ui::OSExchangeData>( |
| 71 base::MakeUnique<aura::OSExchangeDataProviderMus>(std::move(data))); |
| 72 } |
| 73 |
| 74 uint32_t DragDropControllerMus::OnDragEnter(WindowMus* window, |
| 75 uint32_t event_flags, |
| 76 const gfx::Point& screen_location, |
| 77 uint32_t effect_bitmask) { |
| 78 return HandleDragEnterOrOver(window, event_flags, screen_location, |
| 79 effect_bitmask, true); |
| 80 } |
| 81 |
| 82 uint32_t DragDropControllerMus::OnDragOver(WindowMus* window, |
| 83 uint32_t event_flags, |
| 84 const gfx::Point& screen_location, |
| 85 uint32_t effect_bitmask) { |
| 86 return HandleDragEnterOrOver(window, event_flags, screen_location, |
| 87 effect_bitmask, false); |
| 88 } |
| 89 |
| 90 void DragDropControllerMus::OnDragLeave(WindowMus* window) { |
| 91 if (drop_target_window_tracker_.windows().empty()) |
| 92 return; |
| 93 DCHECK(window); |
| 94 Window* current_target = drop_target_window_tracker_.Pop(); |
| 95 DCHECK_EQ(window->GetWindow(), current_target); |
| 96 client::GetDragDropDelegate(current_target)->OnDragExited(); |
| 97 } |
| 98 |
| 99 uint32_t DragDropControllerMus::OnCompleteDrop( |
| 100 WindowMus* window, |
| 101 uint32_t event_flags, |
| 102 const gfx::Point& screen_location, |
| 103 uint32_t effect_bitmask) { |
| 104 if (drop_target_window_tracker_.windows().empty()) |
| 105 return ui::mojom::kDropEffectNone; |
| 106 |
| 107 DCHECK(window); |
| 108 Window* current_target = drop_target_window_tracker_.Pop(); |
| 109 DCHECK_EQ(window->GetWindow(), current_target); |
| 110 std::unique_ptr<ui::DropTargetEvent> event = CreateDropTargetEvent( |
| 111 window->GetWindow(), event_flags, screen_location, effect_bitmask); |
| 112 return client::GetDragDropDelegate(current_target)->OnPerformDrop(*event); |
| 113 } |
| 114 |
| 115 void DragDropControllerMus::OnPerformDragDropCompleted(uint32_t action_taken) { |
| 116 DCHECK(current_drag_state_); |
| 117 current_drag_state_->completed_action = action_taken; |
| 118 current_drag_state_->runloop_quit_closure.Run(); |
| 119 } |
| 120 |
| 121 void DragDropControllerMus::OnDragDropDone() { |
| 122 os_exchange_data_.reset(); |
| 123 } |
| 124 |
| 125 int DragDropControllerMus::StartDragAndDrop( |
| 126 const ui::OSExchangeData& data, |
| 127 Window* root_window, |
| 128 Window* source_window, |
| 129 const gfx::Point& screen_location, |
| 130 int drag_operations, |
| 131 ui::DragDropTypes::DragEventSource source) { |
| 132 DCHECK(!current_drag_state_); |
| 133 |
| 134 // TODO(erg): Pass |cursor_location| and |bitmap| in PerformDragDrop() when |
| 135 // we start showing an image representation of the drag under he cursor. |
| 136 |
| 137 base::RunLoop run_loop; |
| 138 WindowMus* source_window_mus = WindowMus::Get(source_window); |
| 139 const uint32_t change_id = |
| 140 drag_drop_controller_host_->CreateChangeIdForDrag(source_window_mus); |
| 141 CurrentDragState current_drag_state = {source_window_mus->server_id(), |
| 142 change_id, ui::mojom::kDropEffectNone, |
| 143 data, run_loop.QuitClosure()}; |
| 144 base::AutoReset<CurrentDragState*> resetter(¤t_drag_state_, |
| 145 ¤t_drag_state); |
| 146 std::map<std::string, std::vector<uint8_t>> drag_data = |
| 147 static_cast<const aura::OSExchangeDataProviderMus&>(data.provider()) |
| 148 .GetData(); |
| 149 window_tree_->PerformDragDrop( |
| 150 change_id, source_window_mus->server_id(), |
| 151 mojo::Map<mojo::String, mojo::Array<uint8_t>>::From(drag_data), |
| 152 drag_operations); |
| 153 |
| 154 base::MessageLoop* loop = base::MessageLoop::current(); |
| 155 base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); |
| 156 run_loop.Run(); |
| 157 |
| 158 return current_drag_state.completed_action; |
| 159 } |
| 160 |
| 161 void DragDropControllerMus::DragCancel() { |
| 162 DCHECK(current_drag_state_); |
| 163 // Server will clean up drag and fail the in-flight change. |
| 164 window_tree_->CancelDragDrop(current_drag_state_->window_id); |
| 165 } |
| 166 |
| 167 bool DragDropControllerMus::IsDragDropInProgress() { |
| 168 return current_drag_state_ != nullptr; |
| 169 } |
| 170 |
| 171 uint32_t DragDropControllerMus::HandleDragEnterOrOver( |
| 172 WindowMus* window, |
| 173 uint32_t event_flags, |
| 174 const gfx::Point& screen_location, |
| 175 uint32_t effect_bitmask, |
| 176 bool is_enter) { |
| 177 client::DragDropDelegate* drag_drop_delegate = |
| 178 window ? client::GetDragDropDelegate(window->GetWindow()) : nullptr; |
| 179 WindowTreeHost* window_tree_host = |
| 180 window ? window->GetWindow()->GetHost() : nullptr; |
| 181 if ((!is_enter && drop_target_window_tracker_.windows().empty()) || |
| 182 !drag_drop_delegate || !window_tree_host) { |
| 183 drop_target_window_tracker_.RemoveAll(); |
| 184 return ui::mojom::kDropEffectNone; |
| 185 } |
| 186 drop_target_window_tracker_.Add(window->GetWindow()); |
| 187 |
| 188 std::unique_ptr<ui::DropTargetEvent> event = CreateDropTargetEvent( |
| 189 window->GetWindow(), event_flags, screen_location, effect_bitmask); |
| 190 if (is_enter) |
| 191 drag_drop_delegate->OnDragEntered(*event); |
| 192 return drag_drop_delegate->OnDragUpdated(*event); |
| 193 } |
| 194 |
| 195 std::unique_ptr<ui::DropTargetEvent> |
| 196 DragDropControllerMus::CreateDropTargetEvent(Window* window, |
| 197 uint32_t event_flags, |
| 198 const gfx::Point& screen_location, |
| 199 uint32_t effect_bitmask) { |
| 200 DCHECK(window->GetHost()); |
| 201 gfx::Point root_location = screen_location; |
| 202 window->GetHost()->ConvertPointFromNativeScreen(&root_location); |
| 203 gfx::Point location = root_location; |
| 204 Window::ConvertPointToTarget(window->GetRootWindow(), window, &location); |
| 205 std::unique_ptr<ui::DropTargetEvent> event = |
| 206 base::MakeUnique<ui::DropTargetEvent>( |
| 207 current_drag_state_ ? current_drag_state_->drag_data |
| 208 : *(os_exchange_data_.get()), |
| 209 location, root_location, effect_bitmask); |
| 210 event->set_flags(event_flags); |
| 211 return event; |
| 212 } |
| 213 |
| 214 } // namespace aura |
| OLD | NEW |