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