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