Compare commits

...

45 Commits

Author SHA1 Message Date
Benjamin Otte 3b4f3520c9 gtk: Add GtkTreeList
This is a GListModel implementation with a neat API that can be used to
implement trees inside GtkListBox.
2018-06-12 03:56:21 +02:00
Benjamin Otte 9aba2c435f rendernode: Use g_slice_alloc()
g_slice_alloc() conforms to the allocation requirements for graphene
structs, g_malloc() does not.
2018-06-11 14:50:51 +02:00
Benjamin Otte b8b9cc3805 dnd: Remove gdk_drag_context_get_dest_surface()
... and gdk_drag_context_get_source_surface().

In the backends, use direct access to the variables instead.
2018-06-10 03:17:12 +02:00
Benjamin Otte 7769be22f0 dnd: Implement gtk_drag_get_source_widget() differently
Instead of keeping a list of source contexts, just use the current
drag's info.
2018-06-10 03:17:12 +02:00
Benjamin Otte 00a171626d x11: Replace the hardcoded DND filter
Use the new method of connecting to the xevent signal instead.

Also, don't consume the xevent, there might be other code listening for
it. And we don't use PropertyNotify in the generic code path anymore, so
it'll just be ignored there.
2018-06-10 03:17:12 +02:00
Руслан Ижбулатов bdc37cf161 GDK W32: Remove unused files 2018-06-10 03:17:12 +02:00
Руслан Ижбулатов ad7d4acc77 GDK W32: Adapt to GdkDrop and GdkDragContext changes
* Remove clipdrop->dnd_target_state, it's not used anymore
* Remove non-functioning _gdk_dropfiles_store(), store dropfiles
  list in GdkWin32Drop instead
* Fix multiple comment typos
* Fix _gdk_win32_get_clipboard_format_name_as_interned_mimetype() to
  leave names that look like mime/types alone
* Refactor _gdk_win32_add_w32format_to_pairs() to populate
  GdkContentFormatsBuilder directly, instead of making a GList
* Rename context -> drag (still using GdkDragContext type,
  but [almost?] all variables and comments say "drag" now)
* Rename GdkDropContext -> GdkDrop
* Rename some parameter names for clarity
* Rewrite local protocol to look more like OLE2 protocol
  instead of mirroring the structure of the X11 API.
* Add handle_events field to GdkWin32DragContext,
  to shut off event handling (temporary fix until GTK is patched up)
* Remove _gdk_win32_drag_context_find() - the drag object is stored
  in GdkDrop instead. Use _gdk_win32_find_drag_for_dest_surface()
  to get it initially.
* Remove target_ctx_for_window, droptarget context is stored
  in the surface instead.
* Call gdk_drag_context_set_cursor() just like wayland backend does
  (slightly broken for now)
* Clean up the action choosing code (filter source actions by using
  keyboard state, pass that to GTK, get all actions supported by GTK in
  response, match them up with filtered source actions, return the
  result, falling back to COPY in case of multiple actions)
* Check drag_win32->protocol instead of the use_ole2_dnd variable where
  possible
* Remove protocol checks from functions that are only used by the local
  protocol
* Use event state to manufacture the keyboard state for WM_MOUSEMOVE
* Change function names printed by GDK_NOTE to name the actual
  functions, not their theoretical generic GDK stack ancestors
* Consistently use drag_win32 and drop_win32 variables instead of a mix
  of that and win32_drag/win32_drop
* Return FALSE from button handler to ensure that GTK gets the button
  event to break implicit grab
* Emit leave event on failed idroptarget_drop() calls
2018-06-10 03:17:12 +02:00
Benjamin Otte 604a85b852 dnd: Add read_value() and read_text() functions to GdkDrop
These just copy what GdkClipboard does.
2018-06-10 03:17:12 +02:00
Benjamin Otte 209ceaa844 drop: Implement shortcut for local DND
Now that we have the drop->drag, we can use the same shortcut we use in
the clipboard code to shortcut DND operations.
2018-06-10 03:17:12 +02:00
Benjamin Otte 8d1bdcef8f x11: Pass the drag source when creating a drop context 2018-06-10 03:17:12 +02:00
Benjamin Otte 431f78a992 x11: Find dest drops differently
Instead of looking at the list of contexts, just look at the current
drop context. There is only one, after all.

