| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |