*
* Notes on the implementation:
*
- * Source drag context, IDragSource and IDataObject for it are created
+ * Source drag context, IDropSource and IDataObject for it are created
* (almost) simultaneously, whereas target drag context and IDropTarget
* are separated in time - IDropTarget is created when a window is made
* to accept drops, while target drag context is created when a dragging
* To account for it the data is transmuted back and forth. There are two
* main points of transmutation:
* * GdkWin32HDATAOutputStream: transmutes GTK+ data to W32 data
- * * GdkWin32DropContext: transmutes W32 data to GTK+ data
+ * * GdkWin32Drop: transmutes W32 data to GTK+ data
*
* There are also two points where data formats are considered:
* * When source drag context is created, it gets a list of GDK contentformats
IDropSource ids;
IDropSourceNotify idsn;
gint ref_count;
- GdkDragContext *context;
+ GdkDragContext *drag;
/* These are thread-local
* copies of the similar fields from GdkWin32DragContext
typedef struct {
IDataObject ido;
int ref_count;
- GdkDragContext *context;
+ GdkDragContext *drag;
GArray *formats;
} data_object;
case GDK_WIN32_DND_THREAD_QUEUE_ITEM_UPDATE_DRAG_STATE:
case GDK_WIN32_DND_THREAD_QUEUE_ITEM_GIVE_FEEDBACK:
case GDK_WIN32_DND_THREAD_QUEUE_ITEM_DRAG_INFO:
+ /* These have no data to clean up */
break;
case GDK_WIN32_DND_THREAD_QUEUE_ITEM_GET_DATA:
getdata = (GdkWin32DnDThreadGetData *) item;
return FALSE;
}
+void
+_gdk_win32_local_drag_context_drop_response (GdkDragContext *drag,
+ GdkDragAction action)
+{
+ GDK_NOTE (DND, g_print ("_gdk_win32_local_drag_context_drop_response: 0x%p\n",
+ drag));
+
+ g_signal_emit_by_name (drag, "dnd-finished");
+ gdk_drag_drop_done (drag, action != 0);
+}
+
static gboolean
do_drag_drop_response (gpointer user_data)
{
GdkWin32DnDThreadDoDragDrop *ddd = (GdkWin32DnDThreadDoDragDrop *) user_data;
HRESULT hr = ddd->received_result;
- GdkDragContext *context = GDK_DRAG_CONTEXT (ddd->base.opaque_context);
+ GdkDragContext *drag = GDK_DRAG_CONTEXT (ddd->base.opaque_context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
- gpointer table_value = g_hash_table_lookup (clipdrop->active_source_drags, context);
+ gpointer table_value = g_hash_table_lookup (clipdrop->active_source_drags, drag);
- /* This just verifies that we got the right context,
- * we don't need the ddd struct itself.
- */
if (ddd == table_value)
{
GDK_NOTE (DND, g_print ("DoDragDrop returned %s with effect %lu\n",
(hr == E_UNEXPECTED ? "E_UNEXPECTED" :
g_strdup_printf ("%#.8lx", hr)))), ddd->received_drop_effect));
- GDK_WIN32_DRAG_CONTEXT (context)->drop_failed = !(SUCCEEDED (hr) || hr == DRAGDROP_S_DROP);
+ drag_win32->drop_failed = !(SUCCEEDED (hr) || hr == DRAGDROP_S_DROP);
/* We used to delete the selection here,
* now GTK does that automatically in response to
* the "dnd-finished" signal,
* if the operation was successful and was a move.
*/
- GDK_NOTE (DND, g_print ("gdk_dnd_handle_drop_finihsed: 0x%p\n",
- context));
+ GDK_NOTE (DND, g_print ("gdk_dnd_handle_drop_finished: 0x%p\n",
+ drag));
- g_signal_emit_by_name (context, "dnd-finished");
- gdk_drag_drop_done (context, !(GDK_WIN32_DRAG_CONTEXT (context))->drop_failed);
+ g_signal_emit_by_name (drag, "dnd-finished");
+ gdk_drag_drop_done (drag, !drag_win32->drop_failed);
}
else
{
if (!table_value)
- g_critical ("Did not find context 0x%p in the active contexts table", context);
+ g_critical ("Did not find drag 0x%p in the active drags table", drag);
else
- g_critical ("Found context 0x%p in the active contexts table, but the record doesn't match (0x%p != 0x%p)", context, ddd, table_value);
+ g_critical ("Found drag 0x%p in the active drags table, but the record doesn't match (0x%p != 0x%p)", drag, ddd, table_value);
}
/* 3rd parties could keep a reference to this object,
- * but we won't keep the context alive that long.
+ * but we won't keep the drag alive that long.
* Neutralize it (attempts to get its data will fail)
- * by nullifying the context pointer (it doesn't hold
+ * by nullifying the drag pointer (it doesn't hold
* a reference, so no unreffing).
*/
- ddd->src_object->context = NULL;
+ g_clear_object (&ddd->src_object->drag);
IDropSource_Release (&ddd->src_context->ids);
IDataObject_Release (&ddd->src_object->ido);
- g_hash_table_remove (clipdrop->active_source_drags, context);
+ g_hash_table_remove (clipdrop->active_source_drags, drag);
free_queue_item (&ddd->base);
return G_SOURCE_REMOVE;
}
static void
-received_drag_context_data (GObject *context,
+received_drag_context_data (GObject *drag,
GAsyncResult *result,
gpointer user_data)
{
GdkWin32DnDThreadGetData *getdata = (GdkWin32DnDThreadGetData *) user_data;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
- if (!gdk_drag_context_write_finish (GDK_DRAG_CONTEXT (context), result, &error))
+ if (!gdk_drag_context_write_finish (GDK_DRAG_CONTEXT (drag), result, &error))
{
HANDLE handle;
gboolean is_hdata;
- GDK_NOTE (DND, g_printerr ("%p: failed to write HData-backed stream: %s\n", context, error->message));
+ GDK_NOTE (DND, g_printerr ("%p: failed to write HData-backed stream: %s\n", drag, error->message));
g_error_free (error);
g_output_stream_close (G_OUTPUT_STREAM (getdata->stream), NULL, NULL);
handle = gdk_win32_hdata_output_stream_get_handle (getdata->stream, &is_hdata);
{
GdkWin32DnDThreadGetData *getdata = (GdkWin32DnDThreadGetData *) user_data;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
- GdkDragContext *context = GDK_DRAG_CONTEXT (getdata->base.opaque_context);
- gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, context);
+ GdkDragContext *drag = GDK_DRAG_CONTEXT (getdata->base.opaque_context);
+ gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
GDK_NOTE (DND, g_print ("idataobject_getdata will request target 0x%p (%s)",
getdata->pair.contentformat, getdata->pair.contentformat));
- /* This just verifies that we got the right context,
+ /* This just verifies that we got the right drag,
* we don't need the ddd struct itself.
*/
if (ddd)
if (stream)
{
getdata->stream = GDK_WIN32_HDATA_OUTPUT_STREAM (stream);
- gdk_drag_context_write_async (context,
+ gdk_drag_context_write_async (drag,
getdata->pair.contentformat,
stream,
G_PRIORITY_DEFAULT,
GDK_DRAG_STATUS_DROP
} GdkDragStatus;
-static GList *local_source_contexts;
-static GdkDragContext *current_dest_drag = NULL;
-
static gboolean use_ole2_dnd = TRUE;
-static gboolean drag_context_grab (GdkDragContext *context);
+static gboolean drag_context_grab (GdkDragContext *drag);
G_DEFINE_TYPE (GdkWin32DragContext, gdk_win32_drag_context, GDK_TYPE_DRAG_CONTEXT)
static void
-move_drag_surface (GdkDragContext *context,
+move_drag_surface (GdkDragContext *drag,
guint x_root,
guint y_root)
{
- GdkWin32DragContext *context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
- gdk_surface_move (context_win32->drag_surface,
- x_root - context_win32->hot_x,
- y_root - context_win32->hot_y);
- gdk_surface_raise (context_win32->drag_surface);
+ gdk_surface_move (drag_win32->drag_surface,
+ x_root - drag_win32->hot_x,
+ y_root - drag_win32->hot_y);
+ gdk_surface_raise (drag_win32->drag_surface);
}
static void
-gdk_win32_drag_context_init (GdkWin32DragContext *context)
+gdk_win32_drag_context_init (GdkWin32DragContext *drag)
{
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
- if (!use_ole2_dnd)
- {
- local_source_contexts = g_list_prepend (local_source_contexts, context);
- }
- else
- {
- }
+ drag->handle_events = TRUE;
- GDK_NOTE (DND, g_print ("gdk_drag_context_init %p\n", context));
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_init %p\n", drag));
}
static void
gdk_win32_drag_context_finalize (GObject *object)
{
- GdkDragContext *context;
- GdkWin32DragContext *context_win32;
+ GdkDragContext *drag;
+ GdkWin32DragContext *drag_win32;
GdkSurface *drag_surface;
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
- GDK_NOTE (DND, g_print ("gdk_drag_context_finalize %p\n", object));
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_finalize %p\n", object));
g_return_if_fail (GDK_IS_WIN32_DRAG_CONTEXT (object));
- context = GDK_DRAG_CONTEXT (object);
- context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ drag = GDK_DRAG_CONTEXT (object);
+ drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
- if (!use_ole2_dnd)
- {
- local_source_contexts = g_list_remove (local_source_contexts, context);
-
- if (context == current_dest_drag)
- current_dest_drag = NULL;
- }
+ gdk_drag_context_set_cursor (drag, NULL);
- g_set_object (&context_win32->ipc_window, NULL);
- drag_surface = context_win32->drag_surface;
+ g_set_object (&drag_win32->ipc_window, NULL);
+ drag_surface = drag_win32->drag_surface;
G_OBJECT_CLASS (gdk_win32_drag_context_parent_class)->finalize (object);
static GdkDragContext *
gdk_drag_context_new (GdkDisplay *display,
GdkContentProvider *content,
- GdkSurface *source_surface,
- GdkContentFormats *formats,
GdkDragAction actions,
GdkDevice *device,
GdkDragProtocol protocol)
{
- GdkWin32DragContext *context_win32;
+ GdkWin32DragContext *drag_win32;
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
- GdkDragContext *context;
+ GdkDragContext *drag;
- context_win32 = g_object_new (GDK_TYPE_WIN32_DRAG_CONTEXT,
- "device", device ? device : gdk_seat_get_pointer (gdk_display_get_default_seat (display)),
+ drag_win32 = g_object_new (GDK_TYPE_WIN32_DRAG_CONTEXT,
+ "device", device,
"content", content,
- "formats", formats,
NULL);
- context = GDK_DRAG_CONTEXT (context_win32);
+ drag = GDK_DRAG_CONTEXT (drag_win32);
if (win32_display->has_fixed_scale)
- context_win32->scale = win32_display->surface_scale;
+ drag_win32->scale = win32_display->surface_scale;
else
- context_win32->scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, NULL, NULL, NULL);
-
- context->is_source = TRUE;
- g_set_object (&context->source_surface, source_surface);
- gdk_drag_context_set_actions (context, actions, actions);
- context_win32->protocol = protocol;
+ drag_win32->scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, NULL, NULL, NULL);
- gdk_content_formats_unref (formats);
+ gdk_drag_context_set_actions (drag, actions, actions);
+ drag_win32->protocol = protocol;
- return context;
-}
-
-GdkDragContext *
-_gdk_win32_drag_context_find (GdkSurface *source,
- GdkSurface *dest)
-{
- GList *tmp_list = local_source_contexts;
- GdkDragContext *context;
-
- g_assert (_win32_main_thread == NULL ||
- _win32_main_thread == g_thread_self ());
-
- while (tmp_list)
- {
- context = (GdkDragContext *)tmp_list->data;
-
- if (context->is_source &&
- ((source == NULL) || (context->source_surface && (context->source_surface == source))) &&
- ((dest == NULL) || (context->dest_surface && (context->dest_surface == dest))))
- return context;
-
- tmp_list = tmp_list->next;
- }
-
- return NULL;
+ return drag;
}
#define PRINT_GUID(guid) \
static enum_formats *enum_formats_new (GArray *formats);
+/* Finds a GdkDragContext object that corresponds to a DnD operation
+ * which is currently targetting the dest_surface
+ * Does not give a reference.
+ */
GdkDragContext *
-_gdk_win32_find_source_context_for_dest_surface (GdkSurface *dest_surface)
+_gdk_win32_find_drag_for_dest_surface (GdkSurface *dest_surface)
{
GHashTableIter iter;
- GdkWin32DragContext *win32_context;
+ GdkWin32DragContext *drag_win32;
GdkWin32DnDThreadDoDragDrop *ddd;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
g_hash_table_iter_init (&iter, clipdrop->active_source_drags);
- while (g_hash_table_iter_next (&iter, (gpointer *) &win32_context, (gpointer *) &ddd))
+ while (g_hash_table_iter_next (&iter, (gpointer *) &drag_win32, (gpointer *) &ddd))
if (ddd->src_context->dest_window_handle == GDK_SURFACE_HWND (dest_surface))
- return GDK_DRAG_CONTEXT (win32_context);
+ return GDK_DRAG_CONTEXT (drag_win32);
return NULL;
}
notify_dnd_enter (gpointer user_data)
{
GdkWin32DnDEnterLeaveNotify *notify = (GdkWin32DnDEnterLeaveNotify *) user_data;
- GdkDragContext *context = GDK_DRAG_CONTEXT (notify->opaque_context);
+ GdkDragContext *drag = GDK_DRAG_CONTEXT (notify->opaque_context);
GdkSurface *dest_surface, *dw;
dw = gdk_win32_handle_table_lookup (notify->target_window_handle);
if (dw)
dest_surface = g_object_ref (dw);
else
- dest_surface = gdk_win32_surface_foreign_new_for_display (gdk_drag_context_get_display (context), notify->target_window_handle);
+ dest_surface = gdk_win32_surface_foreign_new_for_display (gdk_drag_context_get_display (drag), notify->target_window_handle);
- g_clear_object (&context->dest_surface);
- context->dest_surface = dest_surface;
+ g_clear_object (&drag->dest_surface);
+ drag->dest_surface = dest_surface;
g_free (notify);
notify_dnd_leave (gpointer user_data)
{
GdkWin32DnDEnterLeaveNotify *notify = (GdkWin32DnDEnterLeaveNotify *) user_data;
- GdkDragContext *context = GDK_DRAG_CONTEXT (notify->opaque_context);
+ GdkDragContext *drag = GDK_DRAG_CONTEXT (notify->opaque_context);
GdkSurface *dest_surface, *dw;
dw = gdk_win32_handle_table_lookup (notify->target_window_handle);
{
dest_surface = gdk_surface_get_toplevel (dw);
- if (dest_surface == context->dest_surface)
- g_clear_object (&context->dest_surface);
+ if (dest_surface == drag->dest_surface)
+ g_clear_object (&drag->dest_surface);
else
- g_warning ("Destination window for handle 0x%p is 0x%p, but context has 0x%p", notify->target_window_handle, dest_surface, context->dest_surface);
+ g_warning ("Destination window for handle 0x%p is 0x%p, but drag has 0x%p", notify->target_window_handle, dest_surface, drag->dest_surface);
}
else
g_warning ("Failed to find destination window for handle 0x%p", notify->target_window_handle);
notify = g_new0 (GdkWin32DnDEnterLeaveNotify, 1);
notify->target_window_handle = hwndTarget;
- notify->opaque_context = ctx->context;
+ notify->opaque_context = ctx->drag;
g_idle_add_full (G_PRIORITY_DEFAULT, notify_dnd_enter, notify, NULL);
return S_OK;
notify = g_new0 (GdkWin32DnDEnterLeaveNotify, 1);
notify->target_window_handle = ctx->dest_window_handle;
ctx->dest_window_handle = NULL;
- notify->opaque_context = ctx->context;
+ notify->opaque_context = ctx->drag;
g_idle_add_full (G_PRIORITY_DEFAULT, notify_dnd_leave, notify, NULL);
return S_OK;
static gboolean
unref_context_in_main_thread (gpointer opaque_context)
{
- GdkDragContext *context = GDK_DRAG_CONTEXT (opaque_context);
+ GdkDragContext *drag = GDK_DRAG_CONTEXT (opaque_context);
- g_clear_object (&context);
+ g_clear_object (&drag);
return G_SOURCE_REMOVE;
}
if (ref_count == 0)
{
- g_idle_add (unref_context_in_main_thread, ctx->context);
+ g_idle_add (unref_context_in_main_thread, ctx->drag);
g_free (This);
}
{
source_drag_context *ctx = (source_drag_context *) This;
- GDK_NOTE (DND, g_print ("idropsource_querycontinuedrag %p esc=%d keystate=0x%lx with state %d", This, fEscapePressed, grfKeyState, ctx->util_data.state));
+ GDK_NOTE (DND, g_print ("idropsource_querycontinuedrag %p esc=%d keystate=0x%lx with state %d\n", This, fEscapePressed, grfKeyState, ctx->util_data.state));
if (!dnd_queue_is_empty ())
process_dnd_queue (FALSE, 0, NULL);
+ GDK_NOTE (DND, g_print ("idropsource_querycontinuedrag state %d\n", ctx->util_data.state));
+
if (ctx->util_data.state == GDK_WIN32_DND_DROPPED)
{
GDK_NOTE (DND, g_print ("DRAGDROP_S_DROP\n"));
}
}
+static void
+maybe_emit_action_changed (GdkWin32DragContext *drag_win32,
+ GdkDragAction actions)
+{
+ if (actions != drag_win32->current_action)
+ {
+ drag_win32->current_action = actions;
+ g_signal_emit_by_name (GDK_DRAG_CONTEXT (drag_win32), "action-changed", actions);
+ }
+}
+
+void
+_gdk_win32_local_drag_give_feedback (GdkDragContext *drag,
+ GdkDragAction actions)
+{
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
+
+ if (drag_win32->drag_status == GDK_DRAG_STATUS_MOTION_WAIT)
+ drag_win32->drag_status = GDK_DRAG_STATUS_DRAG;
+
+ GDK_NOTE (DND, g_print ("_gdk_win32_local_drag_give_feedback: 0x%p\n",
+ drag));
+
+ drag->action = actions;
+ maybe_emit_action_changed (drag_win32, actions);
+}
+
static gboolean
give_feedback (gpointer user_data)
{
if (ddd)
{
- GdkDragContext *context = GDK_DRAG_CONTEXT (feedback->base.opaque_context);
- GdkWin32DragContext *win32_context = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkDragContext *drag = GDK_DRAG_CONTEXT (feedback->base.opaque_context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GDK_NOTE (DND, g_print ("gdk_dnd_handle_drag_status: 0x%p\n",
- context));
-
- context->action = action_for_drop_effect (feedback->received_drop_effect);
+ drag));
- if (context->action != win32_context->current_action)
- {
- win32_context->current_action = context->action;
- g_signal_emit_by_name (context, "action-changed", context->action);
- }
+ drag->action = action_for_drop_effect (feedback->received_drop_effect);
+ maybe_emit_action_changed (drag_win32, drag->action);
}
free_queue_item (&feedback->base);
process_dnd_queue (FALSE, 0, NULL);
feedback = g_new0 (GdkWin32DnDThreadGiveFeedback, 1);
- feedback->base.opaque_context = ctx->context;
+ feedback->base.item_type = GDK_WIN32_DND_THREAD_QUEUE_ITEM_GIVE_FEEDBACK;
+ feedback->base.opaque_context = ctx->drag;
feedback->received_drop_effect = dwEffect;
g_idle_add_full (G_PRIORITY_DEFAULT, give_feedback, feedback, NULL);
GdkWin32DnDThreadGetData *getdata;
GdkWin32ContentFormatPair *pair;
- if (ctx->context == NULL)
+ if (ctx->drag == NULL)
return E_FAIL;
GDK_NOTE (DND, g_print ("idataobject_getdata %p %s ",
getdata = g_new0 (GdkWin32DnDThreadGetData, 1);
getdata->base.item_type = GDK_WIN32_DND_THREAD_QUEUE_ITEM_GET_DATA;
- getdata->base.opaque_context = (gpointer) ctx->context;
+ getdata->base.opaque_context = (gpointer) ctx->drag;
getdata->pair = *pair;
g_idle_add_full (G_PRIORITY_DEFAULT, get_data_response, getdata, NULL);
};
static source_drag_context *
-source_context_new (GdkDragContext *context,
+source_context_new (GdkDragContext *drag,
GdkSurface *window,
GdkContentFormats *formats)
{
- GdkWin32DragContext *context_win32;
+ GdkWin32DragContext *drag_win32;
source_drag_context *result;
- context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
result = g_new0 (source_drag_context, 1);
- result->context = g_object_ref (context);
+ result->drag = g_object_ref (drag);
result->ids.lpVtbl = &ids_vtbl;
result->idsn.lpVtbl = &idsn_vtbl;
result->ref_count = 1;
- result->source_window_handle = GDK_SURFACE_HWND (context->source_surface);
- result->scale = context_win32->scale;
+ result->source_window_handle = GDK_SURFACE_HWND (drag->source_surface);
+ result->scale = drag_win32->scale;
result->util_data.state = GDK_WIN32_DND_PENDING; /* Implicit */
- GDK_NOTE (DND, g_print ("source_context_new: %p (drag context %p)\n", result, result->context));
+ GDK_NOTE (DND, g_print ("source_context_new: %p (drag %p)\n", result, result->drag));
return result;
}
static data_object *
-data_object_new (GdkDragContext *context)
+data_object_new (GdkDragContext *drag)
{
data_object *result;
const char * const *mime_types;
result->ido.lpVtbl = &ido_vtbl;
result->ref_count = 1;
- result->context = context;
+ result->drag = drag;
result->formats = g_array_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair));
- mime_types = gdk_content_formats_get_mime_types (gdk_drag_context_get_formats (context), &n_mime_types);
+ mime_types = gdk_content_formats_get_mime_types (gdk_drag_context_get_formats (drag), &n_mime_types);
for (i = 0; i < n_mime_types; i++)
{
{
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
- if (g_strcmp0 (getenv ("GDK_WIN32_OLE2_DND"), "0") != 0)
- use_ole2_dnd = TRUE;
+ if (g_strcmp0 (getenv ("GDK_WIN32_OLE2_DND"), "0") == 0)
+ use_ole2_dnd = FALSE;
if (use_ole2_dnd)
{
CoUninitialize ();
}
-/* Source side */
-
-void
-_gdk_win32_drag_context_send_local_status_event (GdkDragContext *src_context,
- GdkDragAction action)
-{
- GdkWin32DragContext *src_context_win32 = GDK_WIN32_DRAG_CONTEXT (src_context);
-
- if (src_context_win32->drag_status == GDK_DRAG_STATUS_MOTION_WAIT)
- src_context_win32->drag_status = GDK_DRAG_STATUS_DRAG;
-
- src_context->action = action;
-
- GDK_NOTE (DND, g_print ("gdk_dnd_handle_drag_status: 0x%p\n",
- src_context));
-
- if (action != src_context_win32->current_action)
- {
- src_context_win32->current_action = action;
- g_signal_emit_by_name (src_context, "action-changed", action);
- }
-}
-
-static void
-local_send_leave (GdkDragContext *context,
- guint32 time)
-{
- GdkEvent *tmp_event;
-
- GDK_NOTE (DND, g_print ("local_send_leave: context=%p current_dest_drag=%p\n",
- context,
- current_dest_drag));
-
- if ((current_dest_drag != NULL) &&
- (GDK_WIN32_DRAG_CONTEXT (current_dest_drag)->protocol == GDK_DRAG_PROTO_LOCAL) &&
- (current_dest_drag->source_surface == context->source_surface))
- {
- gdk_drop_emit_leave_event (GDK_DROP (current_dest_drag), FALSE, GDK_CURRENT_TIME);
-
- current_dest_drag = NULL;
- }
-}
-
-static void
-local_send_motion (GdkDragContext *context,
- gint x_root,
- gint y_root,
- GdkDragAction action,
- guint32 time)
-{
- GdkWin32DragContext *context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
-
- GDK_NOTE (DND, g_print ("local_send_motion: context=%p (%d,%d) current_dest_drag=%p\n",
- context, x_root, y_root,
- current_dest_drag));
-
- if ((current_dest_drag != NULL) &&
- (GDK_WIN32_DRAG_CONTEXT (current_dest_drag)->protocol == GDK_DRAG_PROTO_LOCAL) &&
- (current_dest_drag->source_surface == context->source_surface))
- {
- GdkWin32DragContext *current_dest_drag_win32;
-
- gdk_drag_context_set_actions (current_dest_drag, action, action);
-
- current_dest_drag_win32 = GDK_WIN32_DRAG_CONTEXT (current_dest_drag);
- current_dest_drag_win32->util_data.last_x = x_root;
- current_dest_drag_win32->util_data.last_y = y_root;
-
- context_win32->drag_status = GDK_DRAG_STATUS_MOTION_WAIT;
-
- gdk_drop_emit_motion_event (GDK_DROP (current_dest_drag), FALSE, x_root, y_root, time);
- }
-}
-
-static void
-local_send_drop (GdkDragContext *context,
- guint32 time)
-{
- GDK_NOTE (DND, g_print ("local_send_drop: context=%p current_dest_drag=%p\n",
- context,
- current_dest_drag));
-
- if ((current_dest_drag != NULL) &&
- (GDK_WIN32_DRAG_CONTEXT (current_dest_drag)->protocol == GDK_DRAG_PROTO_LOCAL) &&
- (current_dest_drag->source_surface == context->source_surface))
- {
- GdkWin32DragContext *context_win32;
-
- context_win32 = GDK_WIN32_DRAG_CONTEXT (current_dest_drag);
-
- gdk_drop_emit_motion_event (GDK_DROP (current_dest_drag),
- FALSE,
- context_win32->util_data.last_x, context_win32->util_data.last_y,
- GDK_CURRENT_TIME);
-
- current_dest_drag = NULL;
- }
-}
-
-void
-_gdk_win32_drag_do_leave (GdkDragContext *context,
- guint32 time)
-{
- if (context->dest_surface)
- {
- GDK_NOTE (DND, g_print ("gdk_drag_do_leave\n"));
-
- if (!use_ole2_dnd)
- {
- if (GDK_WIN32_DRAG_CONTEXT (context)->protocol == GDK_DRAG_PROTO_LOCAL)
- local_send_leave (context, time);
- }
-
- g_clear_object (&context->dest_surface);
- }
-}
-
static GdkSurface *
create_drag_surface (GdkDisplay *display)
{
}
GdkDragContext *
-_gdk_win32_surface_drag_begin (GdkSurface *window,
- GdkDevice *device,
- GdkContentProvider *content,
- GdkDragAction actions,
- gint dx,
- gint dy)
-{
- GdkDragContext *context;
- GdkWin32DragContext *context_win32;
+_gdk_win32_surface_drag_begin (GdkSurface *window,
+ GdkDevice *device,
+ GdkContentProvider *content,
+ GdkDragAction actions,
+ gint dx,
+ gint dy)
+{
+ GdkDragContext *drag;
+ GdkWin32DragContext *drag_win32;
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
int x_root, y_root;
g_return_val_if_fail (window != NULL, NULL);
- context = gdk_drag_context_new (gdk_surface_get_display (window),
- content,
- window,
- gdk_content_formats_union_serialize_mime_types (gdk_content_provider_ref_storable_formats (content)),
- actions,
- device,
- use_ole2_dnd ? GDK_DRAG_PROTO_OLE2 : GDK_DRAG_PROTO_LOCAL);
+ drag = gdk_drag_context_new (gdk_surface_get_display (window),
+ content,
+ actions,
+ device,
+ use_ole2_dnd ? GDK_DRAG_PROTO_OLE2 : GDK_DRAG_PROTO_LOCAL);
+ drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
- context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ g_set_object (&drag->source_surface, window);
+ drag->is_source = TRUE;
- GDK_NOTE (DND, g_print ("gdk_drag_begin\n"));
+ GDK_NOTE (DND, g_print ("_gdk_win32_surface_drag_begin\n"));
gdk_device_get_position (device, &x_root, &y_root);
x_root += dx;
y_root += dy;
- context_win32->start_x = x_root;
- context_win32->start_y = y_root;
- context_win32->util_data.last_x = context_win32->start_x;
- context_win32->util_data.last_y = context_win32->start_y;
+ drag_win32->start_x = x_root;
+ drag_win32->start_y = y_root;
+ drag_win32->util_data.last_x = drag_win32->start_x;
+ drag_win32->util_data.last_y = drag_win32->start_y;
- g_set_object (&context_win32->ipc_window, window);
+ g_set_object (&drag_win32->ipc_window, window);
- context_win32->drag_surface = create_drag_surface (gdk_surface_get_display (window));
+ drag_win32->drag_surface = create_drag_surface (gdk_surface_get_display (window));
- if (!drag_context_grab (context))
+ if (!drag_context_grab (drag))
{
- g_object_unref (context);
+ g_object_unref (drag);
return FALSE;
}
- if (use_ole2_dnd)
+ if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
{
GdkWin32DnDThreadDoDragDrop *ddd = g_new0 (GdkWin32DnDThreadDoDragDrop, 1);
source_drag_context *source_ctx;
data_object *data_obj;
- source_ctx = source_context_new (context,
+ source_ctx = source_context_new (drag,
window,
- gdk_drag_context_get_formats (context));
- data_obj = data_object_new (context);
+ gdk_drag_context_get_formats (drag));
+ data_obj = data_object_new (drag);
ddd->base.item_type = GDK_WIN32_DND_THREAD_QUEUE_ITEM_DO_DRAG_DROP;
- ddd->base.opaque_context = context_win32;
+ ddd->base.opaque_context = drag_win32;
ddd->src_context = source_ctx;
ddd->src_object = data_obj;
ddd->allowed_drop_effects = 0;
if (actions & GDK_ACTION_LINK)
ddd->allowed_drop_effects |= DROPEFFECT_LINK;
- g_hash_table_replace (clipdrop->active_source_drags, g_object_ref (context), ddd);
+ g_hash_table_replace (clipdrop->active_source_drags, g_object_ref (drag), ddd);
increment_dnd_queue_counter ();
g_async_queue_push (clipdrop->dnd_queue, ddd);
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, thread_wakeup_message, 0, 0));
- context_win32->util_data.state = GDK_WIN32_DND_PENDING;
+ drag_win32->util_data.state = GDK_WIN32_DND_PENDING;
}
- move_drag_surface (context, x_root, y_root);
+ move_drag_surface (drag, x_root, y_root);
- return context;
+ return drag;
}
/* TODO: remove this?
return TRUE;
}
+/* Finds the GdkSurface under cursor. Local DnD protcol
+ * uses this function, since local protocol is implemented
+ * entirely in GDK and cannot rely on the OS to notify
+ * drop targets about drags that move over them.
+ */
static GdkSurface *
-gdk_win32_drag_context_find_surface (GdkDragContext *context,
+gdk_win32_drag_context_find_surface (GdkDragContext *drag,
GdkSurface *drag_surface,
gint x_root,
- gint y_root,
- GdkDragProtocol *protocol)
+ gint y_root)
{
- GdkWin32DragContext *context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GdkSurface *dest_surface, *dw;
find_window_enum_arg a;
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
- a.x = x_root * context_win32->scale - _gdk_offset_x;
- a.y = y_root * context_win32->scale - _gdk_offset_y;
+ a.x = x_root * drag_win32->scale - _gdk_offset_x;
+ a.y = y_root * drag_win32->scale - _gdk_offset_y;
a.ignore = drag_surface ? GDK_SURFACE_HWND (drag_surface) : NULL;
a.result = NULL;
g_object_ref (dest_surface);
}
else
- dest_surface = gdk_win32_surface_foreign_new_for_display (gdk_drag_context_get_display (context), a.result);
-
- if (use_ole2_dnd)
- *protocol = GDK_DRAG_PROTO_OLE2;
- else if (context->source_surface)
- *protocol = GDK_DRAG_PROTO_LOCAL;
- else
- *protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
+ dest_surface = gdk_win32_surface_foreign_new_for_display (gdk_drag_context_get_display (drag), a.result);
}
GDK_NOTE (DND,
- g_print ("gdk_win32_drag_context_find_surface: %p %+d%+d: %p: %p %s\n",
+ g_print ("gdk_win32_drag_context_find_surface: %p %+d%+d: %p: %p\n",
(drag_surface ? GDK_SURFACE_HWND (drag_surface) : NULL),
x_root, y_root,
a.result,
- (dest_surface ? GDK_SURFACE_HWND (dest_surface) : NULL),
- _gdk_win32_drag_protocol_to_string (*protocol)));
+ (dest_surface ? GDK_SURFACE_HWND (dest_surface) : NULL)));
return dest_surface;
}
-static gboolean
-gdk_win32_drag_context_drag_motion (GdkDragContext *context,
- GdkSurface *dest_surface,
- GdkDragProtocol protocol,
- gint x_root,
- gint y_root,
- GdkDragAction suggested_action,
- GdkDragAction possible_actions,
- guint32 time)
+static DWORD
+manufacture_keystate_from_GMT (GdkModifierType state)
{
- GdkWin32DragContext *context_win32;
+ DWORD key_state = 0;
- g_assert (_win32_main_thread == NULL ||
- _win32_main_thread == g_thread_self ());
+ if (state & GDK_MOD1_MASK)
+ key_state |= MK_ALT;
+ if (state & GDK_CONTROL_MASK)
+ key_state |= MK_CONTROL;
+ if (state & GDK_SHIFT_MASK)
+ key_state |= MK_SHIFT;
+ if (state & GDK_BUTTON1_MASK)
+ key_state |= MK_LBUTTON;
+ if (state & GDK_BUTTON2_MASK)
+ key_state |= MK_MBUTTON;
+ if (state & GDK_BUTTON3_MASK)
+ key_state |= MK_RBUTTON;
- g_return_val_if_fail (context != NULL, FALSE);
+ return key_state;
+}
- GDK_NOTE (DND, g_print ("gdk_win32_drag_context_drag_motion: @ %+d:%+d %s suggested=%s, possible=%s\n"
- " context=%p:{actions=%s,suggested=%s,action=%s}\n",
- x_root, y_root,
- _gdk_win32_drag_protocol_to_string (protocol),
- _gdk_win32_drag_action_to_string (suggested_action),
- _gdk_win32_drag_action_to_string (possible_actions),
- context,
- _gdk_win32_drag_action_to_string (gdk_drag_context_get_actions (context)),
- _gdk_win32_drag_action_to_string (gdk_drag_context_get_suggested_action (context)),
- _gdk_win32_drag_action_to_string (context->action)));
+static gboolean
+gdk_win32_local_drag_motion (GdkDragContext *drag,
+ GdkSurface *dest_surface,
+ gint x_root,
+ gint y_root,
+ GdkDragAction possible_actions,
+ DWORD key_state,
+ guint32 time_)
+{
+ GdkWin32DragContext *drag_win32;
+ GdkDrop *drop;
+ GdkDragAction actions;
- context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ g_assert (_win32_main_thread == NULL ||
+ _win32_main_thread == g_thread_self ());
- if (context_win32->drag_surface)
- move_drag_surface (context, x_root, y_root);
+ g_return_val_if_fail (drag != NULL, FALSE);
- if (!use_ole2_dnd)
- {
- if (context->dest_surface == dest_surface)
- {
- GdkDragContext *dest_context;
+ drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
- dest_context = _gdk_win32_drop_context_find (context->source_surface,
- dest_surface);
+ drop = _gdk_win32_get_drop_for_dest_surface (drag->dest_surface);
- if (dest_context)
- gdk_drag_context_set_actions (dest_context, possible_actions, suggested_action);
+ actions = gdk_drag_context_get_actions (drag);
- gdk_drag_context_set_actions (context, possible_actions, suggested_action);
- }
- else
- {
- /* Send a leave to the last destination */
- _gdk_win32_drag_do_leave (context, time);
+ GDK_NOTE (DND, g_print ("gdk_win32_local_drag_motion: @ %+d:%+d possible=%s\n"
+ " dest=%p (current %p) drop=%p drag=%p:{actions=%s,suggested=%s,action=%s}\n",
+ x_root, y_root,
+ _gdk_win32_drag_action_to_string (possible_actions),
+ dest_surface, drag->dest_surface, drop, drag,
+ _gdk_win32_drag_action_to_string (actions),
+ _gdk_win32_drag_action_to_string (gdk_drag_context_get_suggested_action (drag)),
+ _gdk_win32_drag_action_to_string (drag->action)));
- context_win32->drag_status = GDK_DRAG_STATUS_DRAG;
+ if (drag->dest_surface != dest_surface)
+ {
+ /* Send a leave to the last destination */
+ if (drop)
+ _gdk_win32_local_drop_target_dragleave (drop, time_);
- /* Check if new destination accepts drags, and which protocol */
- if (dest_surface)
- {
- g_set_object (&context->dest_surface, dest_surface);
- context_win32->protocol = protocol;
+ g_set_object (&drag->dest_surface, dest_surface);
- switch (protocol)
- {
- case GDK_DRAG_PROTO_LOCAL:
- _gdk_win32_local_send_enter (context, time);
- break;
+ drag_win32->drag_status = GDK_DRAG_STATUS_DRAG;
- default:
- break;
- }
- gdk_drag_context_set_actions (context, possible_actions, suggested_action);
- }
- else
- {
- context->dest_surface = NULL;
- gdk_drag_context_set_actions (context, 0, 0);
- }
+ _gdk_win32_local_drop_target_dragenter (drag, dest_surface, x_root, y_root, key_state, time_, &actions);
- GDK_NOTE (DND, g_print ("gdk_dnd_handle_drag_status: 0x%p\n",
- context));
-
- if (context->action != context_win32->current_action)
- {
- context_win32->current_action = context->action;
- g_signal_emit_by_name (context, "action-changed", context->action);
- }
- }
+ drop = _gdk_win32_get_drop_for_dest_surface (drag->dest_surface);
+ maybe_emit_action_changed (drag_win32, actions);
+ }
- /* Send a drag-motion event */
+ /* Send a drag-motion event */
- context_win32->util_data.last_x = x_root;
- context_win32->util_data.last_y = y_root;
+ drag_win32->util_data.last_x = x_root;
+ drag_win32->util_data.last_y = y_root;
- if (context->dest_surface)
- {
- if (context_win32->drag_status == GDK_DRAG_STATUS_DRAG)
- {
- switch (context_win32->protocol)
- {
- case GDK_DRAG_PROTO_LOCAL:
- local_send_motion (context, x_root, y_root, suggested_action, time);
- break;
+ if (drop != NULL &&
+ drag_win32->drag_status == GDK_DRAG_STATUS_DRAG &&
+ _gdk_win32_local_drop_target_will_emit_motion (drop, x_root, y_root, key_state))
+ {
+ actions = gdk_drag_context_get_actions (drag);
+ drag_win32->drag_status = GDK_DRAG_STATUS_MOTION_WAIT;
- case GDK_DRAG_PROTO_NONE:
- g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_win32_drag_context_drag_motion()");
- break;
+ _gdk_win32_local_drop_target_dragover (drop, drag, x_root, y_root, key_state, time_, &actions);
- default:
- break;
- }
- }
- else
- {
- GDK_NOTE (DND, g_print (" returning TRUE\n"
- " context=%p:{actions=%s,suggested=%s,action=%s}\n",
- context,
- _gdk_win32_drag_action_to_string (gdk_drag_context_get_actions (context)),
- _gdk_win32_drag_action_to_string (gdk_drag_context_get_suggested_action (context)),
- _gdk_win32_drag_action_to_string (context->action)));
- return TRUE;
- }
- }
+ maybe_emit_action_changed (drag_win32, actions);
}
- GDK_NOTE (DND, g_print (" returning FALSE\n"
- " context=%p:{actions=%s,suggested=%s,action=%s}\n",
- context,
- _gdk_win32_drag_action_to_string (gdk_drag_context_get_actions (context)),
- _gdk_win32_drag_action_to_string (gdk_drag_context_get_suggested_action (context)),
- _gdk_win32_drag_action_to_string (context->action)));
- return FALSE;
+ GDK_NOTE (DND, g_print (" returning %s\n"
+ " drag=%p:{actions=%s,suggested=%s,action=%s}\n",
+ (drop != NULL && drag_win32->drag_status == GDK_DRAG_STATUS_DRAG) ? "TRUE" : "FALSE",
+ drag,
+ _gdk_win32_drag_action_to_string (gdk_drag_context_get_actions (drag)),
+ _gdk_win32_drag_action_to_string (gdk_drag_context_get_suggested_action (drag)),
+ _gdk_win32_drag_action_to_string (drag->action)));
+ return (drop != NULL && drag_win32->drag_status == GDK_DRAG_STATUS_DRAG);
}
static void
}
static void
-gdk_win32_drag_context_drag_drop (GdkDragContext *context,
- guint32 time)
+gdk_win32_drag_context_drag_drop (GdkDragContext *drag,
+ guint32 time_)
{
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
- g_return_if_fail (context != NULL);
+ g_return_if_fail (drag != NULL);
- GDK_NOTE (DND, g_print ("gdk_drag_drop\n"));
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_drag_drop\n"));
- if (!use_ole2_dnd)
+ if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
{
- if (context->dest_surface &&
- GDK_WIN32_DRAG_CONTEXT (context)->protocol == GDK_DRAG_PROTO_LOCAL)
- local_send_drop (context, time);
+ GdkDrop *drop;
+ drop = _gdk_win32_get_drop_for_dest_surface (drag->dest_surface);
+
+ if (drop)
+ {
+ GdkDragAction actions;
+
+ actions = gdk_drag_context_get_actions (drag);
+ _gdk_win32_local_drop_target_drop (drop, drag, time_, &actions);
+ maybe_emit_action_changed (drag_win32, actions);
+ _gdk_win32_local_drag_context_drop_response (drag, actions);
+ }
}
- else
+ else if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
{
- gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, context);
+ gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
- GDK_WIN32_DRAG_CONTEXT (context)->util_data.state = GDK_WIN32_DND_DROPPED;
+ drag_win32->util_data.state = GDK_WIN32_DND_DROPPED;
if (ddd)
- send_source_state_update (clipdrop, GDK_WIN32_DRAG_CONTEXT (context), ddd);
+ send_source_state_update (clipdrop, drag_win32, ddd);
}
}
static void
-gdk_win32_drag_context_drag_abort (GdkDragContext *context,
- guint32 time)
+gdk_win32_drag_context_drag_abort (GdkDragContext *drag,
+ guint32 time_)
{
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
- g_return_if_fail (context != NULL);
+ g_return_if_fail (drag != NULL);
- GDK_NOTE (DND, g_print ("gdk_drag_abort\n"));
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_drag_abort\n"));
- if (use_ole2_dnd)
+ if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
{
- gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, context);
+ gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
- GDK_WIN32_DRAG_CONTEXT (context)->util_data.state = GDK_WIN32_DND_NONE;
+ drag_win32->util_data.state = GDK_WIN32_DND_NONE;
if (ddd)
- send_source_state_update (clipdrop, GDK_WIN32_DRAG_CONTEXT (context), ddd);
+ send_source_state_update (clipdrop, drag_win32, ddd);
}
}
static void
-gdk_win32_drag_context_set_cursor (GdkDragContext *context,
+gdk_win32_drag_context_set_cursor (GdkDragContext *drag,
GdkCursor *cursor)
{
- GdkWin32DragContext *context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
- GDK_NOTE (DND, g_print ("gdk_drag_context_set_cursor: 0x%p 0x%p\n", context, cursor));
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_set_cursor: 0x%p 0x%p\n", drag, cursor));
- if (!g_set_object (&context_win32->cursor, cursor))
+ if (!g_set_object (&drag_win32->cursor, cursor))
return;
- if (context_win32->grab_seat)
+ if (drag_win32->grab_seat)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
- gdk_device_grab (gdk_seat_get_pointer (context_win32->grab_seat),
- context_win32->ipc_window,
+ gdk_device_grab (gdk_seat_get_pointer (drag_win32->grab_seat),
+ drag_win32->ipc_window,
GDK_OWNERSHIP_APPLICATION, FALSE,
GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
cursor, GDK_CURRENT_TIME);
typedef struct _GdkDragAnim GdkDragAnim;
struct _GdkDragAnim {
- GdkWin32DragContext *context;
+ GdkWin32DragContext *drag;
GdkFrameClock *frame_clock;
gint64 start_time;
};
static void
gdk_drag_anim_destroy (GdkDragAnim *anim)
{
- g_object_unref (anim->context);
+ g_object_unref (anim->drag);
g_slice_free (GdkDragAnim, anim);
}
gdk_drag_anim_timeout (gpointer data)
{
GdkDragAnim *anim = data;
- GdkWin32DragContext *context = anim->context;
+ GdkWin32DragContext *drag = anim->drag;
GdkFrameClock *frame_clock = anim->frame_clock;
gint64 current_time;
double f;
t = ease_out_cubic (f);
- gdk_surface_show (context->drag_surface);
- gdk_surface_move (context->drag_surface,
- context->util_data.last_x + (context->start_x - context->util_data.last_x) * t - context->hot_x,
- context->util_data.last_y + (context->start_y - context->util_data.last_y) * t - context->hot_y);
- gdk_surface_set_opacity (context->drag_surface, 1.0 - f);
+ gdk_surface_show (drag->drag_surface);
+ gdk_surface_move (drag->drag_surface,
+ drag->util_data.last_x + (drag->start_x - drag->util_data.last_x) * t - drag->hot_x,
+ drag->util_data.last_y + (drag->start_y - drag->util_data.last_y) * t - drag->hot_y);
+ gdk_surface_set_opacity (drag->drag_surface, 1.0 - f);
return G_SOURCE_CONTINUE;
}
static void
-gdk_win32_drag_context_drop_done (GdkDragContext *context,
+gdk_win32_drag_context_drop_done (GdkDragContext *drag,
gboolean success)
{
- GdkWin32DragContext *win32_context = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GdkDragAnim *anim;
/*
cairo_surface_t *win_surface;
*/
guint id;
- GDK_NOTE (DND, g_print ("gdk_drag_context_drop_done: 0x%p %s\n",
- context,
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_drop_done: 0x%p %s\n",
+ drag,
success ? "dropped successfully" : "dropped unsuccessfully"));
/* FIXME: This is temporary, until the code is fixed to ensure that
* gdk_drag_finish () is called by GTK.
*/
- if (use_ole2_dnd)
+ if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
{
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
- gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, context);
+ gpointer ddd = g_hash_table_lookup (clipdrop->active_source_drags, drag);
if (success)
- win32_context->util_data.state = GDK_WIN32_DND_DROPPED;
+ drag_win32->util_data.state = GDK_WIN32_DND_DROPPED;
else
- win32_context->util_data.state = GDK_WIN32_DND_NONE;
+ drag_win32->util_data.state = GDK_WIN32_DND_NONE;
if (ddd)
- send_source_state_update (clipdrop, win32_context, ddd);
+ send_source_state_update (clipdrop, drag_win32, ddd);
+ }
+ else if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
+ {
+
}
+ drag_win32->handle_events = FALSE;
+
if (success)
{
- gdk_surface_hide (win32_context->drag_surface);
+ gdk_surface_hide (drag_win32->drag_surface);
return;
}
/*
- win_surface = _gdk_surface_ref_cairo_surface (win32_context->drag_surface);
- surface = gdk_surface_create_similar_surface (win32_context->drag_surface,
+ win_surface = _gdk_surface_ref_cairo_surface (drag_win32->drag_surface);
+ surface = gdk_surface_create_similar_surface (drag_win32->drag_surface,
cairo_surface_get_content (win_surface),
- gdk_surface_get_width (win32_context->drag_surface),
- gdk_surface_get_height (win32_context->drag_surface));
+ gdk_surface_get_width (drag_win32->drag_surface),
+ gdk_surface_get_height (drag_win32->drag_surface));
cr = cairo_create (surface);
cairo_set_source_surface (cr, win_surface, 0, 0);
cairo_paint (cr);
pattern = cairo_pattern_create_for_surface (surface);
- gdk_surface_set_background_pattern (win32_context->drag_surface, pattern);
+ gdk_surface_set_background_pattern (drag_win32->drag_surface, pattern);
cairo_pattern_destroy (pattern);
cairo_surface_destroy (surface);
*/
anim = g_slice_new0 (GdkDragAnim);
- g_set_object (&anim->context, win32_context);
- anim->frame_clock = gdk_surface_get_frame_clock (win32_context->drag_surface);
+ g_set_object (&anim->drag, drag_win32);
+ anim->frame_clock = gdk_surface_get_frame_clock (drag_win32->drag_surface);
anim->start_time = gdk_frame_clock_get_frame_time (anim->frame_clock);
- GDK_NOTE (DND, g_print ("gdk_drag_context_drop_done: animate the drag window from %d : %d to %d : %d\n",
- win32_context->util_data.last_x, win32_context->util_data.last_y,
- win32_context->start_x, win32_context->start_y));
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_drop_done: animate the drag window from %d : %d to %d : %d\n",
+ drag_win32->util_data.last_x, drag_win32->util_data.last_y,
+ drag_win32->start_x, drag_win32->start_y));
id = g_timeout_add_full (G_PRIORITY_DEFAULT, 17,
gdk_drag_anim_timeout, anim,
}
static gboolean
-drag_context_grab (GdkDragContext *context)
+drag_context_grab (GdkDragContext *drag)
{
- GdkWin32DragContext *context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GdkSeatCapabilities capabilities;
GdkSeat *seat;
GdkCursor *cursor;
- if (!context_win32->ipc_window)
+ GDK_NOTE (DND, g_print ("drag_context_grab: 0x%p with ipc window 0x%p\n",
+ drag,
+ drag_win32->ipc_window));
+
+ if (!drag_win32->ipc_window)
return FALSE;
- seat = gdk_device_get_seat (gdk_drag_context_get_device (context));
+ seat = gdk_device_get_seat (gdk_drag_context_get_device (drag));
capabilities = GDK_SEAT_CAPABILITY_ALL;
- cursor = gdk_drag_get_cursor (context, gdk_drag_context_get_selected_action (context));
- g_set_object (&context_win32->cursor, cursor);
+ cursor = gdk_drag_get_cursor (drag, gdk_drag_context_get_selected_action (drag));
+ g_set_object (&drag_win32->cursor, cursor);
- if (gdk_seat_grab (seat, context_win32->ipc_window,
+ if (gdk_seat_grab (seat, drag_win32->ipc_window,
capabilities, FALSE,
- context_win32->cursor, NULL, NULL, NULL) != GDK_GRAB_SUCCESS)
+ drag_win32->cursor, NULL, NULL, NULL) != GDK_GRAB_SUCCESS)
return FALSE;
- g_set_object (&context_win32->grab_seat, seat);
+ g_set_object (&drag_win32->grab_seat, seat);
/* TODO: Should be grabbing keys here, to support keynav. SetWindowsHookEx()? */
}
static void
-drag_context_ungrab (GdkDragContext *context)
+drag_context_ungrab (GdkDragContext *drag)
{
- GdkWin32DragContext *context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
- if (!context_win32->grab_seat)
+ GDK_NOTE (DND, g_print ("drag_context_ungrab: 0x%p 0x%p\n",
+ drag,
+ drag_win32->grab_seat));
+
+ if (!drag_win32->grab_seat)
return;
- gdk_seat_ungrab (context_win32->grab_seat);
+ gdk_seat_ungrab (drag_win32->grab_seat);
- g_clear_object (&context_win32->grab_seat);
+ g_clear_object (&drag_win32->grab_seat);
/* TODO: Should be ungrabbing keys here */
}
static void
-gdk_win32_drag_context_cancel (GdkDragContext *context,
+gdk_win32_drag_context_cancel (GdkDragContext *drag,
GdkDragCancelReason reason)
{
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
+
const gchar *reason_str = NULL;
switch (reason)
{
break;
}
- GDK_NOTE (DND, g_print ("gdk_drag_context_cancel: 0x%p %s\n",
- context,
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_cancel: 0x%p %s\n",
+ drag,
reason_str));
- drag_context_ungrab (context);
- gdk_drag_drop_done (context, FALSE);
+
+ if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
+ {
+ GdkDrop *drop = _gdk_win32_get_drop_for_dest_surface (drag->dest_surface);
+ if (drop)
+ _gdk_win32_local_drop_target_dragleave (drop, GDK_CURRENT_TIME);
+ drop = NULL;
+ }
+
+ gdk_drag_context_set_cursor (drag, NULL);
+ drag_context_ungrab (drag);
+ gdk_drag_drop_done (drag, FALSE);
}
static void
-gdk_win32_drag_context_drop_performed (GdkDragContext *context,
+gdk_win32_drag_context_drop_performed (GdkDragContext *drag,
guint32 time_)
{
- GDK_NOTE (DND, g_print ("gdk_drag_context_drop_performed: 0x%p %u\n",
- context,
+ GDK_NOTE (DND, g_print ("gdk_win32_drag_context_drop_performed: 0x%p %u\n",
+ drag,
time_));
- gdk_drag_drop (context, time_);
- drag_context_ungrab (context);
+ gdk_drag_drop (drag, time_);
+ gdk_drag_context_set_cursor (drag, NULL);
+ drag_context_ungrab (drag);
}
#define BIG_STEP 20
#define SMALL_STEP 1
static void
-gdk_drag_get_current_actions (GdkModifierType state,
- gint button,
- GdkDragAction actions,
- GdkDragAction *suggested_action,
- GdkDragAction *possible_actions)
+gdk_local_drag_update (GdkDragContext *drag,
+ gdouble x_root,
+ gdouble y_root,
+ DWORD grfKeyState,
+ guint32 evtime)
{
- *suggested_action = 0;
- *possible_actions = 0;
-
- if ((button == GDK_BUTTON_MIDDLE || button == GDK_BUTTON_SECONDARY) && (actions & GDK_ACTION_ASK))
- {
- *suggested_action = GDK_ACTION_ASK;
- *possible_actions = actions;
- }
- else if (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))
- {
- if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK))
- {
- if (actions & GDK_ACTION_LINK)
- {
- *suggested_action = GDK_ACTION_LINK;
- *possible_actions = GDK_ACTION_LINK;
- }
- }
- else if (state & GDK_CONTROL_MASK)
- {
- if (actions & GDK_ACTION_COPY)
- {
- *suggested_action = GDK_ACTION_COPY;
- *possible_actions = GDK_ACTION_COPY;
- }
- }
- else
- {
- if (actions & GDK_ACTION_MOVE)
- {
- *suggested_action = GDK_ACTION_MOVE;
- *possible_actions = GDK_ACTION_MOVE;
- }
- }
- }
- else
- {
- *possible_actions = actions;
-
- if ((state & (GDK_MOD1_MASK)) && (actions & GDK_ACTION_ASK))
- *suggested_action = GDK_ACTION_ASK;
- else if (actions & GDK_ACTION_COPY)
- *suggested_action = GDK_ACTION_COPY;
- else if (actions & GDK_ACTION_MOVE)
- *suggested_action = GDK_ACTION_MOVE;
- else if (actions & GDK_ACTION_LINK)
- *suggested_action = GDK_ACTION_LINK;
- }
-}
-
-static void
-gdk_drag_update (GdkDragContext *context,
- gdouble x_root,
- gdouble y_root,
- GdkModifierType mods,
- guint32 evtime)
-{
- GdkWin32DragContext *win32_context = GDK_WIN32_DRAG_CONTEXT (context);
- GdkDragAction action, possible_actions;
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GdkSurface *dest_surface;
- GdkDragProtocol protocol;
g_assert (_win32_main_thread == NULL ||
_win32_main_thread == g_thread_self ());
- gdk_drag_get_current_actions (mods, GDK_BUTTON_PRIMARY, win32_context->actions,
- &action, &possible_actions);
-
- dest_surface = gdk_win32_drag_context_find_surface (context,
- win32_context->drag_surface,
- x_root, y_root, &protocol);
+ dest_surface = gdk_win32_drag_context_find_surface (drag,
+ drag_win32->drag_surface,
+ x_root, y_root);
- gdk_win32_drag_context_drag_motion (context, dest_surface, protocol, x_root, y_root,
- action, possible_actions, evtime);
+ gdk_win32_local_drag_motion (drag, dest_surface, x_root, y_root,
+ gdk_drag_context_get_actions (drag),
+ grfKeyState, evtime);
}
static gboolean
-gdk_dnd_handle_motion_event (GdkDragContext *context,
+gdk_dnd_handle_motion_event (GdkDragContext *drag,
const GdkEventMotion *event)
{
GdkModifierType state;
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
+ DWORD key_state;
if (!gdk_event_get_state ((GdkEvent *) event, &state))
return FALSE;
GDK_NOTE (DND, g_print ("gdk_dnd_handle_motion_event: 0x%p\n",
- context));
+ drag));
- gdk_drag_update (context, event->x_root, event->y_root, state,
- gdk_event_get_time ((GdkEvent *) event));
+ if (drag_win32->drag_surface)
+ move_drag_surface (drag, event->x_root, event->y_root);
+ key_state = manufacture_keystate_from_GMT (state);
- if (use_ole2_dnd)
+ if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
+ {
+ gdk_local_drag_update (drag, event->x_root, event->y_root, key_state,
+ gdk_event_get_time ((GdkEvent *) event));
+ }
+ else if (drag_win32->protocol == GDK_DRAG_PROTO_OLE2)
{
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
- GdkWin32DragContext *context_win32;
- DWORD key_state = 0;
- BYTE kbd_state[256];
-
- /* TODO: is this correct? We get the state at current moment,
- * not at the moment when the event was emitted.
- * I don't think that it ultimately serves any purpose,
- * as our IDropSource does not react to the keyboard
- * state changes (rather, it reacts to our status updates),
- * but there's no way to tell what goes inside DoDragDrop(),
- * so we should send at least *something* that looks right.
- */
- API_CALL (GetKeyboardState, (kbd_state));
-
- if (kbd_state[VK_CONTROL] & 0x80)
- key_state |= MK_CONTROL;
- if (kbd_state[VK_SHIFT] & 0x80)
- key_state |= MK_SHIFT;
- if (kbd_state[VK_LBUTTON] & 0x80)
- key_state |= MK_LBUTTON;
- if (kbd_state[VK_MBUTTON] & 0x80)
- key_state |= MK_MBUTTON;
- if (kbd_state[VK_RBUTTON] & 0x80)
- key_state |= MK_RBUTTON;
GDK_NOTE (DND, g_print ("Post WM_MOUSEMOVE keystate=%lu\n", key_state));
- context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
-
- context_win32->util_data.last_x = event->x_root;
- context_win32->util_data.last_y = event->y_root;
+ drag_win32->util_data.last_x = event->x_root;
+ drag_win32->util_data.last_y = event->y_root;
API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id,
WM_MOUSEMOVE,
key_state,
- MAKELPARAM ((event->x_root - _gdk_offset_x) * context_win32->scale,
- (event->y_root - _gdk_offset_y) * context_win32->scale)));
+ MAKELPARAM ((event->x_root - _gdk_offset_x) * drag_win32->scale,
+ (event->y_root - _gdk_offset_y) * drag_win32->scale)));
}
return TRUE;
}
static gboolean
-gdk_dnd_handle_key_event (GdkDragContext *context,
+gdk_dnd_handle_key_event (GdkDragContext *drag,
const GdkEventKey *event)
{
- GdkWin32DragContext *win32_context = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GdkModifierType state;
GdkDevice *pointer;
gint dx, dy;
+ if (!gdk_event_get_state ((GdkEvent *) event, &state))
+ return FALSE;
+
GDK_NOTE (DND, g_print ("gdk_dnd_handle_key_event: 0x%p\n",
- context));
+ drag));
dx = dy = 0;
- state = event->state;
pointer = gdk_device_get_associated_device (gdk_event_get_device ((GdkEvent *) event));
if (event->any.type == GDK_KEY_PRESS)
switch (event->keyval)
{
case GDK_KEY_Escape:
- gdk_drag_context_cancel (context, GDK_DRAG_CANCEL_USER_CANCELLED);
+ gdk_drag_context_cancel (drag, GDK_DRAG_CANCEL_USER_CANCELLED);
return TRUE;
case GDK_KEY_space:
case GDK_KEY_ISO_Enter:
case GDK_KEY_KP_Enter:
case GDK_KEY_KP_Space:
- if ((gdk_drag_context_get_selected_action (context) != 0) &&
- (gdk_drag_context_get_dest_surface (context) != NULL))
+ if ((gdk_drag_context_get_selected_action (drag) != 0) &&
+ (gdk_drag_context_get_dest_surface (drag) != NULL))
{
- g_signal_emit_by_name (context, "drop-performed",
+ g_signal_emit_by_name (drag, "drop-performed",
gdk_event_get_time ((GdkEvent *) event));
}
else
- gdk_drag_context_cancel (context, GDK_DRAG_CANCEL_NO_TARGET);
+ gdk_drag_context_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
return TRUE;
if (dx != 0 || dy != 0)
{
- win32_context->util_data.last_x += dx;
- win32_context->util_data.last_y += dy;
- gdk_device_warp (pointer, win32_context->util_data.last_x, win32_context->util_data.last_y);
+ drag_win32->util_data.last_x += dx;
+ drag_win32->util_data.last_y += dy;
+ gdk_device_warp (pointer, drag_win32->util_data.last_x, drag_win32->util_data.last_y);
}
- gdk_drag_update (context, win32_context->util_data.last_x, win32_context->util_data.last_y, state,
- gdk_event_get_time ((GdkEvent *) event));
+ if (drag_win32->drag_surface)
+ move_drag_surface (drag, drag_win32->util_data.last_x, drag_win32->util_data.last_y);
+
+ if (drag_win32->protocol == GDK_DRAG_PROTO_LOCAL)
+ gdk_local_drag_update (drag, drag_win32->util_data.last_x, drag_win32->util_data.last_y,
+ manufacture_keystate_from_GMT (state),
+ gdk_event_get_time ((GdkEvent *) event));
return TRUE;
}
static gboolean
-gdk_dnd_handle_grab_broken_event (GdkDragContext *context,
+gdk_dnd_handle_grab_broken_event (GdkDragContext *drag,
const GdkEventGrabBroken *event)
{
- GdkWin32DragContext *win32_context = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GDK_NOTE (DND, g_print ("gdk_dnd_handle_grab_broken_event: 0x%p\n",
- context));
+ drag));
/* Don't cancel if we break the implicit grab from the initial button_press.
* Also, don't cancel if we re-grab on the widget or on our IPC window, for
* example, when changing the drag cursor.
*/
if (event->implicit ||
- event->grab_surface == win32_context->drag_surface ||
- event->grab_surface == win32_context->ipc_window)
+ event->grab_surface == drag_win32->drag_surface ||
+ event->grab_surface == drag_win32->ipc_window)
return FALSE;
if (gdk_event_get_device ((GdkEvent *) event) !=
- gdk_drag_context_get_device (context))
+ gdk_drag_context_get_device (drag))
return FALSE;
- gdk_drag_context_cancel (context, GDK_DRAG_CANCEL_ERROR);
+ gdk_drag_context_cancel (drag, GDK_DRAG_CANCEL_ERROR);
return TRUE;
}
static gboolean
-gdk_dnd_handle_button_event (GdkDragContext *context,
+gdk_dnd_handle_button_event (GdkDragContext *drag,
const GdkEventButton *event)
{
GDK_NOTE (DND, g_print ("gdk_dnd_handle_button_event: 0x%p\n",
- context));
+ drag));
#if 0
/* FIXME: Check the button matches */
- if (event->button != win32_context->button)
+ if (event->button != drag_win32->button)
return FALSE;
#endif
- if ((gdk_drag_context_get_selected_action (context) != 0))
+ if ((gdk_drag_context_get_selected_action (drag) != 0))
{
- g_signal_emit_by_name (context, "drop-performed",
+ g_signal_emit_by_name (drag, "drop-performed",
gdk_event_get_time ((GdkEvent *) event));
}
else
- gdk_drag_context_cancel (context, GDK_DRAG_CANCEL_NO_TARGET);
+ gdk_drag_context_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
- return TRUE;
+ /* Make sure GTK gets mouse release button event */
+ return FALSE;
}
gboolean
-gdk_win32_drag_context_handle_event (GdkDragContext *context,
+gdk_win32_drag_context_handle_event (GdkDragContext *drag,
const GdkEvent *event)
{
- GdkWin32DragContext *win32_context = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
- if (!context->is_source)
+ if (!drag->is_source)
return FALSE;
- if (!win32_context->grab_seat)
+ if (!drag_win32->grab_seat)
return FALSE;
+ if (!drag_win32->handle_events)
+ {
+ /* FIXME: remove this functionality once gtk no longer calls DnD after drag_done() */
+ g_warning ("Got an event %d for drag context %p, even though it's done!", event->any.type, drag);
+ return FALSE;
+ }
switch (event->any.type)
{
case GDK_MOTION_NOTIFY:
- return gdk_dnd_handle_motion_event (context, &event->motion);
+ return gdk_dnd_handle_motion_event (drag, &event->motion);
case GDK_BUTTON_RELEASE:
- return gdk_dnd_handle_button_event (context, &event->button);
+ return gdk_dnd_handle_button_event (drag, &event->button);
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
- return gdk_dnd_handle_key_event (context, &event->key);
+ return gdk_dnd_handle_key_event (drag, &event->key);
case GDK_GRAB_BROKEN:
- return gdk_dnd_handle_grab_broken_event (context, &event->grab_broken);
+ return gdk_dnd_handle_grab_broken_event (drag, &event->grab_broken);
default:
break;
}
}
void
-gdk_win32_drag_context_action_changed (GdkDragContext *context,
+gdk_win32_drag_context_action_changed (GdkDragContext *drag,
GdkDragAction action)
{
GdkCursor *cursor;
- cursor = gdk_drag_get_cursor (context, action);
- gdk_drag_context_set_cursor (context, cursor);
+ cursor = gdk_drag_get_cursor (drag, action);
+ gdk_drag_context_set_cursor (drag, cursor);
}
static GdkSurface *
-gdk_win32_drag_context_get_drag_surface (GdkDragContext *context)
+gdk_win32_drag_context_get_drag_surface (GdkDragContext *drag)
{
- return GDK_WIN32_DRAG_CONTEXT (context)->drag_surface;
+ return GDK_WIN32_DRAG_CONTEXT (drag)->drag_surface;
}
static void
-gdk_win32_drag_context_set_hotspot (GdkDragContext *context,
+gdk_win32_drag_context_set_hotspot (GdkDragContext *drag,
gint hot_x,
gint hot_y)
{
- GdkWin32DragContext *win32_context = GDK_WIN32_DRAG_CONTEXT (context);
+ GdkWin32DragContext *drag_win32 = GDK_WIN32_DRAG_CONTEXT (drag);
GDK_NOTE (DND, g_print ("gdk_drag_context_set_hotspot: 0x%p %d:%d\n",
- context,
+ drag,
hot_x, hot_y));
- win32_context->hot_x = hot_x;
- win32_context->hot_y = hot_y;
+ drag_win32->hot_x = hot_x;
+ drag_win32->hot_y = hot_y;
- if (win32_context->grab_seat)
+ if (drag_win32->grab_seat)
{
/* DnD is managed, update current position */
- move_drag_surface (context, win32_context->util_data.last_x, win32_context->util_data.last_y);
+ move_drag_surface (drag, drag_win32->util_data.last_x, drag_win32->util_data.last_y);
}
}
#include <gdk/gdk.h>
#include <glib/gstdio.h>
-typedef struct
+#define GDK_TYPE_WIN32_DROP (gdk_win32_drop_get_type ())
+#define GDK_WIN32_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WIN32_DROP, GdkWin32Drop))
+#define GDK_WIN32_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_DROP, GdkWin32DropClass))
+#define GDK_IS_WIN32_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WIN32_DROP))
+#define GDK_IS_WIN32_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_DROP))
+#define GDK_WIN32_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_DROP, GdkWin32DropClass))
+
+typedef struct _GdkWin32Drop GdkWin32Drop;
+typedef struct _GdkWin32DropClass GdkWin32DropClass;
+
+struct _GdkWin32Drop
+{
+ GdkDrop drop;
+
+ /* The drag protocol being in use */
+ GdkDragProtocol protocol;
+
+ /* The actions supported at GTK level. Set in gdk_win32_drop_status(). */
+ GdkDragAction actions;
+
+ guint scale; /* Temporarily caches the HiDPI scale */
+ gint last_x; /* Coordinates from last event, in GDK space */
+ gint last_y;
+ DWORD last_key_state; /* Key state from last event */
+
+ /* Just like GdkDrop->formats, but an array, and with format IDs
+ * stored inside.
+ */
+ GArray *droptarget_w32format_contentformat_map;
+
+ /* The list from WM_DROPFILES is store here temporarily,
+ * until the next gdk_win32_drop_read_async ()
+ */
+ gchar *dropfiles_list;
+
+ guint drop_finished : 1; /* FALSE until gdk_drop_finish() is called */
+ guint drop_failed : 1; /* Whether the drop was unsuccessful */
+};
+
+struct _GdkWin32DropClass
+{
+ GdkDropClass parent_class;
+};
+
+GType gdk_win32_drop_get_type (void);
+
+G_DEFINE_TYPE (GdkWin32Drop, gdk_win32_drop, GDK_TYPE_DROP)
+
+/* This structure is presented to COM as an object that
+ * implements IDropTarget interface. Every surface that
+ * can be a droptarget has one of these.
+ */
+struct _drop_target_context
{
IDropTarget idt;
gint ref_count;
- GdkDragContext *context;
- /* We get this at the object creation time and keep
- * it indefinitely. Contexts come and go, but this window
- * remains the same.
+
+ /* The drop object we create when a drag enters our surface.
+ * The drop objóct is destroyed when the drag leaves.
*/
- GdkSurface *dest_surface;
+ GdkDrop *drop;
+ /* We get this at the object at creation time and keep
+ * it indefinitely. Drops (see above) come and go, but
+ * this surface remains the same.
+ * This is not a reference, as drop_target_context must not
+ * outlive the surface it's attached to.
+ * drop_target_context is not folded into GdkSurfaceImplWin32
+ * only because it's easier to present it to COM as a separate
+ * object when it's allocated separately.
+ */
+ GdkSurface *surface;
/* This is given to us by the OS, we store it here
- * until the drag leaves our window.
+ * until the drag leaves our window. It is referenced
+ * (using COM reference counting).
*/
IDataObject *data_object;
-} target_drag_context;
-
-static GList *dnd_target_contexts;
-static GdkDragContext *current_dest_drag = NULL;
+};
+/* TRUE to use OLE2 protocol, FALSE to use local protocol */
static gboolean use_ole2_dnd = TRUE;
-G_DEFINE_TYPE (GdkWin32DropContext, gdk_win32_drop_context, GDK_TYPE_DRAG_CONTEXT)
-
static void
-gdk_win32_drop_context_init (GdkWin32DropContext *context)
+gdk_win32_drop_init (GdkWin32Drop *drop)
{
- if (!use_ole2_dnd)
- {
- dnd_target_contexts = g_list_prepend (dnd_target_contexts, context);
- }
- else
- {
- }
+ drop->droptarget_w32format_contentformat_map = g_array_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair));
- GDK_NOTE (DND, g_print ("gdk_drop_context_init %p\n", context));
+ GDK_NOTE (DND, g_print ("gdk_win32_drop_init %p\n", drop));
}
static void
-gdk_win32_drop_context_finalize (GObject *object)
+gdk_win32_drop_finalize (GObject *object)
{
- GdkDragContext *context;
- GdkWin32DropContext *context_win32;
+ GdkDrop *drop;
+ GdkWin32Drop *drop_win32;
- GDK_NOTE (DND, g_print ("gdk_drop_context_finalize %p\n", object));
+ GDK_NOTE (DND, g_print ("gdk_win32_drop_finalize %p\n", object));
- g_return_if_fail (GDK_IS_WIN32_DROP_CONTEXT (object));
+ drop = GDK_DROP (object);
- context = GDK_DRAG_CONTEXT (object);
- context_win32 = GDK_WIN32_DROP_CONTEXT (context);
+ drop_win32 = GDK_WIN32_DROP (drop);
- if (!use_ole2_dnd)
- {
- dnd_target_contexts = g_list_remove (dnd_target_contexts, context);
-
- if (context == current_dest_drag)
- current_dest_drag = NULL;
- }
-
- g_clear_object (&context_win32->local_source_context);
+ g_array_unref (drop_win32->droptarget_w32format_contentformat_map);
- g_array_unref (context_win32->droptarget_w32format_contentformat_map);
-
- G_OBJECT_CLASS (gdk_win32_drop_context_parent_class)->finalize (object);
+ G_OBJECT_CLASS (gdk_win32_drop_parent_class)->finalize (object);
}
-/* Drag Contexts */
-
-static GdkDragContext *
-gdk_drop_context_new (GdkDisplay *display,
- GdkSurface *source_surface,
- GdkSurface *dest_surface,
- GdkContentFormats *formats,
- GdkDragAction actions,
- GdkDragProtocol protocol)
+static GdkDrop *
+gdk_drop_new (GdkDisplay *display,
+ GdkDevice *device,
+ GdkDragContext *drag,
+ GdkContentFormats *formats,
+ GdkSurface *surface,
+ GdkDragProtocol protocol)
{
- GdkWin32DropContext *context_win32;
+ GdkWin32Drop *drop_win32;
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
- GdkDragContext *context;
- context_win32 = g_object_new (GDK_TYPE_WIN32_DROP_CONTEXT,
- "device", gdk_seat_get_pointer (gdk_display_get_default_seat (display)),
- "formats", formats,
- "surface", dest_surface,
- NULL);
-
- context = GDK_DRAG_CONTEXT (context_win32);
+ drop_win32 = g_object_new (GDK_TYPE_WIN32_DROP,
+ "device", device,
+ "drag", drag,
+ "formats", formats,
+ "surface", surface,
+ NULL);
if (win32_display->has_fixed_scale)
- context_win32->scale = win32_display->surface_scale;
+ drop_win32->scale = win32_display->surface_scale;
else
- context_win32->scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, NULL, NULL, NULL);
-
- context_win32->droptarget_w32format_contentformat_map = g_array_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair));
+ drop_win32->scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, NULL, NULL, NULL);
- context->is_source = FALSE;
- g_set_object (&context->source_surface, source_surface);
- g_set_object (&context->dest_surface, dest_surface);
- gdk_drag_context_set_actions (context, actions, actions);
- context_win32->protocol = protocol;
+ drop_win32->protocol = protocol;
- gdk_content_formats_unref (formats);
-
- return context;
+ return GDK_DROP (drop_win32);
}
-GdkDragContext *
-_gdk_win32_drop_context_find (GdkSurface *source,
- GdkSurface *dest)
+/* Gets the GdkDrop that corresponds to a particular GdkSurface.
+ * Will be NULL for surfaces that are not registered as drop targets,
+ * or for surfaces that are currently not under the drag cursor.
+ */
+GdkDrop *
+_gdk_win32_get_drop_for_dest_surface (GdkSurface *dest)
{
- GList *tmp_list = dnd_target_contexts;
- GdkDragContext *context;
+ GdkSurfaceImplWin32 *impl;
- while (tmp_list)
- {
- context = (GdkDragContext *) tmp_list->data;
+ if (dest == NULL)
+ return NULL;
- if (!context->is_source &&
- ((source == NULL) || (context->source_surface && (context->source_surface == source))) &&
- ((dest == NULL) || (context->dest_surface && (context->dest_surface == dest))))
- return context;
+ impl = GDK_SURFACE_IMPL_WIN32 (dest->impl);
- tmp_list = tmp_list->next;
- }
+ if (impl->drop_target != NULL)
+ return impl->drop_target->drop;
- return NULL;
+ return impl->drop;
}
+
#define PRINT_GUID(guid) \
g_print ("%.08lx-%.04x-%.04x-%.02x%.02x-%.02x%.02x%.02x%.02x%.02x%.02x", \
((gulong *) guid)[0], \
((guchar *) guid)[14], \
((guchar *) guid)[15]);
-/* map windows -> target drag contexts. The table
- * owns a ref to each context.
- */
-static GHashTable* target_ctx_for_window = NULL;
-
-static target_drag_context *
-find_droptarget_for_target_context (GdkDragContext *context)
-{
- return g_hash_table_lookup (target_ctx_for_window, GDK_SURFACE_HWND (context->dest_surface));
-}
-
static ULONG STDMETHODCALLTYPE
idroptarget_addref (LPDROPTARGET This)
{
- target_drag_context *ctx = (target_drag_context *) This;
+ drop_target_context *ctx = (drop_target_context *) This;
int ref_count = ++ctx->ref_count;
static ULONG STDMETHODCALLTYPE
idroptarget_release (LPDROPTARGET This)
{
- target_drag_context *ctx = (target_drag_context *) This;
+ drop_target_context *ctx = (drop_target_context *) This;
int ref_count = --ctx->ref_count;
if (ref_count == 0)
{
- g_object_unref (ctx->context);
- g_clear_object (&ctx->dest_surface);
+ g_clear_object (&ctx->drop);
g_free (This);
}
return ref_count;
}
-static GdkDragAction
-get_suggested_action (GdkWin32DropContext *win32_context,
- DWORD grfKeyState)
-{
- /* This is the yucky Windows standard: Force link action if both
- * Control and Alt are down, copy if Control is down alone, move if
- * Alt is down alone, or use default of move within the app or copy
- * when origin of the drag is in another app.
- */
- if (grfKeyState & MK_CONTROL && grfKeyState & MK_SHIFT)
- return GDK_ACTION_LINK; /* Link action not supported */
- else if (grfKeyState & MK_CONTROL)
- return GDK_ACTION_COPY;
- else if (grfKeyState & MK_ALT)
- return GDK_ACTION_MOVE;
- else if (win32_context->local_source_context &&
- win32_context->local_source_context->util_data.state == GDK_WIN32_DND_DRAGGING)
- return GDK_ACTION_MOVE;
- else
- return GDK_ACTION_COPY;
- /* Any way to determine when to add in DROPEFFECT_SCROLL? */
-}
-
-static DWORD
-drop_effect_for_action (GdkDragAction action)
-{
- DWORD effect = 0;
-
- if (action & GDK_ACTION_MOVE)
- effect |= DROPEFFECT_MOVE;
- if (action & GDK_ACTION_LINK)
- effect |= DROPEFFECT_LINK;
- if (action & GDK_ACTION_COPY)
- effect |= DROPEFFECT_COPY;
-
- if (effect == 0)
- effect = DROPEFFECT_NONE;
-
- return effect;
-}
-
static GdkContentFormats *
-query_targets (LPDATAOBJECT pDataObj,
- GArray *format_target_map)
+query_object_formats (LPDATAOBJECT pDataObj,
+ GArray *w32format_contentformat_map)
{
IEnumFORMATETC *pfmt = NULL;
FORMATETC fmt;
- GList *result = NULL;
HRESULT hr;
GdkContentFormatsBuilder *builder;
GdkContentFormats *result_formats;
- GList *p;
+
+ builder = gdk_content_formats_builder_new ();
hr = IDataObject_EnumFormatEtc (pDataObj, DATADIR_GET, &pfmt);
GDK_NOTE (DND, g_print ("supported unnamed? source format 0x%x\n", fmt.cfFormat));
g_free (registered_name);
- _gdk_win32_add_w32format_to_pairs (fmt.cfFormat, format_target_map, &result);
+ _gdk_win32_add_w32format_to_pairs (fmt.cfFormat, w32format_contentformat_map, builder);
hr = IEnumFORMATETC_Next (pfmt, 1, &fmt, NULL);
}
if (pfmt)
IEnumFORMATETC_Release (pfmt);
- builder = gdk_content_formats_builder_new ();
-
- for (p = g_list_reverse (result); p; p = p->next)
- gdk_content_formats_builder_add_mime_type (builder, (const gchar *) p->data);
-
result_formats = gdk_content_formats_builder_free_to_formats (builder);
- g_list_free (result);
return result_formats;
}
IDataObject_AddRef (*location);
}
+/* Figures out an action that the user forces onto us by
+ * pressing some modifier keys.
+ */
+static GdkDragAction
+get_user_action (DWORD grfKeyState)
+{
+ /* Windows explorer does this:
+ * 'C'ontrol for 'C'opy
+ * a'L't (or Contro'L' + Shift) for 'L'ink
+ * Shift for Move
+ * Control + Alt or Shift + Alt or Control + Alt + Shift for Default action (see below).
+ *
+ * Default action is 'Copy' when dragging between drives, 'Move' otherwise.
+ * For GTK 'between drives' turns into 'between applications'.
+ */
+ if (((grfKeyState & (MK_CONTROL | MK_ALT)) == (MK_CONTROL | MK_ALT)) ||
+ ((grfKeyState & (MK_ALT | MK_SHIFT)) == (MK_ALT | MK_SHIFT)) ||
+ ((grfKeyState & (MK_CONTROL | MK_ALT | MK_SHIFT)) == (MK_CONTROL | MK_ALT | MK_SHIFT)))
+ {
+ return 0;
+ }
+ else if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == (MK_CONTROL | MK_SHIFT))
+ return GDK_ACTION_LINK;
+ else if (grfKeyState & MK_CONTROL)
+ return GDK_ACTION_COPY;
+ else if (grfKeyState & MK_ALT)
+ return GDK_ACTION_MOVE;
+
+ return 0;
+}
+
+static DWORD
+drop_effect_for_actions (GdkDragAction actions)
+{
+ DWORD effects = 0;
+ int effect_count = 0;
+
+ if (actions & GDK_ACTION_MOVE)
+ {
+ effects |= DROPEFFECT_MOVE;
+ effect_count++;
+ }
+ if (actions & GDK_ACTION_LINK)
+ {
+ effects |= DROPEFFECT_LINK;
+ effect_count++;
+ }
+ if (actions & GDK_ACTION_COPY)
+ {
+ effects |= DROPEFFECT_COPY;
+ effect_count++;
+ }
+
+ if (effect_count == 0)
+ effects = DROPEFFECT_NONE;
+ else if (effect_count > 1)
+ /* Actually it should be DROPEFECT_ASK, but Windows doesn't support that */
+ effects = DROPEFFECT_COPY;
+
+ return effects;
+}
+
+static GdkDragAction
+actions_for_drop_effects (DWORD effects)
+{
+ GdkDragAction actions = 0;
+
+ if (effects & DROPEFFECT_MOVE)
+ actions |= GDK_ACTION_MOVE;
+ if (effects & DROPEFFECT_LINK)
+ actions |= GDK_ACTION_LINK;
+ if (effects & DROPEFFECT_COPY)
+ actions |= GDK_ACTION_COPY;
+
+ return actions;
+}
+
+static GdkDragAction
+filter_actions (GdkDragAction actions,
+ GdkDragAction filter)
+{
+ return actions & filter;
+}
+
+static GdkDragAction
+set_source_actions_helper (GdkDrop *drop,
+ GdkDragAction actions,
+ DWORD grfKeyState)
+{
+ GdkDragAction user_action;
+
+ user_action = get_user_action (grfKeyState);
+
+ if (user_action != 0)
+ gdk_drop_set_actions (drop, user_action);
+ else
+ gdk_drop_set_actions (drop, actions);
+
+ return actions;
+}
+
+void
+_gdk_win32_local_drop_target_dragenter (GdkDragContext *drag,
+ GdkSurface *dest_surface,
+ gint x_root,
+ gint y_root,
+ DWORD grfKeyState,
+ guint32 time_,
+ GdkDragAction *actions)
+{
+ GdkDrop *drop;
+ GdkWin32Drop *drop_win32;
+ GdkDisplay *display;
+ GdkDragAction source_actions;
+ GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (dest_surface->impl);
+
+ GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragenter %p @ %d : %d"
+ " for dest window 0x%p"
+ ". actions = %s\n",
+ drag, x_root, y_root,
+ dest_surface,
+ _gdk_win32_drag_action_to_string (*actions)));
+
+ display = gdk_surface_get_display (dest_surface);
+ drop = gdk_drop_new (display,
+ gdk_seat_get_pointer (gdk_display_get_default_seat (display)),
+ drag,
+ gdk_content_formats_ref (gdk_drag_context_get_formats (drag)),
+ dest_surface,
+ GDK_DRAG_PROTO_LOCAL);
+ drop_win32 = GDK_WIN32_DROP (drop);
+
+ impl->drop = drop;
+
+ source_actions = set_source_actions_helper (drop, *actions, grfKeyState);
+
+ gdk_drop_emit_enter_event (drop, TRUE, time_);
+ gdk_drop_emit_motion_event (drop, TRUE, x_root, y_root, time_);
+ drop_win32->last_key_state = grfKeyState;
+ drop_win32->last_x = x_root;
+ drop_win32->last_y = y_root;
+ *actions = filter_actions (drop_win32->actions, source_actions);
+
+ GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragenter returns with actions %s\n",
+ _gdk_win32_drag_action_to_string (*actions)));
+}
+
+/* The pdwEffect here initially points
+ * to a DWORD that contains the value of dwOKEffects argument in DoDragDrop,
+ * i.e. the drag action that the drag source deems acceptable.
+ * On return it should point to the effect value that denotes the
+ * action that is going to happen on drop, and that is what DoDragDrop will
+ * put into the DWORD that pdwEffect was pointing to.
+ */
static HRESULT STDMETHODCALLTYPE
idroptarget_dragenter (LPDROPTARGET This,
LPDATAOBJECT pDataObj,
DWORD grfKeyState,
POINTL pt,
- LPDWORD pdwEffect)
+ LPDWORD pdwEffect_and_dwOKEffects)
{
- target_drag_context *ctx = (target_drag_context *) This;
- GdkDragContext *context;
- GdkWin32DropContext *context_win32;
+ drop_target_context *ctx = (drop_target_context *) This;
+ GdkDrop *drop;
+ GdkWin32Drop *drop_win32;
GdkDisplay *display;
gint pt_x;
gint pt_y;
- GdkDragContext *source_context;
-
- GDK_NOTE (DND, g_print ("idroptarget_dragenter %p @ %ld : %ld for dest window 0x%p S_OK\n", This, pt.x, pt.y, ctx->dest_surface));
-
- g_clear_object (&ctx->context);
-
- source_context = _gdk_win32_find_source_context_for_dest_surface (ctx->dest_surface);
-
- display = gdk_surface_get_display (ctx->dest_surface);
- context = gdk_drop_context_new (display,
- /* OLE2 DnD does not allow us to get the source window,
- * but we *can* find it if it's ours. This is needed to
- * support DnD within the same widget, for example.
- */
- source_context ? source_context->source_surface : NULL,
- ctx->dest_surface,
- query_targets (pDataObj, NULL),
- GDK_ACTION_COPY | GDK_ACTION_MOVE,
- GDK_DRAG_PROTO_OLE2);
- context_win32 = GDK_WIN32_DROP_CONTEXT (context);
- gdk_content_formats_unref (query_targets (pDataObj, context_win32->droptarget_w32format_contentformat_map));
- g_array_set_size (context_win32->droptarget_w32format_contentformat_map, 0);
- g_set_object (&context_win32->local_source_context, GDK_WIN32_DRAG_CONTEXT (source_context));
-
- ctx->context = context;
- context->action = GDK_ACTION_MOVE;
- gdk_drag_context_set_actions (context,
- GDK_ACTION_COPY | GDK_ACTION_MOVE,
- get_suggested_action (context_win32, grfKeyState));
- set_data_object (&ctx->data_object, pDataObj);
- pt_x = pt.x / context_win32->scale + _gdk_offset_x;
- pt_y = pt.y / context_win32->scale + _gdk_offset_y;
- gdk_drop_emit_enter_event (GDK_DROP (context), TRUE, GDK_CURRENT_TIME);
- gdk_drop_emit_motion_event (GDK_DROP (context), TRUE, pt_x, pt_y, GDK_CURRENT_TIME);
- context_win32->last_key_state = grfKeyState;
- context_win32->last_x = pt_x;
- context_win32->last_y = pt_y;
- *pdwEffect = drop_effect_for_action (context->action);
+ GdkDragContext *drag;
+ GdkDragAction source_actions;
+ GdkDragAction dest_actions;
+
+ GDK_NOTE (DND, g_print ("idroptarget_dragenter %p @ %ld : %ld"
+ " for dest window 0x%p"
+ ". dwOKEffects = %lu\n",
+ This, pt.x, pt.y,
+ ctx->surface,
+ *pdwEffect_and_dwOKEffects));
+
+ g_clear_object (&ctx->drop);
+
+ /* Try to find the GdkDragContext object for this DnD operation,
+ * if it originated in our own application.
+ */
+ drag = _gdk_win32_find_drag_for_dest_surface (ctx->surface);
+
+ display = gdk_surface_get_display (ctx->surface);
+ drop = gdk_drop_new (display,
+ gdk_seat_get_pointer (gdk_display_get_default_seat (display)),
+ drag,
+ query_object_formats (pDataObj, NULL),
+ ctx->surface,
+ GDK_DRAG_PROTO_OLE2);
+ drop_win32 = GDK_WIN32_DROP (drop);
+ g_array_set_size (drop_win32->droptarget_w32format_contentformat_map, 0);
+ gdk_content_formats_unref (query_object_formats (pDataObj, drop_win32->droptarget_w32format_contentformat_map));
- GDK_NOTE (DND, g_print ("idroptarget_dragenter returns with action %d and drop effect %lu\n", context->action, *pdwEffect));
+ ctx->drop = drop;
+
+ source_actions = set_source_actions_helper (drop,
+ actions_for_drop_effects (*pdwEffect_and_dwOKEffects),
+ grfKeyState);
+
+ set_data_object (&ctx->data_object, pDataObj);
+ pt_x = pt.x / drop_win32->scale + _gdk_offset_x;
+ pt_y = pt.y / drop_win32->scale + _gdk_offset_y;
+ gdk_drop_emit_enter_event (drop, TRUE, GDK_CURRENT_TIME);
+ gdk_drop_emit_motion_event (drop, TRUE, pt_x, pt_y, GDK_CURRENT_TIME);
+ drop_win32->last_key_state = grfKeyState;
+ drop_win32->last_x = pt_x;
+ drop_win32->last_y = pt_y;
+ dest_actions = filter_actions (drop_win32->actions, source_actions);
+ *pdwEffect_and_dwOKEffects = drop_effect_for_actions (dest_actions);
+
+ GDK_NOTE (DND, g_print ("idroptarget_dragenter returns S_OK with actions %s"
+ " and drop effect %lu\n",
+ _gdk_win32_drag_action_to_string (dest_actions),
+ *pdwEffect_and_dwOKEffects));
return S_OK;
}
+gboolean
+_gdk_win32_local_drop_target_will_emit_motion (GdkDrop *drop,
+ gint x_root,
+ gint y_root,
+ DWORD grfKeyState)
+{
+ GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
+
+ if (x_root != drop_win32->last_x ||
+ y_root != drop_win32->last_y ||
+ grfKeyState != drop_win32->last_key_state)
+ return TRUE;
+
+ return FALSE;
+}
+
+void
+_gdk_win32_local_drop_target_dragover (GdkDrop *drop,
+ GdkDragContext *drag,
+ gint x_root,
+ gint y_root,
+ DWORD grfKeyState,
+ guint32 time_,
+ GdkDragAction *actions)
+{
+ GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
+ GdkDragAction source_actions;
+
+ source_actions = set_source_actions_helper (drop, *actions, grfKeyState);
+
+ GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragover %p @ %d : %d"
+ ", actions = %s\n",
+ drop, x_root, y_root,
+ _gdk_win32_drag_action_to_string (*actions)));
+
+ if (_gdk_win32_local_drop_target_will_emit_motion (drop, x_root, y_root, grfKeyState))
+ {
+ gdk_drop_emit_motion_event (drop, TRUE, x_root, y_root, time_);
+ drop_win32->last_key_state = grfKeyState;
+ drop_win32->last_x = x_root;
+ drop_win32->last_y = y_root;
+ }
+
+ *actions = filter_actions (drop_win32->actions, source_actions);
+
+ GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragover returns with actions %s\n",
+ _gdk_win32_drag_action_to_string (*actions)));
+}
+
/* NOTE: This method is called continuously, even if nothing is
* happening, as long as the drag operation is in progress and
* the cursor is above our window.
idroptarget_dragover (LPDROPTARGET This,
DWORD grfKeyState,
POINTL pt,
- LPDWORD pdwEffect)
+ LPDWORD pdwEffect_and_dwOKEffects)
{
- target_drag_context *ctx = (target_drag_context *) This;
- GdkWin32DropContext *context_win32 = GDK_WIN32_DROP_CONTEXT (ctx->context);
- gint pt_x = pt.x / context_win32->scale + _gdk_offset_x;
- gint pt_y = pt.y / context_win32->scale + _gdk_offset_y;
-
- gdk_drag_context_set_actions (ctx->context,
- gdk_drag_context_get_actions (ctx->context),
- get_suggested_action (context_win32, grfKeyState));
-
- GDK_NOTE (DND, g_print ("idroptarget_dragover %p @ %d : %d (raw %ld : %ld), suggests %d action S_OK\n", This, pt_x, pt_y, pt.x, pt.y, gdk_drag_context_get_suggested_action (ctx->context)));
-
- if (pt_x != context_win32->last_x ||
- pt_y != context_win32->last_y ||
- grfKeyState != context_win32->last_key_state)
+ drop_target_context *ctx = (drop_target_context *) This;
+ GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (ctx->drop);
+ gint pt_x = pt.x / drop_win32->scale + _gdk_offset_x;
+ gint pt_y = pt.y / drop_win32->scale + _gdk_offset_y;
+ GdkDragAction source_actions;
+ GdkDragAction dest_actions;
+
+ source_actions = set_source_actions_helper (ctx->drop,
+ actions_for_drop_effects (*pdwEffect_and_dwOKEffects),
+ grfKeyState);
+
+ GDK_NOTE (DND, g_print ("idroptarget_dragover %p @ %d : %d"
+ " (raw %ld : %ld)"
+ ", dwOKEffects = %lu"
+ ", suggests %d action\n",
+ This, pt_x, pt_y,
+ pt.x, pt.y,
+ *pdwEffect_and_dwOKEffects,
+ source_actions));
+
+ if (pt_x != drop_win32->last_x ||
+ pt_y != drop_win32->last_y ||
+ grfKeyState != drop_win32->last_key_state)
{
- gdk_drop_emit_motion_event (GDK_DROP (ctx->context), TRUE, pt_x, pt_y, GDK_CURRENT_TIME);
- context_win32->last_key_state = grfKeyState;
- context_win32->last_x = pt_x;
- context_win32->last_y = pt_y;
+ gdk_drop_emit_motion_event (ctx->drop, TRUE, pt_x, pt_y, GDK_CURRENT_TIME);
+ drop_win32->last_key_state = grfKeyState;
+ drop_win32->last_x = pt_x;
+ drop_win32->last_y = pt_y;
}
- *pdwEffect = drop_effect_for_action (ctx->context->action);
+ dest_actions = filter_actions (drop_win32->actions, source_actions);
+ *pdwEffect_and_dwOKEffects = drop_effect_for_actions (dest_actions);
- GDK_NOTE (DND, g_print ("idroptarget_dragover returns with action %d and effect %lu\n", ctx->context->action, *pdwEffect));
+ GDK_NOTE (DND, g_print ("idroptarget_dragover returns S_OK with actions %s"
+ " and effect %lu\n",
+ _gdk_win32_drag_action_to_string (dest_actions),
+ *pdwEffect_and_dwOKEffects));
return S_OK;
}
+void
+_gdk_win32_local_drop_target_dragleave (GdkDrop *drop,
+ guint32 time_)
+{
+ GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (gdk_drop_get_surface (drop)->impl);
+ GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_dragleave %p\n", drop));
+
+ gdk_drop_emit_leave_event (drop, TRUE, time_);
+
+ g_clear_object (&impl->drop);
+}
+
static HRESULT STDMETHODCALLTYPE
idroptarget_dragleave (LPDROPTARGET This)
{
- target_drag_context *ctx = (target_drag_context *) This;
+ drop_target_context *ctx = (drop_target_context *) This;
GDK_NOTE (DND, g_print ("idroptarget_dragleave %p S_OK\n", This));
- gdk_drop_emit_leave_event (GDK_DROP (ctx->context), TRUE, GDK_CURRENT_TIME);
+ gdk_drop_emit_leave_event (GDK_DROP (ctx->drop), TRUE, GDK_CURRENT_TIME);
- g_clear_object (&ctx->context);
+ g_clear_object (&ctx->drop);
set_data_object (&ctx->data_object, NULL);
return S_OK;
}
+void
+_gdk_win32_local_drop_target_drop (GdkDrop *drop,
+ GdkDragContext *drag,
+ guint32 time_,
+ GdkDragAction *actions)
+{
+ GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
+
+ GDK_NOTE (DND, g_print ("_gdk_win32_local_drop_target_drop %p ", drop));
+
+ set_source_actions_helper (drop,
+ *actions,
+ drop_win32->last_key_state);
+
+ drop_win32->drop_finished = FALSE;
+ gdk_drop_emit_drop_event (drop, TRUE, drop_win32->last_x, drop_win32->last_y, time_);
+
+ while (!drop_win32->drop_finished)
+ g_main_context_iteration (NULL, FALSE);
+
+ /* Notify local source of the DnD result
+ * Special case:
+ * drop_win32->actions is guaranteed to contain 1 action after gdk_drop_finish ()
+ */
+ *actions = drop_win32->actions;
+
+ GDK_NOTE (DND, g_print ("drop with action %s\n", _gdk_win32_drag_action_to_string (*actions)));
+}
+
static HRESULT STDMETHODCALLTYPE
idroptarget_drop (LPDROPTARGET This,
LPDATAOBJECT pDataObj,
DWORD grfKeyState,
POINTL pt,
- LPDWORD pdwEffect)
+ LPDWORD pdwEffect_and_dwOKEffects)
{
- target_drag_context *ctx = (target_drag_context *) This;
- GdkWin32DropContext *context_win32 = GDK_WIN32_DROP_CONTEXT (ctx->context);
- gint pt_x = pt.x / context_win32->scale + _gdk_offset_x;
- gint pt_y = pt.y / context_win32->scale + _gdk_offset_y;
+ drop_target_context *ctx = (drop_target_context *) This;
+ GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (ctx->drop);
+ gint pt_x = pt.x / drop_win32->scale + _gdk_offset_x;
+ gint pt_y = pt.y / drop_win32->scale + _gdk_offset_y;
+ GdkDragAction dest_action;
GDK_NOTE (DND, g_print ("idroptarget_drop %p ", This));
if (pDataObj == NULL)
{
GDK_NOTE (DND, g_print ("E_POINTER\n"));
- g_clear_object (&ctx->context);
+ gdk_drop_emit_leave_event (ctx->drop, TRUE, GDK_CURRENT_TIME);
+ g_clear_object (&ctx->drop);
set_data_object (&ctx->data_object, NULL);
return E_POINTER;
}
- gdk_drag_context_set_actions (ctx->context,
- gdk_drag_context_get_actions (ctx->context),
- get_suggested_action (context_win32, grfKeyState));
+ set_source_actions_helper (ctx->drop,
+ actions_for_drop_effects (*pdwEffect_and_dwOKEffects),
+ grfKeyState);
- gdk_drop_emit_drop_event (GDK_DROP (ctx->context), TRUE, pt_x, pt_y, GDK_CURRENT_TIME);
+ drop_win32->drop_finished = FALSE;
+ gdk_drop_emit_drop_event (ctx->drop, TRUE, pt_x, pt_y, GDK_CURRENT_TIME);
- /* Notify OLE of copy or move */
- *pdwEffect = drop_effect_for_action (ctx->context->action);
+ while (!drop_win32->drop_finished)
+ g_main_context_iteration (NULL, FALSE);
+
+ /* Notify OLE of the DnD result
+ * Special case:
+ * drop_win32->actions is guaranteed to contain 1 action after gdk_drop_finish ()
+ */
+ dest_action = drop_win32->actions;
+ *pdwEffect_and_dwOKEffects = drop_effect_for_actions (dest_action);
- g_clear_object (&ctx->context);
+ g_clear_object (&ctx->drop);
set_data_object (&ctx->data_object, NULL);
- GDK_NOTE (DND, g_print ("drop S_OK with effect %lx\n", *pdwEffect));
+ GDK_NOTE (DND, g_print ("drop S_OK with effect %lx\n", *pdwEffect_and_dwOKEffects));
return S_OK;
}
idroptarget_drop
};
-static target_drag_context *
+static drop_target_context *
target_context_new (GdkSurface *window)
{
- target_drag_context *result;
+ drop_target_context *result;
- result = g_new0 (target_drag_context, 1);
+ result = g_new0 (drop_target_context, 1);
result->idt.lpVtbl = &idt_vtbl;
result->ref_count = 0;
- result->dest_surface = g_object_ref (window);
+ result->surface = window;
idroptarget_addref (&result->idt);
- GDK_NOTE (DND, g_print ("target_context_new: %p (window %p)\n", result, result->dest_surface));
+ GDK_NOTE (DND, g_print ("target_context_new: %p (window %p)\n", result, result->surface));
return result;
}
gpointer data)
{
GdkSurface *window;
- GdkDragContext *context;
- GdkWin32DropContext *context_win32;
+ GdkDrop *drop;
+ GdkWin32Drop *drop_win32;
GString *result;
HANDLE hdrop;
POINT pt;
if (msg->message != WM_DROPFILES)
return GDK_WIN32_MESSAGE_FILTER_CONTINUE;
- GDK_NOTE (DND, g_print ("WM_DROPFILES: %p\n", msg->hwnd));
+ GDK_NOTE (DND, g_print ("WM_DROPFILES: %p\n", msg->hwnd));
- window = gdk_win32_handle_table_lookup (msg->hwnd);
+ window = gdk_win32_handle_table_lookup (msg->hwnd);
- context = gdk_drop_context_new (GDK_DISPLAY (display),
- NULL,
- window,
- gdk_content_formats_new ((const char *[2]) {
- "text/uri-list",
- NULL
- }, 1),
- GDK_ACTION_COPY,
- GDK_DRAG_PROTO_WIN32_DROPFILES);
- context_win32 = GDK_WIN32_DROP_CONTEXT (context);
- /* WM_DROPFILES drops are always file names */
+ drop = gdk_drop_new (GDK_DISPLAY (display),
+ gdk_seat_get_pointer (gdk_display_get_default_seat (GDK_DISPLAY (display))),
+ NULL,
+ /* WM_DROPFILES drops are always file names */
+ gdk_content_formats_new ((const char *[2]) {
+ "text/uri-list",
+ NULL
+ }, 1),
+ window,
+ GDK_DRAG_PROTO_WIN32_DROPFILES);
+ drop_win32 = GDK_WIN32_DROP (drop);
- gdk_drag_context_set_actions (context, GDK_ACTION_COPY, GDK_ACTION_COPY);
- current_dest_drag = context;
+ gdk_drop_set_actions (drop, GDK_ACTION_COPY);
- hdrop = (HANDLE) msg->wParam;
- DragQueryPoint (hdrop, &pt);
- ClientToScreen (msg->hwnd, &pt);
+ hdrop = (HANDLE) msg->wParam;
+ DragQueryPoint (hdrop, &pt);
+ ClientToScreen (msg->hwnd, &pt);
- nfiles = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
+ nfiles = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
- result = g_string_new (NULL);
- for (i = 0; i < nfiles; i++)
- {
- gchar *uri;
- wchar_t wfn[MAX_PATH];
+ result = g_string_new (NULL);
+ for (i = 0; i < nfiles; i++)
+ {
+ gchar *uri;
+ wchar_t wfn[MAX_PATH];
- DragQueryFileW (hdrop, i, wfn, MAX_PATH);
- fileName = g_utf16_to_utf8 (wfn, -1, NULL, NULL, NULL);
+ DragQueryFileW (hdrop, i, wfn, MAX_PATH);
+ fileName = g_utf16_to_utf8 (wfn, -1, NULL, NULL, NULL);
- /* Resolve shortcuts */
- if (resolve_link (msg->hwnd, wfn, &linkedFile))
+ /* Resolve shortcuts */
+ if (resolve_link (msg->hwnd, wfn, &linkedFile))
+ {
+ uri = g_filename_to_uri (linkedFile, NULL, NULL);
+ if (uri != NULL)
{
- 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);
- }
- g_free (fileName);
- fileName = linkedFile;
+ g_string_append (result, uri);
+ GDK_NOTE (DND, g_print ("... %s link to %s: %s\n",
+ fileName, linkedFile, uri));
+ g_free (uri);
}
- else
+ g_free (fileName);
+ fileName = linkedFile;
+ }
+ else
+ {
+ uri = g_filename_to_uri (fileName, NULL, NULL);
+ if (uri != NULL)
{
- 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, uri);
+ GDK_NOTE (DND, g_print ("... %s: %s\n", fileName, uri));
+ g_free (uri);
}
+ }
#if 0
- /* Awful hack to recognize temp files corresponding to
- * images dragged from Firefox... Open the file right here
- * so that it is less likely that Firefox manages to delete
- * it before the GTK+-using app (typically GIMP) has opened
- * it.
- *
- * Not compiled in for now, because it means images dragged
- * from Firefox would stay around in the temp folder which
- * is not what Firefox intended. I don't feel comfortable
- * with that, both from a geenral sanity point of view, and
- * from a privacy point of view. It's better to wait for
- * Firefox to fix the problem, for instance by deleting the
- * temp file after a longer delay, or to wait until we
- * implement the OLE2_DND...
- */
- if (filename_looks_tempish (fileName))
+ /* Awful hack to recognize temp files corresponding to
+ * images dragged from Firefox... Open the file right here
+ * so that it is less likely that Firefox manages to delete
+ * it before the GTK+-using app (typically GIMP) has opened
+ * it.
+ *
+ * Not compiled in for now, because it means images dragged
+ * from Firefox would stay around in the temp folder which
+ * is not what Firefox intended. I don't feel comfortable
+ * with that, both from a geenral sanity point of view, and
+ * from a privacy point of view. It's better to wait for
+ * Firefox to fix the problem, for instance by deleting the
+ * temp file after a longer delay, or to wait until we
+ * implement the OLE2_DND...
+ */
+ if (filename_looks_tempish (fileName))
+ {
+ int fd = g_open (fileName, _O_RDONLY|_O_BINARY, 0);
+ if (fd == -1)
{
- int fd = g_open (fileName, _O_RDONLY|_O_BINARY, 0);
- if (fd == -1)
- {
- GDK_NOTE (DND, g_print ("Could not open %s, maybe an image dragged from Firefox that it already deleted\n", fileName));
- }
- else
- {
- GDK_NOTE (DND, g_print ("Opened %s as %d so that Firefox won't delete it\n", fileName, fd));
- g_timeout_add_seconds (1, close_it, GINT_TO_POINTER (fd));
- }
+ GDK_NOTE (DND, g_print ("Could not open %s, maybe an image dragged from Firefox that it already deleted\n", fileName));
}
+ else
+ {
+ GDK_NOTE (DND, g_print ("Opened %s as %d so that Firefox won't delete it\n", fileName, fd));
+ g_timeout_add_seconds (1, close_it, GINT_TO_POINTER (fd));
+ }
+ }
#endif
- g_free (fileName);
- g_string_append (result, "\015\012");
- }
+ g_free (fileName);
+ g_string_append (result, "\015\012");
+ }
- /* FIXME: this call is currently a no-op, but it should
- * stash the string somewhere, and later produce it,
- * maybe in response to gdk_win32_drop_context_read_async()?
- */
- _gdk_dropfiles_store (result->str);
- g_string_free (result, FALSE);
+ g_clear_pointer (&drop_win32->dropfiles_list, g_free);
+ drop_win32->dropfiles_list = result->str;
+ g_string_free (result, FALSE);
+ if (drop_win32->dropfiles_list == NULL)
+ drop_win32->dropfiles_list = g_strdup ("");
- gdk_drop_emit_drop_event (GDK_DROP (context),
- FALSE,
- pt.x / context_win32->scale + _gdk_offset_x,
- pt.y / context_win32->scale + _gdk_offset_y,
- _gdk_win32_get_next_tick (msg->time));
+ gdk_drop_emit_drop_event (drop,
+ FALSE,
+ pt.x / drop_win32->scale + _gdk_offset_x,
+ pt.y / drop_win32->scale + _gdk_offset_y,
+ _gdk_win32_get_next_tick (msg->time));
- DragFinish (hdrop);
+ DragFinish (hdrop);
*ret_valp = 0;
return GDK_WIN32_MESSAGE_FILTER_REMOVE;
}
-/* Destination side */
-
static void
-gdk_win32_drop_context_status (GdkDrop *drop,
- GdkDragAction action)
+gdk_win32_drop_status (GdkDrop *drop,
+ GdkDragAction actions)
{
- GdkDragContext *context = GDK_DRAG_CONTEXT (drop);
- GdkDragContext *src_context;
+ GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
+ GdkDragContext *drag;
- g_return_if_fail (context != NULL);
+ g_return_if_fail (drop != NULL);
- GDK_NOTE (DND, g_print ("gdk_drag_status: %s\n"
- " context=%p:{actions=%s,suggested=%s,action=%s}\n",
- _gdk_win32_drag_action_to_string (action),
- context,
- _gdk_win32_drag_action_to_string (gdk_drag_context_get_actions (context)),
- _gdk_win32_drag_action_to_string (gdk_drag_context_get_suggested_action (context)),
- _gdk_win32_drag_action_to_string (context->action)));
+ GDK_NOTE (DND, g_print ("gdk_win32_drop_status: %s\n"
+ " context=%p:{source_actions=%s}\n",
+ _gdk_win32_drag_action_to_string (actions),
+ drop,
+ _gdk_win32_drag_action_to_string (gdk_drop_get_actions (drop))));
- context->action = action;
+ drop_win32->actions = actions;
- if (!use_ole2_dnd)
- {
- src_context = _gdk_win32_drag_context_find (context->source_surface,
- context->dest_surface);
+ if (drop_win32->protocol == GDK_DRAG_PROTO_OLE2)
+ return;
- if (src_context)
- {
- _gdk_win32_drag_context_send_local_status_event (src_context, action);
- }
- }
+ drag = gdk_drop_get_drag (drop);
+
+ if (drag != NULL)
+ _gdk_win32_local_drag_give_feedback (drag, actions);
}
static void
-gdk_win32_drop_context_finish (GdkDrop *drop,
- GdkDragAction action)
+gdk_win32_drop_finish (GdkDrop *drop,
+ GdkDragAction action)
{
- GdkDragContext *context = GDK_DRAG_CONTEXT (drop);
- GdkDragContext *src_context;
- GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
-
- g_return_if_fail (context != NULL);
+ GdkDragContext *drag;
+ GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
- GDK_NOTE (DND, g_print ("gdk_drag_finish\n"));
+ g_return_if_fail (drop != NULL);
- if (context->action != action)
- gdk_win32_drop_context_status (context, action);
+ GDK_NOTE (DND, g_print ("gdk_win32_drop_finish with action %s\n",
+ _gdk_win32_drag_action_to_string (action)));
- if (!use_ole2_dnd)
- {
- src_context = _gdk_win32_drag_context_find (context->source_surface,
- context->dest_surface);
- if (src_context)
- {
- GDK_NOTE (DND, g_print ("gdk_dnd_handle_drop_finihsed: 0x%p\n",
- context));
+ drop_win32->actions = action;
+ drop_win32->drop_finished = TRUE;
- g_signal_emit_by_name (context, "dnd-finished");
- gdk_drag_drop_done (context, !GDK_WIN32_DROP_CONTEXT (context)->drop_failed);
- }
- }
- else
- {
- _gdk_win32_drag_do_leave (context, GDK_CURRENT_TIME);
+ if (drop_win32->protocol == GDK_DRAG_PROTO_OLE2)
+ return;
+/* FIXME: remove?
+ drag = gdk_drop_get_drag (drop);
- if (action)
- clipdrop->dnd_target_state = GDK_WIN32_DND_DROPPED;
- else
- clipdrop->dnd_target_state = GDK_WIN32_DND_FAILED;
- }
+ if (drag != NULL)
+ _gdk_win32_local_drag_context_drop_response (drag, action);
+*/
}
#if 0
void
_gdk_win32_surface_register_dnd (GdkSurface *window)
{
- target_drag_context *ctx;
+ drop_target_context *ctx;
HRESULT hr;
g_return_if_fail (window != NULL);
else
g_object_set_data (G_OBJECT (window), "gdk-dnd-registered", GINT_TO_POINTER (TRUE));
- GDK_NOTE (DND, g_print ("gdk_surface_register_dnd: %p\n", GDK_SURFACE_HWND (window)));
+ GDK_NOTE (DND, g_print ("gdk_win32_surface_register_dnd: %p\n", GDK_SURFACE_HWND (window)));
if (!use_ole2_dnd)
{
}
else
{
+ GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
/* Return if window is already setup for DND. */
- if (g_hash_table_lookup (target_ctx_for_window, GDK_SURFACE_HWND (window)) != NULL)
+ if (impl->drop_target != NULL)
return;
ctx = target_context_new (window);
OTHER_API_FAILED ("RegisterDragDrop");
else
{
- g_object_ref (window);
- g_hash_table_insert (target_ctx_for_window, GDK_SURFACE_HWND (window), ctx);
+ impl->drop_target = ctx;
}
}
}
}
+void
+_gdk_win32_surface_unregister_dnd (GdkSurface *window)
+{
+ GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+ if (impl->drop_target)
+ idroptarget_release (&impl->drop_target->idt);
+}
+
static gpointer
grab_data_from_hdata (GTask *task,
HANDLE hdata,
}
static void
-gdk_win32_drop_context_read_async (GdkDrop *drop,
- GdkContentFormats *formats,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+gdk_win32_drop_read_async (GdkDrop *drop,
+ GdkContentFormats *formats,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GdkWin32DropContext *context_win32 = GDK_WIN32_DROP_CONTEXT (drop);
+ GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
GTask *task;
- target_drag_context *tctx;
+ drop_target_context *tctx;
const char * const *mime_types;
gsize i, j, n_mime_types;
GdkWin32ContentFormatPair *pair;
task = g_task_new (drop, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
- g_task_set_source_tag (task, gdk_win32_drop_context_read_async);
+ g_task_set_source_tag (task, gdk_win32_drop_read_async);
+
+ mime_types = gdk_content_formats_get_mime_types (formats, &n_mime_types);
- tctx = find_droptarget_for_target_context (GDK_DRAG_CONTEXT (drop));
+ if (drop_win32->protocol == GDK_DRAG_PROTO_WIN32_DROPFILES)
+ {
+ for (i = 0; i < n_mime_types; i++)
+ if (g_strcmp0 (mime_types[i], "text/uri-list") == 0)
+ break;
+ if (i >= n_mime_types)
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("No compatible transfer format found"));
+ g_clear_pointer (&drop_win32->dropfiles_list, g_free);
+
+ return;
+ }
+
+ stream = g_memory_input_stream_new_from_data (drop_win32->dropfiles_list, strlen (drop_win32->dropfiles_list), g_free);
+ drop_win32->dropfiles_list = NULL;
+ g_object_set_data (G_OBJECT (stream), "gdk-dnd-stream-contenttype", (gpointer) "text/uri-list");
+ g_task_return_pointer (task, stream, g_object_unref);
+
+ return;
+ }
+
+ tctx = GDK_SURFACE_IMPL_WIN32 (gdk_drop_get_surface (drop)->impl)->drop_target;
if (tctx == NULL)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Failed to find target context record for context 0x%p"), drop);
+ _("GDK surface 0x%p is not registered as a drop target"), gdk_drop_get_surface (drop));
return;
}
return;
}
- mime_types = gdk_content_formats_get_mime_types (formats, &n_mime_types);
-
for (pair = NULL, i = 0; i < n_mime_types; i++)
{
- for (j = 0; j < context_win32->droptarget_w32format_contentformat_map->len; j++)
+ for (j = 0; j < drop_win32->droptarget_w32format_contentformat_map->len; j++)
{
- pair = &g_array_index (context_win32->droptarget_w32format_contentformat_map, GdkWin32ContentFormatPair, j);
+ pair = &g_array_index (drop_win32->droptarget_w32format_contentformat_map, GdkWin32ContentFormatPair, j);
if (pair->contentformat == mime_types[i])
break;
}
static GInputStream *
-gdk_win32_drop_context_read_finish (GdkDrop *drop,
- const char **out_mime_type,
- GAsyncResult *result,
- GError **error)
+gdk_win32_drop_read_finish (GdkDrop *drop,
+ const char **out_mime_type,
+ GAsyncResult *result,
+ GError **error)
{
GTask *task;
GInputStream *stream;
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (drop)), NULL);
task = G_TASK (result);
- g_return_val_if_fail (g_task_get_source_tag (task) == gdk_win32_drop_context_read_async, NULL);
+ g_return_val_if_fail (g_task_get_source_tag (task) == gdk_win32_drop_read_async, NULL);
stream = g_task_propagate_pointer (task, error);
}
static void
-gdk_win32_drop_context_class_init (GdkWin32DropContextClass *klass)
+gdk_win32_drop_class_init (GdkWin32DropClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDropClass *drop_class = GDK_DROP_CLASS (klass);
- GdkDragContextClass *context_class = GDK_DRAG_CONTEXT_CLASS (klass);
- object_class->finalize = gdk_win32_drop_context_finalize;
+ object_class->finalize = gdk_win32_drop_finalize;
- drop_class->status = gdk_win32_drop_context_status;
- drop_class->finish = gdk_win32_drop_context_finish;
- drop_class->read_async = gdk_win32_drop_context_read_async;
- drop_class->read_finish = gdk_win32_drop_context_read_finish;
-}
-
-void
-_gdk_win32_local_send_enter (GdkDragContext *context,
- guint32 time)
-{
- GdkDragContext *new_context;
-
- GDK_NOTE (DND, g_print ("local_send_enter: context=%p current_dest_drag=%p\n",
- context,
- current_dest_drag));
-
- if (current_dest_drag != NULL)
- {
- g_object_unref (G_OBJECT (current_dest_drag));
- current_dest_drag = NULL;
- }
-
- new_context = gdk_drop_context_new (gdk_surface_get_display (context->source_surface),
- context->source_surface,
- context->dest_surface,
- gdk_content_formats_ref (gdk_drag_context_get_formats (context)),
- gdk_drag_context_get_actions (context),
- GDK_DRAG_PROTO_LOCAL);
-
- gdk_surface_set_events (new_context->source_surface,
- gdk_surface_get_events (new_context->source_surface) |
- GDK_PROPERTY_CHANGE_MASK);
-
- current_dest_drag = new_context;
-
- gdk_drop_emit_enter_event (GDK_DROP (new_context), FALSE, GDK_CURRENT_TIME);
+ drop_class->status = gdk_win32_drop_status;
+ drop_class->finish = gdk_win32_drop_finish;
+ drop_class->read_async = gdk_win32_drop_read_async;
+ drop_class->read_finish = gdk_win32_drop_read_finish;
}
void
_gdk_drop_init (void)
{
- if (use_ole2_dnd)
- {
- target_ctx_for_window = g_hash_table_new (g_direct_hash, g_direct_equal);
- }
+ if (g_strcmp0 (getenv ("GDK_WIN32_OLE2_DND"), "0") == 0)
+ use_ole2_dnd = FALSE;
}