Then remove the is_source argument from gdk_drag_context_find().
2018-06-10 03:17:12 +02:00
Benjamin Otte bce4305bee wayland: Store the current drag operation
Use it to detect local drags when creating drop objects.
2018-06-10 03:17:12 +02:00
Benjamin Otte 58a6c8f237 dnd: Move GdkDragAction to gdktypes.h
That way, both gdkdrag.h and gdkdrop.h can use it without one having to
include the other.
2018-06-10 03:17:12 +02:00
Benjamin Otte 637d5d633c gdk: Remove leftover type from autocleanup 2018-06-10 03:17:12 +02:00
Benjamin Otte 31e850cd7f wayland: Get rid of GdkWaylandSelection
Move data source handling into the DND code instead.
2018-06-10 03:17:12 +02:00
Benjamin Otte cde1ee8662 wayland: Split drop context into GdkWaylandDrop
GdkWaylandDrop no longer inherits from GdkDragContext now.
2018-06-10 03:17:12 +02:00
Benjamin Otte 3c4d1356a0 wayland: Remove a bunch of unused functions 2018-06-10 03:17:11 +02:00
Benjamin Otte 1413ce13cb events: Make GdkEventDND have a GdkDrop member
... instead of a GdkDragContext.
2018-06-10 03:17:11 +02:00
Benjamin Otte 70ef32bb29 x11: Refactor DND filter
The filters now return TRUE/FALSE and no longer a GdkFilterReturn. They
also don't conform to the GdkFilterFunc typedef anymore but instead take
the arguments that they need.
2018-06-10 03:17:11 +02:00
Benjamin Otte af70ca4ca2 x11: Use new DND event emitters 2018-06-10 03:17:11 +02:00
Benjamin Otte de3a0dbcfd win32: Use new DND event emitters 2018-06-10 03:17:11 +02:00
Benjamin Otte 7ff9738561 wayland: Use new DND event emitters 2018-06-10 03:17:11 +02:00
Benjamin Otte 9870688e27 drop: Add private API for event emission 2018-06-10 03:17:11 +02:00
Benjamin Otte 41cc232c55 drop: Add GdkDrop:surface property
This replaces gdk_drag_context_get_dest_surface().
2018-06-10 03:17:11 +02:00
Benjamin Otte 7f715168c9 display: Don't wake up the main loop anymore
This is not needed because GTK must be run in the main thread these days,
which is the same one that runs the main loop. So when this function is
called, the main loop is awake.

https://bugzilla.gnome.org/show_bug.cgi?id=550989
2018-06-10 03:17:11 +02:00
Benjamin Otte 0d78bc7500 x11: Don't sneakily allocate memory in initializers 2018-06-10 03:17:11 +02:00
Benjamin Otte 83af276f35 dnd: Add gdk_event_get_drop()
And remove gdk_event_get_drag_context().

All GTK code now only uses GdkDrop for dropping.
2018-06-10 03:17:11 +02:00
Benjamin Otte 0964f2b2c0 wayland: Fix drop operations for new semantics 2018-06-10 03:17:11 +02:00
Benjamin Otte e2891cd506 dnd: Remove GdkDragContext::commit_drag_status() vfunc
The idea behind the vfunc doesn't work as status updates can happen
asynchronously.

A better solution needs to be found.
2018-06-10 03:17:11 +02:00
Benjamin Otte f40f33afb9 dnd: Make drag-motion and drag-drop signals use GdkDrop 2018-06-10 03:17:11 +02:00
Benjamin Otte 2a85948942 dnd: Make drag-data-received use a GdkDrop 2018-06-10 03:16:51 +02:00
Benjamin Otte d4b8579488 drop: Add gdk_drop_get_drag()
For now, it'll always return NULL. We'll fix that later.
2018-06-10 03:16:51 +02:00
Benjamin Otte b5d89153b5 widget: Make GtkWidgetClass::drag_leave() take a GdkDrop
Drag Contexts are on their way out!
2018-06-10 03:16:51 +02:00
Benjamin Otte 390012a633 dnd: Add gdk_drop_finish()
and move the vfunc into GdkDrop.
2018-06-10 03:16:51 +02:00
Benjamin Otte 60d83804d7 dnd: Get rid of gtk_drag_finish()
It's just a wrapper around gdk_drag_finish(), so use that one instead.
2018-06-10 03:16:51 +02:00
Benjamin Otte ed8423e15c dnd: Rename gdk_drop_finish() => gdk_drag_finish()
This is a simple rename, so that we can reintroduce gdk_drop_finish()
with the GdkDrop object.
2018-06-10 03:16:51 +02:00
Benjamin Otte 63571fc5e5 dnd: Move the gdk_drag_status() function
It's now gdk_drop_status().

Also clarify the intended semantics.
2018-06-10 03:16:51 +02:00
Benjamin Otte b36c5e48e3 dnd: Add gdk_drop_get_actions()
This uses the new method without GDK_ACTION_ASK:

