Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b4f3520c9 | |||
| 9aba2c435f | |||
| b8b9cc3805 | |||
| 7769be22f0 | |||
| 00a171626d | |||
| bdc37cf161 | |||
| ad7d4acc77 | |||
| 604a85b852 | |||
| 209ceaa844 | |||
| 8d1bdcef8f | |||
| 431f78a992 | |||
| bce4305bee | |||
| 58a6c8f237 | |||
| 637d5d633c | |||
| 31e850cd7f | |||
| cde1ee8662 | |||
| 3c4d1356a0 | |||
| 1413ce13cb | |||
| 70ef32bb29 | |||
| af70ca4ca2 | |||
| de3a0dbcfd | |||
| 7ff9738561 | |||
| 9870688e27 | |||
| 41cc232c55 | |||
| 7f715168c9 | |||
| 0d78bc7500 | |||
| 83af276f35 | |||
| 0964f2b2c0 | |||
| e2891cd506 | |||
| f40f33afb9 | |||
| 2a85948942 | |||
| d4b8579488 | |||
| b5d89153b5 | |||
| 390012a633 | |||
| 60d83804d7 | |||
| ed8423e15c | |||
| 63571fc5e5 | |||
| b36c5e48e3 | |||
| 2d6e88e3ee | |||
| 0c1f739c1a | |||
| 8aadfd730e | |||
| 7b2e2d6bad | |||
| 34c2e1b3fb | |||
| 7be144b436 | |||
| 0ee542e588 |
@@ -150,9 +150,8 @@ drag_data_get (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data,
|
||||
guint32 time,
|
||||
gpointer data)
|
||||
{
|
||||
if (gtk_selection_data_get_length (selection_data) > 0)
|
||||
|
||||
@@ -71,7 +71,7 @@ straightforward manner.
|
||||
void gdk_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time);
|
||||
void gdk_drop_finish (GdkDragContext *context,
|
||||
void gdk_drag_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time);
|
||||
GdkAtom gdk_drag_get_selection (GdkDragContext *context);
|
||||
|
||||
@@ -652,7 +652,7 @@ gdk_event_get_scancode
|
||||
gdk_event_get_pointer_emulated
|
||||
gdk_event_get_crossing_detail
|
||||
gdk_event_get_crossing_mode
|
||||
gdk_event_get_drag_context
|
||||
gdk_event_get_drop
|
||||
gdk_event_get_focus_in
|
||||
gdk_event_get_grab_surface
|
||||
gdk_event_get_motion_history
|
||||
@@ -783,8 +783,9 @@ GdkDragContext
|
||||
GdkDragCancelReason
|
||||
gdk_drag_drop_done
|
||||
gdk_drag_begin
|
||||
gdk_drop_finish
|
||||
gdk_drag_finish
|
||||
GdkDragAction
|
||||
GDK_ACTION_ALL
|
||||
gdk_drag_status
|
||||
|
||||
gdk_drag_context_get_display
|
||||
@@ -793,11 +794,12 @@ gdk_drag_context_get_suggested_action
|
||||
gdk_drag_context_get_selected_action
|
||||
gdk_drag_context_get_formats
|
||||
gdk_drag_context_get_device
|
||||
gdk_drag_context_get_source_surface
|
||||
gdk_drag_context_get_dest_surface
|
||||
gdk_drag_context_get_drag_surface
|
||||
gdk_drag_context_set_hotspot
|
||||
|
||||
<SUBSECTION>
|
||||
gdk_drag_action_is_unique
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GDK_DRAG_CONTEXT
|
||||
GDK_TYPE_DRAG_CONTEXT
|
||||
|
||||
@@ -5026,7 +5026,6 @@ gtk_drag_dest_add_image_targets
|
||||
gtk_drag_dest_add_uri_targets
|
||||
gtk_drag_dest_set_track_motion
|
||||
gtk_drag_dest_get_track_motion
|
||||
gtk_drag_finish
|
||||
gtk_drag_get_data
|
||||
gtk_drag_get_source_widget
|
||||
gtk_drag_highlight
|
||||
|
||||
@@ -118,24 +118,6 @@ gdk_broadway_drag_context_drag_abort (GdkDragContext *context,
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
/* Destination side */
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_context_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_context_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_broadway_surface_register_dnd (GdkSurface *surface)
|
||||
{
|
||||
@@ -154,8 +136,6 @@ gdk_broadway_drag_context_class_init (GdkBroadwayDragContextClass *klass)
|
||||
|
||||
object_class->finalize = gdk_broadway_drag_context_finalize;
|
||||
|
||||
context_class->drag_status = gdk_broadway_drag_context_drag_status;
|
||||
context_class->drag_abort = gdk_broadway_drag_context_drag_abort;
|
||||
context_class->drag_drop = gdk_broadway_drag_context_drag_drop;
|
||||
context_class->drop_finish = gdk_broadway_drag_context_drop_finish;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDevice, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplayManager, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDragContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrawingContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrawContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkFrameClock, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkGLContext, g_object_unref)
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <gdk/gdkdisplaymanager.h>
|
||||
#include <gdk/gdkdnd.h>
|
||||
#include <gdk/gdkdrawcontext.h>
|
||||
#include <gdk/gdkdrop.h>
|
||||
#include <gdk/gdkenumtypes.h>
|
||||
#include <gdk/gdkevents.h>
|
||||
#include <gdk/gdkframeclock.h>
|
||||
|
||||
@@ -492,8 +492,6 @@ gdk_display_put_event_nocopy (GdkDisplay *display,
|
||||
GdkEvent *event)
|
||||
{
|
||||
_gdk_event_queue_append (display, event);
|
||||
/* If the main loop is blocking in a different thread, wake it up */
|
||||
g_main_context_wakeup (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+69
-172
@@ -35,13 +35,19 @@
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkeventsprivate.h"
|
||||
|
||||
#define DROP_SUBCLASS 1
|
||||
|
||||
typedef struct _GdkDragContextPrivate GdkDragContextPrivate;
|
||||
|
||||
struct _GdkDragContextPrivate
|
||||
{
|
||||
#ifndef DROP_SUBCLASS
|
||||
GdkDisplay *display;
|
||||
GdkDevice *device;
|
||||
#endif
|
||||
GdkContentFormats *formats;
|
||||
GdkDragAction actions;
|
||||
GdkDragAction suggested_action;
|
||||
};
|
||||
|
||||
static struct {
|
||||
@@ -49,7 +55,6 @@ static struct {
|
||||
const gchar *name;
|
||||
GdkCursor *cursor;
|
||||
} drag_cursors[] = {
|
||||
{ GDK_ACTION_DEFAULT, NULL, NULL },
|
||||
{ GDK_ACTION_ASK, "dnd-ask", NULL },
|
||||
{ GDK_ACTION_COPY, "dnd-copy", NULL },
|
||||
{ GDK_ACTION_MOVE, "dnd-move", NULL },
|
||||
@@ -60,9 +65,11 @@ static struct {
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CONTENT,
|
||||
#ifndef DROP_SUBCLASS
|
||||
PROP_DEVICE,
|
||||
PROP_DISPLAY,
|
||||
PROP_FORMATS,
|
||||
#endif
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
@@ -78,7 +85,7 @@ static GParamSpec *properties[N_PROPERTIES] = { NULL, };
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
static GList *contexts = NULL;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkDragContext, gdk_drag_context, G_TYPE_OBJECT)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkDragContext, gdk_drag_context, GDK_TYPE_DROP)
|
||||
|
||||
/**
|
||||
* SECTION:dnd
|
||||
@@ -114,11 +121,15 @@ G_DEFINE_TYPE_WITH_PRIVATE (GdkDragContext, gdk_drag_context, G_TYPE_OBJECT)
|
||||
GdkDisplay *
|
||||
gdk_drag_context_get_display (GdkDragContext *context)
|
||||
{
|
||||
#ifdef DROP_SUBCLASS
|
||||
return gdk_drop_get_display (GDK_DROP (context));
|
||||
#else
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return priv->display;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,6 +147,12 @@ gdk_drag_context_get_formats (GdkDragContext *context)
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
#ifdef DROP_SUBCLASS
|
||||
GdkContentFormats *formats = gdk_drop_get_formats (GDK_DROP (context));
|
||||
|
||||
if (formats)
|
||||
return formats;
|
||||
#endif
|
||||
return priv->formats;
|
||||
}
|
||||
|
||||
@@ -151,9 +168,11 @@ gdk_drag_context_get_formats (GdkDragContext *context)
|
||||
GdkDragAction
|
||||
gdk_drag_context_get_actions (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), GDK_ACTION_DEFAULT);
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
return context->actions;
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), 0);
|
||||
|
||||
return priv->actions;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,9 +186,11 @@ gdk_drag_context_get_actions (GdkDragContext *context)
|
||||
GdkDragAction
|
||||
gdk_drag_context_get_suggested_action (GdkDragContext *context)
|
||||
{
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), 0);
|
||||
|
||||
return context->suggested_action;
|
||||
return priv->suggested_action;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,38 +209,6 @@ gdk_drag_context_get_selected_action (GdkDragContext *context)
|
||||
return context->action;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_source_surface:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Returns the #GdkSurface where the DND operation started.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkSurface
|
||||
**/
|
||||
GdkSurface *
|
||||
gdk_drag_context_get_source_surface (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return context->source_surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_dest_surface:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Returns the destination surface for the DND operation.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkSurface
|
||||
**/
|
||||
GdkSurface *
|
||||
gdk_drag_context_get_dest_surface (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return context->dest_surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_device:
|
||||
* @context: a #GdkDragContext
|
||||
@@ -231,11 +220,15 @@ gdk_drag_context_get_dest_surface (GdkDragContext *context)
|
||||
GdkDevice *
|
||||
gdk_drag_context_get_device (GdkDragContext *context)
|
||||
{
|
||||
#ifdef DROP_SUBCLASS
|
||||
return gdk_drop_get_device (GDK_DROP (context));
|
||||
#else
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return priv->device;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -264,6 +257,7 @@ gdk_drag_context_set_property (GObject *gobject,
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef DROP_SUBCLASS
|
||||
case PROP_DEVICE:
|
||||
priv->device = g_value_dup_object (value);
|
||||
g_assert (priv->device != NULL);
|
||||
@@ -286,6 +280,7 @@ gdk_drag_context_set_property (GObject *gobject,
|
||||
g_assert (priv->formats != NULL);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
@@ -300,7 +295,9 @@ gdk_drag_context_get_property (GObject *gobject,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (gobject);
|
||||
#ifndef DROP_SUBCLASS
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
#endif
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -308,6 +305,7 @@ gdk_drag_context_get_property (GObject *gobject,
|
||||
g_value_set_object (value, context->content);
|
||||
break;
|
||||
|
||||
#ifndef DROP_SUBCLASS
|
||||
case PROP_DEVICE:
|
||||
g_value_set_object (value, priv->device);
|
||||
break;
|
||||
@@ -319,6 +317,7 @@ gdk_drag_context_get_property (GObject *gobject,
|
||||
case PROP_FORMATS:
|
||||
g_value_set_boxed (value, priv->formats);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
@@ -346,40 +345,6 @@ gdk_drag_context_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (gdk_drag_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_read_local_async (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_drag_context_read_local_async);
|
||||
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("Reading not implemented."));
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_drag_context_read_local_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, context), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drag_context_read_local_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_class_init (GdkDragContextClass *klass)
|
||||
{
|
||||
@@ -405,6 +370,7 @@ gdk_drag_context_class_init (GdkDragContextClass *klass)
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
#ifndef DROP_SUBCLASS
|
||||
/**
|
||||
* GdkDragContext:device:
|
||||
*
|
||||
@@ -448,6 +414,7 @@ gdk_drag_context_class_init (GdkDragContextClass *klass)
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* GdkDragContext::cancel:
|
||||
@@ -534,9 +501,7 @@ gdk_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time_)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
|
||||
GDK_DRAG_CONTEXT_GET_CLASS (context)->drag_status (context, action, time_);
|
||||
gdk_drop_status (GDK_DROP (context), action);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -576,7 +541,7 @@ gdk_drag_drop (GdkDragContext *context,
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_finish:
|
||||
* gdk_drag_finish:
|
||||
* @context: a #GdkDragContext
|
||||
* @success: %TRUE if the data was successfully received
|
||||
* @time_: the timestamp for this operation
|
||||
@@ -586,13 +551,16 @@ gdk_drag_drop (GdkDragContext *context,
|
||||
* This function is called by the drag destination.
|
||||
*/
|
||||
void
|
||||
gdk_drop_finish (GdkDragContext *context,
|
||||
gdk_drag_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time_)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
|
||||
GDK_DRAG_CONTEXT_GET_CLASS (context)->drop_finish (context, success, time_);
|
||||
if (success)
|
||||
gdk_drop_finish (GDK_DROP (context), gdk_drag_context_get_selected_action (context));
|
||||
else
|
||||
gdk_drop_finish (GDK_DROP (context), 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -714,73 +682,20 @@ gdk_drag_context_write_finish (GdkDragContext *context,
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_async:
|
||||
* @context: a #GdkDragContext
|
||||
* @mime_types: (array zero-terminated=1) (element-type utf8): pointer to an array of mime types
|
||||
* @io_priority: the io priority for the read operation
|
||||
* @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to @callback
|
||||
*
|
||||
* Asynchronously read the dropped data from a DND context
|
||||
* in a format that complies with one of the mime types.
|
||||
*/
|
||||
void
|
||||
gdk_drop_read_async (GdkDragContext *context,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
gdk_drag_context_set_actions (GdkDragContext *context,
|
||||
GdkDragAction actions,
|
||||
GdkDragAction suggested_action)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
g_return_if_fail (mime_types != NULL && mime_types[0] != NULL);
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
priv->actions = actions;
|
||||
priv->suggested_action = suggested_action;
|
||||
|
||||
formats = gdk_content_formats_new (mime_types, g_strv_length ((char **) mime_types));
|
||||
|
||||
GDK_DRAG_CONTEXT_GET_CLASS (context)->read_async (context,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_finish:
|
||||
* @context: a #GdkDragContext
|
||||
* @out_mime_type: (out) (type utf8): return location for the used mime type
|
||||
* @result: a #GAsyncResult
|
||||
* @error: (allow-none): location to store error information on failure, or %NULL
|
||||
*
|
||||
* Finishes an async drop read operation, see gdk_drop_read_async().
|
||||
*
|
||||
* Returns: (nullable) (transfer full): the #GInputStream, or %NULL
|
||||
*/
|
||||
GInputStream *
|
||||
gdk_drop_read_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (g_async_result_is_tagged (result, gdk_drag_context_read_local_async))
|
||||
{
|
||||
return gdk_drag_context_read_local_finish (context, out_mime_type, result, error);
|
||||
}
|
||||
if (suggested_action & GDK_ACTION_ASK)
|
||||
gdk_drop_set_actions (GDK_DROP (context), actions & GDK_ACTION_ALL);
|
||||
else
|
||||
{
|
||||
return GDK_DRAG_CONTEXT_GET_CLASS (context)->read_finish (context, out_mime_type, result, error);
|
||||
}
|
||||
gdk_drop_set_actions (GDK_DROP (context), suggested_action);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -917,38 +832,20 @@ gdk_drag_get_cursor (GdkDragContext *context,
|
||||
return drag_cursors[i].cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_commit_drag_status (GdkDragContext *context)
|
||||
/**
|
||||
* gdk_drag_action_is_unique:
|
||||
* @action: a #GdkDragAction
|
||||
*
|
||||
* Checks if @action represents a single action or if it
|
||||
* includes multiple flags that can be selected from.
|
||||
*
|
||||
* When @action is 0 - ie no action was given, %TRUE
|
||||
* is returned.
|
||||
*
|
||||
* Returns: %TRUE if exactly one action was given
|
||||
**/
|
||||
GdkDragAction
|
||||
gdk_drag_action_is_unique (GdkDragAction action)
|
||||
{
|
||||
GdkDragContextClass *context_class;
|
||||
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
g_return_if_fail (!context->is_source);
|
||||
|
||||
context_class = GDK_DRAG_CONTEXT_GET_CLASS (context);
|
||||
|
||||
if (context_class->commit_drag_status)
|
||||
context_class->commit_drag_status (context);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_drag_context_handle_dest_event (GdkEvent *event)
|
||||
{
|
||||
GdkDragContext *context = NULL;
|
||||
|
||||
switch ((guint) event->any.type)
|
||||
{
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
context = event->dnd.context;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
gdk_drag_context_commit_drag_status (context);
|
||||
return TRUE;;
|
||||
return (action & (action - 1)) == 0;
|
||||
}
|
||||
|
||||
+2
-42
@@ -39,31 +39,6 @@ G_BEGIN_DECLS
|
||||
#define GDK_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DRAG_CONTEXT, GdkDragContext))
|
||||
#define GDK_IS_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DRAG_CONTEXT))
|
||||
|
||||
/**
|
||||
* GdkDragAction:
|
||||
* @GDK_ACTION_DEFAULT: Means nothing, and should not be used.
|
||||
* @GDK_ACTION_COPY: Copy the data.
|
||||
* @GDK_ACTION_MOVE: Move the data, i.e. first copy it, then delete
|
||||
* it from the source using the DELETE target of the X selection protocol.
|
||||
* @GDK_ACTION_LINK: Add a link to the data. Note that this is only
|
||||
* useful if source and destination agree on what it means.
|
||||
* @GDK_ACTION_PRIVATE: Special action which tells the source that the
|
||||
* destination will do something that the source doesn’t understand.
|
||||
* @GDK_ACTION_ASK: Ask the user what to do with the data.
|
||||
*
|
||||
* Used in #GdkDragContext to indicate what the destination
|
||||
* should do with the dropped data.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GDK_ACTION_DEFAULT = 1 << 0,
|
||||
GDK_ACTION_COPY = 1 << 1,
|
||||
GDK_ACTION_MOVE = 1 << 2,
|
||||
GDK_ACTION_LINK = 1 << 3,
|
||||
GDK_ACTION_PRIVATE = 1 << 4,
|
||||
GDK_ACTION_ASK = 1 << 5
|
||||
} GdkDragAction;
|
||||
|
||||
/**
|
||||
* GdkDragCancelReason:
|
||||
* @GDK_DRAG_CANCEL_NO_TARGET: There is no suitable drop target.
|
||||
@@ -98,9 +73,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drag_context_get_selected_action (GdkDragContext *context);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface *gdk_drag_context_get_source_surface (GdkDragContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface *gdk_drag_context_get_dest_surface (GdkDragContext *context);
|
||||
GdkDragAction gdk_drag_action_is_unique (GdkDragAction action);
|
||||
|
||||
/* Destination side */
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -108,23 +81,10 @@ void gdk_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time_);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_finish (GdkDragContext *context,
|
||||
void gdk_drag_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time_);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_read_async (GdkDragContext *context,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GInputStream * gdk_drop_read_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
/* Source side */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
||||
+8
-23
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "gdkdnd.h"
|
||||
|
||||
#include "gdkdropprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
@@ -31,28 +33,12 @@ typedef struct _GdkDragContextClass GdkDragContextClass;
|
||||
|
||||
|
||||
struct _GdkDragContextClass {
|
||||
GObjectClass parent_class;
|
||||
GdkDropClass parent_class;
|
||||
|
||||
void (*drag_status) (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time_);
|
||||
void (*drag_abort) (GdkDragContext *context,
|
||||
guint32 time_);
|
||||
void (*drag_drop) (GdkDragContext *context,
|
||||
guint32 time_);
|
||||
void (*drop_finish) (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time_);
|
||||
void (* read_async) (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GInputStream * (* read_finish) (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GdkSurface* (*get_drag_surface) (GdkDragContext *context);
|
||||
void (*set_hotspot) (GdkDragContext *context,
|
||||
gint hot_x,
|
||||
@@ -72,12 +58,10 @@ struct _GdkDragContextClass {
|
||||
const GdkEvent *event);
|
||||
void (*action_changed) (GdkDragContext *context,
|
||||
GdkDragAction action);
|
||||
|
||||
void (*commit_drag_status) (GdkDragContext *context);
|
||||
};
|
||||
|
||||
struct _GdkDragContext {
|
||||
GObject parent_instance;
|
||||
GdkDrop parent_instance;
|
||||
|
||||
/*< private >*/
|
||||
gboolean is_source;
|
||||
@@ -86,8 +70,6 @@ struct _GdkDragContext {
|
||||
GdkSurface *drag_surface;
|
||||
|
||||
GdkContentProvider *content;
|
||||
GdkDragAction actions;
|
||||
GdkDragAction suggested_action;
|
||||
GdkDragAction action;
|
||||
|
||||
guint drop_done : 1; /* Whether gdk_drag_drop_done() was performed */
|
||||
@@ -95,10 +77,13 @@ struct _GdkDragContext {
|
||||
|
||||
void gdk_drag_context_set_cursor (GdkDragContext *context,
|
||||
GdkCursor *cursor);
|
||||
void gdk_drag_context_set_actions (GdkDragContext *context,
|
||||
GdkDragAction actions,
|
||||
GdkDragAction suggested_action);
|
||||
|
||||
void gdk_drag_context_cancel (GdkDragContext *context,
|
||||
GdkDragCancelReason reason);
|
||||
gboolean gdk_drag_context_handle_source_event (GdkEvent *event);
|
||||
gboolean gdk_drag_context_handle_dest_event (GdkEvent *event);
|
||||
GdkCursor * gdk_drag_get_cursor (GdkDragContext *context,
|
||||
GdkDragAction action);
|
||||
|
||||
|
||||
+983
@@ -0,0 +1,983 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdndprivate.h"
|
||||
|
||||
#include "gdkcontentdeserializer.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkcontentprovider.h"
|
||||
#include "gdkcontentserializer.h"
|
||||
#include "gdkcursor.h"
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkeventsprivate.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkpipeiostreamprivate.h"
|
||||
#include "gdksurface.h"
|
||||
|
||||
typedef struct _GdkDropPrivate GdkDropPrivate;
|
||||
|
||||
struct _GdkDropPrivate {
|
||||
GdkDevice *device;
|
||||
GdkDragContext *drag;
|
||||
GdkContentFormats *formats;
|
||||
GdkSurface *surface;
|
||||
GdkDragAction actions;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ACTIONS,
|
||||
PROP_DEVICE,
|
||||
PROP_DISPLAY,
|
||||
PROP_DRAG,
|
||||
PROP_FORMATS,
|
||||
PROP_SURFACE,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPERTIES] = { NULL, };
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkDrop, gdk_drop, G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* GdkDrop:
|
||||
*
|
||||
* The GdkDrop struct contains only private fields and
|
||||
* should not be accessed directly.
|
||||
*/
|
||||
|
||||
static void
|
||||
gdk_drop_default_status (GdkDrop *self,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_local_write_done (GObject *drag,
|
||||
GAsyncResult *result,
|
||||
gpointer stream)
|
||||
{
|
||||
/* we don't care about the error, we just want to clean up */
|
||||
gdk_drag_context_write_finish (GDK_DRAG_CONTEXT (drag), result, NULL);
|
||||
|
||||
/* XXX: Do we need to close_async() here? */
|
||||
g_output_stream_close (stream, NULL, NULL);
|
||||
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_local_async (GdkDrop *self,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkContentFormats *content_formats;
|
||||
const char *mime_type;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_drop_read_local_async);
|
||||
|
||||
if (priv->drag == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("Drag'n'drop from other applications is not supported."));
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
content_formats = gdk_content_provider_ref_formats (priv->drag->content);
|
||||
content_formats = gdk_content_formats_union_serialize_mime_types (content_formats);
|
||||
mime_type = gdk_content_formats_match_mime_type (content_formats, formats);
|
||||
|
||||
if (mime_type != NULL)
|
||||
{
|
||||
GOutputStream *output_stream;
|
||||
GIOStream *stream;
|
||||
|
||||
stream = gdk_pipe_io_stream_new ();
|
||||
output_stream = g_io_stream_get_output_stream (stream);
|
||||
gdk_drag_context_write_async (priv->drag,
|
||||
mime_type,
|
||||
output_stream,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_drop_read_local_write_done,
|
||||
g_object_ref (output_stream));
|
||||
g_task_set_task_data (task, (gpointer) mime_type, NULL);
|
||||
g_task_return_pointer (task, g_object_ref (g_io_stream_get_input_stream (stream)), g_object_unref);
|
||||
|
||||
g_object_unref (stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible formats to transfer contents."));
|
||||
}
|
||||
|
||||
gdk_content_formats_unref (content_formats);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_drop_read_local_finish (GdkDrop *self,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drop_read_local_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDrop *self = GDK_DROP (gobject);
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTIONS:
|
||||
gdk_drop_set_actions (self, g_value_get_flags (value));
|
||||
break;
|
||||
|
||||
case PROP_DEVICE:
|
||||
priv->device = g_value_dup_object (value);
|
||||
g_assert (priv->device != NULL);
|
||||
if (priv->surface)
|
||||
g_assert (gdk_surface_get_display (priv->surface) == gdk_device_get_display (priv->device));
|
||||
break;
|
||||
|
||||
case PROP_DRAG:
|
||||
priv->drag = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_FORMATS:
|
||||
priv->formats = g_value_dup_boxed (value);
|
||||
#ifdef DROP_SUBCLASS
|
||||
g_assert (priv->formats != NULL);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
priv->surface = g_value_dup_object (value);
|
||||
#ifdef DROP_SUBCLASS
|
||||
g_assert (priv->surface != NULL);
|
||||
if (priv->device)
|
||||
g_assert (gdk_surface_get_display (priv->surface) == gdk_device_get_display (priv->device));
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDrop *self = GDK_DROP (gobject);
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTIONS:
|
||||
g_value_set_flags (value, priv->actions);
|
||||
break;
|
||||
|
||||
case PROP_DEVICE:
|
||||
g_value_set_object (value, priv->device);
|
||||
break;
|
||||
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, gdk_device_get_display (priv->device));
|
||||
break;
|
||||
|
||||
case PROP_DRAG:
|
||||
g_value_set_object (value, priv->drag);
|
||||
break;
|
||||
|
||||
case PROP_FORMATS:
|
||||
g_value_set_boxed (value, priv->formats);
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
g_value_set_object (value, priv->surface);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_finalize (GObject *object)
|
||||
{
|
||||
GdkDrop *self = GDK_DROP (object);
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->device);
|
||||
g_clear_object (&priv->drag);
|
||||
|
||||
G_OBJECT_CLASS (gdk_drop_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_class_init (GdkDropClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->status = gdk_drop_default_status;
|
||||
|
||||
object_class->get_property = gdk_drop_get_property;
|
||||
object_class->set_property = gdk_drop_set_property;
|
||||
object_class->finalize = gdk_drop_finalize;
|
||||
|
||||
/**
|
||||
* GdkDrop:actions:
|
||||
*
|
||||
* The possible actions for this drop
|
||||
*/
|
||||
properties[PROP_ACTIONS] =
|
||||
g_param_spec_flags ("actions",
|
||||
"Actions",
|
||||
"The possible actions for this drop",
|
||||
GDK_TYPE_DRAG_ACTION,
|
||||
GDK_ACTION_ALL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:device:
|
||||
*
|
||||
* The #GdkDevice performing the drop
|
||||
*/
|
||||
properties[PROP_DEVICE] =
|
||||
g_param_spec_object ("device",
|
||||
"Device",
|
||||
"The device performing the drop",
|
||||
GDK_TYPE_DEVICE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:display:
|
||||
*
|
||||
* The #GdkDisplay that the drop belongs to.
|
||||
*/
|
||||
properties[PROP_DISPLAY] =
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"Display this drag belongs to",
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:drag:
|
||||
*
|
||||
* The #GdkDrag that initiated this drop
|
||||
*/
|
||||
properties[PROP_DRAG] =
|
||||
g_param_spec_object ("drag",
|
||||
"Drag",
|
||||
"The drag that initiated this drop",
|
||||
GDK_TYPE_DRAG_CONTEXT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:formats:
|
||||
*
|
||||
* The possible formats that the drop can provide its data in.
|
||||
*/
|
||||
properties[PROP_FORMATS] =
|
||||
g_param_spec_boxed ("formats",
|
||||
"Formats",
|
||||
"The possible formats for data",
|
||||
GDK_TYPE_CONTENT_FORMATS,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:surface:
|
||||
*
|
||||
* The #GdkSurface the drop happens on
|
||||
*/
|
||||
properties[PROP_SURFACE] =
|
||||
g_param_spec_object ("surface",
|
||||
"Surface",
|
||||
"The surface the drop is happening on",
|
||||
GDK_TYPE_SURFACE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_init (GdkDrop *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_display:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Gets the #GdkDisplay that @self was created for.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkDisplay
|
||||
**/
|
||||
GdkDisplay *
|
||||
gdk_drop_get_display (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
|
||||
return gdk_device_get_display (priv->device);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_device:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Returns the #GdkDevice performing the drop.
|
||||
*
|
||||
* Returns: (transfer none): The #GdkDevice performing the drop.
|
||||
**/
|
||||
GdkDevice *
|
||||
gdk_drop_get_device (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
|
||||
return priv->device;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_formats:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Returns the #GdkContentFormats that the drop offers the data
|
||||
* to be read in.
|
||||
*
|
||||
* Returns: (transfer none): The possible #GdkContentFormats
|
||||
**/
|
||||
GdkContentFormats *
|
||||
gdk_drop_get_formats (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
|
||||
return priv->formats;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_surface:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Returns the #GdkSurface performing the drop.
|
||||
*
|
||||
* Returns: (transfer none): The #GdkSurface performing the drop.
|
||||
**/
|
||||
GdkSurface *
|
||||
gdk_drop_get_surface (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
|
||||
return priv->surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_actions:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Returns the possible actions for this #GdkDrop. If this value
|
||||
* contains multiple actions - ie gdk_drag_action_is_unique()
|
||||
* returns %FALSE for the result - gdk_drag_finish() must choose
|
||||
* the action to use when accepting the drop.
|
||||
*
|
||||
* This value may change over the lifetime of the #GdkDrop both
|
||||
* as a response to source side actions as well as to calls to
|
||||
* gdk_drop_status() or gdk_drag_finish(). The source side will
|
||||
* not change this value anymore once a drop has started.
|
||||
*
|
||||
* Returns: The possible #GdkDragActions
|
||||
**/
|
||||
GdkDragAction
|
||||
gdk_drop_get_actions (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), 0);
|
||||
|
||||
return priv->actions;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_set_actions (GdkDrop *self,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail ((actions & GDK_ACTION_ASK) == 0);
|
||||
|
||||
if (priv->actions == actions)
|
||||
return;
|
||||
|
||||
priv->actions = actions;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_drag:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* If this is an in-app drag-and-drop operation, returns the #GdkDrag
|
||||
* that corresponds to this drop.
|
||||
*
|
||||
* If it is not, %NULL is returned.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the corresponding #GdkDrag
|
||||
**/
|
||||
GdkDragContext *
|
||||
gdk_drop_get_drag (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), 0);
|
||||
|
||||
return priv->drag;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_status:
|
||||
* @self: a #GdkDrop
|
||||
* @actions: Supported actions of the destination, or 0 to indicate
|
||||
* that a drop will not be accepted
|
||||
*
|
||||
* Selects all actions that are potentially supported by the destination.
|
||||
*
|
||||
* When calling this function, do not restrict the passed in actions to
|
||||
* the ones provided by gdk_drop_get_actions(). Those actions may
|
||||
* change in the future, even depending on the actions you provide here.
|
||||
*
|
||||
* This function should be called by drag destinations in response to
|
||||
* %GDK_DRAG_ENTER or %GDK_DRAG_MOTION events. If the destination does
|
||||
* not yet know the exact actions it supports, it should set any possible
|
||||
* actions first and then later call this function again.
|
||||
*/
|
||||
void
|
||||
gdk_drop_status (GdkDrop *self,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
|
||||
GDK_DROP_GET_CLASS (self)->status (self, actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_finish:
|
||||
* @self: a #GdkDrop
|
||||
* @action: the action performed by the destination or 0 if the drop
|
||||
* failed
|
||||
*
|
||||
* Ends the drag operation after a drop.
|
||||
*
|
||||
* The @action must be a single action selected from the actions
|
||||
* available via gdk_drop_get_actions().
|
||||
**/
|
||||
void
|
||||
gdk_drop_finish (GdkDrop *self,
|
||||
GdkDragAction action)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail (gdk_drag_action_is_unique (action));
|
||||
|
||||
GDK_DROP_GET_CLASS (self)->finish (self, action);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_internal (GdkDrop *self,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
if (priv->drag)
|
||||
{
|
||||
gdk_drop_read_local_async (self,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
GDK_DROP_GET_CLASS (self)->read_async (self,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_async:
|
||||
* @self: a #GdkDrop
|
||||
* @mime_types: (array zero-terminated=1) (element-type utf8):
|
||||
* pointer to an array of mime types
|
||||
* @io_priority: the io priority for the read operation
|
||||
* @cancellable: (allow-none): optional #GCancellable object,
|
||||
* %NULL to ignore
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when
|
||||
* the request is satisfied
|
||||
* @user_data: (closure): the data to pass to @callback
|
||||
*
|
||||
* Asynchronously read the dropped data from a #GdkDrop
|
||||
* in a format that complies with one of the mime types.
|
||||
*/
|
||||
void
|
||||
gdk_drop_read_async (GdkDrop *self,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail (mime_types != NULL && mime_types[0] != NULL);
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
formats = gdk_content_formats_new (mime_types, g_strv_length ((char **) mime_types));
|
||||
|
||||
gdk_drop_read_internal (self, formats, io_priority, cancellable, callback, user_data);
|
||||
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_finish:
|
||||
* @self: a #GdkDrop
|
||||
* @out_mime_type: (out) (type utf8): return location for the used mime type
|
||||
* @result: a #GAsyncResult
|
||||
* @error: (allow-none): location to store error information on failure, or %NULL
|
||||
*
|
||||
* Finishes an async drop read operation, see gdk_drop_read_async().
|
||||
*
|
||||
* Returns: (nullable) (transfer full): the #GInputStream, or %NULL
|
||||
*/
|
||||
GInputStream *
|
||||
gdk_drop_read_finish (GdkDrop *self,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (g_async_result_is_tagged (result, gdk_drop_read_local_async))
|
||||
{
|
||||
return gdk_drop_read_local_finish (self, out_mime_type, result, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GDK_DROP_GET_CLASS (self)->read_finish (self, out_mime_type, result, error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_value_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GTask *task = data;
|
||||
GError *error = NULL;
|
||||
GValue *value;
|
||||
|
||||
value = g_task_get_task_data (task);
|
||||
|
||||
if (!gdk_content_deserialize_finish (result, value, &error))
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_pointer (task, value, NULL);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_value_got_stream (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GError *error = NULL;
|
||||
GTask *task = data;
|
||||
const char *mime_type;
|
||||
|
||||
stream = gdk_drop_read_finish (GDK_DROP (source), &mime_type, result, &error);
|
||||
if (stream == NULL)
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_content_deserialize_async (stream,
|
||||
mime_type,
|
||||
G_VALUE_TYPE (g_task_get_task_data (task)),
|
||||
g_task_get_priority (task),
|
||||
g_task_get_cancellable (task),
|
||||
gdk_drop_read_value_done,
|
||||
task);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
free_value (gpointer value)
|
||||
{
|
||||
g_value_unset (value);
|
||||
g_slice_free (GValue, value);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_value_internal (GdkDrop *self,
|
||||
GType type,
|
||||
gpointer source_tag,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkContentFormatsBuilder *builder;
|
||||
GdkContentFormats *formats;
|
||||
GValue *value;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, source_tag);
|
||||
value = g_slice_new0 (GValue);
|
||||
g_value_init (value, type);
|
||||
g_task_set_task_data (task, value, free_value);
|
||||
|
||||
if (priv->drag)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (gdk_content_provider_get_value (priv->drag->content, value, &error))
|
||||
{
|
||||
g_task_return_pointer (task, value, NULL);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fall through to regular stream transfer */
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
gdk_content_formats_builder_add_gtype (builder, type);
|
||||
formats = gdk_content_formats_builder_free_to_formats (builder);
|
||||
formats = gdk_content_formats_union_deserialize_mime_types (formats);
|
||||
|
||||
gdk_drop_read_internal (self,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_drop_read_value_got_stream,
|
||||
task);
|
||||
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_value_async:
|
||||
* @self: a #GdkDrop
|
||||
* @type: a #GType to read
|
||||
* @io_priority: the [I/O priority][io-priority]
|
||||
* of the request.
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
*
|
||||
* Asynchronously request the drag operation's contents converted to the given
|
||||
* @type. When the operation is finished @callback will be called.
|
||||
* You can then call gdk_drop_read_value_finish() to get the resulting
|
||||
* #GValue.
|
||||
*
|
||||
* For local drag'n'drop operations that are available in the given #GType, the
|
||||
* value will be copied directly. Otherwise, GDK will try to use
|
||||
* gdk_content_deserialize_async() to convert the data.
|
||||
**/
|
||||
void
|
||||
gdk_drop_read_value_async (GdkDrop *self,
|
||||
GType type,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
gdk_drop_read_value_internal (self,
|
||||
type,
|
||||
gdk_drop_read_value_async,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_value_finish:
|
||||
* @self: a #GdkDrop
|
||||
* @result: a #GAsyncResult
|
||||
* @error: a #GError location to store the error occurring, or %NULL to
|
||||
* ignore.
|
||||
*
|
||||
* Finishes an async drop read started with
|
||||
* gdk_drop_read_value_async().
|
||||
*
|
||||
* Returns: (transfer none): a #GValue containing the result.
|
||||
**/
|
||||
const GValue *
|
||||
gdk_drop_read_value_finish (GdkDrop *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drop_read_value_async, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_text_async:
|
||||
* @self: a #GdkDrop
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
*
|
||||
* Asynchronously request the drag operation's contents converted to a string.
|
||||
* When the operation is finished @callback will be called. You can then
|
||||
* call gdk_drop_read_text_finish() to get the result.
|
||||
*
|
||||
* This is a simple wrapper around gdk_drop_read_value_async(). Use
|
||||
* that function or gdk_drop_read_async() directly if you need more
|
||||
* control over the operation.
|
||||
**/
|
||||
void
|
||||
gdk_drop_read_text_async (GdkDrop *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
gdk_drop_read_value_internal (self,
|
||||
G_TYPE_STRING,
|
||||
gdk_drop_read_text_async,
|
||||
G_PRIORITY_DEFAULT,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_text_finish:
|
||||
* @self: a #GdkDrop
|
||||
* @result: a #GAsyncResult
|
||||
* @error: a #GError location to store the error occurring, or %NULL to
|
||||
* ignore.
|
||||
*
|
||||
* Finishes an asynchronous read started with
|
||||
* gdk_drop_read_text_async().
|
||||
*
|
||||
* Returns: (transfer full) (nullable): a new string or %NULL on error.
|
||||
**/
|
||||
char *
|
||||
gdk_drop_read_text_finish (GdkDrop *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
const GValue *value;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drop_read_text_async, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
value = g_task_propagate_pointer (G_TASK (result), error);
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
return g_value_dup_string (value);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_do_emit_event (GdkEvent *event,
|
||||
gboolean dont_queue)
|
||||
{
|
||||
if (dont_queue)
|
||||
{
|
||||
_gdk_event_emit (event);
|
||||
g_object_unref (event);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gdk_event_queue_append (gdk_event_get_display (event), event);
|
||||
}
|
||||
}
|
||||
void
|
||||
gdk_drop_emit_enter_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DRAG_ENTER);
|
||||
event->any.surface = g_object_ref (priv->surface);
|
||||
event->dnd.drop = g_object_ref (self);
|
||||
event->dnd.time = time;
|
||||
gdk_event_set_device (event, priv->device);
|
||||
|
||||
gdk_drop_do_emit_event (event, dont_queue);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_emit_motion_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
double x_root,
|
||||
double y_root,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DRAG_MOTION);
|
||||
event->any.surface = g_object_ref (priv->surface);
|
||||
event->dnd.drop = g_object_ref (self);
|
||||
event->dnd.time = time;
|
||||
event->dnd.x_root = x_root;
|
||||
event->dnd.y_root = y_root;
|
||||
gdk_event_set_device (event, priv->device);
|
||||
|
||||
gdk_drop_do_emit_event (event, dont_queue);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_emit_leave_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DRAG_LEAVE);
|
||||
event->any.surface = g_object_ref (priv->surface);
|
||||
event->dnd.drop = g_object_ref (self);
|
||||
event->dnd.time = time;
|
||||
gdk_event_set_device (event, priv->device);
|
||||
|
||||
gdk_drop_do_emit_event (event, dont_queue);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_emit_drop_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
double x_root,
|
||||
double y_root,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DROP_START);
|
||||
event->any.surface = g_object_ref (priv->surface);
|
||||
event->dnd.drop = g_object_ref (self);
|
||||
event->dnd.time = time;
|
||||
event->dnd.x_root = x_root;
|
||||
event->dnd.y_root = y_root;
|
||||
gdk_event_set_device (event, priv->device);
|
||||
|
||||
gdk_drop_do_emit_event (event, dont_queue);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GDK_DROP_H__
|
||||
#define __GDK_DROP_H__
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkversionmacros.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrop, g_object_unref)
|
||||
|
||||
#define GDK_TYPE_DROP (gdk_drop_get_type ())
|
||||
#define GDK_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DROP, GdkDrop))
|
||||
#define GDK_IS_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DROP))
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_drop_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_drop_get_display (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDevice * gdk_drop_get_device (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_drop_get_surface (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats * gdk_drop_get_formats (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drop_get_actions (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragContext * gdk_drop_get_drag (GdkDrop *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_status (GdkDrop *self,
|
||||
GdkDragAction actions);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_finish (GdkDrop *self,
|
||||
GdkDragAction action);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_read_async (GdkDrop *self,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GInputStream * gdk_drop_read_finish (GdkDrop *self,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_read_value_async (GdkDrop *self,
|
||||
GType type,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GValue * gdk_drop_read_value_finish (GdkDrop *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_read_text_async (GdkDrop *drop,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
char * gdk_drop_read_text_finish (GdkDrop *drop,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_DROP_H__ */
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GDK_DROP_PRIVATE_H__
|
||||
#define __GDK_DROP_PRIVATE_H__
|
||||
|
||||
#include "gdkdrop.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GDK_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DROP, GdkDropClass))
|
||||
#define GDK_IS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DROP))
|
||||
#define GDK_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DROP, GdkDropClass))
|
||||
|
||||
typedef struct _GdkDropClass GdkDropClass;
|
||||
|
||||
|
||||
struct _GdkDrop {
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _GdkDropClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* status) (GdkDrop *self,
|
||||
GdkDragAction actions);
|
||||
void (* finish) (GdkDrop *self,
|
||||
GdkDragAction action);
|
||||
|
||||
void (* read_async) (GdkDrop *self,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GInputStream * (* read_finish) (GdkDrop *self,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
};
|
||||
|
||||
void gdk_drop_set_actions (GdkDrop *self,
|
||||
GdkDragAction actions);
|
||||
|
||||
void gdk_drop_emit_enter_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
guint32 time);
|
||||
void gdk_drop_emit_motion_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
double x_root,
|
||||
double y_root,
|
||||
guint32 time);
|
||||
void gdk_drop_emit_leave_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
guint32 time);
|
||||
void gdk_drop_emit_drop_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
double x_root,
|
||||
double y_root,
|
||||
guint32 time);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
+10
-16
@@ -29,6 +29,7 @@
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkdndprivate.h"
|
||||
#include "gdkdropprivate.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -169,9 +170,6 @@ _gdk_event_emit (GdkEvent *event)
|
||||
|
||||
if (_gdk_event_func)
|
||||
(*_gdk_event_func) (event, _gdk_event_data);
|
||||
|
||||
if (gdk_drag_context_handle_dest_event (event))
|
||||
return;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
@@ -645,7 +643,7 @@ gdk_event_copy (const GdkEvent *event)
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
g_object_ref (event->dnd.context);
|
||||
g_object_ref (event->dnd.drop);
|
||||
break;
|
||||
|
||||
case GDK_EXPOSE:
|
||||
@@ -716,8 +714,7 @@ gdk_event_finalize (GObject *object)
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
if (event->dnd.context != NULL)
|
||||
g_object_unref (event->dnd.context);
|
||||
g_clear_object (&event->dnd.drop);
|
||||
break;
|
||||
|
||||
case GDK_BUTTON_PRESS:
|
||||
@@ -2061,17 +2058,15 @@ gdk_event_is_sent (const GdkEvent *event)
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_event_get_drag_context:
|
||||
* gdk_event_get_drop:
|
||||
* @event: a #GdkEvent
|
||||
* @context: (out) (transfer none): return location for the drag context
|
||||
*
|
||||
* Gets the drag context from a DND event.
|
||||
* Gets the #GdkDrop from a DND event.
|
||||
*
|
||||
* Returns: %TRUE on success, otherwise %FALSE
|
||||
* Returns: (transfer none) (nullable): the drop
|
||||
**/
|
||||
gboolean
|
||||
gdk_event_get_drag_context (const GdkEvent *event,
|
||||
GdkDragContext **context)
|
||||
GdkDrop *
|
||||
gdk_event_get_drop (const GdkEvent *event)
|
||||
{
|
||||
if (!event)
|
||||
return FALSE;
|
||||
@@ -2081,11 +2076,10 @@ gdk_event_get_drag_context (const GdkEvent *event,
|
||||
event->any.type == GDK_DRAG_MOTION ||
|
||||
event->any.type == GDK_DROP_START)
|
||||
{
|
||||
*context = event->dnd.context;
|
||||
return TRUE;
|
||||
return event->dnd.drop;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-2
@@ -513,8 +513,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_is_sent (const GdkEvent *event);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_get_drag_context (const GdkEvent *event,
|
||||
GdkDragContext **context);
|
||||
GdkDrop * gdk_event_get_drop (const GdkEvent *event);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_get_crossing_mode (const GdkEvent *event,
|
||||
|
||||
@@ -430,7 +430,7 @@ struct _GdkEventGrabBroken {
|
||||
* %GDK_DRAG_MOTION or %GDK_DROP_START)
|
||||
* @surface: the surface which received the event.
|
||||
* @send_event: %TRUE if the event was sent explicitly.
|
||||
* @context: the #GdkDragContext for the current DND operation.
|
||||
* @drop: the #GdkDrop for the current DND operation.
|
||||
* @time: the time of the event in milliseconds.
|
||||
* @x_root: the x coordinate of the pointer relative to the root of the
|
||||
* screen, only set for %GDK_DRAG_MOTION and %GDK_DROP_START.
|
||||
@@ -441,7 +441,7 @@ struct _GdkEventGrabBroken {
|
||||
*/
|
||||
struct _GdkEventDND {
|
||||
GdkEventAny any;
|
||||
GdkDragContext *context;
|
||||
GdkDrop *drop;
|
||||
|
||||
guint32 time;
|
||||
gshort x_root, y_root;
|
||||
|
||||
@@ -124,6 +124,7 @@ typedef struct _GdkCursor GdkCursor;
|
||||
typedef struct _GdkTexture GdkTexture;
|
||||
typedef struct _GdkDevice GdkDevice;
|
||||
typedef struct _GdkDragContext GdkDragContext;
|
||||
typedef struct _GdkDrop GdkDrop;
|
||||
|
||||
typedef struct _GdkClipboard GdkClipboard;
|
||||
typedef struct _GdkDisplayManager GdkDisplayManager;
|
||||
@@ -575,6 +576,35 @@ typedef enum
|
||||
GDK_AXIS_FLAG_SLIDER = 1 << GDK_AXIS_SLIDER,
|
||||
} GdkAxisFlags;
|
||||
|
||||
/**
|
||||
* GdkDragAction:
|
||||
* @GDK_ACTION_COPY: Copy the data.
|
||||
* @GDK_ACTION_MOVE: Move the data, i.e. first copy it, then delete
|
||||
* it from the source using the DELETE target of the X selection protocol.
|
||||
* @GDK_ACTION_LINK: Add a link to the data. Note that this is only
|
||||
* useful if source and destination agree on what it means.
|
||||
* @GDK_ACTION_ASK: Ask the user what to do with the data.
|
||||
*
|
||||
* Used in #GdkDragContext to indicate what the destination
|
||||
* should do with the dropped data.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GDK_ACTION_COPY = 1 << 0,
|
||||
GDK_ACTION_MOVE = 1 << 1,
|
||||
GDK_ACTION_LINK = 1 << 2,
|
||||
GDK_ACTION_ASK = 1 << 3
|
||||
} GdkDragAction;
|
||||
|
||||
/**
|
||||
* GDK_ACTION_ALL:
|
||||
*
|
||||
* Defines all possible DND actions. This can be used in gdk_drop_status()
|
||||
* messages when any drop can be accepted or a more specific drop method
|
||||
* is not yet known.
|
||||
*/
|
||||
#define GDK_ACTION_ALL (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_TYPES_H__ */
|
||||
|
||||
@@ -17,6 +17,7 @@ gdk_public_sources = files([
|
||||
'gdkdisplaymanager.c',
|
||||
'gdkdnd.c',
|
||||
'gdkdrawcontext.c',
|
||||
'gdkdrop.c',
|
||||
'gdkevents.c',
|
||||
'gdkframeclock.c',
|
||||
'gdkframeclockidle.c',
|
||||
@@ -66,6 +67,7 @@ gdk_public_headers = files([
|
||||
'gdkdisplaymanager.h',
|
||||
'gdkdnd.h',
|
||||
'gdkdrawcontext.h',
|
||||
'gdkdrop.h',
|
||||
'gdkevents.h',
|
||||
'gdkframeclock.h',
|
||||
'gdkframetimings.h',
|
||||
|
||||
@@ -527,16 +527,6 @@ drag_operation_to_drag_action (NSDragOperation operation)
|
||||
/* GDK and Quartz drag operations do not map 1:1.
|
||||
* This mapping represents about the best that we
|
||||
* can come up.
|
||||
*
|
||||
* Note that NSDragOperationPrivate and GDK_ACTION_PRIVATE
|
||||
* have almost opposite meanings: the GDK one means that the
|
||||
* destination is solely responsible for the action; the Quartz
|
||||
* one means that the source and destination will agree
|
||||
* privately on the action. NSOperationGeneric is close in meaning
|
||||
* to GDK_ACTION_PRIVATE but there is a problem: it will be
|
||||
* sent for any ordinary drag, and likely not understood
|
||||
* by any intra-widget drag (since the source & dest are the
|
||||
* same).
|
||||
*/
|
||||
|
||||
if (operation & NSDragOperationGeneric)
|
||||
@@ -569,11 +559,13 @@ drag_action_to_drag_operation (GdkDragAction action)
|
||||
static void
|
||||
update_context_from_dragging_info (id <NSDraggingInfo> sender)
|
||||
{
|
||||
GdkDragAction action;
|
||||
|
||||
g_assert (current_context != NULL);
|
||||
|
||||
GDK_QUARTZ_DRAG_CONTEXT (current_context)->dragging_info = sender;
|
||||
current_context->suggested_action = drag_operation_to_drag_action ([sender draggingSourceOperationMask]);
|
||||
current_context->actions = current_context->suggested_action;
|
||||
action = drag_operation_to_drag_action ([sender draggingSourceOperationMask]);
|
||||
gdk_drag_context_set_actions (current_context, action, action);
|
||||
}
|
||||
|
||||
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
|
||||
@@ -70,22 +70,6 @@ gdk_quartz_drag_context_drag_abort (GdkDragContext *context,
|
||||
/* FIXME: Implement */
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_drag_context_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time)
|
||||
{
|
||||
context->action = action;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_drag_context_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
{
|
||||
/* FIXME: Implement */
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_quartz_surface_register_dnd (GdkSurface *window)
|
||||
{
|
||||
@@ -117,8 +101,6 @@ gdk_quartz_drag_context_class_init (GdkQuartzDragContextClass *klass)
|
||||
|
||||
object_class->finalize = gdk_quartz_drag_context_finalize;
|
||||
|
||||
context_class->drag_status = gdk_quartz_drag_context_drag_status;
|
||||
context_class->drag_abort = gdk_quartz_drag_context_drag_abort;
|
||||
context_class->drag_drop = gdk_quartz_drag_context_drag_drop;
|
||||
context_class->drop_finish = gdk_quartz_drag_context_drop_finish;
|
||||
}
|
||||
|
||||
@@ -246,7 +246,8 @@ struct _GdkWaylandSeat
|
||||
GdkClipboard *clipboard;
|
||||
GdkClipboard *primary_clipboard;
|
||||
struct wl_data_device *data_device;
|
||||
GdkDragContext *drop_context;
|
||||
GdkDragContext *drag;
|
||||
GdkDrop *drop;
|
||||
|
||||
/* Source/dest for non-local dnd */
|
||||
GdkSurface *foreign_dnd_surface;
|
||||
@@ -1140,8 +1141,6 @@ data_offer_source_actions (void *data,
|
||||
uint32_t source_actions)
|
||||
{
|
||||
GdkWaylandSeat *seat = data;
|
||||
GdkDragContext *drop_context;
|
||||
GdkDevice *device;
|
||||
|
||||
if (offer == seat->pending_offer)
|
||||
{
|
||||
@@ -1149,15 +1148,16 @@ data_offer_source_actions (void *data,
|
||||
return;
|
||||
}
|
||||
|
||||
device = gdk_seat_get_pointer (GDK_SEAT (seat));
|
||||
drop_context = gdk_wayland_device_get_drop_context (device);
|
||||
if (drop_context == NULL)
|
||||
if (seat->drop == NULL)
|
||||
return;
|
||||
|
||||
drop_context->actions = gdk_wayland_actions_to_gdk_actions (source_actions);
|
||||
gdk_wayland_drop_set_source_actions (seat->drop, source_actions);
|
||||
|
||||
_gdk_wayland_drag_context_emit_event (drop_context, GDK_DRAG_MOTION,
|
||||
GDK_CURRENT_TIME);
|
||||
gdk_drop_emit_motion_event (seat->drop,
|
||||
FALSE,
|
||||
seat->pointer_info.surface_x,
|
||||
seat->pointer_info.surface_y,
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1166,8 +1166,6 @@ data_offer_action (void *data,
|
||||
uint32_t action)
|
||||
{
|
||||
GdkWaylandSeat *seat = data;
|
||||
GdkDragContext *drop_context;
|
||||
GdkDevice *device;
|
||||
|
||||
if (offer == seat->pending_offer)
|
||||
{
|
||||
@@ -1175,15 +1173,16 @@ data_offer_action (void *data,
|
||||
return;
|
||||
}
|
||||
|
||||
device = gdk_seat_get_pointer (GDK_SEAT (seat));
|
||||
drop_context = gdk_wayland_device_get_drop_context (device);
|
||||
if (drop_context == NULL)
|
||||
if (seat->drop == NULL)
|
||||
return;
|
||||
|
||||
drop_context->action = gdk_wayland_actions_to_gdk_actions (action);
|
||||
gdk_wayland_drop_set_action (seat->drop, action);
|
||||
|
||||
_gdk_wayland_drag_context_emit_event (drop_context, GDK_DRAG_MOTION,
|
||||
GDK_CURRENT_TIME);
|
||||
gdk_drop_emit_motion_event (seat->drop,
|
||||
FALSE,
|
||||
seat->pointer_info.surface_x,
|
||||
seat->pointer_info.surface_y,
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static const struct wl_data_offer_listener data_offer_listener = {
|
||||
@@ -1225,7 +1224,7 @@ data_device_enter (void *data,
|
||||
struct wl_data_offer *offer)
|
||||
{
|
||||
GdkWaylandSeat *seat = data;
|
||||
GdkSurface *dest_surface, *dnd_owner;
|
||||
GdkSurface *dest_surface;
|
||||
GdkContentFormats *formats;
|
||||
GdkDevice *device;
|
||||
|
||||
@@ -1265,22 +1264,13 @@ data_device_enter (void *data,
|
||||
seat->pending_builder = NULL;
|
||||
seat->pending_offer = NULL;
|
||||
|
||||
seat->drop_context = _gdk_wayland_drop_context_new (device, formats, offer);
|
||||
|
||||
dnd_owner = seat->foreign_dnd_surface;
|
||||
|
||||
_gdk_wayland_drag_context_set_source_surface (seat->drop_context, dnd_owner);
|
||||
|
||||
_gdk_wayland_drag_context_set_dest_surface (seat->drop_context,
|
||||
dest_surface, serial);
|
||||
_gdk_wayland_drag_context_set_coords (seat->drop_context,
|
||||
wl_fixed_to_double (x),
|
||||
wl_fixed_to_double (y));
|
||||
seat->drop = gdk_wayland_drop_new (device, seat->drag, formats, dest_surface, offer, serial);
|
||||
|
||||
gdk_wayland_seat_discard_pending_offer (seat);
|
||||
|
||||
_gdk_wayland_drag_context_emit_event (seat->drop_context, GDK_DRAG_ENTER,
|
||||
GDK_CURRENT_TIME);
|
||||
gdk_drop_emit_enter_event (seat->drop,
|
||||
FALSE,
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1292,18 +1282,17 @@ data_device_leave (void *data,
|
||||
GDK_DISPLAY_NOTE (seat->display, EVENTS,
|
||||
g_message ("data device leave, data device %p", data_device));
|
||||
|
||||
if (seat->drop_context == NULL)
|
||||
if (seat->drop == NULL)
|
||||
return;
|
||||
|
||||
g_object_unref (seat->pointer_info.focus);
|
||||
seat->pointer_info.focus = NULL;
|
||||
|
||||
_gdk_wayland_drag_context_set_coords (seat->drop_context, -1, -1);
|
||||
_gdk_wayland_drag_context_emit_event (seat->drop_context, GDK_DRAG_LEAVE,
|
||||
GDK_CURRENT_TIME);
|
||||
_gdk_wayland_drag_context_set_dest_surface (seat->drop_context, NULL, 0);
|
||||
gdk_drop_emit_leave_event (seat->drop,
|
||||
FALSE,
|
||||
GDK_CURRENT_TIME);
|
||||
|
||||
g_clear_object (&seat->drop_context);
|
||||
g_clear_object (&seat->drop);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1319,18 +1308,18 @@ data_device_motion (void *data,
|
||||
g_message ("data device motion, data_device = %p, time = %d, x = %f, y = %f",
|
||||
data_device, time, wl_fixed_to_double (x), wl_fixed_to_double (y)));
|
||||
|
||||
if (seat->drop_context == NULL)
|
||||
if (seat->drop == NULL)
|
||||
return;
|
||||
|
||||
/* Update pointer state, so device state queries work during DnD */
|
||||
seat->pointer_info.surface_x = wl_fixed_to_double (x);
|
||||
seat->pointer_info.surface_y = wl_fixed_to_double (y);
|
||||
|
||||
_gdk_wayland_drag_context_set_coords (seat->drop_context,
|
||||
wl_fixed_to_double (x),
|
||||
wl_fixed_to_double (y));
|
||||
_gdk_wayland_drag_context_emit_event (seat->drop_context,
|
||||
GDK_DRAG_MOTION, time);
|
||||
gdk_drop_emit_motion_event (seat->drop,
|
||||
FALSE,
|
||||
seat->pointer_info.surface_x,
|
||||
seat->pointer_info.surface_y,
|
||||
time);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1342,8 +1331,11 @@ data_device_drop (void *data,
|
||||
GDK_DISPLAY_NOTE (seat->display, EVENTS,
|
||||
g_message ("data device drop, data device %p", data_device));
|
||||
|
||||
_gdk_wayland_drag_context_emit_event (seat->drop_context,
|
||||
GDK_DROP_START, GDK_CURRENT_TIME);
|
||||
gdk_drop_emit_drop_event (seat->drop,
|
||||
FALSE,
|
||||
seat->pointer_info.surface_x,
|
||||
seat->pointer_info.surface_y,
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4606,7 +4598,8 @@ gdk_wayland_seat_finalize (GObject *object)
|
||||
gdk_wayland_pointer_data_finalize (&seat->pointer_info);
|
||||
/* FIXME: destroy data_device */
|
||||
g_clear_object (&seat->keyboard_settings);
|
||||
g_clear_object (&seat->drop_context);
|
||||
g_clear_object (&seat->drag);
|
||||
g_clear_object (&seat->drop);
|
||||
g_clear_object (&seat->clipboard);
|
||||
g_clear_object (&seat->primary_clipboard);
|
||||
g_hash_table_destroy (seat->touches);
|
||||
@@ -5146,6 +5139,15 @@ gdk_wayland_seat_set_global_cursor (GdkSeat *seat,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_seat_set_drag (GdkSeat *seat,
|
||||
GdkDragContext *context)
|
||||
{
|
||||
GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
|
||||
|
||||
g_set_object (&wayland_seat->drag, context);
|
||||
}
|
||||
|
||||
struct wl_data_device *
|
||||
gdk_wayland_device_get_data_device (GdkDevice *gdk_device)
|
||||
{
|
||||
@@ -5189,14 +5191,6 @@ gdk_wayland_seat_get_wl_seat (GdkSeat *seat)
|
||||
return GDK_WAYLAND_SEAT (seat)->wl_seat;
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
gdk_wayland_device_get_drop_context (GdkDevice *device)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (device);
|
||||
|
||||
return GDK_WAYLAND_SEAT (seat)->drop_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_device_get_node_path:
|
||||
* @device: a #GdkDevice
|
||||
|
||||
@@ -666,8 +666,6 @@ _gdk_wayland_display_open (const gchar *display_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display_wayland->selection = gdk_wayland_selection_new ();
|
||||
|
||||
gdk_display_emit_opened (display);
|
||||
|
||||
return display;
|
||||
@@ -693,12 +691,6 @@ gdk_wayland_display_dispose (GObject *object)
|
||||
display_wayland->event_source = NULL;
|
||||
}
|
||||
|
||||
if (display_wayland->selection)
|
||||
{
|
||||
gdk_wayland_selection_free (display_wayland->selection);
|
||||
display_wayland->selection = NULL;
|
||||
}
|
||||
|
||||
g_list_free_full (display_wayland->async_roundtrips, (GDestroyNotify) wl_callback_destroy);
|
||||
|
||||
if (display_wayland->known_globals)
|
||||
@@ -1356,15 +1348,6 @@ _gdk_wayland_is_shm_surface (cairo_surface_t *surface)
|
||||
return cairo_surface_get_user_data (surface, &gdk_wayland_shm_surface_cairo_key) != NULL;
|
||||
}
|
||||
|
||||
GdkWaylandSelection *
|
||||
gdk_wayland_display_get_selection (GdkDisplay *display)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
return display_wayland->selection;
|
||||
}
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSD_FONT_ANTIALIASING_MODE_NONE,
|
||||
|
||||
@@ -139,8 +139,6 @@ struct _GdkWaylandDisplay
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
|
||||
GdkWaylandSelection *selection;
|
||||
|
||||
GPtrArray *monitors;
|
||||
|
||||
gint64 last_bell_time_ms;
|
||||
|
||||
+206
-195
@@ -53,8 +53,6 @@ struct _GdkWaylandDragContext
|
||||
struct wl_data_offer *offer;
|
||||
GdkDragAction selected_action;
|
||||
uint32_t serial;
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
gint hot_x;
|
||||
gint hot_y;
|
||||
};
|
||||
@@ -79,10 +77,7 @@ gdk_wayland_drag_context_finalize (GObject *object)
|
||||
|
||||
contexts = g_list_remove (contexts, context);
|
||||
|
||||
if (context->is_source)
|
||||
{
|
||||
gdk_drag_context_set_cursor (context, NULL);
|
||||
}
|
||||
gdk_drag_context_set_cursor (context, NULL);
|
||||
|
||||
g_clear_pointer (&wayland_context->data_source, (GDestroyNotify) wl_data_source_destroy);
|
||||
g_clear_pointer (&wayland_context->offer, (GDestroyNotify) wl_data_offer_destroy);
|
||||
@@ -95,48 +90,12 @@ gdk_wayland_drag_context_finalize (GObject *object)
|
||||
gdk_surface_destroy (dnd_surface);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_drag_context_emit_event (GdkDragContext *context,
|
||||
GdkEventType type,
|
||||
guint32 time_)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
GdkEvent *event;
|
||||
|
||||
switch ((guint) type)
|
||||
{
|
||||
case GDK_DRAG_ENTER:
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->is_source)
|
||||
surface = gdk_drag_context_get_source_surface (context);
|
||||
else
|
||||
surface = gdk_drag_context_get_dest_surface (context);
|
||||
|
||||
event = gdk_event_new (type);
|
||||
event->any.surface = g_object_ref (surface);
|
||||
event->dnd.context = g_object_ref (context);
|
||||
event->dnd.time = time_;
|
||||
event->dnd.x_root = GDK_WAYLAND_DRAG_CONTEXT (context)->x;
|
||||
event->dnd.y_root = GDK_WAYLAND_DRAG_CONTEXT (context)->y;
|
||||
gdk_event_set_device (event, gdk_drag_context_get_device (context));
|
||||
|
||||
gdk_display_put_event (gdk_surface_get_display (surface), event);
|
||||
g_object_unref (event);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
gdk_to_wl_actions (GdkDragAction action)
|
||||
{
|
||||
uint32_t dnd_actions = 0;
|
||||
|
||||
if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_PRIVATE))
|
||||
if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK))
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
if (action & GDK_ACTION_MOVE)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
@@ -146,13 +105,6 @@ gdk_to_wl_actions (GdkDragAction action)
|
||||
return dnd_actions;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_drag_context_set_action (GdkDragContext *context,
|
||||
GdkDragAction action)
|
||||
{
|
||||
context->suggested_action = context->action = action;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drag_abort (GdkDragContext *context,
|
||||
guint32 time)
|
||||
@@ -168,20 +120,15 @@ gdk_wayland_drag_context_drag_drop (GdkDragContext *context,
|
||||
/* Destination side */
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_context_set_status (GdkDragContext *context,
|
||||
gboolean accepted)
|
||||
gdk_wayland_drop_context_set_status (GdkWaylandDragContext *context_wayland,
|
||||
gboolean accepted)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
|
||||
if (!context->dest_surface)
|
||||
return;
|
||||
|
||||
if (accepted)
|
||||
{
|
||||
const char *const *mimetypes;
|
||||
gsize i, n_mimetypes;
|
||||
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drag_context_get_formats (context), &n_mimetypes);
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drop_get_formats (GDK_DROP (context_wayland)), &n_mimetypes);
|
||||
for (i = 0; i < n_mimetypes; i++)
|
||||
{
|
||||
if (mimetypes[i] != g_intern_static_string ("DELETE"))
|
||||
@@ -199,52 +146,58 @@ gdk_wayland_drop_context_set_status (GdkDragContext *context,
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_commit_status (GdkDragContext *context)
|
||||
gdk_wayland_drag_context_commit_status (GdkWaylandDragContext *wayland_context)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
GdkDisplay *display;
|
||||
uint32_t dnd_actions, all_actions = 0;
|
||||
uint32_t dnd_actions;
|
||||
|
||||
display = gdk_device_get_display (gdk_drag_context_get_device (context));
|
||||
display = gdk_drop_get_display (GDK_DROP (wayland_context));
|
||||
|
||||
dnd_actions = gdk_to_wl_actions (wayland_context->selected_action);
|
||||
|
||||
if (dnd_actions != 0)
|
||||
all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE |
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
|
||||
if (GDK_WAYLAND_DISPLAY (display)->data_device_manager_version >=
|
||||
WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION)
|
||||
wl_data_offer_set_actions (wayland_context->offer, all_actions, dnd_actions);
|
||||
{
|
||||
if (gdk_drag_action_is_unique (wayland_context->selected_action))
|
||||
{
|
||||
wl_data_offer_set_actions (wayland_context->offer, dnd_actions, dnd_actions);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_data_offer_set_actions (wayland_context->offer,
|
||||
dnd_actions | WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK,
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_wayland_drop_context_set_status (context, wayland_context->selected_action != 0);
|
||||
gdk_wayland_drop_context_set_status (wayland_context, wayland_context->selected_action != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time_)
|
||||
gdk_wayland_drag_context_status (GdkDrop *drop,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context;
|
||||
|
||||
wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
wayland_context = GDK_WAYLAND_DRAG_CONTEXT (drop);
|
||||
wayland_context->selected_action = action;
|
||||
|
||||
gdk_wayland_drag_context_commit_status (wayland_context);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
gdk_wayland_drag_context_finish (GdkDrop *drop,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
GdkDisplay *display = gdk_device_get_display (gdk_drag_context_get_device (context));
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (drop);
|
||||
GdkDisplay *display = gdk_drop_get_display (drop);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
if (success && wayland_context->selected_action &&
|
||||
wayland_context->selected_action != GDK_ACTION_ASK)
|
||||
wayland_context->selected_action = action;
|
||||
|
||||
if (action)
|
||||
{
|
||||
gdk_wayland_drag_context_commit_status (context);
|
||||
gdk_wayland_drag_context_commit_status (wayland_context);
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_OFFER_FINISH_SINCE_VERSION)
|
||||
@@ -253,14 +206,14 @@ gdk_wayland_drag_context_drop_finish (GdkDragContext *context,
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_read_async (GdkDragContext *context,
|
||||
gdk_wayland_drag_context_read_async (GdkDrop *drop,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (drop);
|
||||
GdkDisplay *display;
|
||||
GInputStream *stream;
|
||||
const char *mime_type;
|
||||
@@ -268,16 +221,16 @@ gdk_wayland_drag_context_read_async (GdkDragContext *context,
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
display = gdk_drag_context_get_display (context),
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
display = gdk_drop_get_display (drop),
|
||||
task = g_task_new (drop, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_wayland_drag_context_read_async);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND, char *s = gdk_content_formats_to_string (formats);
|
||||
g_message ("%p: read for %s", context, s);
|
||||
g_message ("%p: read for %s", drop, s);
|
||||
g_free (s); );
|
||||
mime_type = gdk_content_formats_match_mime_type (formats,
|
||||
gdk_drag_context_get_formats (context));
|
||||
gdk_drop_get_formats (drop));
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
@@ -300,14 +253,14 @@ gdk_wayland_drag_context_read_async (GdkDragContext *context,
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_wayland_drag_context_read_finish (GdkDragContext *context,
|
||||
gdk_wayland_drag_context_read_finish (GdkDrop *drop,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (context)), NULL);
|
||||
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_wayland_drag_context_read_async, NULL);
|
||||
|
||||
@@ -326,8 +279,6 @@ gdk_wayland_drag_context_init (GdkWaylandDragContext *context_wayland)
|
||||
contexts = g_list_prepend (contexts, context);
|
||||
|
||||
context->action = GDK_ACTION_COPY;
|
||||
context->suggested_action = GDK_ACTION_COPY;
|
||||
context->actions = GDK_ACTION_COPY | GDK_ACTION_MOVE;
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
@@ -395,6 +346,9 @@ gdk_wayland_drag_context_drop_done (GdkDragContext *context,
|
||||
gboolean success)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
GdkDevice *device = gdk_drag_context_get_device (context);
|
||||
|
||||
gdk_wayland_seat_set_drag (gdk_device_get_seat (device), context);
|
||||
|
||||
if (success)
|
||||
{
|
||||
@@ -407,17 +361,18 @@ static void
|
||||
gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *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_wayland_drag_context_finalize;
|
||||
|
||||
context_class->drag_status = gdk_wayland_drag_context_drag_status;
|
||||
drop_class->status = gdk_wayland_drag_context_status;
|
||||
drop_class->finish = gdk_wayland_drag_context_finish;
|
||||
drop_class->read_async = gdk_wayland_drag_context_read_async;
|
||||
drop_class->read_finish = gdk_wayland_drag_context_read_finish;
|
||||
|
||||
context_class->drag_abort = gdk_wayland_drag_context_drag_abort;
|
||||
context_class->drag_drop = gdk_wayland_drag_context_drag_drop;
|
||||
context_class->drop_finish = gdk_wayland_drag_context_drop_finish;
|
||||
context_class->drop_finish = gdk_wayland_drag_context_drop_finish;
|
||||
context_class->read_async = gdk_wayland_drag_context_read_async;
|
||||
context_class->read_finish = gdk_wayland_drag_context_read_finish;
|
||||
context_class->get_drag_surface = gdk_wayland_drag_context_get_drag_surface;
|
||||
context_class->set_hotspot = gdk_wayland_drag_context_set_hotspot;
|
||||
context_class->drop_done = gdk_wayland_drag_context_drop_done;
|
||||
@@ -425,7 +380,6 @@ gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass)
|
||||
context_class->action_changed = gdk_wayland_drag_context_action_changed;
|
||||
context_class->drop_performed = gdk_wayland_drag_context_drop_performed;
|
||||
context_class->cancel = gdk_wayland_drag_context_cancel;
|
||||
context_class->commit_drag_status = gdk_wayland_drag_context_commit_status;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -445,21 +399,161 @@ create_dnd_surface (GdkDisplay *display)
|
||||
return surface;
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
_gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
gint dx,
|
||||
gint dy)
|
||||
static inline GdkDragAction
|
||||
_wl_to_gdk_actions (uint32_t dnd_actions)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland;
|
||||
GdkDragContext *context;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
GdkDragAction actions = 0;
|
||||
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||
actions |= GDK_ACTION_COPY;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||
actions |= GDK_ACTION_MOVE;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
actions |= GDK_ACTION_ASK;
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_target (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("data source target, source = %p, mime_type = %s",
|
||||
source, mime_type));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_write_done (GObject *context,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_drag_context_write_finish (GDK_DRAG_CONTEXT (context), result, &error))
|
||||
{
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (GDK_DRAG_CONTEXT (context)), DND, g_message ("%p: failed to write stream: %s", context, error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_send (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
GdkDragContext *context = data;
|
||||
GOutputStream *stream;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), DND, g_message ("%p: data source send request for %s on fd %d\n",
|
||||
source, mime_type, fd));
|
||||
|
||||
//mime_type = gdk_intern_mime_type (mime_type);
|
||||
mime_type = g_intern_string (mime_type);
|
||||
stream = g_unix_output_stream_new (fd, TRUE);
|
||||
|
||||
gdk_drag_context_write_async (context,
|
||||
mime_type,
|
||||
stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_wayland_drag_context_write_done,
|
||||
context);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_cancelled (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDragContext *context = data;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), EVENTS,
|
||||
g_message ("data source cancelled, source = %p", source));
|
||||
|
||||
gdk_drag_context_cancel (context, GDK_DRAG_CANCEL_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_dnd_drop_performed (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDragContext *context = data;
|
||||
|
||||
g_signal_emit_by_name (context, "drop-performed", GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_dnd_finished (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDragContext *context = data;
|
||||
|
||||
g_signal_emit_by_name (context, "dnd-finished");
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_action (void *data,
|
||||
struct wl_data_source *source,
|
||||
uint32_t action)
|
||||
{
|
||||
GdkDragContext *context = data;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), EVENTS,
|
||||
g_message ("data source action, source = %p action=%x",
|
||||
source, action));
|
||||
|
||||
context->action = _wl_to_gdk_actions (action);
|
||||
g_signal_emit_by_name (context, "action-changed", context->action);
|
||||
}
|
||||
|
||||
static const struct wl_data_source_listener data_source_listener = {
|
||||
data_source_target,
|
||||
data_source_send,
|
||||
data_source_cancelled,
|
||||
data_source_dnd_drop_performed,
|
||||
data_source_dnd_finished,
|
||||
data_source_action,
|
||||
};
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_create_data_source (GdkDragContext *context)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
GdkDisplay *display = gdk_drag_context_get_display (context);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
const char *const *mimetypes;
|
||||
gsize i, n_mimetypes;
|
||||
|
||||
context_wayland->data_source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
|
||||
wl_data_source_add_listener (context_wayland->data_source,
|
||||
&data_source_listener,
|
||||
context);
|
||||
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drag_context_get_formats (context), &n_mimetypes);
|
||||
for (i = 0; i < n_mimetypes; i++)
|
||||
{
|
||||
wl_data_source_offer (context_wayland->data_source, mimetypes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
_gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
gint dx,
|
||||
gint dy)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland;
|
||||
GdkDragContext *context;
|
||||
GdkSeat *seat;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_device_get_display (device));
|
||||
seat = gdk_device_get_seat (device);
|
||||
|
||||
context_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT,
|
||||
"device", device,
|
||||
@@ -471,14 +565,8 @@ _gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
|
||||
context_wayland->dnd_surface = create_dnd_surface (gdk_surface_get_display (surface));
|
||||
context_wayland->dnd_wl_surface = gdk_wayland_surface_get_wl_surface (context_wayland->dnd_surface);
|
||||
context_wayland->data_source =
|
||||
gdk_wayland_selection_get_data_source (surface);
|
||||
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drag_context_get_formats (context), &n_mimetypes);
|
||||
for (i = 0; i < n_mimetypes; i++)
|
||||
{
|
||||
wl_data_source_offer (context_wayland->data_source, mimetypes[i]);
|
||||
}
|
||||
|
||||
gdk_wayland_drag_context_create_data_source (context);
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION)
|
||||
@@ -487,49 +575,19 @@ _gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
gdk_to_wl_actions (actions));
|
||||
}
|
||||
|
||||
gdk_wayland_seat_set_drag (seat, context);
|
||||
|
||||
wl_data_device_start_drag (gdk_wayland_device_get_data_device (device),
|
||||
context_wayland->data_source,
|
||||
gdk_wayland_surface_get_wl_surface (surface),
|
||||
context_wayland->dnd_wl_surface,
|
||||
_gdk_wayland_display_get_serial (display_wayland));
|
||||
|
||||
gdk_seat_ungrab (gdk_device_get_seat (device));
|
||||
gdk_seat_ungrab (seat);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
GdkDragContext *
|
||||
_gdk_wayland_drop_context_new (GdkDevice *device,
|
||||
GdkContentFormats *formats,
|
||||
struct wl_data_offer *offer)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland;
|
||||
GdkDragContext *context;
|
||||
|
||||
context_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT,
|
||||
"device", device,
|
||||
"formats", formats,
|
||||
NULL);
|
||||
context = GDK_DRAG_CONTEXT (context_wayland);
|
||||
context->is_source = FALSE;
|
||||
context_wayland->offer = offer;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_drag_context_set_coords (GdkDragContext *context,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland;
|
||||
|
||||
context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
context_wayland->x = x;
|
||||
context_wayland->y = y;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_drag_context_set_source_surface (GdkDragContext *context,
|
||||
GdkSurface *surface)
|
||||
@@ -540,50 +598,3 @@ _gdk_wayland_drag_context_set_source_surface (GdkDragContext *context,
|
||||
context->source_surface = surface ? g_object_ref (surface) : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_drag_context_set_dest_surface (GdkDragContext *context,
|
||||
GdkSurface *dest_surface,
|
||||
uint32_t serial)
|
||||
{
|
||||
if (context->dest_surface)
|
||||
g_object_unref (context->dest_surface);
|
||||
|
||||
context->dest_surface = dest_surface ? g_object_ref (dest_surface) : NULL;
|
||||
GDK_WAYLAND_DRAG_CONTEXT (context)->serial = serial;
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
gdk_wayland_drag_context_lookup_by_data_source (struct wl_data_source *source)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = contexts; l; l = l->next)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = l->data;
|
||||
|
||||
if (wayland_context->data_source == source)
|
||||
return l->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
gdk_wayland_drag_context_lookup_by_source_surface (GdkSurface *surface)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = contexts; l; l = l->next)
|
||||
{
|
||||
if (surface == gdk_drag_context_get_source_surface (l->data))
|
||||
return l->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_data_source *
|
||||
gdk_wayland_drag_context_get_data_source (GdkDragContext *context)
|
||||
{
|
||||
return GDK_WAYLAND_DRAG_CONTEXT (context)->data_source;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdndprivate.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkseat-wayland.h"
|
||||
|
||||
#include "gdkdeviceprivate.h"
|
||||
|
||||
#include <glib-unix.h>
|
||||
#include <gio/gunixinputstream.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GDK_TYPE_WAYLAND_DROP (gdk_wayland_drop_get_type ())
|
||||
#define GDK_WAYLAND_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_DROP, GdkWaylandDrop))
|
||||
#define GDK_WAYLAND_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_DROP, GdkWaylandDropClass))
|
||||
#define GDK_IS_WAYLAND_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DROP))
|
||||
#define GDK_IS_WAYLAND_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_DROP))
|
||||
#define GDK_WAYLAND_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_DROP, GdkWaylandDropClass))
|
||||
|
||||
typedef struct _GdkWaylandDrop GdkWaylandDrop;
|
||||
typedef struct _GdkWaylandDropClass GdkWaylandDropClass;
|
||||
|
||||
struct _GdkWaylandDrop
|
||||
{
|
||||
GdkDrop drop;
|
||||
|
||||
struct wl_data_offer *offer;
|
||||
uint32_t source_actions;
|
||||
uint32_t action;
|
||||
GdkDragAction selected_action;
|
||||
uint32_t serial;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDropClass
|
||||
{
|
||||
GdkDropClass parent_class;
|
||||
};
|
||||
|
||||
GType gdk_wayland_drop_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (GdkWaylandDrop, gdk_wayland_drop, GDK_TYPE_DROP)
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_finalize (GObject *object)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (object);
|
||||
|
||||
g_clear_pointer (&wayland_drop->offer, (GDestroyNotify) wl_data_offer_destroy);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_drop_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
gdk_to_wl_actions (GdkDragAction action)
|
||||
{
|
||||
uint32_t dnd_actions = 0;
|
||||
|
||||
if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK))
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
if (action & GDK_ACTION_MOVE)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
if (action & GDK_ACTION_ASK)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
|
||||
return dnd_actions;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_drop_set_status (GdkWaylandDrop *drop_wayland,
|
||||
gboolean accepted)
|
||||
{
|
||||
if (accepted)
|
||||
{
|
||||
const char *const *mimetypes;
|
||||
gsize i, n_mimetypes;
|
||||
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drop_get_formats (GDK_DROP (drop_wayland)), &n_mimetypes);
|
||||
for (i = 0; i < n_mimetypes; i++)
|
||||
{
|
||||
if (mimetypes[i] != g_intern_static_string ("DELETE"))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < n_mimetypes)
|
||||
{
|
||||
wl_data_offer_accept (drop_wayland->offer, drop_wayland->serial, mimetypes[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wl_data_offer_accept (drop_wayland->offer, drop_wayland->serial, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_commit_status (GdkWaylandDrop *wayland_drop)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
uint32_t dnd_actions;
|
||||
|
||||
display = gdk_drop_get_display (GDK_DROP (wayland_drop));
|
||||
|
||||
dnd_actions = gdk_to_wl_actions (wayland_drop->selected_action);
|
||||
|
||||
if (GDK_WAYLAND_DISPLAY (display)->data_device_manager_version >=
|
||||
WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION)
|
||||
{
|
||||
if (gdk_drag_action_is_unique (wayland_drop->selected_action))
|
||||
{
|
||||
wl_data_offer_set_actions (wayland_drop->offer, dnd_actions, dnd_actions);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_data_offer_set_actions (wayland_drop->offer,
|
||||
dnd_actions | WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK,
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_wayland_drop_drop_set_status (wayland_drop, wayland_drop->selected_action != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_status (GdkDrop *drop,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop;
|
||||
|
||||
wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
wayland_drop->selected_action = action;
|
||||
|
||||
gdk_wayland_drop_commit_status (wayland_drop);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_finish (GdkDrop *drop,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
GdkDisplay *display = gdk_drop_get_display (drop);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
wayland_drop->selected_action = action;
|
||||
|
||||
if (action)
|
||||
{
|
||||
gdk_wayland_drop_commit_status (wayland_drop);
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_OFFER_FINISH_SINCE_VERSION)
|
||||
wl_data_offer_finish (wayland_drop->offer);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_read_async (GdkDrop *drop,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
GdkDisplay *display;
|
||||
GInputStream *stream;
|
||||
const char *mime_type;
|
||||
int pipe_fd[2];
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
display = gdk_drop_get_display (drop),
|
||||
task = g_task_new (drop, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_wayland_drop_read_async);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND, char *s = gdk_content_formats_to_string (formats);
|
||||
g_message ("%p: read for %s", drop, s);
|
||||
g_free (s); );
|
||||
mime_type = gdk_content_formats_match_mime_type (formats,
|
||||
gdk_drop_get_formats (drop));
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible transfer format found"));
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_set_task_data (task, (gpointer) mime_type, NULL);
|
||||
|
||||
if (!g_unix_open_pipe (pipe_fd, FD_CLOEXEC, &error))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_data_offer_receive (wayland_drop->offer, mime_type, pipe_fd[1]);
|
||||
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
|
||||
close (pipe_fd[1]);
|
||||
g_task_return_pointer (task, stream, g_object_unref);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_wayland_drop_read_finish (GdkDrop *drop,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
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_wayland_drop_read_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (task);
|
||||
|
||||
return g_task_propagate_pointer (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_class_init (GdkWaylandDropClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkDropClass *drop_class = GDK_DROP_CLASS (klass);
|
||||
|
||||
object_class->finalize = gdk_wayland_drop_finalize;
|
||||
|
||||
drop_class->status = gdk_wayland_drop_status;
|
||||
drop_class->finish = gdk_wayland_drop_finish;
|
||||
drop_class->read_async = gdk_wayland_drop_read_async;
|
||||
drop_class->read_finish = gdk_wayland_drop_read_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_init (GdkWaylandDrop *drop)
|
||||
{
|
||||
}
|
||||
|
||||
GdkDrop *
|
||||
gdk_wayland_drop_new (GdkDevice *device,
|
||||
GdkDragContext *drag,
|
||||
GdkContentFormats *formats,
|
||||
GdkSurface *surface,
|
||||
struct wl_data_offer *offer,
|
||||
uint32_t serial)
|
||||
|
||||
{
|
||||
GdkWaylandDrop *drop;
|
||||
|
||||
drop = g_object_new (GDK_TYPE_WAYLAND_DROP,
|
||||
"device", device,
|
||||
"drag", drag,
|
||||
"formats", formats,
|
||||
"surface", surface,
|
||||
NULL);
|
||||
drop->offer = offer;
|
||||
drop->serial = serial;
|
||||
|
||||
return GDK_DROP (drop);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_update_actions (GdkWaylandDrop *drop)
|
||||
{
|
||||
GdkDragAction gdk_actions = 0;
|
||||
uint32_t wl_actions;
|
||||
|
||||
if (drop->action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
wl_actions = drop->source_actions;
|
||||
else
|
||||
wl_actions = drop->action;
|
||||
|
||||
if (wl_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||
gdk_actions |= GDK_ACTION_COPY;
|
||||
if (wl_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||
gdk_actions |= GDK_ACTION_MOVE;
|
||||
|
||||
gdk_drop_set_actions (GDK_DROP (drop), gdk_actions);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_drop_set_source_actions (GdkDrop *drop,
|
||||
uint32_t source_actions)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
|
||||
wayland_drop->source_actions = source_actions;
|
||||
|
||||
gdk_wayland_drop_update_actions (wayland_drop);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_drop_set_action (GdkDrop *drop,
|
||||
uint32_t action)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
|
||||
wayland_drop->action = action;
|
||||
|
||||
gdk_wayland_drop_update_actions (wayland_drop);
|
||||
}
|
||||
|
||||
@@ -104,27 +104,19 @@ GdkDragContext *_gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
void _gdk_wayland_surface_offset_next_wl_buffer (GdkSurface *surface,
|
||||
int x,
|
||||
int y);
|
||||
GdkDragContext * _gdk_wayland_drop_context_new (GdkDevice *device,
|
||||
GdkContentFormats *formats,
|
||||
struct wl_data_offer *offer);
|
||||
GdkDrop * gdk_wayland_drop_new (GdkDevice *device,
|
||||
GdkDragContext *drag,
|
||||
GdkContentFormats *formats,
|
||||
GdkSurface *surface,
|
||||
struct wl_data_offer *offer,
|
||||
uint32_t serial);
|
||||
void gdk_wayland_drop_set_source_actions (GdkDrop *drop,
|
||||
uint32_t source_actions);
|
||||
void gdk_wayland_drop_set_action (GdkDrop *drop,
|
||||
uint32_t action);
|
||||
|
||||
void _gdk_wayland_drag_context_set_source_surface (GdkDragContext *context,
|
||||
GdkSurface *surface);
|
||||
void _gdk_wayland_drag_context_set_dest_surface (GdkDragContext *context,
|
||||
GdkSurface *dest_surface,
|
||||
uint32_t serial);
|
||||
void _gdk_wayland_drag_context_emit_event (GdkDragContext *context,
|
||||
GdkEventType type,
|
||||
guint32 time_);
|
||||
void _gdk_wayland_drag_context_set_coords (GdkDragContext *context,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
|
||||
void gdk_wayland_drag_context_set_action (GdkDragContext *context,
|
||||
GdkDragAction action);
|
||||
|
||||
GdkDragContext * gdk_wayland_drag_context_lookup_by_data_source (struct wl_data_source *source);
|
||||
GdkDragContext * gdk_wayland_drag_context_lookup_by_source_surface (GdkSurface *surface);
|
||||
struct wl_data_source * gdk_wayland_drag_context_get_data_source (GdkDragContext *context);
|
||||
|
||||
void _gdk_wayland_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
@@ -192,14 +184,6 @@ cairo_surface_t * _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *di
|
||||
struct wl_buffer *_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface);
|
||||
gboolean _gdk_wayland_is_shm_surface (cairo_surface_t *surface);
|
||||
|
||||
GdkWaylandSelection * gdk_wayland_display_get_selection (GdkDisplay *display);
|
||||
GdkWaylandSelection * gdk_wayland_selection_new (void);
|
||||
void gdk_wayland_selection_free (GdkWaylandSelection *selection);
|
||||
|
||||
|
||||
struct wl_data_source * gdk_wayland_selection_get_data_source (GdkSurface *owner);
|
||||
void gdk_wayland_selection_unset_data_source (GdkDisplay *display);
|
||||
|
||||
EGLSurface gdk_wayland_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config);
|
||||
EGLSurface gdk_wayland_surface_get_dummy_egl_surface (GdkSurface *surface,
|
||||
@@ -209,6 +193,8 @@ struct gtk_surface1 * gdk_wayland_surface_get_gtk_surface (GdkSurface *surface);
|
||||
|
||||
void gdk_wayland_seat_set_global_cursor (GdkSeat *seat,
|
||||
GdkCursor *cursor);
|
||||
void gdk_wayland_seat_set_drag (GdkSeat *seat,
|
||||
GdkDragContext *drag);
|
||||
|
||||
struct wl_output *gdk_wayland_surface_get_wl_output (GdkSurface *surface);
|
||||
|
||||
|
||||
@@ -33,210 +33,6 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct _GdkWaylandSelection
|
||||
{
|
||||
struct wl_data_source *dnd_source; /* Owned by the GdkDragContext */
|
||||
};
|
||||
|
||||
GdkWaylandSelection *
|
||||
gdk_wayland_selection_new (void)
|
||||
{
|
||||
GdkWaylandSelection *selection;
|
||||
|
||||
selection = g_new0 (GdkWaylandSelection, 1);
|
||||
|
||||
return selection;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_selection_free (GdkWaylandSelection *selection)
|
||||
{
|
||||
if (selection->dnd_source)
|
||||
wl_data_source_destroy (selection->dnd_source);
|
||||
|
||||
g_free (selection);
|
||||
}
|
||||
|
||||
static inline GdkDragAction
|
||||
_wl_to_gdk_actions (uint32_t dnd_actions)
|
||||
{
|
||||
GdkDragAction actions = 0;
|
||||
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||
actions |= GDK_ACTION_COPY;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||
actions |= GDK_ACTION_MOVE;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
actions |= GDK_ACTION_ASK;
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_target (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("data source target, source = %p, mime_type = %s",
|
||||
source, mime_type));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_write_done (GObject *context,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_drag_context_write_finish (GDK_DRAG_CONTEXT (context), result, &error))
|
||||
{
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (GDK_DRAG_CONTEXT (context)), DND, g_message ("%p: failed to write stream: %s", context, error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_send (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
GOutputStream *stream;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), DND, g_message ("%p: data source send request for %s on fd %d\n",
|
||||
source, mime_type, fd));
|
||||
|
||||
//mime_type = gdk_intern_mime_type (mime_type);
|
||||
mime_type = g_intern_string (mime_type);
|
||||
stream = g_unix_output_stream_new (fd, TRUE);
|
||||
|
||||
gdk_drag_context_write_async (context,
|
||||
mime_type,
|
||||
stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_wayland_drag_context_write_done,
|
||||
context);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_cancelled (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = data;
|
||||
GdkDragContext *context;
|
||||
GdkDisplay *display;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
|
||||
GDK_DISPLAY_NOTE (display, EVENTS,
|
||||
g_message ("data source cancelled, source = %p", source));
|
||||
|
||||
if (source != wayland_selection->dnd_source)
|
||||
return;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
|
||||
if (context)
|
||||
gdk_drag_context_cancel (context, GDK_DRAG_CANCEL_ERROR);
|
||||
|
||||
gdk_wayland_selection_unset_data_source (display);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_dnd_drop_performed (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (context, "drop-performed", GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_dnd_finished (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (context, "dnd-finished");
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_action (void *data,
|
||||
struct wl_data_source *source,
|
||||
uint32_t action)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), EVENTS,
|
||||
g_message ("data source action, source = %p action=%x",
|
||||
source, action));
|
||||
|
||||
context->action = _wl_to_gdk_actions (action);
|
||||
g_signal_emit_by_name (context, "action-changed", context->action);
|
||||
}
|
||||
|
||||
static const struct wl_data_source_listener data_source_listener = {
|
||||
data_source_target,
|
||||
data_source_send,
|
||||
data_source_cancelled,
|
||||
data_source_dnd_drop_performed,
|
||||
data_source_dnd_finished,
|
||||
data_source_action,
|
||||
};
|
||||
|
||||
struct wl_data_source *
|
||||
gdk_wayland_selection_get_data_source (GdkSurface *owner)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (owner);
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
gpointer source = NULL;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
|
||||
if (wayland_selection->dnd_source)
|
||||
return wayland_selection->dnd_source;
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (owner));
|
||||
|
||||
source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
|
||||
wl_data_source_add_listener (source,
|
||||
&data_source_listener,
|
||||
wayland_selection);
|
||||
|
||||
wayland_selection->dnd_source = source;
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_selection_unset_data_source (GdkDisplay *display)
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
wayland_selection->dnd_source = NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
_gdk_wayland_display_text_property_to_utf8_list (GdkDisplay *display,
|
||||
GdkAtom encoding,
|
||||
|
||||
@@ -6,6 +6,7 @@ gdk_wayland_sources = files([
|
||||
'gdkdevice-wayland.c',
|
||||
'gdkdisplay-wayland.c',
|
||||
'gdkdnd-wayland.c',
|
||||
'gdkdrop-wayland.c',
|
||||
'gdkeventsource.c',
|
||||
'gdkglcontext-wayland.c',
|
||||
'gdkkeys-wayland.c',
|
||||
|
||||
@@ -1541,8 +1541,6 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
win32_clipdrop->GetUpdatedClipboardFormats = GetProcAddress (user32, "GetUpdatedClipboardFormats");
|
||||
FreeLibrary (user32);
|
||||
|
||||
win32_clipdrop->dnd_target_state = GDK_WIN32_DND_NONE;
|
||||
|
||||
atoms = g_array_sized_new (FALSE, TRUE, sizeof (GdkAtom), GDK_WIN32_ATOM_INDEX_LAST);
|
||||
g_array_set_size (atoms, GDK_WIN32_ATOM_INDEX_LAST);
|
||||
cfs = g_array_sized_new (FALSE, TRUE, sizeof (UINT), GDK_WIN32_CF_INDEX_LAST);
|
||||
@@ -1876,34 +1874,6 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
win32_clipdrop->dnd_thread_id = GPOINTER_TO_UINT (g_async_queue_pop (win32_clipdrop->dnd_queue));
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_dropfiles_store (gchar *data)
|
||||
{
|
||||
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
|
||||
|
||||
/* FIXME: REMOVE ALL THAT STUFF
|
||||
if (data != NULL)
|
||||
{
|
||||
g_assert (clipdrop->dropfiles_prop == NULL);
|
||||
|
||||
clipdrop->dropfiles_prop = g_new (GdkSelProp, 1);
|
||||
clipdrop->dropfiles_prop->data = (guchar *) data;
|
||||
clipdrop->dropfiles_prop->length = strlen (data) + 1;
|
||||
clipdrop->dropfiles_prop->bitness = 8;
|
||||
clipdrop->dropfiles_prop->target = _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clipdrop->dropfiles_prop != NULL)
|
||||
{
|
||||
g_free (clipdrop->dropfiles_prop->data);
|
||||
g_free (clipdrop->dropfiles_prop);
|
||||
}
|
||||
clipdrop->dropfiles_prop = NULL;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#define CLIPBOARD_IDLE_ABORT_TIME 30
|
||||
|
||||
static const gchar *
|
||||
@@ -1970,7 +1940,7 @@ _gdk_win32_get_clipboard_format_name (UINT fmt,
|
||||
}
|
||||
|
||||
/* If GetClipboardFormatNameW() used up all the space, it means that
|
||||
* we probably need a bigger buffer, but cap this at 1 kilobyte.
|
||||
* we probably need a bigger buffer, but cap this at 1 megabyte.
|
||||
*/
|
||||
if (gcfn_result == 0 || registered_name_w_len > 1024 * 1024)
|
||||
{
|
||||
@@ -1997,12 +1967,22 @@ _gdk_win32_get_clipboard_format_name (UINT fmt,
|
||||
/* This turns an arbitrary string into a string that
|
||||
* *looks* like a mime/type, such as:
|
||||
* "application/x.windows.FOO_BAR" from "FOO_BAR".
|
||||
* Does nothing for strings that already look like a mime/type
|
||||
* (no spaces, one slash, with at least one char on each side of the slash).
|
||||
*/
|
||||
const gchar *
|
||||
_gdk_win32_get_clipboard_format_name_as_interned_mimetype (gchar *w32format_name)
|
||||
{
|
||||
gchar *mime_type;
|
||||
const gchar *result;
|
||||
gchar *space = strchr (w32format_name, ' ');
|
||||
gchar *slash = strchr (w32format_name, '/');
|
||||
|
||||
if (space == NULL &&
|
||||
slash > w32format_name &&
|
||||
slash[1] != '\0' &&
|
||||
strchr (&slash[1], '/') == NULL)
|
||||
return g_intern_string (w32format_name);
|
||||
|
||||
mime_type = g_strdup_printf ("application/x.windows.%s", w32format_name);
|
||||
result = g_intern_string (mime_type);
|
||||
@@ -2061,15 +2041,16 @@ _gdk_win32_get_compatibility_contentformats_for_w32format (UINT w32format)
|
||||
|
||||
/* Turn W32 format into a GDK content format and add it
|
||||
* to the array of W32 format <-> GDK content format pairs
|
||||
* and/or to a list of GDK content formats.
|
||||
* and/or to a GDK contentformat builder.
|
||||
* Also add compatibility GDK content formats for that W32 format.
|
||||
* The added content format string is always interned.
|
||||
* Ensures that duplicates are not added.
|
||||
* Ensures that duplicates are not added to the pairs array
|
||||
* (builder already takes care of that for itself).
|
||||
*/
|
||||
void
|
||||
_gdk_win32_add_w32format_to_pairs (UINT w32format,
|
||||
GArray *array,
|
||||
GList **list)
|
||||
_gdk_win32_add_w32format_to_pairs (UINT w32format,
|
||||
GArray *pairs,
|
||||
GdkContentFormatsBuilder *builder)
|
||||
{
|
||||
gboolean predef;
|
||||
gchar *w32format_name = _gdk_win32_get_clipboard_format_name (w32format, &predef);
|
||||
@@ -2084,47 +2065,45 @@ _gdk_win32_add_w32format_to_pairs (UINT w32format,
|
||||
GDK_NOTE (DND, g_print ("Maybe add as-is format %s (%s) (0x%p)\n", w32format_name, interned_w32format_name, interned_w32format_name));
|
||||
g_free (w32format_name);
|
||||
|
||||
if (array && interned_w32format_name != 0)
|
||||
if (pairs && interned_w32format_name != 0)
|
||||
{
|
||||
for (j = 0; j < array->len; j++)
|
||||
if (g_array_index (array, GdkWin32ContentFormatPair, j).contentformat == interned_w32format_name)
|
||||
for (j = 0; j < pairs->len; j++)
|
||||
if (g_array_index (pairs, GdkWin32ContentFormatPair, j).contentformat == interned_w32format_name)
|
||||
break;
|
||||
if (j == array->len)
|
||||
if (j == pairs->len)
|
||||
{
|
||||
pair.w32format = w32format;
|
||||
pair.contentformat = interned_w32format_name;
|
||||
pair.transmute = FALSE;
|
||||
g_array_append_val (array, pair);
|
||||
g_array_append_val (pairs, pair);
|
||||
}
|
||||
}
|
||||
|
||||
if (list && interned_w32format_name != 0 && g_list_find (*list, interned_w32format_name) == NULL)
|
||||
*list = g_list_prepend (*list, interned_w32format_name);
|
||||
if (builder != NULL && interned_w32format_name != 0)
|
||||
gdk_content_formats_builder_add_mime_type (builder, interned_w32format_name);
|
||||
}
|
||||
|
||||
comp_pairs = _gdk_win32_get_compatibility_contentformats_for_w32format (w32format);
|
||||
|
||||
if (array && comp_pairs != NULL)
|
||||
if (pairs != NULL && comp_pairs != NULL)
|
||||
for (i = 0; i < comp_pairs->len; i++)
|
||||
{
|
||||
pair = g_array_index (comp_pairs, GdkWin32ContentFormatPair, i);
|
||||
|
||||
for (j = 0; j < array->len; j++)
|
||||
if (g_array_index (array, GdkWin32ContentFormatPair, j).contentformat == pair.contentformat &&
|
||||
g_array_index (array, GdkWin32ContentFormatPair, j).w32format == pair.w32format)
|
||||
for (j = 0; j < pairs->len; j++)
|
||||
if (g_array_index (pairs, GdkWin32ContentFormatPair, j).contentformat == pair.contentformat &&
|
||||
g_array_index (pairs, GdkWin32ContentFormatPair, j).w32format == pair.w32format)
|
||||
break;
|
||||
|
||||
if (j == array->len)
|
||||
g_array_append_val (array, pair);
|
||||
if (j == pairs->len)
|
||||
g_array_append_val (pairs, pair);
|
||||
}
|
||||
|
||||
if (list && comp_pairs != NULL)
|
||||
if (builder != NULL && comp_pairs != NULL)
|
||||
for (i = 0; i < comp_pairs->len; i++)
|
||||
{
|
||||
pair = g_array_index (comp_pairs, GdkWin32ContentFormatPair, i);
|
||||
|
||||
if (g_list_find (*list, pair.contentformat) == NULL)
|
||||
*list = g_list_prepend (*list, pair.contentformat);
|
||||
gdk_content_formats_builder_add_mime_type (builder, pair.contentformat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,8 +142,6 @@ struct _GdkWin32Clipdrop
|
||||
*/
|
||||
GArray *known_clipboard_formats;
|
||||
|
||||
GdkWin32DndState dnd_target_state;
|
||||
|
||||
/* A target-keyed hash table of GArrays of GdkWin32ContentFormatPairs describing compatibility w32formats for a contentformat */
|
||||
GHashTable *compatibility_w32formats;
|
||||
/* A format-keyed hash table of GArrays of GdkAtoms describing compatibility contentformats for a w32format */
|
||||
@@ -213,12 +211,12 @@ struct _GdkWin32Clipdrop
|
||||
/* We don't actually support multiple simultaneous drags,
|
||||
* for obvious reasons (though this might change with
|
||||
* the advent of multitouch support?), but there may be
|
||||
* circumstances where we have two drag contexts at
|
||||
* circumstances where we have two drag objects at
|
||||
* the same time (one of them will grab the cursor
|
||||
* and thus cancel the other drag operation, but
|
||||
* there will be a point of time when both contexts
|
||||
* there will be a point of time when both objects
|
||||
* are out there). Thus we keep them around in this hash table.
|
||||
* Key is the context object (which is safe, because the main
|
||||
* Key is the GdkDragContext object (which is safe, because the main
|
||||
* thread keeps a reference on each one of those), value
|
||||
* is a pointer to a GdkWin32DnDThreadDoDragDrop struct,
|
||||
* which we can only examine when we're sure that the
|
||||
@@ -236,42 +234,42 @@ GType gdk_win32_clipdrop_get_type (void) G_GNUC
|
||||
|
||||
void _gdk_win32_clipdrop_init (void);
|
||||
|
||||
gboolean _gdk_win32_format_uses_hdata (UINT w32format);
|
||||
gboolean _gdk_win32_format_uses_hdata (UINT w32format);
|
||||
|
||||
gchar * _gdk_win32_get_clipboard_format_name (UINT fmt,
|
||||
gboolean *is_predefined);
|
||||
void _gdk_win32_add_w32format_to_pairs (UINT format,
|
||||
GArray *array,
|
||||
GList **list);
|
||||
gint _gdk_win32_add_contentformat_to_pairs (GdkAtom target,
|
||||
GArray *array);
|
||||
gchar * _gdk_win32_get_clipboard_format_name (UINT w32format,
|
||||
gboolean *is_predefined);
|
||||
void _gdk_win32_add_w32format_to_pairs (UINT w32format,
|
||||
GArray *pairs,
|
||||
GdkContentFormatsBuilder *builder);
|
||||
gint _gdk_win32_add_contentformat_to_pairs (GdkAtom target,
|
||||
GArray *array);
|
||||
|
||||
void _gdk_win32_clipboard_default_output_done (GObject *clipboard,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data);
|
||||
gboolean _gdk_win32_transmute_contentformat (const gchar *from_contentformat,
|
||||
UINT to_w32format,
|
||||
const guchar *data,
|
||||
gint length,
|
||||
guchar **set_data,
|
||||
gint *set_data_length);
|
||||
void _gdk_win32_clipboard_default_output_done (GObject *clipboard,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data);
|
||||
gboolean _gdk_win32_transmute_contentformat (const gchar *from_contentformat,
|
||||
UINT to_w32format,
|
||||
const guchar *data,
|
||||
gint length,
|
||||
guchar **set_data,
|
||||
gint *set_data_length);
|
||||
|
||||
gboolean _gdk_win32_transmute_windows_data (UINT from_w32format,
|
||||
const gchar *to_contentformat,
|
||||
HANDLE hdata,
|
||||
guchar **set_data,
|
||||
gsize *set_data_length);
|
||||
gboolean _gdk_win32_transmute_windows_data (UINT from_w32format,
|
||||
const gchar *to_contentformat,
|
||||
HANDLE hdata,
|
||||
guchar **set_data,
|
||||
gsize *set_data_length);
|
||||
|
||||
|
||||
gboolean _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
|
||||
GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
gboolean _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
|
||||
GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
|
||||
void _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
void _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
|
||||
void _gdk_win32_advertise_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
void _gdk_win32_advertise_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
|
||||
|
||||
|
||||
|
||||
+467
-713
File diff suppressed because it is too large
Load Diff
+667
-500
File diff suppressed because it is too large
Load Diff
@@ -871,13 +871,10 @@ _gdk_win32_print_event (const GdkEvent *event)
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
if (event->dnd.context != NULL)
|
||||
g_print ("ctx:%p: %s %s src:%p dest:%p",
|
||||
event->dnd.context,
|
||||
_gdk_win32_drag_protocol_to_string (GDK_WIN32_DRAG_CONTEXT (event->dnd.context)->protocol),
|
||||
event->dnd.context->is_source ? "SOURCE" : "DEST",
|
||||
event->dnd.context->source_surface == NULL ? NULL : GDK_SURFACE_HWND (event->dnd.context->source_surface),
|
||||
event->dnd.context->dest_surface == NULL ? NULL : GDK_SURFACE_HWND (event->dnd.context->dest_surface));
|
||||
if (event->dnd.drop != NULL)
|
||||
g_print ("ctx:%p: %s",
|
||||
event->dnd.drop,
|
||||
_gdk_win32_drag_protocol_to_string (GDK_WIN32_DRAG_CONTEXT (event->dnd.drop)->protocol));
|
||||
break;
|
||||
case GDK_SCROLL:
|
||||
g_print ("(%.4g,%.4g) (%.4g,%.4g) %s ",
|
||||
|
||||
@@ -438,11 +438,9 @@ _gdk_win32_drag_action_to_string (GdkDragAction actions)
|
||||
if (actions & GDK_ACTION_ ## x) \
|
||||
(bufp += sprintf (bufp, "%s" #x, s), s = "|")
|
||||
|
||||
BIT (DEFAULT);
|
||||
BIT (COPY);
|
||||
BIT (MOVE);
|
||||
BIT (LINK);
|
||||
BIT (PRIVATE);
|
||||
BIT (ASK);
|
||||
#undef BIT
|
||||
|
||||
|
||||
@@ -202,8 +202,6 @@ void _gdk_win32_adjust_client_rect (GdkSurface *window,
|
||||
|
||||
void _gdk_selection_property_delete (GdkSurface *);
|
||||
|
||||
void _gdk_dropfiles_store (gchar *data);
|
||||
|
||||
void _gdk_push_modal_window (GdkSurface *window);
|
||||
void _gdk_remove_modal_window (GdkSurface *window);
|
||||
GdkSurface *_gdk_modal_current (void);
|
||||
@@ -424,6 +422,8 @@ void _gdk_win32_display_create_surface_impl (GdkDisplay *display,
|
||||
|
||||
/* stray GdkSurfaceImplWin32 members */
|
||||
void _gdk_win32_surface_register_dnd (GdkSurface *window);
|
||||
void _gdk_win32_surface_unregister_dnd (GdkSurface *window);
|
||||
|
||||
GdkDragContext *_gdk_win32_surface_drag_begin (GdkSurface *window,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,230 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* gdkselection-win32.h: Private Win32 specific selection object
|
||||
*
|
||||
* Copyright © 2017 LRN
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_SELECTION_WIN32_H__
|
||||
#define __GDK_SELECTION_WIN32_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define _gdk_win32_selection_get() (_win32_selection)
|
||||
#define _gdk_atom_array_index(a, i) (g_array_index (a, GdkAtom, i))
|
||||
#define _gdk_win32_selection_atom(i) (_gdk_atom_array_index (_gdk_win32_selection_get ()->known_atoms, i))
|
||||
#define _gdk_cf_array_index(a, i) (g_array_index (a, UINT, i))
|
||||
#define _gdk_win32_selection_cf(i) (_gdk_cf_array_index (_gdk_win32_selection_get ()->known_clipboard_formats, i))
|
||||
|
||||
/* Maps targets to formats or vice versa, depending on the
|
||||
* semantics of the array that holds these.
|
||||
* Also remembers whether the data needs to be transmuted.
|
||||
*/
|
||||
typedef struct {
|
||||
gint format;
|
||||
GdkAtom target;
|
||||
gboolean transmute;
|
||||
} GdkSelTargetFormat;
|
||||
|
||||
/* We emulate the GDK_SELECTION window properties of windows (as used
|
||||
* in the X11 backend) by using a hash table from window handles to
|
||||
* GdkSelProp structs.
|
||||
*/
|
||||
typedef struct {
|
||||
guchar *data;
|
||||
gsize length;
|
||||
gint bitness;
|
||||
GdkAtom target;
|
||||
} GdkSelProp;
|
||||
|
||||
/* OLE-based DND state */
|
||||
typedef enum {
|
||||
GDK_WIN32_DND_NONE,
|
||||
GDK_WIN32_DND_PENDING,
|
||||
GDK_WIN32_DND_DROPPED,
|
||||
GDK_WIN32_DND_FAILED,
|
||||
GDK_WIN32_DND_DRAGGING,
|
||||
} GdkWin32DndState;
|
||||
|
||||
enum _GdkWin32AtomIndex
|
||||
{
|
||||
/* GdkAtoms: properties, targets and types */
|
||||
GDK_WIN32_ATOM_INDEX_GDK_SELECTION = 0,
|
||||
GDK_WIN32_ATOM_INDEX_CLIPBOARD_MANAGER,
|
||||
GDK_WIN32_ATOM_INDEX_WM_TRANSIENT_FOR,
|
||||
GDK_WIN32_ATOM_INDEX_TARGETS,
|
||||
GDK_WIN32_ATOM_INDEX_DELETE,
|
||||
GDK_WIN32_ATOM_INDEX_SAVE_TARGETS,
|
||||
GDK_WIN32_ATOM_INDEX_UTF8_STRING,
|
||||
GDK_WIN32_ATOM_INDEX_TEXT,
|
||||
GDK_WIN32_ATOM_INDEX_COMPOUND_TEXT,
|
||||
GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST,
|
||||
GDK_WIN32_ATOM_INDEX_TEXT_HTML,
|
||||
GDK_WIN32_ATOM_INDEX_IMAGE_PNG,
|
||||
GDK_WIN32_ATOM_INDEX_IMAGE_JPEG,
|
||||
GDK_WIN32_ATOM_INDEX_IMAGE_BMP,
|
||||
GDK_WIN32_ATOM_INDEX_IMAGE_GIF,
|
||||
/* DND selections */
|
||||
GDK_WIN32_ATOM_INDEX_LOCAL_DND_SELECTION,
|
||||
GDK_WIN32_ATOM_INDEX_DROPFILES_DND,
|
||||
GDK_WIN32_ATOM_INDEX_OLE2_DND,
|
||||
/* Clipboard formats */
|
||||
GDK_WIN32_ATOM_INDEX_PNG,
|
||||
GDK_WIN32_ATOM_INDEX_JFIF,
|
||||
GDK_WIN32_ATOM_INDEX_GIF,
|
||||
GDK_WIN32_ATOM_INDEX_CF_DIB,
|
||||
GDK_WIN32_ATOM_INDEX_CFSTR_SHELLIDLIST,
|
||||
GDK_WIN32_ATOM_INDEX_CF_TEXT,
|
||||
GDK_WIN32_ATOM_INDEX_CF_UNICODETEXT,
|
||||
GDK_WIN32_ATOM_INDEX_LAST
|
||||
};
|
||||
|
||||
typedef enum _GdkWin32AtomIndex GdkWin32AtomIndex;
|
||||
|
||||
enum _GdkWin32CFIndex
|
||||
{
|
||||
GDK_WIN32_CF_INDEX_PNG = 0,
|
||||
GDK_WIN32_CF_INDEX_JFIF,
|
||||
GDK_WIN32_CF_INDEX_GIF,
|
||||
GDK_WIN32_CF_INDEX_UNIFORMRESOURCELOCATORW,
|
||||
GDK_WIN32_CF_INDEX_CFSTR_SHELLIDLIST,
|
||||
GDK_WIN32_CF_INDEX_HTML_FORMAT,
|
||||
GDK_WIN32_CF_INDEX_TEXT_HTML,
|
||||
GDK_WIN32_CF_INDEX_IMAGE_PNG,
|
||||
GDK_WIN32_CF_INDEX_IMAGE_JPEG,
|
||||
GDK_WIN32_CF_INDEX_IMAGE_BMP,
|
||||
GDK_WIN32_CF_INDEX_IMAGE_GIF,
|
||||
GDK_WIN32_CF_INDEX_TEXT_URI_LIST,
|
||||
GDK_WIN32_CF_INDEX_UTF8_STRING,
|
||||
GDK_WIN32_CF_INDEX_LAST
|
||||
};
|
||||
|
||||
typedef enum _GdkWin32CFIndex GdkWin32CFIndex;
|
||||
|
||||
#define GDK_TYPE_WIN32_SELECTION (gdk_win32_selection_get_type ())
|
||||
#define GDK_WIN32_SELECTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_WIN32_SELECTION, GdkWin32Selection))
|
||||
#define GDK_WIN32_SELECTION_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_WIN32_SELECTION, GdkWin32SelectionClass))
|
||||
#define GDK_IS_WIN32_SELECTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_WIN32_SELECTION))
|
||||
#define GDK_IS_WIN32_SELECTION_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_WIN32_SELECTION))
|
||||
#define GDK_WIN32_SELECTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_WIN32_SELECTION, GdkWin32SelectionClass))
|
||||
|
||||
typedef struct _GdkWin32Selection GdkWin32Selection;
|
||||
typedef struct _GdkWin32SelectionClass GdkWin32SelectionClass;
|
||||
|
||||
/* This object is just a sink to hold all the selection- and dnd-related data
|
||||
* that otherwise would be in global variables.
|
||||
*/
|
||||
struct _GdkWin32Selection
|
||||
{
|
||||
GObject *parent_instance;
|
||||
GHashTable *sel_prop_table;
|
||||
GdkSelProp *dropfiles_prop;
|
||||
/* We store the owner of each selection in this table. Obviously, this only
|
||||
* is valid intra-app, and in fact it is necessary for the intra-app DND to work.
|
||||
*/
|
||||
GHashTable *sel_owner_table;
|
||||
|
||||
/* GdkAtoms for well-known image formats */
|
||||
GdkAtom *known_pixbuf_formats;
|
||||
int n_known_pixbuf_formats;
|
||||
|
||||
/* GArray of GdkAtoms for various known Selection and DnD strings.
|
||||
* Size is guaranteed to be at least GDK_WIN32_ATOM_INDEX_LAST
|
||||
*/
|
||||
GArray *known_atoms;
|
||||
|
||||
/* GArray of UINTs for various known clipboard formats.
|
||||
* Size is guaranteed to be at least GDK_WIN32_CF_INDEX_LAST.
|
||||
*/
|
||||
GArray *known_clipboard_formats;
|
||||
|
||||
GdkWin32DndState dnd_target_state;
|
||||
GdkWin32DndState dnd_source_state;
|
||||
|
||||
/* Holds a reference to the data object for the target drop site.
|
||||
*/
|
||||
IDataObject *dnd_data_object_target;
|
||||
|
||||
/* Carries DnD target context from idroptarget_*() to convert_selection() */
|
||||
GdkDragContext *target_drag_context;
|
||||
|
||||
/* Carries W32 format ID from idataobject_getdata() to property_change() */
|
||||
UINT property_change_format;
|
||||
/* Carries the W32-wrapped data between idataobject_getdata() and property_change() */
|
||||
LPSTGMEDIUM property_change_data;
|
||||
/* Carries the transmute field of the GdkSelTargetFormat from from idataobject_getdata() to property_change() */
|
||||
gboolean property_change_transmute;
|
||||
/* Carries the target atom from GDK_SELECTION_REQUEST issuer to property_change() */
|
||||
GdkAtom property_change_target_atom;
|
||||
|
||||
/* TRUE when we are emptying the clipboard ourselves */
|
||||
gboolean ignore_destroy_clipboard;
|
||||
|
||||
/* Array of GdkSelTargetFormats describing the targets supported by the clipboard selection */
|
||||
GArray *clipboard_selection_targets;
|
||||
|
||||
/* Same for the DnD selection (applies for both LOCAL and OLE2 DnD) */
|
||||
GArray *dnd_selection_targets;
|
||||
|
||||
/* If TRUE, then we queued a GDK_SELECTION_REQUEST with TARGETS
|
||||
* target. This field is checked to prevent queueing
|
||||
* multiple selection requests.
|
||||
*/
|
||||
gboolean targets_request_pending;
|
||||
|
||||
/* The handle that was given to OpenClipboard().
|
||||
* NULL is a valid handle,
|
||||
* INVALID_HANDLE_VALUE means that the clipboard is closed.
|
||||
*/
|
||||
HWND clipboard_opened_for;
|
||||
|
||||
/* A target-keyed hash table of GArrays of GdkSelTargetFormats describing compatibility formats for a target */
|
||||
GHashTable *compatibility_formats;
|
||||
/* A format-keyed hash table of GArrays of GdkAtoms describing compatibility targets for a format */
|
||||
GHashTable *compatibility_targets;
|
||||
|
||||
/* Last observer owner of the clipboard, as reported by the OS.
|
||||
* This is compared to GetClipboardOwner() return value to see
|
||||
* whether the owner changed.
|
||||
*/
|
||||
HWND stored_hwnd_owner;
|
||||
};
|
||||
|
||||
struct _GdkWin32SelectionClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType gdk_win32_selection_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void _gdk_win32_clear_clipboard_queue ();
|
||||
gchar * _gdk_win32_get_clipboard_format_name (UINT fmt,
|
||||
gboolean *is_predefined);
|
||||
void _gdk_win32_add_format_to_targets (UINT format,
|
||||
GArray *array,
|
||||
GList **list);
|
||||
gint _gdk_win32_add_target_to_selformats (GdkAtom target,
|
||||
GArray *array);
|
||||
void _gdk_win32_selection_property_change (GdkWin32Selection *win32_sel,
|
||||
GdkSurface *window,
|
||||
GdkAtom property,
|
||||
GdkAtom type,
|
||||
gint format,
|
||||
GdkPropMode mode,
|
||||
const guchar *data,
|
||||
gint nelements);
|
||||
|
||||
#endif /* __GDK_SELECTION_WIN32_H__ */
|
||||
@@ -254,6 +254,9 @@ gdk_surface_impl_win32_finalize (GObject *object)
|
||||
surface_impl->cache_surface = NULL;
|
||||
}
|
||||
|
||||
_gdk_win32_surface_unregister_dnd (wrapper);
|
||||
g_clear_object (&surface_impl->drop);
|
||||
|
||||
g_assert (surface_impl->transient_owner == NULL);
|
||||
g_assert (surface_impl->transient_children == NULL);
|
||||
|
||||
|
||||
@@ -216,6 +216,9 @@ struct _GdkW32DragMoveResizeContext
|
||||
|
||||
typedef struct _GdkW32DragMoveResizeContext GdkW32DragMoveResizeContext;
|
||||
|
||||
/* defined in gdkdrop-win32.c */
|
||||
typedef struct _drop_target_context drop_target_context;
|
||||
|
||||
struct _GdkSurfaceImplWin32
|
||||
{
|
||||
GdkSurfaceImpl parent_instance;
|
||||
@@ -243,6 +246,15 @@ struct _GdkSurfaceImplWin32
|
||||
|
||||
GdkEventMask native_event_mask;
|
||||
|
||||
/* Non-NULL for any window that is registered as a drop target.
|
||||
* For OLE2 protocol only.
|
||||
*/
|
||||
drop_target_context *drop_target;
|
||||
/* Temporarily holds the GdkDrop currently associated with this window.
|
||||
* For LOCAL protocol only.
|
||||
*/
|
||||
GdkDrop *drop;
|
||||
|
||||
GdkSurfaceTypeHint type_hint;
|
||||
|
||||
GdkSurface *transient_owner;
|
||||
|
||||
@@ -38,13 +38,12 @@ struct _GdkWin32DragContextUtilityData
|
||||
|
||||
struct _GdkWin32DragContext
|
||||
{
|
||||
GdkDragContext context;
|
||||
GdkDragContext drag;
|
||||
GdkDragProtocol protocol;
|
||||
GdkSurface *ipc_window;
|
||||
GdkSurface *drag_surface;
|
||||
GdkCursor *cursor;
|
||||
GdkSeat *grab_seat;
|
||||
GdkDragAction actions;
|
||||
GdkDragAction current_action;
|
||||
|
||||
GdkWin32DragContextUtilityData util_data;
|
||||
@@ -57,6 +56,7 @@ struct _GdkWin32DragContext
|
||||
|
||||
guint drag_status : 4; /* Current status of drag */
|
||||
guint drop_failed : 1; /* Whether the drop was unsuccessful */
|
||||
guint handle_events : 1; /* Whether handle_event() should do anything */
|
||||
};
|
||||
|
||||
struct _GdkWin32DragContextClass
|
||||
@@ -64,51 +64,54 @@ struct _GdkWin32DragContextClass
|
||||
GdkDragContextClass parent_class;
|
||||
};
|
||||
|
||||
struct _GdkWin32DropContext
|
||||
{
|
||||
GdkDragContext context;
|
||||
GdkDragProtocol protocol;
|
||||
GdkDragAction actions;
|
||||
GdkDragAction current_action;
|
||||
|
||||
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 */
|
||||
gpointer _gdk_win32_dnd_thread_main (gpointer data);
|
||||
|
||||
/* Just like context->formats, but an array, and with format IDs
|
||||
* stored inside.
|
||||
*/
|
||||
GArray *droptarget_w32format_contentformat_map;
|
||||
GdkDragContext *_gdk_win32_find_drag_for_dest_surface (GdkSurface *dest_surface);
|
||||
|
||||
GdkWin32DragContext *local_source_context;
|
||||
void _gdk_win32_drag_send_local_status_event (GdkDragContext *drag,
|
||||
GdkDragAction action);
|
||||
void _gdk_win32_local_send_enter (GdkDragContext *drag,
|
||||
GdkSurface *dest_surface,
|
||||
guint32 time);
|
||||
|
||||
guint drag_status : 4; /* Current status of drag */
|
||||
guint drop_failed : 1; /* Whether the drop was unsuccessful */
|
||||
};
|
||||
GdkDragContext *_gdk_win32_drag_context_find (GdkSurface *source,
|
||||
GdkSurface *dest);
|
||||
GdkDrop *_gdk_win32_get_drop_for_dest_surface (GdkSurface *dest);
|
||||
|
||||
struct _GdkWin32DropContextClass
|
||||
{
|
||||
GdkDragContextClass parent_class;
|
||||
};
|
||||
void _gdk_win32_drag_do_leave (GdkDragContext *context,
|
||||
guint32 time);
|
||||
|
||||
gpointer _gdk_win32_dnd_thread_main (gpointer data);
|
||||
gboolean _gdk_win32_local_drop_target_will_emit_motion (GdkDrop *drop,
|
||||
gint x_root,
|
||||
gint y_root,
|
||||
DWORD grfKeyState);
|
||||
|
||||
GdkDragContext *_gdk_win32_find_source_context_for_dest_surface (GdkSurface *dest_surface);
|
||||
void _gdk_win32_local_drop_target_dragenter (GdkDragContext *drag,
|
||||
GdkSurface *dest_surface,
|
||||
gint x_root,
|
||||
gint y_root,
|
||||
DWORD grfKeyState,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions);
|
||||
void _gdk_win32_local_drop_target_dragover (GdkDrop *drop,
|
||||
GdkDragContext *drag,
|
||||
gint x_root,
|
||||
gint y_root,
|
||||
DWORD grfKeyState,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions);
|
||||
void _gdk_win32_local_drop_target_dragleave (GdkDrop *drop,
|
||||
guint32 time_);
|
||||
void _gdk_win32_local_drop_target_drop (GdkDrop *drop,
|
||||
GdkDragContext *drag,
|
||||
guint32 time_,
|
||||
GdkDragAction *actions);
|
||||
|
||||
void _gdk_win32_drag_context_send_local_status_event (GdkDragContext *src_context,
|
||||
GdkDragAction action);
|
||||
void _gdk_win32_local_send_enter (GdkDragContext *context,
|
||||
guint32 time);
|
||||
|
||||
GdkDragContext *_gdk_win32_drag_context_find (GdkSurface *source,
|
||||
GdkSurface *dest);
|
||||
GdkDragContext *_gdk_win32_drop_context_find (GdkSurface *source,
|
||||
GdkSurface *dest);
|
||||
|
||||
|
||||
void _gdk_win32_drag_do_leave (GdkDragContext *context,
|
||||
guint32 time);
|
||||
void _gdk_win32_local_drag_give_feedback (GdkDragContext *drag,
|
||||
GdkDragAction actions);
|
||||
void _gdk_win32_local_drag_context_drop_response (GdkDragContext *drag,
|
||||
GdkDragAction action);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -43,23 +43,6 @@ typedef struct _GdkWin32DragContextClass GdkWin32DragContextClass;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_win32_drag_context_get_type (void);
|
||||
|
||||
#define GDK_TYPE_WIN32_DROP_CONTEXT (gdk_win32_drop_context_get_type ())
|
||||
#define GDK_WIN32_DROP_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WIN32_DROP_CONTEXT, GdkWin32DropContext))
|
||||
#define GDK_WIN32_DROP_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_DROP_CONTEXT, GdkWin32DropContextClass))
|
||||
#define GDK_IS_WIN32_DROP_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WIN32_DROP_CONTEXT))
|
||||
#define GDK_IS_WIN32_DROP_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_DROP_CONTEXT))
|
||||
#define GDK_WIN32_DROP_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_DROP_CONTEXT, GdkWin32DropContextClass))
|
||||
|
||||
#ifdef GDK_COMPILATION
|
||||
typedef struct _GdkWin32DropContext GdkWin32DropContext;
|
||||
#else
|
||||
typedef GdkDragContext GdkWin32DropContext;
|
||||
#endif
|
||||
typedef struct _GdkWin32DropContextClass GdkWin32DropContextClass;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_win32_drop_context_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WIN32_DRAG_CONTEXT_H__ */
|
||||
|
||||
+161
-235
@@ -104,8 +104,6 @@ struct _GdkX11DragContext
|
||||
guint16 last_x; /* Coordinates from last event */
|
||||
guint16 last_y;
|
||||
gulong timestamp; /* Timestamp we claimed the DND selection with */
|
||||
GdkDragAction old_action; /* The last action we sent to the source */
|
||||
GdkDragAction old_actions; /* The last actions we sent to the source */
|
||||
GdkDragAction xdnd_actions; /* What is currently set in XdndActionList */
|
||||
guint version; /* Xdnd protocol version */
|
||||
|
||||
@@ -125,7 +123,6 @@ struct _GdkX11DragContext
|
||||
Window dest_xid; /* The last window we looked up */
|
||||
Window drop_xid; /* The (non-proxied) window that is receiving drops */
|
||||
guint xdnd_targets_set : 1; /* Whether we've already set XdndTypeList */
|
||||
guint xdnd_actions_set : 1; /* Whether we've already set XdndActionList */
|
||||
guint xdnd_have_actions : 1; /* Whether an XdndActionList was provided */
|
||||
guint drag_status : 4; /* current status of drag */
|
||||
guint drop_failed : 1; /* Whether the drop was unsuccessful */
|
||||
@@ -170,24 +167,18 @@ static GrabKey grab_keys[] = {
|
||||
static GdkSurfaceCache *gdk_surface_cache_ref (GdkSurfaceCache *cache);
|
||||
static void gdk_surface_cache_unref (GdkSurfaceCache *cache);
|
||||
|
||||
static GdkFilterReturn xdnd_enter_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data);
|
||||
static GdkFilterReturn xdnd_leave_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data);
|
||||
static GdkFilterReturn xdnd_position_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data);
|
||||
static GdkFilterReturn xdnd_status_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data);
|
||||
static GdkFilterReturn xdnd_finished_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data);
|
||||
static GdkFilterReturn xdnd_drop_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data);
|
||||
static gboolean xdnd_enter_filter (GdkSurface *surface,
|
||||
const XEvent *xevent);
|
||||
static gboolean xdnd_leave_filter (GdkSurface *surface,
|
||||
const XEvent *xevent);
|
||||
static gboolean xdnd_position_filter (GdkSurface *surface,
|
||||
const XEvent *xevent);
|
||||
static gboolean xdnd_status_filter (GdkSurface *surface,
|
||||
const XEvent *xevent);
|
||||
static gboolean xdnd_finished_filter (GdkSurface *surface,
|
||||
const XEvent *xevent);
|
||||
static gboolean xdnd_drop_filter (GdkSurface *surface,
|
||||
const XEvent *xevent);
|
||||
|
||||
static void xdnd_manage_source_filter (GdkDragContext *context,
|
||||
GdkSurface *surface,
|
||||
@@ -203,7 +194,7 @@ static GSList *window_caches;
|
||||
|
||||
static const struct {
|
||||
const char *atom_name;
|
||||
GdkFilterFunc func;
|
||||
gboolean (* func) (GdkSurface *surface, const XEvent *event);
|
||||
} xdnd_filters[] = {
|
||||
{ "XdndEnter", xdnd_enter_filter },
|
||||
{ "XdndLeave", xdnd_leave_filter },
|
||||
@@ -236,16 +227,14 @@ static gboolean gdk_x11_drag_context_drag_motion (GdkDragContext *context,
|
||||
GdkDragAction suggested_action,
|
||||
GdkDragAction possible_actions,
|
||||
guint32 time);
|
||||
static void gdk_x11_drag_context_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time_);
|
||||
static void gdk_x11_drag_context_status (GdkDrop *drop,
|
||||
GdkDragAction actions);
|
||||
static void gdk_x11_drag_context_drag_abort (GdkDragContext *context,
|
||||
guint32 time_);
|
||||
static void gdk_x11_drag_context_drag_drop (GdkDragContext *context,
|
||||
guint32 time_);
|
||||
static void gdk_x11_drag_context_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time_);
|
||||
static void gdk_x11_drag_context_finish (GdkDrop *drop,
|
||||
GdkDragAction action);
|
||||
static GdkSurface * gdk_x11_drag_context_get_drag_surface (GdkDragContext *context);
|
||||
static void gdk_x11_drag_context_set_hotspot (GdkDragContext *context,
|
||||
gint hot_x,
|
||||
@@ -279,13 +268,13 @@ gdk_x11_drag_context_read_got_stream (GObject *source,
|
||||
next = targets->next;
|
||||
if (next)
|
||||
{
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (g_task_get_source_object (task));
|
||||
GdkDrop *drop = GDK_DROP (g_task_get_source_object (task));
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), DND, g_printerr ("reading %s failed, trying %s next\n",
|
||||
GDK_DISPLAY_NOTE (gdk_drop_get_display (drop), DND, g_printerr ("reading %s failed, trying %s next\n",
|
||||
(char *) targets->data, (char *) next->data));
|
||||
targets->next = NULL;
|
||||
g_task_set_task_data (task, next, (GDestroyNotify) g_slist_free);
|
||||
gdk_x11_selection_input_stream_new_async (gdk_drag_context_get_display (context),
|
||||
gdk_x11_selection_input_stream_new_async (gdk_drop_get_display (drop),
|
||||
"XdndSelection",
|
||||
next->data,
|
||||
CurrentTime,
|
||||
@@ -330,7 +319,7 @@ gdk_x11_drag_context_read_got_stream (GObject *source,
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_drag_context_read_async (GdkDragContext *context,
|
||||
gdk_x11_drag_context_read_async (GdkDrop *drop,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
@@ -340,7 +329,7 @@ gdk_x11_drag_context_read_async (GdkDragContext *context,
|
||||
GSList *targets;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
task = g_task_new (drop, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_x11_drag_context_read_async);
|
||||
|
||||
@@ -353,9 +342,9 @@ gdk_x11_drag_context_read_async (GdkDragContext *context,
|
||||
return;
|
||||
}
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), DND, g_printerr ("new read for %s (%u other options)\n",
|
||||
GDK_DISPLAY_NOTE (gdk_drop_get_display (drop), DND, g_printerr ("new read for %s (%u other options)\n",
|
||||
(char *) targets->data, g_slist_length (targets->next)));
|
||||
gdk_x11_selection_input_stream_new_async (gdk_drag_context_get_display (context),
|
||||
gdk_x11_selection_input_stream_new_async (gdk_drop_get_display (drop),
|
||||
"XdndSelection",
|
||||
targets->data,
|
||||
CurrentTime,
|
||||
@@ -366,14 +355,14 @@ gdk_x11_drag_context_read_async (GdkDragContext *context,
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_x11_drag_context_read_finish (GdkDragContext *context,
|
||||
gdk_x11_drag_context_read_finish (GdkDrop *drop,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (context)), NULL);
|
||||
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_x11_drag_context_read_async, NULL);
|
||||
|
||||
@@ -392,16 +381,18 @@ static void
|
||||
gdk_x11_drag_context_class_init (GdkX11DragContextClass *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_x11_drag_context_finalize;
|
||||
|
||||
context_class->drag_status = gdk_x11_drag_context_drag_status;
|
||||
drop_class->status = gdk_x11_drag_context_status;
|
||||
drop_class->finish = gdk_x11_drag_context_finish;
|
||||
drop_class->read_async = gdk_x11_drag_context_read_async;
|
||||
drop_class->read_finish = gdk_x11_drag_context_read_finish;
|
||||
|
||||
context_class->drag_abort = gdk_x11_drag_context_drag_abort;
|
||||
context_class->drag_drop = gdk_x11_drag_context_drag_drop;
|
||||
context_class->drop_finish = gdk_x11_drag_context_drop_finish;
|
||||
context_class->read_async = gdk_x11_drag_context_read_async;
|
||||
context_class->read_finish = gdk_x11_drag_context_read_finish;
|
||||
context_class->get_drag_surface = gdk_x11_drag_context_get_drag_surface;
|
||||
context_class->set_hotspot = gdk_x11_drag_context_set_hotspot;
|
||||
context_class->drop_done = gdk_x11_drag_context_drop_done;
|
||||
@@ -445,7 +436,6 @@ gdk_x11_drag_context_finalize (GObject *object)
|
||||
|
||||
static GdkDragContext *
|
||||
gdk_drag_context_find (GdkDisplay *display,
|
||||
gboolean is_source,
|
||||
Window source_xid,
|
||||
Window dest_xid)
|
||||
{
|
||||
@@ -469,7 +459,7 @@ gdk_drag_context_find (GdkDisplay *display,
|
||||
: GDK_SURFACE_XID (context->dest_surface))
|
||||
: None;
|
||||
|
||||
if ((!context->is_source == !is_source) &&
|
||||
if ((context->is_source) &&
|
||||
((source_xid == None) || (context->source_surface &&
|
||||
(GDK_SURFACE_XID (context->source_surface) == source_xid))) &&
|
||||
((dest_xid == None) || (context_dest_xid == dest_xid)))
|
||||
@@ -1050,10 +1040,9 @@ xdnd_action_to_atom (GdkDisplay *display,
|
||||
|
||||
/* Source side */
|
||||
|
||||
static GdkFilterReturn
|
||||
xdnd_status_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data)
|
||||
static gboolean
|
||||
xdnd_status_filter (GdkSurface *surface,
|
||||
const XEvent *xevent)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
guint32 dest_surface = xevent->xclient.data.l[0];
|
||||
@@ -1061,12 +1050,8 @@ xdnd_status_filter (const XEvent *xevent,
|
||||
Atom action = xevent->xclient.data.l[4];
|
||||
GdkDragContext *context;
|
||||
|
||||
if (!event->any.surface ||
|
||||
gdk_surface_get_surface_type (event->any.surface) == GDK_SURFACE_FOREIGN)
|
||||
return GDK_FILTER_CONTINUE; /* Not for us */
|
||||
|
||||
display = gdk_surface_get_display (event->any.surface);
|
||||
context = gdk_drag_context_find (display, TRUE, xevent->xclient.window, dest_surface);
|
||||
display = gdk_surface_get_display (surface);
|
||||
context = gdk_drag_context_find (display, xevent->xclient.window, dest_surface);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND,
|
||||
g_message ("XdndStatus: dest_surface: %#x action: %ld",
|
||||
@@ -1094,25 +1079,20 @@ xdnd_status_filter (const XEvent *xevent,
|
||||
}
|
||||
}
|
||||
|
||||
return GDK_FILTER_REMOVE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkFilterReturn
|
||||
xdnd_finished_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data)
|
||||
static gboolean
|
||||
xdnd_finished_filter (GdkSurface *surface,
|
||||
const XEvent *xevent)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
guint32 dest_surface = xevent->xclient.data.l[0];
|
||||
GdkDragContext *context;
|
||||
GdkX11DragContext *context_x11;
|
||||
|
||||
if (!event->any.surface ||
|
||||
gdk_surface_get_surface_type (event->any.surface) == GDK_SURFACE_FOREIGN)
|
||||
return GDK_FILTER_CONTINUE; /* Not for us */
|
||||
|
||||
display = gdk_surface_get_display (event->any.surface);
|
||||
context = gdk_drag_context_find (display, TRUE, xevent->xclient.window, dest_surface);
|
||||
display = gdk_surface_get_display (surface);
|
||||
context = gdk_drag_context_find (display, xevent->xclient.window, dest_surface);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND,
|
||||
g_message ("XdndFinished: dest_surface: %#x", dest_surface));
|
||||
@@ -1131,7 +1111,7 @@ xdnd_finished_filter (const XEvent *xevent,
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
return GDK_FILTER_REMOVE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1169,7 +1149,7 @@ xdnd_set_actions (GdkX11DragContext *context_x11)
|
||||
guint actions;
|
||||
GdkDisplay *display = gdk_drag_context_get_display (context);
|
||||
|
||||
actions = context->actions;
|
||||
actions = gdk_drag_context_get_actions (context);
|
||||
n_atoms = 0;
|
||||
for (i = 0; i < xdnd_n_actions; i++)
|
||||
{
|
||||
@@ -1182,7 +1162,7 @@ xdnd_set_actions (GdkX11DragContext *context_x11)
|
||||
|
||||
atomlist = g_new (Atom, n_atoms);
|
||||
|
||||
actions = context->actions;
|
||||
actions = gdk_drag_context_get_actions (context);
|
||||
n_atoms = 0;
|
||||
for (i = 0; i < xdnd_n_actions; i++)
|
||||
{
|
||||
@@ -1202,8 +1182,7 @@ xdnd_set_actions (GdkX11DragContext *context_x11)
|
||||
|
||||
g_free (atomlist);
|
||||
|
||||
context_x11->xdnd_actions_set = TRUE;
|
||||
context_x11->xdnd_actions = context->actions;
|
||||
context_x11->xdnd_actions = gdk_drag_context_get_actions (context);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1278,15 +1257,7 @@ xdnd_send_xevent (GdkX11DragContext *context_x11,
|
||||
if (gdk_x11_get_xatom_by_name_for_display (display, xdnd_filters[i].atom_name) ==
|
||||
event_send->xclient.message_type)
|
||||
{
|
||||
GdkEvent *temp_event;
|
||||
|
||||
temp_event = gdk_event_new (GDK_NOTHING);
|
||||
temp_event->any.surface = g_object_ref (surface);
|
||||
|
||||
if ((*xdnd_filters[i].func) (event_send, temp_event, NULL) == GDK_FILTER_TRANSLATE)
|
||||
gdk_display_put_event (display, temp_event);
|
||||
|
||||
g_object_unref (temp_event);
|
||||
(*xdnd_filters[i].func) (surface, event_send);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1529,6 +1500,7 @@ xdnd_read_actions (GdkX11DragContext *context_x11)
|
||||
{
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (context_x11);
|
||||
GdkDisplay *display = gdk_drag_context_get_display (context);
|
||||
GdkDragAction actions = GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK;
|
||||
Atom type;
|
||||
int format;
|
||||
gulong nitems, after;
|
||||
@@ -1551,12 +1523,12 @@ xdnd_read_actions (GdkX11DragContext *context_x11)
|
||||
&after, &data) == Success &&
|
||||
type == XA_ATOM)
|
||||
{
|
||||
actions = 0;
|
||||
|
||||
atoms = (Atom *)data;
|
||||
|
||||
context->actions = 0;
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
context->actions |= xdnd_action_from_atom (display, atoms[i]);
|
||||
actions |= xdnd_action_from_atom (display, atoms[i]);
|
||||
|
||||
context_x11->xdnd_have_actions = TRUE;
|
||||
|
||||
@@ -1564,20 +1536,20 @@ xdnd_read_actions (GdkX11DragContext *context_x11)
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, DND))
|
||||
{
|
||||
GString *action_str = g_string_new (NULL);
|
||||
if (context->actions & GDK_ACTION_MOVE)
|
||||
GdkDragAction actions = gdk_drag_context_get_actions (context);
|
||||
if (actions & GDK_ACTION_MOVE)
|
||||
g_string_append(action_str, "MOVE ");
|
||||
if (context->actions & GDK_ACTION_COPY)
|
||||
if (actions & GDK_ACTION_COPY)
|
||||
g_string_append(action_str, "COPY ");
|
||||
if (context->actions & GDK_ACTION_LINK)
|
||||
if (actions & GDK_ACTION_LINK)
|
||||
g_string_append(action_str, "LINK ");
|
||||
if (context->actions & GDK_ACTION_ASK)
|
||||
if (actions & GDK_ACTION_ASK)
|
||||
g_string_append(action_str, "ASK ");
|
||||
|
||||
g_message("Xdnd actions = %s", action_str->str);
|
||||
g_string_free (action_str, TRUE);
|
||||
}
|
||||
#endif /* G_ENABLE_DEBUG */
|
||||
|
||||
}
|
||||
|
||||
if (data)
|
||||
@@ -1591,16 +1563,18 @@ xdnd_read_actions (GdkX11DragContext *context_x11)
|
||||
*/
|
||||
GdkDragContext *source_context;
|
||||
|
||||
source_context = gdk_drag_context_find (display, TRUE,
|
||||
source_context = gdk_drag_context_find (display,
|
||||
GDK_SURFACE_XID (context->source_surface),
|
||||
GDK_SURFACE_XID (context->dest_surface));
|
||||
|
||||
if (source_context)
|
||||
{
|
||||
context->actions = source_context->actions;
|
||||
actions = gdk_drag_context_get_actions (source_context);
|
||||
context_x11->xdnd_have_actions = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gdk_drag_context_set_actions (context, actions, gdk_drag_context_get_suggested_action (context));
|
||||
}
|
||||
|
||||
/* We have to make sure that the XdndActionList we keep internally
|
||||
@@ -1609,29 +1583,23 @@ xdnd_read_actions (GdkX11DragContext *context_x11)
|
||||
* to continually send actions. So we select on PropertyChangeMask
|
||||
* and add this filter.
|
||||
*/
|
||||
GdkFilterReturn
|
||||
xdnd_source_surface_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data)
|
||||
static gboolean
|
||||
xdnd_source_surface_filter (GdkDisplay *display,
|
||||
const XEvent *xevent,
|
||||
gpointer data)
|
||||
{
|
||||
GdkX11DragContext *context_x11;
|
||||
GdkDisplay *display;
|
||||
|
||||
if (!data)
|
||||
return GDK_FILTER_CONTINUE;
|
||||
GdkX11DragContext *context_x11 = data;
|
||||
|
||||
context_x11 = data;
|
||||
display = gdk_drag_context_get_display (GDK_DRAG_CONTEXT (context_x11));
|
||||
|
||||
if ((xevent->xany.type == PropertyNotify) &&
|
||||
(xevent->xany.window == GDK_SURFACE_XID (GDK_DRAG_CONTEXT (context_x11)->source_surface)) &&
|
||||
(xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "XdndActionList")))
|
||||
{
|
||||
xdnd_read_actions (context_x11);
|
||||
|
||||
return GDK_FILTER_REMOVE;
|
||||
}
|
||||
|
||||
return GDK_FILTER_CONTINUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1644,25 +1612,26 @@ xdnd_manage_source_filter (GdkDragContext *context,
|
||||
{
|
||||
GdkDisplay *display = gdk_drag_context_get_display (context);
|
||||
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
|
||||
if (add_filter)
|
||||
{
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
gdk_surface_set_events (surface,
|
||||
gdk_surface_get_events (surface) |
|
||||
GDK_PROPERTY_CHANGE_MASK);
|
||||
g_object_set_data (G_OBJECT (surface), "xdnd-source-context", context);
|
||||
gdk_surface_get_events (surface) |
|
||||
GDK_PROPERTY_CHANGE_MASK);
|
||||
gdk_x11_display_error_trap_pop_ignored (display);
|
||||
|
||||
g_signal_connect (display, "xevent", G_CALLBACK (xdnd_source_surface_filter), context);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set_data (G_OBJECT (surface), "xdnd-source-context", NULL);
|
||||
g_signal_handlers_disconnect_by_func (display,
|
||||
xdnd_source_surface_filter,
|
||||
context);
|
||||
/* Should we remove the GDK_PROPERTY_NOTIFY mask?
|
||||
* but we might want it for other reasons. (Like
|
||||
* INCR selection transactions).
|
||||
*/
|
||||
}
|
||||
|
||||
gdk_x11_display_error_trap_pop_ignored (display);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1717,15 +1686,15 @@ xdnd_precache_atoms (GdkDisplay *display)
|
||||
}
|
||||
}
|
||||
|
||||
static GdkFilterReturn
|
||||
xdnd_enter_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer cb_data)
|
||||
static gboolean
|
||||
xdnd_enter_filter (GdkSurface *surface,
|
||||
const XEvent *xevent)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkX11Display *display_x11;
|
||||
GdkDragContext *context;
|
||||
GdkX11DragContext *context_x11;
|
||||
GdkDragContext *drag;
|
||||
GdkSeat *seat;
|
||||
gint i;
|
||||
Atom type;
|
||||
@@ -1739,15 +1708,11 @@ xdnd_enter_filter (const XEvent *xevent,
|
||||
gboolean get_types;
|
||||
gint version;
|
||||
|
||||
if (!event->any.surface ||
|
||||
gdk_surface_get_surface_type (event->any.surface) == GDK_SURFACE_FOREIGN)
|
||||
return GDK_FILTER_CONTINUE; /* Not for us */
|
||||
|
||||
source_surface = xevent->xclient.data.l[0];
|
||||
get_types = ((xevent->xclient.data.l[1] & 1) != 0);
|
||||
version = (xevent->xclient.data.l[1] & 0xff000000) >> 24;
|
||||
|
||||
display = GDK_SURFACE_DISPLAY (event->any.surface);
|
||||
display = gdk_surface_get_display (surface);
|
||||
display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
xdnd_precache_atoms (display);
|
||||
@@ -1760,7 +1725,7 @@ xdnd_enter_filter (const XEvent *xevent,
|
||||
{
|
||||
/* Old source ignore */
|
||||
GDK_DISPLAY_NOTE (display, DND, g_message ("Ignored old XdndEnter message"));
|
||||
return GDK_FILTER_REMOVE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (display_x11->current_dest_drag != NULL)
|
||||
@@ -1775,7 +1740,7 @@ xdnd_enter_filter (const XEvent *xevent,
|
||||
if (get_types)
|
||||
{
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
XGetWindowProperty (GDK_SURFACE_XDISPLAY (event->any.surface),
|
||||
XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
|
||||
source_surface,
|
||||
gdk_x11_get_xatom_by_name_for_display (display, "XdndTypeList"),
|
||||
0, 65536,
|
||||
@@ -1787,7 +1752,7 @@ xdnd_enter_filter (const XEvent *xevent,
|
||||
if (data)
|
||||
XFree (data);
|
||||
|
||||
return GDK_FILTER_REMOVE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
atoms = (Atom *)data;
|
||||
@@ -1813,9 +1778,13 @@ xdnd_enter_filter (const XEvent *xevent,
|
||||
print_target_list (content_formats);
|
||||
#endif /* G_ENABLE_DEBUG */
|
||||
|
||||
drag = gdk_drag_context_find (display, source_surface, GDK_SURFACE_XID (surface));
|
||||
|
||||
context_x11 = g_object_new (GDK_TYPE_X11_DRAG_CONTEXT,
|
||||
"device", gdk_seat_get_pointer (seat),
|
||||
"drag", drag,
|
||||
"formats", content_formats,
|
||||
"surface", surface,
|
||||
NULL);
|
||||
context = (GdkDragContext *)context_x11;
|
||||
|
||||
@@ -1828,39 +1797,31 @@ xdnd_enter_filter (const XEvent *xevent,
|
||||
if (!context->source_surface)
|
||||
{
|
||||
g_object_unref (context);
|
||||
return GDK_FILTER_REMOVE;
|
||||
return TRUE;
|
||||
}
|
||||
context->dest_surface = event->any.surface;
|
||||
context->dest_surface = surface;
|
||||
g_object_ref (context->dest_surface);
|
||||
xdnd_manage_source_filter (context, context->source_surface, TRUE);
|
||||
xdnd_read_actions (context_x11);
|
||||
|
||||
event->any.type = GDK_DRAG_ENTER;
|
||||
event->dnd.context = context;
|
||||
gdk_event_set_device (event, gdk_drag_context_get_device (context));
|
||||
g_object_ref (context);
|
||||
|
||||
display_x11->current_dest_drag = context;
|
||||
|
||||
gdk_drop_emit_enter_event (GDK_DROP (context), FALSE, GDK_CURRENT_TIME);
|
||||
|
||||
gdk_content_formats_unref (content_formats);
|
||||
|
||||
return GDK_FILTER_TRANSLATE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkFilterReturn
|
||||
xdnd_leave_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data)
|
||||
static gboolean
|
||||
xdnd_leave_filter (GdkSurface *surface,
|
||||
const XEvent *xevent)
|
||||
{
|
||||
guint32 source_surface = xevent->xclient.data.l[0];
|
||||
GdkDisplay *display;
|
||||
GdkX11Display *display_x11;
|
||||
|
||||
if (!event->any.surface ||
|
||||
gdk_surface_get_surface_type (event->any.surface) == GDK_SURFACE_FOREIGN)
|
||||
return GDK_FILTER_CONTINUE; /* Not for us */
|
||||
|
||||
display = GDK_SURFACE_DISPLAY (event->any.surface);
|
||||
display = gdk_surface_get_display (surface);
|
||||
display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND,
|
||||
@@ -1873,23 +1834,17 @@ xdnd_leave_filter (const XEvent *xevent,
|
||||
(GDK_X11_DRAG_CONTEXT (display_x11->current_dest_drag)->protocol == GDK_DRAG_PROTO_XDND) &&
|
||||
(GDK_SURFACE_XID (display_x11->current_dest_drag->source_surface) == source_surface))
|
||||
{
|
||||
event->any.type = GDK_DRAG_LEAVE;
|
||||
/* Pass ownership of context to the event */
|
||||
event->dnd.context = display_x11->current_dest_drag;
|
||||
gdk_event_set_device (event, gdk_drag_context_get_device (event->dnd.context));
|
||||
gdk_drop_emit_leave_event (GDK_DROP (display_x11->current_dest_drag), FALSE, GDK_CURRENT_TIME);
|
||||
|
||||
display_x11->current_dest_drag = NULL;
|
||||
|
||||
return GDK_FILTER_TRANSLATE;
|
||||
g_clear_object (&display_x11->current_dest_drag);
|
||||
}
|
||||
else
|
||||
return GDK_FILTER_REMOVE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkFilterReturn
|
||||
xdnd_position_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data)
|
||||
static gboolean
|
||||
xdnd_position_filter (GdkSurface *surface,
|
||||
const XEvent *xevent)
|
||||
{
|
||||
GdkSurfaceImplX11 *impl;
|
||||
guint32 source_surface = xevent->xclient.data.l[0];
|
||||
@@ -1901,12 +1856,9 @@ xdnd_position_filter (const XEvent *xevent,
|
||||
GdkX11Display *display_x11;
|
||||
GdkDragContext *context;
|
||||
GdkX11DragContext *context_x11;
|
||||
GdkDragAction suggested_action;
|
||||
|
||||
if (!event->any.surface ||
|
||||
gdk_surface_get_surface_type (event->any.surface) == GDK_SURFACE_FOREIGN)
|
||||
return GDK_FILTER_CONTINUE; /* Not for us */
|
||||
|
||||
display = GDK_SURFACE_DISPLAY (event->any.surface);
|
||||
display = gdk_surface_get_display (surface);
|
||||
display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND,
|
||||
@@ -1921,38 +1873,32 @@ xdnd_position_filter (const XEvent *xevent,
|
||||
(GDK_X11_DRAG_CONTEXT (context)->protocol == GDK_DRAG_PROTO_XDND) &&
|
||||
(GDK_SURFACE_XID (context->source_surface) == source_surface))
|
||||
{
|
||||
impl = GDK_SURFACE_IMPL_X11 (event->any.surface->impl);
|
||||
impl = GDK_SURFACE_IMPL_X11 (gdk_drop_get_surface (GDK_DROP (context))->impl);
|
||||
|
||||
context_x11 = GDK_X11_DRAG_CONTEXT (context);
|
||||
|
||||
event->any.type = GDK_DRAG_MOTION;
|
||||
event->dnd.context = context;
|
||||
gdk_event_set_device (event, gdk_drag_context_get_device (context));
|
||||
g_object_ref (context);
|
||||
|
||||
event->dnd.time = time;
|
||||
|
||||
context->suggested_action = xdnd_action_from_atom (display, action);
|
||||
|
||||
if (!context_x11->xdnd_have_actions)
|
||||
context->actions = context->suggested_action;
|
||||
|
||||
event->dnd.x_root = x_root / impl->surface_scale;
|
||||
event->dnd.y_root = y_root / impl->surface_scale;
|
||||
suggested_action = xdnd_action_from_atom (display, action);
|
||||
if (context_x11->xdnd_have_actions)
|
||||
gdk_drag_context_set_actions (context,
|
||||
gdk_drag_context_get_actions (context),
|
||||
suggested_action);
|
||||
else
|
||||
gdk_drag_context_set_actions (context,
|
||||
suggested_action,
|
||||
suggested_action);
|
||||
|
||||
context_x11->last_x = x_root / impl->surface_scale;
|
||||
context_x11->last_y = y_root / impl->surface_scale;
|
||||
|
||||
return GDK_FILTER_TRANSLATE;
|
||||
gdk_drop_emit_motion_event (GDK_DROP (context), FALSE, context_x11->last_x, context_x11->last_y, time);
|
||||
}
|
||||
|
||||
return GDK_FILTER_REMOVE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkFilterReturn
|
||||
xdnd_drop_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data)
|
||||
static gboolean
|
||||
xdnd_drop_filter (GdkSurface *surface,
|
||||
const XEvent *xevent)
|
||||
{
|
||||
guint32 source_surface = xevent->xclient.data.l[0];
|
||||
guint32 time = xevent->xclient.data.l[2];
|
||||
@@ -1961,11 +1907,7 @@ xdnd_drop_filter (const XEvent *xevent,
|
||||
GdkDragContext *context;
|
||||
GdkX11DragContext *context_x11;
|
||||
|
||||
if (!event->any.surface ||
|
||||
gdk_surface_get_surface_type (event->any.surface) == GDK_SURFACE_FOREIGN)
|
||||
return GDK_FILTER_CONTINUE; /* Not for us */
|
||||
|
||||
display = GDK_SURFACE_DISPLAY (event->any.surface);
|
||||
display = gdk_surface_get_display (surface);
|
||||
display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND,
|
||||
@@ -1981,22 +1923,13 @@ xdnd_drop_filter (const XEvent *xevent,
|
||||
(GDK_SURFACE_XID (context->source_surface) == source_surface))
|
||||
{
|
||||
context_x11 = GDK_X11_DRAG_CONTEXT (context);
|
||||
event->any.type = GDK_DROP_START;
|
||||
|
||||
event->dnd.context = context;
|
||||
gdk_event_set_device (event, gdk_drag_context_get_device (context));
|
||||
g_object_ref (context);
|
||||
gdk_x11_surface_set_user_time (gdk_drop_get_surface (GDK_DROP (context)), time);
|
||||
|
||||
event->dnd.time = time;
|
||||
event->dnd.x_root = context_x11->last_x;
|
||||
event->dnd.y_root = context_x11->last_y;
|
||||
|
||||
gdk_x11_surface_set_user_time (event->any.surface, time);
|
||||
|
||||
return GDK_FILTER_TRANSLATE;
|
||||
gdk_drop_emit_drop_event (GDK_DROP (context), FALSE, context_x11->last_x, context_x11->last_y, time);
|
||||
}
|
||||
|
||||
return GDK_FILTER_REMOVE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GdkFilterReturn
|
||||
@@ -2013,6 +1946,10 @@ _gdk_x11_dnd_filter (const XEvent *xevent,
|
||||
if (xevent->type != ClientMessage)
|
||||
return GDK_FILTER_CONTINUE;
|
||||
|
||||
if (!event->any.surface ||
|
||||
gdk_surface_get_surface_type (event->any.surface) == GDK_SURFACE_FOREIGN)
|
||||
return GDK_FILTER_CONTINUE; /* Not for us */
|
||||
|
||||
display = GDK_SURFACE_DISPLAY (event->any.surface);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (xdnd_filters); i++)
|
||||
@@ -2020,7 +1957,10 @@ _gdk_x11_dnd_filter (const XEvent *xevent,
|
||||
if (xevent->xclient.message_type != gdk_x11_get_xatom_by_name_for_display (display, xdnd_filters[i].atom_name))
|
||||
continue;
|
||||
|
||||
return xdnd_filters[i].func (xevent, event, data);
|
||||
if (xdnd_filters[i].func (event->any.surface, xevent))
|
||||
return GDK_FILTER_REMOVE;
|
||||
else
|
||||
return GDK_FILTER_CONTINUE;
|
||||
}
|
||||
|
||||
return GDK_FILTER_CONTINUE;
|
||||
@@ -2221,11 +2161,7 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context,
|
||||
if (context_x11->drag_surface)
|
||||
move_drag_surface (context, x_root, y_root);
|
||||
|
||||
context_x11->old_actions = context->actions;
|
||||
context->actions = possible_actions;
|
||||
|
||||
if (context_x11->old_actions != possible_actions)
|
||||
context_x11->xdnd_actions_set = FALSE;
|
||||
gdk_drag_context_set_actions (context, possible_actions, suggested_action);
|
||||
|
||||
if (protocol == GDK_DRAG_PROTO_XDND && context_x11->version == 0)
|
||||
{
|
||||
@@ -2250,7 +2186,7 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context,
|
||||
/* When we have a Xdnd target, make sure our XdndActionList
|
||||
* matches the current actions;
|
||||
*/
|
||||
if (protocol == GDK_DRAG_PROTO_XDND && !context_x11->xdnd_actions_set)
|
||||
if (protocol == GDK_DRAG_PROTO_XDND && context_x11->xdnd_actions != gdk_drag_context_get_actions (context))
|
||||
{
|
||||
if (dest_surface)
|
||||
{
|
||||
@@ -2261,13 +2197,12 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context,
|
||||
GdkDisplay *display = GDK_SURFACE_DISPLAY (dest_surface);
|
||||
GdkDragContext *dest_context;
|
||||
|
||||
dest_context = gdk_drag_context_find (display, FALSE,
|
||||
GDK_SURFACE_XID (context->source_surface),
|
||||
GDK_SURFACE_XID (dest_surface));
|
||||
dest_context = GDK_X11_DISPLAY (display)->current_dest_drag;
|
||||
|
||||
if (dest_context)
|
||||
if (dest_context &&
|
||||
dest_context->dest_surface == dest_surface)
|
||||
{
|
||||
dest_context->actions = context->actions;
|
||||
gdk_drag_context_set_actions (dest_context, possible_actions, suggested_action);
|
||||
GDK_X11_DRAG_CONTEXT (dest_context)->xdnd_have_actions = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -2300,9 +2235,6 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
context_x11->old_action = suggested_action;
|
||||
context->suggested_action = suggested_action;
|
||||
context_x11->old_actions = possible_actions;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2320,11 +2252,6 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context,
|
||||
g_signal_emit_by_name (context, "action-changed", context->action);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context_x11->old_action = context->suggested_action;
|
||||
context->suggested_action = suggested_action;
|
||||
}
|
||||
|
||||
/* Send a drag-motion event */
|
||||
|
||||
@@ -2351,7 +2278,7 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context,
|
||||
*/
|
||||
if (gdk_content_formats_contain_mime_type (formats, "application/x-rootwindow-drop") ||
|
||||
gdk_content_formats_contain_mime_type (formats, "application/x-rootwin-drop"))
|
||||
context->action = context->suggested_action;
|
||||
context->action = gdk_drag_context_get_suggested_action (context);
|
||||
else
|
||||
context->action = 0;
|
||||
|
||||
@@ -2413,30 +2340,32 @@ gdk_x11_drag_context_drag_drop (GdkDragContext *context,
|
||||
/* Destination side */
|
||||
|
||||
static void
|
||||
gdk_x11_drag_context_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time_)
|
||||
gdk_x11_drag_context_status (GdkDrop *drop,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (drop);
|
||||
GdkX11DragContext *context_x11 = GDK_X11_DRAG_CONTEXT (context);
|
||||
XEvent xev;
|
||||
GdkDisplay *display;
|
||||
|
||||
display = gdk_drag_context_get_display (context);
|
||||
|
||||
context->action = action;
|
||||
context->action = actions;
|
||||
|
||||
if (context_x11->protocol == GDK_DRAG_PROTO_XDND)
|
||||
{
|
||||
GdkDragAction possible_actions = actions & gdk_drop_get_actions (drop);
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "XdndStatus");
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.window = GDK_SURFACE_XID (context->source_surface);
|
||||
|
||||
xev.xclient.data.l[0] = GDK_SURFACE_XID (context->dest_surface);
|
||||
xev.xclient.data.l[1] = (action != 0) ? (2 | 1) : 0;
|
||||
xev.xclient.data.l[1] = (possible_actions != 0) ? (2 | 1) : 0;
|
||||
xev.xclient.data.l[2] = 0;
|
||||
xev.xclient.data.l[3] = 0;
|
||||
xev.xclient.data.l[4] = xdnd_action_to_atom (display, action);
|
||||
xev.xclient.data.l[4] = xdnd_action_to_atom (display, possible_actions);
|
||||
if (!xdnd_send_xevent (context_x11, context->source_surface, FALSE, &xev))
|
||||
{
|
||||
GDK_DISPLAY_NOTE (display, DND,
|
||||
@@ -2444,28 +2373,26 @@ gdk_x11_drag_context_drag_status (GdkDragContext *context,
|
||||
GDK_SURFACE_XID (context->source_surface)));
|
||||
}
|
||||
}
|
||||
|
||||
context_x11->old_action = action;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_drag_context_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
gdk_x11_drag_context_finish (GdkDrop *drop,
|
||||
GdkDragAction action)
|
||||
{
|
||||
if (GDK_X11_DRAG_CONTEXT (context)->protocol == GDK_DRAG_PROTO_XDND)
|
||||
if (GDK_X11_DRAG_CONTEXT (drop)->protocol == GDK_DRAG_PROTO_XDND)
|
||||
{
|
||||
GdkDisplay *display = gdk_drag_context_get_display (context);
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (drop);
|
||||
GdkDisplay *display = gdk_drop_get_display (drop);
|
||||
XEvent xev;
|
||||
|
||||
if (success && gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE)
|
||||
if (action == GDK_ACTION_MOVE)
|
||||
{
|
||||
XConvertSelection (GDK_DISPLAY_XDISPLAY (display),
|
||||
gdk_x11_get_xatom_by_name_for_display (display, "XdndSelection"),
|
||||
gdk_x11_get_xatom_by_name_for_display (display, "DELETE"),
|
||||
gdk_x11_get_xatom_by_name_for_display (display, "GDK_SELECTION"),
|
||||
GDK_SURFACE_XID (context->source_surface),
|
||||
time);
|
||||
GDK_X11_DRAG_CONTEXT (drop)->timestamp);
|
||||
/* XXX: Do we need to wait for a reply here before sending the next message? */
|
||||
}
|
||||
|
||||
@@ -2475,11 +2402,10 @@ gdk_x11_drag_context_drop_finish (GdkDragContext *context,
|
||||
xev.xclient.window = GDK_SURFACE_XID (context->source_surface);
|
||||
|
||||
xev.xclient.data.l[0] = GDK_SURFACE_XID (context->dest_surface);
|
||||
if (success)
|
||||
if (action != 0)
|
||||
{
|
||||
xev.xclient.data.l[1] = 1;
|
||||
xev.xclient.data.l[2] = xdnd_action_to_atom (display,
|
||||
context->action);
|
||||
xev.xclient.data.l[2] = xdnd_action_to_atom (display, action);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3156,7 +3082,7 @@ gdk_dnd_handle_key_event (GdkDragContext *context,
|
||||
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))
|
||||
(context->dest_surface != NULL))
|
||||
{
|
||||
g_signal_emit_by_name (context, "drop-performed",
|
||||
gdk_event_get_time ((GdkEvent *) event));
|
||||
@@ -3244,7 +3170,7 @@ gdk_dnd_handle_button_event (GdkDragContext *context,
|
||||
#endif
|
||||
|
||||
if ((gdk_drag_context_get_selected_action (context) != 0) &&
|
||||
(gdk_drag_context_get_dest_surface (context) != NULL))
|
||||
(context->dest_surface != NULL))
|
||||
{
|
||||
g_signal_emit_by_name (context, "drop-performed",
|
||||
gdk_event_get_time ((GdkEvent *) event));
|
||||
|
||||
@@ -225,7 +225,7 @@ gdk_event_source_translate_event (GdkX11Display *x11_display,
|
||||
const XEvent *xevent)
|
||||
{
|
||||
GdkEventSource *event_source = (GdkEventSource *) x11_display->event_source;
|
||||
GdkEvent *event = gdk_event_new (GDK_NOTHING);
|
||||
GdkEvent *event;
|
||||
GdkFilterReturn result = GDK_FILTER_CONTINUE;
|
||||
GdkDisplay *display = GDK_DISPLAY (x11_display);
|
||||
GdkEventTranslator *event_translator;
|
||||
@@ -235,9 +235,9 @@ gdk_event_source_translate_event (GdkX11Display *x11_display,
|
||||
gpointer cache;
|
||||
|
||||
x11_screen = GDK_X11_DISPLAY (display)->screen;
|
||||
|
||||
dpy = GDK_DISPLAY_XDISPLAY (display);
|
||||
|
||||
event = gdk_event_new (GDK_NOTHING);
|
||||
filter_surface = gdk_event_source_get_filter_surface (event_source, xevent,
|
||||
&event_translator);
|
||||
if (filter_surface)
|
||||
@@ -268,12 +268,6 @@ gdk_event_source_translate_event (GdkX11Display *x11_display,
|
||||
if (result == GDK_FILTER_CONTINUE)
|
||||
result = _gdk_x11_dnd_filter (xevent, event, NULL);
|
||||
|
||||
if (result == GDK_FILTER_CONTINUE && filter_surface)
|
||||
{
|
||||
gpointer context = g_object_get_data (G_OBJECT (filter_surface), "xdnd-source-context");
|
||||
result = xdnd_source_surface_filter (xevent, event, context);
|
||||
}
|
||||
|
||||
if (result != GDK_FILTER_CONTINUE)
|
||||
{
|
||||
if (result == GDK_FILTER_REMOVE)
|
||||
|
||||
@@ -202,11 +202,6 @@ _gdk_x11_dnd_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data);
|
||||
|
||||
GdkFilterReturn
|
||||
xdnd_source_surface_filter (const XEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data);
|
||||
|
||||
typedef struct _GdkSurfaceCache GdkSurfaceCache;
|
||||
|
||||
GdkSurfaceCache *
|
||||
|
||||
+8
-4
@@ -64,9 +64,12 @@ G_DEFINE_QUARK (gsk-serialization-error-quark, gsk_serialization_error)
|
||||
static void
|
||||
gsk_render_node_finalize (GskRenderNode *self)
|
||||
{
|
||||
self->node_class->finalize (self);
|
||||
const GskRenderNodeClass *klass = self->node_class;
|
||||
gsize extra_size;
|
||||
|
||||
g_free (self);
|
||||
extra_size = self->node_class->finalize (self);
|
||||
|
||||
g_slice_free1 (klass->struct_size + extra_size, self);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
@@ -76,14 +79,15 @@ gsk_render_node_finalize (GskRenderNode *self)
|
||||
* Returns: (transfer full): the newly created #GskRenderNode
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size)
|
||||
gsk_render_node_new (const GskRenderNodeClass *node_class,
|
||||
gsize extra_size)
|
||||
{
|
||||
GskRenderNode *self;
|
||||
|
||||
g_return_val_if_fail (node_class != NULL, NULL);
|
||||
g_return_val_if_fail (node_class->node_type != GSK_NOT_A_RENDER_NODE, NULL);
|
||||
|
||||
self = g_malloc0 (node_class->struct_size + extra_size);
|
||||
self = g_slice_alloc0 (node_class->struct_size + extra_size);
|
||||
|
||||
self->node_class = node_class;
|
||||
|
||||
|
||||
+60
-21
@@ -72,9 +72,10 @@ struct _GskColorNode
|
||||
GdkRGBA color;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_color_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -199,9 +200,12 @@ struct _GskLinearGradientNode
|
||||
GskColorStop stops[];
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_linear_gradient_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskLinearGradientNode *self = (GskLinearGradientNode *) node;
|
||||
|
||||
return self->n_stops * sizeof (GskColorStop);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -508,9 +512,10 @@ struct _GskBorderNode
|
||||
GdkRGBA border_color[4];
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_border_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -755,12 +760,14 @@ struct _GskTextureNode
|
||||
GdkTexture *texture;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_texture_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskTextureNode *self = (GskTextureNode *) node;
|
||||
|
||||
g_object_unref (self->texture);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -948,9 +955,10 @@ struct _GskInsetShadowNode
|
||||
float blur_radius;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_inset_shadow_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1533,9 +1541,10 @@ struct _GskOutsetShadowNode
|
||||
float blur_radius;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_outset_shadow_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1858,13 +1867,15 @@ struct _GskCairoNode
|
||||
cairo_surface_t *surface;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_cairo_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskCairoNode *self = (GskCairoNode *) node;
|
||||
|
||||
if (self->surface)
|
||||
cairo_surface_destroy (self->surface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2123,7 +2134,7 @@ struct _GskContainerNode
|
||||
GskRenderNode *children[];
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_container_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskContainerNode *container = (GskContainerNode *) node;
|
||||
@@ -2131,6 +2142,8 @@ gsk_container_node_finalize (GskRenderNode *node)
|
||||
|
||||
for (i = 0; i < container->n_children; i++)
|
||||
gsk_render_node_unref (container->children[i]);
|
||||
|
||||
return container->n_children * sizeof (GskRenderNode *);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2389,12 +2402,14 @@ struct _GskTransformNode
|
||||
graphene_matrix_t transform;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_transform_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskTransformNode *self = (GskTransformNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2565,12 +2580,14 @@ struct _GskOffsetNode
|
||||
double y_offset;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_offset_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskOffsetNode *self = (GskOffsetNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2764,13 +2781,15 @@ struct _GskDebugNode
|
||||
char *message;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_debug_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskDebugNode *self = (GskDebugNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
g_free (self->message);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2935,12 +2954,14 @@ struct _GskOpacityNode
|
||||
double opacity;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_opacity_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskOpacityNode *self = (GskOpacityNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3103,12 +3124,14 @@ struct _GskColorMatrixNode
|
||||
graphene_vec4_t color_offset;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_color_matrix_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskColorMatrixNode *self = (GskColorMatrixNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3356,12 +3379,14 @@ struct _GskRepeatNode
|
||||
graphene_rect_t child_bounds;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_repeat_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskRepeatNode *self = (GskRepeatNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3527,12 +3552,14 @@ struct _GskClipNode
|
||||
graphene_rect_t clip;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_clip_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskClipNode *self = (GskClipNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3701,12 +3728,14 @@ struct _GskRoundedClipNode
|
||||
GskRoundedRect clip;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_rounded_clip_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskRoundedClipNode *self = (GskRoundedClipNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3890,12 +3919,14 @@ struct _GskShadowNode
|
||||
GskShadow shadows[];
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_shadow_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskShadowNode *self = (GskShadowNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return self->n_shadows * sizeof (GskShadow);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4220,13 +4251,15 @@ gsk_blend_mode_to_cairo_operator (GskBlendMode blend_mode)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_blend_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskBlendNode *self = (GskBlendNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->bottom);
|
||||
gsk_render_node_unref (self->top);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4408,13 +4441,15 @@ struct _GskCrossFadeNode
|
||||
double progress;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_cross_fade_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskCrossFadeNode *self = (GskCrossFadeNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->start);
|
||||
gsk_render_node_unref (self->end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4603,12 +4638,14 @@ struct _GskTextNode
|
||||
PangoGlyphInfo glyphs[];
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_text_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskTextNode *self = (GskTextNode *) node;
|
||||
|
||||
g_object_unref (self->font);
|
||||
|
||||
return self->num_glyphs * sizeof (PangoGlyphInfo);
|
||||
}
|
||||
|
||||
#ifndef STACK_BUFFER_SIZE
|
||||
@@ -4937,12 +4974,14 @@ struct _GskBlurNode
|
||||
double radius;
|
||||
};
|
||||
|
||||
static void
|
||||
static gsize
|
||||
gsk_blur_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskBlurNode *self = (GskBlurNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -25,7 +25,7 @@ struct _GskRenderNodeClass
|
||||
gsize struct_size;
|
||||
const char *type_name;
|
||||
|
||||
void (* finalize) (GskRenderNode *node);
|
||||
gsize (* finalize) (GskRenderNode *node);
|
||||
void (* draw) (GskRenderNode *node,
|
||||
cairo_t *cr);
|
||||
gboolean (* can_diff) (GskRenderNode *node1,
|
||||
|
||||
@@ -220,6 +220,7 @@
|
||||
#include <gtk/gtktooltip.h>
|
||||
#include <gtk/gtktestutils.h>
|
||||
#include <gtk/gtktreednd.h>
|
||||
#include <gtk/gtktreelist.h>
|
||||
#include <gtk/gtktreemodel.h>
|
||||
#include <gtk/gtktreemodelfilter.h>
|
||||
#include <gtk/gtktreemodelsort.h>
|
||||
|
||||
+33
-44
@@ -312,22 +312,18 @@ static void gtk_calendar_drag_data_get (GtkWidget *widget,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time);
|
||||
static void gtk_calendar_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time);
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data);
|
||||
static gboolean gtk_calendar_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static void gtk_calendar_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
GdkDrop *drop);
|
||||
static gboolean gtk_calendar_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
|
||||
|
||||
static void calendar_start_spinning (GtkCalendar *calendar,
|
||||
@@ -2927,39 +2923,36 @@ gtk_calendar_drag_data_get (GtkWidget *widget,
|
||||
* since the data doesn’t result from a drop.
|
||||
*/
|
||||
static void
|
||||
set_status_pending (GdkDragContext *context,
|
||||
GdkDragAction suggested_action)
|
||||
set_status_pending (GdkDrop *drop,
|
||||
GdkDragAction suggested_action)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (context),
|
||||
g_object_set_data (G_OBJECT (drop),
|
||||
I_("gtk-calendar-status-pending"),
|
||||
GINT_TO_POINTER (suggested_action));
|
||||
}
|
||||
|
||||
static GdkDragAction
|
||||
get_status_pending (GdkDragContext *context)
|
||||
get_status_pending (GdkDrop *drop)
|
||||
{
|
||||
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
|
||||
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drop),
|
||||
"gtk-calendar-status-pending"));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_calendar_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
gtk_calendar_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkCalendarPrivate *priv = GTK_CALENDAR (widget)->priv;
|
||||
|
||||
priv->drag_highlight = 0;
|
||||
gtk_drag_unhighlight (widget);
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_calendar_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gint y)
|
||||
{
|
||||
GtkCalendarPrivate *priv = GTK_CALENDAR (widget)->priv;
|
||||
GdkAtom target;
|
||||
@@ -2970,13 +2963,13 @@ gtk_calendar_drag_motion (GtkWidget *widget,
|
||||
gtk_drag_highlight (widget);
|
||||
}
|
||||
|
||||
target = gtk_drag_dest_find_target (widget, context, NULL);
|
||||
if (target == NULL || gdk_drag_context_get_suggested_action (context) == 0)
|
||||
gdk_drag_status (context, 0, time);
|
||||
else if (get_status_pending (context) == 0)
|
||||
target = gtk_drag_dest_find_target (widget, drop, NULL);
|
||||
if (target == NULL || gdk_drop_get_actions (drop) == 0)
|
||||
gdk_drop_status (drop, 0);
|
||||
else if (get_status_pending (drop) == 0)
|
||||
{
|
||||
set_status_pending (context, gdk_drag_context_get_suggested_action (context));
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
set_status_pending (drop, gdk_drop_get_actions (drop));
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -2984,19 +2977,16 @@ gtk_calendar_drag_motion (GtkWidget *widget,
|
||||
|
||||
static gboolean
|
||||
gtk_calendar_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gint y)
|
||||
{
|
||||
GdkAtom target;
|
||||
|
||||
target = gtk_drag_dest_find_target (widget, context, NULL);
|
||||
target = gtk_drag_dest_find_target (widget, drop, NULL);
|
||||
if (target != NULL)
|
||||
{
|
||||
gtk_drag_get_data (widget, context,
|
||||
target,
|
||||
time);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -3005,9 +2995,8 @@ gtk_calendar_drag_drop (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
gtk_calendar_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
GtkCalendar *calendar = GTK_CALENDAR (widget);
|
||||
GtkCalendarPrivate *priv = calendar->priv;
|
||||
@@ -3016,11 +3005,11 @@ gtk_calendar_drag_data_received (GtkWidget *widget,
|
||||
GDate *date;
|
||||
GdkDragAction suggested_action;
|
||||
|
||||
suggested_action = get_status_pending (context);
|
||||
suggested_action = get_status_pending (drop);
|
||||
|
||||
if (suggested_action)
|
||||
{
|
||||
set_status_pending (context, 0);
|
||||
set_status_pending (drop, 0);
|
||||
|
||||
/* We are getting this data due to a request in drag_motion,
|
||||
* rather than due to a request in drag_drop, so we are just
|
||||
@@ -3041,7 +3030,7 @@ gtk_calendar_drag_data_received (GtkWidget *widget,
|
||||
else
|
||||
suggested_action = 0;
|
||||
|
||||
gdk_drag_status (context, suggested_action, time);
|
||||
gdk_drop_status (drop, suggested_action);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -3058,7 +3047,7 @@ gtk_calendar_drag_data_received (GtkWidget *widget,
|
||||
{
|
||||
g_warning ("Received invalid date data");
|
||||
g_date_free (date);
|
||||
gtk_drag_finish (context, FALSE, time);
|
||||
gdk_drop_finish (drop, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3067,7 +3056,7 @@ gtk_calendar_drag_data_received (GtkWidget *widget,
|
||||
year = g_date_get_year (date);
|
||||
g_date_free (date);
|
||||
|
||||
gtk_drag_finish (context, TRUE, time);
|
||||
gdk_drop_finish (drop, suggested_action);
|
||||
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (calendar));
|
||||
|
||||
@@ -120,11 +120,8 @@ static void gtk_color_button_drag_data_get (GtkWidget *widget,
|
||||
|
||||
/* target side drag signals */
|
||||
static void gtk_color_button_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data,
|
||||
guint32 time,
|
||||
GtkColorButton *button);
|
||||
|
||||
|
||||
@@ -276,11 +273,8 @@ gtk_color_button_class_init (GtkColorButtonClass *klass)
|
||||
|
||||
static void
|
||||
gtk_color_button_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data,
|
||||
guint32 time,
|
||||
GtkColorButton *button)
|
||||
{
|
||||
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
|
||||
|
||||
@@ -208,9 +208,8 @@ swatch_drag_data_get (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
swatch_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
gint length;
|
||||
guint16 *vals;
|
||||
|
||||
@@ -0,0 +1,750 @@
|
||||
/* gtkrbtree.c
|
||||
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssrbtreeprivate.h"
|
||||
|
||||
#include "gtkdebug.h"
|
||||
|
||||
typedef struct _GtkCssRbNode GtkCssRbNode;
|
||||
|
||||
struct _GtkCssRbTree
|
||||
{
|
||||
guint ref_count;
|
||||
|
||||
gsize element_size;
|
||||
gsize augment_size;
|
||||
GtkCssRbTreeAugmentFunc augment_func;
|
||||
GDestroyNotify clear_func;
|
||||
GDestroyNotify clear_augment_func;
|
||||
|
||||
GtkCssRbNode *root;
|
||||
};
|
||||
|
||||
struct _GtkCssRbNode
|
||||
{
|
||||
guint red :1;
|
||||
guint dirty :1;
|
||||
|
||||
GtkCssRbNode *left;
|
||||
GtkCssRbNode *right;
|
||||
GtkCssRbNode *parent;
|
||||
};
|
||||
|
||||
#define NODE_FROM_POINTER(ptr) ((GtkCssRbNode *) ((ptr) ? (((guchar *) (ptr)) - sizeof (GtkCssRbNode)) : NULL))
|
||||
#define NODE_TO_POINTER(node) ((gpointer) ((node) ? (((guchar *) (node)) + sizeof (GtkCssRbNode)) : NULL))
|
||||
#define NODE_TO_AUG_POINTER(tree, node) ((gpointer) ((node) ? (((guchar *) (node)) + sizeof (GtkCssRbNode) + (tree)->element_size) : NULL))
|
||||
|
||||
static inline gsize
|
||||
gtk_css_rb_node_get_size (GtkCssRbTree *tree)
|
||||
{
|
||||
return sizeof (GtkCssRbNode) + tree->element_size + tree->augment_size;
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_new (GtkCssRbTree *tree)
|
||||
{
|
||||
GtkCssRbNode *result;
|
||||
|
||||
result = g_slice_alloc0 (gtk_css_rb_node_get_size (tree));
|
||||
|
||||
result->red = TRUE;
|
||||
result->dirty = TRUE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_free (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
if (tree->clear_func)
|
||||
tree->clear_func (NODE_TO_POINTER (node));
|
||||
if (tree->clear_augment_func)
|
||||
tree->clear_augment_func (NODE_TO_AUG_POINTER (tree, node));
|
||||
|
||||
g_slice_free1 (gtk_css_rb_node_get_size (tree), node);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_free_deep (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *right = node->right;
|
||||
|
||||
if (node->left)
|
||||
gtk_css_rb_node_free_deep (tree, node->left);
|
||||
|
||||
gtk_css_rb_node_free (tree, node);
|
||||
|
||||
if (right)
|
||||
gtk_css_rb_node_free_deep (tree, right);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_mark_dirty (GtkCssRbNode *node,
|
||||
gboolean mark_parent)
|
||||
{
|
||||
if (node->dirty)
|
||||
return;
|
||||
|
||||
node->dirty = TRUE;
|
||||
|
||||
if (mark_parent && node->parent)
|
||||
gtk_css_rb_node_mark_dirty (node->parent, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_clean (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
if (!node->dirty)
|
||||
return;
|
||||
|
||||
node->dirty = FALSE;
|
||||
if (tree->augment_func)
|
||||
tree->augment_func (tree,
|
||||
NODE_TO_AUG_POINTER (tree, node),
|
||||
NODE_TO_POINTER (node),
|
||||
NODE_TO_POINTER (node->left),
|
||||
NODE_TO_POINTER (node->right));
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_get_first (GtkCssRbNode *node)
|
||||
{
|
||||
while (node->left)
|
||||
node = node->left;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_get_last (GtkCssRbNode *node)
|
||||
{
|
||||
while (node->right)
|
||||
node = node->right;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_get_previous (GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *parent;
|
||||
|
||||
if (node->left)
|
||||
return gtk_css_rb_node_get_last (node->left);
|
||||
|
||||
for (parent = node->parent; parent != NULL; parent = node->parent)
|
||||
{
|
||||
if (parent->right == node)
|
||||
return parent;
|
||||
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_get_next (GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *parent;
|
||||
|
||||
if (node->right)
|
||||
return gtk_css_rb_node_get_first (node->right);
|
||||
|
||||
for (parent = node->parent; parent != NULL; parent = node->parent)
|
||||
{
|
||||
if (parent->left == node)
|
||||
return parent;
|
||||
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_rotate_left (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *right;
|
||||
|
||||
right = node->right;
|
||||
|
||||
node->right = right->left;
|
||||
if (right->left)
|
||||
right->left->parent = node;
|
||||
|
||||
right->parent = node->parent;
|
||||
if (node->parent)
|
||||
{
|
||||
if (node == node->parent->left)
|
||||
node->parent->left = right;
|
||||
else
|
||||
node->parent->right = right;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->root = right;
|
||||
}
|
||||
|
||||
right->left = node;
|
||||
node->parent = right;
|
||||
|
||||
gtk_css_rb_node_mark_dirty (node, FALSE);
|
||||
gtk_css_rb_node_mark_dirty (right, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_rotate_right (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *left;
|
||||
|
||||
left = node->left;
|
||||
|
||||
node->left = left->right;
|
||||
if (left->right)
|
||||
left->right->parent = node;
|
||||
|
||||
left->parent = node->parent;
|
||||
if (node->parent)
|
||||
{
|
||||
if (node == node->parent->right)
|
||||
node->parent->right = left;
|
||||
else
|
||||
node->parent->left = left;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->root = left;
|
||||
}
|
||||
|
||||
/* link node and left */
|
||||
left->right = node;
|
||||
node->parent = left;
|
||||
|
||||
gtk_css_rb_node_mark_dirty (node, FALSE);
|
||||
gtk_css_rb_node_mark_dirty (left, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_red (GtkCssRbNode *node_or_null)
|
||||
{
|
||||
if (node_or_null == NULL)
|
||||
return FALSE;
|
||||
else
|
||||
return node_or_null->red;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_black (GtkCssRbNode *node_or_null)
|
||||
{
|
||||
return !is_red (node_or_null);
|
||||
}
|
||||
|
||||
static void
|
||||
set_black (GtkCssRbNode *node_or_null)
|
||||
{
|
||||
if (node_or_null == NULL)
|
||||
return;
|
||||
|
||||
node_or_null->red = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_red (GtkCssRbNode *node_or_null)
|
||||
{
|
||||
if (node_or_null == NULL)
|
||||
return;
|
||||
|
||||
node_or_null->red = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_tree_insert_fixup (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
|
||||
/* check Red-Black properties */
|
||||
while (node->parent && is_red (node->parent))
|
||||
{
|
||||
/* we have a violation */
|
||||
g_assert (node->parent->parent);
|
||||
|
||||
if (node->parent == node->parent->parent->left)
|
||||
{
|
||||
GtkCssRbNode *uncle = node->parent->parent->right;
|
||||
|
||||
if (is_red (uncle))
|
||||
{
|
||||
/* uncle is red */
|
||||
set_black (node->parent);
|
||||
set_black (uncle);
|
||||
set_red (node->parent->parent);
|
||||
node = node->parent->parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* uncle is black */
|
||||
if (node == node->parent->right)
|
||||
{
|
||||
/* make node a left child */
|
||||
node = node->parent;
|
||||
gtk_css_rb_node_rotate_left (tree, node);
|
||||
}
|
||||
/* recolor and rotate */
|
||||
set_black (node->parent);
|
||||
set_red (node->parent->parent);
|
||||
gtk_css_rb_node_rotate_right (tree, node->parent->parent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* mirror image of above code */
|
||||
GtkCssRbNode *uncle = node->parent->parent->left;
|
||||
|
||||
if (is_red (uncle))
|
||||
{
|
||||
/* uncle is red */
|
||||
set_black (node->parent);
|
||||
set_black (uncle);
|
||||
set_red (node->parent->parent);
|
||||
node = node->parent->parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* uncle is black */
|
||||
if (node == node->parent->left)
|
||||
{
|
||||
node = node->parent;
|
||||
gtk_css_rb_node_rotate_right (tree, node);
|
||||
}
|
||||
set_black (node->parent);
|
||||
set_red (node->parent->parent);
|
||||
gtk_css_rb_node_rotate_left (tree, node->parent->parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_black (tree->root);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_tree_remove_node_fixup (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node,
|
||||
GtkCssRbNode *parent)
|
||||
{
|
||||
while (node->parent && is_black (node))
|
||||
{
|
||||
if (node == parent->left)
|
||||
{
|
||||
GtkCssRbNode *w = parent->right;
|
||||
|
||||
if (is_red (w))
|
||||
{
|
||||
set_black (w);
|
||||
set_red (parent);
|
||||
gtk_css_rb_node_rotate_left (tree, parent);
|
||||
w = parent->right;
|
||||
}
|
||||
if (is_black (w->left) && is_black (w->right))
|
||||
{
|
||||
set_red (w);
|
||||
node = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_black (w->right))
|
||||
{
|
||||
set_black (w->left);
|
||||
set_red (w);
|
||||
gtk_css_rb_node_rotate_right (tree, w);
|
||||
w = parent->right;
|
||||
}
|
||||
w->red = parent->red;
|
||||
set_black (parent);
|
||||
set_black (w->right);
|
||||
gtk_css_rb_node_rotate_left (tree, parent);
|
||||
node = tree->root;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkCssRbNode *w = parent->left;
|
||||
if (is_red (w))
|
||||
{
|
||||
set_black (w);
|
||||
set_red (parent);
|
||||
gtk_css_rb_node_rotate_right (tree, parent);
|
||||
w = parent->left;
|
||||
}
|
||||
if (is_black (w->right) && is_black (w->left))
|
||||
{
|
||||
set_red (w);
|
||||
node = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_black (w->left))
|
||||
{
|
||||
set_black (w->right);
|
||||
set_red (w);
|
||||
gtk_css_rb_node_rotate_left (tree, w);
|
||||
w = parent->left;
|
||||
}
|
||||
w->red = parent->red;
|
||||
set_black (parent);
|
||||
set_black (w->left);
|
||||
gtk_css_rb_node_rotate_right (tree, parent);
|
||||
node = tree->root;
|
||||
}
|
||||
}
|
||||
|
||||
parent = node->parent;
|
||||
}
|
||||
|
||||
set_black (node);
|
||||
}
|
||||
|
||||
GtkCssRbTree *
|
||||
gtk_css_rb_tree_new_for_size (gsize element_size,
|
||||
gsize augment_size,
|
||||
GtkCssRbTreeAugmentFunc augment_func,
|
||||
GDestroyNotify clear_func,
|
||||
GDestroyNotify clear_augment_func)
|
||||
{
|
||||
GtkCssRbTree *tree;
|
||||
|
||||
tree = g_slice_new0 (GtkCssRbTree);
|
||||
tree->ref_count = 1;
|
||||
|
||||
tree->element_size = element_size;
|
||||
tree->augment_size = augment_size;
|
||||
tree->augment_func = augment_func;
|
||||
tree->clear_func = clear_func;
|
||||
tree->clear_augment_func = clear_augment_func;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
GtkCssRbTree *
|
||||
gtk_css_rb_tree_ref (GtkCssRbTree *tree)
|
||||
{
|
||||
tree->ref_count++;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rb_tree_unref (GtkCssRbTree *tree)
|
||||
{
|
||||
tree->ref_count--;
|
||||
if (tree->ref_count > 0)
|
||||
return;
|
||||
|
||||
if (tree->root)
|
||||
gtk_css_rb_node_free_deep (tree, tree->root);
|
||||
|
||||
g_slice_free (GtkCssRbTree, tree);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_first (GtkCssRbTree *tree)
|
||||
{
|
||||
if (tree->root == NULL)
|
||||
return NULL;
|
||||
|
||||
return NODE_TO_POINTER (gtk_css_rb_node_get_first (tree->root));
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_last (GtkCssRbTree *tree)
|
||||
{
|
||||
if (tree->root == NULL)
|
||||
return NULL;
|
||||
|
||||
return NODE_TO_POINTER (gtk_css_rb_node_get_last (tree->root));
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_previous (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (gtk_css_rb_node_get_previous (NODE_FROM_POINTER (node)));
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_next (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (gtk_css_rb_node_get_next (NODE_FROM_POINTER (node)));
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_root (GtkCssRbTree *tree)
|
||||
{
|
||||
return NODE_TO_POINTER (tree->root);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_parent (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (NODE_FROM_POINTER (node)->parent);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_left (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (NODE_FROM_POINTER (node)->left);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_right (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (NODE_FROM_POINTER (node)->right);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_augment (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
GtkCssRbNode *rbnode = NODE_FROM_POINTER (node);
|
||||
|
||||
gtk_css_rb_node_clean (tree, rbnode);
|
||||
|
||||
return NODE_TO_AUG_POINTER (tree, rbnode);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rb_tree_mark_dirty (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
gtk_css_rb_node_mark_dirty (NODE_FROM_POINTER (node), TRUE);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_insert_before (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
GtkCssRbNode *result;
|
||||
|
||||
/* setup new node */
|
||||
result = gtk_css_rb_node_new (tree);
|
||||
|
||||
if (tree->root == NULL)
|
||||
{
|
||||
g_assert (node == NULL);
|
||||
tree->root = result;
|
||||
}
|
||||
else if (node == NULL)
|
||||
{
|
||||
return gtk_css_rb_tree_insert_after (tree, gtk_css_rb_tree_get_last (tree));
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkCssRbNode *current = NODE_FROM_POINTER (node);
|
||||
|
||||
if (current->left)
|
||||
{
|
||||
current = gtk_css_rb_node_get_last (current);
|
||||
current->right = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
current->left = result;
|
||||
}
|
||||
result->parent = current;
|
||||
gtk_css_rb_node_mark_dirty (current, TRUE);
|
||||
}
|
||||
|
||||
gtk_css_rb_tree_insert_fixup (tree, result);
|
||||
|
||||
return NODE_TO_POINTER (result);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_insert_after (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
GtkCssRbNode *result;
|
||||
|
||||
/* setup new node */
|
||||
result = gtk_css_rb_node_new (tree);
|
||||
|
||||
if (tree->root == NULL)
|
||||
{
|
||||
g_assert (node == NULL);
|
||||
tree->root = result;
|
||||
}
|
||||
else if (node == NULL)
|
||||
{
|
||||
return gtk_css_rb_tree_insert_before (tree, gtk_css_rb_tree_get_first (tree));
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkCssRbNode *current = NODE_FROM_POINTER (node);
|
||||
|
||||
if (current->right )
|
||||
{
|
||||
current = gtk_css_rb_node_get_first (current);
|
||||
current->left = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
current->right = result;
|
||||
}
|
||||
result->parent = current;
|
||||
gtk_css_rb_node_mark_dirty (current, TRUE);
|
||||
}
|
||||
|
||||
gtk_css_rb_tree_insert_fixup (tree, result);
|
||||
|
||||
return NODE_TO_POINTER (result);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rb_tree_remove (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
GtkCssRbNode *x, *y, *real_node;
|
||||
|
||||
real_node = NODE_FROM_POINTER (node);
|
||||
y = real_node;
|
||||
if (y->left && y->right)
|
||||
{
|
||||
y = y->right;
|
||||
|
||||
while (y->left)
|
||||
y = y->left;
|
||||
}
|
||||
|
||||
/* x is y's only child, or nil */
|
||||
if (y->left)
|
||||
x = y->left;
|
||||
else
|
||||
x = y->right;
|
||||
|
||||
/* remove y from the parent chain */
|
||||
if (x != NULL)
|
||||
x->parent = y->parent;
|
||||
if (y->parent)
|
||||
{
|
||||
if (y == y->parent->left)
|
||||
y->parent->left = x;
|
||||
else
|
||||
y->parent->right = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->root = x;
|
||||
}
|
||||
|
||||
/* We need to clean up the validity of the tree.
|
||||
*/
|
||||
if (x && is_black (y))
|
||||
gtk_css_rb_tree_remove_node_fixup (tree, x, y->parent);
|
||||
|
||||
if (y != real_node)
|
||||
{
|
||||
/* Move the node over */
|
||||
if (is_red (real_node) != is_red (y))
|
||||
y->red = !y->red;
|
||||
|
||||
y->left = real_node->left;
|
||||
if (y->left)
|
||||
y->left->parent = y;
|
||||
y->right = real_node->right;
|
||||
if (y->right)
|
||||
y->right->parent = y;
|
||||
y->parent = real_node->parent;
|
||||
if (y->parent)
|
||||
{
|
||||
if (y->parent->left == real_node)
|
||||
y->parent->left = y;
|
||||
else
|
||||
y->parent->right = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->root = y;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_css_rb_node_free (tree, real_node);
|
||||
}
|
||||
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_find (GtkCssRbTree *tree,
|
||||
gpointer *out_before,
|
||||
gpointer *out_after,
|
||||
GtkCssRbTreeFindFunc find_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkCssRbNode *node, *before = NULL, *after = NULL;
|
||||
int cmp;
|
||||
|
||||
if (tree->root == NULL)
|
||||
{
|
||||
if (out_before)
|
||||
*out_before = NULL;
|
||||
if (out_after)
|
||||
*out_after = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = tree->root;
|
||||
for (cmp = find_func (tree, NODE_TO_POINTER (node), user_data);
|
||||
cmp != 0;
|
||||
cmp = find_func (tree, NODE_TO_POINTER (node), user_data))
|
||||
{
|
||||
if (cmp < 0)
|
||||
{
|
||||
before = node;
|
||||
node = node->right;
|
||||
}
|
||||
else /* cmp > 0 */
|
||||
{
|
||||
after = node;
|
||||
node = node->left;
|
||||
}
|
||||
if (node == NULL)
|
||||
{
|
||||
if (out_before)
|
||||
*out_before = NODE_TO_POINTER (before);
|
||||
if (out_after)
|
||||
*out_after = NODE_TO_POINTER (after);
|
||||
return NULL;;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_before)
|
||||
*out_before = NODE_TO_POINTER (gtk_css_rb_node_get_previous (node));
|
||||
if (out_after)
|
||||
*out_after = NODE_TO_POINTER (gtk_css_rb_node_get_next (node));
|
||||
|
||||
return NODE_TO_POINTER (node);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/* gtkrb_tree.h
|
||||
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* A Red-Black Tree implementation used specifically by GtkTreeView.
|
||||
*/
|
||||
#ifndef __GTK_CSS_RB_TREE_H__
|
||||
#define __GTK_CSS_RB_TREE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
typedef struct _GtkCssRbTree GtkCssRbTree;
|
||||
|
||||
typedef void (* GtkCssRbTreeAugmentFunc) (GtkCssRbTree *tree,
|
||||
gpointer node_augment,
|
||||
gpointer node,
|
||||
gpointer left,
|
||||
gpointer right);
|
||||
typedef int (* GtkCssRbTreeFindFunc) (GtkCssRbTree *tree,
|
||||
gpointer node,
|
||||
gpointer user_data);
|
||||
|
||||
GtkCssRbTree * gtk_css_rb_tree_new_for_size (gsize element_size,
|
||||
gsize augment_size,
|
||||
GtkCssRbTreeAugmentFunc augment_func,
|
||||
GDestroyNotify clear_func,
|
||||
GDestroyNotify clear_augment_func);
|
||||
#define gtk_css_rb_tree_new(type, augment_type, augment_func, clear_func, clear_augment_func) \
|
||||
gtk_css_rb_tree_new_for_size (sizeof (type), sizeof (augment_type), (augment_func), (clear_func), (clear_augment_func))
|
||||
|
||||
GtkCssRbTree * gtk_css_rb_tree_ref (GtkCssRbTree *tree);
|
||||
void gtk_css_rb_tree_unref (GtkCssRbTree *tree);
|
||||
|
||||
gpointer gtk_css_rb_tree_get_first (GtkCssRbTree *tree);
|
||||
gpointer gtk_css_rb_tree_get_last (GtkCssRbTree *tree);
|
||||
gpointer gtk_css_rb_tree_get_previous (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_get_next (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
|
||||
gpointer gtk_css_rb_tree_get_root (GtkCssRbTree *tree);
|
||||
gpointer gtk_css_rb_tree_get_parent (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_get_left (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_get_right (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_get_augment (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
|
||||
void gtk_css_rb_tree_mark_dirty (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
|
||||
gpointer gtk_css_rb_tree_insert_before (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_insert_after (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
void gtk_css_rb_tree_remove (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
|
||||
gpointer gtk_css_rb_tree_find (GtkCssRbTree *tree,
|
||||
gpointer *out_before,
|
||||
gpointer *out_after,
|
||||
GtkCssRbTreeFindFunc find_func,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
#endif /* __GTK_CSS_RB_TREE_H__ */
|
||||
+85
-122
@@ -59,8 +59,6 @@
|
||||
*/
|
||||
|
||||
|
||||
static GSList *source_widgets = NULL;
|
||||
|
||||
typedef struct _GtkDragSourceInfo GtkDragSourceInfo;
|
||||
typedef struct _GtkDragDestInfo GtkDragDestInfo;
|
||||
|
||||
@@ -79,42 +77,42 @@ struct _GtkDragSourceInfo
|
||||
struct _GtkDragDestInfo
|
||||
{
|
||||
GtkWidget *widget; /* Widget in which drag is in */
|
||||
GdkDragContext *context; /* Drag context */
|
||||
GdkDrop *drop; /* drop */
|
||||
};
|
||||
|
||||
#define DROP_ABORT_TIME 300000
|
||||
|
||||
typedef gboolean (* GtkDragDestCallback) (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint32 time);
|
||||
|
||||
/* Forward declarations */
|
||||
static gboolean gtk_drag_find_widget (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
static gboolean gtk_drop_find_widget (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
GtkDragDestInfo *info,
|
||||
gint x,
|
||||
gint y,
|
||||
guint32 time,
|
||||
GtkDragDestCallback callback);
|
||||
static void gtk_drag_dest_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
guint time);
|
||||
static gboolean gtk_drag_dest_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
static gboolean gtk_drag_dest_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
static void gtk_drag_dest_set_widget (GtkDragDestInfo *info,
|
||||
GtkWidget *widget);
|
||||
|
||||
static GtkDragDestInfo * gtk_drag_get_dest_info (GdkDragContext *context,
|
||||
static GtkDragDestInfo * gtk_drag_get_dest_info (GdkDrop *drop,
|
||||
gboolean create);
|
||||
static GtkDragSourceInfo *gtk_drag_get_source_info (GdkDragContext *context,
|
||||
gboolean create);
|
||||
@@ -154,10 +152,9 @@ static void set_icon_helper (GdkDragContext *context,
|
||||
********************/
|
||||
|
||||
typedef struct {
|
||||
GdkDragContext *context;
|
||||
GdkDrop *drop;
|
||||
GtkWidget *widget;
|
||||
const char *mime_type;
|
||||
guint time;
|
||||
} GtkDragGetData;
|
||||
|
||||
static void
|
||||
@@ -185,30 +182,38 @@ gtk_drag_get_data_finish (GtkDragGetData *data,
|
||||
size >= 0)
|
||||
g_signal_emit_by_name (data->widget,
|
||||
"drag-data-received",
|
||||
data->context,
|
||||
&sdata,
|
||||
data->time);
|
||||
data->drop,
|
||||
&sdata);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_signal_emit_by_name (data->widget,
|
||||
"drag-data-received",
|
||||
data->context,
|
||||
&sdata,
|
||||
data->time);
|
||||
data->drop,
|
||||
&sdata);
|
||||
}
|
||||
|
||||
if (site && site->flags & GTK_DEST_DEFAULT_DROP)
|
||||
{
|
||||
GdkDragAction action = site->actions & gdk_drop_get_actions (data->drop);
|
||||
|
||||
gtk_drag_finish (data->context,
|
||||
size > 0,
|
||||
data->time);
|
||||
if (size == 0)
|
||||
action = 0;
|
||||
|
||||
if (!gdk_drag_action_is_unique (action))
|
||||
{
|
||||
if (action & GDK_ACTION_COPY)
|
||||
action = GDK_ACTION_COPY;
|
||||
else if (action & GDK_ACTION_MOVE)
|
||||
action = GDK_ACTION_MOVE;
|
||||
}
|
||||
|
||||
gdk_drop_finish (data->drop, action);
|
||||
}
|
||||
|
||||
g_object_unref (data->widget);
|
||||
g_object_unref (data->context);
|
||||
g_object_unref (data->drop);
|
||||
g_slice_free (GtkDragGetData, data);
|
||||
}
|
||||
|
||||
@@ -241,7 +246,7 @@ gtk_drag_get_data_got_stream (GObject *source,
|
||||
GInputStream *input_stream;
|
||||
GOutputStream *output_stream;
|
||||
|
||||
input_stream = gdk_drop_read_finish (GDK_DRAG_CONTEXT (source), &data->mime_type, result, NULL);
|
||||
input_stream = gdk_drop_read_finish (GDK_DROP (source), &data->mime_type, result, NULL);
|
||||
if (input_stream == NULL)
|
||||
{
|
||||
gtk_drag_get_data_finish (data, NULL, 0);
|
||||
@@ -265,7 +270,7 @@ gtk_drag_get_data_got_stream (GObject *source,
|
||||
* gtk_drag_get_data: (method)
|
||||
* @widget: the widget that will receive the
|
||||
* #GtkWidget::drag-data-received signal
|
||||
* @context: the drag context
|
||||
* @drop: the #GdkDrop
|
||||
* @target: the target (form of the data) to retrieve
|
||||
* @time_: a timestamp for retrieving the data. This will
|
||||
* generally be the time received in a #GtkWidget::drag-motion
|
||||
@@ -281,23 +286,21 @@ gtk_drag_get_data_got_stream (GObject *source,
|
||||
* drops.
|
||||
*/
|
||||
void
|
||||
gtk_drag_get_data (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkAtom target,
|
||||
guint32 time_)
|
||||
gtk_drag_get_data (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
GdkAtom target)
|
||||
{
|
||||
GtkDragGetData *data;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
g_return_if_fail (GDK_IS_DROP (drop));
|
||||
|
||||
data = g_slice_new0 (GtkDragGetData);
|
||||
data->widget = g_object_ref (widget);
|
||||
data->context = g_object_ref (context);
|
||||
data->drop = g_object_ref (drop);
|
||||
data->mime_type = target;
|
||||
data->time = time_;
|
||||
|
||||
gdk_drop_read_async (context,
|
||||
gdk_drop_read_async (drop,
|
||||
(const gchar *[2]) { target, NULL },
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
@@ -318,41 +321,15 @@ gtk_drag_get_data (GtkWidget *widget,
|
||||
GtkWidget *
|
||||
gtk_drag_get_source_widget (GdkDragContext *context)
|
||||
{
|
||||
GSList *tmp_list;
|
||||
GtkDragSourceInfo *info;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
tmp_list = source_widgets;
|
||||
while (tmp_list)
|
||||
{
|
||||
GtkWidget *widget = tmp_list->data;
|
||||
info = gtk_drag_get_source_info (context, FALSE);
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
if (gtk_widget_get_surface (widget) == gdk_drag_context_get_source_surface (context))
|
||||
return widget;
|
||||
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_drag_finish:
|
||||
* @context: the drag context
|
||||
* @success: a flag indicating whether the drop was successful
|
||||
* @time_: the timestamp from the #GtkWidget::drag-drop signal
|
||||
*
|
||||
* Informs the drag source that the drop is finished, and
|
||||
* that the data of the drag will no longer be required.
|
||||
*/
|
||||
void
|
||||
gtk_drag_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
|
||||
gdk_drop_finish (context, success, time);
|
||||
return info->widget;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,7 +376,7 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GtkDragDestInfo *info;
|
||||
GdkDragContext *context;
|
||||
GdkDrop *drop;
|
||||
guint32 time;
|
||||
GdkEventType event_type;
|
||||
|
||||
@@ -407,10 +384,10 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
event_type = gdk_event_get_event_type (event);
|
||||
gdk_event_get_drag_context (event, &context);
|
||||
drop = gdk_event_get_drop (event);
|
||||
time = gdk_event_get_time (event);
|
||||
|
||||
info = gtk_drag_get_dest_info (context, TRUE);
|
||||
info = gtk_drag_get_dest_info (drop, TRUE);
|
||||
|
||||
/* Find the widget for the event */
|
||||
switch ((guint) event_type)
|
||||
@@ -421,7 +398,7 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
case GDK_DRAG_LEAVE:
|
||||
if (info->widget)
|
||||
{
|
||||
gtk_drag_dest_leave (info->widget, context, time);
|
||||
gtk_drag_dest_leave (info->widget, drop, time);
|
||||
gtk_drag_dest_set_widget (info, NULL);
|
||||
}
|
||||
break;
|
||||
@@ -441,7 +418,7 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
*/
|
||||
if (info->widget)
|
||||
{
|
||||
gtk_drag_dest_leave (info->widget, context, time);
|
||||
gtk_drag_dest_leave (info->widget, drop, time);
|
||||
gtk_drag_dest_set_widget (info, NULL);
|
||||
}
|
||||
}
|
||||
@@ -451,8 +428,8 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
gdk_surface_get_position (surface, &tx, &ty);
|
||||
gdk_event_get_root_coords (event, &x_root, &y_root);
|
||||
|
||||
found = gtk_drag_find_widget (toplevel,
|
||||
context,
|
||||
found = gtk_drop_find_widget (toplevel,
|
||||
drop,
|
||||
info,
|
||||
x_root - tx,
|
||||
y_root - ty,
|
||||
@@ -463,14 +440,14 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
|
||||
if (info->widget && !found)
|
||||
{
|
||||
gtk_drag_dest_leave (info->widget, context, time);
|
||||
gtk_drag_dest_leave (info->widget, drop, time);
|
||||
gtk_drag_dest_set_widget (info, NULL);
|
||||
}
|
||||
|
||||
/* Send a reply.
|
||||
*/
|
||||
if (!found)
|
||||
gdk_drag_status (context, 0, time);
|
||||
gdk_drop_status (drop, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -480,8 +457,8 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_drag_find_widget (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gtk_drop_find_widget (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
GtkDragDestInfo *info,
|
||||
gint x,
|
||||
gint y,
|
||||
@@ -531,13 +508,13 @@ gtk_drag_find_widget (GtkWidget *widget,
|
||||
*/
|
||||
if (g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"))
|
||||
{
|
||||
found = callback (widget, context, x, y, time);
|
||||
found = callback (widget, drop, x, y, time);
|
||||
|
||||
/* If so, send a "drag-leave" to the last widget */
|
||||
if (found && info->widget != widget)
|
||||
{
|
||||
if (info->widget)
|
||||
gtk_drag_dest_leave (info->widget, context, time);
|
||||
gtk_drag_dest_leave (info->widget, drop, time);
|
||||
|
||||
gtk_drag_dest_set_widget (info, widget);
|
||||
}
|
||||
@@ -600,20 +577,20 @@ gtk_drag_dest_info_destroy (gpointer data)
|
||||
}
|
||||
|
||||
static GtkDragDestInfo *
|
||||
gtk_drag_get_dest_info (GdkDragContext *context,
|
||||
gboolean create)
|
||||
gtk_drag_get_dest_info (GdkDrop *drop,
|
||||
gboolean create)
|
||||
{
|
||||
GtkDragDestInfo *info;
|
||||
static GQuark info_quark = 0;
|
||||
if (!info_quark)
|
||||
info_quark = g_quark_from_static_string ("gtk-dest-info");
|
||||
|
||||
info = g_object_get_qdata (G_OBJECT (context), info_quark);
|
||||
info = g_object_get_qdata (G_OBJECT (drop), info_quark);
|
||||
if (!info && create)
|
||||
{
|
||||
info = g_slice_new0 (GtkDragDestInfo);
|
||||
info->context = context;
|
||||
g_object_set_qdata_full (G_OBJECT (context), info_quark,
|
||||
info->drop = drop;
|
||||
g_object_set_qdata_full (G_OBJECT (drop), info_quark,
|
||||
info, gtk_drag_dest_info_destroy);
|
||||
}
|
||||
|
||||
@@ -652,7 +629,7 @@ gtk_drag_clear_source_info (GdkDragContext *context)
|
||||
*/
|
||||
static void
|
||||
gtk_drag_dest_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
guint time)
|
||||
{
|
||||
GtkDragDestSite *site;
|
||||
@@ -665,20 +642,19 @@ gtk_drag_dest_leave (GtkWidget *widget,
|
||||
|
||||
if (!(site->flags & GTK_DEST_DEFAULT_MOTION) || site->have_drag ||
|
||||
site->track_motion)
|
||||
g_signal_emit_by_name (widget, "drag-leave", context, time);
|
||||
g_signal_emit_by_name (widget, "drag-leave", drop, time);
|
||||
|
||||
site->have_drag = FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_drag_dest_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_drag_dest_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
{
|
||||
GtkDragDestSite *site;
|
||||
GdkDragAction action = 0;
|
||||
gboolean retval;
|
||||
|
||||
site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
|
||||
@@ -686,24 +662,14 @@ gtk_drag_dest_motion (GtkWidget *widget,
|
||||
|
||||
if (site->track_motion || site->flags & GTK_DEST_DEFAULT_MOTION)
|
||||
{
|
||||
if (gdk_drag_context_get_suggested_action (context) & site->actions)
|
||||
action = gdk_drag_context_get_suggested_action (context);
|
||||
else
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if ((site->actions & (1 << i)) &&
|
||||
(gdk_drag_context_get_actions (context) & (1 << i)))
|
||||
{
|
||||
action = (1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GdkDragAction actions;
|
||||
|
||||
actions = gdk_drop_get_actions (drop);
|
||||
|
||||
if (action && gtk_drag_dest_find_target (widget, context, NULL))
|
||||
if ((actions & site->actions) == 0)
|
||||
actions = 0;
|
||||
|
||||
if (actions && gtk_drag_dest_find_target (widget, drop, NULL))
|
||||
{
|
||||
if (!site->have_drag)
|
||||
{
|
||||
@@ -712,28 +678,28 @@ gtk_drag_dest_motion (GtkWidget *widget,
|
||||
gtk_drag_highlight (widget);
|
||||
}
|
||||
|
||||
gdk_drag_status (context, action, time);
|
||||
gdk_drop_status (drop, site->actions);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_drag_status (context, 0, time);
|
||||
gdk_drop_status (drop, 0);
|
||||
if (!site->track_motion)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (widget, "drag-motion",
|
||||
context, x, y, time, &retval);
|
||||
drop, x, y, &retval);
|
||||
|
||||
return (site->flags & GTK_DEST_DEFAULT_MOTION) ? TRUE : retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_drag_dest_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_drag_dest_drop (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
{
|
||||
GtkDragDestSite *site;
|
||||
GtkDragDestInfo *info;
|
||||
@@ -742,24 +708,24 @@ gtk_drag_dest_drop (GtkWidget *widget,
|
||||
site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
|
||||
g_return_val_if_fail (site != NULL, FALSE);
|
||||
|
||||
info = gtk_drag_get_dest_info (context, FALSE);
|
||||
info = gtk_drag_get_dest_info (drop, FALSE);
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
if (site->flags & GTK_DEST_DEFAULT_DROP)
|
||||
{
|
||||
GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
|
||||
GdkAtom target = gtk_drag_dest_find_target (widget, drop, NULL);
|
||||
|
||||
if (target == NULL)
|
||||
{
|
||||
gtk_drag_finish (context, FALSE, time);
|
||||
gdk_drop_finish (drop, 0);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (widget, "drag-drop",
|
||||
context, x, y, time, &retval);
|
||||
drop, x, y, &retval);
|
||||
|
||||
return (site->flags & GTK_DEST_DEFAULT_DROP) ? TRUE : retval;
|
||||
}
|
||||
@@ -935,8 +901,6 @@ gtk_drag_begin_internal (GtkWidget *widget,
|
||||
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
||||
device = gdk_device_get_associated_device (device);
|
||||
|
||||
source_widgets = g_slist_prepend (source_widgets, widget);
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
gtk_widget_translate_coordinates (widget, toplevel,
|
||||
x, y, &x, &y);
|
||||
@@ -1357,7 +1321,6 @@ gtk_drag_source_info_destroy (GtkDragSourceInfo *info)
|
||||
g_signal_emit_by_name (info->widget, "drag-end", info->context);
|
||||
|
||||
g_object_set_data (G_OBJECT (info->widget), I_("gtk-info"), NULL);
|
||||
source_widgets = g_slist_remove (source_widgets, info->widget);
|
||||
|
||||
g_clear_object (&info->widget);
|
||||
|
||||
|
||||
+2
-7
@@ -41,13 +41,8 @@ G_BEGIN_DECLS
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drag_get_data (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkAtom target,
|
||||
guint32 time_);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drag_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time_);
|
||||
GdkDrop *drop,
|
||||
GdkAtom target);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget *gtk_drag_get_source_widget (GdkDragContext *context);
|
||||
|
||||
+6
-6
@@ -115,7 +115,7 @@ gtk_drag_dest_set_internal (GtkWidget *widget,
|
||||
* behaviors described by @flags make some assumptions, that can conflict
|
||||
* with your own signal handlers. For instance #GTK_DEST_DEFAULT_DROP causes
|
||||
* invokations of gdk_drag_status() in the context of #GtkWidget::drag-motion,
|
||||
* and invokations of gtk_drag_finish() in #GtkWidget::drag-data-received.
|
||||
* and invokations of gdk_drag_finish() in #GtkWidget::drag-data-received.
|
||||
* Especially the later is dramatic, when your own #GtkWidget::drag-motion
|
||||
* handler calls gtk_drag_get_data() to inspect the dragged data.
|
||||
*
|
||||
@@ -380,11 +380,11 @@ gtk_drag_dest_get_track_motion (GtkWidget *widget)
|
||||
/**
|
||||
* gtk_drag_dest_find_target: (method)
|
||||
* @widget: drag destination widget
|
||||
* @context: drag context
|
||||
* @drop: #GdkDrop
|
||||
* @target_list: (allow-none): list of droppable targets, or %NULL to use
|
||||
* gtk_drag_dest_get_target_list (@widget).
|
||||
*
|
||||
* Looks for a match between the supported targets of @context and the
|
||||
* Looks for a match between the supported targets of @drop and the
|
||||
* @dest_target_list, returning the first matching target, otherwise
|
||||
* returning %NULL. @dest_target_list should usually be the return
|
||||
* value from gtk_drag_dest_get_target_list(), but some widgets may
|
||||
@@ -397,11 +397,11 @@ gtk_drag_dest_get_track_motion (GtkWidget *widget)
|
||||
*/
|
||||
const char *
|
||||
gtk_drag_dest_find_target (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GdkContentFormats *target_list)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (GDK_IS_DROP (drop), NULL);
|
||||
|
||||
if (target_list == NULL)
|
||||
target_list = gtk_drag_dest_get_target_list (widget);
|
||||
@@ -410,6 +410,6 @@ gtk_drag_dest_find_target (GtkWidget *widget,
|
||||
return NULL;
|
||||
|
||||
return gdk_content_formats_match_mime_type (target_list,
|
||||
gdk_drag_context_get_formats (context));
|
||||
gdk_drop_get_formats (drop));
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -49,9 +49,9 @@ G_BEGIN_DECLS
|
||||
* @GTK_DEST_DEFAULT_DROP: If set for a widget, when a drop occurs, GTK+ will
|
||||
* will check if the drag matches this widget’s list of possible formats and
|
||||
* actions. If so, GTK+ will call gtk_drag_get_data() on behalf of the widget.
|
||||
* Whether or not the drop is successful, GTK+ will call gtk_drag_finish(). If
|
||||
* Whether or not the drop is successful, GTK+ will call gdk_drag_finish(). If
|
||||
* the action was a move, then if the drag was successful, then %TRUE will be
|
||||
* passed for the @delete parameter to gtk_drag_finish().
|
||||
* passed for the @delete parameter to gdk_drag_finish().
|
||||
* @GTK_DEST_DEFAULT_ALL: If set, specifies that all default actions should
|
||||
* be taken.
|
||||
*
|
||||
@@ -77,7 +77,7 @@ void gtk_drag_dest_unset (GtkWidget *widget);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * gtk_drag_dest_find_target (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GdkContentFormats *target_list);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats* gtk_drag_dest_get_target_list (GtkWidget *widget);
|
||||
|
||||
+54
-50
@@ -437,22 +437,18 @@ static void gtk_entry_display_changed (GtkWidget *widget,
|
||||
GdkDisplay *old_display);
|
||||
|
||||
static gboolean gtk_entry_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static gboolean gtk_entry_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static void gtk_entry_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
GdkDrop *drop);
|
||||
static void gtk_entry_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time);
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data);
|
||||
static void gtk_entry_drag_data_get (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
@@ -8591,9 +8587,8 @@ gtk_entry_drag_end (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_entry_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
gtk_entry_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkEntry *entry = GTK_ENTRY (widget);
|
||||
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
|
||||
@@ -8604,40 +8599,37 @@ gtk_entry_drag_leave (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_entry_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_entry_drag_drop (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkEntry *entry = GTK_ENTRY (widget);
|
||||
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
|
||||
GdkAtom target = NULL;
|
||||
|
||||
if (priv->editable)
|
||||
target = gtk_drag_dest_find_target (widget, context, NULL);
|
||||
target = gtk_drag_dest_find_target (widget, drop, NULL);
|
||||
|
||||
if (target != NULL)
|
||||
{
|
||||
priv->drop_position = gtk_entry_find_position (entry, x + priv->scroll_offset);
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
}
|
||||
else
|
||||
gtk_drag_finish (context, FALSE, time);
|
||||
gdk_drop_finish (drop, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_entry_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_entry_drag_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkEntry *entry = GTK_ENTRY (widget);
|
||||
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
|
||||
GtkWidget *source_widget;
|
||||
GdkDragAction suggested_action;
|
||||
gint new_position, old_position;
|
||||
gint sel1, sel2;
|
||||
@@ -8646,30 +8638,17 @@ gtk_entry_drag_motion (GtkWidget *widget,
|
||||
new_position = gtk_entry_find_position (entry, x + priv->scroll_offset);
|
||||
|
||||
if (priv->editable &&
|
||||
gtk_drag_dest_find_target (widget, context, NULL) != NULL)
|
||||
gtk_drag_dest_find_target (widget, drop, NULL) != NULL)
|
||||
{
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
suggested_action = gdk_drag_context_get_suggested_action (context);
|
||||
suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
|
||||
|
||||
if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &sel1, &sel2) ||
|
||||
new_position < sel1 || new_position > sel2)
|
||||
{
|
||||
if (source_widget == widget)
|
||||
{
|
||||
/* Default to MOVE, unless the user has
|
||||
* pressed ctrl or alt to affect available actions
|
||||
*/
|
||||
if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
|
||||
suggested_action = GDK_ACTION_MOVE;
|
||||
}
|
||||
|
||||
priv->dnd_position = new_position;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (source_widget == widget)
|
||||
suggested_action = 0; /* Can't drop in selection where drag started */
|
||||
|
||||
priv->dnd_position = -1;
|
||||
}
|
||||
}
|
||||
@@ -8683,7 +8662,7 @@ gtk_entry_drag_motion (GtkWidget *widget,
|
||||
if (show_placeholder_text (entry))
|
||||
priv->dnd_position = -1;
|
||||
|
||||
gdk_drag_status (context, suggested_action, time);
|
||||
gdk_drop_status (drop, suggested_action);
|
||||
if (suggested_action == 0)
|
||||
gtk_drag_unhighlight (widget);
|
||||
else
|
||||
@@ -8695,20 +8674,45 @@ gtk_entry_drag_motion (GtkWidget *widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkDragAction
|
||||
gtk_entry_get_action (GtkEntry *entry,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (entry);
|
||||
GdkDragContext *drag = gdk_drop_get_drag (drop);
|
||||
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
|
||||
GdkDragAction actions;
|
||||
|
||||
actions = gdk_drop_get_actions (drop);
|
||||
|
||||
if (source_widget == widget &&
|
||||
actions & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
if (actions & GDK_ACTION_COPY)
|
||||
return GDK_ACTION_COPY;
|
||||
|
||||
if (actions & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_entry_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
GtkEntry *entry = GTK_ENTRY (widget);
|
||||
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
|
||||
GtkEditable *editable = GTK_EDITABLE (widget);
|
||||
GdkDragAction action;
|
||||
gchar *str;
|
||||
|
||||
str = (gchar *) gtk_selection_data_get_text (selection_data);
|
||||
action = gtk_entry_get_action (entry, drop);
|
||||
|
||||
if (str && priv->editable)
|
||||
if (action && str && priv->editable)
|
||||
{
|
||||
gint sel1, sel2;
|
||||
gint length = -1;
|
||||
@@ -8730,12 +8734,12 @@ gtk_entry_drag_data_received (GtkWidget *widget,
|
||||
end_change (entry);
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, TRUE, time);
|
||||
gdk_drop_finish (drop, action);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Drag and drop didn't happen! */
|
||||
gtk_drag_finish (context, FALSE, time);
|
||||
gdk_drop_finish (drop, 0);
|
||||
}
|
||||
|
||||
g_free (str);
|
||||
|
||||
+9
-13
@@ -179,13 +179,11 @@ static void gtk_expander_size_allocate (GtkWidget *widget,
|
||||
static gboolean gtk_expander_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static gboolean gtk_expander_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static void gtk_expander_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
GdkDrop *drop);
|
||||
|
||||
static void gtk_expander_add (GtkContainer *container,
|
||||
GtkWidget *widget);
|
||||
@@ -527,11 +525,10 @@ expand_timeout (gpointer data)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_expander_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_expander_drag_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkExpander *expander = GTK_EXPANDER (widget);
|
||||
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
|
||||
@@ -546,9 +543,8 @@ gtk_expander_drag_motion (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
gtk_expander_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkExpander *expander = GTK_EXPANDER (widget);
|
||||
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
|
||||
|
||||
@@ -252,9 +252,8 @@ static void gtk_file_chooser_button_finalize (GObject *ob
|
||||
/* GtkWidget Functions */
|
||||
static void gtk_file_chooser_button_destroy (GtkWidget *widget);
|
||||
static void gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *data,
|
||||
guint drag_time);
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *data);
|
||||
static void gtk_file_chooser_button_show (GtkWidget *widget);
|
||||
static void gtk_file_chooser_button_hide (GtkWidget *widget);
|
||||
static void gtk_file_chooser_button_map (GtkWidget *widget);
|
||||
@@ -1199,9 +1198,8 @@ dnd_select_folder_get_info_cb (GCancellable *cancellable,
|
||||
|
||||
static void
|
||||
gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *data,
|
||||
guint drag_time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *data)
|
||||
{
|
||||
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget);
|
||||
GtkFileChooserButtonPrivate *priv = button->priv;
|
||||
@@ -1210,11 +1208,10 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
|
||||
|
||||
if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->drag_data_received != NULL)
|
||||
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->drag_data_received (widget,
|
||||
context,
|
||||
data,
|
||||
drag_time);
|
||||
drop,
|
||||
data);
|
||||
|
||||
if (widget == NULL || context == NULL || data == NULL || gtk_selection_data_get_length (data) < 0)
|
||||
if (widget == NULL || gtk_selection_data_get_length (data) < 0)
|
||||
return;
|
||||
|
||||
if (gtk_selection_data_targets_include_uri (data))
|
||||
@@ -1255,7 +1252,7 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
|
||||
g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0);
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, TRUE, drag_time);
|
||||
gdk_drop_finish (drop, GDK_ACTION_COPY);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
+10
-11
@@ -1932,9 +1932,8 @@ out:
|
||||
|
||||
static void
|
||||
file_list_drag_data_received_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time_,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (user_data);
|
||||
@@ -1944,12 +1943,14 @@ file_list_drag_data_received_cb (GtkWidget *widget,
|
||||
GFile *file;
|
||||
|
||||
/* Allow only drags from other widgets; see bug #533891. */
|
||||
if (gtk_drag_get_source_widget (context) == widget)
|
||||
if (gdk_drop_get_drag (drop) &&
|
||||
gtk_drag_get_source_widget (gdk_drop_get_drag (drop)) == widget)
|
||||
{
|
||||
g_signal_stop_emission_by_name (widget, "drag-data-received");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Parse the text/uri-list string, navigate to the first one */
|
||||
uris = gtk_selection_data_get_uris (selection_data);
|
||||
if (uris && uris[0])
|
||||
@@ -1980,10 +1981,9 @@ file_list_drag_data_received_cb (GtkWidget *widget,
|
||||
/* Don't do anything with the drag_drop signal */
|
||||
static gboolean
|
||||
file_list_drag_drop_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time_,
|
||||
GtkFileChooserWidget *impl)
|
||||
{
|
||||
g_signal_stop_emission_by_name (widget, "drag-drop");
|
||||
@@ -1992,22 +1992,21 @@ file_list_drag_drop_cb (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
file_list_drag_begin_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GtkFileChooserWidget *impl)
|
||||
{
|
||||
gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (impl->priv->places_sidebar),
|
||||
TRUE,
|
||||
context);
|
||||
drop);
|
||||
}
|
||||
|
||||
/* Disable the normal tree drag motion handler, it makes it look like you're
|
||||
dropping the dragged item onto a tree item */
|
||||
static gboolean
|
||||
file_list_drag_motion_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time_,
|
||||
GtkFileChooserWidget *impl)
|
||||
{
|
||||
g_signal_stop_emission_by_name (widget, "drag-motion");
|
||||
@@ -2016,7 +2015,7 @@ file_list_drag_motion_cb (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
file_list_drag_end_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFileChooserWidget *impl;
|
||||
@@ -2024,7 +2023,7 @@ file_list_drag_end_cb (GtkWidget *widget,
|
||||
impl = GTK_FILE_CHOOSER_WIDGET (user_data);
|
||||
gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (impl->priv->places_sidebar),
|
||||
FALSE,
|
||||
context);
|
||||
drop);
|
||||
}
|
||||
|
||||
/* Sensitizes the "Copy file’s location" and other context menu items if there is actually
|
||||
|
||||
+79
-73
@@ -289,22 +289,18 @@ static void gtk_icon_view_drag_data_delete (GtkWidget *widget,
|
||||
|
||||
/* Target side drag signals */
|
||||
static void gtk_icon_view_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
GdkDrop *drop);
|
||||
static gboolean gtk_icon_view_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static gboolean gtk_icon_view_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static void gtk_icon_view_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time);
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data);
|
||||
static gboolean gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
|
||||
double x,
|
||||
double y,
|
||||
@@ -5681,18 +5677,18 @@ gtk_icon_view_get_item_padding (GtkIconView *icon_view)
|
||||
* since the data doesn’t result from a drop.
|
||||
*/
|
||||
static void
|
||||
set_status_pending (GdkDragContext *context,
|
||||
set_status_pending (GdkDrop *drop,
|
||||
GdkDragAction suggested_action)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (context),
|
||||
g_object_set_data (G_OBJECT (drop),
|
||||
I_("gtk-icon-view-status-pending"),
|
||||
GINT_TO_POINTER (suggested_action));
|
||||
}
|
||||
|
||||
static GdkDragAction
|
||||
get_status_pending (GdkDragContext *context)
|
||||
get_status_pending (GdkDrop *drop)
|
||||
{
|
||||
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
|
||||
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drop),
|
||||
"gtk-icon-view-status-pending"));
|
||||
}
|
||||
|
||||
@@ -5752,7 +5748,7 @@ dest_row_free (gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
set_dest_row (GdkDragContext *context,
|
||||
set_dest_row (GdkDrop *drop,
|
||||
GtkTreeModel *model,
|
||||
GtkTreePath *dest_row,
|
||||
gboolean empty_view_drop,
|
||||
@@ -5762,7 +5758,7 @@ set_dest_row (GdkDragContext *context,
|
||||
|
||||
if (!dest_row)
|
||||
{
|
||||
g_object_set_data_full (G_OBJECT (context),
|
||||
g_object_set_data_full (G_OBJECT (drop),
|
||||
I_("gtk-icon-view-dest-row"),
|
||||
NULL, NULL);
|
||||
return;
|
||||
@@ -5773,17 +5769,17 @@ set_dest_row (GdkDragContext *context,
|
||||
dr->dest_row = gtk_tree_row_reference_new (model, dest_row);
|
||||
dr->empty_view_drop = empty_view_drop;
|
||||
dr->drop_append_mode = drop_append_mode;
|
||||
g_object_set_data_full (G_OBJECT (context),
|
||||
g_object_set_data_full (G_OBJECT (drop),
|
||||
I_("gtk-icon-view-dest-row"),
|
||||
dr, (GDestroyNotify) dest_row_free);
|
||||
}
|
||||
|
||||
static GtkTreePath*
|
||||
get_dest_row (GdkDragContext *context)
|
||||
get_dest_row (GdkDrop *drop)
|
||||
{
|
||||
DestRow *dr;
|
||||
|
||||
dr = g_object_get_data (G_OBJECT (context), "gtk-icon-view-dest-row");
|
||||
dr = g_object_get_data (G_OBJECT (drop), "gtk-icon-view-dest-row");
|
||||
|
||||
if (dr)
|
||||
{
|
||||
@@ -5880,7 +5876,7 @@ drag_scroll_timeout (gpointer data)
|
||||
|
||||
static gboolean
|
||||
set_destination (GtkIconView *icon_view,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
GdkDragAction *suggested_action,
|
||||
@@ -5913,7 +5909,7 @@ set_destination (GtkIconView *icon_view,
|
||||
return FALSE; /* no longer a drop site */
|
||||
}
|
||||
|
||||
*target = gtk_drag_dest_find_target (widget, context,
|
||||
*target = gtk_drag_dest_find_target (widget, drop,
|
||||
gtk_drag_dest_get_target_list (widget));
|
||||
if (*target == NULL)
|
||||
return FALSE;
|
||||
@@ -5965,19 +5961,7 @@ set_destination (GtkIconView *icon_view,
|
||||
out:
|
||||
if (can_drop)
|
||||
{
|
||||
GtkWidget *source_widget;
|
||||
|
||||
*suggested_action = gdk_drag_context_get_suggested_action (context);
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
|
||||
if (source_widget == widget)
|
||||
{
|
||||
/* Default to MOVE, unless the user has
|
||||
* pressed ctrl or shift to affect available actions
|
||||
*/
|
||||
if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
|
||||
*suggested_action = GDK_ACTION_MOVE;
|
||||
}
|
||||
*suggested_action = GDK_ACTION_ALL;
|
||||
|
||||
gtk_icon_view_set_drag_dest_item (GTK_ICON_VIEW (widget),
|
||||
path, pos);
|
||||
@@ -6218,9 +6202,8 @@ gtk_icon_view_drag_data_delete (GtkWidget *widget,
|
||||
|
||||
/* Target side drag signals */
|
||||
static void
|
||||
gtk_icon_view_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
gtk_icon_view_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkIconView *icon_view;
|
||||
|
||||
@@ -6235,11 +6218,10 @@ gtk_icon_view_drag_leave (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_icon_view_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_icon_view_drag_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkTreePath *path = NULL;
|
||||
GtkIconViewDropPosition pos;
|
||||
@@ -6250,7 +6232,7 @@ gtk_icon_view_drag_motion (GtkWidget *widget,
|
||||
|
||||
icon_view = GTK_ICON_VIEW (widget);
|
||||
|
||||
if (!set_destination (icon_view, context, x, y, &suggested_action, &target))
|
||||
if (!set_destination (icon_view, drop, x, y, &suggested_action, &target))
|
||||
return FALSE;
|
||||
|
||||
icon_view->priv->event_last_x = x;
|
||||
@@ -6264,7 +6246,7 @@ gtk_icon_view_drag_motion (GtkWidget *widget,
|
||||
if (path == NULL && !empty)
|
||||
{
|
||||
/* Can't drop here. */
|
||||
gdk_drag_status (context, 0, time);
|
||||
gdk_drop_status (drop, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6279,13 +6261,13 @@ gtk_icon_view_drag_motion (GtkWidget *widget,
|
||||
/* Request data so we can use the source row when
|
||||
* determining whether to accept the drop
|
||||
*/
|
||||
set_status_pending (context, suggested_action);
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
set_status_pending (drop, suggested_action);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_status_pending (context, 0);
|
||||
gdk_drag_status (context, suggested_action, time);
|
||||
set_status_pending (drop, 0);
|
||||
gdk_drop_status (drop, suggested_action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6296,11 +6278,10 @@ gtk_icon_view_drag_motion (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_icon_view_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_icon_view_drag_drop (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkIconView *icon_view;
|
||||
GtkTreePath *path;
|
||||
@@ -6320,7 +6301,7 @@ gtk_icon_view_drag_drop (GtkWidget *widget,
|
||||
if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-drop"))
|
||||
return FALSE;
|
||||
|
||||
if (!set_destination (icon_view, context, x, y, &suggested_action, &target))
|
||||
if (!set_destination (icon_view, drop, x, y, &suggested_action, &target))
|
||||
return FALSE;
|
||||
|
||||
path = get_logical_destination (icon_view, &drop_append_mode);
|
||||
@@ -6330,8 +6311,8 @@ gtk_icon_view_drag_drop (GtkWidget *widget,
|
||||
/* in case a motion had requested drag data, change things so we
|
||||
* treat drag data receives as a drop.
|
||||
*/
|
||||
set_status_pending (context, 0);
|
||||
set_dest_row (context, model, path,
|
||||
set_status_pending (drop, 0);
|
||||
set_dest_row (drop, model, path,
|
||||
icon_view->priv->empty_view_drop, drop_append_mode);
|
||||
}
|
||||
|
||||
@@ -6343,21 +6324,45 @@ gtk_icon_view_drag_drop (GtkWidget *widget,
|
||||
|
||||
if (target != NULL)
|
||||
{
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkDragAction
|
||||
gtk_icon_view_get_action (GtkWidget *treeview,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GdkDragContext *drag = gdk_drop_get_drag (drop);
|
||||
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
|
||||
GdkDragAction actions;
|
||||
|
||||
actions = gdk_drop_get_actions (drop);
|
||||
|
||||
if (source_widget == treeview &&
|
||||
actions & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
if (actions & GDK_ACTION_COPY)
|
||||
return GDK_ACTION_COPY;
|
||||
|
||||
if (actions & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
if (actions & GDK_ACTION_LINK)
|
||||
return GDK_ACTION_LINK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_icon_view_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
gboolean accepted = FALSE;
|
||||
GtkTreeModel *model;
|
||||
GtkIconView *icon_view;
|
||||
GtkTreePath *dest_row;
|
||||
@@ -6373,7 +6378,7 @@ gtk_icon_view_drag_data_received (GtkWidget *widget,
|
||||
if (!icon_view->priv->dest_set)
|
||||
return;
|
||||
|
||||
suggested_action = get_status_pending (context);
|
||||
suggested_action = get_status_pending (drop);
|
||||
|
||||
if (suggested_action)
|
||||
{
|
||||
@@ -6395,7 +6400,7 @@ gtk_icon_view_drag_data_received (GtkWidget *widget,
|
||||
suggested_action = 0;
|
||||
}
|
||||
|
||||
gdk_drag_status (context, suggested_action, time);
|
||||
gdk_drop_status (drop, suggested_action);
|
||||
|
||||
if (path)
|
||||
gtk_tree_path_free (path);
|
||||
@@ -6409,27 +6414,28 @@ gtk_icon_view_drag_data_received (GtkWidget *widget,
|
||||
}
|
||||
|
||||
|
||||
dest_row = get_dest_row (context);
|
||||
dest_row = get_dest_row (drop);
|
||||
|
||||
if (dest_row == NULL)
|
||||
return;
|
||||
|
||||
if (gtk_selection_data_get_length (selection_data) >= 0)
|
||||
{
|
||||
if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
|
||||
dest_row,
|
||||
selection_data))
|
||||
accepted = TRUE;
|
||||
suggested_action = gtk_icon_view_get_action (widget, drop);
|
||||
|
||||
if (suggested_action &&
|
||||
!gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
|
||||
dest_row,
|
||||
selection_data))
|
||||
suggested_action = 0;
|
||||
}
|
||||
|
||||
gtk_drag_finish (context,
|
||||
accepted,
|
||||
time);
|
||||
gdk_drop_finish (drop, suggested_action);
|
||||
|
||||
gtk_tree_path_free (dest_row);
|
||||
|
||||
/* drop dest_row */
|
||||
set_dest_row (context, NULL, NULL, FALSE, FALSE);
|
||||
set_dest_row (drop, NULL, NULL, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/* Drag-and-Drop support */
|
||||
|
||||
+3
-5
@@ -230,8 +230,7 @@ static void gtk_list_box_size_allocate (GtkWidget
|
||||
const GtkAllocation *allocation,
|
||||
int baseline);
|
||||
static void gtk_list_box_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time_);
|
||||
GdkDrop *drop);
|
||||
static void gtk_list_box_activate_cursor_row (GtkListBox *box);
|
||||
static void gtk_list_box_toggle_cursor_row (GtkListBox *box);
|
||||
static void gtk_list_box_move_cursor (GtkListBox *box,
|
||||
@@ -2721,9 +2720,8 @@ gtk_list_box_drag_highlight_row (GtkListBox *box,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_box_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time_)
|
||||
gtk_list_box_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
gtk_list_box_drag_unhighlight_row (GTK_LIST_BOX (widget));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ BOOLEAN:ENUM,DOUBLE
|
||||
BOOLEAN:ENUM,INT
|
||||
BOOLEAN:OBJECT
|
||||
BOOLEAN:OBJECT,UINT,FLAGS
|
||||
BOOLEAN:OBJECT,INT,INT,UINT
|
||||
BOOLEAN:OBJECT,INT,INT
|
||||
BOOLEAN:OBJECT,STRING,STRING,BOXED
|
||||
BOOLEAN:OBJECT,BOXED
|
||||
BOOLEAN:OBJECT,OBJECT,BOXED
|
||||
@@ -73,6 +73,7 @@ VOID:INT,INT
|
||||
VOID:INT,INT,BOXED
|
||||
VOID:INT,INT,INT
|
||||
VOID:OBJECT,BOOLEAN
|
||||
VOID:OBJECT,BOXED
|
||||
VOID:OBJECT,BOXED,BOXED
|
||||
VOID:OBJECT,BOXED,UINT
|
||||
VOID:OBJECT,BOXED,BOOLEAN,BOOLEAN
|
||||
|
||||
+32
-37
@@ -393,26 +393,22 @@ static gboolean gtk_notebook_drag_failed (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkDragResult result);
|
||||
static gboolean gtk_notebook_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static void gtk_notebook_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
GdkDrop *drop);
|
||||
static gboolean gtk_notebook_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static void gtk_notebook_drag_data_get (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *data,
|
||||
guint time);
|
||||
static void gtk_notebook_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *data,
|
||||
guint time);
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *data);
|
||||
static void gtk_notebook_direction_changed (GtkWidget *widget,
|
||||
GtkTextDirection previous_direction);
|
||||
|
||||
@@ -3055,11 +3051,10 @@ gtk_notebook_switch_tab_timeout (gpointer data)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_notebook_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_notebook_drag_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
|
||||
GtkNotebookPrivate *priv = notebook->priv;
|
||||
@@ -3074,14 +3069,14 @@ gtk_notebook_drag_motion (GtkWidget *widget,
|
||||
{
|
||||
priv->click_child = arrow;
|
||||
gtk_notebook_set_scroll_timer (notebook);
|
||||
gdk_drag_status (context, 0, time);
|
||||
gdk_drop_status (drop, 0);
|
||||
|
||||
retval = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
stop_scrolling (notebook);
|
||||
target = gtk_drag_dest_find_target (widget, context, NULL);
|
||||
target = gtk_drag_dest_find_target (widget, drop, NULL);
|
||||
tab_target = g_intern_static_string ("GTK_NOTEBOOK_TAB");
|
||||
|
||||
if (target == tab_target)
|
||||
@@ -3092,7 +3087,7 @@ gtk_notebook_drag_motion (GtkWidget *widget,
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
source = GTK_NOTEBOOK (gtk_drag_get_source_widget (context));
|
||||
source = GTK_NOTEBOOK (gtk_drag_get_source_widget (gdk_drop_get_drag (drop)));
|
||||
g_assert (source->priv->cur_page != NULL);
|
||||
source_child = source->priv->cur_page->child;
|
||||
|
||||
@@ -3103,14 +3098,14 @@ gtk_notebook_drag_motion (GtkWidget *widget,
|
||||
!(widget == source_child ||
|
||||
gtk_widget_is_ancestor (widget, source_child)))
|
||||
{
|
||||
gdk_drag_status (context, GDK_ACTION_MOVE, time);
|
||||
gdk_drop_status (drop, GDK_ACTION_MOVE);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* it's a tab, but doesn't share
|
||||
* ID with this notebook */
|
||||
gdk_drag_status (context, 0, time);
|
||||
gdk_drop_status (drop, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3144,9 +3139,8 @@ gtk_notebook_drag_motion (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_notebook_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
gtk_notebook_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
|
||||
|
||||
@@ -3155,23 +3149,22 @@ gtk_notebook_drag_leave (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_notebook_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_notebook_drag_drop (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
|
||||
GdkAtom target, tab_target;
|
||||
|
||||
target = gtk_drag_dest_find_target (widget, context, NULL);
|
||||
target = gtk_drag_dest_find_target (widget, drop, NULL);
|
||||
tab_target = g_intern_static_string ("GTK_NOTEBOOK_TAB");
|
||||
|
||||
if (target == tab_target)
|
||||
{
|
||||
notebook->priv->mouse_x = x;
|
||||
notebook->priv->mouse_y = y;
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -3283,27 +3276,29 @@ gtk_notebook_drag_data_get (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
gtk_notebook_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *data,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *data)
|
||||
{
|
||||
GtkNotebook *notebook;
|
||||
GdkDragContext *drag;
|
||||
GtkWidget *source_widget;
|
||||
GtkWidget **child;
|
||||
|
||||
notebook = GTK_NOTEBOOK (widget);
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
drag = gdk_drop_get_drag (drop);
|
||||
source_widget = gtk_drag_get_source_widget (drag);
|
||||
|
||||
if (source_widget &&
|
||||
(gdk_drop_get_actions (drop) & GDK_ACTION_MOVE) &&
|
||||
gtk_selection_data_get_target (data) == g_intern_static_string ("GTK_NOTEBOOK_TAB"))
|
||||
{
|
||||
child = (void*) gtk_selection_data_get_data (data);
|
||||
|
||||
do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, *child);
|
||||
gtk_drag_finish (context, TRUE, time);
|
||||
gdk_drop_finish (drop, GDK_ACTION_MOVE);
|
||||
}
|
||||
else
|
||||
gtk_drag_finish (context, FALSE, time);
|
||||
gdk_drop_finish (drop, 0);
|
||||
}
|
||||
|
||||
/* Private GtkContainer Methods :
|
||||
|
||||
+55
-59
@@ -377,14 +377,14 @@ emit_unmount_operation (GtkPlacesSidebar *sidebar,
|
||||
|
||||
static GdkDragAction
|
||||
emit_drag_action_requested (GtkPlacesSidebar *sidebar,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GFile *dest_file,
|
||||
GList *source_file_list)
|
||||
{
|
||||
GdkDragAction ret_action = 0;
|
||||
|
||||
g_signal_emit (sidebar, places_sidebar_signals[DRAG_ACTION_REQUESTED], 0,
|
||||
context, dest_file, source_file_list, &ret_action);
|
||||
drop, dest_file, source_file_list, &ret_action);
|
||||
|
||||
return ret_action;
|
||||
}
|
||||
@@ -1512,7 +1512,7 @@ update_places (GtkPlacesSidebar *sidebar)
|
||||
static gboolean
|
||||
check_valid_drop_target (GtkPlacesSidebar *sidebar,
|
||||
GtkSidebarRow *row,
|
||||
GdkDragContext *context)
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkPlacesSidebarPlaceType place_type;
|
||||
GtkPlacesSidebarSectionType section_type;
|
||||
@@ -1568,12 +1568,12 @@ check_valid_drop_target (GtkPlacesSidebar *sidebar,
|
||||
else
|
||||
{
|
||||
/* Dragging a file */
|
||||
if (context)
|
||||
if (drop)
|
||||
{
|
||||
if (uri != NULL)
|
||||
{
|
||||
dest_file = g_file_new_for_uri (uri);
|
||||
drag_action = emit_drag_action_requested (sidebar, context, dest_file, sidebar->drag_list);
|
||||
drag_action = emit_drag_action_requested (sidebar, drop, dest_file, sidebar->drag_list);
|
||||
valid = drag_action > 0;
|
||||
|
||||
g_object_unref (dest_file);
|
||||
@@ -1585,8 +1585,8 @@ check_valid_drop_target (GtkPlacesSidebar *sidebar,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We cannot discern if it is valid or not because there is not drag
|
||||
* context available to ask the client.
|
||||
/* We cannot discern if it is valid or not because there is not drop
|
||||
* available to ask the client.
|
||||
* Simply make insensitive the drop targets we know are not valid for
|
||||
* files, that are the ones remaining.
|
||||
*/
|
||||
@@ -1601,7 +1601,7 @@ check_valid_drop_target (GtkPlacesSidebar *sidebar,
|
||||
static void
|
||||
update_possible_drop_targets (GtkPlacesSidebar *sidebar,
|
||||
gboolean dragging,
|
||||
GdkDragContext *context)
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GList *rows;
|
||||
GList *l;
|
||||
@@ -1611,7 +1611,7 @@ update_possible_drop_targets (GtkPlacesSidebar *sidebar,
|
||||
|
||||
for (l = rows; l != NULL; l = l->next)
|
||||
{
|
||||
sensitive = !dragging || check_valid_drop_target (sidebar, GTK_SIDEBAR_ROW (l->data), context);
|
||||
sensitive = !dragging || check_valid_drop_target (sidebar, GTK_SIDEBAR_ROW (l->data), drop);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (l->data), sensitive);
|
||||
}
|
||||
|
||||
@@ -1620,17 +1620,19 @@ update_possible_drop_targets (GtkPlacesSidebar *sidebar,
|
||||
|
||||
static gboolean
|
||||
get_drag_data (GtkWidget *list_box,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkListBoxRow *row)
|
||||
{
|
||||
GdkAtom target;
|
||||
|
||||
target = gtk_drag_dest_find_target (list_box, context, NULL);
|
||||
target = gtk_drag_dest_find_target (list_box, drop, NULL);
|
||||
|
||||
if (target == NULL)
|
||||
return FALSE;
|
||||
|
||||
gtk_drag_get_data (list_box, context, target, time);
|
||||
if (row)
|
||||
g_object_set_data_full (G_OBJECT (drop), "places-sidebar-row", g_object_ref (row), g_object_unref);
|
||||
gtk_drag_get_data (list_box, drop, target);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1651,7 +1653,7 @@ free_drag_data (GtkPlacesSidebar *sidebar)
|
||||
static void
|
||||
start_drop_feedback (GtkPlacesSidebar *sidebar,
|
||||
GtkSidebarRow *row,
|
||||
GdkDragContext *context)
|
||||
GdkDrop *drop)
|
||||
{
|
||||
if (sidebar->drag_data_info != DND_GTK_SIDEBAR_ROW)
|
||||
{
|
||||
@@ -1661,7 +1663,7 @@ start_drop_feedback (GtkPlacesSidebar *sidebar,
|
||||
sidebar->drop_state = DROP_STATE_NEW_BOOKMARK_ARMED;
|
||||
}
|
||||
|
||||
update_possible_drop_targets (sidebar, TRUE, context);
|
||||
update_possible_drop_targets (sidebar, TRUE, drop);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1763,12 +1765,11 @@ create_placeholder_row (GtkPlacesSidebar *sidebar)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drag_motion_callback (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time,
|
||||
gpointer user_data)
|
||||
drag_motion_callback (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint action;
|
||||
GtkListBoxRow *row;
|
||||
@@ -1786,11 +1787,11 @@ drag_motion_callback (GtkWidget *widget,
|
||||
|
||||
/* Nothing to do if no drag data */
|
||||
if (!sidebar->drag_data_received &&
|
||||
!get_drag_data (sidebar->list_box, context, time))
|
||||
!get_drag_data (sidebar->list_box, drop, row))
|
||||
goto out;
|
||||
|
||||
/* Nothing to do if the target is not valid drop destination */
|
||||
if (!check_valid_drop_target (sidebar, GTK_SIDEBAR_ROW (row), context))
|
||||
if (!check_valid_drop_target (sidebar, GTK_SIDEBAR_ROW (row), drop))
|
||||
goto out;
|
||||
|
||||
if (sidebar->drag_data_received &&
|
||||
@@ -1877,7 +1878,7 @@ drag_motion_callback (GtkWidget *widget,
|
||||
{
|
||||
GFile *dest_file = g_file_new_for_uri (drop_target_uri);
|
||||
|
||||
action = emit_drag_action_requested (sidebar, context, dest_file, sidebar->drag_list);
|
||||
action = emit_drag_action_requested (sidebar, drop, dest_file, sidebar->drag_list);
|
||||
|
||||
g_object_unref (dest_file);
|
||||
}
|
||||
@@ -1888,11 +1889,11 @@ drag_motion_callback (GtkWidget *widget,
|
||||
}
|
||||
|
||||
out:
|
||||
start_drop_feedback (sidebar, GTK_SIDEBAR_ROW (row), context);
|
||||
start_drop_feedback (sidebar, GTK_SIDEBAR_ROW (row), drop);
|
||||
|
||||
g_signal_stop_emission_by_name (sidebar->list_box, "drag-motion");
|
||||
|
||||
gdk_drag_status (context, action, time);
|
||||
gdk_drop_status (drop, action);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1981,20 +1982,17 @@ drag_data_get_callback (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
drag_data_received_callback (GtkWidget *list_box,
|
||||
GdkDragContext *context,
|
||||
int x,
|
||||
int y,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint target_order_index;
|
||||
GtkPlacesSidebarPlaceType target_place_type;
|
||||
GtkPlacesSidebarSectionType target_section_type;
|
||||
gchar *target_uri;
|
||||
gboolean success;
|
||||
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
|
||||
GtkListBoxRow *target_row;
|
||||
GdkDragAction real_action;
|
||||
|
||||
if (!sidebar->drag_data_received)
|
||||
{
|
||||
@@ -2024,8 +2022,7 @@ drag_data_received_callback (GtkWidget *list_box,
|
||||
if (!sidebar->drop_occurred)
|
||||
return;
|
||||
|
||||
target_row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (sidebar->list_box), y);
|
||||
|
||||
target_row = g_object_get_data (G_OBJECT (drop), "places-sidebar-row");
|
||||
if (target_row == NULL)
|
||||
return;
|
||||
|
||||
@@ -2036,9 +2033,9 @@ drag_data_received_callback (GtkWidget *list_box,
|
||||
"uri", &target_uri,
|
||||
NULL);
|
||||
|
||||
success = FALSE;
|
||||
real_action = 0;
|
||||
|
||||
if (!check_valid_drop_target (sidebar, GTK_SIDEBAR_ROW (target_row), context))
|
||||
if (!check_valid_drop_target (sidebar, GTK_SIDEBAR_ROW (target_row), drop))
|
||||
goto out;
|
||||
|
||||
if (sidebar->drag_data_info == DND_GTK_SIDEBAR_ROW)
|
||||
@@ -2051,20 +2048,19 @@ drag_data_received_callback (GtkWidget *list_box,
|
||||
source_row = (void*) gtk_selection_data_get_data (selection_data);
|
||||
|
||||
reorder_bookmarks (sidebar, GTK_SIDEBAR_ROW (*source_row), target_order_index);
|
||||
success = TRUE;
|
||||
real_action = GDK_ACTION_MOVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dropping URIs! */
|
||||
GdkDragAction real_action;
|
||||
gchar **uris;
|
||||
GList *source_file_list;
|
||||
|
||||
/* file transfer requested */
|
||||
real_action = gdk_drag_context_get_selected_action (context);
|
||||
real_action = gdk_drop_get_actions (drop);
|
||||
|
||||
if (real_action == GDK_ACTION_ASK)
|
||||
real_action = emit_drag_action_ask (sidebar, gdk_drag_context_get_actions (context));
|
||||
if (!gdk_drag_action_is_unique (real_action))
|
||||
real_action = emit_drag_action_ask (sidebar, real_action);
|
||||
|
||||
if (real_action > 0)
|
||||
{
|
||||
@@ -2086,7 +2082,6 @@ drag_data_received_callback (GtkWidget *list_box,
|
||||
g_object_unref (dest_file);
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
g_list_free_full (source_file_list, g_object_unref);
|
||||
g_strfreev (uris);
|
||||
}
|
||||
@@ -2094,7 +2089,8 @@ drag_data_received_callback (GtkWidget *list_box,
|
||||
|
||||
out:
|
||||
sidebar->drop_occurred = FALSE;
|
||||
gtk_drag_finish (context, success, time);
|
||||
g_object_set_data (G_OBJECT (drop), "places-sidebar-row", NULL);
|
||||
gdk_drop_finish (drop, real_action);
|
||||
stop_drop_feedback (sidebar);
|
||||
g_free (target_uri);
|
||||
}
|
||||
@@ -2126,16 +2122,15 @@ drag_end_callback (GtkWidget *widget,
|
||||
* we build new drag data in drag_data_received.
|
||||
*/
|
||||
static void
|
||||
drag_leave_callback (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time,
|
||||
gpointer user_data)
|
||||
drag_leave_callback (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
|
||||
|
||||
if (sidebar->drop_state != DROP_STATE_NEW_BOOKMARK_ARMED_PERMANENT)
|
||||
{
|
||||
update_possible_drop_targets (sidebar, FALSE, context);
|
||||
update_possible_drop_targets (sidebar, FALSE, drop);
|
||||
gtk_sidebar_row_hide (GTK_SIDEBAR_ROW (sidebar->new_bookmark_row), FALSE);
|
||||
sidebar->drop_state = DROP_STATE_NORMAL;
|
||||
}
|
||||
@@ -2146,18 +2141,19 @@ drag_leave_callback (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drag_drop_callback (GtkWidget *list_box,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time,
|
||||
gpointer user_data)
|
||||
drag_drop_callback (GtkWidget *list_box,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
gpointer user_data)
|
||||
{
|
||||
gboolean retval = FALSE;
|
||||
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
|
||||
GtkListBoxRow *row;
|
||||
|
||||
row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (sidebar->list_box), y);
|
||||
sidebar->drop_occurred = TRUE;
|
||||
retval = get_drag_data (sidebar->list_box, context, time);
|
||||
retval = get_drag_data (sidebar->list_box, drop, row);
|
||||
g_signal_stop_emission_by_name (sidebar->list_box, "drag-drop");
|
||||
|
||||
return retval;
|
||||
@@ -4486,7 +4482,7 @@ gtk_places_sidebar_class_init (GtkPlacesSidebarClass *class)
|
||||
/*
|
||||
* GtkPlacesSidebar::drag-action-requested:
|
||||
* @sidebar: the object which received the signal.
|
||||
* @context: (type Gdk.DragContext): #GdkDragContext with information about the drag operation
|
||||
* @drop: (type Gdk.Drop): #GdkDrop with information about the drag operation
|
||||
* @dest_file: (type Gio.File): #GFile with the tentative location that is being hovered for a drop
|
||||
* @source_file_list: (type GLib.List) (element-type GFile) (transfer none):
|
||||
* List of #GFile that are being dragged
|
||||
@@ -4513,7 +4509,7 @@ gtk_places_sidebar_class_init (GtkPlacesSidebarClass *class)
|
||||
NULL, NULL,
|
||||
_gtk_marshal_INT__OBJECT_OBJECT_POINTER,
|
||||
G_TYPE_INT, 3,
|
||||
GDK_TYPE_DRAG_CONTEXT,
|
||||
GDK_TYPE_DROP,
|
||||
G_TYPE_OBJECT,
|
||||
G_TYPE_POINTER /* GList of GFile */ );
|
||||
|
||||
@@ -5316,7 +5312,7 @@ gtk_places_sidebar_get_nth_bookmark (GtkPlacesSidebar *sidebar,
|
||||
* gtk_places_sidebar_set_drop_targets_visible:
|
||||
* @sidebar: a places sidebar.
|
||||
* @visible: whether to show the valid targets or not.
|
||||
* @context: drag context used to ask the source about the action that wants to
|
||||
* @drop: #GdkDrop used to ask the source about the action that wants to
|
||||
* perform, so hints are more accurate.
|
||||
*
|
||||
* Make the GtkPlacesSidebar show drop targets, so it can show the available
|
||||
@@ -5332,12 +5328,12 @@ gtk_places_sidebar_get_nth_bookmark (GtkPlacesSidebar *sidebar,
|
||||
void
|
||||
gtk_places_sidebar_set_drop_targets_visible (GtkPlacesSidebar *sidebar,
|
||||
gboolean visible,
|
||||
GdkDragContext *context)
|
||||
GdkDrop *drop)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
sidebar->drop_state = DROP_STATE_NEW_BOOKMARK_ARMED_PERMANENT;
|
||||
start_drop_feedback (sidebar, NULL, context);
|
||||
start_drop_feedback (sidebar, NULL, drop);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -103,7 +103,7 @@ GFile * gtk_places_sidebar_get_nth_bookmark (GtkPlacesSideb
|
||||
gint n);
|
||||
void gtk_places_sidebar_set_drop_targets_visible (GtkPlacesSidebar *sidebar,
|
||||
gboolean visible,
|
||||
GdkDragContext *context);
|
||||
GdkDrop *drop);
|
||||
gboolean gtk_places_sidebar_get_show_trash (GtkPlacesSidebar *sidebar);
|
||||
void gtk_places_sidebar_set_show_trash (GtkPlacesSidebar *sidebar,
|
||||
gboolean show_trash);
|
||||
|
||||
@@ -291,11 +291,10 @@ gtk_stack_switcher_switch_timeout (gpointer data)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_stack_switcher_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_stack_switcher_drag_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkStackSwitcher *self = GTK_STACK_SWITCHER (widget);
|
||||
GtkStackSwitcherPrivate *priv;
|
||||
@@ -335,9 +334,8 @@ gtk_stack_switcher_drag_motion (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_stack_switcher_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
gtk_stack_switcher_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkStackSwitcher *self = GTK_STACK_SWITCHER (widget);
|
||||
|
||||
|
||||
+57
-60
@@ -429,22 +429,18 @@ static void gtk_text_view_drag_data_delete (GtkWidget *widget,
|
||||
|
||||
/* Target side drag signals */
|
||||
static void gtk_text_view_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
GdkDrop *drop);
|
||||
static gboolean gtk_text_view_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static gboolean gtk_text_view_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static void gtk_text_view_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time);
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data);
|
||||
|
||||
static gboolean gtk_text_view_popup_menu (GtkWidget *widget);
|
||||
|
||||
@@ -7698,9 +7694,8 @@ gtk_text_view_drag_data_delete (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_view_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
gtk_text_view_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkTextView *text_view;
|
||||
GtkTextViewPrivate *priv;
|
||||
@@ -7721,11 +7716,10 @@ gtk_text_view_drag_leave (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_text_view_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_text_view_drag_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkTextIter newplace;
|
||||
GtkTextView *text_view;
|
||||
@@ -7735,7 +7729,7 @@ gtk_text_view_drag_motion (GtkWidget *widget,
|
||||
GdkRectangle target_rect;
|
||||
gint bx, by;
|
||||
GdkAtom target;
|
||||
GdkDragAction suggested_action = 0;
|
||||
gboolean can_accept = FALSE;
|
||||
|
||||
text_view = GTK_TEXT_VIEW (widget);
|
||||
priv = text_view->priv;
|
||||
@@ -7757,7 +7751,7 @@ gtk_text_view_drag_motion (GtkWidget *widget,
|
||||
&newplace,
|
||||
bx, by);
|
||||
|
||||
target = gtk_drag_dest_find_target (widget, context,
|
||||
target = gtk_drag_dest_find_target (widget, drop,
|
||||
gtk_drag_dest_get_target_list (widget));
|
||||
|
||||
if (target == NULL)
|
||||
@@ -7773,37 +7767,17 @@ gtk_text_view_drag_motion (GtkWidget *widget,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_text_iter_can_insert (&newplace, priv->editable))
|
||||
{
|
||||
GtkWidget *source_widget;
|
||||
|
||||
suggested_action = gdk_drag_context_get_suggested_action (context);
|
||||
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
|
||||
if (source_widget == widget)
|
||||
{
|
||||
/* Default to MOVE, unless the user has
|
||||
* pressed ctrl or alt to affect available actions
|
||||
*/
|
||||
if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
|
||||
suggested_action = GDK_ACTION_MOVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Can't drop here. */
|
||||
}
|
||||
can_accept = gtk_text_iter_can_insert (&newplace, priv->editable);
|
||||
}
|
||||
|
||||
if (suggested_action != 0)
|
||||
if (can_accept)
|
||||
{
|
||||
gtk_text_mark_set_visible (priv->dnd_mark, cursor_visible (text_view));
|
||||
gdk_drag_status (context, suggested_action, time);
|
||||
gdk_drop_status (drop, GDK_ACTION_COPY | GDK_ACTION_MOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_drag_status (context, 0, time);
|
||||
gdk_drop_status (drop, 0);
|
||||
gtk_text_mark_set_visible (priv->dnd_mark, FALSE);
|
||||
}
|
||||
|
||||
@@ -7828,11 +7802,10 @@ gtk_text_view_drag_motion (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_text_view_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_text_view_drag_drop (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkTextView *text_view;
|
||||
GtkTextViewPrivate *priv;
|
||||
@@ -7854,12 +7827,12 @@ gtk_text_view_drag_drop (GtkWidget *widget,
|
||||
priv->dnd_mark);
|
||||
|
||||
if (gtk_text_iter_can_insert (&drop_point, priv->editable))
|
||||
target = gtk_drag_dest_find_target (widget, context, NULL);
|
||||
target = gtk_drag_dest_find_target (widget, drop, NULL);
|
||||
|
||||
if (target != NULL)
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
else
|
||||
gtk_drag_finish (context, FALSE, time);
|
||||
gdk_drop_finish (drop, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -7886,17 +7859,39 @@ insert_text_data (GtkTextView *text_view,
|
||||
}
|
||||
}
|
||||
|
||||
static GdkDragAction
|
||||
gtk_text_view_get_action (GtkWidget *textview,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GdkDragContext *drag = gdk_drop_get_drag (drop);
|
||||
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
|
||||
GdkDragAction actions;
|
||||
|
||||
actions = gdk_drop_get_actions (drop);
|
||||
|
||||
if (source_widget == textview &&
|
||||
actions & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
if (actions & GDK_ACTION_COPY)
|
||||
return GDK_ACTION_COPY;
|
||||
|
||||
if (actions & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_view_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
GtkTextIter drop_point;
|
||||
GtkTextView *text_view;
|
||||
GtkTextViewPrivate *priv;
|
||||
gboolean success = FALSE;
|
||||
GtkTextBuffer *buffer = NULL;
|
||||
GdkDragAction action = 0;
|
||||
|
||||
text_view = GTK_TEXT_VIEW (widget);
|
||||
priv = text_view->priv;
|
||||
@@ -7913,7 +7908,9 @@ gtk_text_view_drag_data_received (GtkWidget *widget,
|
||||
if (!gtk_text_iter_can_insert (&drop_point, priv->editable))
|
||||
goto done;
|
||||
|
||||
success = TRUE;
|
||||
action = gtk_text_view_get_action (widget, drop);
|
||||
if (action == 0)
|
||||
goto done;
|
||||
|
||||
gtk_text_buffer_begin_user_action (buffer);
|
||||
|
||||
@@ -7965,9 +7962,9 @@ gtk_text_view_drag_data_received (GtkWidget *widget,
|
||||
insert_text_data (text_view, &drop_point, selection_data);
|
||||
|
||||
done:
|
||||
gtk_drag_finish (context, success, time);
|
||||
gdk_drop_finish (drop, action);
|
||||
|
||||
if (success)
|
||||
if (action)
|
||||
{
|
||||
gtk_text_buffer_get_iter_at_mark (buffer,
|
||||
&drop_point,
|
||||
|
||||
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtktreelist.h"
|
||||
|
||||
#include "gtkcssrbtreeprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ROOT_MODEL,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
typedef struct _TreeNode TreeNode;
|
||||
typedef struct _TreeAugment TreeAugment;
|
||||
|
||||
struct _TreeNode
|
||||
{
|
||||
GListModel *model;
|
||||
GtkCssRbTree *children;
|
||||
union {
|
||||
TreeNode *parent;
|
||||
GtkTreeList *list;
|
||||
};
|
||||
|
||||
guint empty : 1;
|
||||
guint is_root : 1;
|
||||
};
|
||||
|
||||
struct _TreeAugment
|
||||
{
|
||||
guint n_items;
|
||||
guint n_local;
|
||||
};
|
||||
|
||||
struct _GtkTreeList
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
TreeNode root_node;
|
||||
|
||||
GtkTreeListCreateModelFunc create_func;
|
||||
gpointer user_data;
|
||||
GDestroyNotify user_destroy;
|
||||
};
|
||||
|
||||
struct _GtkTreeListClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
static TreeNode *
|
||||
gtk_tree_list_get_nth (GtkTreeList *self,
|
||||
guint position)
|
||||
{
|
||||
GtkCssRbTree *tree;
|
||||
TreeNode *node, *tmp;
|
||||
TreeAugment *aug;
|
||||
|
||||
tree = self->root_node.children;
|
||||
node = gtk_css_rb_tree_get_root (tree);
|
||||
aug = gtk_css_rb_tree_get_augment (tree, node);
|
||||
if (aug->n_items <= position)
|
||||
return NULL;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
tmp = gtk_css_rb_tree_get_left (tree, node);
|
||||
if (tmp)
|
||||
{
|
||||
aug = gtk_css_rb_tree_get_augment (tree, tmp);
|
||||
if (position < aug->n_items)
|
||||
{
|
||||
node = tmp;
|
||||
continue;
|
||||
}
|
||||
position -= aug->n_items;
|
||||
}
|
||||
|
||||
if (position == 0)
|
||||
return node;
|
||||
|
||||
position--;
|
||||
|
||||
if (node->children)
|
||||
{
|
||||
tmp = gtk_css_rb_tree_get_root (node->children);
|
||||
aug = gtk_css_rb_tree_get_augment (node->children, tmp);
|
||||
if (position < aug->n_items)
|
||||
{
|
||||
tree = node->children;
|
||||
node = tmp;
|
||||
continue;
|
||||
}
|
||||
position -= aug->n_items;
|
||||
}
|
||||
|
||||
node = gtk_css_rb_tree_get_right (tree, node);
|
||||
}
|
||||
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
static guint
|
||||
tree_node_get_local_position (GtkCssRbTree *tree,
|
||||
TreeNode *node)
|
||||
{
|
||||
TreeNode *left, *parent;
|
||||
TreeAugment *left_aug;
|
||||
guint n;
|
||||
|
||||
left = gtk_css_rb_tree_get_left (tree, node);
|
||||
if (left)
|
||||
{
|
||||
left_aug = gtk_css_rb_tree_get_augment (tree, left);
|
||||
n = left_aug->n_local;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
|
||||
for (parent = gtk_css_rb_tree_get_parent (tree, node);
|
||||
parent;
|
||||
parent = gtk_css_rb_tree_get_parent (tree, node))
|
||||
{
|
||||
left = gtk_css_rb_tree_get_left (tree, parent);
|
||||
if (left == node)
|
||||
{
|
||||
/* we are the left node, nothing changes */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we are the right node */
|
||||
n++;
|
||||
if (left)
|
||||
{
|
||||
left_aug = gtk_css_rb_tree_get_augment (tree, left);
|
||||
n += left_aug->n_local;
|
||||
}
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static GType
|
||||
gtk_tree_list_get_item_type (GListModel *list)
|
||||
{
|
||||
GtkTreeList *self = GTK_TREE_LIST (list);
|
||||
|
||||
return g_list_model_get_item_type (self->root_node.model);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_node_mark_dirty (TreeNode *node)
|
||||
{
|
||||
for (;
|
||||
!node->is_root;
|
||||
node = node->parent)
|
||||
{
|
||||
gtk_css_rb_tree_mark_dirty (node->parent->children, node);
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
tree_node_get_n_children (TreeNode *node)
|
||||
{
|
||||
TreeAugment *child_aug;
|
||||
TreeNode *child_node;
|
||||
|
||||
if (node->children == NULL)
|
||||
return 0;
|
||||
|
||||
child_node = gtk_css_rb_tree_get_root (node->children);
|
||||
if (child_node == NULL)
|
||||
return 0;
|
||||
|
||||
child_aug = gtk_css_rb_tree_get_augment (node->children, child_node);
|
||||
|
||||
return child_aug->n_items;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_tree_list_get_n_items (GListModel *list)
|
||||
{
|
||||
GtkTreeList *self = GTK_TREE_LIST (list);
|
||||
|
||||
return tree_node_get_n_children (&self->root_node);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gtk_tree_list_get_item (GListModel *list,
|
||||
guint position)
|
||||
{
|
||||
GtkTreeList *self = GTK_TREE_LIST (list);
|
||||
TreeNode *node, *parent;
|
||||
|
||||
node = gtk_tree_list_get_nth (self, position);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
parent = node->parent;
|
||||
return g_list_model_get_item (parent->model,
|
||||
tree_node_get_local_position (parent->children, node));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_model_init (GListModelInterface *iface)
|
||||
{
|
||||
iface->get_item_type = gtk_tree_list_get_item_type;
|
||||
iface->get_n_items = gtk_tree_list_get_n_items;
|
||||
iface->get_item = gtk_tree_list_get_item;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkTreeList, gtk_tree_list, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_tree_list_model_init))
|
||||
|
||||
static void
|
||||
gtk_tree_list_augment (GtkCssRbTree *tree,
|
||||
gpointer _aug,
|
||||
gpointer _node,
|
||||
gpointer left,
|
||||
gpointer right)
|
||||
{
|
||||
TreeAugment *aug = _aug;
|
||||
|
||||
aug->n_items = 1;
|
||||
aug->n_items += tree_node_get_n_children (_node);
|
||||
aug->n_local = 1;
|
||||
|
||||
if (left)
|
||||
{
|
||||
TreeAugment *left_aug = gtk_css_rb_tree_get_augment (tree, left);
|
||||
aug->n_items += left_aug->n_items;
|
||||
aug->n_local += left_aug->n_local;
|
||||
}
|
||||
if (right)
|
||||
{
|
||||
TreeAugment *right_aug = gtk_css_rb_tree_get_augment (tree, right);
|
||||
aug->n_items += right_aug->n_items;
|
||||
aug->n_local += right_aug->n_local;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_clear_node (gpointer data)
|
||||
{
|
||||
TreeNode *node = data;
|
||||
|
||||
if (node->model)
|
||||
g_object_unref (node->model);
|
||||
if (node->children)
|
||||
gtk_css_rb_tree_unref (node->children);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_init_node (GtkTreeList *list,
|
||||
TreeNode *self,
|
||||
GListModel *model)
|
||||
{
|
||||
gsize i, n;
|
||||
TreeNode *node;
|
||||
|
||||
self->model = g_object_ref (model);
|
||||
self->children = gtk_css_rb_tree_new (TreeNode,
|
||||
TreeAugment,
|
||||
gtk_tree_list_augment,
|
||||
gtk_tree_list_clear_node,
|
||||
NULL);
|
||||
|
||||
n = g_list_model_get_n_items (model);
|
||||
node = NULL;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
node = gtk_css_rb_tree_insert_after (self->children, node);
|
||||
node->parent = self;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
/* GtkTreeList *self = GTK_TREE_LIST (object); */
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkTreeList *self = GTK_TREE_LIST (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ROOT_MODEL:
|
||||
g_value_set_object (value, self->root_node.model);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_finalize (GObject *object)
|
||||
{
|
||||
GtkTreeList *self = GTK_TREE_LIST (object);
|
||||
|
||||
gtk_tree_list_clear_node (&self->root_node);
|
||||
if (self->user_destroy)
|
||||
self->user_destroy (self->user_data);
|
||||
|
||||
G_OBJECT_CLASS (gtk_tree_list_parent_class)->finalize (object);
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_tree_list_class_init (GtkTreeListClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = gtk_tree_list_set_property;
|
||||
gobject_class->get_property = gtk_tree_list_get_property;
|
||||
gobject_class->finalize = gtk_tree_list_finalize;
|
||||
|
||||
/**
|
||||
* GtkTreeList:root-model:
|
||||
*
|
||||
* The root model displayed
|
||||
*/
|
||||
properties[PROP_ROOT_MODEL] =
|
||||
g_param_spec_object ("root-model",
|
||||
P_("Root model"),
|
||||
P_("The root model displayed"),
|
||||
G_TYPE_LIST_MODEL,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_init (GtkTreeList *self)
|
||||
{
|
||||
self->root_node.list = self;
|
||||
self->root_node.is_root = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_tree_list_new:
|
||||
* @root: The #GListModel to use as root
|
||||
* @create_func: Function to call to create the #GListModel for the children
|
||||
* of an item
|
||||
* @user_data: Data to pass to @create_func
|
||||
* @user_destroy: Function to call to free @user_data
|
||||
*
|
||||
* Creates a new empty #GtkTreeList displaying @root with all rows collapsed.
|
||||
*
|
||||
* Returns: a newly created #GtkTreeList.
|
||||
**/
|
||||
GListModel *
|
||||
gtk_tree_list_new (GListModel *root,
|
||||
GtkTreeListCreateModelFunc create_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy)
|
||||
{
|
||||
GtkTreeList *self;
|
||||
|
||||
g_return_val_if_fail (G_IS_LIST_MODEL (root), NULL);
|
||||
g_return_val_if_fail (create_func != NULL, NULL);
|
||||
|
||||
self = g_object_new (GTK_TYPE_TREE_LIST,
|
||||
NULL);
|
||||
|
||||
gtk_tree_list_init_node (self, &self->root_node, g_object_ref (root));
|
||||
self->create_func = create_func;
|
||||
self->user_data = user_data;
|
||||
self->user_destroy = user_destroy;
|
||||
|
||||
return G_LIST_MODEL (self);
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_tree_list_get_depth (GtkTreeList *self,
|
||||
guint position)
|
||||
{
|
||||
TreeNode *node;
|
||||
guint depth;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TREE_LIST (self), FALSE);
|
||||
|
||||
node = gtk_tree_list_get_nth (self, position);
|
||||
if (node == NULL)
|
||||
return 0;
|
||||
|
||||
depth = 0;
|
||||
for (node = node->parent;
|
||||
!node->is_root;
|
||||
node = node->parent)
|
||||
depth++;
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
tree_node_create_model (GtkTreeList *self,
|
||||
TreeNode *node)
|
||||
{
|
||||
TreeNode *parent = node->parent;
|
||||
GListModel *model;
|
||||
GObject *item;
|
||||
|
||||
item = g_list_model_get_item (parent->model,
|
||||
tree_node_get_local_position (parent->children, node));
|
||||
model = self->create_func (item, self->user_data);
|
||||
g_object_unref (item);
|
||||
if (model == NULL)
|
||||
node->empty = TRUE;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_expand_node (GtkTreeList *self,
|
||||
guint position,
|
||||
TreeNode *node)
|
||||
{
|
||||
GListModel *model;
|
||||
guint n_items;
|
||||
|
||||
if (node->empty)
|
||||
return;
|
||||
|
||||
if (node->model != NULL)
|
||||
return;
|
||||
|
||||
model = tree_node_create_model (self, node);
|
||||
|
||||
if (model == NULL)
|
||||
return;
|
||||
|
||||
g_assert (g_list_model_get_item_type (model) == g_list_model_get_item_type (self->root_node.model));
|
||||
gtk_tree_list_init_node (self, node, model);
|
||||
|
||||
tree_node_mark_dirty (node);
|
||||
n_items = tree_node_get_n_children (node);
|
||||
|
||||
if (n_items > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position + 1, 0, n_items);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_list_collapse_node (GtkTreeList *self,
|
||||
guint position,
|
||||
TreeNode *node)
|
||||
{
|
||||
guint n_items;
|
||||
|
||||
if (node->model == NULL)
|
||||
return;
|
||||
|
||||
n_items = tree_node_get_n_children (node);
|
||||
|
||||
g_clear_pointer (&node->children, gtk_css_rb_tree_unref);
|
||||
g_clear_object (&node->model);
|
||||
|
||||
tree_node_mark_dirty (node);
|
||||
|
||||
if (n_items > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position + 1, n_items, 0);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_list_set_expanded (GtkTreeList *self,
|
||||
guint position,
|
||||
gboolean expanded)
|
||||
{
|
||||
TreeNode *node;
|
||||
|
||||
g_return_if_fail (GTK_IS_TREE_LIST (self));
|
||||
|
||||
node = gtk_tree_list_get_nth (self, position);
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
if (expanded)
|
||||
gtk_tree_list_expand_node (self, position, node);
|
||||
else
|
||||
gtk_tree_list_collapse_node (self, position, node);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_tree_list_get_expanded (GtkTreeList *self,
|
||||
guint position)
|
||||
{
|
||||
TreeNode *node;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TREE_LIST (self), FALSE);
|
||||
|
||||
node = gtk_tree_list_get_nth (self, position);
|
||||
if (node == NULL)
|
||||
return FALSE;
|
||||
|
||||
return node->children != NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_tree_list_is_expandable (GtkTreeList *self,
|
||||
guint position)
|
||||
{
|
||||
GListModel *model;
|
||||
TreeNode *node;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TREE_LIST (self), FALSE);
|
||||
|
||||
node = gtk_tree_list_get_nth (self, position);
|
||||
if (node == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (node->empty)
|
||||
return FALSE;
|
||||
|
||||
if (node->model)
|
||||
return TRUE;
|
||||
|
||||
model = tree_node_create_model (self, node);
|
||||
if (model)
|
||||
{
|
||||
g_object_unref (model);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_TREE_LIST_H__
|
||||
#define __GTK_TREE_LIST_H__
|
||||
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtkwidget.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_TREE_LIST (gtk_tree_list_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkTreeList, gtk_tree_list, GTK, TREE_LIST, GObject)
|
||||
|
||||
typedef GListModel * (* GtkTreeListCreateModelFunc) (gpointer item, gpointer data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_tree_list_new (GListModel *root,
|
||||
GtkTreeListCreateModelFunc create_func,
|
||||
gpointer data,
|
||||
GDestroyNotify data_destroy);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
guint gtk_tree_list_get_depth (GtkTreeList *self,
|
||||
guint position);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_tree_list_set_expanded (GtkTreeList *self,
|
||||
guint position,
|
||||
gboolean expanded);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_tree_list_get_expanded (GtkTreeList *self,
|
||||
guint position);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_tree_list_is_expandable (GtkTreeList *self,
|
||||
guint position);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_TREE_LIST_H__ */
|
||||
+83
-81
@@ -630,22 +630,18 @@ static void gtk_tree_view_drag_data_delete (GtkWidget *widget,
|
||||
|
||||
/* Target side drag signals */
|
||||
static void gtk_tree_view_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
GdkDrop *drop);
|
||||
static gboolean gtk_tree_view_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static gboolean gtk_tree_view_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
gint y);
|
||||
static void gtk_tree_view_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time);
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data);
|
||||
|
||||
/* tree_model signals */
|
||||
static gboolean gtk_tree_view_real_move_cursor (GtkTreeView *tree_view,
|
||||
@@ -6863,18 +6859,18 @@ dest_row_free (gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
set_dest_row (GdkDragContext *context,
|
||||
GtkTreeModel *model,
|
||||
GtkTreePath *dest_row,
|
||||
gboolean path_down_mode,
|
||||
gboolean empty_view_drop,
|
||||
gboolean drop_append_mode)
|
||||
set_dest_row (GdkDrop *drop,
|
||||
GtkTreeModel *model,
|
||||
GtkTreePath *dest_row,
|
||||
gboolean path_down_mode,
|
||||
gboolean empty_view_drop,
|
||||
gboolean drop_append_mode)
|
||||
{
|
||||
DestRow *dr;
|
||||
|
||||
if (!dest_row)
|
||||
{
|
||||
g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
|
||||
g_object_set_data_full (G_OBJECT (drop), I_("gtk-tree-view-dest-row"),
|
||||
NULL, NULL);
|
||||
return;
|
||||
}
|
||||
@@ -6886,16 +6882,16 @@ set_dest_row (GdkDragContext *context,
|
||||
dr->empty_view_drop = empty_view_drop != FALSE;
|
||||
dr->drop_append_mode = drop_append_mode != FALSE;
|
||||
|
||||
g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
|
||||
g_object_set_data_full (G_OBJECT (drop), I_("gtk-tree-view-dest-row"),
|
||||
dr, (GDestroyNotify) dest_row_free);
|
||||
}
|
||||
|
||||
static GtkTreePath*
|
||||
get_dest_row (GdkDragContext *context,
|
||||
gboolean *path_down_mode)
|
||||
get_dest_row (GdkDrop *drop,
|
||||
gboolean *path_down_mode)
|
||||
{
|
||||
DestRow *dr =
|
||||
g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
|
||||
g_object_get_data (G_OBJECT (drop), "gtk-tree-view-dest-row");
|
||||
|
||||
if (dr)
|
||||
{
|
||||
@@ -6925,18 +6921,18 @@ get_dest_row (GdkDragContext *context,
|
||||
* since the data doesn’t result from a drop.
|
||||
*/
|
||||
static void
|
||||
set_status_pending (GdkDragContext *context,
|
||||
GdkDragAction suggested_action)
|
||||
set_status_pending (GdkDrop *drop,
|
||||
GdkDragAction suggested_action)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (context),
|
||||
g_object_set_data (G_OBJECT (drop),
|
||||
I_("gtk-tree-view-status-pending"),
|
||||
GINT_TO_POINTER (suggested_action));
|
||||
}
|
||||
|
||||
static GdkDragAction
|
||||
get_status_pending (GdkDragContext *context)
|
||||
get_status_pending (GdkDrop *drop)
|
||||
{
|
||||
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
|
||||
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drop),
|
||||
"gtk-tree-view-status-pending"));
|
||||
}
|
||||
|
||||
@@ -7132,7 +7128,7 @@ scroll_row_timeout (gpointer data)
|
||||
/* Returns TRUE if event should not be propagated to parent widgets */
|
||||
static gboolean
|
||||
set_destination_row (GtkTreeView *tree_view,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
/* coordinates relative to the widget */
|
||||
gint x,
|
||||
gint y,
|
||||
@@ -7170,7 +7166,7 @@ set_destination_row (GtkTreeView *tree_view,
|
||||
return FALSE; /* no longer a drop site */
|
||||
}
|
||||
|
||||
*target = gtk_drag_dest_find_target (widget, context,
|
||||
*target = gtk_drag_dest_find_target (widget, drop,
|
||||
gtk_drag_dest_get_target_list (widget));
|
||||
if (*target == NULL)
|
||||
{
|
||||
@@ -7238,19 +7234,7 @@ set_destination_row (GtkTreeView *tree_view,
|
||||
out:
|
||||
if (can_drop)
|
||||
{
|
||||
GtkWidget *source_widget;
|
||||
|
||||
*suggested_action = gdk_drag_context_get_suggested_action (context);
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
|
||||
if (source_widget == widget)
|
||||
{
|
||||
/* Default to MOVE, unless the user has
|
||||
* pressed ctrl or shift to affect available actions
|
||||
*/
|
||||
if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
|
||||
*suggested_action = GDK_ACTION_MOVE;
|
||||
}
|
||||
*suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
|
||||
|
||||
gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
|
||||
path, pos);
|
||||
@@ -7535,9 +7519,8 @@ gtk_tree_view_drag_data_delete (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_view_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
gtk_tree_view_drag_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
|
||||
|
||||
@@ -7555,12 +7538,10 @@ gtk_tree_view_drag_leave (GtkWidget *widget,
|
||||
|
||||
|
||||
static gboolean
|
||||
gtk_tree_view_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
/* coordinates relative to the widget */
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_tree_view_drag_motion (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
gboolean empty;
|
||||
GtkTreePath *path = NULL;
|
||||
@@ -7571,7 +7552,7 @@ gtk_tree_view_drag_motion (GtkWidget *widget,
|
||||
|
||||
tree_view = GTK_TREE_VIEW (widget);
|
||||
|
||||
if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
|
||||
if (!set_destination_row (tree_view, drop, x, y, &suggested_action, &target))
|
||||
return FALSE;
|
||||
|
||||
tree_view->priv->event_last_x = x;
|
||||
@@ -7585,7 +7566,7 @@ gtk_tree_view_drag_motion (GtkWidget *widget,
|
||||
if (path == NULL && !empty)
|
||||
{
|
||||
/* Can't drop here. */
|
||||
gdk_drag_status (context, 0, time);
|
||||
gdk_drop_status (drop, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7607,13 +7588,13 @@ gtk_tree_view_drag_motion (GtkWidget *widget,
|
||||
/* Request data so we can use the source row when
|
||||
* determining whether to accept the drop
|
||||
*/
|
||||
set_status_pending (context, suggested_action);
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
set_status_pending (drop, suggested_action);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_status_pending (context, 0);
|
||||
gdk_drag_status (context, suggested_action, time);
|
||||
set_status_pending (drop, 0);
|
||||
gdk_drop_status (drop, suggested_action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7625,12 +7606,10 @@ gtk_tree_view_drag_motion (GtkWidget *widget,
|
||||
|
||||
|
||||
static gboolean
|
||||
gtk_tree_view_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
/* coordinates relative to the widget */
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gtk_tree_view_drag_drop (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkTreeView *tree_view;
|
||||
GtkTreePath *path;
|
||||
@@ -7656,7 +7635,7 @@ gtk_tree_view_drag_drop (GtkWidget *widget,
|
||||
if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_drop"))
|
||||
return FALSE;
|
||||
|
||||
if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
|
||||
if (!set_destination_row (tree_view, drop, x, y, &suggested_action, &target))
|
||||
return FALSE;
|
||||
|
||||
path = get_logical_dest_row (tree_view, &path_down_mode, &drop_append_mode);
|
||||
@@ -7666,8 +7645,8 @@ gtk_tree_view_drag_drop (GtkWidget *widget,
|
||||
/* in case a motion had requested drag data, change things so we
|
||||
* treat drag data receives as a drop.
|
||||
*/
|
||||
set_status_pending (context, 0);
|
||||
set_dest_row (context, model, path,
|
||||
set_status_pending (drop, 0);
|
||||
set_dest_row (drop, model, path,
|
||||
path_down_mode, tree_view->priv->empty_view_drop,
|
||||
drop_append_mode);
|
||||
}
|
||||
@@ -7682,22 +7661,43 @@ gtk_tree_view_drag_drop (GtkWidget *widget,
|
||||
|
||||
if (target != NULL)
|
||||
{
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
gtk_drag_get_data (widget, drop, target);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkDragAction
|
||||
gtk_tree_view_get_action (GtkWidget *treeview,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GdkDragContext *drag = gdk_drop_get_drag (drop);
|
||||
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
|
||||
GdkDragAction actions;
|
||||
|
||||
actions = gdk_drop_get_actions (drop);
|
||||
|
||||
if (source_widget == treeview &&
|
||||
actions & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
if (actions & GDK_ACTION_COPY)
|
||||
return GDK_ACTION_COPY;
|
||||
|
||||
if (actions & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_view_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
TreeViewDragInfo *di;
|
||||
gboolean accepted = FALSE;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeView *tree_view;
|
||||
GtkTreePath *dest_row;
|
||||
@@ -7717,7 +7717,7 @@ gtk_tree_view_drag_data_received (GtkWidget *widget,
|
||||
if (di == NULL)
|
||||
return;
|
||||
|
||||
suggested_action = get_status_pending (context);
|
||||
suggested_action = get_status_pending (drop);
|
||||
|
||||
if (suggested_action)
|
||||
{
|
||||
@@ -7755,7 +7755,7 @@ gtk_tree_view_drag_data_received (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
gdk_drag_status (context, suggested_action, time);
|
||||
gdk_drop_status (drop, suggested_action);
|
||||
|
||||
if (path)
|
||||
gtk_tree_path_free (path);
|
||||
@@ -7769,7 +7769,7 @@ gtk_tree_view_drag_data_received (GtkWidget *widget,
|
||||
return;
|
||||
}
|
||||
|
||||
dest_row = get_dest_row (context, &path_down_mode);
|
||||
dest_row = get_dest_row (drop, &path_down_mode);
|
||||
|
||||
if (dest_row == NULL)
|
||||
return;
|
||||
@@ -7787,13 +7787,16 @@ gtk_tree_view_drag_data_received (GtkWidget *widget,
|
||||
|
||||
if (gtk_selection_data_get_length (selection_data) >= 0)
|
||||
{
|
||||
if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
|
||||
dest_row,
|
||||
selection_data))
|
||||
accepted = TRUE;
|
||||
suggested_action = gtk_tree_view_get_action (widget, drop);
|
||||
|
||||
if (suggested_action &&
|
||||
!gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
|
||||
dest_row,
|
||||
selection_data))
|
||||
suggested_action = 0;
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, accepted, time);
|
||||
gdk_drop_finish (drop, suggested_action);
|
||||
|
||||
if (gtk_tree_path_get_depth (dest_row) == 1 &&
|
||||
gtk_tree_path_get_indices (dest_row)[0] == 0 &&
|
||||
@@ -7807,11 +7810,10 @@ gtk_tree_view_drag_data_received (GtkWidget *widget,
|
||||
gtk_tree_path_free (dest_row);
|
||||
|
||||
/* drop dest_row */
|
||||
set_dest_row (context, NULL, NULL, FALSE, FALSE, FALSE);
|
||||
set_dest_row (drop, NULL, NULL, FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* GtkContainer Methods
|
||||
*/
|
||||
|
||||
|
||||
+41
-59
@@ -1736,10 +1736,9 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkWidgetClass, drag_leave),
|
||||
NULL, NULL,
|
||||
_gtk_marshal_VOID__OBJECT_UINT,
|
||||
G_TYPE_NONE, 2,
|
||||
GDK_TYPE_DRAG_CONTEXT,
|
||||
G_TYPE_UINT);
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
GDK_TYPE_DROP);
|
||||
|
||||
/**
|
||||
* GtkWidget::drag-begin:
|
||||
@@ -1831,10 +1830,9 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
/**
|
||||
* GtkWidget::drag-motion:
|
||||
* @widget: the object which received the signal
|
||||
* @context: the drag context
|
||||
* @drop: the #GdkDrop
|
||||
* @x: the x coordinate of the current cursor position
|
||||
* @y: the y coordinate of the current cursor position
|
||||
* @time: the timestamp of the motion event
|
||||
*
|
||||
* The ::drag-motion signal is emitted on the drop site when the user
|
||||
* moves the cursor over the widget during a drag. The signal handler
|
||||
@@ -1859,11 +1857,10 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
* the drop site with gtk_drag_highlight().
|
||||
* |[<!-- language="C" -->
|
||||
* static void
|
||||
* drag_motion (GtkWidget *widget,
|
||||
* GdkDragContext *context,
|
||||
* gint x,
|
||||
* gint y,
|
||||
* guint time)
|
||||
* drag_motion (GtkWidget *widget,
|
||||
* GdkDrop *drop,
|
||||
* gint x,
|
||||
* gint y,
|
||||
* {
|
||||
* GdkAtom target;
|
||||
*
|
||||
@@ -1875,14 +1872,14 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
* gtk_drag_highlight (widget);
|
||||
* }
|
||||
*
|
||||
* target = gtk_drag_dest_find_target (widget, context, NULL);
|
||||
* target = gtk_drag_dest_find_target (widget, drop, NULL);
|
||||
* if (target == NULL)
|
||||
* gdk_drag_status (context, 0, time);
|
||||
* gdk_drop_status (drop, 0);
|
||||
* else
|
||||
* {
|
||||
* private_data->pending_status
|
||||
* = gdk_drag_context_get_suggested_action (context);
|
||||
* gtk_drag_get_data (widget, context, target, time);
|
||||
* = gdk_drop_get_actions (drop);
|
||||
* gtk_drag_get_data (widget, drop, target);
|
||||
* }
|
||||
*
|
||||
* return TRUE;
|
||||
@@ -1890,12 +1887,8 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
*
|
||||
* static void
|
||||
* drag_data_received (GtkWidget *widget,
|
||||
* GdkDragContext *context,
|
||||
* gint x,
|
||||
* gint y,
|
||||
* GtkSelectionData *selection_data,
|
||||
* guint info,
|
||||
* guint time)
|
||||
* GdkDrop *drop,
|
||||
* GtkSelectionData *selection_data)
|
||||
* {
|
||||
* PrivateData *private_data = GET_PRIVATE_DATA (widget);
|
||||
*
|
||||
@@ -1910,11 +1903,9 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
*
|
||||
* str = gtk_selection_data_get_text (selection_data);
|
||||
* if (!data_is_acceptable (str))
|
||||
* gdk_drag_status (context, 0, time);
|
||||
* gdk_drop_status (drop, 0);
|
||||
* else
|
||||
* gdk_drag_status (context,
|
||||
* private_data->suggested_action,
|
||||
* time);
|
||||
* gdk_drag_status (drop, GDK_ACTION_ALL);
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
@@ -1931,28 +1922,26 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkWidgetClass, drag_motion),
|
||||
_gtk_boolean_handled_accumulator, NULL,
|
||||
_gtk_marshal_BOOLEAN__OBJECT_INT_INT_UINT,
|
||||
G_TYPE_BOOLEAN, 4,
|
||||
GDK_TYPE_DRAG_CONTEXT,
|
||||
_gtk_marshal_BOOLEAN__OBJECT_INT_INT,
|
||||
G_TYPE_BOOLEAN, 3,
|
||||
GDK_TYPE_DROP,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_UINT);
|
||||
G_TYPE_INT);
|
||||
|
||||
/**
|
||||
* GtkWidget::drag-drop:
|
||||
* @widget: the object which received the signal
|
||||
* @context: the drag context
|
||||
* @drop: the #GdkDrop
|
||||
* @x: the x coordinate of the current cursor position
|
||||
* @y: the y coordinate of the current cursor position
|
||||
* @time: the timestamp of the motion event
|
||||
*
|
||||
* The ::drag-drop signal is emitted on the drop site when the user drops
|
||||
* the data onto the widget. The signal handler must determine whether
|
||||
* the cursor position is in a drop zone or not. If it is not in a drop
|
||||
* zone, it returns %FALSE and no further processing is necessary.
|
||||
* Otherwise, the handler returns %TRUE. In this case, the handler must
|
||||
* ensure that gtk_drag_finish() is called to let the source know that
|
||||
* the drop is done. The call to gtk_drag_finish() can be done either
|
||||
* ensure that gdk_drag_finish() is called to let the source know that
|
||||
* the drop is done. The call to gdk_drag_finish() can be done either
|
||||
* directly or in a #GtkWidget::drag-data-received handler which gets
|
||||
* triggered by calling gtk_drag_get_data() to receive the data for one
|
||||
* or more of the supported targets.
|
||||
@@ -1965,12 +1954,11 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkWidgetClass, drag_drop),
|
||||
_gtk_boolean_handled_accumulator, NULL,
|
||||
_gtk_marshal_BOOLEAN__OBJECT_INT_INT_UINT,
|
||||
G_TYPE_BOOLEAN, 4,
|
||||
GDK_TYPE_DRAG_CONTEXT,
|
||||
_gtk_marshal_BOOLEAN__OBJECT_INT_INT,
|
||||
G_TYPE_BOOLEAN, 3,
|
||||
GDK_TYPE_DROP,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_UINT);
|
||||
G_TYPE_INT);
|
||||
|
||||
/**
|
||||
* GtkWidget::drag-data-get:
|
||||
@@ -2002,11 +1990,10 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
/**
|
||||
* GtkWidget::drag-data-received:
|
||||
* @widget: the object which received the signal
|
||||
* @context: the drag context
|
||||
* @drop: the #GdkDrop
|
||||
* @x: where the drop happened
|
||||
* @y: where the drop happened
|
||||
* @data: the received data
|
||||
* @time: the timestamp at which the data was received
|
||||
*
|
||||
* The ::drag-data-received signal is emitted on the drop site when the
|
||||
* dragged data has been received. If the data was received in order to
|
||||
@@ -2015,25 +2002,21 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
* If the data was received in response to a #GtkWidget::drag-drop signal
|
||||
* (and this is the last target to be received), the handler for this
|
||||
* signal is expected to process the received data and then call
|
||||
* gtk_drag_finish(), setting the @success parameter depending on
|
||||
* gdk_drag_finish(), setting the @success parameter depending on
|
||||
* whether the data was processed successfully.
|
||||
*
|
||||
* Applications must create some means to determine why the signal was emitted
|
||||
* and therefore whether to call gdk_drag_status() or gtk_drag_finish().
|
||||
* and therefore whether to call gdk_drag_status() or gdk_drag_finish().
|
||||
*
|
||||
* The handler may inspect the selected action with
|
||||
* gdk_drag_context_get_selected_action() before calling
|
||||
* gtk_drag_finish(), e.g. to implement %GDK_ACTION_ASK as
|
||||
* gdk_drag_finish(), e.g. to implement %GDK_ACTION_ASK as
|
||||
* shown in the following example:
|
||||
* |[<!-- language="C" -->
|
||||
* void
|
||||
* drag_data_received (GtkWidget *widget,
|
||||
* GdkDragContext *context,
|
||||
* gint x,
|
||||
* gint y,
|
||||
* GtkSelectionData *data,
|
||||
* guint info,
|
||||
* guint time)
|
||||
* GdkDrop *drop,
|
||||
* GtkSelectionData *data)
|
||||
* {
|
||||
* if ((data->length >= 0) && (data->format == 8))
|
||||
* {
|
||||
@@ -2041,8 +2024,8 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
*
|
||||
* // handle data here
|
||||
*
|
||||
* action = gdk_drag_context_get_selected_action (context);
|
||||
* if (action == GDK_ACTION_ASK)
|
||||
* action = gdk_drop_get_actions (drop);
|
||||
* if (!gdk_drag_action_is_unique (action))
|
||||
* {
|
||||
* GtkWidget *dialog;
|
||||
* gint response;
|
||||
@@ -2062,10 +2045,10 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
* action = GDK_ACTION_COPY;
|
||||
* }
|
||||
*
|
||||
* gtk_drag_finish (context, TRUE, action == GDK_ACTION_MOVE, time);
|
||||
* gdk_drop_finish (context, action);
|
||||
* }
|
||||
* else
|
||||
* gtk_drag_finish (context, FALSE, FALSE, time);
|
||||
* gdk_drop_finish (context, 0);
|
||||
* }
|
||||
* ]|
|
||||
*/
|
||||
@@ -2075,11 +2058,10 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkWidgetClass, drag_data_received),
|
||||
NULL, NULL,
|
||||
_gtk_marshal_VOID__OBJECT_BOXED_UINT,
|
||||
G_TYPE_NONE, 3,
|
||||
GDK_TYPE_DRAG_CONTEXT,
|
||||
GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE,
|
||||
G_TYPE_UINT);
|
||||
_gtk_marshal_VOID__OBJECT_BOXED,
|
||||
G_TYPE_NONE, 2,
|
||||
GDK_TYPE_DROP,
|
||||
GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
|
||||
/**
|
||||
* GtkWidget::query-tooltip:
|
||||
|
||||
+7
-11
@@ -306,22 +306,18 @@ struct _GtkWidgetClass
|
||||
|
||||
/* Target side drag signals */
|
||||
void (* drag_leave) (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time_);
|
||||
GdkDrop *drop);
|
||||
gboolean (* drag_motion) (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time_);
|
||||
gint y);
|
||||
gboolean (* drag_drop) (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time_);
|
||||
gint y);
|
||||
void (* drag_data_received) (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time_);
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data);
|
||||
gboolean (* drag_failed) (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkDragResult result);
|
||||
|
||||
@@ -75,6 +75,7 @@ gtk_private_sources = files([
|
||||
'gtkcssparser.c',
|
||||
'gtkcsspathnode.c',
|
||||
'gtkcsspositionvalue.c',
|
||||
'gtkcssrbtree.c',
|
||||
'gtkcssrepeatvalue.c',
|
||||
'gtkcssrgbavalue.c',
|
||||
'gtkcssselector.c',
|
||||
@@ -362,6 +363,7 @@ gtk_public_sources = files([
|
||||
'gtktooltip.c',
|
||||
'gtktooltipwindow.c',
|
||||
'gtktreednd.c',
|
||||
'gtktreelist.c',
|
||||
'gtktreemenu.c',
|
||||
'gtktreemodel.c',
|
||||
'gtktreemodelfilter.c',
|
||||
@@ -583,6 +585,7 @@ gtk_public_headers = files([
|
||||
'gtktoolshell.h',
|
||||
'gtktooltip.h',
|
||||
'gtktreednd.h',
|
||||
'gtktreelist.h',
|
||||
'gtktreemodel.h',
|
||||
'gtktreemodelfilter.h',
|
||||
'gtktreemodelsort.h',
|
||||
|
||||
@@ -113,6 +113,7 @@ gtk_tests = [
|
||||
['testrevealer'],
|
||||
['testrevealer2'],
|
||||
['testtitlebar'],
|
||||
['testtreelist'],
|
||||
['testsplitheaders'],
|
||||
['teststackedheaders'],
|
||||
['testactionbar'],
|
||||
|
||||
+58
-46
@@ -299,7 +299,7 @@ static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
|
||||
|
||||
void
|
||||
target_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
guint time)
|
||||
{
|
||||
g_print("leave\n");
|
||||
@@ -309,12 +309,12 @@ target_drag_leave (GtkWidget *widget,
|
||||
|
||||
gboolean
|
||||
target_drag_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gint y)
|
||||
{
|
||||
GtkWidget *source_widget;
|
||||
GdkDragContext *drag;
|
||||
char *s;
|
||||
|
||||
if (!have_drag)
|
||||
@@ -323,25 +323,25 @@ target_drag_motion (GtkWidget *widget,
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_open);
|
||||
}
|
||||
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
drag = gdk_drop_get_drag (drop);
|
||||
source_widget = drag ? gtk_drag_get_source_widget (drag) : NULL;
|
||||
g_print ("motion, source %s\n", source_widget ?
|
||||
G_OBJECT_TYPE_NAME (source_widget) :
|
||||
"NULL");
|
||||
|
||||
s = gdk_content_formats_to_string (gdk_drag_context_get_formats (context));
|
||||
s = gdk_content_formats_to_string (gdk_drop_get_formats (drop));
|
||||
g_print ("%s\n", s);
|
||||
|
||||
gdk_drag_status (context, gdk_drag_context_get_suggested_action (context), time);
|
||||
gdk_drop_status (drop, GDK_ACTION_ALL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
target_drag_drop (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gint y)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
const char *format;
|
||||
@@ -351,53 +351,69 @@ target_drag_drop (GtkWidget *widget,
|
||||
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_closed);
|
||||
|
||||
formats = gdk_drag_context_get_formats (context);
|
||||
formats = gdk_drop_get_formats (drop);
|
||||
format = gdk_content_formats_match_mime_type (formats, formats);
|
||||
if (format)
|
||||
{
|
||||
gtk_drag_get_data (widget, context,
|
||||
format,
|
||||
time);
|
||||
gtk_drag_get_data (widget, drop, format);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkDragAction
|
||||
action_make_unique (GdkDragAction action)
|
||||
{
|
||||
if (gdk_drag_action_is_unique (action))
|
||||
return action;
|
||||
|
||||
if (action & GDK_ACTION_COPY)
|
||||
return GDK_ACTION_COPY;
|
||||
|
||||
if (action & GDK_ACTION_MOVE)
|
||||
return GDK_ACTION_MOVE;
|
||||
|
||||
if (action & GDK_ACTION_LINK)
|
||||
return GDK_ACTION_LINK;
|
||||
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
target_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
if (gtk_selection_data_get_length (selection_data) >= 0 &&
|
||||
gtk_selection_data_get_format (selection_data) == 8)
|
||||
{
|
||||
GdkDragAction action = gdk_drop_get_actions (drop);
|
||||
g_print ("Received \"%s\" in trashcan\n", (gchar *) gtk_selection_data_get_data (selection_data));
|
||||
gtk_drag_finish (context, TRUE, time);
|
||||
action = action_make_unique (action);
|
||||
gdk_drop_finish (drop, action);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, FALSE, time);
|
||||
gdk_drop_finish (drop, 0);
|
||||
}
|
||||
|
||||
void
|
||||
label_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time)
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
if (gtk_selection_data_get_length (selection_data) >= 0 &&
|
||||
gtk_selection_data_get_format (selection_data) == 8)
|
||||
{
|
||||
GdkDragAction action = action_make_unique (gdk_drop_get_actions (drop));
|
||||
g_print ("Received \"%s\" in label\n", (gchar *) gtk_selection_data_get_data (selection_data));
|
||||
gtk_drag_finish (context, TRUE, time);
|
||||
gdk_drop_finish (drop, action);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, FALSE, time);
|
||||
gdk_drop_finish (drop, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -439,10 +455,9 @@ popdown_cb (gpointer data)
|
||||
|
||||
gboolean
|
||||
popup_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gint y)
|
||||
{
|
||||
if (!in_popup)
|
||||
{
|
||||
@@ -460,8 +475,7 @@ popup_motion (GtkWidget *widget,
|
||||
|
||||
void
|
||||
popup_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
GdkDrop *drop)
|
||||
{
|
||||
if (in_popup)
|
||||
{
|
||||
@@ -506,9 +520,9 @@ popup_cb (gpointer data)
|
||||
GTK_DEST_DEFAULT_ALL,
|
||||
targets,
|
||||
GDK_ACTION_COPY | GDK_ACTION_MOVE);
|
||||
g_signal_connect (button, "drag_motion",
|
||||
g_signal_connect (button, "drag-motion",
|
||||
G_CALLBACK (popup_motion), NULL);
|
||||
g_signal_connect (button, "drag_leave",
|
||||
g_signal_connect (button, "drag-leave",
|
||||
G_CALLBACK (popup_leave), NULL);
|
||||
}
|
||||
gtk_container_add (GTK_CONTAINER (popup_window), grid);
|
||||
@@ -529,10 +543,9 @@ popup_cb (gpointer data)
|
||||
|
||||
gboolean
|
||||
popsite_motion (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
gint y)
|
||||
{
|
||||
if (!popup_timer)
|
||||
popup_timer = g_timeout_add (500, popup_cb, NULL);
|
||||
@@ -542,8 +555,7 @@ popsite_motion (GtkWidget *widget,
|
||||
|
||||
void
|
||||
popsite_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
GdkDrop *drop)
|
||||
{
|
||||
if (popup_timer)
|
||||
{
|
||||
@@ -623,9 +635,9 @@ main (int argc, char **argv)
|
||||
gtk_widget_set_vexpand (label, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1);
|
||||
|
||||
g_signal_connect (label, "drag_motion",
|
||||
g_signal_connect (label, "drag-motion",
|
||||
G_CALLBACK (popsite_motion), NULL);
|
||||
g_signal_connect (label, "drag_leave",
|
||||
g_signal_connect (label, "drag-leave",
|
||||
G_CALLBACK (popsite_leave), NULL);
|
||||
gdk_content_formats_unref (targets);
|
||||
|
||||
@@ -635,16 +647,16 @@ main (int argc, char **argv)
|
||||
gtk_widget_set_vexpand (pixmap, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (grid), pixmap, 1, 0, 1, 1);
|
||||
|
||||
g_signal_connect (pixmap, "drag_leave",
|
||||
g_signal_connect (pixmap, "drag-leave",
|
||||
G_CALLBACK (target_drag_leave), NULL);
|
||||
|
||||
g_signal_connect (pixmap, "drag_motion",
|
||||
g_signal_connect (pixmap, "drag-motion",
|
||||
G_CALLBACK (target_drag_motion), NULL);
|
||||
|
||||
g_signal_connect (pixmap, "drag_drop",
|
||||
g_signal_connect (pixmap, "drag-drop",
|
||||
G_CALLBACK (target_drag_drop), NULL);
|
||||
|
||||
g_signal_connect (pixmap, "drag_data_received",
|
||||
g_signal_connect (pixmap, "drag-data-received",
|
||||
G_CALLBACK (target_drag_data_received), NULL);
|
||||
|
||||
/* Drag site */
|
||||
@@ -664,9 +676,9 @@ main (int argc, char **argv)
|
||||
gtk_widget_set_vexpand (button, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 1, 1);
|
||||
|
||||
g_signal_connect (button, "drag_data_get",
|
||||
g_signal_connect (button, "drag-data-get",
|
||||
G_CALLBACK (source_drag_data_get), NULL);
|
||||
g_signal_connect (button, "drag_data_delete",
|
||||
g_signal_connect (button, "drag-data-delete",
|
||||
G_CALLBACK (source_drag_data_delete), NULL);
|
||||
|
||||
gtk_widget_show (window);
|
||||
|
||||
+1
-2
@@ -186,9 +186,8 @@ image_drag_data_get (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
image_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data,
|
||||
guint32 time,
|
||||
gpointer data)
|
||||
{
|
||||
gchar *text;
|
||||
|
||||
+1
-2
@@ -42,9 +42,8 @@ drag_data_get (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data,
|
||||
guint32 time,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *target;
|
||||
|
||||
@@ -122,9 +122,8 @@ remove_in_idle (gpointer data)
|
||||
|
||||
static void
|
||||
on_button_drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *data,
|
||||
guint time,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget **child;
|
||||
|
||||
+1
-2
@@ -90,9 +90,8 @@ get_dragsource (void)
|
||||
|
||||
static void
|
||||
drag_data_received (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selda,
|
||||
guint time,
|
||||
gpointer dada)
|
||||
{
|
||||
gchar *text;
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GListModel *
|
||||
create_list_model_for_directory (gpointer file,
|
||||
gpointer unused)
|
||||
{
|
||||
GFileEnumerator *enumerate;
|
||||
GListStore *store;
|
||||
GFile *child;
|
||||
GFileInfo *info;
|
||||
|
||||
enumerate = g_file_enumerate_children (file,
|
||||
G_FILE_ATTRIBUTE_STANDARD_TYPE
|
||||
"," G_FILE_ATTRIBUTE_STANDARD_NAME,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (enumerate == NULL)
|
||||
return NULL;
|
||||
|
||||
store = g_list_store_new (G_TYPE_FILE);
|
||||
|
||||
while (g_file_enumerator_iterate (enumerate, &info, NULL, NULL, NULL))
|
||||
{
|
||||
if (info == NULL)
|
||||
break;
|
||||
|
||||
if (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY)
|
||||
continue;
|
||||
|
||||
child = g_file_get_child (file, g_file_info_get_name (info));
|
||||
g_list_store_append (store, child);
|
||||
g_object_unref (child);
|
||||
}
|
||||
|
||||
g_object_unref (enumerate);
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
static GtkTreeList *
|
||||
get_tree_list (GtkWidget *row)
|
||||
{
|
||||
return GTK_TREE_LIST (g_object_get_data (G_OBJECT (gtk_widget_get_parent (row)), "model"));
|
||||
}
|
||||
|
||||
static void
|
||||
expand_clicked (GtkWidget *button,
|
||||
GtkWidget *row)
|
||||
{
|
||||
gtk_tree_list_set_expanded (get_tree_list (row),
|
||||
gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row)),
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
collapse_clicked (GtkWidget *button,
|
||||
GtkWidget *row)
|
||||
{
|
||||
gtk_tree_list_set_expanded (get_tree_list (row),
|
||||
gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row)),
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_widget_for_model (gpointer file,
|
||||
gpointer root)
|
||||
{
|
||||
GtkWidget *row, *box, *child;
|
||||
GFile *iter;
|
||||
guint depth;
|
||||
|
||||
row = gtk_list_box_row_new ();
|
||||
|
||||
depth = 0;
|
||||
for (iter = g_object_ref (g_file_get_parent (file));
|
||||
!g_file_equal (root, iter);
|
||||
g_set_object (&iter, g_file_get_parent (iter)))
|
||||
{
|
||||
g_object_unref (iter);
|
||||
depth++;
|
||||
}
|
||||
g_object_unref (iter);
|
||||
g_object_unref (iter);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (row), box);
|
||||
|
||||
if (depth > 0)
|
||||
{
|
||||
child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_size_request (child, 16 * depth, 0);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
}
|
||||
|
||||
child = gtk_button_new_from_icon_name ("list-remove-symbolic");
|
||||
gtk_button_set_relief (GTK_BUTTON (child), GTK_RELIEF_NONE);
|
||||
g_signal_connect (child, "clicked", G_CALLBACK (collapse_clicked), row);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
|
||||
child = gtk_button_new_from_icon_name ("list-add-symbolic");
|
||||
gtk_button_set_relief (GTK_BUTTON (child), GTK_RELIEF_NONE);
|
||||
g_signal_connect (child, "clicked", G_CALLBACK (expand_clicked), row);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
|
||||
child = gtk_label_new (g_file_get_basename (file));
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *win;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *listbox;
|
||||
GListModel *model, *dirmodel;
|
||||
GFile *root;
|
||||
|
||||
gtk_init ();
|
||||
|
||||
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size (GTK_WINDOW (win), 400, 600);
|
||||
g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), win);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (win), sw);
|
||||
|
||||
listbox = gtk_list_box_new ();
|
||||
gtk_container_add (GTK_CONTAINER (sw), listbox);
|
||||
|
||||
root = g_file_new_for_path (g_get_current_dir ());
|
||||
dirmodel = create_list_model_for_directory (root, NULL);
|
||||
model = gtk_tree_list_new (dirmodel,
|
||||
create_list_model_for_directory,
|
||||
NULL, NULL);
|
||||
g_object_unref (dirmodel);
|
||||
gtk_list_box_bind_model (GTK_LIST_BOX (listbox),
|
||||
model,
|
||||
create_widget_for_model,
|
||||
root, g_object_unref);
|
||||
g_object_set_data (G_OBJECT (listbox), "model", model);
|
||||
g_object_unref (model);
|
||||
|
||||
gtk_widget_show (win);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -419,6 +419,15 @@ test_type (gconstpointer data)
|
||||
NULL);
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
else if (g_str_equal (g_type_name (type), "GdkDrop"))
|
||||
{
|
||||
GdkContentFormats *formats = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
|
||||
instance = g_object_new (type,
|
||||
"device", gdk_seat_get_pointer (gdk_display_get_default_seat (gdk_display_get_default ())),
|
||||
"formats", formats,
|
||||
NULL);
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
else
|
||||
instance = g_object_new (type, NULL);
|
||||
|
||||
|
||||
@@ -54,7 +54,8 @@ test_finalize_object (gconstpointer data)
|
||||
|
||||
if (g_str_equal (g_type_name (test_type), "GdkClipboard"))
|
||||
object = g_object_new (test_type, "display", gdk_display_get_default (), NULL);
|
||||
else if (g_str_equal (g_type_name (test_type), "GdkDragContext"))
|
||||
else if (g_str_equal (g_type_name (test_type), "GdkDragContext") ||
|
||||
g_str_equal (g_type_name (test_type), "GdkDrop"))
|
||||
{
|
||||
GdkContentFormats *formats = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
|
||||
object = g_object_new (test_type,
|
||||
|
||||
Reference in New Issue
Block a user