Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/widget/gtk/nsDragService.h
Line
Count
Source (jump to first uncovered line)
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 "mozilla/RefPtr.h"
11
#include "nsBaseDragService.h"
12
#include "nsIObserver.h"
13
#include "nsAutoRef.h"
14
#include <gtk/gtk.h>
15
16
class nsWindow;
17
class nsWaylandDragContext;
18
19
namespace mozilla {
20
namespace gfx {
21
class SourceSurface;
22
}
23
}
24
25
#ifndef HAVE_NSGOBJECTREFTRAITS
26
#define HAVE_NSGOBJECTREFTRAITS
27
template <class T>
28
class nsGObjectRefTraits : public nsPointerRefTraits<T> {
29
public:
30
0
    static void Release(T *aPtr) { g_object_unref(aPtr); }
Unexecuted instantiation: nsGObjectRefTraits<_GdkDragContext>::Release(_GdkDragContext*)
Unexecuted instantiation: nsGObjectRefTraits<_GtkWidget>::Release(_GtkWidget*)
31
0
    static void AddRef(T *aPtr) { g_object_ref(aPtr); }
Unexecuted instantiation: nsGObjectRefTraits<_GdkDragContext>::AddRef(_GdkDragContext*)
Unexecuted instantiation: nsGObjectRefTraits<_GtkWidget>::AddRef(_GtkWidget*)
32
};
33
#endif
34
35
#ifndef HAVE_NSAUTOREFTRAITS_GTKWIDGET
36
#define HAVE_NSAUTOREFTRAITS_GTKWIDGET
37
template <>
38
class nsAutoRefTraits<GtkWidget> : public nsGObjectRefTraits<GtkWidget> { };
39
#endif
40
41
#ifndef HAVE_NSAUTOREFTRAITS_GDKDRAGCONTEXT
42
#define HAVE_NSAUTOREFTRAITS_GDKDRAGCONTEXT
43
template <>
44
class nsAutoRefTraits<GdkDragContext> :
45
    public nsGObjectRefTraits<GdkDragContext> { };
46
#endif
47
48
/**
49
 * Native GTK DragService wrapper
50
 */
51
52
class nsDragService final : public nsBaseDragService,
53
                            public nsIObserver
54
{
55
public:
56
    nsDragService();
57
58
    NS_DECL_ISUPPORTS_INHERITED
59
60
    NS_DECL_NSIOBSERVER
61
62
    // nsBaseDragService
63
    virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables,
64
                                           const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
65
                                           uint32_t aActionType) override;
66
    // nsIDragService
67
    NS_IMETHOD InvokeDragSession (nsINode *aDOMNode,
68
                                  const nsACString& aPrincipalURISpec,
69
                                  nsIArray * anArrayTransferables,
70
                                  uint32_t aActionType,
71
                                  nsContentPolicyType aContentPolicyType) override;
72
    NS_IMETHOD StartDragSession() override;
73
    NS_IMETHOD EndDragSession(bool aDoneDrag, uint32_t aKeyModifiers) override;
74
75
    // nsIDragSession
76
    NS_IMETHOD SetCanDrop            (bool             aCanDrop) override;
77
    NS_IMETHOD GetCanDrop            (bool            *aCanDrop) override;
78
    NS_IMETHOD GetNumDropItems       (uint32_t * aNumItems) override;
79
    NS_IMETHOD GetData               (nsITransferable * aTransferable,
80
                                      uint32_t aItemIndex) override;
81
    NS_IMETHOD IsDataFlavorSupported (const char *aDataFlavor,
82
                                      bool *_retval) override;
83
84
     NS_IMETHOD UpdateDragEffect() override;
85
86
    // Methods called from nsWindow to handle responding to GTK drag
87
    // destination signals
88
89
    static already_AddRefed<nsDragService> GetInstance();
90
91
    void TargetDataReceived          (GtkWidget         *aWidget,
92
                                      GdkDragContext    *aContext,
93
                                      gint               aX,
94
                                      gint               aY,
95
                                      GtkSelectionData  *aSelection_data,
96
                                      guint              aInfo,
97
                                      guint32            aTime);
98
99
    gboolean ScheduleMotionEvent(nsWindow *aWindow,
100
                                 GdkDragContext *aDragContext,
101
                                 nsWaylandDragContext* aPendingWaylandDragContext,
102
                                 mozilla::LayoutDeviceIntPoint aWindowPoint,
103
                                 guint aTime);
104
    void ScheduleLeaveEvent();
105
    gboolean ScheduleDropEvent(nsWindow *aWindow,
106
                               GdkDragContext *aDragContext,
107
                               nsWaylandDragContext* aPendingWaylandDragContext,
108
                               mozilla::LayoutDeviceIntPoint aWindowPoint,
109
                               guint aTime);
110
111
    nsWindow* GetMostRecentDestWindow()
112
0
    {
113
0
        return mScheduledTask == eDragTaskNone ? mTargetWindow
114
0
            : mPendingWindow;
115
0
    }
116
117
    //  END PUBLIC API
118
119
    // These methods are public only so that they can be called from functions
120
    // with C calling conventions.  They are called for drags started with the
121
    // invisible widget.
