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

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