/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1998-1999 Tor Lillqvist
+ * Copyright (C) 1998-2002 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
- * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#include "config.h"
+#include <string.h>
+
+/* #define OLE2_DND */
#define INITGUID
-#include <string.h>
+#include "gdkdnd.h"
+#include "gdkproperty.h"
+#include "gdkinternals.h"
+#include "gdkprivate-win32.h"
+#ifdef OLE2_DND
#include <ole2.h>
+#else
+#include <objbase.h>
+#endif
+
#include <shlobj.h>
#include <shlguid.h>
#include <gdk/gdk.h>
-#include "gdkx.h"
-typedef struct _GdkDragContextPrivate GdkDragContextPrivate;
+typedef struct _GdkDragContextPrivateWin32 GdkDragContextPrivateWin32;
typedef enum {
GDK_DRAG_STATUS_DRAG,
#ifdef OLE2_DND
-HRESULT STDMETHODCALLTYPE
- m_query_interface_target (IDropTarget __RPC_FAR *This,
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
-
-ULONG STDMETHODCALLTYPE
- m_add_ref_target (IDropTarget __RPC_FAR *This);
-
-ULONG STDMETHODCALLTYPE
- m_release_target (IDropTarget __RPC_FAR *This);
-
-HRESULT STDMETHODCALLTYPE
- m_drag_enter (IDropTarget __RPC_FAR *This,
- /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
- /* [in] */ DWORD grfKeyState,
- /* [in] */ POINTL pt,
- /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
-
-HRESULT STDMETHODCALLTYPE
- m_drag_over (IDropTarget __RPC_FAR *This,
- /* [in] */ DWORD grfKeyState,
- /* [in] */ POINTL pt,
- /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
-
-HRESULT STDMETHODCALLTYPE
- m_drag_leave (IDropTarget __RPC_FAR *This);
-
-HRESULT STDMETHODCALLTYPE
- m_drop (IDropTarget __RPC_FAR *This,
- /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
- /* [in] */ DWORD grfKeyState,
- /* [in] */ POINTL pt,
- /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
-
-HRESULT STDMETHODCALLTYPE
- m_query_interface_source (IDropSource __RPC_FAR *This,
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
-
-ULONG STDMETHODCALLTYPE
- m_add_ref_source (IDropSource __RPC_FAR *This);
-
-ULONG STDMETHODCALLTYPE
- m_release_source (IDropSource __RPC_FAR *This);
-
-HRESULT STDMETHODCALLTYPE
- m_query_continue_drag (IDropSource __RPC_FAR *This,
- /* [in] */ BOOL fEscapePressed,
- /* [in] */ DWORD grfKeyState);
-HRESULT STDMETHODCALLTYPE
- m_give_feedback (IDropSource __RPC_FAR *This,
- /* [in] */ DWORD dwEffect);
+#define PRINT_GUID(guid) \
+ g_print ("guid = %.08x-%.04x-%.04x-%.02x%.02x-%.02x%.02x%.02x%.02x%.02x%.02x", \
+ ((gulong *) guid)[0], \
+ ((gushort *) guid)[2], \
+ ((gushort *) guid)[3], \
+ ((guchar *) guid)[8], \
+ ((guchar *) guid)[9], \
+ ((guchar *) guid)[10], \
+ ((guchar *) guid)[11], \
+ ((guchar *) guid)[12], \
+ ((guchar *) guid)[13], \
+ ((guchar *) guid)[14], \
+ ((guchar *) guid)[15]);
+
+
+static FORMATETC *formats;
+static int nformats;
#endif /* OLE2_DND */
/* Structure that holds information about a drag in progress.
* this is used on both source and destination sides.
*/
-struct _GdkDragContextPrivate {
- GdkDragContext context;
-
- guint ref_count;
+struct _GdkDragContextPrivateWin32 {
+ gint ref_count;
guint16 last_x; /* Coordinates from last event */
guint16 last_y;
- HWND dest_xid;
- guint drag_status; /* Current status of drag */
+ HWND dest_xid;
+ guint drag_status; /* Current status of drag */
};
+#define GDK_DRAG_CONTEXT_PRIVATE_DATA(context) ((GdkDragContextPrivateWin32 *) GDK_DRAG_CONTEXT (context)->windowing_data)
+
GdkDragContext *current_dest_drag = NULL;
-/* Drag Contexts */
+static void gdk_drag_context_init (GdkDragContext *dragcontext);
+static void gdk_drag_context_class_init (GdkDragContextClass *klass);
+static void gdk_drag_context_finalize (GObject *object);
+static gpointer parent_class = NULL;
static GList *contexts;
+GType
+gdk_drag_context_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (GdkDragContextClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gdk_drag_context_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GdkDragContext),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gdk_drag_context_init,
+ };
+
+ object_type = g_type_register_static (G_TYPE_OBJECT,
+ "GdkDragContext",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+gdk_drag_context_init (GdkDragContext *dragcontext)
+{
+ GdkDragContextPrivateWin32 *private = g_new0 (GdkDragContextPrivateWin32, 1);
+
+ dragcontext->windowing_data = private;
+ private->ref_count = 1;
+
+ contexts = g_list_prepend (contexts, dragcontext);
+}
+
+static void
+gdk_drag_context_class_init (GdkDragContextClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = gdk_drag_context_finalize;
+}
+
+static void
+gdk_drag_context_finalize (GObject *object)
+{
+ GdkDragContext *context = GDK_DRAG_CONTEXT (object);
+ GdkDragContextPrivateWin32 *private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
+
+ g_list_free (context->targets);
+
+ if (context->source_window)
+ {
+ gdk_window_unref (context->source_window);
+ }
+
+ if (context->dest_window)
+ gdk_window_unref (context->dest_window);
+
+ contexts = g_list_remove (contexts, context);
+
+ g_free (private);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/* Drag Contexts */
+
GdkDragContext *
-gdk_drag_context_new (void)
+gdk_drag_context_new (void)
{
- GdkDragContextPrivate *result;
+ return g_object_new (gdk_drag_context_get_type (), NULL);
+}
- result = g_new0 (GdkDragContextPrivate, 1);
+void
+gdk_drag_context_ref (GdkDragContext *context)
+{
+ g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
- result->ref_count = 1;
+ GDK_NOTE (DND, g_print ("gdk_drag_context_ref: %p %d\n", context, G_OBJECT(context)->ref_count));
+
+ g_object_ref (context);
+}
- contexts = g_list_prepend (contexts, result);
+void
+gdk_drag_context_unref (GdkDragContext *context)
+{
+ g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
- return (GdkDragContext *)result;
+ GDK_NOTE (DND, g_print ("gdk_drag_context_unref: %p %d\n", context, G_OBJECT(context)->ref_count));
+ g_object_unref (context);
+}
+
+static GdkDragContext *
+gdk_drag_context_find (gboolean is_source,
+ GdkWindow *source,
+ GdkWindow *dest)
+{
+ GList *tmp_list = contexts;
+ GdkDragContext *context;
+ GdkDragContextPrivateWin32 *private;
+
+ while (tmp_list)
+ {
+ context = (GdkDragContext *)tmp_list->data;
+ private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
+
+ if ((!context->is_source == !is_source) &&
+ ((source == NULL) || (context->source_window && (context->source_window == source))) &&
+ ((dest == NULL) || (context->dest_window && (context->dest_window == dest))))
+ return context;
+
+ tmp_list = tmp_list->next;
+ }
+
+ return NULL;
}
-#if OLE2_DND
typedef struct {
+#ifdef OLE2_DND
IDropTarget idt;
+#endif
GdkDragContext *context;
} target_drag_context;
typedef struct {
+#ifdef OLE2_DND
IDropSource ids;
+#endif
GdkDragContext *context;
} source_drag_context;
-HRESULT STDMETHODCALLTYPE
-m_query_interface_target (IDropTarget __RPC_FAR *This,
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
+#ifdef OLE2_DND
+
+typedef struct {
+ IDataObject ido;
+ int ref_count;
+} data_object;
+
+typedef struct {
+ IEnumFORMATETC ief;
+ int ref_count;
+ int ix;
+} enum_formats;
+
+static enum_formats *enum_formats_new (void);
+
+static ULONG STDMETHODCALLTYPE
+idroptarget_addref (LPDROPTARGET This)
{
- GDK_NOTE (DND, g_print ("m_query_interface_target\n"));
+ target_drag_context *ctx = (target_drag_context *) This;
+ GdkDragContextPrivateWin32 *private = GDK_DRAG_CONTEXT_PRIVATE_DATA (ctx->context);
+ int ref_count = ++private->ref_count;
+
+ gdk_drag_context_ref (ctx->context);
+ GDK_NOTE (DND, g_print ("idroptarget_addref %#x %d\n", This, ref_count));
+
+ return ref_count;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idroptarget_queryinterface (LPDROPTARGET This,
+ REFIID riid,
+ LPVOID *ppvObject)
+{
+ GDK_NOTE (DND, g_print ("idroptarget_queryinterface %#x\n", This));
*ppvObject = NULL;
- g_print ("riid = %.08x-%.04x-%.04x-%.02x%.02x-%.02x%.02x%.02x%.02x%.02x%.02x",
- ((gulong *) riid)[0],
- ((gushort *) riid)[2],
- ((gushort *) riid)[3],
- ((guchar *) riid)[8],
- ((guchar *) riid)[9],
- ((guchar *) riid)[10],
- ((guchar *) riid)[11],
- ((guchar *) riid)[12],
- ((guchar *) riid)[13],
- ((guchar *) riid)[14],
- ((guchar *) riid)[15]);
+ PRINT_GUID (riid);
+
if (IsEqualGUID (riid, &IID_IUnknown))
{
- m_add_ref_target (This);
- *ppvObject = This;
g_print ("...IUnknown\n");
+ idroptarget_addref (This);
+ *ppvObject = This;
return S_OK;
}
else if (IsEqualGUID (riid, &IID_IDropTarget))
{
- m_add_ref_target (This);
- *ppvObject = This;
g_print ("...IDropTarget\n");
+ idroptarget_addref (This);
+ *ppvObject = This;
return S_OK;
}
else
}
}
-ULONG STDMETHODCALLTYPE
-m_add_ref_target (IDropTarget __RPC_FAR *This)
+static ULONG STDMETHODCALLTYPE
+idroptarget_release (LPDROPTARGET This)
{
target_drag_context *ctx = (target_drag_context *) This;
- GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context;
+ GdkDragContextPrivateWin32 *private = GDK_DRAG_CONTEXT_PRIVATE_DATA (ctx->context);
+ int ref_count = --private->ref_count;
+
+ gdk_drag_context_unref (ctx->context);
+ GDK_NOTE (DND, g_print ("idroptarget_release %#x %d\n", This, ref_count));
+
+ if (ref_count == 0)
+ g_free (This);
+
+ return ref_count;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idroptarget_dragenter (LPDROPTARGET This,
+ LPDATAOBJECT pDataObj,
+ DWORD grfKeyState,
+ POINTL pt,
+ LPDWORD pdwEffect)
+{
+ GDK_NOTE (DND, g_print ("idroptarget_dragenter %#x\n", This));
+
+ return E_UNEXPECTED;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idroptarget_dragover (LPDROPTARGET This,
+ DWORD grfKeyState,
+ POINTL pt,
+ LPDWORD pdwEffect)
+{
+ GDK_NOTE (DND, g_print ("idroptarget_dragover %#x\n", This));
+
+ return E_UNEXPECTED;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idroptarget_dragleave (LPDROPTARGET This)
+{
+ GDK_NOTE (DND, g_print ("idroptarget_dragleave %#x\n", This));
+
+ return E_UNEXPECTED;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idroptarget_drop (LPDROPTARGET This,
+ LPDATAOBJECT pDataObj,
+ DWORD grfKeyState,
+ POINTL pt,
+ LPDWORD pdwEffect)
+{
+ GDK_NOTE (DND, g_print ("idroptarget_drop %#x\n", This));
+
+ return E_UNEXPECTED;
+}
+
+static ULONG STDMETHODCALLTYPE
+idropsource_addref (LPDROPSOURCE This)
+{
+ source_drag_context *ctx = (source_drag_context *) This;
+ GdkDragContextPrivateWin32 *private = GDK_DRAG_CONTEXT_PRIVATE_DATA (ctx->context);
- GDK_NOTE (DND, g_print ("m_add_ref_target\n"));
gdk_drag_context_ref (ctx->context);
+ GDK_NOTE (DND, g_print ("idropsource_addref %#x %d\n",
+ This, private->ref_count));
return private->ref_count;
}
-ULONG STDMETHODCALLTYPE
-m_release_target (IDropTarget __RPC_FAR *This)
+static HRESULT STDMETHODCALLTYPE
+idropsource_queryinterface (LPDROPSOURCE This,
+ REFIID riid,
+ LPVOID *ppvObject)
{
- target_drag_context *ctx = (target_drag_context *) This;
- GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context;
+ GDK_NOTE (DND, g_print ("idropsource_queryinterface %#x\n", This));
- GDK_NOTE (DND, g_print ("m_release_target\n"));
- gdk_drag_context_unref (ctx->context);
+ *ppvObject = NULL;
- if (private->ref_count == 1)
+ PRINT_GUID (riid);
+ if (IsEqualGUID (riid, &IID_IUnknown))
+ {
+ g_print ("...IUnknown\n");
+ idropsource_addref (This);
+ *ppvObject = This;
+ return S_OK;
+ }
+ else if (IsEqualGUID (riid, &IID_IDropSource))
{
- gdk_drag_context_unref (ctx->context);
- return 0;
+ g_print ("...IDropSource\n");
+ idropsource_addref (This);
+ *ppvObject = This;
+ return S_OK;
}
else
- return private->ref_count - 1;
+ {
+ g_print ("...Huh?\n");
+ return E_NOINTERFACE;
+ }
}
-HRESULT STDMETHODCALLTYPE
-m_drag_enter (IDropTarget __RPC_FAR *This,
- /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
- /* [in] */ DWORD grfKeyState,
- /* [in] */ POINTL pt,
- /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
+static ULONG STDMETHODCALLTYPE
+idropsource_release (LPDROPSOURCE This)
{
- GDK_NOTE (DND, g_print ("m_drag_enter\n"));
+ source_drag_context *ctx = (source_drag_context *) This;
+ GdkDragContextPrivateWin32 *private = GDK_DRAG_CONTEXT_PRIVATE_DATA (ctx->context);
+ int ref_count = --private->ref_count;
+
+ gdk_drag_context_unref (ctx->context);
+ GDK_NOTE (DND, g_print ("idropsource_release %#x %d\n", This, ref_count));
+
+ if (ref_count == 0)
+ g_free (This);
+
+ return ref_count;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idropsource_querycontinuedrag (LPDROPSOURCE This,
+ BOOL fEscapePressed,
+ DWORD grfKeyState)
+{
+ GDK_NOTE (DND, g_print ("idropsource_querycontinuedrag %#x\n", This));
+
+ return E_UNEXPECTED;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idropsource_givefeedback (LPDROPSOURCE This,
+ DWORD dwEffect)
+{
+ GDK_NOTE (DND, g_print ("idropsource_givefeedback %#x\n", This));
+
return E_UNEXPECTED;
}
-HRESULT STDMETHODCALLTYPE
-m_drag_over (IDropTarget __RPC_FAR *This,
- /* [in] */ DWORD grfKeyState,
- /* [in] */ POINTL pt,
- /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
+static ULONG STDMETHODCALLTYPE
+idataobject_addref (LPDATAOBJECT This)
+{
+ data_object *dobj = (data_object *) This;
+ int ref_count = ++dobj->ref_count;
+
+ GDK_NOTE (DND, g_print ("idataobject_addref %#x %d\n", This, ref_count));
+
+ return ref_count;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idataobject_queryinterface (LPDATAOBJECT This,
+ REFIID riid,
+ LPVOID *ppvObject)
+{
+ GDK_NOTE (DND, g_print ("idataobject_queryinterface %#x\n", This));
+
+ *ppvObject = NULL;
+
+ PRINT_GUID (riid);
+ if (IsEqualGUID (riid, &IID_IUnknown))
+ {
+ g_print ("...IUnknown\n");
+ idataobject_addref (This);
+ *ppvObject = This;
+ return S_OK;
+ }
+ else if (IsEqualGUID (riid, &IID_IDataObject))
+ {
+ g_print ("...IDataObject\n");
+ idataobject_addref (This);
+ *ppvObject = This;
+ return S_OK;
+ }
+ else
+ {
+ g_print ("...Huh?\n");
+ return E_NOINTERFACE;
+ }
+}
+
+static ULONG STDMETHODCALLTYPE
+idataobject_release (LPDATAOBJECT This)
+{
+ data_object *dobj = (data_object *) This;
+ int ref_count = --dobj->ref_count;
+
+ GDK_NOTE (DND, g_print ("idataobject_release %#x %d\n", This, ref_count));
+
+ if (ref_count == 0)
+ g_free (This);
+
+ return ref_count;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idataobject_getdata (LPDATAOBJECT This,
+ LPFORMATETC pFormatEtc,
+ LPSTGMEDIUM pMedium)
{
- GDK_NOTE (DND, g_print ("m_drag_over\n"));
+ GDK_NOTE (DND, g_print ("idataobject_getdata %#x\n", This));
+
return E_UNEXPECTED;
}
-HRESULT STDMETHODCALLTYPE
-m_drag_leave (IDropTarget __RPC_FAR *This)
+static HRESULT STDMETHODCALLTYPE
+idataobject_getdatahere (LPDATAOBJECT This,
+ LPFORMATETC pFormatEtc,
+ LPSTGMEDIUM pMedium)
{
- GDK_NOTE (DND, g_print ("m_drag_leave\n"));
+ GDK_NOTE (DND, g_print ("idataobject_getdatahere %#x\n", This));
+
return E_UNEXPECTED;
}
-HRESULT STDMETHODCALLTYPE
-m_drop (IDropTarget __RPC_FAR *This,
- /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
- /* [in] */ DWORD grfKeyState,
- /* [in] */ POINTL pt,
- /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
+static HRESULT STDMETHODCALLTYPE
+idataobject_querygetdata (LPDATAOBJECT This,
+ LPFORMATETC pFormatEtc)
+{
+ int i;
+
+ GDK_NOTE (DND, g_print ("idataobject_querygetdata %#x %#x", This, pFormatEtc->cfFormat));
+
+ for (i = 0; i < nformats; i++)
+ if (pFormatEtc->cfFormat == formats[i].cfFormat)
+ {
+ GDK_NOTE (DND, g_print (" S_OK\n"));
+ return S_OK;
+ }
+
+ GDK_NOTE (DND, g_print (" DV_E_FORMATETC\n"));
+ return DV_E_FORMATETC;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idataobject_getcanonicalformatetc (LPDATAOBJECT This,
+ LPFORMATETC pFormatEtcIn,
+ LPFORMATETC pFormatEtcOut)
+{
+ GDK_NOTE (DND, g_print ("idataobject_getcanonicalformatetc %#x\n", This));
+
+ return E_FAIL;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idataobject_setdata (LPDATAOBJECT This,
+ LPFORMATETC pFormatEtc,
+ LPSTGMEDIUM pMedium,
+ BOOL fRelease)
{
- GDK_NOTE (DND, g_print ("m_drop\n"));
+ GDK_NOTE (DND, g_print ("idataobject_setdata %#x\n", This));
+
return E_UNEXPECTED;
}
-
-HRESULT STDMETHODCALLTYPE
-m_query_interface_source (IDropSource __RPC_FAR *This,
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
+
+static HRESULT STDMETHODCALLTYPE
+idataobject_enumformatetc (LPDATAOBJECT This,
+ DWORD dwDirection,
+ LPENUMFORMATETC *ppEnumFormatEtc)
+{
+ GDK_NOTE (DND, g_print ("idataobject_enumformatetc %#x\n", This));
+
+ if (dwDirection != DATADIR_GET)
+ return E_NOTIMPL;
+
+ *ppEnumFormatEtc = &enum_formats_new ()->ief;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idataobject_dadvise (LPDATAOBJECT This,
+ LPFORMATETC pFormatetc,
+ DWORD advf,
+ LPADVISESINK pAdvSink,
+ DWORD *pdwConnection)
+{
+ GDK_NOTE (DND, g_print ("idataobject_dadvise %#x\n", This));
+
+ return E_FAIL;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idataobject_dunadvise (LPDATAOBJECT This,
+ DWORD dwConnection)
+{
+ GDK_NOTE (DND, g_print ("idataobject_dunadvise %#x\n", This));
+
+ return E_FAIL;
+}
+
+static HRESULT STDMETHODCALLTYPE
+idataobject_enumdadvise (LPDATAOBJECT This,
+ LPENUMSTATDATA *ppenumAdvise)
+{
+ GDK_NOTE (DND, g_print ("idataobject_enumdadvise %#x\n", This));
+
+ return E_FAIL;
+}
+
+static ULONG STDMETHODCALLTYPE
+ienumformatetc_addref (LPENUMFORMATETC This)
{
- GDK_NOTE (DND, g_print ("m_query_interface_source\n"));
+ enum_formats *en = (enum_formats *) This;
+ int ref_count = ++en->ref_count;
+
+ GDK_NOTE (DND, g_print ("ienumformatetc_addref %#x %d\n", This, ref_count));
+
+ return ref_count;
+}
+
+static HRESULT STDMETHODCALLTYPE
+ienumformatetc_queryinterface (LPENUMFORMATETC This,
+ REFIID riid,
+ LPVOID *ppvObject)
+{
+ GDK_NOTE (DND, g_print ("ienumformatetc_queryinterface %#x\n", This));
*ppvObject = NULL;
- g_print ("riid = %.02x%.02x%.02x%.02x-%.02x%.02x-%.02x%.02x-%.02x%.02x-%.02x%.02x%.02x%.02x%.02x%.02x",
- ((guchar *) riid)[0],
- ((guchar *) riid)[1],
- ((guchar *) riid)[2],
- ((guchar *) riid)[3],
- ((guchar *) riid)[4],
- ((guchar *) riid)[5],
- ((guchar *) riid)[6],
- ((guchar *) riid)[7],
- ((guchar *) riid)[8],
- ((guchar *) riid)[9],
- ((guchar *) riid)[10],
- ((guchar *) riid)[11],
- ((guchar *) riid)[12],
- ((guchar *) riid)[13],
- ((guchar *) riid)[14],
- ((guchar *) riid)[15]);
+ PRINT_GUID (riid);
if (IsEqualGUID (riid, &IID_IUnknown))
{
- m_add_ref_source (This);
- *ppvObject = This;
g_print ("...IUnknown\n");
+ ienumformatetc_addref (This);
+ *ppvObject = This;
return S_OK;
}
- else if (IsEqualGUID (riid, &IID_IDropSource))
+ else if (IsEqualGUID (riid, &IID_IEnumFORMATETC))
{
- m_add_ref_source (This);
+ g_print ("...IEnumFORMATETC\n");
+ ienumformatetc_addref (This);
*ppvObject = This;
- g_print ("...IDropSource\n");
return S_OK;
}
else
}
}
-ULONG STDMETHODCALLTYPE
-m_add_ref_source (IDropSource __RPC_FAR *This)
+static ULONG STDMETHODCALLTYPE
+ienumformatetc_release (LPENUMFORMATETC This)
{
- source_drag_context *ctx = (source_drag_context *) This;
- GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context;
+ enum_formats *en = (enum_formats *) This;
+ int ref_count = --en->ref_count;
- GDK_NOTE (DND, g_print ("m_add_ref_source\n"));
- gdk_drag_context_ref (ctx->context);
-
- return private->ref_count;
+ GDK_NOTE (DND, g_print ("ienumformatetc_release %#x %d\n", This, ref_count));
+
+ if (ref_count == 0)
+ g_free (This);
+
+ return ref_count;
}
-ULONG STDMETHODCALLTYPE
-m_release_source (IDropSource __RPC_FAR *This)
+static HRESULT STDMETHODCALLTYPE
+ienumformatetc_next (LPENUMFORMATETC This,
+ ULONG celt,
+ LPFORMATETC elts,
+ ULONG *nelt)
{
- source_drag_context *ctx = (source_drag_context *) This;
- GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context;
+ enum_formats *en = (enum_formats *) This;
+ int i, n;
- GDK_NOTE (DND, g_print ("m_release_source\n"));
- gdk_drag_context_unref (ctx->context);
+ GDK_NOTE (DND, g_print ("ienumformatetc_next %#x %d %d\n", This, en->ix, celt));
- if (private->ref_count == 1)
+ n = 0;
+ for (i = 0; i < celt; i++)
{
- gdk_drag_context_unref (ctx->context);
- return 0;
+ if (en->ix >= nformats)
+ break;
+ elts[i] = formats[en->ix++];
+ n++;
}
+
+ if (nelt != NULL)
+ *nelt = n;
+
+ if (n == celt)
+ return S_OK;
else
- return private->ref_count - 1;
+ return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE
-m_query_continue_drag (IDropSource __RPC_FAR *This,
- /* [in] */ BOOL fEscapePressed,
- /* [in] */ DWORD grfKeyState)
+static HRESULT STDMETHODCALLTYPE
+ienumformatetc_skip (LPENUMFORMATETC This,
+ ULONG celt)
{
- GDK_NOTE (DND, g_print ("m_query_continue_drag\n"));
- return E_UNEXPECTED;
+ enum_formats *en = (enum_formats *) This;
+
+ GDK_NOTE (DND, g_print ("ienumformatetc_skip %#x %d %d\n", This, en->ix, celt));
+ en->ix += celt;
+
+ return S_OK;
}
-HRESULT STDMETHODCALLTYPE
-m_give_feedback (IDropSource __RPC_FAR *This,
- /* [in] */ DWORD dwEffect)
+static HRESULT STDMETHODCALLTYPE
+ienumformatetc_reset (LPENUMFORMATETC This)
{
- GDK_NOTE (DND, g_print ("m_give_feedback\n"));
- return E_UNEXPECTED;
+ enum_formats *en = (enum_formats *) This;
+
+ GDK_NOTE (DND, g_print ("ienumformatetc_reset %#x\n", This));
+
+ en->ix = 0;
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE
+ienumformatetc_clone (LPENUMFORMATETC This,
+ LPENUMFORMATETC *ppEnumFormatEtc)
+{
+ enum_formats *en = (enum_formats *) This;
+ enum_formats *new;
+
+ GDK_NOTE (DND, g_print ("ienumformatetc_clone %#x\n", This));
+
+ new = enum_formats_new ();
+
+ new->ix = en->ix;
+
+ *ppEnumFormatEtc = &new->ief;
+
+ return S_OK;
}
static IDropTargetVtbl idt_vtbl = {
- m_query_interface_target,
- m_add_ref_target,
- m_release_target,
- m_drag_enter,
- m_drag_over,
- m_drag_leave,
- m_drop
+ idroptarget_queryinterface,
+ idroptarget_addref,
+ idroptarget_release,
+ idroptarget_dragenter,
+ idroptarget_dragover,
+ idroptarget_dragleave,
+ idroptarget_drop
};
static IDropSourceVtbl ids_vtbl = {
- m_query_interface_source,
- m_add_ref_source,
- m_release_source,
- m_query_continue_drag,
- m_give_feedback
+ idropsource_queryinterface,
+ idropsource_addref,
+ idropsource_release,
+ idropsource_querycontinuedrag,
+ idropsource_givefeedback
+};
+
+static IDataObjectVtbl ido_vtbl = {
+ idataobject_queryinterface,
+ idataobject_addref,
+ idataobject_release,
+ idataobject_getdata,
+ idataobject_getdatahere,
+ idataobject_querygetdata,
+ idataobject_getcanonicalformatetc,
+ idataobject_setdata,
+ idataobject_enumformatetc,
+ idataobject_dadvise,
+ idataobject_dunadvise,
+ idataobject_enumdadvise
+};
+
+static IEnumFORMATETCVtbl ief_vtbl = {
+ ienumformatetc_queryinterface,
+ ienumformatetc_addref,
+ ienumformatetc_release,
+ ienumformatetc_next,
+ ienumformatetc_skip,
+ ienumformatetc_reset,
+ ienumformatetc_clone
};
-target_drag_context *
+#endif /* OLE2_DND */
+
+static target_drag_context *
target_context_new (void)
{
target_drag_context *result;
result = g_new0 (target_drag_context, 1);
+#ifdef OLE2_DND
result->idt.lpVtbl = &idt_vtbl;
+#endif
result->context = gdk_drag_context_new ();
+ result->context->is_source = FALSE;
+
+ GDK_NOTE (DND, g_print ("target_context_new: %p\n", result));
return result;
}
-source_drag_context *
+static source_drag_context *
source_context_new (void)
{
source_drag_context *result;
result = g_new0 (source_drag_context, 1);
+#ifdef OLE2_DND
result->ids.lpVtbl = &ids_vtbl;
+#endif
result->context = gdk_drag_context_new ();
+ result->context->is_source = TRUE;
- return result;
-}
+ GDK_NOTE (DND, g_print ("source_context_new: %p\n", result));
-#endif /* OLE2_DND */
-
-void
-gdk_drag_context_ref (GdkDragContext *context)
-{
- g_return_if_fail (context != NULL);
-
- ((GdkDragContextPrivate *)context)->ref_count++;
+ return result;
}
-void
-gdk_drag_context_unref (GdkDragContext *context)
+#ifdef OLE2_DND
+static data_object *
+data_object_new (void)
{
- GdkDragContextPrivate *private = (GdkDragContextPrivate *)context;
-
- g_return_if_fail (context != NULL);
-
- private->ref_count--;
+ data_object *result;
- GDK_NOTE (DND, g_print ("gdk_drag_context_unref: %d%s\n",
- private->ref_count,
- (private->ref_count == 0 ? " freeing" : "")));
-
- if (private->ref_count == 0)
- {
- g_dataset_destroy (private);
-
- g_list_free (context->targets);
+ result = g_new0 (data_object, 1);
- if (context->source_window)
- gdk_window_unref (context->source_window);
+ result->ido.lpVtbl = &ido_vtbl;
+ result->ref_count = 1;
- if (context->dest_window)
- gdk_window_unref (context->dest_window);
+ GDK_NOTE (DND, g_print ("data_object_new: %#x\n", result));
- contexts = g_list_remove (contexts, private);
- g_free (private);
- }
+ return result;
}
-#if 0
-static GdkDragContext *
-gdk_drag_context_find (gboolean is_source,
- HWND source_xid,
- HWND dest_xid)
+static enum_formats *
+enum_formats_new (void)
{
- GList *tmp_list = contexts;
- GdkDragContext *context;
+ enum_formats *result;
- while (tmp_list)
- {
- context = (GdkDragContext *)tmp_list->data;
+ result = g_new0 (enum_formats, 1);
- if ((!context->is_source == !is_source) &&
- ((source_xid == None) || (context->source_window &&
- (GDK_WINDOW_XWINDOW (context->source_window) == source_xid))) &&
- ((dest_xid == None) || (context->dest_window &&
- (GDK_WINDOW_XWINDOW (context->dest_window) == dest_xid))))
- return context;
-
- tmp_list = tmp_list->next;
- }
+ result->ief.lpVtbl = &ief_vtbl;
+ result->ref_count = 1;
+ result->ix = 0;
- return NULL;
+ GDK_NOTE (DND, g_print ("enum_formats_new: %#x\n", result));
+
+ return result;
}
#endif
*/
static HRESULT
-resolve_link(HWND hWnd,
+resolve_link(HWND hWnd,
LPCTSTR lpszLinkName,
- LPSTR lpszPath,
- LPSTR lpszDescription)
+ LPSTR lpszPath,
+ LPSTR lpszDescription)
{
HRESULT hres;
IShellLink *psl;
gpointer data)
{
GdkDragContext *context;
- GdkDragContextPrivate *private;
- static GdkAtom text_uri_list_atom = GDK_NONE;
+ GdkDragContextPrivateWin32 *private;
GString *result;
MSG *msg = (MSG *) xev;
HANDLE hdrop;
POINT pt;
- gint nfiles, i, k;
+ gint nfiles, i;
guchar fileName[MAX_PATH], linkedFile[MAX_PATH];
- if (text_uri_list_atom == GDK_NONE)
- text_uri_list_atom = gdk_atom_intern ("text/uri-list", FALSE);
-
if (msg->message == WM_DROPFILES)
{
- GDK_NOTE (DND, g_print ("WM_DROPFILES: %#x\n", msg->hwnd));
+ GDK_NOTE (DND, g_print ("WM_DROPFILES: %#x\n", (guint) msg->hwnd));
context = gdk_drag_context_new ();
- private = (GdkDragContextPrivate *) context;
+ private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
context->protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
context->is_source = FALSE;
- context->source_window = (GdkWindow *) &gdk_root_parent;
+ context->source_window = _gdk_parent_root;
+ gdk_drawable_ref (context->source_window);
context->dest_window = event->any.window;
- gdk_window_ref (context->dest_window);
+ gdk_drawable_ref (context->dest_window);
/* WM_DROPFILES drops are always file names */
context->targets =
- g_list_append (NULL, GUINT_TO_POINTER (text_uri_list_atom));
+ g_list_append (NULL, GUINT_TO_POINTER (_text_uri_list));
current_dest_drag = context;
event->dnd.type = GDK_DROP_START;
event->dnd.context = current_dest_drag;
- gdk_drag_context_ref (current_dest_drag);
hdrop = (HANDLE) msg->wParam;
DragQueryPoint (hdrop, &pt);
event->dnd.x_root = pt.x;
event->dnd.y_root = pt.y;
- event->dnd.time = msg->time;
+ event->dnd.time = _gdk_win32_get_next_tick (msg->time);
nfiles = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
result = g_string_new (NULL);
for (i = 0; i < nfiles; i++)
{
- g_string_append (result, "file:");
+ gchar *uri;
+
DragQueryFile (hdrop, i, fileName, MAX_PATH);
/* Resolve shortcuts */
if (resolve_link (msg->hwnd, fileName, linkedFile, NULL))
{
- g_string_append (result, linkedFile);
- GDK_NOTE (DND, g_print ("...%s link to %s\n",
- fileName, linkedFile));
+ uri = g_filename_to_uri (linkedFile, NULL, NULL);
+ if (uri != NULL)
+ {
+ g_string_append (result, uri);
+ GDK_NOTE (DND, g_print ("...%s link to %s: %s\n",
+ fileName, linkedFile, uri));
+ g_free (uri);
+ }
}
else
{
- g_string_append (result, fileName);
- GDK_NOTE (DND, g_print ("...%s\n", fileName));
+ uri = g_filename_to_uri (fileName, NULL, NULL);
+ if (uri != NULL)
+ {
+ g_string_append (result, uri);
+ GDK_NOTE (DND, g_print ("...%s: %s\n", fileName, uri));
+ g_free (uri);
+ }
}
g_string_append (result, "\015\012");
}
- gdk_sel_prop_store ((GdkWindow *) &gdk_root_parent,
- text_uri_list_atom, 8, result->str, result->len + 1);
+ _gdk_dropfiles_store (result->str);
+ g_string_free (result, FALSE);
DragFinish (hdrop);
else
return GDK_FILTER_CONTINUE;
}
-
/*************************************************************
************************** Public API ***********************
*************************************************************/
void
-gdk_dnd_init (void)
+_gdk_dnd_init (void)
{
+#ifdef OLE2_DND
HRESULT hres;
-
hres = OleInitialize (NULL);
if (! SUCCEEDED (hres))
g_error ("OleInitialize failed");
-}
+
+ nformats = 2;
+ formats = g_new (FORMATETC, nformats);
+
+ formats[0].cfFormat = CF_TEXT;
+ formats[0].ptd = NULL;
+ formats[0].dwAspect = DVASPECT_CONTENT;
+ formats[0].lindex = -1;
+ formats[0].tymed = TYMED_HGLOBAL;
+
+ formats[1].cfFormat = CF_GDIOBJFIRST;
+ formats[1].ptd = NULL;
+ formats[1].dwAspect = DVASPECT_CONTENT;
+ formats[1].lindex = -1;
+ formats[1].tymed = TYMED_HGLOBAL;
+#endif
+}
void
-gdk_dnd_exit (void)
+_gdk_win32_dnd_exit (void)
{
+#ifdef OLE2_DND
OleUninitialize ();
+#endif
}
/* Source side */
static void
-gdk_drag_do_leave (GdkDragContext *context, guint32 time)
+local_send_leave (GdkDragContext *context,
+ guint32 time)
+{
+ GdkEvent tmp_event;
+
+ if ((current_dest_drag != NULL) &&
+ (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) &&
+ (current_dest_drag->source_window == context->source_window))
+ {
+ tmp_event.dnd.type = GDK_DRAG_LEAVE;
+ tmp_event.dnd.window = context->dest_window;
+ /* Pass ownership of context to the event */
+ tmp_event.dnd.send_event = FALSE;
+ tmp_event.dnd.context = current_dest_drag;
+ tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
+
+ current_dest_drag = NULL;
+
+ gdk_event_put (&tmp_event);
+ }
+}
+
+static void
+local_send_enter (GdkDragContext *context,
+ guint32 time)
+{
+ GdkEvent tmp_event;
+ GdkDragContextPrivateWin32 *private;
+ GdkDragContext *new_context;
+
+ private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
+
+ if (current_dest_drag != NULL)
+ {
+ gdk_drag_context_unref (current_dest_drag);
+ current_dest_drag = NULL;
+ }
+
+ new_context = gdk_drag_context_new ();
+ new_context->protocol = GDK_DRAG_PROTO_LOCAL;
+ new_context->is_source = FALSE;
+
+ new_context->source_window = context->source_window;
+ gdk_window_ref (new_context->source_window);
+ new_context->dest_window = context->dest_window;
+ gdk_window_ref (new_context->dest_window);
+
+ new_context->targets = g_list_copy (context->targets);
+
+ gdk_window_set_events (new_context->source_window,
+ gdk_window_get_events (new_context->source_window) |
+ GDK_PROPERTY_CHANGE_MASK);
+ new_context->actions = context->actions;
+
+ tmp_event.dnd.type = GDK_DRAG_ENTER;
+ tmp_event.dnd.window = context->dest_window;
+ tmp_event.dnd.send_event = FALSE;
+ tmp_event.dnd.context = new_context;
+ tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
+
+ current_dest_drag = new_context;
+
+ gdk_event_put (&tmp_event);
+}
+
+static void
+local_send_motion (GdkDragContext *context,
+ gint x_root,
+ gint y_root,
+ GdkDragAction action,
+ guint32 time)
+{
+ GdkEvent tmp_event;
+
+ if ((current_dest_drag != NULL) &&
+ (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) &&
+ (current_dest_drag->source_window == context->source_window))
+ {
+ tmp_event.dnd.type = GDK_DRAG_MOTION;
+ tmp_event.dnd.window = current_dest_drag->dest_window;
+ tmp_event.dnd.send_event = FALSE;
+ tmp_event.dnd.context = current_dest_drag;
+ tmp_event.dnd.time = time;
+
+ current_dest_drag->suggested_action = action;
+ current_dest_drag->actions = current_dest_drag->suggested_action;
+
+ tmp_event.dnd.x_root = x_root;
+ tmp_event.dnd.y_root = y_root;
+
+ (GDK_DRAG_CONTEXT_PRIVATE_DATA (current_dest_drag))->last_x = x_root;
+ (GDK_DRAG_CONTEXT_PRIVATE_DATA (current_dest_drag))->last_y = y_root;
+
+ GDK_DRAG_CONTEXT_PRIVATE_DATA (context)->drag_status = GDK_DRAG_STATUS_MOTION_WAIT;
+
+ gdk_event_put (&tmp_event);
+ }
+}
+
+static void
+local_send_drop (GdkDragContext *context,
+ guint32 time)
+{
+ GdkEvent tmp_event;
+
+ if ((current_dest_drag != NULL) &&
+ (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) &&
+ (current_dest_drag->source_window == context->source_window))
+ {
+ GdkDragContextPrivateWin32 *private;
+ private = GDK_DRAG_CONTEXT_PRIVATE_DATA (current_dest_drag);
+
+ tmp_event.dnd.type = GDK_DROP_START;
+ tmp_event.dnd.window = current_dest_drag->dest_window;
+ tmp_event.dnd.send_event = FALSE;
+ tmp_event.dnd.context = current_dest_drag;
+ tmp_event.dnd.time = GDK_CURRENT_TIME;
+
+ tmp_event.dnd.x_root = private->last_x;
+ tmp_event.dnd.y_root = private->last_y;
+
+ gdk_event_put (&tmp_event);
+ }
+
+}
+
+static void
+gdk_drag_do_leave (GdkDragContext *context,
+ guint32 time)
{
if (context->dest_window)
{
GDK_NOTE (DND, g_print ("gdk_drag_do_leave\n"));
- gdk_window_unref (context->dest_window);
+
+ switch (context->protocol)
+ {
+ case GDK_DRAG_PROTO_LOCAL:
+ local_send_leave (context, time);
+ break;
+ default:
+ break;
+ }
+
+ gdk_drawable_unref (context->dest_window);
context->dest_window = NULL;
}
}
GdkDragContext *
-gdk_drag_begin (GdkWindow *window,
- GList *targets)
+gdk_drag_begin (GdkWindow *window,
+ GList *targets)
{
+#ifndef OLE2_DND
GList *tmp_list;
GdkDragContext *new_context;
-
- g_return_val_if_fail (window != NULL, NULL);
- GDK_NOTE (DND, g_print ("gdk_drag_begin\n"));
+ g_return_val_if_fail (window != NULL, NULL);
new_context = gdk_drag_context_new ();
new_context->is_source = TRUE;
new_context->actions = 0;
return new_context;
+#else
+ source_drag_context *ctx;
+ GList *tmp_list;
+ data_object *dobj;
+ HRESULT hResult;
+ DWORD dwEffect;
+ HGLOBAL global;
+ FORMATETC format;
+ STGMEDIUM medium;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ GDK_NOTE (DND, g_print ("gdk_drag_begin\n"));
+
+ ctx = source_context_new ();
+ ctx->context->protocol = GDK_DRAG_PROTO_OLE2;
+ ctx->context->source_window = window;
+ gdk_drawable_ref (window);
+
+ tmp_list = g_list_last (targets);
+ ctx->context->targets = NULL;
+ while (tmp_list)
+ {
+ ctx->context->targets = g_list_prepend (ctx->context->targets,
+ tmp_list->data);
+ tmp_list = tmp_list->prev;
+ }
+
+ ctx->context->actions = 0;
+
+ dobj = data_object_new ();
+
+ global = GlobalAlloc (GMEM_FIXED, sizeof (ctx));
+
+ memcpy (&global, ctx, sizeof (ctx));
+
+ medium.tymed = TYMED_HGLOBAL;
+ medium.hGlobal = global;
+ medium.pUnkForRelease = NULL;
+
+ dobj->ido.lpVtbl->SetData (&dobj->ido, &formats[1], &medium, TRUE);
+
+ hResult = DoDragDrop (&dobj->ido, &ctx->ids, DROPEFFECT_MOVE|DROPEFFECT_COPY, &dwEffect);
+
+ GDK_NOTE (DND, g_print ("DoDragDrop returned %s\n",
+ (hResult == DRAGDROP_S_DROP ? "DRAGDROP_S_DROP" :
+ (hResult == DRAGDROP_S_CANCEL ? "DRAGDROP_S_CANCEL" :
+ (hResult == E_UNEXPECTED ? "E_UNEXPECTED" :
+ g_strdup_printf ("%#.8x", hResult))))));
+
+ dobj->ido.lpVtbl->Release (&dobj->ido);
+ ctx->ids.lpVtbl->Release (&ctx->ids);
+
+ return ctx->context;
+#endif
}
guint32
-gdk_drag_get_protocol (guint32 xid,
- GdkDragProtocol *protocol)
+gdk_drag_get_protocol_for_display (GdkDisplay *display,
+ guint32 xid,
+ GdkDragProtocol *protocol)
{
- /* This isn't used */
+ GdkWindow *window;
+
+ GDK_NOTE (DND, g_print ("gdk_drag_get_protocol\n"));
+
+ window = gdk_window_lookup (xid);
+
+ if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered")))
+ {
+ *protocol = GDK_DRAG_PROTO_LOCAL;
+ return xid;
+ }
+
return 0;
}
void
-gdk_drag_find_window (GdkDragContext *context,
- GdkWindow *drag_window,
- gint x_root,
- gint y_root,
- GdkWindow **dest_window,
- GdkDragProtocol *protocol)
-{
- GdkDragContextPrivate *private = (GdkDragContextPrivate *)context;
- GdkWindowPrivate *drag_window_private = (GdkWindowPrivate *) drag_window;
+gdk_drag_find_window_for_screen (GdkDragContext *context,
+ GdkWindow *drag_window,
+ GdkScreen *screen,
+ gint x_root,
+ gint y_root,
+ GdkWindow **dest_window,
+ GdkDragProtocol *protocol)
+{
HWND recipient;
POINT pt;
- GDK_NOTE (DND, g_print ("gdk_drag_find_window: %#x +%d+%d\n",
- (drag_window ? drag_window_private->xwindow : 0),
- x_root, y_root));
-
pt.x = x_root;
pt.y = y_root;
recipient = WindowFromPoint (pt);
*dest_window = NULL;
else
{
- *dest_window = gdk_window_lookup (recipient);
+ *dest_window = gdk_win32_handle_table_lookup (GPOINTER_TO_UINT(recipient));
if (*dest_window)
- gdk_window_ref (*dest_window);
- *protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
+ {
+ *dest_window = gdk_window_get_toplevel (*dest_window);
+ gdk_drawable_ref (*dest_window);
+ }
+
+ if (context->source_window)
+ *protocol = GDK_DRAG_PROTO_LOCAL;
+ else
+ *protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
}
+
+ GDK_NOTE (DND, g_print ("gdk_drag_find_window: %#x +%d+%d Protocol: %d\n",
+ (drag_window ? (guint) GDK_WINDOW_HWND (drag_window) : 0),
+ x_root, y_root, *protocol));
}
-gboolean
+gboolean
gdk_drag_motion (GdkDragContext *context,
GdkWindow *dest_window,
GdkDragProtocol protocol,
GdkDragAction possible_actions,
guint32 time)
{
+ GdkDragContextPrivateWin32 *private;
+
+ g_return_val_if_fail (context != NULL, FALSE);
+
+ GDK_NOTE (DND, g_print ("gdk_drag_motion\n"));
+
+ private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
+
+ if (context->dest_window != dest_window)
+ {
+ GdkEvent temp_event;
+
+ /* Send a leave to the last destination */
+ gdk_drag_do_leave (context, time);
+ private->drag_status = GDK_DRAG_STATUS_DRAG;
+
+ /* Check if new destination accepts drags, and which protocol */
+ if (dest_window)
+ {
+ context->dest_window = dest_window;
+ gdk_window_ref (context->dest_window);
+ context->protocol = protocol;
+
+ switch (protocol)
+ {
+ case GDK_DRAG_PROTO_LOCAL:
+ local_send_enter (context, time);
+ break;
+
+ default:
+ break;
+ }
+ context->suggested_action = suggested_action;
+ }
+ else
+ {
+ context->dest_window = NULL;
+ context->action = 0;
+ }
+
+ /* Push a status event, to let the client know that
+ * the drag changed
+ */
+
+ temp_event.dnd.type = GDK_DRAG_STATUS;
+ temp_event.dnd.window = context->source_window;
+ /* We use this to signal a synthetic status. Perhaps
+ * we should use an extra field...
+ */
+ temp_event.dnd.send_event = TRUE;
+
+ temp_event.dnd.context = context;
+ temp_event.dnd.time = time;
+
+ gdk_event_put (&temp_event);
+ }
+ else
+ {
+ context->suggested_action = suggested_action;
+ }
+
+ /* Send a drag-motion event */
+
+ private->last_x = x_root;
+ private->last_y = y_root;
+
+ if (context->dest_window)
+ {
+ if (private->drag_status == GDK_DRAG_STATUS_DRAG)
+ {
+ switch (context->protocol)
+ {
+ case GDK_DRAG_PROTO_LOCAL:
+ local_send_motion (context, x_root, y_root, suggested_action, time);
+ break;
+
+ case GDK_DRAG_PROTO_NONE:
+ g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_motion()");
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ return TRUE;
+ }
+
return FALSE;
}
{
g_return_if_fail (context != NULL);
- g_warning ("gdk_drag_drop: not implemented\n");
+ GDK_NOTE (DND, g_print ("gdk_drag_drop\n"));
+
+ if (context->dest_window)
+ {
+ switch (context->protocol)
+ {
+ case GDK_DRAG_PROTO_LOCAL:
+ local_send_drop (context, time);
+ break;
+
+ case GDK_DRAG_PROTO_NONE:
+ g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_drop()");
+ break;
+
+ default:
+ break;
+ }
+ }
}
void
{
g_return_if_fail (context != NULL);
+ GDK_NOTE (DND, g_print ("gdk_drag_abort\n"));
+
gdk_drag_do_leave (context, time);
}
/* Destination side */
-void
-gdk_drag_status (GdkDragContext *context,
- GdkDragAction action,
- guint32 time)
+void
+gdk_drag_status (GdkDragContext *context,
+ GdkDragAction action,
+ guint32 time)
{
- GDK_NOTE (DND, g_print ("gdk_drag_status\n"));
+ GdkDragContextPrivateWin32 *private;
+ GdkDragContext *src_context;
+ GdkEvent tmp_event;
+
+ g_return_if_fail (context != NULL);
+
+ private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
+
+ src_context = gdk_drag_context_find (TRUE,
+ context->source_window,
+ context->dest_window);
+
+ if (src_context)
+ {
+ GdkDragContextPrivateWin32 *private = GDK_DRAG_CONTEXT_PRIVATE_DATA (src_context);
+
+ if (private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT)
+ private->drag_status = GDK_DRAG_STATUS_DRAG;
+
+ tmp_event.dnd.type = GDK_DRAG_STATUS;
+ tmp_event.dnd.window = context->source_window;
+ tmp_event.dnd.send_event = FALSE;
+ tmp_event.dnd.context = src_context;
+ tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
+
+ if (action == GDK_ACTION_DEFAULT)
+ action = 0;
+
+ src_context->action = action;
+
+ gdk_event_put (&tmp_event);
+ }
}
void
-gdk_drop_reply (GdkDragContext *context,
- gboolean ok,
- guint32 time)
+gdk_drop_reply (GdkDragContext *context,
+ gboolean ok,
+ guint32 time)
{
+ g_return_if_fail (context != NULL);
+
+ GDK_NOTE (DND, g_print ("gdk_drop_reply\n"));
+
+ if (context->dest_window)
+ {
+ switch (context->protocol)
+ {
+ case GDK_DRAG_PROTO_WIN32_DROPFILES:
+ _gdk_dropfiles_store (NULL);
+ break;
+
+ default:
+ break;
+ }
+ }
}
-void
-gdk_drop_finish (GdkDragContext *context,
- gboolean success,
- guint32 time)
+void
+gdk_drop_finish (GdkDragContext *context,
+ gboolean success,
+ guint32 time)
{
+ GdkDragContextPrivateWin32 *private;
+ GdkDragContext *src_context;
+ GdkEvent tmp_event;
+
+ g_return_if_fail (context != NULL);
+
+ GDK_NOTE (DND, g_print ("gdk_drop_finish\n"));
+
+ private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
+
+ src_context = gdk_drag_context_find (TRUE,
+ context->source_window,
+ context->dest_window);
+ if (src_context)
+ {
+ tmp_event.dnd.type = GDK_DROP_FINISHED;
+ tmp_event.dnd.window = src_context->source_window;
+ tmp_event.dnd.send_event = FALSE;
+ tmp_event.dnd.context = src_context;
+
+ gdk_event_put (&tmp_event);
+ }
}
+#ifdef OLE2_DND
-void
-gdk_window_register_dnd (GdkWindow *window)
+static GdkFilterReturn
+gdk_destroy_filter (GdkXEvent *xev,
+ GdkEvent *event,
+ gpointer data)
{
- GdkWindowPrivate *private = (GdkWindowPrivate *) window;
-#if OLE2_DND
- target_drag_context *context;
+ MSG *msg = (MSG *) xev;
+
+ if (msg->message == WM_DESTROY)
+ {
+ IDropTarget *idtp = (IDropTarget *) data;
+
+ GDK_NOTE (DND, g_print ("gdk_destroy_filter: WM_DESTROY: %#x\n", msg->hwnd));
+#if 0
+ idtp->lpVtbl->Release (idtp);
+#endif
+ RevokeDragDrop (msg->hwnd);
+ CoLockObjectExternal (idtp, FALSE, TRUE);
+ }
+ return GDK_FILTER_CONTINUE;
+}
+#endif
+
+void
+gdk_window_register_dnd (GdkWindow *window)
+{
+#ifdef OLE2_DND
+ target_drag_context *ctx;
HRESULT hres;
#endif
g_return_if_fail (window != NULL);
- GDK_NOTE (DND, g_print ("gdk_window_register_dnd: %#x\n", private->xwindow));
+ if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered")))
+ return;
+
+ gdk_drawable_set_data (window, "gdk-dnd-registered", GINT_TO_POINTER(TRUE), NULL);
+
+ GDK_NOTE (DND, g_print ("gdk_window_register_dnd: %#x\n",
+ (guint) GDK_WINDOW_HWND (window)));
/* We always claim to accept dropped files, but in fact we might not,
* of course. This function is called in such a way that it cannot know
* (in gtk, data of type text/uri-list) or not.
*/
gdk_window_add_filter (window, gdk_dropfiles_filter, NULL);
- DragAcceptFiles (private->xwindow, TRUE);
+ DragAcceptFiles (GDK_WINDOW_HWND (window), TRUE);
-#if OLE2_DND
+#ifdef OLE2_DND
/* Register for OLE2 d&d */
- context = target_context_new ();
- hres = CoLockObjectExternal ((IUnknown *) &context->idt, TRUE, FALSE);
+ ctx = target_context_new ();
+ ctx->context->protocol = GDK_DRAG_PROTO_OLE2;
+ hres = CoLockObjectExternal ((IUnknown *) &ctx->idt, TRUE, FALSE);
if (!SUCCEEDED (hres))
- g_warning ("gdk_window_register_dnd: CoLockObjectExternal failed");
+ OTHER_API_FAILED ("CoLockObjectExternal");
else
{
- hres = RegisterDragDrop (private->xwindow, &context->idt);
+ hres = RegisterDragDrop (GDK_WINDOW_HWND (window), &ctx->idt);
if (hres == DRAGDROP_E_ALREADYREGISTERED)
{
g_print ("DRAGDROP_E_ALREADYREGISTERED\n");
- CoLockObjectExternal ((IUnknown *) &context->idt, FALSE, FALSE);
+#if 0
+ ctx->idt.lpVtbl->Release (&ctx->idt);
+#endif
+ CoLockObjectExternal ((IUnknown *) &ctx->idt, FALSE, FALSE);
}
else if (!SUCCEEDED (hres))
- g_warning ("gdk_window_register_dnd: RegisterDragDrop failed");
+ OTHER_API_FAILED ("RegisterDragDrop");
+ else
+ {
+ gdk_window_add_filter (window, gdk_destroy_filter, &ctx->idt);
+ }
}
#endif
}
* gdk_drag_get_selection:
* Returns the selection atom for the current source window
* arguments:
- *
+ *
* results:
*************************************************************/
-GdkAtom
+GdkAtom
gdk_drag_get_selection (GdkDragContext *context)
{
- if (context->protocol == GDK_DRAG_PROTO_WIN32_DROPFILES)
- return gdk_win32_dropfiles_atom;
+ if (context->protocol == GDK_DRAG_PROTO_LOCAL)
+ return _local_dnd;
+ else if (context->protocol == GDK_DRAG_PROTO_WIN32_DROPFILES)
+ return _gdk_win32_dropfiles;
else if (context->protocol == GDK_DRAG_PROTO_OLE2)
- return gdk_ole2_dnd_atom;
+ return _gdk_ole2_dnd;
else
return GDK_NONE;
}