122
    void           SourceEndDragSession(GdkDragContext *aContext,
123
                                        gint            aResult);
124
    void           SourceDataGet(GtkWidget        *widget,
125
                                 GdkDragContext   *context,
126
                                 GtkSelectionData *selection_data,
127
                                 guint32           aTime);
128
129
    // set the drag icon during drag-begin
130
    void SetDragIcon(GdkDragContext* aContext);
131
132
protected:
133
    virtual ~nsDragService();
134
135
private:
136
137
    // mScheduledTask indicates what signal has been received from GTK and
138
    // so what needs to be dispatched when the scheduled task is run.  It is
139
    // eDragTaskNone when there is no task scheduled (but the
140
    // previous task may still not have finished running).
141
    enum DragTask {
142
        eDragTaskNone,
143
        eDragTaskMotion,
144
        eDragTaskLeave,
145
        eDragTaskDrop,
146
        eDragTaskSourceEnd
147
    };
148
    DragTask mScheduledTask;
149
    // mTaskSource is the GSource id for the task that is either scheduled
150
    // or currently running.  It is 0 if no task is scheduled or running.
151
    guint mTaskSource;
152
153
    // target/destination side vars
154
    // These variables keep track of the state of the current drag.
155
156
    // mPendingWindow, mPendingWindowPoint, mPendingDragContext, and
157
    // mPendingTime, carry information from the GTK signal that will be used
158
    // when the scheduled task is run.  mPendingWindow and mPendingDragContext
159
    // will be nullptr if the scheduled task is eDragTaskLeave.
160
    RefPtr<nsWindow> mPendingWindow;
161
    mozilla::LayoutDeviceIntPoint mPendingWindowPoint;
162
    nsCountedRef<GdkDragContext> mPendingDragContext;
163
#ifdef MOZ_WAYLAND
164
    RefPtr<nsWaylandDragContext> mPendingWaylandDragContext;
165
#endif
166
    guint mPendingTime;
167
168
    // mTargetWindow and mTargetWindowPoint record the position of the last
169
    // eDragTaskMotion or eDragTaskDrop task that was run or is still running.
170
    // mTargetWindow is cleared once the drag has completed or left.
171
    RefPtr<nsWindow> mTargetWindow;
172
    mozilla::LayoutDeviceIntPoint mTargetWindowPoint;
173
    // mTargetWidget and mTargetDragContext are set only while dispatching
174
    // motion or drop events.  mTime records the corresponding timestamp.
175
    nsCountedRef<GtkWidget> mTargetWidget;
176
    nsCountedRef<GdkDragContext> mTargetDragContext;
177
#ifdef MOZ_WAYLAND
178
    RefPtr<nsWaylandDragContext> mTargetWaylandDragContext;
179
#endif
180
    // mTargetDragContextForRemote is set while waiting for a reply from
181
    // a child process.
182
    nsCountedRef<GdkDragContext> mTargetDragContextForRemote;
183
#ifdef MOZ_WAYLAND
184
    RefPtr<nsWaylandDragContext> mTargetWaylandDragContextForRemote;
185
#endif
186
    guint           mTargetTime;
187
188
    // is it OK to drop on us?
189
    bool            mCanDrop;
190
191
    // have we received our drag data?
192
    bool            mTargetDragDataReceived;
193
    // last data received and its length
194
    void           *mTargetDragData;
195
    uint32_t        mTargetDragDataLen;
196
    // is the current target drag context contain a list?
197
    bool           IsTargetContextList(void);
198
    // this will get the native data from the last target given a
199
    // specific flavor
200
    void           GetTargetDragData(GdkAtom aFlavor);
201
    // this will reset all of the target vars
202
    void           TargetResetData(void);
203
204
    // source side vars
205
206
    // the source of our drags
207
    GtkWidget     *mHiddenWidget;
208
    // our source data items
209
    nsCOMPtr<nsIArray> mSourceDataItems;
210
211
    // get a list of the sources in gtk's format
212
    GtkTargetList *GetSourceList(void);
213
214
    // attempts to create a semi-transparent drag image. Returns TRUE if
215
    // successful, FALSE if not
216
    bool SetAlphaPixmap(SourceSurface *aPixbuf,
217
                        GdkDragContext  *aContext,
218
                        int32_t          aXOffset,
219
                        int32_t          aYOffset,
220
                        const mozilla::LayoutDeviceIntRect &dragRect);
221
222
    gboolean Schedule(DragTask aTask, nsWindow *aWindow,
223
                      GdkDragContext *aDragContext,
224
                      nsWaylandDragContext* aPendingWaylandDragContext,
225
                      mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime);
226
227
    // Callback for g_idle_add_full() to run mScheduledTask.
228
    static gboolean TaskDispatchCallback(gpointer data);
229
    gboolean RunScheduledTask();
230
    void UpdateDragAction();
231
    void DispatchMotionEvents();
232
    void ReplyToDragMotion(GdkDragContext* aDragContext);
233
#ifdef MOZ_WAYLAND
234
    void ReplyToDragMotion(nsWaylandDragContext* aDragContext);
235
#endif
236
    gboolean DispatchDropEvent();
237
    static uint32_t GetCurrentModifiers();
238
};
239
240
#endif // nsDragService_h__