Either it is a single action (queryable via gdk_drag_action_is_unique())
or it is not and then the drop target has to make a decision
(potentially by asking someone).
2018-06-10 03:16:51 +02:00
Benjamin Otte 2d6e88e3ee dnd: Make actions a private member variable
Use a setter in the backends.
2018-06-10 03:16:51 +02:00
Benjamin Otte 0c1f739c1a x11: Remove unused variables 2018-06-10 03:16:51 +02:00
Benjamin Otte 8aadfd730e wayland: Set correct variable
This got messed up in commit 7f8a8f221d.
2018-06-10 03:16:51 +02:00
Benjamin Otte 7b2e2d6bad dnd: Add gdk_drag_action_is_unique()
This will be necessary once we remove the ASK action.
2018-06-10 03:16:51 +02:00
Benjamin Otte 34c2e1b3fb dnd: Remove GDK_ACTION_DEFAULT and GDK_ACTION_PRIVATE
They're unused and nobody knows what they're supposed to men anyway.
2018-06-10 03:16:51 +02:00
Benjamin Otte 7be144b436 drop: Move gdk_drop_read_async() to GdkDrop class 2018-06-10 03:16:51 +02:00
Benjamin Otte 0ee542e588 dnd: Add GdkDrop base class for GdkDragContext
The ultimate goal of this patch series is to split GdkDragContext into
GdkDrop + GdkDrag classes for the destination and source side of a dnd
operation.

The refactoring is meant to work something like this:
1. Introduce GdkDrop as a base class
2. Make all drop related code (like GdkEvent) use GdkDrop instead of
   GdkDragContext. Move/duplicate APIs to allow that.
3. Port all drop contexts in the backends from GdkDragContext to GdkDrop
4. Delete all APIs in GdkDragContext that aren't needed anymore.
5. Make GdkDragContext no longer a GdkDrop subclass
6. Rename GdkDragContext to GdkDrag
2018-06-10 03:16:51 +02:00
85 changed files with 5666 additions and 6282 deletions
+1 -2
View File
@@ -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)
+1 -1
View File
@@ -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);
+6 -4
View File
@@ -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
-1
View File
@@ -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
-20
View File
@@ -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;
}
-1
View File
@@ -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)
+1
View File
@@ -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>
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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 doesnt 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
View File
@@ -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
View File
@@ -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);
}
+98
View File
@@ -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__ */
+81
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+2 -2
View File
@@ -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;
+30
View File
@@ -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__ */
+2
View File
@@ -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',
+4 -12
View File
@@ -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
-18
View File
@@ -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;
}
+48 -54
View File
@@ -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
-17
View File
@@ -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,
-2
View File
@@ -139,8 +139,6 @@ struct _GdkWaylandDisplay
struct xkb_context *xkb_context;
GdkWaylandSelection *selection;
GPtrArray *monitors;
gint64 last_bell_time_ms;
+206 -195
View File
@@ -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;
}
+325
View File
@@ -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);
}
+13 -27
View File
@@ -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);
-204
View File
@@ -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,
+1
View File
@@ -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',
+32 -53
View File
@@ -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);
}
}
+32 -34
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+667 -500
View File
File diff suppressed because it is too large Load Diff
+4 -7
View File
@@ -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 ",
-2
View File
@@ -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
+2 -2
View File
@@ -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
-230
View File
@@ -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__ */
+3
View File
@@ -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);
+12
View File
@@ -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;
+42 -39
View File
@@ -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
-17
View File
@@ -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
View File
@@ -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));
+2 -8
View File
@@ -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)
-5
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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,
+1
View File
@@ -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
View File
@@ -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 doesnt 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));
+2 -8
View File
@@ -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);
+2 -3
View File
@@ -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;
+750
View File
@@ -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);
}
+89
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 widgets 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
View File
@@ -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
View File
@@ -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);
+8 -11
View File
@@ -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
View File
@@ -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 files location" and other context menu items if there is actually
+79 -73
View File
@@ -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 doesnt 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
View File
@@ -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));
}
+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
{
+1 -1
View File
@@ -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);
+6 -8
View File
@@ -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
View File
@@ -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,
+569
View File
@@ -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;
}
+64
View File
@@ -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
View File
@@ -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 doesnt 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
View File
@@ -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
View File
@@ -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);
+3
View File
@@ -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',
+1
View File
@@ -113,6 +113,7 @@ gtk_tests = [
['testrevealer'],
['testrevealer2'],
['testtitlebar'],
['testtreelist'],
['testsplitheaders'],
['teststackedheaders'],
['testactionbar'],
+58 -46
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+1 -2
View File
@@ -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
View File
@@ -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;
+151
View File
@@ -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;
}
+9
View File
@@ -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);
+2 -1
View File
@@ -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,