Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: services/ui/ws/current_drag_operation.cc

Issue 2266603002: mus: Implement interwindow drag and drop (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Uploaded for a few comments. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "services/ui/ws/current_drag_operation.h"
6
7 #include "base/logging.h"
8 #include "services/ui/ws/current_drag_operation_delegate.h"
9 #include "services/ui/ws/event_dispatcher.h"
10 #include "services/ui/ws/server_window.h"
11 #include "services/ui/ws/window_server.h"
12 #include "services/ui/ws/window_tree.h"
13
14 namespace ui {
15 namespace ws {
16
17 enum DragEventType { TYPE_ENTER, TYPE_OVER, TYPE_LEAVE, TYPE_DROP };
18
19 struct CurrentDragOperation::Operation {
20 DragEventType type;
21 uint32_t key_state;
22 gfx::Point position;
23 };
24
25 // TODO(erg): We need to know when WindowTree gets destroyed, or otherwise put
26 // in another layer to communicate back that. This is threaded from the a
27 // WindowTree to a WMS to the EventDispatcher to here.
28
29 CurrentDragOperation::CurrentDragOperation(
30 CurrentDragOperationDelegate* delegate,
31 uint32_t change_id,
32 WindowTree* source_window_tree,
33 ServerWindow* source_window,
34 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data,
35 uint32_t drag_operations)
36 : delegate_(delegate),
37 change_id_(change_id),
38 drag_operations_(drag_operations),
39 source_window_tree_(source_window_tree),
40 window_server_(source_window_tree->window_server()),
41 source_window_(source_window),
42 mime_data_(std::move(mime_data)),
43 weak_factory_(this) {
44 source_window_->AddObserver(this);
45 }
46
47 CurrentDragOperation::~CurrentDragOperation() {
48 source_window_->RemoveObserver(this);
49 }
50
51 void CurrentDragOperation::DispatchLocatedEvent(
52 const ui::LocatedEvent& event,
53 ServerWindow* current_target,
54 const ClientSpecificId& client_id) {
55 uint32_t key_state = event.flags();
56 gfx::Point position = event.location();
57
58 if (waiting_for_final_drop_response_) {
59 // If we're waiting on a target window to respond to the final drag drop
60 // call, don't process any more mouse events.
61 return;
62 }
63
64 if (current_target && !current_target->can_accept_drags()) {
65 // If the current window over point doesn't accept drops, than don't send
66 // it events.
67 current_target = nullptr;
68 }
69
70 if (event.type() == ET_POINTER_UP) {
71 if (current_target) {
72 auto& window_ops = current_window_state_[current_target];
73 window_ops.push_back({TYPE_DROP, key_state, position});
74 if (window_ops.size() == 1)
75 DispatchFrontOfWindowQueue(current_target, &window_ops);
76 } else {
77 // The pointer was released over no window or a window that doesn't
78 // accept drags.
79 MessageDragCompleted(false);
80 }
81
82 return;
83 }
84
85 if (current_target && current_target == current_target_window_) {
86 // We're continuing a drag inside the bounds of
87 // |current_target_window_|. Send a continue message.
88
89 auto& window_ops = current_window_state_[current_target];
90 if (window_ops.empty()) {
91 // We have no window operations so send it immediately.
92 window_ops.push_back({TYPE_OVER, key_state, position});
93 DispatchFrontOfWindowQueue(current_target, &window_ops);
94 } else if (window_ops.size() > 1 && window_ops.back().type == TYPE_OVER) {
95 // If we have a queued DragOver which isn't in progress, then just
96 // modify it's data.
97 auto& back = window_ops.back();
98 back.key_state = key_state;
99 back.position = position;
100 } else {
101 // In all other cases, queue.
102 window_ops.push_back({TYPE_OVER, key_state, position});
103 }
104 } else if (current_target != current_target_window_) {
105 if (current_target_window_) {
106 // TODO(erg): There's probably more clever eliding that we can do by
107 // pulling off DragOver events?
108 auto& window_ops = current_window_state_[current_target_window_];
109 window_ops.push_back({TYPE_LEAVE, key_state, position});
110 if (window_ops.size() == 1)
111 DispatchFrontOfWindowQueue(current_target_window_, &window_ops);
112 }
113
114 if (current_target) {
115 auto& window_ops = current_window_state_[current_target];
116 window_ops.push_back({TYPE_ENTER, key_state, position});
117 if (window_ops.size() == 1)
118 DispatchFrontOfWindowQueue(current_target, &window_ops);
119 }
120
121 current_target_window_ = current_target;
122 }
123 }
124
125 void CurrentDragOperation::MessageDragCompleted(bool success) {
126 // Message our original caller that this drag is completed.
127 source_window_tree_->OnChangeCompleted(change_id_, success);
128
129 // Deletes the CurrentDragOperation.
130 delegate_->OnDragOver(false);
131 }
132
133 void CurrentDragOperation::DispatchFrontOfWindowQueue(
134 ServerWindow* target,
135 std::deque<Operation>* queue) {
136 WindowTree* tree = window_server_->GetTreeWithRoot(target);
137
138 DCHECK(!queue->empty());
139 const Operation& op = queue->front();
140 switch (op.type) {
141 case TYPE_ENTER: {
142 tree->PerformOnDragEnter(
143 target, mime_data_.Clone(), op.key_state, op.position,
144 drag_operations_,
145 base::Bind(&CurrentDragOperation::OnDragStatusCompleted,
146 weak_factory_.GetWeakPtr(), target->id()));
147 break;
148 }
149 case TYPE_OVER: {
150 tree->PerformOnDragOver(
151 target, op.key_state, op.position, drag_operations_,
152 base::Bind(&CurrentDragOperation::OnDragStatusCompleted,
153 weak_factory_.GetWeakPtr(), target->id()));
154 break;
155 }
156 case TYPE_LEAVE: {
157 tree->PerformOnDragLeave(target);
158 queue->pop_front();
159 if (!queue->empty())
160 DispatchFrontOfWindowQueue(target, queue);
161 break;
162 }
163 case TYPE_DROP: {
164 tree->PerformOnDragDrop(
165 target, op.key_state, op.position, drag_operations_,
166 base::Bind(&CurrentDragOperation::OnDragDropCompleted,
167 weak_factory_.GetWeakPtr(), target->id()));
168 break;
169 }
170 }
171 }
172
173 void CurrentDragOperation::OnWindowDestroying(ServerWindow* window) {
174 current_window_state_.erase(window);
175
176 if (current_target_window_ == window)
177 current_target_window_ = nullptr;
178 }
179
180 void CurrentDragOperation::OnDragStatusCompleted(const WindowId& id,
181 uint32_t bitmask) {
182 ServerWindow* window = window_server_->GetWindow(id);
183 DCHECK(window);
184
185 // We must remove the completed item.
186 auto& window_ops = current_window_state_[window];
187 DCHECK(!window_ops.empty());
188 window_ops.pop_front();
189
190 if (!window_ops.empty()) {
191 // There are queued events here. We should dispatch them.
192 DispatchFrontOfWindowQueue(window, &window_ops);
193 }
194
195 // TODO(erg): |bitmask| is the allowed drag actions at the mouse location. We
196 // should use this data to change the cursor.
197 }
198
199 void CurrentDragOperation::OnDragDropCompleted(const WindowId& id,
200 uint32_t bitmask) {
201 ServerWindow* window = window_server_->GetWindow(id);
202 DCHECK(window);
203
204 // We must remove the completed item.
205 auto& window_ops = current_window_state_[window];
206 DCHECK(!window_ops.empty());
207 DCHECK_EQ(TYPE_DROP, window_ops.front().type);
208 window_ops.pop_front();
209 DCHECK(window_ops.empty());
210
211 MessageDragCompleted(bitmask != 0u);
212 }
213
214 } // namespace ws
215 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698