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