[gtk/wip/otte/dnd: 9/10] notebook: Use proper DND
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/dnd: 9/10] notebook: Use proper DND
- Date: Mon, 17 Feb 2020 04:01:13 +0000 (UTC)
commit 488449d0da253545d40a3d032252024dd5e98cbc
Author: Benjamin Otte <otte redhat com>
Date: Mon Feb 17 03:58:28 2020 +0100
notebook: Use proper DND
Actually use GValues for the DND operation instead of sending GBytes of
pointer addresses through pipes.
This is a bit complicated because we need to special-case rootwindow
drops, because they're handled on the source side, so we need a custom
ContentProvider.
gtk/gtknotebook.c | 185 ++++++++++++++++++++++++++++++++----------------------
1 file changed, 111 insertions(+), 74 deletions(-)
---
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
index 1d9370649a..d627c735b2 100644
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -235,7 +235,6 @@ struct _GtkNotebookPrivate
GtkNotebookDragOperation operation;
GtkNotebookPage *cur_page;
GtkNotebookPage *detached_tab;
- GdkContentFormats *source_targets;
GtkWidget *action_widget[N_ACTION_WIDGETS];
GtkWidget *menu;
GtkWidget *menu_box;
@@ -645,15 +644,105 @@ gtk_notebook_page_class_init (GtkNotebookPageClass *class)
}
-static const char *src_notebook_targets [] = {
- "GTK_NOTEBOOK_TAB",
- "application/x-rootwindow-drop"
+#define GTK_TYPE_NOTEBOOK_ROOT_CONTENT (gtk_notebook_root_content_get_type ())
+#define GTK_NOTEBOOK_ROOT_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_NOTEBOOK_ROOT_CONTENT,
GtkNotebookRootContent))
+#define GTK_IS_NOTEBOOK_ROOT_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GTK_TYPE_NOTEBOOK_ROOT_CONTENT))
+
+typedef struct _GtkNotebookRootContent GtkNotebookRootContent;
+typedef struct _GtkNotebookRootContentClass GtkNotebookRootContentClass;
+
+struct _GtkNotebookRootContent
+{
+ GdkContentProvider parent_instance;
+
+ GtkNotebook *notebook;
};
-static const char *dst_notebook_targets [] = {
- "GTK_NOTEBOOK_TAB"
+struct _GtkNotebookRootContentClass
+{
+ GdkContentProviderClass parent_class;
};
+static GdkContentFormats *
+gtk_notebook_root_content_ref_formats (GdkContentProvider *provider)
+{
+ return gdk_content_formats_new ((const char *[1]) { "application/x-rootwindow-drop" }, 1);
+}
+
+GType gtk_notebook_root_content_get_type (void);
+
+G_DEFINE_TYPE (GtkNotebookRootContent, gtk_notebook_root_content, GDK_TYPE_CONTENT_PROVIDER)
+
+static void
+gtk_notebook_root_content_write_mime_type_async (GdkContentProvider *provider,
+ const char *mime_type,
+ GOutputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GtkNotebookRootContent *self = GTK_NOTEBOOK_ROOT_CONTENT (provider);
+ GtkNotebookPrivate *priv = self->notebook->priv;
+ GTask *task;
+
+ priv->rootwindow_drop = TRUE;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (task, io_priority);
+ g_task_set_source_tag (task, gtk_notebook_root_content_write_mime_type_async);
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static gboolean
+gtk_notebook_root_content_write_mime_type_finish (GdkContentProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+gtk_notebook_root_content_finalize (GObject *object)
+{
+ GtkNotebookRootContent *self = GTK_NOTEBOOK_ROOT_CONTENT (object);
+
+ g_object_unref (self->notebook);
+
+ G_OBJECT_CLASS (gtk_notebook_root_content_parent_class)->finalize (object);
+}
+
+static void
+gtk_notebook_root_content_class_init (GtkNotebookRootContentClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
+
+ object_class->finalize = gtk_notebook_root_content_finalize;
+
+ provider_class->ref_formats = gtk_notebook_root_content_ref_formats;
+ provider_class->write_mime_type_async = gtk_notebook_root_content_write_mime_type_async;
+ provider_class->write_mime_type_finish = gtk_notebook_root_content_write_mime_type_finish;
+}
+
+static void
+gtk_notebook_root_content_init (GtkNotebookRootContent *self)
+{
+}
+
+static GdkContentProvider *
+gtk_notebook_root_content_new (GtkNotebook *notebook)
+{
+ GtkNotebookRootContent *result;
+
+ result = g_object_new (GTK_TYPE_NOTEBOOK_ROOT_CONTENT, NULL);
+
+ result->notebook = g_object_ref (notebook);
+
+ return GDK_CONTENT_PROVIDER (result);
+}
+
/*** GtkNotebook Methods ***/
static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
gboolean move_focus);
@@ -713,8 +802,6 @@ static gboolean gtk_notebook_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y);
-static GBytes * gtk_notebook_drag_data_get (const char *mime_type,
- gpointer data);
/*** GtkContainer Methods ***/
static void gtk_notebook_add (GtkContainer *container,
@@ -1321,8 +1408,6 @@ gtk_notebook_init (GtkNotebook *notebook)
priv->pressed_button = 0;
priv->dnd_timer = 0;
priv->switch_tab_timer = 0;
- priv->source_targets = gdk_content_formats_new (src_notebook_targets,
- G_N_ELEMENTS (src_notebook_targets));
priv->operation = DRAG_OPERATION_NONE;
priv->detached_tab = NULL;
priv->has_scrolled = FALSE;
@@ -1347,7 +1432,7 @@ gtk_notebook_init (GtkNotebook *notebook)
gtk_widget_set_vexpand (priv->stack_widget, TRUE);
gtk_widget_set_parent (priv->stack_widget, GTK_WIDGET (notebook));
- dest = gtk_drop_target_new (gdk_content_formats_new (dst_notebook_targets, G_N_ELEMENTS
(dst_notebook_targets)), GDK_ACTION_MOVE);
+ dest = gtk_drop_target_new (gdk_content_formats_new_for_gtype (GTK_TYPE_NOTEBOOK_PAGE), GDK_ACTION_MOVE);
g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_notebook_drag_motion), NULL);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_notebook_drag_leave), NULL);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_notebook_drag_drop), NULL);
@@ -1843,11 +1928,6 @@ gtk_notebook_destroy (GtkWidget *widget)
if (priv->pages)
g_list_model_items_changed (G_LIST_MODEL (priv->pages), 0, g_list_length (priv->children), 0);
- if (priv->source_targets)
- {
- gdk_content_formats_unref (priv->source_targets);
- priv->source_targets = NULL;
- }
remove_switch_tab_timer (notebook);
@@ -2877,10 +2957,10 @@ gtk_notebook_motion (GtkEventController *controller,
surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (notebook)));
device = gtk_get_current_event_device ();
- content = gdk_content_provider_new_with_formats (priv->source_targets,
- gtk_notebook_drag_data_get,
- widget,
- NULL);
+ content = gdk_content_provider_new_union ((GdkContentProvider *[2]) {
+ gtk_notebook_root_content_new (notebook),
+ gdk_content_provider_new_typed (GTK_TYPE_NOTEBOOK_PAGE,
priv->cur_page)
+ }, 2);
drag = gdk_drag_begin (surface, device, content, GDK_ACTION_MOVE, priv->drag_begin_x,
priv->drag_begin_y);
g_object_unref (content);
@@ -3241,13 +3321,11 @@ gtk_notebook_drag_motion (GtkDropTarget *dest,
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
graphene_rect_t position;
- GdkAtom target, tab_target;
+ GdkContentFormats *formats;
GList *tab;
- target = gtk_drop_target_find_mimetype (dest);
- tab_target = g_intern_static_string ("GTK_NOTEBOOK_TAB");
-
- if (target == tab_target)
+ formats = gtk_drop_target_get_formats (dest);
+ if (gdk_content_formats_contain_gtype (formats, GTK_TYPE_NOTEBOOK_PAGE))
{
GQuark group, source_group;
GtkWidget *source_child;
@@ -3320,34 +3398,26 @@ gtk_notebook_drag_leave (GtkDropTarget *dest)
}
static void
-got_page (GObject *source,
+got_page (GObject *source,
GAsyncResult *result,
- gpointer data)
+ gpointer data)
{
GtkNotebook *notebook = GTK_NOTEBOOK (data);
GdkDrop *drop = GDK_DROP (source);
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget;
- GInputStream *stream;
- const char *mime_type;
+ const GValue *value;
source_widget = GTK_WIDGET (drag ? g_object_get_data (G_OBJECT (drag), "gtk-notebook-drag-origin") : NULL);
- stream = gdk_drop_read_finish (drop, result, &mime_type, NULL);
+ value = gdk_drop_read_value_finish (drop, result, NULL);
- if (stream)
+ if (value)
{
- GBytes *bytes;
- GtkWidget **child;
+ GtkNotebookPage *page = g_value_get_object (value);
- bytes = g_input_stream_read_bytes (stream, sizeof (gpointer), NULL, NULL);
- child = (gpointer)g_bytes_get_data (bytes, NULL);
-
- do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, *child);
+ do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, page->child);
gdk_drop_finish (drop, GDK_ACTION_MOVE);
-
- g_bytes_unref (bytes);
- g_object_unref (stream);
}
else
gdk_drop_finish (drop, 0);
@@ -3364,21 +3434,16 @@ gtk_notebook_drag_drop (GtkDropTarget *dest,
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget;
- GdkAtom target, tab_target;
source_widget = GTK_WIDGET (drag ? g_object_get_data (G_OBJECT (drag), "gtk-notebook-drag-origin") : NULL);
- target = gtk_drop_target_find_mimetype (dest);
- tab_target = g_intern_static_string ("GTK_NOTEBOOK_TAB");
-
if (GTK_IS_NOTEBOOK (source_widget) &&
- target == tab_target &&
(gdk_drop_get_actions (drop) & GDK_ACTION_MOVE))
{
notebook->priv->mouse_x = x;
notebook->priv->mouse_y = y;
- gdk_drop_read_async (drop, (const char *[]) { "GTK_NOTEBOOK_TAB", NULL }, G_PRIORITY_DEFAULT, NULL,
got_page, notebook);
+ gdk_drop_read_value_async (drop, GTK_TYPE_NOTEBOOK_PAGE, G_PRIORITY_DEFAULT, NULL, got_page, notebook);
return TRUE;
}
@@ -3467,34 +3532,6 @@ do_detach_tab (GtkNotebook *from,
gtk_notebook_set_current_page (to, page_num);
}
-static GBytes *
-gtk_notebook_drag_data_get (const char *mime_type,
- gpointer data)
-{
- GtkNotebook *notebook = GTK_NOTEBOOK (data);
- GtkNotebookPrivate *priv = notebook->priv;
- GtkSelectionData sdata = { 0, };
-
- sdata.target = g_intern_string (mime_type);
-
- if (sdata.target == g_intern_static_string ("GTK_NOTEBOOK_TAB"))
- {
- gtk_selection_data_set (&sdata,
- sdata.target,
- 8,
- (void*) &priv->detached_tab->child,
- sizeof (gpointer));
- priv->rootwindow_drop = FALSE;
- }
- else if (sdata.target == g_intern_static_string ("application/x-rootwindow-drop"))
- {
- gtk_selection_data_set (&sdata, sdata.target, 8, NULL, 0);
- priv->rootwindow_drop = TRUE;
- }
-
- return g_bytes_new_take (sdata.data, sdata.length);
-}
-
/* Private GtkContainer Methods :
*
* gtk_notebook_add
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]