michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim: set ts=4 et sw=4 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsDragService_h__ michael@0: #define nsDragService_h__ michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "nsBaseDragService.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsAutoRef.h" michael@0: #include michael@0: michael@0: class nsWindow; michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: class SourceSurface; michael@0: } michael@0: } michael@0: michael@0: #ifndef HAVE_NSGOBJECTREFTRAITS michael@0: #define HAVE_NSGOBJECTREFTRAITS michael@0: template michael@0: class nsGObjectRefTraits : public nsPointerRefTraits { michael@0: public: michael@0: static void Release(T *aPtr) { g_object_unref(aPtr); } michael@0: static void AddRef(T *aPtr) { g_object_ref(aPtr); } michael@0: }; michael@0: #endif michael@0: michael@0: #ifndef HAVE_NSAUTOREFTRAITS_GTKWIDGET michael@0: #define HAVE_NSAUTOREFTRAITS_GTKWIDGET michael@0: template <> michael@0: class nsAutoRefTraits : public nsGObjectRefTraits { }; michael@0: #endif michael@0: michael@0: #ifndef HAVE_NSAUTOREFTRAITS_GDKDRAGCONTEXT michael@0: #define HAVE_NSAUTOREFTRAITS_GDKDRAGCONTEXT michael@0: template <> michael@0: class nsAutoRefTraits : michael@0: public nsGObjectRefTraits { }; michael@0: #endif michael@0: michael@0: /** michael@0: * Native GTK DragService wrapper michael@0: */ michael@0: michael@0: class nsDragService : public nsBaseDragService, michael@0: public nsIObserver michael@0: { michael@0: public: michael@0: nsDragService(); michael@0: virtual ~nsDragService(); michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: // nsIDragService michael@0: NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, michael@0: nsISupportsArray * anArrayTransferables, michael@0: nsIScriptableRegion * aRegion, michael@0: uint32_t aActionType); michael@0: NS_IMETHOD StartDragSession(); michael@0: NS_IMETHOD EndDragSession(bool aDoneDrag); michael@0: michael@0: // nsIDragSession michael@0: NS_IMETHOD SetCanDrop (bool aCanDrop); michael@0: NS_IMETHOD GetCanDrop (bool *aCanDrop); michael@0: NS_IMETHOD GetNumDropItems (uint32_t * aNumItems); michael@0: NS_IMETHOD GetData (nsITransferable * aTransferable, michael@0: uint32_t aItemIndex); michael@0: NS_IMETHOD IsDataFlavorSupported (const char *aDataFlavor, bool *_retval); michael@0: michael@0: // Methods called from nsWindow to handle responding to GTK drag michael@0: // destination signals michael@0: michael@0: static nsDragService* GetInstance(); michael@0: michael@0: void TargetDataReceived (GtkWidget *aWidget, michael@0: GdkDragContext *aContext, michael@0: gint aX, michael@0: gint aY, michael@0: GtkSelectionData *aSelection_data, michael@0: guint aInfo, michael@0: guint32 aTime); michael@0: michael@0: gboolean ScheduleMotionEvent(nsWindow *aWindow, michael@0: GdkDragContext *aDragContext, michael@0: nsIntPoint aWindowPoint, michael@0: guint aTime); michael@0: void ScheduleLeaveEvent(); michael@0: gboolean ScheduleDropEvent(nsWindow *aWindow, michael@0: GdkDragContext *aDragContext, michael@0: nsIntPoint aWindowPoint, michael@0: guint aTime); michael@0: michael@0: nsWindow* GetMostRecentDestWindow() michael@0: { michael@0: return mScheduledTask == eDragTaskNone ? mTargetWindow michael@0: : mPendingWindow; michael@0: } michael@0: michael@0: // END PUBLIC API michael@0: michael@0: // These methods are public only so that they can be called from functions michael@0: // with C calling conventions. They are called for drags started with the michael@0: // invisible widget. michael@0: void SourceEndDragSession(GdkDragContext *aContext, michael@0: gint aResult); michael@0: void SourceDataGet(GtkWidget *widget, michael@0: GdkDragContext *context, michael@0: GtkSelectionData *selection_data, michael@0: guint32 aTime); michael@0: michael@0: // set the drag icon during drag-begin michael@0: void SetDragIcon(GdkDragContext* aContext); michael@0: michael@0: private: michael@0: michael@0: // mScheduledTask indicates what signal has been received from GTK and michael@0: // so what needs to be dispatched when the scheduled task is run. It is michael@0: // eDragTaskNone when there is no task scheduled (but the michael@0: // previous task may still not have finished running). michael@0: enum DragTask { michael@0: eDragTaskNone, michael@0: eDragTaskMotion, michael@0: eDragTaskLeave, michael@0: eDragTaskDrop, michael@0: eDragTaskSourceEnd michael@0: }; michael@0: DragTask mScheduledTask; michael@0: // mTaskSource is the GSource id for the task that is either scheduled michael@0: // or currently running. It is 0 if no task is scheduled or running. michael@0: guint mTaskSource; michael@0: michael@0: // target/destination side vars michael@0: // These variables keep track of the state of the current drag. michael@0: michael@0: // mPendingWindow, mPendingWindowPoint, mPendingDragContext, and michael@0: // mPendingTime, carry information from the GTK signal that will be used michael@0: // when the scheduled task is run. mPendingWindow and mPendingDragContext michael@0: // will be nullptr if the scheduled task is eDragTaskLeave. michael@0: nsRefPtr mPendingWindow; michael@0: nsIntPoint mPendingWindowPoint; michael@0: nsCountedRef mPendingDragContext; michael@0: guint mPendingTime; michael@0: michael@0: // mTargetWindow and mTargetWindowPoint record the position of the last michael@0: // eDragTaskMotion or eDragTaskDrop task that was run or is still running. michael@0: // mTargetWindow is cleared once the drag has completed or left. michael@0: nsRefPtr mTargetWindow; michael@0: nsIntPoint mTargetWindowPoint; michael@0: // mTargetWidget and mTargetDragContext are set only while dispatching michael@0: // motion or drop events. mTime records the corresponding timestamp. michael@0: nsCountedRef mTargetWidget; michael@0: nsCountedRef mTargetDragContext; michael@0: guint mTargetTime; michael@0: michael@0: // is it OK to drop on us? michael@0: bool mCanDrop; michael@0: michael@0: // have we received our drag data? michael@0: bool mTargetDragDataReceived; michael@0: // last data received and its length michael@0: void *mTargetDragData; michael@0: uint32_t mTargetDragDataLen; michael@0: // is the current target drag context contain a list? michael@0: bool IsTargetContextList(void); michael@0: // this will get the native data from the last target given a michael@0: // specific flavor michael@0: void GetTargetDragData(GdkAtom aFlavor); michael@0: // this will reset all of the target vars michael@0: void TargetResetData(void); michael@0: michael@0: // source side vars michael@0: michael@0: // the source of our drags michael@0: GtkWidget *mHiddenWidget; michael@0: // our source data items michael@0: nsCOMPtr mSourceDataItems; michael@0: michael@0: nsCOMPtr mSourceRegion; michael@0: michael@0: // get a list of the sources in gtk's format michael@0: GtkTargetList *GetSourceList(void); michael@0: michael@0: // attempts to create a semi-transparent drag image. Returns TRUE if michael@0: // successful, FALSE if not michael@0: bool SetAlphaPixmap(SourceSurface *aPixbuf, michael@0: GdkDragContext *aContext, michael@0: int32_t aXOffset, michael@0: int32_t aYOffset, michael@0: const nsIntRect &dragRect); michael@0: michael@0: gboolean Schedule(DragTask aTask, nsWindow *aWindow, michael@0: GdkDragContext *aDragContext, michael@0: nsIntPoint aWindowPoint, guint aTime); michael@0: michael@0: // Callback for g_idle_add_full() to run mScheduledTask. michael@0: static gboolean TaskDispatchCallback(gpointer data); michael@0: gboolean RunScheduledTask(); michael@0: void UpdateDragAction(); michael@0: void DispatchMotionEvents(); michael@0: void ReplyToDragMotion(); michael@0: gboolean DispatchDropEvent(); michael@0: }; michael@0: michael@0: #endif // nsDragService_h__ michael@0: