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