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

Side by Side Diff: ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc

Issue 2372403002: Drag and drop improvements on X11. (Closed)
Patch Set: Documented specs, minor refactorings, fixed 2 bugs. Created 4 years, 2 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" 5 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h"
6 6
7 #include <X11/Xatom.h> 7 #include <X11/Xatom.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 20 matching lines...) Expand all
31 #include "ui/events/platform/platform_event_source.h" 31 #include "ui/events/platform/platform_event_source.h"
32 #include "ui/gfx/image/image_skia.h" 32 #include "ui/gfx/image/image_skia.h"
33 #include "ui/views/controls/image_view.h" 33 #include "ui/views/controls/image_view.h"
34 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" 34 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
35 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" 35 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
36 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" 36 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
37 #include "ui/views/widget/widget.h" 37 #include "ui/views/widget/widget.h"
38 #include "ui/wm/public/drag_drop_client.h" 38 #include "ui/wm/public/drag_drop_client.h"
39 #include "ui/wm/public/drag_drop_delegate.h" 39 #include "ui/wm/public/drag_drop_delegate.h"
40 40
41 // Reading recommended for understanding the implementation in this file:
42 //
43 // * The X Window System Concepts section in The X New Developer’s Guide
44 // * The X Selection Mechanism paper by Keith Packard
45 // * The Peer-to-Peer Communication by Means of Selections section in the
46 // ICCCM (X Consortium's Inter-Client Communication Conventions Manual)
47 // * The XDND specification, Drag-and-Drop Protocol for the X Window System
48 // * The XDS specification, The Direct Save Protocol for the X Window System
49 //
50 // All the readings are freely available online.
51
41 using aura::client::DragDropDelegate; 52 using aura::client::DragDropDelegate;
42 using ui::OSExchangeData; 53 using ui::OSExchangeData;
43 54
44 namespace { 55 namespace {
45 56
46 const int kMinXdndVersion = 5; 57 // The lowest XDND protocol version that we understand.
58 //
59 // The XDND protocol specification says that we must support all versions
60 // between 3 and the version we advertise in the XDndAware property.
61 constexpr int kMinXdndVersion = 3;
Elliot Glaysher 2016/09/30 20:30:49 nit: blank line between this code and the next com
pwnall 2016/09/30 20:58:14 Done.
62 // The value used in the XdndAware property.
63 //
64 // The XDND protocol version used between two windows will be the minimum
65 // between the two versions advertised in the XDndAware property.
66 constexpr int kMaxXdndVersion = 5;
47 67
48 const int kWillAcceptDrop = 1; 68 constexpr int kWillAcceptDrop = 1;
49 const int kWantFurtherPosEvents = 2; 69 constexpr int kWantFurtherPosEvents = 2;
50 70
71 // These actions have the same meaning as in the W3C Drag and Drop spec.
51 const char kXdndActionCopy[] = "XdndActionCopy"; 72 const char kXdndActionCopy[] = "XdndActionCopy";
52 const char kXdndActionMove[] = "XdndActionMove"; 73 const char kXdndActionMove[] = "XdndActionMove";
53 const char kXdndActionLink[] = "XdndActionLink"; 74 const char kXdndActionLink[] = "XdndActionLink";
75 // "The target will do something that the source would not understand." The
76 // source only needs to provide a copy of the dragged data.
77 const char kXdndActionPrivate[] = "XdndActionPrivate";
78 // The target should ask the user what action it wants to perform. Intended to
79 // match Windows' right-click drag and drop, which shows a dropdown.
80 const char kXdndActionAsk[] = "XdndActionAsk";
81 // Triggers the XDS protocol.
54 const char kXdndActionDirectSave[] = "XdndActionDirectSave"; 82 const char kXdndActionDirectSave[] = "XdndActionDirectSave";
55 83
84 // Window property that will receive the drag and drop selection data.
56 const char kChromiumDragReciever[] = "_CHROMIUM_DRAG_RECEIVER"; 85 const char kChromiumDragReciever[] = "_CHROMIUM_DRAG_RECEIVER";
86 // Window property that contains the possible actions that will be presented to
87 // the user when the drag and drop action is kXdndActionAsk.
88 const char kXdndActionList[] = "XdndActionList";
89 // Window property that tells other applications the window understands XDND.
90 const char kXdndAware[] = "XdndAware";
91 // Window property on the source window and message used by the XDS protocol.
92 // This atom name intentionally includes the XDS protocol version (0).
93 // After the source sends the XdndDrop message, this property stores the
94 // (path-less) name of the file to be saved, and has the type text/plain, with
95 // an optional charset attribute.
96 // When receiving an XdndDrop event, the target needs to check for the
97 // XdndDirectSave property on the source window. The target then modifies the
98 // XdndDirectSave on the source window, and sends an XdndDirectSave message to
99 // the source.
100 // After the target sends the XdndDirectSave message, this property stores an
101 // URL indicating the location where the source should save the file.
102 const char kXdndDirectSave0[] = "XdndDirectSave0";
103 // Window property pointing to a proxy window to receive XDND target messages.
104 // The XDND source must check the proxy window must for the XdndAware property,
105 // and must send all XDND messages to the proxy instead of the target. However,
106 // the target field in the messages must still represent the original target
107 // window (the window pointed to by the cursor).
108 const char kXdndProxy[] = "XdndProxy";
109 // Window property that holds the supported drag and drop data types.
110 // This property is set on the XDND source window when the drag and drop data
111 // can be converted to more than 3 types.
112 const char kXdndTypeList[] = "XdndTypeList";
113
114 // Selection used by the XDND protocol to transfer data between applications.
57 const char kXdndSelection[] = "XdndSelection"; 115 const char kXdndSelection[] = "XdndSelection";
58 const char kXdndDirectSave0[] = "XdndDirectSave0"; 116
117 // Message sent from an XDND source to the target when the user confirms the
118 // drag and drop operation.
119 const char kXdndDrop[] = "XdndDrop";
120 // Message sent from an XDND source to the target to start the XDND protocol.
121 // The target must wait for an XDndPosition event before querying the data.
122 const char kXdndEnter[] = "XdndEnter";
123 // Message sent from an XDND target to the source in respose to an XdndDrop.
124 // The message must be sent whether the target acceepts the drop or not.
125 const char kXdndFinished[] = "XdndFinished";
126 // Message sent from an XDND source to the target when the user cancels the drag
127 // and drop operation.
128 const char kXdndLeave[] = "XdndLeave";
129 // Message sent by the XDND source when the cursor position changes.
130 // The source will also send an XdndPosition event right after the XdndEnter
131 // event, to tell the target about the initial cursor position and the desired
132 // drop action.
133 // The time stamp in the XdndPosition must be used when requesting selection
134 // information.
135 // After the target optionally acquires selection information, it must tell the
136 // source if it can accept the drop via an XdndStatus message.
137 const char kXdndPosition[] = "XdndPosition";
138 // Message sent by the XDND target in response to an XdndPosition message.
139 // The message informs the source if the target will accept the drop, and what
140 // action will be taken if the drop is accepted.
141 const char kXdndStatus[] = "XdndStatus";
59 142
60 const char* kAtomsToCache[] = { 143 const char* kAtomsToCache[] = {
61 kChromiumDragReciever, 144 kChromiumDragReciever,
62 "XdndActionAsk", 145 kXdndActionAsk,
63 kXdndActionCopy, 146 kXdndActionCopy,
64 kXdndActionDirectSave, 147 kXdndActionDirectSave,
65 kXdndActionLink, 148 kXdndActionLink,
66 "XdndActionList", 149 kXdndActionList,
67 kXdndActionMove, 150 kXdndActionMove,
68 "XdndActionPrivate", 151 kXdndActionPrivate,
69 "XdndAware", 152 kXdndAware,
70 kXdndDirectSave0, 153 kXdndDirectSave0,
71 "XdndDrop", 154 kXdndDrop,
72 "XdndEnter", 155 kXdndEnter,
73 "XdndFinished", 156 kXdndFinished,
74 "XdndLeave", 157 kXdndLeave,
75 "XdndPosition", 158 kXdndPosition,
76 "XdndProxy", // Proxy windows? 159 kXdndProxy,
77 kXdndSelection, 160 kXdndSelection,
78 "XdndStatus", 161 kXdndStatus,
79 "XdndTypeList", 162 kXdndTypeList,
80 ui::Clipboard::kMimeTypeText, 163 ui::Clipboard::kMimeTypeText,
81 NULL 164 NULL
82 }; 165 };
83 166
84 int XGetModifiers() { 167 int XGetModifiers() {
85 XDisplay* display = gfx::GetXDisplay(); 168 XDisplay* display = gfx::GetXDisplay();
86 169
87 XID root, child; 170 XID root, child;
88 int root_x, root_y, win_x, win_y; 171 int root_x, root_y, win_x, win_y;
89 unsigned int mask; 172 unsigned int mask;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 const int kRepeatMouseMoveTimeoutMs = 350; 207 const int kRepeatMouseMoveTimeoutMs = 350;
125 208
126 // The minimum alpha before we declare a pixel transparent when searching in 209 // The minimum alpha before we declare a pixel transparent when searching in
127 // our source image. 210 // our source image.
128 const uint32_t kMinAlpha = 32; 211 const uint32_t kMinAlpha = 32;
129 212
130 // |drag_widget_|'s opacity. 213 // |drag_widget_|'s opacity.
131 const float kDragWidgetOpacity = .75f; 214 const float kDragWidgetOpacity = .75f;
132 215
133 static base::LazyInstance< 216 static base::LazyInstance<
134 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky 217 std::map<::Window, views::DesktopDragDropClientAuraX11*> >::Leaky
135 g_live_client_map = LAZY_INSTANCE_INITIALIZER; 218 g_live_client_map = LAZY_INSTANCE_INITIALIZER;
136 219
137 } // namespace 220 } // namespace
138 221
139 namespace views { 222 namespace views {
140 223
141 DesktopDragDropClientAuraX11* 224 DesktopDragDropClientAuraX11*
142 DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL; 225 DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL;
143 226
144 class DesktopDragDropClientAuraX11::X11DragContext 227 class DesktopDragDropClientAuraX11::X11DragContext
145 : public ui::PlatformEventDispatcher { 228 : public ui::PlatformEventDispatcher {
146 public: 229 public:
147 X11DragContext(ui::X11AtomCache* atom_cache, 230 X11DragContext(ui::X11AtomCache* atom_cache,
148 ::Window local_window, 231 ::Window local_window,
149 const XClientMessageEvent& event); 232 const XClientMessageEvent& event);
150 ~X11DragContext() override; 233 ~X11DragContext() override;
151 234
152 // When we receive an XdndPosition message, we need to have all the data 235 // When we receive an XdndPosition message, we need to have all the data
153 // copied from the other window before we process the XdndPosition 236 // copied from the other window before we process the XdndPosition
154 // message. If we have that data already, dispatch immediately. Otherwise, 237 // message. If we have that data already, dispatch immediately. Otherwise,
155 // delay dispatching until we do. 238 // delay dispatching until we do.
156 void OnStartXdndPositionMessage(DesktopDragDropClientAuraX11* client, 239 void OnXdndPositionMessage(DesktopDragDropClientAuraX11* client,
157 ::Atom suggested_action, 240 ::Atom suggested_action,
158 ::Window source_window, 241 ::Window source_window,
242 ::Time time_stamp,
159 const gfx::Point& screen_point); 243 const gfx::Point& screen_point);
160 244
161 // Called to request the next target from the source window. This is only
162 // done on the first XdndPosition; after that, we cache the data offered by
163 // the source window.
164 void RequestNextTarget();
165
166 // Called when XSelection data has been copied to our process. 245 // Called when XSelection data has been copied to our process.
167 void OnSelectionNotify(const XSelectionEvent& xselection); 246 void OnSelectionNotify(const XSelectionEvent& xselection);
168 247
169 // Clones the fetched targets. 248 // Clones the fetched targets.
170 const ui::SelectionFormatMap& fetched_targets() { return fetched_targets_; } 249 const ui::SelectionFormatMap& fetched_targets() { return fetched_targets_; }
171 250
172 // Reads the "XdndActionList" property from |source_window| and copies it 251 // Reads the kXdndActionList property from |source_window| and copies it
173 // into |actions|. 252 // into |actions|.
174 void ReadActions(); 253 void ReadActions();
175 254
176 // Creates a ui::DragDropTypes::DragOperation representation of the current 255 // Creates a ui::DragDropTypes::DragOperation representation of the current
177 // action list. 256 // action list.
178 int GetDragOperation() const; 257 int GetDragOperation() const;
179 258
180 DesktopDragDropClientAuraX11* source_client() { return source_client_; } 259 DesktopDragDropClientAuraX11* source_client() { return source_client_; }
181 260
182 private: 261 private:
262 // Called to request the next target from the source window. This is only
263 // done on the first XdndPosition; after that, we cache the data offered by
264 // the source window.
265 void RequestNextTarget();
266
183 // Masks the X11 atom |xdnd_operation|'s views representation onto 267 // Masks the X11 atom |xdnd_operation|'s views representation onto
184 // |drag_operation|. 268 // |drag_operation|.
185 void MaskOperation(::Atom xdnd_operation, int* drag_operation) const; 269 void MaskOperation(::Atom xdnd_operation, int* drag_operation) const;
186 270
187 // ui::PlatformEventDispatcher: 271 // ui::PlatformEventDispatcher:
188 bool CanDispatchEvent(const ui::PlatformEvent& event) override; 272 bool CanDispatchEvent(const ui::PlatformEvent& event) override;
189 uint32_t DispatchEvent(const ui::PlatformEvent& event) override; 273 uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
190 274
191 // The atom cache owned by our parent. 275 // The atom cache owned by our parent.
192 ui::X11AtomCache* atom_cache_; 276 ui::X11AtomCache* atom_cache_;
(...skipping 14 matching lines...) Expand all
207 // The client we inform once we're done with requesting data. 291 // The client we inform once we're done with requesting data.
208 DesktopDragDropClientAuraX11* drag_drop_client_; 292 DesktopDragDropClientAuraX11* drag_drop_client_;
209 293
210 // Whether we're blocking the handling of an XdndPosition message by waiting 294 // Whether we're blocking the handling of an XdndPosition message by waiting
211 // for |unfetched_targets_| to be fetched. 295 // for |unfetched_targets_| to be fetched.
212 bool waiting_to_handle_position_; 296 bool waiting_to_handle_position_;
213 297
214 // Where the cursor is on screen. 298 // Where the cursor is on screen.
215 gfx::Point screen_point_; 299 gfx::Point screen_point_;
216 300
301 // The time stamp of the last XdndPosition event we received. The XDND
302 // specification mandates that we use this time stamp when querying the source
303 // about the drag and drop data.
304 ::Time position_time_stamp_;
305
217 // A SelectionFormatMap of data that we have in our process. 306 // A SelectionFormatMap of data that we have in our process.
218 ui::SelectionFormatMap fetched_targets_; 307 ui::SelectionFormatMap fetched_targets_;
219 308
220 // The names of various data types offered by the other window that we 309 // The names of various data types offered by the other window that we
221 // haven't fetched and put in |fetched_targets_| yet. 310 // haven't fetched and put in |fetched_targets_| yet.
222 std::vector<Atom> unfetched_targets_; 311 std::vector<::Atom> unfetched_targets_;
223 312
224 // XdndPosition messages have a suggested action. Qt applications exclusively 313 // XdndPosition messages have a suggested action. Qt applications exclusively
225 // use this, instead of the XdndActionList which is backed by |actions_|. 314 // use this, instead of the XdndActionList which is backed by |actions_|.
226 Atom suggested_action_; 315 ::Atom suggested_action_;
227 316
228 // Possible actions. 317 // Possible actions.
229 std::vector<Atom> actions_; 318 std::vector<::Atom> actions_;
230 319
231 DISALLOW_COPY_AND_ASSIGN(X11DragContext); 320 DISALLOW_COPY_AND_ASSIGN(X11DragContext);
232 }; 321 };
233 322
234 DesktopDragDropClientAuraX11::X11DragContext::X11DragContext( 323 DesktopDragDropClientAuraX11::X11DragContext::X11DragContext(
235 ui::X11AtomCache* atom_cache, 324 ui::X11AtomCache* atom_cache,
236 ::Window local_window, 325 ::Window local_window,
237 const XClientMessageEvent& event) 326 const XClientMessageEvent& event)
238 : atom_cache_(atom_cache), 327 : atom_cache_(atom_cache),
239 local_window_(local_window), 328 local_window_(local_window),
240 source_window_(event.data.l[0]), 329 source_window_(event.data.l[0]),
241 source_client_( 330 source_client_(
242 DesktopDragDropClientAuraX11::GetForWindow(source_window_)), 331 DesktopDragDropClientAuraX11::GetForWindow(source_window_)),
243 drag_drop_client_(NULL), 332 drag_drop_client_(NULL),
244 waiting_to_handle_position_(false), 333 waiting_to_handle_position_(false),
245 suggested_action_(None) { 334 suggested_action_(None) {
246 if (!source_client_) { 335 if (!source_client_) {
247 bool get_types = ((event.data.l[1] & 1) != 0); 336 bool get_types_from_property = ((event.data.l[1] & 1) != 0);
248 337
249 if (get_types) { 338 if (get_types_from_property) {
250 if (!ui::GetAtomArrayProperty(source_window_, 339 if (!ui::GetAtomArrayProperty(source_window_,
251 "XdndTypeList", 340 kXdndTypeList,
252 &unfetched_targets_)) { 341 &unfetched_targets_)) {
253 return; 342 return;
254 } 343 }
255 } else { 344 } else {
256 // data.l[2,3,4] contain the first three types. Unused slots can be None. 345 // data.l[2,3,4] contain the first three types. Unused slots can be None.
257 for (int i = 0; i < 3; ++i) { 346 for (int i = 0; i < 3; ++i) {
258 if (event.data.l[2+i] != None) { 347 if (event.data.l[2 + i] != None) {
259 unfetched_targets_.push_back(event.data.l[2+i]); 348 unfetched_targets_.push_back(event.data.l[2 + i]);
260 } 349 }
261 } 350 }
262 } 351 }
263 352
353 #if DCHECK_IS_ON()
354 DVLOG(1) << "XdndEnter has " << unfetched_targets_.size() << " data types";
355 for (::Atom target : unfetched_targets_) {
356 DVLOG(1) << "XdndEnter data type: " << target;
357 }
358 #endif // DCHECK_IS_ON()
359
264 // The window doesn't have a DesktopDragDropClientAuraX11, that means it's 360 // The window doesn't have a DesktopDragDropClientAuraX11, that means it's
265 // created by some other process. Listen for messages on it. 361 // created by some other process. Listen for messages on it.
266 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); 362 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
267 source_window_events_.reset( 363 source_window_events_.reset(
268 new ui::XScopedEventSelector(source_window_, PropertyChangeMask)); 364 new ui::XScopedEventSelector(source_window_, PropertyChangeMask));
269 365
270 // We must perform a full sync here because we could be racing 366 // We must perform a full sync here because we could be racing
271 // |source_window_|. 367 // |source_window_|.
272 XSync(gfx::GetXDisplay(), False); 368 XSync(gfx::GetXDisplay(), False);
273 } else { 369 } else {
274 // This drag originates from an aura window within our process. This means 370 // This drag originates from an aura window within our process. This means
275 // that we can shortcut the X11 server and ask the owning SelectionOwner 371 // that we can shortcut the X11 server and ask the owning SelectionOwner
276 // for the data it's offering. 372 // for the data it's offering.
277 fetched_targets_ = source_client_->GetFormatMap(); 373 fetched_targets_ = source_client_->GetFormatMap();
278 } 374 }
279 375
280 ReadActions(); 376 ReadActions();
281 } 377 }
282 378
283 DesktopDragDropClientAuraX11::X11DragContext::~X11DragContext() { 379 DesktopDragDropClientAuraX11::X11DragContext::~X11DragContext() {
284 if (!source_client_) { 380 if (!source_client_) {
285 // Unsubscribe from message events. 381 // Unsubscribe from message events.
286 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); 382 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
287 } 383 }
288 } 384 }
289 385
290 void DesktopDragDropClientAuraX11::X11DragContext::OnStartXdndPositionMessage( 386 void DesktopDragDropClientAuraX11::X11DragContext::OnXdndPositionMessage(
291 DesktopDragDropClientAuraX11* client, 387 DesktopDragDropClientAuraX11* client,
292 ::Atom suggested_action, 388 ::Atom suggested_action,
293 ::Window source_window, 389 ::Window source_window,
390 ::Time time_stamp,
294 const gfx::Point& screen_point) { 391 const gfx::Point& screen_point) {
295 DCHECK_EQ(source_window_, source_window); 392 DCHECK_EQ(source_window_, source_window);
296 suggested_action_ = suggested_action; 393 suggested_action_ = suggested_action;
297 394
298 if (!unfetched_targets_.empty()) { 395 if (!unfetched_targets_.empty()) {
299 // We have unfetched targets. That means we need to pause the handling of 396 // We have unfetched targets. That means we need to pause the handling of
300 // the position message and ask the other window for its data. 397 // the position message and ask the other window for its data.
301 screen_point_ = screen_point; 398 screen_point_ = screen_point;
302 drag_drop_client_ = client; 399 drag_drop_client_ = client;
400 position_time_stamp_ = time_stamp;
303 waiting_to_handle_position_ = true; 401 waiting_to_handle_position_ = true;
304 402
305 fetched_targets_ = ui::SelectionFormatMap(); 403 fetched_targets_ = ui::SelectionFormatMap();
306 RequestNextTarget(); 404 RequestNextTarget();
307 } else { 405 } else {
308 client->CompleteXdndPosition(source_window, screen_point); 406 client->CompleteXdndPosition(source_window, screen_point);
309 } 407 }
310 } 408 }
311 409
312 void DesktopDragDropClientAuraX11::X11DragContext::RequestNextTarget() { 410 void DesktopDragDropClientAuraX11::X11DragContext::RequestNextTarget() {
411 DCHECK(!unfetched_targets_.empty());
412 DCHECK(drag_drop_client_);
413 DCHECK(waiting_to_handle_position_);
414
313 ::Atom target = unfetched_targets_.back(); 415 ::Atom target = unfetched_targets_.back();
314 unfetched_targets_.pop_back(); 416 unfetched_targets_.pop_back();
315 417
316 XConvertSelection(gfx::GetXDisplay(), 418 XConvertSelection(gfx::GetXDisplay(),
317 atom_cache_->GetAtom(kXdndSelection), 419 atom_cache_->GetAtom(kXdndSelection),
318 target, 420 target,
319 atom_cache_->GetAtom(kChromiumDragReciever), 421 atom_cache_->GetAtom(kChromiumDragReciever),
320 local_window_, 422 local_window_,
321 CurrentTime); 423 position_time_stamp_);
322 } 424 }
323 425
324 void DesktopDragDropClientAuraX11::X11DragContext::OnSelectionNotify( 426 void DesktopDragDropClientAuraX11::X11DragContext::OnSelectionNotify(
325 const XSelectionEvent& event) { 427 const XSelectionEvent& event) {
326 if (!waiting_to_handle_position_) { 428 if (!waiting_to_handle_position_) {
327 // A misbehaved window may send SelectionNotify without us requesting data 429 // A misbehaved window may send SelectionNotify without us requesting data
328 // via XConvertSelection(). 430 // via XConvertSelection().
329 return; 431 return;
330 } 432 }
331 DCHECK(drag_drop_client_); 433 DCHECK(drag_drop_client_);
332 DCHECK_EQ(event.property, atom_cache_->GetAtom(kChromiumDragReciever));
333 434
334 scoped_refptr<base::RefCountedMemory> data; 435 DVLOG(1) << "SelectionNotify, format " << event.target;
335 ::Atom type = None; 436
336 if (ui::GetRawBytesOfProperty(local_window_, event.property, 437 if (event.property != None) {
337 &data, NULL, &type)) { 438 DCHECK_EQ(event.property, atom_cache_->GetAtom(kChromiumDragReciever));
338 fetched_targets_.Insert(event.target, data); 439
440 scoped_refptr<base::RefCountedMemory> data;
441 ::Atom type = None;
442 if (ui::GetRawBytesOfProperty(local_window_, event.property,
443 &data, NULL, &type)) {
444 fetched_targets_.Insert(event.target, data);
445 }
446 } else {
447 // The source failed to convert the drop data to the format (target in X11
448 // parlance) that we asked for. This happens, even though we only ask for
449 // the formats advertised by the source. http://crbug.com/628099
450 LOG(ERROR) << "XConvertSelection failed for source-advertised target "
451 << event.target;
339 } 452 }
340 453
341 if (!unfetched_targets_.empty()) { 454 if (!unfetched_targets_.empty()) {
342 RequestNextTarget(); 455 RequestNextTarget();
343 } else { 456 } else {
344 waiting_to_handle_position_ = false; 457 waiting_to_handle_position_ = false;
345 drag_drop_client_->CompleteXdndPosition(source_window_, screen_point_); 458 drag_drop_client_->CompleteXdndPosition(source_window_, screen_point_);
346 drag_drop_client_ = NULL; 459 drag_drop_client_ = NULL;
347 } 460 }
348 } 461 }
349 462
350 void DesktopDragDropClientAuraX11::X11DragContext::ReadActions() { 463 void DesktopDragDropClientAuraX11::X11DragContext::ReadActions() {
351 if (!source_client_) { 464 if (!source_client_) {
352 std::vector<Atom> atom_array; 465 std::vector<::Atom> atom_array;
353 if (!ui::GetAtomArrayProperty(source_window_, 466 if (!ui::GetAtomArrayProperty(source_window_,
354 "XdndActionList", 467 kXdndActionList,
355 &atom_array)) { 468 &atom_array)) {
356 actions_.clear(); 469 actions_.clear();
357 } else { 470 } else {
358 actions_.swap(atom_array); 471 actions_.swap(atom_array);
359 } 472 }
360 } else { 473 } else {
361 // We have a property notify set up for other windows in case they change 474 // We have a property notify set up for other windows in case they change
362 // their action list. Thankfully, the views interface is static and you 475 // their action list. Thankfully, the views interface is static and you
363 // can't change the action list after you enter StartDragAndDrop(). 476 // can't change the action list after you enter StartDragAndDrop().
364 actions_ = source_client_->GetOfferedDragOperations(); 477 actions_ = source_client_->GetOfferedDragOperations();
365 } 478 }
366 } 479 }
367 480
368 int DesktopDragDropClientAuraX11::X11DragContext::GetDragOperation() const { 481 int DesktopDragDropClientAuraX11::X11DragContext::GetDragOperation() const {
369 int drag_operation = ui::DragDropTypes::DRAG_NONE; 482 int drag_operation = ui::DragDropTypes::DRAG_NONE;
370 for (std::vector<Atom>::const_iterator it = actions_.begin(); 483 for (std::vector<::Atom>::const_iterator it = actions_.begin();
371 it != actions_.end(); ++it) { 484 it != actions_.end(); ++it) {
372 MaskOperation(*it, &drag_operation); 485 MaskOperation(*it, &drag_operation);
373 } 486 }
374 487
375 MaskOperation(suggested_action_, &drag_operation); 488 MaskOperation(suggested_action_, &drag_operation);
376 489
377 return drag_operation; 490 return drag_operation;
378 } 491 }
379 492
380 void DesktopDragDropClientAuraX11::X11DragContext::MaskOperation( 493 void DesktopDragDropClientAuraX11::X11DragContext::MaskOperation(
381 ::Atom xdnd_operation, 494 ::Atom xdnd_operation,
382 int* drag_operation) const { 495 int* drag_operation) const {
383 if (xdnd_operation == atom_cache_->GetAtom(kXdndActionCopy)) 496 if (xdnd_operation == atom_cache_->GetAtom(kXdndActionCopy))
384 *drag_operation |= ui::DragDropTypes::DRAG_COPY; 497 *drag_operation |= ui::DragDropTypes::DRAG_COPY;
385 else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionMove)) 498 else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionMove))
386 *drag_operation |= ui::DragDropTypes::DRAG_MOVE; 499 *drag_operation |= ui::DragDropTypes::DRAG_MOVE;
387 else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionLink)) 500 else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionLink))
388 *drag_operation |= ui::DragDropTypes::DRAG_LINK; 501 *drag_operation |= ui::DragDropTypes::DRAG_LINK;
389 } 502 }
390 503
391 bool DesktopDragDropClientAuraX11::X11DragContext::CanDispatchEvent( 504 bool DesktopDragDropClientAuraX11::X11DragContext::CanDispatchEvent(
392 const ui::PlatformEvent& event) { 505 const ui::PlatformEvent& event) {
393 return event->xany.window == source_window_; 506 return event->xany.window == source_window_;
394 } 507 }
395 508
396 uint32_t DesktopDragDropClientAuraX11::X11DragContext::DispatchEvent( 509 uint32_t DesktopDragDropClientAuraX11::X11DragContext::DispatchEvent(
397 const ui::PlatformEvent& event) { 510 const ui::PlatformEvent& event) {
398 if (event->type == PropertyNotify && 511 if (event->type == PropertyNotify &&
399 event->xproperty.atom == atom_cache_->GetAtom("XdndActionList")) { 512 event->xproperty.atom == atom_cache_->GetAtom(kXdndActionList)) {
400 ReadActions(); 513 ReadActions();
401 return ui::POST_DISPATCH_STOP_PROPAGATION; 514 return ui::POST_DISPATCH_STOP_PROPAGATION;
402 } 515 }
403 return ui::POST_DISPATCH_NONE; 516 return ui::POST_DISPATCH_NONE;
404 } 517 }
405 518
406 /////////////////////////////////////////////////////////////////////////////// 519 ///////////////////////////////////////////////////////////////////////////////
407 520
408 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11( 521 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11(
409 aura::Window* root_window, 522 aura::Window* root_window,
(...skipping 13 matching lines...) Expand all
423 source_current_window_(None), 536 source_current_window_(None),
424 source_state_(SOURCE_STATE_OTHER), 537 source_state_(SOURCE_STATE_OTHER),
425 drag_operation_(0), 538 drag_operation_(0),
426 negotiated_operation_(ui::DragDropTypes::DRAG_NONE), 539 negotiated_operation_(ui::DragDropTypes::DRAG_NONE),
427 weak_ptr_factory_(this) { 540 weak_ptr_factory_(this) {
428 // Some tests change the DesktopDragDropClientAuraX11 associated with an 541 // Some tests change the DesktopDragDropClientAuraX11 associated with an
429 // |xwindow|. 542 // |xwindow|.
430 g_live_client_map.Get()[xwindow] = this; 543 g_live_client_map.Get()[xwindow] = this;
431 544
432 // Mark that we are aware of drag and drop concepts. 545 // Mark that we are aware of drag and drop concepts.
433 unsigned long xdnd_version = kMinXdndVersion; 546 unsigned long xdnd_version = kMaxXdndVersion;
434 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"), 547 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndAware),
435 XA_ATOM, 32, PropModeReplace, 548 XA_ATOM, 32, PropModeReplace,
436 reinterpret_cast<unsigned char*>(&xdnd_version), 1); 549 reinterpret_cast<unsigned char*>(&xdnd_version), 1);
437 } 550 }
438 551
439 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() { 552 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() {
440 // This is necessary when the parent native widget gets destroyed while a drag 553 // This is necessary when the parent native widget gets destroyed while a drag
441 // operation is in progress. 554 // operation is in progress.
442 move_loop_->EndMoveLoop(); 555 move_loop_->EndMoveLoop();
443 NotifyDragLeave(); 556 NotifyDragLeave();
444 557
445 g_live_client_map.Get().erase(xwindow_); 558 g_live_client_map.Get().erase(xwindow_);
446 } 559 }
447 560
448 // static 561 // static
449 DesktopDragDropClientAuraX11* DesktopDragDropClientAuraX11::GetForWindow( 562 DesktopDragDropClientAuraX11* DesktopDragDropClientAuraX11::GetForWindow(
450 ::Window window) { 563 ::Window window) {
451 std::map< ::Window, DesktopDragDropClientAuraX11*>::const_iterator it = 564 std::map<::Window, DesktopDragDropClientAuraX11*>::const_iterator it =
452 g_live_client_map.Get().find(window); 565 g_live_client_map.Get().find(window);
453 if (it == g_live_client_map.Get().end()) 566 if (it == g_live_client_map.Get().end())
454 return NULL; 567 return NULL;
455 return it->second; 568 return it->second;
456 } 569 }
457 570
458 void DesktopDragDropClientAuraX11::Init() { 571 void DesktopDragDropClientAuraX11::Init() {
459 move_loop_ = CreateMoveLoop(this); 572 move_loop_ = CreateMoveLoop(this);
460 } 573 }
461 574
462 void DesktopDragDropClientAuraX11::OnXdndEnter( 575 void DesktopDragDropClientAuraX11::OnXdndEnter(
463 const XClientMessageEvent& event) { 576 const XClientMessageEvent& event) {
464 DVLOG(1) << "XdndEnter"; 577 int version = (event.data.l[1] & 0xff000000) >> 24;
578 DVLOG(1) << "OnXdndEnter, version " << version;
465 579
466 int version = (event.data.l[1] & 0xff000000) >> 24; 580 if (version < kMinXdndVersion) {
467 if (version < 3) { 581 // This protocol version is not documented in the XDND standard (last
468 LOG(ERROR) << "Received old XdndEnter message."; 582 // revised in 1999), so we don't support it. Since don't understand the
583 // protocol spoken by the source, we can't tell it that we can't talk to it.
584 LOG(ERROR) << "XdndEnter message discarded because its version is too old.";
585 return;
586 }
587 if (version > kMaxXdndVersion) {
588 // The XDND version used should be the minimum between the versions
589 // advertised by the source and the target. We advertise kMaxXdndVersion, so
590 // this should never happen when talking to an XDND-compliant application.
591 LOG(ERROR) << "XdndEnter message discarded because its version is too new.";
469 return; 592 return;
470 } 593 }
471 594
472 // Make sure that we've run ~X11DragContext() before creating another one. 595 // Make sure that we've run ~X11DragContext() before creating another one.
473 target_current_context_.reset(); 596 target_current_context_.reset();
474 target_current_context_.reset( 597 target_current_context_.reset(
475 new X11DragContext(&atom_cache_, xwindow_, event)); 598 new X11DragContext(&atom_cache_, xwindow_, event));
476 599
477 // In the Windows implementation, we immediately call DesktopDropTargetWin:: 600 // In the Windows implementation, we immediately call DesktopDropTargetWin::
478 // Translate(). Here, we wait until we receive an XdndPosition message 601 // Translate(). The XDND specification demands that we wait until we receive
479 // because the enter message doesn't convey any positioning 602 // an XdndPosition message before we use XConvertSelection or send an
480 // information. 603 // XdndStatus message.
481 } 604 }
482 605
483 void DesktopDragDropClientAuraX11::OnXdndLeave( 606 void DesktopDragDropClientAuraX11::OnXdndLeave(
484 const XClientMessageEvent& event) { 607 const XClientMessageEvent& event) {
485 DVLOG(1) << "XdndLeave"; 608 DVLOG(1) << "OnXdndLeave";
486 NotifyDragLeave(); 609 NotifyDragLeave();
487 target_current_context_.reset(); 610 target_current_context_.reset();
488 } 611 }
489 612
490 void DesktopDragDropClientAuraX11::OnXdndPosition( 613 void DesktopDragDropClientAuraX11::OnXdndPosition(
491 const XClientMessageEvent& event) { 614 const XClientMessageEvent& event) {
492 DVLOG(1) << "XdndPosition"; 615 DVLOG(1) << "OnXdndPosition";
493 616
494 unsigned long source_window = event.data.l[0]; 617 unsigned long source_window = event.data.l[0];
495 int x_root_window = event.data.l[2] >> 16; 618 int x_root_window = event.data.l[2] >> 16;
496 int y_root_window = event.data.l[2] & 0xffff; 619 int y_root_window = event.data.l[2] & 0xffff;
620 ::Time time_stamp = event.data.l[3];
497 ::Atom suggested_action = event.data.l[4]; 621 ::Atom suggested_action = event.data.l[4];
498 622
499 if (!target_current_context_.get()) { 623 if (!target_current_context_.get()) {
500 NOTREACHED(); 624 NOTREACHED();
501 return; 625 return;
502 } 626 }
503 627
504 // If we already have all the data from this drag, we complete it 628 target_current_context_->OnXdndPositionMessage(
505 // immediately. 629 this, suggested_action, source_window, time_stamp,
506 target_current_context_->OnStartXdndPositionMessage(
507 this, suggested_action, source_window,
508 gfx::Point(x_root_window, y_root_window)); 630 gfx::Point(x_root_window, y_root_window));
509 } 631 }
510 632
511 void DesktopDragDropClientAuraX11::OnXdndStatus( 633 void DesktopDragDropClientAuraX11::OnXdndStatus(
512 const XClientMessageEvent& event) { 634 const XClientMessageEvent& event) {
513 DVLOG(1) << "XdndStatus"; 635 DVLOG(1) << "OnXdndStatus";
514 636
515 unsigned long source_window = event.data.l[0]; 637 unsigned long source_window = event.data.l[0];
516 638
517 if (source_window != source_current_window_) 639 if (source_window != source_current_window_)
518 return; 640 return;
519 641
520 if (source_state_ != SOURCE_STATE_PENDING_DROP && 642 if (source_state_ != SOURCE_STATE_PENDING_DROP &&
521 source_state_ != SOURCE_STATE_OTHER) { 643 source_state_ != SOURCE_STATE_OTHER) {
522 return; 644 return;
523 } 645 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 gfx::Point p = next_position_message_->first; 691 gfx::Point p = next_position_message_->first;
570 unsigned long event_time = next_position_message_->second; 692 unsigned long event_time = next_position_message_->second;
571 next_position_message_.reset(); 693 next_position_message_.reset();
572 694
573 SendXdndPosition(source_window, p, event_time); 695 SendXdndPosition(source_window, p, event_time);
574 } 696 }
575 } 697 }
576 698
577 void DesktopDragDropClientAuraX11::OnXdndFinished( 699 void DesktopDragDropClientAuraX11::OnXdndFinished(
578 const XClientMessageEvent& event) { 700 const XClientMessageEvent& event) {
579 DVLOG(1) << "XdndFinished"; 701 DVLOG(1) << "OnXdndFinished";
580 unsigned long source_window = event.data.l[0]; 702 unsigned long source_window = event.data.l[0];
581 if (source_current_window_ != source_window) 703 if (source_current_window_ != source_window)
582 return; 704 return;
583 705
584 // Clear |negotiated_operation_| if the drag was rejected. 706 // Clear |negotiated_operation_| if the drag was rejected.
585 if ((event.data.l[1] & 1) == 0) 707 if ((event.data.l[1] & 1) == 0)
586 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE; 708 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
587 709
588 // Clear |source_current_window_| to avoid sending XdndLeave upon ending the 710 // Clear |source_current_window_| to avoid sending XdndLeave upon ending the
589 // move loop. 711 // move loop.
590 source_current_window_ = None; 712 source_current_window_ = None;
591 move_loop_->EndMoveLoop(); 713 move_loop_->EndMoveLoop();
592 } 714 }
593 715
594 void DesktopDragDropClientAuraX11::OnXdndDrop( 716 void DesktopDragDropClientAuraX11::OnXdndDrop(
595 const XClientMessageEvent& event) { 717 const XClientMessageEvent& event) {
596 DVLOG(1) << "XdndDrop"; 718 DVLOG(1) << "OnXdndDrop";
597 719
598 unsigned long source_window = event.data.l[0]; 720 unsigned long source_window = event.data.l[0];
599 721
600 int drag_operation = ui::DragDropTypes::DRAG_NONE; 722 int drag_operation = ui::DragDropTypes::DRAG_NONE;
601 if (target_window_) { 723 if (target_window_) {
602 aura::client::DragDropDelegate* delegate = 724 aura::client::DragDropDelegate* delegate =
603 aura::client::GetDragDropDelegate(target_window_); 725 aura::client::GetDragDropDelegate(target_window_);
604 if (delegate) { 726 if (delegate) {
605 ui::OSExchangeData data( 727 ui::OSExchangeData data(
606 base::MakeUnique<ui::OSExchangeDataProviderAuraX11>( 728 base::MakeUnique<ui::OSExchangeDataProviderAuraX11>(
(...skipping 16 matching lines...) Expand all
623 745
624 drag_operation = delegate->OnPerformDrop(event); 746 drag_operation = delegate->OnPerformDrop(event);
625 } 747 }
626 748
627 target_window_->RemoveObserver(this); 749 target_window_->RemoveObserver(this);
628 target_window_ = NULL; 750 target_window_ = NULL;
629 } 751 }
630 752
631 XEvent xev; 753 XEvent xev;
632 xev.xclient.type = ClientMessage; 754 xev.xclient.type = ClientMessage;
633 xev.xclient.message_type = atom_cache_.GetAtom("XdndFinished"); 755 xev.xclient.message_type = atom_cache_.GetAtom(kXdndFinished);
634 xev.xclient.format = 32; 756 xev.xclient.format = 32;
635 xev.xclient.window = source_window; 757 xev.xclient.window = source_window;
636 xev.xclient.data.l[0] = xwindow_; 758 xev.xclient.data.l[0] = xwindow_;
637 xev.xclient.data.l[1] = (drag_operation != 0) ? 1 : 0; 759 xev.xclient.data.l[1] = (drag_operation != 0) ? 1 : 0;
638 xev.xclient.data.l[2] = DragOperationToAtom(drag_operation); 760 xev.xclient.data.l[2] = DragOperationToAtom(drag_operation);
639 761
640 SendXClientEvent(source_window, &xev); 762 SendXClientEvent(source_window, &xev);
641 } 763 }
642 764
643 void DesktopDragDropClientAuraX11::OnSelectionNotify( 765 void DesktopDragDropClientAuraX11::OnSelectionNotify(
644 const XSelectionEvent& xselection) { 766 const XSelectionEvent& xselection) {
767 DVLOG(1) << "OnSelectionNotify";
645 if (target_current_context_) 768 if (target_current_context_)
646 target_current_context_->OnSelectionNotify(xselection); 769 target_current_context_->OnSelectionNotify(xselection);
647 770
648 // ICCCM requires us to delete the property passed into SelectionNotify. 771 // ICCCM requires us to delete the property passed into SelectionNotify.
649 if (xselection.property != None) 772 if (xselection.property != None)
650 XDeleteProperty(xdisplay_, xwindow_, xselection.property); 773 XDeleteProperty(xdisplay_, xwindow_, xselection.property);
651 } 774 }
652 775
653 int DesktopDragDropClientAuraX11::StartDragAndDrop( 776 int DesktopDragDropClientAuraX11::StartDragAndDrop(
654 const ui::OSExchangeData& data, 777 const ui::OSExchangeData& data,
(...skipping 14 matching lines...) Expand all
669 source_state_ = SOURCE_STATE_OTHER; 792 source_state_ = SOURCE_STATE_OTHER;
670 drag_operation_ = operation; 793 drag_operation_ = operation;
671 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE; 794 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
672 795
673 const ui::OSExchangeData::Provider* provider = &data.provider(); 796 const ui::OSExchangeData::Provider* provider = &data.provider();
674 source_provider_ = static_cast<const ui::OSExchangeDataProviderAuraX11*>( 797 source_provider_ = static_cast<const ui::OSExchangeDataProviderAuraX11*>(
675 provider); 798 provider);
676 799
677 source_provider_->TakeOwnershipOfSelection(); 800 source_provider_->TakeOwnershipOfSelection();
678 801
679 std::vector< ::Atom> actions = GetOfferedDragOperations(); 802 std::vector<::Atom> actions = GetOfferedDragOperations();
680 if (!source_provider_->file_contents_name().empty()) { 803 if (!source_provider_->file_contents_name().empty()) {
681 actions.push_back(atom_cache_.GetAtom(kXdndActionDirectSave)); 804 actions.push_back(atom_cache_.GetAtom(kXdndActionDirectSave));
682 ui::SetStringProperty( 805 ui::SetStringProperty(
683 xwindow_, 806 xwindow_,
684 atom_cache_.GetAtom(kXdndDirectSave0), 807 atom_cache_.GetAtom(kXdndDirectSave0),
685 atom_cache_.GetAtom(ui::Clipboard::kMimeTypeText), 808 atom_cache_.GetAtom(ui::Clipboard::kMimeTypeText),
686 source_provider_->file_contents_name().AsUTF8Unsafe()); 809 source_provider_->file_contents_name().AsUTF8Unsafe());
687 } 810 }
688 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions); 811 ui::SetAtomArrayProperty(xwindow_, kXdndActionList, "ATOM", actions);
689 812
690 gfx::ImageSkia drag_image = source_provider_->GetDragImage(); 813 gfx::ImageSkia drag_image = source_provider_->GetDragImage();
691 if (IsValidDragImage(drag_image)) { 814 if (IsValidDragImage(drag_image)) {
692 CreateDragWidget(drag_image); 815 CreateDragWidget(drag_image);
693 drag_widget_offset_ = source_provider_->GetDragImageOffset(); 816 drag_widget_offset_ = source_provider_->GetDragImageOffset();
694 } 817 }
695 818
696 // Chrome expects starting drag and drop to release capture. 819 // Chrome expects starting drag and drop to release capture.
697 aura::Window* capture_window = 820 aura::Window* capture_window =
698 aura::client::GetCaptureClient(root_window)->GetGlobalCaptureWindow(); 821 aura::client::GetCaptureClient(root_window)->GetGlobalCaptureWindow();
(...skipping 19 matching lines...) Expand all
718 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); 841 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT);
719 } else { 842 } else {
720 UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Drop", source, 843 UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Drop", source,
721 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); 844 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT);
722 } 845 }
723 drag_widget_.reset(); 846 drag_widget_.reset();
724 847
725 source_provider_ = NULL; 848 source_provider_ = NULL;
726 g_current_drag_drop_client = NULL; 849 g_current_drag_drop_client = NULL;
727 drag_operation_ = 0; 850 drag_operation_ = 0;
728 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList")); 851 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndActionList));
729 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0)); 852 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
730 853
731 return negotiated_operation_; 854 return negotiated_operation_;
732 } 855 }
733 UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Cancel", source, 856 UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Cancel", source,
734 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); 857 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT);
735 return ui::DragDropTypes::DRAG_NONE; 858 return ui::DragDropTypes::DRAG_NONE;
736 } 859 }
737 860
738 void DesktopDragDropClientAuraX11::DragUpdate(aura::Window* target, 861 void DesktopDragDropClientAuraX11::DragUpdate(aura::Window* target,
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 } 969 }
847 970
848 XID DesktopDragDropClientAuraX11::FindWindowFor( 971 XID DesktopDragDropClientAuraX11::FindWindowFor(
849 const gfx::Point& screen_point) { 972 const gfx::Point& screen_point) {
850 views::X11TopmostWindowFinder finder; 973 views::X11TopmostWindowFinder finder;
851 ::Window target = finder.FindWindowAt(screen_point); 974 ::Window target = finder.FindWindowAt(screen_point);
852 975
853 if (target == None) 976 if (target == None)
854 return None; 977 return None;
855 978
979 // TODO(crbug/651775): The proxy window should be reported separately from the
980 // target window. XDND messages should be sent to the proxy, and their
981 // window field should point to the target.
982
856 // Figure out which window we should test as XdndAware. If |target| has 983 // Figure out which window we should test as XdndAware. If |target| has
857 // XdndProxy, it will set that proxy on target, and if not, |target|'s 984 // XdndProxy, it will set that proxy on target, and if not, |target|'s
858 // original value will remain. 985 // original value will remain.
859 ui::GetXIDProperty(target, "XdndProxy", &target); 986 ui::GetXIDProperty(target, kXdndProxy, &target);
860 987
861 int version; 988 int version;
862 if (ui::GetIntProperty(target, "XdndAware", &version) && 989 if (ui::GetIntProperty(target, kXdndAware, &version) &&
863 version >= kMinXdndVersion) { 990 version >= kMaxXdndVersion) {
864 return target; 991 return target;
865 } 992 }
866 return None; 993 return None;
867 } 994 }
868 995
869 void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid, 996 void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid,
870 XEvent* xev) { 997 XEvent* xev) {
871 DCHECK_EQ(ClientMessage, xev->type); 998 DCHECK_EQ(ClientMessage, xev->type);
872 999
873 // Don't send messages to the X11 message queue if we can help it. 1000 // Don't send messages to the X11 message queue if we can help it.
874 DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid); 1001 DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid);
875 if (short_circuit) { 1002 if (short_circuit) {
876 Atom message_type = xev->xclient.message_type; 1003 Atom message_type = xev->xclient.message_type;
877 if (message_type == atom_cache_.GetAtom("XdndEnter")) { 1004 if (message_type == atom_cache_.GetAtom(kXdndEnter)) {
878 short_circuit->OnXdndEnter(xev->xclient); 1005 short_circuit->OnXdndEnter(xev->xclient);
879 return; 1006 return;
880 } else if (message_type == atom_cache_.GetAtom("XdndLeave")) { 1007 } else if (message_type == atom_cache_.GetAtom(kXdndLeave)) {
881 short_circuit->OnXdndLeave(xev->xclient); 1008 short_circuit->OnXdndLeave(xev->xclient);
882 return; 1009 return;
883 } else if (message_type == atom_cache_.GetAtom("XdndPosition")) { 1010 } else if (message_type == atom_cache_.GetAtom(kXdndPosition)) {
884 short_circuit->OnXdndPosition(xev->xclient); 1011 short_circuit->OnXdndPosition(xev->xclient);
885 return; 1012 return;
886 } else if (message_type == atom_cache_.GetAtom("XdndStatus")) { 1013 } else if (message_type == atom_cache_.GetAtom(kXdndStatus)) {
887 short_circuit->OnXdndStatus(xev->xclient); 1014 short_circuit->OnXdndStatus(xev->xclient);
888 return; 1015 return;
889 } else if (message_type == atom_cache_.GetAtom("XdndFinished")) { 1016 } else if (message_type == atom_cache_.GetAtom(kXdndFinished)) {
890 short_circuit->OnXdndFinished(xev->xclient); 1017 short_circuit->OnXdndFinished(xev->xclient);
891 return; 1018 return;
892 } else if (message_type == atom_cache_.GetAtom("XdndDrop")) { 1019 } else if (message_type == atom_cache_.GetAtom(kXdndDrop)) {
893 short_circuit->OnXdndDrop(xev->xclient); 1020 short_circuit->OnXdndDrop(xev->xclient);
894 return; 1021 return;
895 } 1022 }
896 } 1023 }
897 1024
898 // I don't understand why the GTK+ code is doing what it's doing here. It 1025 // I don't understand why the GTK+ code is doing what it's doing here. It
899 // goes out of its way to send the XEvent so that it receives a callback on 1026 // goes out of its way to send the XEvent so that it receives a callback on
900 // success or failure, and when it fails, it then sends an internal 1027 // success or failure, and when it fails, it then sends an internal
901 // GdkEvent about the failed drag. (And sending this message doesn't appear 1028 // GdkEvent about the failed drag. (And sending this message doesn't appear
902 // to go through normal xlib machinery, but instead passes through the low 1029 // to go through normal xlib machinery, but instead passes through the low
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 if (atom == atom_cache_.GetAtom(kXdndActionCopy)) 1168 if (atom == atom_cache_.GetAtom(kXdndActionCopy))
1042 return ui::DragDropTypes::DRAG_COPY; 1169 return ui::DragDropTypes::DRAG_COPY;
1043 if (atom == atom_cache_.GetAtom(kXdndActionMove)) 1170 if (atom == atom_cache_.GetAtom(kXdndActionMove))
1044 return ui::DragDropTypes::DRAG_MOVE; 1171 return ui::DragDropTypes::DRAG_MOVE;
1045 if (atom == atom_cache_.GetAtom(kXdndActionLink)) 1172 if (atom == atom_cache_.GetAtom(kXdndActionLink))
1046 return ui::DragDropTypes::DRAG_LINK; 1173 return ui::DragDropTypes::DRAG_LINK;
1047 1174
1048 return ui::DragDropTypes::DRAG_NONE; 1175 return ui::DragDropTypes::DRAG_NONE;
1049 } 1176 }
1050 1177
1051 std::vector< ::Atom> DesktopDragDropClientAuraX11::GetOfferedDragOperations() { 1178 std::vector<::Atom> DesktopDragDropClientAuraX11::GetOfferedDragOperations() {
1052 std::vector< ::Atom> operations; 1179 std::vector<::Atom> operations;
1053 if (drag_operation_ & ui::DragDropTypes::DRAG_COPY) 1180 if (drag_operation_ & ui::DragDropTypes::DRAG_COPY)
1054 operations.push_back(atom_cache_.GetAtom(kXdndActionCopy)); 1181 operations.push_back(atom_cache_.GetAtom(kXdndActionCopy));
1055 if (drag_operation_ & ui::DragDropTypes::DRAG_MOVE) 1182 if (drag_operation_ & ui::DragDropTypes::DRAG_MOVE)
1056 operations.push_back(atom_cache_.GetAtom(kXdndActionMove)); 1183 operations.push_back(atom_cache_.GetAtom(kXdndActionMove));
1057 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK) 1184 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK)
1058 operations.push_back(atom_cache_.GetAtom(kXdndActionLink)); 1185 operations.push_back(atom_cache_.GetAtom(kXdndActionLink));
1059 return operations; 1186 return operations;
1060 } 1187 }
1061 1188
1062 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const { 1189 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const {
(...skipping 13 matching lines...) Expand all
1076 drag_operation = delegate->OnDragUpdated(*drop_target_event); 1203 drag_operation = delegate->OnDragUpdated(*drop_target_event);
1077 1204
1078 // Sends an XdndStatus message back to the source_window. l[2,3] 1205 // Sends an XdndStatus message back to the source_window. l[2,3]
1079 // theoretically represent an area in the window where the current action is 1206 // theoretically represent an area in the window where the current action is
1080 // the same as what we're returning, but I can't find any implementation that 1207 // the same as what we're returning, but I can't find any implementation that
1081 // actually making use of this. A client can return (0, 0) and/or set the 1208 // actually making use of this. A client can return (0, 0) and/or set the
1082 // first bit of l[1] to disable the feature, and it appears that gtk neither 1209 // first bit of l[1] to disable the feature, and it appears that gtk neither
1083 // sets this nor respects it if set. 1210 // sets this nor respects it if set.
1084 XEvent xev; 1211 XEvent xev;
1085 xev.xclient.type = ClientMessage; 1212 xev.xclient.type = ClientMessage;
1086 xev.xclient.message_type = atom_cache_.GetAtom("XdndStatus"); 1213 xev.xclient.message_type = atom_cache_.GetAtom(kXdndStatus);
1087 xev.xclient.format = 32; 1214 xev.xclient.format = 32;
1088 xev.xclient.window = source_window; 1215 xev.xclient.window = source_window;
1089 xev.xclient.data.l[0] = xwindow_; 1216 xev.xclient.data.l[0] = xwindow_;
1090 xev.xclient.data.l[1] = (drag_operation != 0) ? 1217 xev.xclient.data.l[1] = (drag_operation != 0) ?
1091 (kWantFurtherPosEvents | kWillAcceptDrop) : 0; 1218 (kWantFurtherPosEvents | kWillAcceptDrop) : 0;
1092 xev.xclient.data.l[2] = 0; 1219 xev.xclient.data.l[2] = 0;
1093 xev.xclient.data.l[3] = 0; 1220 xev.xclient.data.l[3] = 0;
1094 xev.xclient.data.l[4] = DragOperationToAtom(drag_operation); 1221 xev.xclient.data.l[4] = DragOperationToAtom(drag_operation);
1095 1222
1096 SendXClientEvent(source_window, &xev); 1223 SendXClientEvent(source_window, &xev);
1097 } 1224 }
1098 1225
1099 void DesktopDragDropClientAuraX11::SendXdndEnter(::Window dest_window) { 1226 void DesktopDragDropClientAuraX11::SendXdndEnter(::Window dest_window) {
1100 XEvent xev; 1227 XEvent xev;
1101 xev.xclient.type = ClientMessage; 1228 xev.xclient.type = ClientMessage;
1102 xev.xclient.message_type = atom_cache_.GetAtom("XdndEnter"); 1229 xev.xclient.message_type = atom_cache_.GetAtom(kXdndEnter);
1103 xev.xclient.format = 32; 1230 xev.xclient.format = 32;
1104 xev.xclient.window = dest_window; 1231 xev.xclient.window = dest_window;
1105 xev.xclient.data.l[0] = xwindow_; 1232 xev.xclient.data.l[0] = xwindow_;
1106 xev.xclient.data.l[1] = (kMinXdndVersion << 24); // The version number. 1233 xev.xclient.data.l[1] = (kMaxXdndVersion << 24); // The version number.
1107 xev.xclient.data.l[2] = 0; 1234 xev.xclient.data.l[2] = 0;
1108 xev.xclient.data.l[3] = 0; 1235 xev.xclient.data.l[3] = 0;
1109 xev.xclient.data.l[4] = 0; 1236 xev.xclient.data.l[4] = 0;
1110 1237
1111 std::vector<Atom> targets; 1238 std::vector<Atom> targets;
1112 source_provider_->RetrieveTargets(&targets); 1239 source_provider_->RetrieveTargets(&targets);
1113 1240
1114 if (targets.size() > 3) { 1241 if (targets.size() > 3) {
1115 xev.xclient.data.l[1] |= 1; 1242 xev.xclient.data.l[1] |= 1;
1116 ui::SetAtomArrayProperty(xwindow_, "XdndTypeList", "ATOM", targets); 1243 ui::SetAtomArrayProperty(xwindow_, kXdndTypeList, "ATOM", targets);
1117 } else { 1244 } else {
1118 // Pack the targets into the enter message. 1245 // Pack the targets into the enter message.
1119 for (size_t i = 0; i < targets.size(); ++i) 1246 for (size_t i = 0; i < targets.size(); ++i)
1120 xev.xclient.data.l[2 + i] = targets[i]; 1247 xev.xclient.data.l[2 + i] = targets[i];
1121 } 1248 }
1122 1249
1123 SendXClientEvent(dest_window, &xev); 1250 SendXClientEvent(dest_window, &xev);
1124 } 1251 }
1125 1252
1126 void DesktopDragDropClientAuraX11::SendXdndLeave(::Window dest_window) { 1253 void DesktopDragDropClientAuraX11::SendXdndLeave(::Window dest_window) {
1127 XEvent xev; 1254 XEvent xev;
1128 xev.xclient.type = ClientMessage; 1255 xev.xclient.type = ClientMessage;
1129 xev.xclient.message_type = atom_cache_.GetAtom("XdndLeave"); 1256 xev.xclient.message_type = atom_cache_.GetAtom(kXdndLeave);
1130 xev.xclient.format = 32; 1257 xev.xclient.format = 32;
1131 xev.xclient.window = dest_window; 1258 xev.xclient.window = dest_window;
1132 xev.xclient.data.l[0] = xwindow_; 1259 xev.xclient.data.l[0] = xwindow_;
1133 xev.xclient.data.l[1] = 0; 1260 xev.xclient.data.l[1] = 0;
1134 xev.xclient.data.l[2] = 0; 1261 xev.xclient.data.l[2] = 0;
1135 xev.xclient.data.l[3] = 0; 1262 xev.xclient.data.l[3] = 0;
1136 xev.xclient.data.l[4] = 0; 1263 xev.xclient.data.l[4] = 0;
1137 SendXClientEvent(dest_window, &xev); 1264 SendXClientEvent(dest_window, &xev);
1138 } 1265 }
1139 1266
1140 void DesktopDragDropClientAuraX11::SendXdndPosition( 1267 void DesktopDragDropClientAuraX11::SendXdndPosition(
1141 ::Window dest_window, 1268 ::Window dest_window,
1142 const gfx::Point& screen_point, 1269 const gfx::Point& screen_point,
1143 unsigned long event_time) { 1270 unsigned long event_time) {
1144 waiting_on_status_ = true; 1271 waiting_on_status_ = true;
1145 1272
1146 XEvent xev; 1273 XEvent xev;
1147 xev.xclient.type = ClientMessage; 1274 xev.xclient.type = ClientMessage;
1148 xev.xclient.message_type = atom_cache_.GetAtom("XdndPosition"); 1275 xev.xclient.message_type = atom_cache_.GetAtom(kXdndPosition);
1149 xev.xclient.format = 32; 1276 xev.xclient.format = 32;
1150 xev.xclient.window = dest_window; 1277 xev.xclient.window = dest_window;
1151 xev.xclient.data.l[0] = xwindow_; 1278 xev.xclient.data.l[0] = xwindow_;
1152 xev.xclient.data.l[1] = 0; 1279 xev.xclient.data.l[1] = 0;
1153 xev.xclient.data.l[2] = (screen_point.x() << 16) | screen_point.y(); 1280 xev.xclient.data.l[2] = (screen_point.x() << 16) | screen_point.y();
1154 xev.xclient.data.l[3] = event_time; 1281 xev.xclient.data.l[3] = event_time;
1155 xev.xclient.data.l[4] = DragOperationToAtom(drag_operation_); 1282 xev.xclient.data.l[4] = DragOperationToAtom(drag_operation_);
1156 SendXClientEvent(dest_window, &xev); 1283 SendXClientEvent(dest_window, &xev);
1157 1284
1158 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html and 1285 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html and
1159 // the Xdnd protocol both recommend that drag events should be sent 1286 // the Xdnd protocol both recommend that drag events should be sent
1160 // periodically. 1287 // periodically.
1161 repeat_mouse_move_timer_.Start( 1288 repeat_mouse_move_timer_.Start(
1162 FROM_HERE, 1289 FROM_HERE,
1163 base::TimeDelta::FromMilliseconds(kRepeatMouseMoveTimeoutMs), 1290 base::TimeDelta::FromMilliseconds(kRepeatMouseMoveTimeoutMs),
1164 base::Bind(&DesktopDragDropClientAuraX11::ProcessMouseMove, 1291 base::Bind(&DesktopDragDropClientAuraX11::ProcessMouseMove,
1165 base::Unretained(this), 1292 base::Unretained(this),
1166 screen_point, 1293 screen_point,
1167 event_time)); 1294 event_time));
1168 } 1295 }
1169 1296
1170 void DesktopDragDropClientAuraX11::SendXdndDrop(::Window dest_window) { 1297 void DesktopDragDropClientAuraX11::SendXdndDrop(::Window dest_window) {
1171 XEvent xev; 1298 XEvent xev;
1172 xev.xclient.type = ClientMessage; 1299 xev.xclient.type = ClientMessage;
1173 xev.xclient.message_type = atom_cache_.GetAtom("XdndDrop"); 1300 xev.xclient.message_type = atom_cache_.GetAtom(kXdndDrop);
1174 xev.xclient.format = 32; 1301 xev.xclient.format = 32;
1175 xev.xclient.window = dest_window; 1302 xev.xclient.window = dest_window;
1176 xev.xclient.data.l[0] = xwindow_; 1303 xev.xclient.data.l[0] = xwindow_;
1177 xev.xclient.data.l[1] = 0; 1304 xev.xclient.data.l[1] = 0;
1178 xev.xclient.data.l[2] = CurrentTime; 1305 xev.xclient.data.l[2] = CurrentTime;
1179 xev.xclient.data.l[3] = None; 1306 xev.xclient.data.l[3] = None;
1180 xev.xclient.data.l[4] = None; 1307 xev.xclient.data.l[4] = None;
1181 SendXClientEvent(dest_window, &xev); 1308 SendXClientEvent(dest_window, &xev);
1182 } 1309 }
1183 1310
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1225 for (int x = 0; x < in_bitmap->width(); ++x) { 1352 for (int x = 0; x < in_bitmap->width(); ++x) {
1226 if (SkColorGetA(in_row[x]) > kMinAlpha) 1353 if (SkColorGetA(in_row[x]) > kMinAlpha)
1227 return true; 1354 return true;
1228 } 1355 }
1229 } 1356 }
1230 1357
1231 return false; 1358 return false;
1232 } 1359 }
1233 1360
1234 } // namespace views 1361 } // namespace views
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698