| 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" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 "XdndDrop", | 57 "XdndDrop", |
| 58 "XdndEnter", | 58 "XdndEnter", |
| 59 "XdndFinished", | 59 "XdndFinished", |
| 60 "XdndLeave", | 60 "XdndLeave", |
| 61 "XdndPosition", | 61 "XdndPosition", |
| 62 "XdndProxy", // Proxy windows? | 62 "XdndProxy", // Proxy windows? |
| 63 kXdndSelection, | 63 kXdndSelection, |
| 64 "XdndStatus", | 64 "XdndStatus", |
| 65 "XdndTypeList", | 65 "XdndTypeList", |
| 66 ui::Clipboard::kMimeTypeText, | 66 ui::Clipboard::kMimeTypeText, |
| 67 "_NET_WM_WINDOW_TYPE_MENU", | |
| 68 NULL | 67 NULL |
| 69 }; | 68 }; |
| 70 | 69 |
| 71 // The time to wait for the target to respond after the user has released the | 70 // The time to wait for the target to respond after the user has released the |
| 72 // mouse button before ending the move loop. | 71 // mouse button before ending the move loop. |
| 73 const int kEndMoveLoopTimeoutMs = 30000; | 72 const int kEndMoveLoopTimeoutMs = 30000; |
| 74 | 73 |
| 75 static base::LazyInstance< | 74 static base::LazyInstance< |
| 76 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky | 75 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky |
| 77 g_live_client_map = LAZY_INSTANCE_INITIALIZER; | 76 g_live_client_map = LAZY_INSTANCE_INITIALIZER; |
| 78 | 77 |
| 79 // Helper class to FindWindowFor which looks for a drag target under the | 78 // Helper class to FindWindowFor which looks for a drag target under the |
| 80 // cursor. | 79 // cursor. |
| 81 class DragTargetWindowFinder : public ui::EnumerateWindowsDelegate { | 80 class DragTargetWindowFinder : public ui::EnumerateWindowsDelegate { |
| 82 public: | 81 public: |
| 83 DragTargetWindowFinder(XID ignored_icon_window, | 82 DragTargetWindowFinder(XID ignored_icon_window, |
| 84 Atom menu_type_atom, | |
| 85 gfx::Point screen_loc) | 83 gfx::Point screen_loc) |
| 86 : ignored_icon_window_(ignored_icon_window), | 84 : ignored_icon_window_(ignored_icon_window), |
| 87 output_window_(None), | 85 output_window_(None), |
| 88 menu_type_atom_(menu_type_atom), | |
| 89 screen_loc_(screen_loc) { | 86 screen_loc_(screen_loc) { |
| 90 ui::EnumerateTopLevelWindows(this); | 87 ui::EnumerateTopLevelWindows(this); |
| 91 } | 88 } |
| 92 | 89 |
| 93 virtual ~DragTargetWindowFinder() {} | 90 virtual ~DragTargetWindowFinder() {} |
| 94 | 91 |
| 95 XID window() const { return output_window_; } | 92 XID window() const { return output_window_; } |
| 96 | 93 |
| 97 protected: | 94 protected: |
| 98 virtual bool ShouldStopIterating(XID window) OVERRIDE { | 95 virtual bool ShouldStopIterating(XID window) OVERRIDE { |
| 99 if (window == ignored_icon_window_) | 96 if (window == ignored_icon_window_) |
| 100 return false; | 97 return false; |
| 101 | 98 |
| 102 if (!ui::IsWindowVisible(window)) | 99 if (!ui::IsWindowVisible(window)) |
| 103 return false; | 100 return false; |
| 104 | 101 |
| 105 if (!ui::WindowContainsPoint(window, screen_loc_)) | 102 if (!ui::WindowContainsPoint(window, screen_loc_)) |
| 106 return false; | 103 return false; |
| 107 | 104 |
| 108 int value = 0; | 105 if (ui::PropertyExists(window, "WM_STATE")) { |
| 109 if (ui::PropertyExists(window, "WM_STATE") || | |
| 110 (ui::GetIntProperty(window, "_NET_WM_WINDOW_TYPE", &value) && | |
| 111 static_cast<Atom>(value) == menu_type_atom_)) { | |
| 112 output_window_ = window; | 106 output_window_ = window; |
| 113 return true; | 107 return true; |
| 114 } | 108 } |
| 115 | 109 |
| 116 return false; | 110 return false; |
| 117 } | 111 } |
| 118 | 112 |
| 119 private: | 113 private: |
| 120 XID ignored_icon_window_; | 114 XID ignored_icon_window_; |
| 121 XID output_window_; | 115 XID output_window_; |
| 122 const Atom menu_type_atom_; | |
| 123 gfx::Point screen_loc_; | 116 gfx::Point screen_loc_; |
| 124 | 117 |
| 125 DISALLOW_COPY_AND_ASSIGN(DragTargetWindowFinder); | 118 DISALLOW_COPY_AND_ASSIGN(DragTargetWindowFinder); |
| 126 }; | 119 }; |
| 127 | 120 |
| 128 // Returns the topmost X11 window at |screen_point| if it is advertising that | 121 // Returns the topmost X11 window at |screen_point| if it is advertising that |
| 129 // is supports the Xdnd protocol. Will return the window under the pointer as | 122 // is supports the Xdnd protocol. Will return the window under the pointer as |
| 130 // |mouse_window|. If there's a Xdnd aware window, it will be returned in | 123 // |mouse_window|. If there's a Xdnd aware window, it will be returned in |
| 131 // |dest_window|. | 124 // |dest_window|. |
| 132 void FindWindowFor(const gfx::Point& screen_point, | 125 void FindWindowFor(const gfx::Point& screen_point, |
| 133 ::Window* mouse_window, ::Window* dest_window, | 126 ::Window* mouse_window, ::Window* dest_window) { |
| 134 Atom menu_type_atom) { | 127 DragTargetWindowFinder finder(None, screen_point); |
| 135 DragTargetWindowFinder finder(None, menu_type_atom, screen_point); | |
| 136 *mouse_window = finder.window(); | 128 *mouse_window = finder.window(); |
| 137 *dest_window = None; | 129 *dest_window = None; |
| 138 | 130 |
| 139 if (finder.window() == None) | 131 if (finder.window() == None) |
| 140 return; | 132 return; |
| 141 | 133 |
| 142 // Figure out which window we should test as XdndAware. If mouse_window has | 134 // Figure out which window we should test as XdndAware. If mouse_window has |
| 143 // XdndProxy, it will set that proxy on target, and if not, |target|'s | 135 // XdndProxy, it will set that proxy on target, and if not, |target|'s |
| 144 // original value will remain. | 136 // original value will remain. |
| 145 XID target = *mouse_window; | 137 XID target = *mouse_window; |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 | 427 |
| 436 // Mark that we are aware of drag and drop concepts. | 428 // Mark that we are aware of drag and drop concepts. |
| 437 unsigned long xdnd_version = kMinXdndVersion; | 429 unsigned long xdnd_version = kMinXdndVersion; |
| 438 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"), | 430 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"), |
| 439 XA_ATOM, 32, PropModeReplace, | 431 XA_ATOM, 32, PropModeReplace, |
| 440 reinterpret_cast<unsigned char*>(&xdnd_version), 1); | 432 reinterpret_cast<unsigned char*>(&xdnd_version), 1); |
| 441 } | 433 } |
| 442 | 434 |
| 443 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() { | 435 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() { |
| 444 g_live_client_map.Get().erase(xwindow_); | 436 g_live_client_map.Get().erase(xwindow_); |
| 445 // Make sure that all observers are unregistered from source and target | |
| 446 // windows. This may be necessary when the parent native widget gets destroyed | |
| 447 // while a drag operation is in progress. | |
| 448 NotifyDragLeave(); | |
| 449 } | 437 } |
| 450 | 438 |
| 451 // static | 439 // static |
| 452 DesktopDragDropClientAuraX11* DesktopDragDropClientAuraX11::GetForWindow( | 440 DesktopDragDropClientAuraX11* DesktopDragDropClientAuraX11::GetForWindow( |
| 453 ::Window window) { | 441 ::Window window) { |
| 454 std::map< ::Window, DesktopDragDropClientAuraX11*>::const_iterator it = | 442 std::map< ::Window, DesktopDragDropClientAuraX11*>::const_iterator it = |
| 455 g_live_client_map.Get().find(window); | 443 g_live_client_map.Get().find(window); |
| 456 if (it == g_live_client_map.Get().end()) | 444 if (it == g_live_client_map.Get().end()) |
| 457 return NULL; | 445 return NULL; |
| 458 return it->second; | 446 return it->second; |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 | 689 |
| 702 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { | 690 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { |
| 703 gfx::Point screen_point(event->x_root, event->y_root); | 691 gfx::Point screen_point(event->x_root, event->y_root); |
| 704 | 692 |
| 705 if (source_state_ != SOURCE_STATE_OTHER) | 693 if (source_state_ != SOURCE_STATE_OTHER) |
| 706 return; | 694 return; |
| 707 | 695 |
| 708 // Find the current window the cursor is over. | 696 // Find the current window the cursor is over. |
| 709 ::Window mouse_window = None; | 697 ::Window mouse_window = None; |
| 710 ::Window dest_window = None; | 698 ::Window dest_window = None; |
| 711 FindWindowFor(screen_point, &mouse_window, &dest_window, | 699 FindWindowFor(screen_point, &mouse_window, &dest_window); |
| 712 atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU")); | |
| 713 | 700 |
| 714 if (source_current_window_ != dest_window) { | 701 if (source_current_window_ != dest_window) { |
| 715 if (source_current_window_ != None) | 702 if (source_current_window_ != None) |
| 716 SendXdndLeave(source_current_window_); | 703 SendXdndLeave(source_current_window_); |
| 717 | 704 |
| 718 source_current_window_ = dest_window; | 705 source_current_window_ = dest_window; |
| 719 | 706 |
| 720 if (source_current_window_ != None) { | 707 if (source_current_window_ != None) { |
| 721 negotiated_operation_.erase(source_current_window_); | 708 negotiated_operation_.erase(source_current_window_); |
| 722 SendXdndEnter(source_current_window_); | 709 SendXdndEnter(source_current_window_); |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 // GdkEvent about the failed drag. (And sending this message doesn't appear | 1012 // 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 | 1013 // to go through normal xlib machinery, but instead passes through the low |
| 1027 // level xProto (the x11 wire format) that I don't understand. | 1014 // level xProto (the x11 wire format) that I don't understand. |
| 1028 // | 1015 // |
| 1029 // I'm unsure if I have to jump through those hoops, or if XSendEvent is | 1016 // I'm unsure if I have to jump through those hoops, or if XSendEvent is |
| 1030 // sufficient. | 1017 // sufficient. |
| 1031 XSendEvent(xdisplay_, xid, False, 0, xev); | 1018 XSendEvent(xdisplay_, xid, False, 0, xev); |
| 1032 } | 1019 } |
| 1033 | 1020 |
| 1034 } // namespace views | 1021 } // namespace views |
| OLD | NEW |