|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* vim: set ts=4 et sw=4 tw=80: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef nsDragService_h__ |
|
8 #define nsDragService_h__ |
|
9 |
|
10 #include "nsAutoPtr.h" |
|
11 #include "nsBaseDragService.h" |
|
12 #include "nsIObserver.h" |
|
13 #include "nsAutoRef.h" |
|
14 #include <gtk/gtk.h> |
|
15 |
|
16 class nsWindow; |
|
17 |
|
18 namespace mozilla { |
|
19 namespace gfx { |
|
20 class SourceSurface; |
|
21 } |
|
22 } |
|
23 |
|
24 #ifndef HAVE_NSGOBJECTREFTRAITS |
|
25 #define HAVE_NSGOBJECTREFTRAITS |
|
26 template <class T> |
|
27 class nsGObjectRefTraits : public nsPointerRefTraits<T> { |
|
28 public: |
|
29 static void Release(T *aPtr) { g_object_unref(aPtr); } |
|
30 static void AddRef(T *aPtr) { g_object_ref(aPtr); } |
|
31 }; |
|
32 #endif |
|
33 |
|
34 #ifndef HAVE_NSAUTOREFTRAITS_GTKWIDGET |
|
35 #define HAVE_NSAUTOREFTRAITS_GTKWIDGET |
|
36 template <> |
|
37 class nsAutoRefTraits<GtkWidget> : public nsGObjectRefTraits<GtkWidget> { }; |
|
38 #endif |
|
39 |
|
40 #ifndef HAVE_NSAUTOREFTRAITS_GDKDRAGCONTEXT |
|
41 #define HAVE_NSAUTOREFTRAITS_GDKDRAGCONTEXT |
|
42 template <> |
|
43 class nsAutoRefTraits<GdkDragContext> : |
|
44 public nsGObjectRefTraits<GdkDragContext> { }; |
|
45 #endif |
|
46 |
|
47 /** |
|
48 * Native GTK DragService wrapper |
|
49 */ |
|
50 |
|
51 class nsDragService : public nsBaseDragService, |
|
52 public nsIObserver |
|
53 { |
|
54 public: |
|
55 nsDragService(); |
|
56 virtual ~nsDragService(); |
|
57 |
|
58 NS_DECL_ISUPPORTS_INHERITED |
|
59 |
|
60 NS_DECL_NSIOBSERVER |
|
61 |
|
62 // nsIDragService |
|
63 NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, |
|
64 nsISupportsArray * anArrayTransferables, |
|
65 nsIScriptableRegion * aRegion, |
|
66 uint32_t aActionType); |
|
67 NS_IMETHOD StartDragSession(); |
|
68 NS_IMETHOD EndDragSession(bool aDoneDrag); |
|
69 |
|
70 // nsIDragSession |
|
71 NS_IMETHOD SetCanDrop (bool aCanDrop); |
|
72 NS_IMETHOD GetCanDrop (bool *aCanDrop); |
|
73 NS_IMETHOD GetNumDropItems (uint32_t * aNumItems); |
|
74 NS_IMETHOD GetData (nsITransferable * aTransferable, |
|
75 uint32_t aItemIndex); |
|
76 NS_IMETHOD IsDataFlavorSupported (const char *aDataFlavor, bool *_retval); |
|
77 |
|
78 // Methods called from nsWindow to handle responding to GTK drag |
|
79 // destination signals |
|
80 |
|
81 static nsDragService* GetInstance(); |
|
82 |
|
83 void TargetDataReceived (GtkWidget *aWidget, |
|
84 GdkDragContext *aContext, |
|
85 gint aX, |
|
86 gint aY, |
|
87 GtkSelectionData *aSelection_data, |
|
88 guint aInfo, |
|
89 guint32 aTime); |
|
90 |
|
91 gboolean ScheduleMotionEvent(nsWindow *aWindow, |
|
92 GdkDragContext *aDragContext, |
|
93 nsIntPoint aWindowPoint, |
|
94 guint aTime); |
|
95 void ScheduleLeaveEvent(); |
|
96 gboolean ScheduleDropEvent(nsWindow *aWindow, |
|
97 GdkDragContext *aDragContext, |
|
98 nsIntPoint aWindowPoint, |
|
99 guint aTime); |
|
100 |
|
101 nsWindow* GetMostRecentDestWindow() |
|
102 { |
|
103 return mScheduledTask == eDragTaskNone ? mTargetWindow |
|
104 : mPendingWindow; |
|
105 } |
|
106 |
|
107 // END PUBLIC API |
|
108 |
|
109 // These methods are public only so that they can be called from functions |
|
110 // with C calling conventions. They are called for drags started with the |
|
111 // invisible widget. |
|
112 void SourceEndDragSession(GdkDragContext *aContext, |
|
113 gint aResult); |
|
114 void SourceDataGet(GtkWidget *widget, |
|
115 GdkDragContext *context, |
|
116 GtkSelectionData *selection_data, |
|
117 guint32 aTime); |
|
118 |
|
119 // set the drag icon during drag-begin |
|
120 void SetDragIcon(GdkDragContext* aContext); |
|
121 |
|
122 private: |
|
123 |
|
124 // mScheduledTask indicates what signal has been received from GTK and |
|
125 // so what needs to be dispatched when the scheduled task is run. It is |
|
126 // eDragTaskNone when there is no task scheduled (but the |
|
127 // previous task may still not have finished running). |
|
128 enum DragTask { |
|
129 eDragTaskNone, |
|
130 eDragTaskMotion, |
|
131 eDragTaskLeave, |
|
132 eDragTaskDrop, |
|
133 eDragTaskSourceEnd |
|
134 }; |
|
135 DragTask mScheduledTask; |
|
136 // mTaskSource is the GSource id for the task that is either scheduled |
|
137 // or currently running. It is 0 if no task is scheduled or running. |
|
138 guint mTaskSource; |
|
139 |
|
140 // target/destination side vars |
|
141 // These variables keep track of the state of the current drag. |
|
142 |
|
143 // mPendingWindow, mPendingWindowPoint, mPendingDragContext, and |
|
144 // mPendingTime, carry information from the GTK signal that will be used |
|
145 // when the scheduled task is run. mPendingWindow and mPendingDragContext |
|
146 // will be nullptr if the scheduled task is eDragTaskLeave. |
|
147 nsRefPtr<nsWindow> mPendingWindow; |
|
148 nsIntPoint mPendingWindowPoint; |
|
149 nsCountedRef<GdkDragContext> mPendingDragContext; |
|
150 guint mPendingTime; |
|
151 |
|
152 // mTargetWindow and mTargetWindowPoint record the position of the last |
|
153 // eDragTaskMotion or eDragTaskDrop task that was run or is still running. |
|
154 // mTargetWindow is cleared once the drag has completed or left. |
|
155 nsRefPtr<nsWindow> mTargetWindow; |
|
156 nsIntPoint mTargetWindowPoint; |
|
157 // mTargetWidget and mTargetDragContext are set only while dispatching |
|
158 // motion or drop events. mTime records the corresponding timestamp. |
|
159 nsCountedRef<GtkWidget> mTargetWidget; |
|
160 nsCountedRef<GdkDragContext> mTargetDragContext; |
|
161 guint mTargetTime; |
|
162 |
|
163 // is it OK to drop on us? |
|
164 bool mCanDrop; |
|
165 |
|
166 // have we received our drag data? |
|
167 bool mTargetDragDataReceived; |
|
168 // last data received and its length |
|
169 void *mTargetDragData; |
|
170 uint32_t mTargetDragDataLen; |
|
171 // is the current target drag context contain a list? |
|
172 bool IsTargetContextList(void); |
|
173 // this will get the native data from the last target given a |
|
174 // specific flavor |
|
175 void GetTargetDragData(GdkAtom aFlavor); |
|
176 // this will reset all of the target vars |
|
177 void TargetResetData(void); |
|
178 |
|
179 // source side vars |
|
180 |
|
181 // the source of our drags |
|
182 GtkWidget *mHiddenWidget; |
|
183 // our source data items |
|
184 nsCOMPtr<nsISupportsArray> mSourceDataItems; |
|
185 |
|
186 nsCOMPtr<nsIScriptableRegion> mSourceRegion; |
|
187 |
|
188 // get a list of the sources in gtk's format |
|
189 GtkTargetList *GetSourceList(void); |
|
190 |
|
191 // attempts to create a semi-transparent drag image. Returns TRUE if |
|
192 // successful, FALSE if not |
|
193 bool SetAlphaPixmap(SourceSurface *aPixbuf, |
|
194 GdkDragContext *aContext, |
|
195 int32_t aXOffset, |
|
196 int32_t aYOffset, |
|
197 const nsIntRect &dragRect); |
|
198 |
|
199 gboolean Schedule(DragTask aTask, nsWindow *aWindow, |
|
200 GdkDragContext *aDragContext, |
|
201 nsIntPoint aWindowPoint, guint aTime); |
|
202 |
|
203 // Callback for g_idle_add_full() to run mScheduledTask. |
|
204 static gboolean TaskDispatchCallback(gpointer data); |
|
205 gboolean RunScheduledTask(); |
|
206 void UpdateDragAction(); |
|
207 void DispatchMotionEvents(); |
|
208 void ReplyToDragMotion(); |
|
209 gboolean DispatchDropEvent(); |
|
210 }; |
|
211 |
|
212 #endif // nsDragService_h__ |
|
213 |