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 "ui/aura/window.h" | 12 #include "ui/aura/window.h" |
13 #include "ui/aura/window_tree_host.h" | 13 #include "ui/aura/window_tree_host.h" |
14 #include "ui/base/clipboard/clipboard.h" | 14 #include "ui/base/clipboard/clipboard.h" |
15 #include "ui/base/dragdrop/drag_drop_types.h" | 15 #include "ui/base/dragdrop/drag_drop_types.h" |
16 #include "ui/base/dragdrop/drop_target_event.h" | 16 #include "ui/base/dragdrop/drop_target_event.h" |
17 #include "ui/base/dragdrop/os_exchange_data.h" | 17 #include "ui/base/dragdrop/os_exchange_data.h" |
18 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" | 18 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" |
19 #include "ui/base/x/selection_utils.h" | 19 #include "ui/base/x/selection_utils.h" |
20 #include "ui/base/x/x11_util.h" | 20 #include "ui/base/x/x11_util.h" |
21 #include "ui/events/event.h" | 21 #include "ui/events/event.h" |
22 #include "ui/events/platform/platform_event_source.h" | 22 #include "ui/events/platform/platform_event_source.h" |
23 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" | 23 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" |
| 24 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.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; |
33 | 34 |
(...skipping 23 matching lines...) Expand all Loading... |
57 "XdndDrop", | 58 "XdndDrop", |
58 "XdndEnter", | 59 "XdndEnter", |
59 "XdndFinished", | 60 "XdndFinished", |
60 "XdndLeave", | 61 "XdndLeave", |
61 "XdndPosition", | 62 "XdndPosition", |
62 "XdndProxy", // Proxy windows? | 63 "XdndProxy", // Proxy windows? |
63 kXdndSelection, | 64 kXdndSelection, |
64 "XdndStatus", | 65 "XdndStatus", |
65 "XdndTypeList", | 66 "XdndTypeList", |
66 ui::Clipboard::kMimeTypeText, | 67 ui::Clipboard::kMimeTypeText, |
67 "_NET_WM_WINDOW_TYPE_MENU", | |
68 NULL | 68 NULL |
69 }; | 69 }; |
70 | 70 |
71 // The time to wait for the target to respond after the user has released the | 71 // The time to wait for the target to respond after the user has released the |
72 // mouse button before ending the move loop. | 72 // mouse button before ending the move loop. |
73 const int kEndMoveLoopTimeoutMs = 1000; | 73 const int kEndMoveLoopTimeoutMs = 1000; |
74 | 74 |
75 static base::LazyInstance< | 75 static base::LazyInstance< |
76 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky | 76 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky |
77 g_live_client_map = LAZY_INSTANCE_INITIALIZER; | 77 g_live_client_map = LAZY_INSTANCE_INITIALIZER; |
78 | 78 |
79 // Helper class to FindWindowFor which looks for a drag target under the | |
80 // cursor. | |
81 class DragTargetWindowFinder : public ui::EnumerateWindowsDelegate { | |
82 public: | |
83 DragTargetWindowFinder(XID ignored_icon_window, | |
84 Atom menu_type_atom, | |
85 gfx::Point screen_loc) | |
86 : ignored_icon_window_(ignored_icon_window), | |
87 output_window_(None), | |
88 menu_type_atom_(menu_type_atom), | |
89 screen_loc_(screen_loc) { | |
90 ui::EnumerateTopLevelWindows(this); | |
91 } | |
92 | |
93 virtual ~DragTargetWindowFinder() {} | |
94 | |
95 XID window() const { return output_window_; } | |
96 | |
97 protected: | |
98 virtual bool ShouldStopIterating(XID window) OVERRIDE { | |
99 if (window == ignored_icon_window_) | |
100 return false; | |
101 | |
102 if (!ui::IsWindowVisible(window)) | |
103 return false; | |
104 | |
105 if (!ui::WindowContainsPoint(window, screen_loc_)) | |
106 return false; | |
107 | |
108 int value = 0; | |
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; | |
113 return true; | |
114 } | |
115 | |
116 return false; | |
117 } | |
118 | |
119 private: | |
120 XID ignored_icon_window_; | |
121 XID output_window_; | |
122 const Atom menu_type_atom_; | |
123 gfx::Point screen_loc_; | |
124 | |
125 DISALLOW_COPY_AND_ASSIGN(DragTargetWindowFinder); | |
126 }; | |
127 | |
128 // Returns the topmost X11 window at |screen_point| if it is advertising that | 79 // 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 | 80 // 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 | 81 // |mouse_window|. If there's a Xdnd aware window, it will be returned in |
131 // |dest_window|. | 82 // |dest_window|. |
132 void FindWindowFor(const gfx::Point& screen_point, | 83 void FindWindowFor(const gfx::Point& screen_point, |
133 ::Window* mouse_window, ::Window* dest_window, | 84 ::Window* mouse_window, |
134 Atom menu_type_atom) { | 85 ::Window* dest_window) { |
135 DragTargetWindowFinder finder(None, menu_type_atom, screen_point); | 86 views::X11TopmostWindowFinder finder; |
136 *mouse_window = finder.window(); | 87 *mouse_window = finder.FindWindowAt(screen_point); |
137 *dest_window = None; | 88 *dest_window = None; |
138 | 89 |
139 if (finder.window() == None) | 90 if (*mouse_window == None) |
140 return; | 91 return; |
141 | 92 |
142 // Figure out which window we should test as XdndAware. If mouse_window has | 93 // 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 | 94 // XdndProxy, it will set that proxy on target, and if not, |target|'s |
144 // original value will remain. | 95 // original value will remain. |
145 XID target = *mouse_window; | 96 XID target = *mouse_window; |
146 ui::GetXIDProperty(*mouse_window, "XdndProxy", &target); | 97 ui::GetXIDProperty(*mouse_window, "XdndProxy", &target); |
147 | 98 |
148 int version; | 99 int version; |
149 if (ui::GetIntProperty(target, "XdndAware", &version) && | 100 if (ui::GetIntProperty(target, "XdndAware", &version) && |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 | 663 |
713 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { | 664 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { |
714 gfx::Point screen_point(event->x_root, event->y_root); | 665 gfx::Point screen_point(event->x_root, event->y_root); |
715 | 666 |
716 if (source_state_ != SOURCE_STATE_OTHER) | 667 if (source_state_ != SOURCE_STATE_OTHER) |
717 return; | 668 return; |
718 | 669 |
719 // Find the current window the cursor is over. | 670 // Find the current window the cursor is over. |
720 ::Window mouse_window = None; | 671 ::Window mouse_window = None; |
721 ::Window dest_window = None; | 672 ::Window dest_window = None; |
722 FindWindowFor(screen_point, &mouse_window, &dest_window, | 673 FindWindowFor(screen_point, &mouse_window, &dest_window); |
723 atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU")); | |
724 | 674 |
725 if (source_current_window_ != dest_window) { | 675 if (source_current_window_ != dest_window) { |
726 if (source_current_window_ != None) | 676 if (source_current_window_ != None) |
727 SendXdndLeave(source_current_window_); | 677 SendXdndLeave(source_current_window_); |
728 | 678 |
729 source_current_window_ = dest_window; | 679 source_current_window_ = dest_window; |
730 | 680 |
731 if (source_current_window_ != None) { | 681 if (source_current_window_ != None) { |
732 negotiated_operation_.erase(source_current_window_); | 682 negotiated_operation_.erase(source_current_window_); |
733 SendXdndEnter(source_current_window_); | 683 SendXdndEnter(source_current_window_); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 // GdkEvent about the failed drag. (And sending this message doesn't appear | 993 // GdkEvent about the failed drag. (And sending this message doesn't appear |
1044 // to go through normal xlib machinery, but instead passes through the low | 994 // to go through normal xlib machinery, but instead passes through the low |
1045 // level xProto (the x11 wire format) that I don't understand. | 995 // level xProto (the x11 wire format) that I don't understand. |
1046 // | 996 // |
1047 // I'm unsure if I have to jump through those hoops, or if XSendEvent is | 997 // I'm unsure if I have to jump through those hoops, or if XSendEvent is |
1048 // sufficient. | 998 // sufficient. |
1049 XSendEvent(xdisplay_, xid, False, 0, xev); | 999 XSendEvent(xdisplay_, xid, False, 0, xev); |
1050 } | 1000 } |
1051 | 1001 |
1052 } // namespace views | 1002 } // namespace views |
OLD | NEW |