desktop_drag_drop_client_aurax11.h revision f2477e01787aa58f445919b809d89e252beef54f
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 3// found in the LICENSE file. 4 5#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_AURAX11_H_ 6#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_AURAX11_H_ 7 8#include <set> 9#include <X11/Xlib.h> 10 11#include "base/compiler_specific.h" 12#include "base/memory/ref_counted.h" 13#include "base/memory/scoped_ptr.h" 14#include "ui/aura/client/drag_drop_client.h" 15#include "ui/aura/window_observer.h" 16#include "ui/base/cursor/cursor.h" 17#include "ui/gfx/point.h" 18#include "ui/gfx/x/x11_atom_cache.h" 19#include "ui/views/views_export.h" 20#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" 21#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop_delegate.h" 22 23namespace aura { 24namespace client { 25class DragDropDelegate; 26} 27} 28 29namespace gfx { 30class Point; 31} 32 33namespace ui { 34class DragSource; 35class DropTargetEvent; 36class OSExchangeData; 37class OSExchangeDataProviderAuraX11; 38class SelectionFormatMap; 39} 40 41namespace views { 42class DesktopNativeCursorManager; 43 44// Implements drag and drop on X11 for aura. On one side, this class takes raw 45// X11 events forwarded from DesktopRootWindowHostLinux, while on the other, it 46// handles the views drag events. 47class VIEWS_EXPORT DesktopDragDropClientAuraX11 48 : public aura::client::DragDropClient, 49 public aura::WindowObserver, 50 public X11WholeScreenMoveLoopDelegate { 51 public: 52 DesktopDragDropClientAuraX11( 53 aura::Window* root_window, 54 views::DesktopNativeCursorManager* cursor_manager, 55 Display* xdisplay, 56 ::Window xwindow); 57 virtual ~DesktopDragDropClientAuraX11(); 58 59 // We maintain a mapping of live DesktopDragDropClientAuraX11 objects to 60 // their ::Windows. We do this so that we're able to short circuit sending 61 // X11 messages to windows in our process. 62 static DesktopDragDropClientAuraX11* GetForWindow(::Window window); 63 64 // These methods handle the various X11 client messages from the platform. 65 void OnXdndEnter(const XClientMessageEvent& event); 66 void OnXdndLeave(const XClientMessageEvent& event); 67 void OnXdndPosition(const XClientMessageEvent& event); 68 void OnXdndStatus(const XClientMessageEvent& event); 69 void OnXdndFinished(const XClientMessageEvent& event); 70 void OnXdndDrop(const XClientMessageEvent& event); 71 72 // Called when XSelection data has been copied to our process. 73 void OnSelectionNotify(const XSelectionEvent& xselection); 74 75 // Overridden from aura::client::DragDropClient: 76 virtual int StartDragAndDrop( 77 const ui::OSExchangeData& data, 78 aura::Window* root_window, 79 aura::Window* source_window, 80 const gfx::Point& root_location, 81 int operation, 82 ui::DragDropTypes::DragEventSource source) OVERRIDE; 83 virtual void DragUpdate(aura::Window* target, 84 const ui::LocatedEvent& event) OVERRIDE; 85 virtual void Drop(aura::Window* target, 86 const ui::LocatedEvent& event) OVERRIDE; 87 virtual void DragCancel() OVERRIDE; 88 virtual bool IsDragDropInProgress() OVERRIDE; 89 90 // Overridden from aura::WindowObserver: 91 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; 92 93 // Overridden from X11WholeScreenMoveLoopDelegate: 94 virtual void OnMouseMovement(XMotionEvent* event) OVERRIDE; 95 virtual void OnMouseReleased() OVERRIDE; 96 virtual void OnMoveLoopEnded() OVERRIDE; 97 98 private: 99 typedef std::map< ::Window, std::pair<gfx::Point, unsigned long> > 100 NextPositionMap; 101 102 // When we receive an position x11 message, we need to translate that into 103 // the underlying aura::Window representation, as moves internal to the X11 104 // window can cause internal drag leave and enter messages. 105 void DragTranslate(const gfx::Point& root_window_location, 106 scoped_ptr<ui::OSExchangeData>* data, 107 scoped_ptr<ui::DropTargetEvent>* event, 108 aura::client::DragDropDelegate** delegate); 109 110 // Called when we need to notify the current aura::Window that we're no 111 // longer dragging over it. 112 void NotifyDragLeave(); 113 114 // Converts our bitfield of actions into an Atom that represents what action 115 // we're most likely to take on drop. 116 ::Atom DragOperationToAtom(int drag_operation); 117 118 // Converts a single action atom to a drag operation. 119 int AtomToDragOperation(::Atom atom); 120 121 // During the blocking StartDragAndDrop() call, this converts the views-style 122 // |drag_operation_| bitfield into a vector of Atoms to offer to other 123 // processes. 124 std::vector< ::Atom> GetOfferedDragOperations(); 125 126 // This returns a representation of the data we're offering in this 127 // drag. This is done to bypass an asynchronous roundtrip with the X11 128 // server. 129 ui::SelectionFormatMap GetFormatMap() const; 130 131 // Handling XdndPosition can be paused while waiting for more data; this is 132 // called either synchronously from OnXdndPosition, or asynchronously after 133 // we've received data requested from the other window. 134 void CompleteXdndPosition(::Window source_window, 135 const gfx::Point& screen_point); 136 137 void SendXdndEnter(::Window dest_window); 138 void SendXdndLeave(::Window dest_window); 139 void SendXdndPosition(::Window dest_window, 140 const gfx::Point& screen_point, 141 unsigned long time); 142 void SendXdndDrop(::Window dest_window); 143 144 // Sends |xev| to |xid|, optionally short circuiting the round trip to the X 145 // server. 146 void SendXClientEvent(::Window xid, XEvent* xev); 147 148 // A nested message loop that notifies this object of events through the 149 // X11WholeScreenMoveLoopDelegate interface. 150 X11WholeScreenMoveLoop move_loop_; 151 152 aura::Window* root_window_; 153 154 Display* xdisplay_; 155 ::Window xwindow_; 156 157 ui::X11AtomCache atom_cache_; 158 159 // Target side information. 160 class X11DragContext; 161 scoped_ptr<X11DragContext> target_current_context_; 162 163 // The Aura window that is currently under the cursor. We need to manually 164 // keep track of this because Windows will only call our drag enter method 165 // once when the user enters the associated X Window. But inside that X 166 // Window there could be multiple aura windows, so we need to generate drag 167 // enter events for them. 168 aura::Window* target_window_; 169 170 // Because Xdnd messages don't contain the position in messages other than 171 // the XdndPosition message, we must manually keep track of the last position 172 // change. 173 gfx::Point target_window_location_; 174 gfx::Point target_window_root_location_; 175 176 // In the Xdnd protocol, we aren't supposed to send another XdndPosition 177 // message until we have received a confirming XdndStatus message. 178 std::set< ::Window> waiting_on_status_; 179 180 // If we would send an XdndPosition message while we're waiting for an 181 // XdndStatus response, we need to cache the latest details we'd send. 182 NextPositionMap next_position_message_; 183 184 // Source side information. 185 ui::OSExchangeDataProviderAuraX11 const* source_provider_; 186 ::Window source_current_window_; 187 188 bool drag_drop_in_progress_; 189 190 // The operation bitfield as requested by StartDragAndDrop. 191 int drag_operation_; 192 193 // The operation performed. Is initialized to None at the start of 194 // StartDragAndDrop(), and is set only during the asynchronous XdndFinished 195 // message. 196 int resulting_operation_; 197 198 // This window will be receiving a drop as soon as we receive an XdndStatus 199 // from it. 200 std::set< ::Window> pending_drop_; 201 202 // We offer the other window a list of possible operations, 203 // XdndActionsList. This is the requested action from the other window. This 204 // is None if we haven't sent out an XdndPosition message yet, haven't yet 205 // received an XdndStatus or if the other window has told us that there's no 206 // action that we can agree on. 207 // 208 // This is a map instead of a simple variable because of the case where we 209 // put an XdndLeave in the queue at roughly the same time that the other 210 // window responds to an XdndStatus. 211 std::map< ::Window, ::Atom> negotiated_operation_; 212 213 // We use these cursors while dragging. 214 gfx::NativeCursor grab_cursor_; 215 gfx::NativeCursor copy_grab_cursor_; 216 gfx::NativeCursor move_grab_cursor_; 217 218 DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientAuraX11); 219}; 220 221} // namespace views 222 223#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_AURAX11_H_ 224