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 |