1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_AURAX11_H_
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_AURAX11_H_
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <set>
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <vector>
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <X11/Xlib.h>
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/compiler_specific.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/weak_ptr.h"
15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/timer/timer.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/window_observer.h"
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/base/cursor/cursor.h"
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/base/dragdrop/drag_drop_types.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/point.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_atom_cache.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/views_export.h"
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/views/widget/desktop_aura/x11_move_loop_delegate.h"
23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/wm/public/drag_drop_client.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace aura {
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace client {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DragDropDelegate;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace gfx {
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ImageSkia;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class Point;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace ui {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DragSource;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DropTargetEvent;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class OSExchangeData;
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass OSExchangeDataProviderAuraX11;
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass SelectionFormatMap;
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace views {
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass DesktopNativeCursorManager;
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class Widget;
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class X11MoveLoop;
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Implements drag and drop on X11 for aura. On one side, this class takes raw
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// X11 events forwarded from DesktopWindowTreeHostLinux, while on the other, it
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// handles the views drag events.
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class VIEWS_EXPORT DesktopDragDropClientAuraX11
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public aura::client::DragDropClient,
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      public aura::WindowObserver,
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      public X11MoveLoopDelegate {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DesktopDragDropClientAuraX11(
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      aura::Window* root_window,
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      views::DesktopNativeCursorManager* cursor_manager,
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Display* xdisplay,
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ::Window xwindow);
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~DesktopDragDropClientAuraX11();
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We maintain a mapping of live DesktopDragDropClientAuraX11 objects to
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // their ::Windows. We do this so that we're able to short circuit sending
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // X11 messages to windows in our process.
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static DesktopDragDropClientAuraX11* GetForWindow(::Window window);
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void Init();
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // These methods handle the various X11 client messages from the platform.
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnXdndEnter(const XClientMessageEvent& event);
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnXdndLeave(const XClientMessageEvent& event);
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnXdndPosition(const XClientMessageEvent& event);
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnXdndStatus(const XClientMessageEvent& event);
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnXdndFinished(const XClientMessageEvent& event);
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnXdndDrop(const XClientMessageEvent& event);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Called when XSelection data has been copied to our process.
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void OnSelectionNotify(const XSelectionEvent& xselection);
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from aura::client::DragDropClient:
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual int StartDragAndDrop(
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const ui::OSExchangeData& data,
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      aura::Window* root_window,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      aura::Window* source_window,
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const gfx::Point& root_location,
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int operation,
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ui::DragDropTypes::DragEventSource source) OVERRIDE;
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void DragUpdate(aura::Window* target,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const ui::LocatedEvent& event) OVERRIDE;
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void Drop(aura::Window* target,
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    const ui::LocatedEvent& event) OVERRIDE;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void DragCancel() OVERRIDE;
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool IsDragDropInProgress() OVERRIDE;
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Overridden from aura::WindowObserver:
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Overridden from X11WholeScreenMoveLoopDelegate:
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnMouseMovement(XMotionEvent* event) OVERRIDE;
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnMouseReleased() OVERRIDE;
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnMoveLoopEnded() OVERRIDE;
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) protected:
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The following methods are virtual for the sake of testing.
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Creates a move loop.
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual scoped_ptr<X11MoveLoop> CreateMoveLoop(
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      X11MoveLoopDelegate* delegate);
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Finds the topmost X11 window at |screen_point| and returns it if it is
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Xdnd aware. Returns NULL otherwise.
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ::Window FindWindowFor(const gfx::Point& screen_point);
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Sends |xev| to |xid|, optionally short circuiting the round trip to the X
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // server.
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void SendXClientEvent(::Window xid, XEvent* xev);
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  enum SourceState {
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // |source_current_window_| will receive a drop once we receive an
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // XdndStatus from it.
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SOURCE_STATE_PENDING_DROP,
125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // The move looped will be ended once we receive XdndFinished from
127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // |source_current_window_|. We should not send XdndPosition to
128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // |source_current_window_| while in this state.
129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SOURCE_STATE_DROPPED,
130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // There is no drag in progress or there is a drag in progress and the
132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // user has not yet released the mouse.
133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SOURCE_STATE_OTHER,
134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  };
135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Processes a mouse move at |screen_point|.
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void ProcessMouseMove(const gfx::Point& screen_point,
138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        unsigned long event_time);
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Start timer to end the move loop if the target is too slow to respond after
141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // the mouse is released.
142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void StartEndMoveLoopTimer();
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Ends the move loop.
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void EndMoveLoop();
146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // When we receive an position x11 message, we need to translate that into
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the underlying aura::Window representation, as moves internal to the X11
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // window can cause internal drag leave and enter messages.
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void DragTranslate(const gfx::Point& root_window_location,
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     scoped_ptr<ui::OSExchangeData>* data,
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     scoped_ptr<ui::DropTargetEvent>* event,
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     aura::client::DragDropDelegate** delegate);
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called when we need to notify the current aura::Window that we're no
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // longer dragging over it.
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void NotifyDragLeave();
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Converts our bitfield of actions into an Atom that represents what action
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // we're most likely to take on drop.
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ::Atom DragOperationToAtom(int drag_operation);
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Converts a single action atom to a drag operation.
1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ui::DragDropTypes::DragOperation AtomToDragOperation(::Atom atom);
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // During the blocking StartDragAndDrop() call, this converts the views-style
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // |drag_operation_| bitfield into a vector of Atoms to offer to other
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // processes.
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector< ::Atom> GetOfferedDragOperations();
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This returns a representation of the data we're offering in this
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // drag. This is done to bypass an asynchronous roundtrip with the X11
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // server.
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::SelectionFormatMap GetFormatMap() const;
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handling XdndPosition can be paused while waiting for more data; this is
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // called either synchronously from OnXdndPosition, or asynchronously after
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // we've received data requested from the other window.
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void CompleteXdndPosition(::Window source_window,
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            const gfx::Point& screen_point);
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void SendXdndEnter(::Window dest_window);
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void SendXdndLeave(::Window dest_window);
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void SendXdndPosition(::Window dest_window,
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        const gfx::Point& screen_point,
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                        unsigned long event_time);
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void SendXdndDrop(::Window dest_window);
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Creates a widget for the user to drag around.
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void CreateDragWidget(const gfx::ImageSkia& image);
1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Returns true if |image| has any visible regions (defined as having a pixel
1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // with alpha > 32).
1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool IsValidDragImage(const gfx::ImageSkia& image);
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // A nested message loop that notifies this object of events through the
1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // X11MoveLoopDelegate interface.
1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<X11MoveLoop> move_loop_;
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Window* root_window_;
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Display* xdisplay_;
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ::Window xwindow_;
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ui::X11AtomCache atom_cache_;
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Target side information.
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  class X11DragContext;
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<X11DragContext> target_current_context_;
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The Aura window that is currently under the cursor. We need to manually
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // keep track of this because Windows will only call our drag enter method
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // once when the user enters the associated X Window. But inside that X
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Window there could be multiple aura windows, so we need to generate drag
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // enter events for them.
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* target_window_;
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Because Xdnd messages don't contain the position in messages other than
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the XdndPosition message, we must manually keep track of the last position
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // change.
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Point target_window_location_;
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Point target_window_root_location_;
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // In the Xdnd protocol, we aren't supposed to send another XdndPosition
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // message until we have received a confirming XdndStatus message.
2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool waiting_on_status_;
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // If we would send an XdndPosition message while we're waiting for an
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // XdndStatus response, we need to cache the latest details we'd send.
2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<std::pair<gfx::Point, unsigned long> > next_position_message_;
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Reprocesses the most recent mouse move event if the mouse has not moved
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // in a while in case the window stacking order has changed and
234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // |source_current_window_| needs to be updated.
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::OneShotTimer<DesktopDragDropClientAuraX11> repeat_mouse_move_timer_;
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // When the mouse is released, we need to wait for the last XdndStatus message
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // only if we have previously received a status message from
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // |source_current_window_|.
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool status_received_since_enter_;
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Source side information.
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::OSExchangeDataProviderAuraX11 const* source_provider_;
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ::Window source_current_window_;
245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SourceState source_state_;
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The current drag-drop client that has an active operation. Since we have
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // multiple root windows and multiple DesktopDragDropClientAuraX11 instances
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // it is important to maintain only one drag and drop operation at any time.
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static DesktopDragDropClientAuraX11* g_current_drag_drop_client;
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The operation bitfield as requested by StartDragAndDrop.
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int drag_operation_;
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We offer the other window a list of possible operations,
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // XdndActionsList. This is the requested action from the other window. This
2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // is DRAG_NONE if we haven't sent out an XdndPosition message yet, haven't
2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // yet received an XdndStatus or if the other window has told us that there's
2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // no action that we can agree on.
2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ui::DragDropTypes::DragOperation negotiated_operation_;
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Ends the move loop if the target is too slow to respond after the mouse is
263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // released.
264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::OneShotTimer<DesktopDragDropClientAuraX11> end_move_loop_timer_;
265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Widget that the user drags around. May be NULL.
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<Widget> drag_widget_;
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // The offset of |drag_widget_| relative to the mouse position.
2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  gfx::Vector2d drag_widget_offset_;
2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // We use these cursors while dragging.
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::NativeCursor grab_cursor_;
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::NativeCursor copy_grab_cursor_;
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::NativeCursor move_grab_cursor_;
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WeakPtrFactory<DesktopDragDropClientAuraX11> weak_ptr_factory_;
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientAuraX11);
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace views
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif  // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_AURAX11_H_
285