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