| 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 static base::LazyInstance< | 65 static base::LazyInstance< |
| 65 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky | 66 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky |
| 66 g_live_client_map = LAZY_INSTANCE_INITIALIZER; | 67 g_live_client_map = LAZY_INSTANCE_INITIALIZER; |
| 67 | 68 |
| 68 // Helper class to FindWindowFor which looks for a drag target under the | 69 // Helper class to FindWindowFor which looks for a drag target under the |
| 69 // cursor. | 70 // cursor. |
| 70 class DragTargetWindowFinder : public ui::EnumerateWindowsDelegate { | 71 class DragTargetWindowFinder : public ui::EnumerateWindowsDelegate { |
| 71 public: | 72 public: |
| 72 DragTargetWindowFinder(XID ignored_icon_window, | 73 DragTargetWindowFinder(XID ignored_icon_window, |
| 74 Atom menu_type_atom, |
| 73 gfx::Point screen_loc) | 75 gfx::Point screen_loc) |
| 74 : ignored_icon_window_(ignored_icon_window), | 76 : ignored_icon_window_(ignored_icon_window), |
| 75 output_window_(None), | 77 output_window_(None), |
| 78 menu_type_atom_(menu_type_atom), |
| 76 screen_loc_(screen_loc) { | 79 screen_loc_(screen_loc) { |
| 77 ui::EnumerateTopLevelWindows(this); | 80 ui::EnumerateTopLevelWindows(this); |
| 78 } | 81 } |
| 79 | 82 |
| 80 virtual ~DragTargetWindowFinder() {} | 83 virtual ~DragTargetWindowFinder() {} |
| 81 | 84 |
| 82 XID window() const { return output_window_; } | 85 XID window() const { return output_window_; } |
| 83 | 86 |
| 84 protected: | 87 protected: |
| 85 virtual bool ShouldStopIterating(XID window) OVERRIDE { | 88 virtual bool ShouldStopIterating(XID window) OVERRIDE { |
| 86 if (window == ignored_icon_window_) | 89 if (window == ignored_icon_window_) |
| 87 return false; | 90 return false; |
| 88 | 91 |
| 89 if (!ui::IsWindowVisible(window)) | 92 if (!ui::IsWindowVisible(window)) |
| 90 return false; | 93 return false; |
| 91 | 94 |
| 92 if (!ui::WindowContainsPoint(window, screen_loc_)) | 95 if (!ui::WindowContainsPoint(window, screen_loc_)) |
| 93 return false; | 96 return false; |
| 94 | 97 |
| 95 if (ui::PropertyExists(window, "WM_STATE")) { | 98 int value = 0; |
| 99 if (ui::PropertyExists(window, "WM_STATE") || |
| 100 (ui::GetIntProperty(window, "_NET_WM_WINDOW_TYPE", &value) && |
| 101 static_cast<Atom>(value) == menu_type_atom_)) { |
| 96 output_window_ = window; | 102 output_window_ = window; |
| 97 return true; | 103 return true; |
| 98 } | 104 } |
| 99 | 105 |
| 100 return false; | 106 return false; |
| 101 } | 107 } |
| 102 | 108 |
| 103 private: | 109 private: |
| 104 XID ignored_icon_window_; | 110 XID ignored_icon_window_; |
| 105 XID output_window_; | 111 XID output_window_; |
| 112 const Atom menu_type_atom_; |
| 106 gfx::Point screen_loc_; | 113 gfx::Point screen_loc_; |
| 107 | 114 |
| 108 DISALLOW_COPY_AND_ASSIGN(DragTargetWindowFinder); | 115 DISALLOW_COPY_AND_ASSIGN(DragTargetWindowFinder); |
| 109 }; | 116 }; |
| 110 | 117 |
| 111 // Returns the topmost X11 window at |screen_point| if it is advertising that | 118 // Returns the topmost X11 window at |screen_point| if it is advertising that |
| 112 // is supports the Xdnd protocol. Will return the window under the pointer as | 119 // is supports the Xdnd protocol. Will return the window under the pointer as |
| 113 // |mouse_window|. If there's a Xdnd aware window, it will be returned in | 120 // |mouse_window|. If there's a Xdnd aware window, it will be returned in |
| 114 // |dest_window|. | 121 // |dest_window|. |
| 115 void FindWindowFor(const gfx::Point& screen_point, | 122 void FindWindowFor(const gfx::Point& screen_point, |
| 116 ::Window* mouse_window, ::Window* dest_window) { | 123 ::Window* mouse_window, ::Window* dest_window, |
| 117 DragTargetWindowFinder finder(None, screen_point); | 124 Atom menu_type_atom) { |
| 125 DragTargetWindowFinder finder(None, menu_type_atom, screen_point); |
| 118 *mouse_window = finder.window(); | 126 *mouse_window = finder.window(); |
| 119 *dest_window = None; | 127 *dest_window = None; |
| 120 | 128 |
| 121 if (finder.window() == None) | 129 if (finder.window() == None) |
| 122 return; | 130 return; |
| 123 | 131 |
| 124 // Figure out which window we should test as XdndAware. If mouse_window has | 132 // Figure out which window we should test as XdndAware. If mouse_window has |
| 125 // XdndProxy, it will set that proxy on target, and if not, |target|'s | 133 // XdndProxy, it will set that proxy on target, and if not, |target|'s |
| 126 // original value will remain. | 134 // original value will remain. |
| 127 XID target = *mouse_window; | 135 XID target = *mouse_window; |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 | 424 |
| 417 // Mark that we are aware of drag and drop concepts. | 425 // Mark that we are aware of drag and drop concepts. |
| 418 unsigned long xdnd_version = kMinXdndVersion; | 426 unsigned long xdnd_version = kMinXdndVersion; |
| 419 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"), | 427 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"), |
| 420 XA_ATOM, 32, PropModeReplace, | 428 XA_ATOM, 32, PropModeReplace, |
| 421 reinterpret_cast<unsigned char*>(&xdnd_version), 1); | 429 reinterpret_cast<unsigned char*>(&xdnd_version), 1); |
| 422 } | 430 } |
| 423 | 431 |
| 424 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() { | 432 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() { |
| 425 g_live_client_map.Get().erase(xwindow_); | 433 g_live_client_map.Get().erase(xwindow_); |
| 434 // Make sure that all observers are unregistered from source and target |
| 435 // windows. This may be necessary when the parent native widget gets destroyed |
| 436 // while a drag operation is in progress. |
| 437 NotifyDragLeave(); |
| 438 target_current_context_.reset(); |
| 426 } | 439 } |
| 427 | 440 |
| 428 // static | 441 // static |
| 429 DesktopDragDropClientAuraX11* DesktopDragDropClientAuraX11::GetForWindow( | 442 DesktopDragDropClientAuraX11* DesktopDragDropClientAuraX11::GetForWindow( |
| 430 ::Window window) { | 443 ::Window window) { |
| 431 std::map< ::Window, DesktopDragDropClientAuraX11*>::const_iterator it = | 444 std::map< ::Window, DesktopDragDropClientAuraX11*>::const_iterator it = |
| 432 g_live_client_map.Get().find(window); | 445 g_live_client_map.Get().find(window); |
| 433 if (it == g_live_client_map.Get().end()) | 446 if (it == g_live_client_map.Get().end()) |
| 434 return NULL; | 447 return NULL; |
| 435 return it->second; | 448 return it->second; |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 DCHECK_EQ(target_window_, window); | 673 DCHECK_EQ(target_window_, window); |
| 661 target_window_ = NULL; | 674 target_window_ = NULL; |
| 662 } | 675 } |
| 663 | 676 |
| 664 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { | 677 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { |
| 665 gfx::Point screen_point(event->x_root, event->y_root); | 678 gfx::Point screen_point(event->x_root, event->y_root); |
| 666 | 679 |
| 667 // Find the current window the cursor is over. | 680 // Find the current window the cursor is over. |
| 668 ::Window mouse_window = None; | 681 ::Window mouse_window = None; |
| 669 ::Window dest_window = None; | 682 ::Window dest_window = None; |
| 670 FindWindowFor(screen_point, &mouse_window, &dest_window); | 683 FindWindowFor(screen_point, &mouse_window, &dest_window, |
| 684 atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU")); |
| 671 | 685 |
| 672 if (source_current_window_ != dest_window) { | 686 if (source_current_window_ != dest_window) { |
| 673 if (source_current_window_ != None) | 687 if (source_current_window_ != None) |
| 674 SendXdndLeave(source_current_window_); | 688 SendXdndLeave(source_current_window_); |
| 675 | 689 |
| 676 source_current_window_ = dest_window; | 690 source_current_window_ = dest_window; |
| 677 | 691 |
| 678 if (source_current_window_ != None) { | 692 if (source_current_window_ != None) { |
| 679 negotiated_operation_.erase(source_current_window_); | 693 negotiated_operation_.erase(source_current_window_); |
| 680 SendXdndEnter(source_current_window_); | 694 SendXdndEnter(source_current_window_); |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 // GdkEvent about the failed drag. (And sending this message doesn't appear | 974 // GdkEvent about the failed drag. (And sending this message doesn't appear |
| 961 // to go through normal xlib machinery, but instead passes through the low | 975 // to go through normal xlib machinery, but instead passes through the low |
| 962 // level xProto (the x11 wire format) that I don't understand. | 976 // level xProto (the x11 wire format) that I don't understand. |
| 963 // | 977 // |
| 964 // I'm unsure if I have to jump through those hoops, or if XSendEvent is | 978 // I'm unsure if I have to jump through those hoops, or if XSendEvent is |
| 965 // sufficient. | 979 // sufficient. |
| 966 XSendEvent(xdisplay_, xid, False, 0, xev); | 980 XSendEvent(xdisplay_, xid, False, 0, xev); |
| 967 } | 981 } |
| 968 | 982 |
| 969 } // namespace views | 983 } // namespace views |
| OLD | NEW |