| 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 | 8 |
| 9 #include "base/event_types.h" | 9 #include "base/event_types.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/message_loop/message_pump_dispatcher.h" | 12 #include "base/message_loop/message_pump_dispatcher.h" |
| 13 #include "ui/aura/window.h" | 13 #include "ui/aura/window.h" |
| 14 #include "ui/aura/window_tree_host.h" | 14 #include "ui/aura/window_tree_host.h" |
| 15 #include "ui/base/clipboard/clipboard.h" | 15 #include "ui/base/clipboard/clipboard.h" |
| 16 #include "ui/base/dragdrop/drag_drop_types.h" | 16 #include "ui/base/dragdrop/drag_drop_types.h" |
| 17 #include "ui/base/dragdrop/drop_target_event.h" | 17 #include "ui/base/dragdrop/drop_target_event.h" |
| 18 #include "ui/base/dragdrop/os_exchange_data.h" | 18 #include "ui/base/dragdrop/os_exchange_data.h" |
| 19 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" | 19 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" |
| 20 #include "ui/base/x/selection_utils.h" | 20 #include "ui/base/x/selection_utils.h" |
| 21 #include "ui/base/x/x11_util.h" | 21 #include "ui/base/x/x11_util.h" |
| 22 #include "ui/events/event.h" | 22 #include "ui/events/event.h" |
| 23 #include "ui/events/platform/platform_event_source.h" |
| 23 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" | 24 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" |
| 24 #include "ui/wm/public/drag_drop_client.h" | 25 #include "ui/wm/public/drag_drop_client.h" |
| 25 #include "ui/wm/public/drag_drop_delegate.h" | 26 #include "ui/wm/public/drag_drop_delegate.h" |
| 26 | 27 |
| 27 using aura::client::DragDropDelegate; | 28 using aura::client::DragDropDelegate; |
| 28 using ui::OSExchangeData; | 29 using ui::OSExchangeData; |
| 29 | 30 |
| 30 namespace { | 31 namespace { |
| 31 | 32 |
| 32 const int kMinXdndVersion = 5; | 33 const int kMinXdndVersion = 5; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 } | 153 } |
| 153 } | 154 } |
| 154 | 155 |
| 155 } // namespace | 156 } // namespace |
| 156 | 157 |
| 157 namespace views { | 158 namespace views { |
| 158 | 159 |
| 159 DesktopDragDropClientAuraX11* | 160 DesktopDragDropClientAuraX11* |
| 160 DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL; | 161 DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL; |
| 161 | 162 |
| 162 class DesktopDragDropClientAuraX11::X11DragContext : | 163 class DesktopDragDropClientAuraX11::X11DragContext |
| 163 public base::MessagePumpDispatcher { | 164 : public ui::PlatformEventDispatcher { |
| 164 public: | 165 public: |
| 165 X11DragContext(ui::X11AtomCache* atom_cache, | 166 X11DragContext(ui::X11AtomCache* atom_cache, |
| 166 ::Window local_window, | 167 ::Window local_window, |
| 167 const XClientMessageEvent& event); | 168 const XClientMessageEvent& event); |
| 168 virtual ~X11DragContext(); | 169 virtual ~X11DragContext(); |
| 169 | 170 |
| 170 // When we receive an XdndPosition message, we need to have all the data | 171 // When we receive an XdndPosition message, we need to have all the data |
| 171 // copied from the other window before we process the XdndPosition | 172 // copied from the other window before we process the XdndPosition |
| 172 // message. If we have that data already, dispatch immediately. Otherwise, | 173 // message. If we have that data already, dispatch immediately. Otherwise, |
| 173 // delay dispatching until we do. | 174 // delay dispatching until we do. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 193 | 194 |
| 194 // Creates a ui::DragDropTypes::DragOperation representation of the current | 195 // Creates a ui::DragDropTypes::DragOperation representation of the current |
| 195 // action list. | 196 // action list. |
| 196 int GetDragOperation() const; | 197 int GetDragOperation() const; |
| 197 | 198 |
| 198 private: | 199 private: |
| 199 // Masks the X11 atom |xdnd_operation|'s views representation onto | 200 // Masks the X11 atom |xdnd_operation|'s views representation onto |
| 200 // |drag_operation|. | 201 // |drag_operation|. |
| 201 void MaskOpeartion(::Atom xdnd_operation, int* drag_operation) const; | 202 void MaskOpeartion(::Atom xdnd_operation, int* drag_operation) const; |
| 202 | 203 |
| 203 // Overridden from MessagePumpDispatcher: | 204 // ui::PlatformEventDispatcher: |
| 204 virtual uint32_t Dispatch(const base::NativeEvent& event) OVERRIDE; | 205 virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE; |
| 206 virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE; |
| 205 | 207 |
| 206 // The atom cache owned by our parent. | 208 // The atom cache owned by our parent. |
| 207 ui::X11AtomCache* atom_cache_; | 209 ui::X11AtomCache* atom_cache_; |
| 208 | 210 |
| 209 // The XID of our chrome local aura window handling our events. | 211 // The XID of our chrome local aura window handling our events. |
| 210 ::Window local_window_; | 212 ::Window local_window_; |
| 211 | 213 |
| 212 // The XID of the window that's initiated the drag. | 214 // The XID of the window that's initiated the drag. |
| 213 unsigned long source_window_; | 215 unsigned long source_window_; |
| 214 | 216 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 unfetched_targets_.push_back(event.data.l[2+i]); | 266 unfetched_targets_.push_back(event.data.l[2+i]); |
| 265 } | 267 } |
| 266 } | 268 } |
| 267 } | 269 } |
| 268 | 270 |
| 269 DesktopDragDropClientAuraX11* client = | 271 DesktopDragDropClientAuraX11* client = |
| 270 DesktopDragDropClientAuraX11::GetForWindow(source_window_); | 272 DesktopDragDropClientAuraX11::GetForWindow(source_window_); |
| 271 if (!client) { | 273 if (!client) { |
| 272 // The window doesn't have a DesktopDragDropClientAuraX11, that means it's | 274 // The window doesn't have a DesktopDragDropClientAuraX11, that means it's |
| 273 // created by some other process. Listen for messages on it. | 275 // created by some other process. Listen for messages on it. |
| 274 base::MessagePumpX11::Current()->AddDispatcherForWindow( | 276 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); |
| 275 this, source_window_); | |
| 276 XSelectInput(gfx::GetXDisplay(), source_window_, PropertyChangeMask); | 277 XSelectInput(gfx::GetXDisplay(), source_window_, PropertyChangeMask); |
| 277 | 278 |
| 278 // We must perform a full sync here because we could be racing | 279 // We must perform a full sync here because we could be racing |
| 279 // |source_window_|. | 280 // |source_window_|. |
| 280 XSync(gfx::GetXDisplay(), False); | 281 XSync(gfx::GetXDisplay(), False); |
| 281 } else { | 282 } else { |
| 282 // This drag originates from an aura window within our process. This means | 283 // This drag originates from an aura window within our process. This means |
| 283 // that we can shortcut the X11 server and ask the owning SelectionOwner | 284 // that we can shortcut the X11 server and ask the owning SelectionOwner |
| 284 // for the data it's offering. | 285 // for the data it's offering. |
| 285 fetched_targets_ = client->GetFormatMap(); | 286 fetched_targets_ = client->GetFormatMap(); |
| 286 unfetched_targets_.clear(); | 287 unfetched_targets_.clear(); |
| 287 } | 288 } |
| 288 | 289 |
| 289 ReadActions(); | 290 ReadActions(); |
| 290 } | 291 } |
| 291 | 292 |
| 292 DesktopDragDropClientAuraX11::X11DragContext::~X11DragContext() { | 293 DesktopDragDropClientAuraX11::X11DragContext::~X11DragContext() { |
| 293 DesktopDragDropClientAuraX11* client = | 294 DesktopDragDropClientAuraX11* client = |
| 294 DesktopDragDropClientAuraX11::GetForWindow(source_window_); | 295 DesktopDragDropClientAuraX11::GetForWindow(source_window_); |
| 295 if (!client) { | 296 if (!client) { |
| 296 // Unsubscribe from message events. | 297 // Unsubscribe from message events. |
| 297 base::MessagePumpX11::Current()->RemoveDispatcherForWindow( | 298 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); |
| 298 source_window_); | |
| 299 } | 299 } |
| 300 } | 300 } |
| 301 | 301 |
| 302 void DesktopDragDropClientAuraX11::X11DragContext::OnStartXdndPositionMessage( | 302 void DesktopDragDropClientAuraX11::X11DragContext::OnStartXdndPositionMessage( |
| 303 DesktopDragDropClientAuraX11* client, | 303 DesktopDragDropClientAuraX11* client, |
| 304 ::Atom suggested_action, | 304 ::Atom suggested_action, |
| 305 ::Window source_window, | 305 ::Window source_window, |
| 306 const gfx::Point& screen_point) { | 306 const gfx::Point& screen_point) { |
| 307 DCHECK_EQ(source_window_, source_window); | 307 DCHECK_EQ(source_window_, source_window); |
| 308 suggested_action_ = suggested_action; | 308 suggested_action_ = suggested_action; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 ::Atom xdnd_operation, | 391 ::Atom xdnd_operation, |
| 392 int* drag_operation) const { | 392 int* drag_operation) const { |
| 393 if (xdnd_operation == atom_cache_->GetAtom(kXdndActionCopy)) | 393 if (xdnd_operation == atom_cache_->GetAtom(kXdndActionCopy)) |
| 394 *drag_operation |= ui::DragDropTypes::DRAG_COPY; | 394 *drag_operation |= ui::DragDropTypes::DRAG_COPY; |
| 395 else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionMove)) | 395 else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionMove)) |
| 396 *drag_operation |= ui::DragDropTypes::DRAG_MOVE; | 396 *drag_operation |= ui::DragDropTypes::DRAG_MOVE; |
| 397 else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionLink)) | 397 else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionLink)) |
| 398 *drag_operation |= ui::DragDropTypes::DRAG_LINK; | 398 *drag_operation |= ui::DragDropTypes::DRAG_LINK; |
| 399 } | 399 } |
| 400 | 400 |
| 401 uint32_t DesktopDragDropClientAuraX11::X11DragContext::Dispatch( | 401 bool DesktopDragDropClientAuraX11::X11DragContext::CanDispatchEvent( |
| 402 const base::NativeEvent& event) { | 402 const ui::PlatformEvent& event) { |
| 403 return event->xany.window == source_window_; |
| 404 } |
| 405 |
| 406 uint32_t DesktopDragDropClientAuraX11::X11DragContext::DispatchEvent( |
| 407 const ui::PlatformEvent& event) { |
| 403 if (event->type == PropertyNotify && | 408 if (event->type == PropertyNotify && |
| 404 event->xproperty.atom == atom_cache_->GetAtom("XdndActionList")) { | 409 event->xproperty.atom == atom_cache_->GetAtom("XdndActionList")) { |
| 405 ReadActions(); | 410 ReadActions(); |
| 411 return ui::POST_DISPATCH_STOP_PROPAGATION; |
| 406 } | 412 } |
| 407 return POST_DISPATCH_NONE; | 413 return ui::POST_DISPATCH_NONE; |
| 408 } | 414 } |
| 409 | 415 |
| 410 /////////////////////////////////////////////////////////////////////////////// | 416 /////////////////////////////////////////////////////////////////////////////// |
| 411 | 417 |
| 412 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11( | 418 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11( |
| 413 aura::Window* root_window, | 419 aura::Window* root_window, |
| 414 views::DesktopNativeCursorManager* cursor_manager, | 420 views::DesktopNativeCursorManager* cursor_manager, |
| 415 Display* xdisplay, | 421 Display* xdisplay, |
| 416 ::Window xwindow) | 422 ::Window xwindow) |
| 417 : move_loop_(this), | 423 : move_loop_(this), |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 // GdkEvent about the failed drag. (And sending this message doesn't appear | 1031 // GdkEvent about the failed drag. (And sending this message doesn't appear |
| 1026 // to go through normal xlib machinery, but instead passes through the low | 1032 // to go through normal xlib machinery, but instead passes through the low |
| 1027 // level xProto (the x11 wire format) that I don't understand. | 1033 // level xProto (the x11 wire format) that I don't understand. |
| 1028 // | 1034 // |
| 1029 // I'm unsure if I have to jump through those hoops, or if XSendEvent is | 1035 // I'm unsure if I have to jump through those hoops, or if XSendEvent is |
| 1030 // sufficient. | 1036 // sufficient. |
| 1031 XSendEvent(xdisplay_, xid, False, 0, xev); | 1037 XSendEvent(xdisplay_, xid, False, 0, xev); |
| 1032 } | 1038 } |
| 1033 | 1039 |
| 1034 } // namespace views | 1040 } // namespace views |
| OLD | NEW |