Compare commits

...

29 Commits

Author SHA1 Message Date
Matthias Clasen df684b8d04 Hook up the GtkDragSource docs 2020-01-03 13:02:16 -05:00
Matthias Clasen ced714e8be Move the rest of the drag-source api over
Just reshuffling some source.
2020-01-03 13:02:16 -05:00
Matthias Clasen 84127c7f7b docs: Mention DND in the migration guide 2020-01-03 13:02:16 -05:00
Matthias Clasen 2b4e9e10c2 Remove traditional drag source API
gtk_drag_source_set, gtk_drag_begin, related apis
and the GtkWidget source-side signals have all been
replaced by GtkDragSource.
2020-01-03 13:02:16 -05:00
Matthias Clasen 435e4e0fb0 tests: Convert to GtkDragSource
Some tests, such as testimage did not have
anything particularly worth keeping, so
were removed instead of fixed.
2020-01-03 13:02:16 -05:00
Matthias Clasen 3616c33ddd notebook: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 811b1005f9 filechooser: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen caeb0d3907 treeview: Port to GtkDragSource
A small api change here is that
gtk_tree_view_enable_model_drag_source now returns
a GtkDragSource that can be used to connect signals.
2020-01-03 13:02:16 -05:00
Matthias Clasen 4a3e75c123 placessidebar: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 28aeb01f9b iconview: Port to GtkDragSource
A small api change here is that
gtk_icon_view_enable_model_drag_source now returns
a GtkDragSource that can be used to connect signals.
2020-01-03 13:02:16 -05:00
Matthias Clasen ad11933eee Add another callback-based provider
This one can be used in cases where data needs
to be served in multiple formats that may not
all be covered by content serializers.
2020-01-03 13:02:16 -05:00
Matthias Clasen 27460826b3 iconbrowser: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 9d65f8d5b2 gtk-demo: Convert the clipboard demo to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 783af4c868 pathbar: Convert to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 7df168859b colorswatch: Convert to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 29418978f7 colorbutton: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 63856c4830 Add a generic callback content provider
This one is convenient to use in cases where a
drag is just serving an existing GType which
is covered by content serializers.
2020-01-03 13:02:16 -05:00
Matthias Clasen f207b2be00 Add (de)serializers for GdkRGBA
This is a format that we use in various
color picker widgets, so support it in GDK.
2020-01-03 13:02:16 -05:00
Matthias Clasen 132373f032 textview: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 5d7e637165 textbuffer: Add a content provider api
We need a content provider for the selection,
to implement DND, and the text buffer already
has one. Just add an api to get it.
2020-01-03 13:02:16 -05:00
Matthias Clasen adab150ac1 text: Convert to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 63362bcd41 entry: Port icon dnd to GtkDragSource
This requires a small change in the api,
since we need to provide a GdkContentProvider now.
2020-01-03 13:02:16 -05:00
Matthias Clasen 1bc6a25a01 calendar: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen 93f1e74bfa linkbutton: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen fef5d7d200 label: Port to GtkDragSource 2020-01-03 13:02:16 -05:00
Matthias Clasen cd7b278e77 dnd: Patch up gtk_drag_get_source_widget
This is temporary until gtk_drag_dest_set users
have been ported over.
2020-01-03 13:02:16 -05:00
Matthias Clasen 9809a313db Add a GtkDragSource object
Add an explicit GtkDragSource object, and move the source-side
DND signals here. The object can be used on the spot, by calling
gtk_drag_source_drag_begin() yourself, or for static drag-source
configuration, by calling gtk_drag_source_attach(). In the latter
case, we set up and conect a drag gesture to trigger the drag_begin
call.
2020-01-03 13:02:16 -05:00
Matthias Clasen f8347cb228 marshalers: Add another 2020-01-03 13:02:16 -05:00
Matthias Clasen 189ff2d99a docs: Add content format api
Putting these in the GtkSelectionData chapter is
temporary; GtkSelectionData is going away.
2020-01-03 13:02:16 -05:00
47 changed files with 2044 additions and 2669 deletions
+22 -25
View File
@@ -119,32 +119,27 @@ get_image_paintable (GtkImage *image)
}
static void
drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
drag_begin (GtkDragSource *source,
GtkWidget *widget)
{
GdkPaintable *paintable;
paintable = get_image_paintable (GTK_IMAGE (widget));
if (paintable)
{
gtk_drag_set_icon_paintable (drag, paintable, -2, -2);
gtk_drag_source_set_icon (source, paintable, -2, -2);
g_object_unref (paintable);
}
}
void
drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
guint info,
gpointer data)
static void
get_texture (GValue *value,
gpointer data)
{
GdkPaintable *paintable;
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data));
paintable = get_image_paintable (GTK_IMAGE (widget));
if (GDK_IS_TEXTURE (paintable))
gtk_selection_data_set_texture (selection_data, GDK_TEXTURE (paintable));
g_value_set_object (value, paintable);
}
static void
@@ -247,6 +242,8 @@ do_clipboard (GtkWidget *do_widget)
{ "paste", paste_image, NULL, NULL, NULL },
};
GActionGroup *actions;
GdkContentProvider *content = NULL;
GtkDragSource *source;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
@@ -305,15 +302,15 @@ do_clipboard (GtkWidget *do_widget)
/* Create the first image */
image = gtk_image_new_from_icon_name ("dialog-warning");
gtk_image_set_pixel_size (GTK_IMAGE (image), 48);
gtk_container_add (GTK_CONTAINER (hbox), image);
/* make image a drag source */
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
gtk_drag_source_add_image_targets (image);
g_signal_connect (image, "drag-begin",
G_CALLBACK (drag_begin), image);
g_signal_connect (image, "drag-data-get",
G_CALLBACK (drag_data_get), image);
content = gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
gtk_drag_source_attach (source, image, GDK_BUTTON1_MASK);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
/* accept drops on image */
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL,
@@ -337,15 +334,15 @@ do_clipboard (GtkWidget *do_widget)
/* Create the second image */
image = gtk_image_new_from_icon_name ("process-stop");
gtk_image_set_pixel_size (GTK_IMAGE (image), 48);
gtk_container_add (GTK_CONTAINER (hbox), image);
/* make image a drag source */
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
gtk_drag_source_add_image_targets (image);
g_signal_connect (image, "drag-begin",
G_CALLBACK (drag_begin), image);
g_signal_connect (image, "drag-data-get",
G_CALLBACK (drag_data_get), image);
content = gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_drag_source_attach (source, image, GDK_BUTTON1_MASK);
/* accept drops on image */
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL,
+75 -72
View File
@@ -5,9 +5,6 @@
#include <gtk/gtk.h>
/* Drag 'n Drop */
static const char *target_table[] = {
"text/uri-list"
};
typedef struct
{
@@ -76,30 +73,11 @@ search_text_changed (GtkEntry *entry, IconBrowserWindow *win)
gtk_tree_model_filter_refilter (win->filter_model);
}
static GdkPixbuf *
get_icon (GtkWidget *image, const gchar *name, gint size)
{
GtkIconInfo *info;
GtkStyleContext *context;
GdkTexture *texture;
GdkPixbuf *pixbuf;
context = gtk_widget_get_style_context (image);
info = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_default (), name, size, 0);
texture = GDK_TEXTURE (gtk_icon_info_load_symbolic_for_context (info, context, NULL, NULL));
pixbuf = gdk_pixbuf_get_from_texture (texture);
g_object_unref (texture);
g_object_unref (info);
return pixbuf;
}
static void
set_image (GtkWidget *image, const gchar *name, gint size)
{
gtk_image_set_from_icon_name (GTK_IMAGE (image), name);
gtk_image_set_pixel_size (GTK_IMAGE (image), size);
gtk_drag_source_set_icon_name (image, name);
}
static void
@@ -365,78 +343,104 @@ search_mode_toggled (GObject *searchbar, GParamSpec *pspec, IconBrowserWindow *w
gtk_list_box_unselect_all (GTK_LIST_BOX (win->context_list));
}
static void
get_image_data (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection,
guint target_info,
gpointer data)
static GdkPaintable *
get_image_paintable (GtkImage *image)
{
GtkWidget *image;
const gchar *name;
gint size;
GdkPixbuf *pixbuf;
const gchar *icon_name;
GtkIconTheme *icon_theme;
GtkIconInfo *icon_info;
int size;
image = gtk_bin_get_child (GTK_BIN (widget));
name = gtk_image_get_icon_name (GTK_IMAGE (image));
size = gtk_image_get_pixel_size (GTK_IMAGE (image));
pixbuf = get_icon (image, name, size);
gtk_selection_data_set_pixbuf (selection, pixbuf);
g_object_unref (pixbuf);
switch (gtk_image_get_storage_type (image))
{
case GTK_IMAGE_PAINTABLE:
return g_object_ref (gtk_image_get_paintable (image));
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (image);
size = gtk_image_get_pixel_size (image);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size,
GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
if (icon_info == NULL)
return NULL;
return gtk_icon_info_load_icon (icon_info, NULL);
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
return NULL;
}
}
static void
get_scalable_image_data (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection,
guint target_info,
gpointer data)
drag_begin (GtkDragSource *source,
GtkWidget *widget)
{
gchar *uris[2];
GtkIconInfo *info;
GtkWidget *image;
GFile *file;
const gchar *name;
GdkPaintable *paintable;
image = gtk_bin_get_child (GTK_BIN (widget));
name = gtk_image_get_icon_name (GTK_IMAGE (image));
paintable = get_image_paintable (GTK_IMAGE (widget));
if (paintable)
{
int w, h;
w = gdk_paintable_get_intrinsic_width (paintable);
h = gdk_paintable_get_intrinsic_height (paintable);
gtk_drag_source_set_icon (source, paintable, w, h);
g_object_unref (paintable);
}
}
static void
get_texture (GValue *value,
gpointer data)
{
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data));
if (GDK_IS_TEXTURE (paintable))
g_value_set_object (value, paintable);
}
static void
get_file (GValue *value,
gpointer data)
{
const char *name;
GtkIconInfo *info;
GFile *file;
name = gtk_image_get_icon_name (GTK_IMAGE (data));
info = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_default (), name, -1, 0);
file = g_file_new_for_path (gtk_icon_info_get_filename (info));
uris[0] = g_file_get_uri (file);
uris[1] = NULL;
gtk_selection_data_set_uris (selection, uris);
g_free (uris[0]);
g_object_unref (info);
g_value_set_object (value, file);
g_object_unref (file);
g_object_unref (info);
}
static void
setup_image_dnd (GtkWidget *image)
{
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
gtk_drag_source_add_image_targets (image);
g_signal_connect (image, "drag-data-get", G_CALLBACK (get_image_data), NULL);
GdkContentProvider *content;
GtkDragSource *source;
content = gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_drag_source_attach (source, image, GDK_BUTTON1_MASK);
}
static void
setup_scalable_image_dnd (GtkWidget *image)
{
GtkWidget *parent;
GdkContentFormats *targets;
GdkContentProvider *content;
GtkDragSource *source;
parent = gtk_widget_get_parent (image);
targets = gdk_content_formats_new (target_table, G_N_ELEMENTS (target_table));
gtk_drag_source_set (parent, GDK_BUTTON1_MASK,
targets,
GDK_ACTION_COPY);
gdk_content_formats_unref (targets);
content = gdk_content_provider_new_with_callback (G_TYPE_FILE, get_file, image);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
g_signal_connect (parent, "drag-data-get", G_CALLBACK (get_scalable_image_data), NULL);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_drag_source_attach (source, image, GDK_BUTTON1_MASK);
}
static void
@@ -459,7 +463,6 @@ icon_browser_window_init (IconBrowserWindow *win)
setup_image_dnd (win->image3);
setup_image_dnd (win->image4);
setup_image_dnd (win->image5);
setup_image_dnd (win->image6);
setup_scalable_image_dnd (win->image6);
win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, context_free);
+5
View File
@@ -344,6 +344,11 @@
<xi:include href="xml/gtkpadcontroller.xml" />
</chapter>
<chapter>
<title>Data exchange, clipboards and Drag-and-Drop</title>
<xi:include href="xml/gtkdragsource.xml"/>
</chapter>
</part>
<part id="gtkbase">
+33
View File
@@ -451,6 +451,7 @@ gtk_selection_model_unselect_all
gtk_selection_model_query_range
<SUBSECTION>
gtk_selection_model_selection_changed
<SUBSECTION Standard>
GTK_SELECTION_MODEL
GTK_SELECTION_MODEL_CLASS
@@ -4995,6 +4996,10 @@ gtk_targets_include_text
gtk_targets_include_uri
gtk_selection_data_copy
gtk_selection_data_free
<SUBSECTION>
gtk_content_formats_add_text_targets
gtk_content_formats_add_image_targets
gtk_content_formats_add_uri_targets
<SUBSECTION Standard>
GTK_TYPE_SELECTION_DATA
<SUBSECTION Private>
@@ -7191,3 +7196,31 @@ gtk_constraint_guide_get_max_size
GTK_TYPE_CONSTRAINT_GUIDE
gtk_constraint_guide_get_tyoe
</SECTION>
<SECTION>
<FILE>gtkdragsource</FILE>
GtkDragSource
gtk_drag_source_new
gtk_drag_source_set_content
gtk_drag_source_get_content
gtk_drag_source_set_actions
gtk_drag_source_get_actions
gtk_drag_source_set_icon
gtk_drag_source_drag_begin
gtk_drag_source_drag_cancel
gtk_drag_get_source
gtk_drag_source_get_origin
gtk_drag_source_get_drag
gtk_drag_source_attach
gtk_drag_source_detach
gtk_drag_check_threshold
<SUBSECTION Standard>
GTK_TYPE_DRAG_SOURCE
GTK_DRAG_SOURCE
GTK_DRAG_SOURCE_CLASS
GTK_IS_DRAG_SOURCE
GTK_IS_DRAG_SOURCE_CLASS
GTK_DRAG_SOURCE_GET_CLASS
<SUBSECTION Private>
gtk_drag_source_get_type
</SECTION>
+1
View File
@@ -57,6 +57,7 @@ gtk_constraint_target_get_type
gtk_container_get_type
gtk_css_provider_get_type
gtk_dialog_get_type
gtk_drag_source_get_type
gtk_drawing_area_get_type
gtk_editable_get_type
gtk_entry_buffer_get_type
+16
View File
@@ -903,6 +903,22 @@
gtk_tooltip_set_custom().
</para>
</section>
<section>
<title>Switch to the new DND api</title>
<para>
The source-side DND apis in GTK 4 have been changed to use a separate object, #GtkDragSource.
</para>
<para>
Instead of calling gtk_drag_source_set() and connecting to #GtkWidget signals, you create
a #GtkDragSource object, attach it to the widget with gtk_drag_source_attach(), and connect
to #GtkDragSource signals. The signals themselves are fairly similar.
</para>
<para>
Instead of calling gtk_drag_begin() on a widget, use a #GtkDragSource object and call
gtk_drag_source_drag_begin().
</para>
</section>
</section>
</chapter>
+64
View File
@@ -24,6 +24,7 @@
#include "gdkcontentformats.h"
#include "filetransferportalprivate.h"
#include "gdktexture.h"
#include "gdkrgbaprivate.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -848,6 +849,63 @@ file_uri_deserializer (GdkContentDeserializer *deserializer)
g_object_unref (output);
}
static void
color_deserializer_finish (GObject *source,
GAsyncResult *result,
gpointer deserializer)
{
GOutputStream *stream = G_OUTPUT_STREAM (source);
GError *error = NULL;
gssize written;
written = g_output_stream_splice_finish (stream, result, &error);
if (written < 0)
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
else if (written == 0)
{
GdkRGBA black = GDK_RGBA ("000");
/* Never return NULL, we only return that on error */
g_value_set_boxed (gdk_content_deserializer_get_value (deserializer), &black);
}
else
{
guint16 *data;
GdkRGBA rgba;
data = (guint16 *)g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (stream));
rgba.red = data[0] / 65535.0;
rgba.green = data[1] / 65535.0;
rgba.blue = data[2] / 65535.0;
rgba.alpha = data[3] / 65535.0;
g_value_set_boxed (gdk_content_deserializer_get_value (deserializer), &rgba);
}
gdk_content_deserializer_return_success (deserializer);
}
static void
color_deserializer (GdkContentDeserializer *deserializer)
{
GOutputStream *output;
guint16 *data;
data = g_new0 (guint16, 4);
output = g_memory_output_stream_new (data, 4 * sizeof (guint16), NULL, g_free);
g_output_stream_splice_async (output,
gdk_content_deserializer_get_input_stream (deserializer),
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
gdk_content_deserializer_get_priority (deserializer),
gdk_content_deserializer_get_cancellable (deserializer),
color_deserializer_finish,
deserializer);
g_object_unref (output);
}
static void
init (void)
{
@@ -956,5 +1014,11 @@ init (void)
string_deserializer,
(gpointer) "ASCII",
NULL);
gdk_content_register_deserializer ("application/x-color",
GDK_TYPE_RGBA,
color_deserializer,
NULL,
NULL);
}
+230
View File
@@ -280,3 +280,233 @@ gdk_content_provider_new_for_bytes (const char *mime_type,
return GDK_CONTENT_PROVIDER (content);
}
#define GDK_TYPE_CONTENT_PROVIDER_CALLBACK (gdk_content_provider_callback_get_type ())
#define GDK_CONTENT_PROVIDER_CALLBACK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_CALLBACK, GdkContentProviderCallback))
typedef struct _GdkContentProviderCallback GdkContentProviderCallback;
typedef struct _GdkContentProviderCallbackClass GdkContentProviderCallbackClass;
struct _GdkContentProviderCallback
{
GdkContentProvider parent;
GType type;
GdkContentProviderGetValueFunc func;
gpointer data;
};
struct _GdkContentProviderCallbackClass
{
GdkContentProviderClass parent_class;
};
GType gdk_content_provider_callback_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GdkContentProviderCallback, gdk_content_provider_callback, GDK_TYPE_CONTENT_PROVIDER)
static GdkContentFormats *
gdk_content_provider_callback_ref_formats (GdkContentProvider *provider)
{
GdkContentProviderCallback *callback = GDK_CONTENT_PROVIDER_CALLBACK (provider);
return gdk_content_formats_new_for_gtype (callback->type);
}
static gboolean
gdk_content_provider_callback_get_value (GdkContentProvider *provider,
GValue *value,
GError **error)
{
GdkContentProviderCallback *callback = GDK_CONTENT_PROVIDER_CALLBACK (provider);
if (G_VALUE_HOLDS (value, callback->type) && callback->func != NULL)
{
callback->func (value, callback->data);
return TRUE;
}
return GDK_CONTENT_PROVIDER_CLASS (gdk_content_provider_callback_parent_class)->get_value (provider, value, error);
}
static void
gdk_content_provider_callback_class_init (GdkContentProviderCallbackClass *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
provider_class->ref_formats = gdk_content_provider_callback_ref_formats;
provider_class->get_value = gdk_content_provider_callback_get_value;
}
static void
gdk_content_provider_callback_init (GdkContentProviderCallback *content)
{
}
/**
* gdk_content_provider_new_for_callback:
* @type: the type that the callback provides
* @func: callback to populate a #GValue
* @data: data that gets passed to @func
*
* Create a content provider that provides data that is provided via a callback.
*
* Returns: a new #GdkContentProvider
**/
GdkContentProvider *
gdk_content_provider_new_with_callback (GType type,
GdkContentProviderGetValueFunc func,
gpointer data)
{
GdkContentProviderCallback *content;
content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_CALLBACK, NULL);
content->type = type;
content->func = func;
content->data = data;
return GDK_CONTENT_PROVIDER (content);
}
#define GDK_TYPE_CONTENT_PROVIDER_CALLBACK2 (gdk_content_provider_callback2_get_type ())
#define GDK_CONTENT_PROVIDER_CALLBACK2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_CALLBACK2, GdkContentProviderCallback2))
typedef struct _GdkContentProviderCallback2 GdkContentProviderCallback2;
typedef struct _GdkContentProviderCallback2Class GdkContentProviderCallback2Class;
struct _GdkContentProviderCallback2
{
GdkContentProvider parent;
GdkContentFormats *formats;
GdkContentProviderGetBytesFunc func;
gpointer data;
};
struct _GdkContentProviderCallback2Class
{
GdkContentProviderClass parent_class;
};
GType gdk_content_provider_callback2_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GdkContentProviderCallback2, gdk_content_provider_callback2, GDK_TYPE_CONTENT_PROVIDER)
static GdkContentFormats *
gdk_content_provider_callback2_ref_formats (GdkContentProvider *provider)
{
GdkContentProviderCallback2 *callback = GDK_CONTENT_PROVIDER_CALLBACK2 (provider);
return gdk_content_formats_ref (callback->formats);
}
static void
gdk_content_provider_callback2_write_mime_type_done (GObject *stream,
GAsyncResult *result,
gpointer task)
{
GError *error = NULL;
if (!g_output_stream_write_all_finish (G_OUTPUT_STREAM (stream), result, NULL, &error))
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
gdk_content_provider_callback2_write_mime_type_async (GdkContentProvider *provider,
const char *mime_type,
GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GdkContentProviderCallback2 *content = GDK_CONTENT_PROVIDER_CALLBACK2 (provider);
GTask *task;
GBytes *bytes;
task = g_task_new (content, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
g_task_set_source_tag (task, gdk_content_provider_callback2_write_mime_type_async);
if (!gdk_content_formats_contain_mime_type (content->formats, mime_type))
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Cannot provide contents as “%s”"), mime_type);
g_object_unref (task);
return;
}
bytes = content->func (mime_type, content->data);
if (!bytes)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Failed to get contents as “%s”"), mime_type);
g_object_unref (task);
return;
}
g_object_set_data_full (G_OBJECT (task), "bytes", bytes, (GDestroyNotify)g_bytes_unref);
g_output_stream_write_all_async (stream,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
io_priority,
cancellable,
gdk_content_provider_callback2_write_mime_type_done,
task);
}
static gboolean
gdk_content_provider_callback2_write_mime_type_finish (GdkContentProvider *provider,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, provider), FALSE);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_content_provider_callback2_write_mime_type_async, FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
gdk_content_provider_callback2_class_init (GdkContentProviderCallback2Class *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
provider_class->ref_formats = gdk_content_provider_callback2_ref_formats;
provider_class->write_mime_type_async = gdk_content_provider_callback2_write_mime_type_async;
provider_class->write_mime_type_finish = gdk_content_provider_callback2_write_mime_type_finish;
}
static void
gdk_content_provider_callback2_init (GdkContentProviderCallback2 *content)
{
}
/**
* gdk_content_provider_new_with_formats:
* @formats: formats to advertise
* @func: callback to populate a #GValue
* @data: data that gets passed to @func
*
* Create a content provider that provides data that is provided via a callback.
*
* Returns: a new #GdkContentProvider
**/
GdkContentProvider *
gdk_content_provider_new_with_formats (GdkContentFormats *formats,
GdkContentProviderGetBytesFunc func,
gpointer data)
{
GdkContentProviderCallback2 *content;
content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_CALLBACK2, NULL);
content->formats = gdk_content_formats_ref (formats);
content->func = func;
content->data = data;
return GDK_CONTENT_PROVIDER (content);
}
+15
View File
@@ -35,6 +35,21 @@ GDK_AVAILABLE_IN_ALL
GdkContentProvider * gdk_content_provider_new_for_bytes (const char *mime_type,
GBytes *bytes);
typedef void (*GdkContentProviderGetValueFunc) (GValue *value,
gpointer data);
GDK_AVAILABLE_IN_ALL
GdkContentProvider * gdk_content_provider_new_with_callback (GType type,
GdkContentProviderGetValueFunc func,
gpointer data);
typedef GBytes * (*GdkContentProviderGetBytesFunc) (const char *mime_type,
gpointer data);
GDK_AVAILABLE_IN_ALL
GdkContentProvider * gdk_content_provider_new_with_formats (GdkContentFormats *formats,
GdkContentProviderGetBytesFunc func,
gpointer data);
G_END_DECLS
+49
View File
@@ -25,6 +25,7 @@
#include "gdkpixbuf.h"
#include "filetransferportalprivate.h"
#include "gdktextureprivate.h"
#include "gdkrgba.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <string.h>
@@ -862,6 +863,48 @@ file_text_serializer (GdkContentSerializer *serializer)
gdk_content_serializer_set_task_data (serializer, path, g_free);
}
static void
color_serializer_finish (GObject *source,
GAsyncResult *result,
gpointer serializer)
{
GOutputStream *stream = G_OUTPUT_STREAM (source);
GError *error = NULL;
if (!g_output_stream_write_all_finish (stream, result, NULL, &error))
gdk_content_serializer_return_error (serializer, error);
else
gdk_content_serializer_return_success (serializer);
}
static void
color_serializer (GdkContentSerializer *serializer)
{
const GValue *value;
GdkRGBA *rgba;
guint16 *data;
value = gdk_content_serializer_get_value (serializer);
rgba = g_value_get_boxed (value);
data = g_new0 (guint16, 4);
if (rgba)
{
data[0] = (guint16) (rgba->red * 65535);
data[1] = (guint16) (rgba->green * 65535);
data[2] = (guint16) (rgba->blue * 65535);
data[3] = (guint16) (rgba->alpha * 65535);
}
g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
data,
4 * sizeof (guint16),
gdk_content_serializer_get_priority (serializer),
gdk_content_serializer_get_cancellable (serializer),
color_serializer_finish,
serializer);
gdk_content_serializer_set_task_data (serializer, data, g_free);
}
static void
init (void)
{
@@ -984,5 +1027,11 @@ init (void)
string_serializer,
(gpointer) "ASCII",
NULL);
gdk_content_register_serializer (GDK_TYPE_RGBA,
"application/x-color",
color_serializer,
NULL,
NULL);
}
+31 -35
View File
@@ -87,6 +87,7 @@
#include "gtkgesturedrag.h"
#include "gtkeventcontrollerscroll.h"
#include "gtkeventcontrollerkey.h"
#include "gtkdragsource.h"
#define TIMEOUT_INITIAL 500
#define TIMEOUT_REPEAT 50
@@ -329,9 +330,6 @@ static gboolean gtk_calendar_query_tooltip (GtkWidget *widget,
gboolean keyboard_mode,
GtkTooltip *tooltip);
static void gtk_calendar_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_calendar_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data);
@@ -392,7 +390,6 @@ gtk_calendar_class_init (GtkCalendarClass *class)
widget_class->grab_notify = gtk_calendar_grab_notify;
widget_class->query_tooltip = gtk_calendar_query_tooltip;
widget_class->drag_data_get = gtk_calendar_drag_data_get;
widget_class->drag_motion = gtk_calendar_drag_motion;
widget_class->drag_leave = gtk_calendar_drag_leave;
widget_class->drag_drop = gtk_calendar_drag_drop;
@@ -2670,6 +2667,27 @@ gtk_calendar_drag_begin (GtkGestureDrag *gesture,
priv->in_drag = TRUE;
}
static GdkContentProvider *
get_calendar_content (GtkCalendar *calendar)
{
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GDate *date;
gchar str[128];
GValue value = G_VALUE_INIT;
GdkContentProvider *content;
date = g_date_new_dmy (priv->selected_day, priv->month + 1, priv->year);
g_date_strftime (str, 127, "%x", date);
g_free (date);
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, str);
content = gdk_content_provider_new_for_value (&value);
g_value_unset (&value);
return content;
}
static void
gtk_calendar_drag_update (GtkGestureDrag *gesture,
double x,
@@ -2680,8 +2698,9 @@ gtk_calendar_drag_update (GtkGestureDrag *gesture,
GtkCalendar *calendar = GTK_CALENDAR (widget);
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
gdouble start_x, start_y;
GdkDrag *drag;
GdkContentFormats *targets;
GtkDragSource *source;
GdkContentProvider *content;
GdkDevice *device;
if (!priv->in_drag)
return;
@@ -2691,19 +2710,14 @@ gtk_calendar_drag_update (GtkGestureDrag *gesture,
gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture));
targets = gdk_content_formats_new (NULL, 0);
targets = gtk_content_formats_add_text_targets (targets);
drag = gtk_drag_begin (widget,
gtk_gesture_get_device (GTK_GESTURE (gesture)),
targets, GDK_ACTION_COPY,
start_x, start_y);
content = get_calendar_content (calendar);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
device = gtk_gesture_get_device (GTK_GESTURE (gesture));
gtk_drag_source_drag_begin (source, widget, device, start_x, start_y);
g_object_unref (source);
priv->in_drag = 0;
gdk_content_formats_unref (targets);
gtk_drag_set_icon_default (drag);
}
static gboolean
@@ -2923,24 +2937,6 @@ gtk_calendar_grab_notify (GtkWidget *widget,
* Drag and Drop *
****************************************/
static void
gtk_calendar_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
GtkCalendar *calendar = GTK_CALENDAR (widget);
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GDate *date;
gchar str[128];
gsize len;
date = g_date_new_dmy (priv->selected_day, priv->month + 1, priv->year);
len = g_date_strftime (str, 127, "%x", date);
gtk_selection_data_set_text (selection_data, str, len);
g_free (date);
}
/* Get/set whether drag_motion requested the drag data and
* drag_data_received should thus not actually insert the data,
* since the data doesnt result from a drop.
+21 -50
View File
@@ -45,6 +45,7 @@
#include "gtkprivate.h"
#include "gtksnapshot.h"
#include "gtkstylecontext.h"
#include "gtkdragsource.h"
/**
@@ -121,15 +122,6 @@ static void gtk_color_button_get_property (GObject *object,
static void gtk_color_button_clicked (GtkButton *button,
gpointer user_data);
/* source side drag signals */
static void gtk_color_button_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data);
static void gtk_color_button_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
GtkColorButton *button);
/* target side drag signals */
static void gtk_color_button_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
@@ -286,50 +278,28 @@ gtk_color_button_drag_data_received (GtkWidget *widget,
}
static void
set_color_icon (GdkDrag *drag,
const GdkRGBA *rgba)
gtk_color_button_drag_begin (GtkDragSource *source,
GtkColorButton *button)
{
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
GtkSnapshot *snapshot;
GdkPaintable *paintable;
snapshot = gtk_snapshot_new ();
gtk_snapshot_append_color (snapshot,
rgba,
&GRAPHENE_RECT_INIT(0, 0, 48, 32));
gtk_snapshot_append_color (snapshot, &priv->rgba, &GRAPHENE_RECT_INIT(0, 0, 48, 32));
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
gtk_drag_set_icon_paintable (drag, paintable, 0, 0);
gtk_drag_source_set_icon (source, paintable, 0, 0);
g_object_unref (paintable);
}
static void
gtk_color_button_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
get_rgba_value (GValue *value,
gpointer data)
{
GtkColorButton *button = data;
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
set_color_icon (drag, &priv->rgba);
}
static void
gtk_color_button_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
GtkColorButton *button)
{
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
guint16 dropped[4];
dropped[0] = (guint16) (priv->rgba.red * 65535);
dropped[1] = (guint16) (priv->rgba.green * 65535);
dropped[2] = (guint16) (priv->rgba.blue * 65535);
dropped[3] = (guint16) (priv->rgba.alpha * 65535);
gtk_selection_data_set (selection_data,
gtk_selection_data_get_target (selection_data),
16, (guchar *)dropped, 8);
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (GTK_COLOR_BUTTON (data));
g_value_set_boxed (value, &priv->rgba);
}
static void
@@ -340,6 +310,8 @@ gtk_color_button_init (GtkColorButton *button)
PangoRectangle rect;
GtkStyleContext *context;
GdkContentFormats *targets;
GdkContentProvider *content;
GtkDragSource *source;
priv->button = gtk_button_new ();
g_signal_connect (priv->button, "clicked", G_CALLBACK (gtk_color_button_clicked), button);
@@ -370,17 +342,16 @@ gtk_color_button_init (GtkColorButton *button)
GTK_DEST_DEFAULT_DROP,
targets,
GDK_ACTION_COPY);
gtk_drag_source_set (priv->button,
GDK_BUTTON1_MASK|GDK_BUTTON3_MASK,
targets,
GDK_ACTION_COPY);
gdk_content_formats_unref (targets);
g_signal_connect (priv->button, "drag-begin",
G_CALLBACK (gtk_color_button_drag_begin), button);
g_signal_connect (priv->button, "drag-data-received",
G_CALLBACK (gtk_color_button_drag_data_received), button);
g_signal_connect (priv->button, "drag-data-get",
G_CALLBACK (gtk_color_button_drag_data_get), button);
gdk_content_formats_unref (targets);
content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, button);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_color_button_drag_begin), button);
gtk_drag_source_attach (source, priv->button, GDK_BUTTON1_MASK|GDK_BUTTON3_MASK);
context = gtk_widget_get_style_context (GTK_WIDGET (priv->button));
gtk_style_context_add_class (context, "color");
+24 -47
View File
@@ -40,6 +40,7 @@
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerkey.h"
#include "gtknative.h"
#include "gtkdragsource.h"
#include "a11y/gtkcolorswatchaccessibleprivate.h"
@@ -113,56 +114,23 @@ swatch_snapshot (GtkWidget *widget,
gtk_widget_snapshot_child (widget, priv->overlay_widget, snapshot);
}
static void
drag_set_color_icon (GdkDrag *drag,
const GdkRGBA *color)
gtk_color_swatch_drag_begin (GtkDragSource *source,
GtkColorSwatch *swatch)
{
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
GtkSnapshot *snapshot;
GdkPaintable *paintable;
snapshot = gtk_snapshot_new ();
gtk_snapshot_append_color (snapshot,
color,
&GRAPHENE_RECT_INIT(0, 0, 48, 32));
gtk_snapshot_append_color (snapshot, &priv->color, &GRAPHENE_RECT_INIT(0, 0, 48, 32));
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
gtk_drag_set_icon_paintable (drag, paintable, 4, 4);
gtk_drag_source_set_icon (source, paintable, 0, 0);
g_object_unref (paintable);
}
static void
swatch_drag_begin (GtkWidget *widget,
GdkDrag *drag)
{
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
GdkRGBA color;
gtk_color_swatch_get_rgba (swatch, &color);
drag_set_color_icon (drag, &color);
}
static void
swatch_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
guint16 vals[4];
GdkRGBA color;
gtk_color_swatch_get_rgba (swatch, &color);
vals[0] = color.red * 0xffff;
vals[1] = color.green * 0xffff;
vals[2] = color.blue * 0xffff;
vals[3] = color.alpha * 0xffff;
gtk_selection_data_set (selection_data,
g_intern_static_string ("application/x-color"),
16, (guchar *)vals, 8);
}
static void
swatch_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
@@ -523,8 +491,6 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
widget_class->measure = gtk_color_swatch_measure;
widget_class->snapshot = swatch_snapshot;
widget_class->drag_begin = swatch_drag_begin;
widget_class->drag_data_get = swatch_drag_data_get;
widget_class->drag_data_received = swatch_drag_data_received;
widget_class->popup_menu = swatch_popup_menu;
widget_class->size_allocate = swatch_size_allocate;
@@ -601,6 +567,14 @@ static const char *dnd_targets[] = {
"application/x-color"
};
static void
get_rgba_value (GValue *value,
gpointer data)
{
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (GTK_COLOR_SWATCH (data));
g_value_set_boxed (value, &priv->color);
}
void
gtk_color_swatch_set_rgba (GtkColorSwatch *swatch,
const GdkRGBA *color)
@@ -612,12 +586,15 @@ gtk_color_swatch_set_rgba (GtkColorSwatch *swatch,
if (!priv->has_color)
{
GdkContentFormats *targets = gdk_content_formats_new (dnd_targets, G_N_ELEMENTS (dnd_targets));
gtk_drag_source_set (GTK_WIDGET (swatch),
GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
targets,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gdk_content_formats_unref (targets);
GdkContentProvider *content;
GtkDragSource *source;
content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, swatch);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_color_swatch_drag_begin), swatch);
gtk_drag_source_attach (source, GTK_WIDGET (swatch), GDK_BUTTON1_MASK | GDK_BUTTON3_MASK);
}
priv->has_color = TRUE;
-792
View File
@@ -63,21 +63,8 @@
*/
typedef struct _GtkDragSourceInfo GtkDragSourceInfo;
typedef struct _GtkDragDestInfo GtkDragDestInfo;
struct _GtkDragSourceInfo
{
GtkWidget *widget;
GdkContentFormats *target_list; /* Targets for drag data */
GdkDrag *drag; /* drag context */
GtkWidget *icon_window; /* Window for drag */
GtkWidget *icon_widget; /* Widget for drag */
guint drop_timeout; /* Timeout for aborting drop */
guint destroy_icon : 1; /* If true, destroy icon_widget */
};
struct _GtkDragDestInfo
{
GtkWidget *widget; /* Widget in which drag is in */
@@ -118,33 +105,6 @@ static void gtk_drag_dest_set_widget (GtkDragDestInfo *info,
static GtkDragDestInfo * gtk_drag_get_dest_info (GdkDrop *drop,
gboolean create);
static GtkDragSourceInfo *gtk_drag_get_source_info (GdkDrag *drag,
gboolean create);
static void gtk_drag_clear_source_info (GdkDrag *drag);
static void gtk_drag_drop (GtkDragSourceInfo *info);
static void gtk_drag_drop_finished (GtkDragSourceInfo *info,
GtkDragResult result);
static void gtk_drag_cancel_internal (GtkDragSourceInfo *info,
GtkDragResult result);
static void gtk_drag_remove_icon (GtkDragSourceInfo *info);
static void gtk_drag_source_info_destroy (GtkDragSourceInfo *info);
static void gtk_drag_drop_performed_cb (GdkDrag *drag,
GtkDragSourceInfo *info);
static void gtk_drag_cancel_cb (GdkDrag *drag,
GdkDragCancelReason reason,
GtkDragSourceInfo *info);
static void gtk_drag_dnd_finished_cb (GdkDrag *drag,
GtkDragSourceInfo *info);
static gboolean gtk_drag_abort_timeout (gpointer data);
static void set_icon_helper (GdkDrag *drag,
GtkImageDefinition *def,
gint hot_x,
gint hot_y);
/********************
@@ -305,30 +265,6 @@ gtk_drag_get_data (GtkWidget *widget,
data);
}
/**
* gtk_drag_get_source_widget:
* @drag: a drag context
*
* Determines the source widget for a drag.
*
* Returns: (nullable) (transfer none): if the drag is occurring
* within a single application, a pointer to the source widget.
* Otherwise, %NULL.
*/
GtkWidget *
gtk_drag_get_source_widget (GdkDrag *drag)
{
GtkDragSourceInfo *info;
g_return_val_if_fail (GDK_IS_DRAG (drag), NULL);
info = gtk_drag_get_source_info (drag, FALSE);
if (info == NULL)
return NULL;
return info->widget;
}
/**
* gtk_drag_highlight: (method)
* @widget: a widget to highlight
@@ -590,33 +526,6 @@ gtk_drag_get_dest_info (GdkDrop *drop,
return info;
}
static GQuark dest_info_quark = 0;
static GtkDragSourceInfo *
gtk_drag_get_source_info (GdkDrag *drag,
gboolean create)
{
GtkDragSourceInfo *info;
if (!dest_info_quark)
dest_info_quark = g_quark_from_static_string ("gtk-source-info");
info = g_object_get_qdata (G_OBJECT (drag), dest_info_quark);
if (!info && create)
{
info = g_new0 (GtkDragSourceInfo, 1);
info->drag = drag;
g_object_set_qdata (G_OBJECT (drag), dest_info_quark, info);
}
return info;
}
static void
gtk_drag_clear_source_info (GdkDrag *drag)
{
g_object_set_qdata (G_OBJECT (drag), dest_info_quark, NULL);
}
/*
* Default drag handlers
*/
@@ -722,704 +631,3 @@ gtk_drag_dest_drop (GtkWidget *widget,
return (site->flags & GTK_DEST_DEFAULT_DROP) ? TRUE : retval;
}
/***************
* Source side *
***************/
#define GTK_TYPE_DRAG_CONTENT (gtk_drag_content_get_type ())
#define GTK_DRAG_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_DRAG_CONTENT, GtkDragContent))
#define GTK_IS_DRAG_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DRAG_CONTENT))
#define GTK_DRAG_CONTENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_DRAG_CONTENT, GtkDragContentClass))
#define GTK_IS_DRAG_CONTENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DRAG_CONTENT))
#define GTK_DRAG_CONTENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_DRAG_CONTENT, GtkDragContentClass))
typedef struct _GtkDragContent GtkDragContent;
typedef struct _GtkDragContentClass GtkDragContentClass;
struct _GtkDragContent
{
GdkContentProvider parent;
GtkWidget *widget;
GdkDrag *drag;
GdkContentFormats *formats;
guint32 time;
};
struct _GtkDragContentClass
{
GdkContentProviderClass parent_class;
};
GType gtk_drag_content_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GtkDragContent, gtk_drag_content, GDK_TYPE_CONTENT_PROVIDER)
static GdkContentFormats *
gtk_drag_content_ref_formats (GdkContentProvider *provider)
{
GtkDragContent *content = GTK_DRAG_CONTENT (provider);
return gdk_content_formats_ref (content->formats);
}
static void
gtk_drag_content_write_mime_type_done (GObject *stream,
GAsyncResult *result,
gpointer task)
{
GError *error = NULL;
if (!g_output_stream_write_all_finish (G_OUTPUT_STREAM (stream),
result,
NULL,
&error))
{
g_task_return_error (task, error);
}
else
{
g_task_return_boolean (task, TRUE);
}
g_object_unref (task);
}
static void
gtk_drag_content_write_mime_type_async (GdkContentProvider *provider,
const char *mime_type,
GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GtkDragContent *content = GTK_DRAG_CONTENT (provider);
GtkSelectionData sdata = { 0, };
GTask *task;
task = g_task_new (content, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
g_task_set_source_tag (task, gtk_drag_content_write_mime_type_async);
sdata.target = g_intern_string (mime_type);
sdata.length = -1;
sdata.display = gtk_widget_get_display (content->widget);
g_signal_emit_by_name (content->widget, "drag-data-get",
content->drag,
&sdata);
if (sdata.length == -1)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Cannot provide contents as “%s”"), mime_type);
g_object_unref (task);
return;
}
g_task_set_task_data (task, sdata.data, g_free);
g_output_stream_write_all_async (stream,
sdata.data,
sdata.length,
io_priority,
cancellable,
gtk_drag_content_write_mime_type_done,
task);
}
static gboolean
gtk_drag_content_write_mime_type_finish (GdkContentProvider *provider,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, provider), FALSE);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gtk_drag_content_write_mime_type_async, FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
gtk_drag_content_finalize (GObject *object)
{
GtkDragContent *content = GTK_DRAG_CONTENT (object);
g_clear_object (&content->widget);
g_clear_pointer (&content->formats, gdk_content_formats_unref);
G_OBJECT_CLASS (gtk_drag_content_parent_class)->finalize (object);
}
static void
gtk_drag_content_class_init (GtkDragContentClass *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = gtk_drag_content_finalize;
provider_class->ref_formats = gtk_drag_content_ref_formats;
provider_class->write_mime_type_async = gtk_drag_content_write_mime_type_async;
provider_class->write_mime_type_finish = gtk_drag_content_write_mime_type_finish;
}
static void
gtk_drag_content_init (GtkDragContent *content)
{
}
/* Like gtk_drag_begin(), but also takes a GtkImageDefinition
* so that we can set the icon from the source site information
*/
GdkDrag *
gtk_drag_begin_internal (GtkWidget *widget,
GdkDevice *device,
GtkImageDefinition *icon,
GdkContentFormats *target_list,
GdkDragAction actions,
int x,
int y)
{
GtkDragSourceInfo *info;
GtkNative *native;
GdkDrag *drag;
double px, py;
int dx, dy;
GtkDragContent *content;
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
device = gdk_device_get_associated_device (device);
native = gtk_widget_get_native (widget);
gtk_widget_translate_coordinates (widget, GTK_WIDGET (native), x, y, &x, &y);
gdk_surface_get_device_position (gtk_native_get_surface (native),
device,
&px, &py,
NULL);
dx = round (px) - x;
dy = round (py) - y;
content = g_object_new (GTK_TYPE_DRAG_CONTENT, NULL);
content->widget = g_object_ref (widget);
content->formats = gdk_content_formats_ref (target_list);
drag = gdk_drag_begin (gtk_native_get_surface (native), device, GDK_CONTENT_PROVIDER (content), actions, dx, dy);
if (drag == NULL)
{
g_object_unref (content);
return NULL;
}
content->drag = drag;
g_object_unref (content);
info = gtk_drag_get_source_info (drag, TRUE);
g_object_set_data (G_OBJECT (widget), I_("gtk-info"), info);
info->widget = g_object_ref (widget);
info->target_list = target_list;
gdk_content_formats_ref (target_list);
info->icon_window = NULL;
info->icon_widget = NULL;
info->destroy_icon = FALSE;
gtk_widget_reset_controllers (widget);
g_signal_emit_by_name (widget, "drag-begin", info->drag);
/* Ensure that we have an icon before we start the drag; the
* application may have set one in ::drag_begin, or it may
* not have set one.
*/
if (!info->icon_widget)
{
if (icon)
{
set_icon_helper (info->drag, icon, 0, 0);
}
else
{
icon = gtk_image_definition_new_icon_name ("text-x-generic");
set_icon_helper (info->drag, icon, 0, 0);
gtk_image_definition_unref (icon);
}
}
g_signal_connect (drag, "drop-performed",
G_CALLBACK (gtk_drag_drop_performed_cb), info);
g_signal_connect (drag, "dnd-finished",
G_CALLBACK (gtk_drag_dnd_finished_cb), info);
g_signal_connect (drag, "cancel",
G_CALLBACK (gtk_drag_cancel_cb), info);
return info->drag;
}
/**
* gtk_drag_begin: (method)
* @widget: the source widget
* @device: (nullable): the device that starts the drag or %NULL to use the default pointer
* @targets: The targets (data formats) in which the source can provide the data
* @actions: A bitmask of the allowed drag actions for this drag
* @x: The initial x coordinate to start dragging from, in the coordinate space of @widget.
* @y: The initial y coordinate to start dragging from, in the coordinate space of @widget.
*
* Initiates a drag on the source side. The function only needs to be used
* when the application is starting drags itself, and is not needed when
* gtk_drag_source_set() is used.
*
* Returns: (transfer none): the context for this drag
*/
GdkDrag *
gtk_drag_begin (GtkWidget *widget,
GdkDevice *device,
GdkContentFormats *targets,
GdkDragAction actions,
gint x,
gint y)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
g_return_val_if_fail (device == NULL || GDK_IS_DEVICE (device), NULL);
g_return_val_if_fail (gtk_widget_get_realized (widget), NULL);
g_return_val_if_fail (targets != NULL, NULL);
if (device == NULL)
{
GdkSeat *seat;
seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
device = gdk_seat_get_pointer (seat);
}
return gtk_drag_begin_internal (widget,
device,
NULL,
targets,
actions,
x, y);
}
static void
icon_widget_destroyed (GtkWidget *widget,
GtkDragSourceInfo *info)
{
g_clear_object (&info->icon_widget);
}
static void
gtk_drag_set_icon_widget_internal (GdkDrag *drag,
GtkWidget *widget,
gint hot_x,
gint hot_y,
gboolean destroy_on_release)
{
GtkDragSourceInfo *info;
g_return_if_fail (!GTK_IS_WINDOW (widget));
info = gtk_drag_get_source_info (drag, FALSE);
if (info == NULL)
{
if (destroy_on_release)
gtk_widget_destroy (widget);
return;
}
gtk_drag_remove_icon (info);
if (widget)
g_object_ref (widget);
info->icon_widget = widget;
info->destroy_icon = destroy_on_release;
if (!widget)
return;
g_signal_connect (widget, "destroy", G_CALLBACK (icon_widget_destroyed), info);
gdk_drag_set_hotspot (drag, hot_x, hot_y);
if (!info->icon_window)
{
info->icon_window = gtk_drag_icon_new ();
g_object_ref_sink (info->icon_window);
gtk_widget_set_size_request (info->icon_window, 24, 24);
gtk_drag_icon_set_surface (GTK_DRAG_ICON (info->icon_window),
gdk_drag_get_drag_surface (drag));
gtk_widget_show (info->icon_window);
}
gtk_drag_icon_set_widget (GTK_DRAG_ICON (info->icon_window), widget);
}
/**
* gtk_drag_set_icon_widget:
* @drag: the context for a drag
* @widget: a widget to use as an icon
* @hot_x: the X offset within @widget of the hotspot
* @hot_y: the Y offset within @widget of the hotspot
*
* Changes the icon for drag operation to a given widget.
* GTK+ will not destroy the widget, so if you dont want
* it to persist, you should connect to the “drag-end”
* signal and destroy it yourself.
*/
void
gtk_drag_set_icon_widget (GdkDrag *drag,
GtkWidget *widget,
gint hot_x,
gint hot_y)
{
g_return_if_fail (GDK_IS_DRAG (drag));
g_return_if_fail (GTK_IS_WIDGET (widget));
gtk_drag_set_icon_widget_internal (drag, widget, hot_x, hot_y, FALSE);
}
static void
set_icon_helper (GdkDrag *drag,
GtkImageDefinition *def,
gint hot_x,
gint hot_y)
{
GtkWidget *widget;
widget = gtk_image_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "drag-icon");
gtk_image_set_from_definition (GTK_IMAGE (widget), def);
gtk_drag_set_icon_widget_internal (drag, widget, hot_x, hot_y, TRUE);
}
void
gtk_drag_set_icon_definition (GdkDrag *drag,
GtkImageDefinition *def,
gint hot_x,
gint hot_y)
{
g_return_if_fail (GDK_IS_DRAG (drag));
g_return_if_fail (def != NULL);
set_icon_helper (drag, def, hot_x, hot_y);
}
/**
* gtk_drag_set_icon_paintable:
* @drag: the context for a drag
* @paintable: the #GdkPaintable to use as icon
* @hot_x: the X offset of the hotspot within the icon
* @hot_y: the Y offset of the hotspot within the icon
*
* Sets @paintable as the icon for a given drag. GTK+ retains
* references for the arguments, and will release them when
* they are no longer needed.
*
* To position the @paintable relative to the mouse, its top
* left will be positioned @hot_x, @hot_y pixels from the
* mouse cursor.
*/
void
gtk_drag_set_icon_paintable (GdkDrag *drag,
GdkPaintable *paintable,
int hot_x,
int hot_y)
{
GtkWidget *widget;
g_return_if_fail (GDK_IS_DRAG (drag));
g_return_if_fail (GDK_IS_PAINTABLE (paintable));
widget = gtk_picture_new_for_paintable (paintable);
gtk_picture_set_can_shrink (GTK_PICTURE (widget), FALSE);
gtk_drag_set_icon_widget_internal (drag, widget, hot_x, hot_y, TRUE);
}
/**
* gtk_drag_set_icon_name:
* @drag: the context for a drag
* @icon_name: name of icon to use
* @hot_x: the X offset of the hotspot within the icon
* @hot_y: the Y offset of the hotspot within the icon
*
* Sets the icon for a given drag from a named themed icon. See
* the docs for #GtkIconTheme for more details. Note that the
* size of the icon depends on the icon theme (the icon is
* loaded at the symbolic size #GTK_ICON_SIZE_DND), thus
* @hot_x and @hot_y have to be used with care.
*/
void
gtk_drag_set_icon_name (GdkDrag *drag,
const gchar *icon_name,
gint hot_x,
gint hot_y)
{
GtkImageDefinition *def;
g_return_if_fail (GDK_IS_DRAG (drag));
g_return_if_fail (icon_name != NULL && icon_name[0] != '\0');
def = gtk_image_definition_new_icon_name (icon_name);
set_icon_helper (drag, def, hot_x, hot_y);
gtk_image_definition_unref (def);
}
/**
* gtk_drag_set_icon_gicon:
* @drag: the context for a drag
* @icon: a #GIcon
* @hot_x: the X offset of the hotspot within the icon
* @hot_y: the Y offset of the hotspot within the icon
*
* Sets the icon for a given drag from the given @icon.
* See the documentation for gtk_drag_set_icon_name()
* for more details about using icons in drag and drop.
*/
void
gtk_drag_set_icon_gicon (GdkDrag *drag,
GIcon *icon,
gint hot_x,
gint hot_y)
{
GtkImageDefinition *def;
g_return_if_fail (GDK_IS_DRAG (drag));
g_return_if_fail (icon != NULL);
def = gtk_image_definition_new_gicon (icon);
set_icon_helper (drag, def, hot_x, hot_y);
gtk_image_definition_unref (def);
}
/**
* gtk_drag_set_icon_default:
* @drag: the context for a drag
*
* Sets the icon for a particular drag to the default
* icon.
*/
void
gtk_drag_set_icon_default (GdkDrag *drag)
{
g_return_if_fail (GDK_IS_DRAG (drag));
gtk_drag_set_icon_name (drag, "text-x-generic", -2, -2);
}
/* Clean up from the drag, and display snapback, if necessary. */
static void
gtk_drag_drop_finished (GtkDragSourceInfo *info,
GtkDragResult result)
{
gboolean success;
success = (result == GTK_DRAG_RESULT_SUCCESS);
if (!success)
g_signal_emit_by_name (info->widget, "drag-failed",
info->drag, result, &success);
gdk_drag_drop_done (info->drag, success);
gtk_drag_source_info_destroy (info);
}
static void
gtk_drag_drop (GtkDragSourceInfo *info)
{
if (info->icon_window)
gtk_widget_hide (info->icon_window);
info->drop_timeout = g_timeout_add (DROP_ABORT_TIME, gtk_drag_abort_timeout, info);
g_source_set_name_by_id (info->drop_timeout, "[gtk] gtk_drag_abort_timeout");
}
/*
* Source side callbacks.
*/
static void
gtk_drag_remove_icon (GtkDragSourceInfo *info)
{
if (info->icon_widget)
{
GtkWidget *widget;
widget = info->icon_widget;
info->icon_widget = NULL;
g_signal_handlers_disconnect_by_func (widget, icon_widget_destroyed, info);
gtk_widget_hide (widget);
gtk_widget_set_opacity (widget, 1.0);
if (info->destroy_icon)
gtk_widget_destroy (widget);
else
gtk_drag_icon_set_widget (GTK_DRAG_ICON (info->icon_window), NULL);
g_object_unref (widget);
}
}
static void
gtk_drag_source_info_free (GtkDragSourceInfo *info)
{
gtk_drag_remove_icon (info);
g_object_unref (info->icon_window);
g_free (info);
}
static void
gtk_drag_source_info_destroy (GtkDragSourceInfo *info)
{
g_signal_handlers_disconnect_by_func (info->drag, gtk_drag_drop_performed_cb, info);
g_signal_handlers_disconnect_by_func (info->drag, gtk_drag_dnd_finished_cb, info);
g_signal_handlers_disconnect_by_func (info->drag, gtk_drag_cancel_cb, info);
g_signal_emit_by_name (info->widget, "drag-end", info->drag);
g_object_set_data (G_OBJECT (info->widget), I_("gtk-info"), NULL);
g_clear_object (&info->widget);
gdk_content_formats_unref (info->target_list);
if (info->drop_timeout)
g_source_remove (info->drop_timeout);
/* keep the icon_window alive until the (possible) drag cancel animation is done */
g_object_set_data_full (G_OBJECT (info->drag), "former-gtk-source-info", info, (GDestroyNotify)gtk_drag_source_info_free);
gtk_drag_clear_source_info (info->drag);
g_object_unref (info->drag);
}
/* Called on cancellation of a drag, either by the user
* or programmatically.
*/
static void
gtk_drag_cancel_internal (GtkDragSourceInfo *info,
GtkDragResult result)
{
gtk_drag_drop_finished (info, result);
}
static void
gtk_drag_drop_performed_cb (GdkDrag *drag,
GtkDragSourceInfo *info)
{
gtk_drag_drop (info);
}
static void
gtk_drag_cancel_cb (GdkDrag *drag,
GdkDragCancelReason reason,
GtkDragSourceInfo *info)
{
GtkDragResult result;
switch (reason)
{
case GDK_DRAG_CANCEL_NO_TARGET:
result = GTK_DRAG_RESULT_NO_TARGET;
break;
case GDK_DRAG_CANCEL_USER_CANCELLED:
result = GTK_DRAG_RESULT_USER_CANCELLED;
break;
case GDK_DRAG_CANCEL_ERROR:
default:
result = GTK_DRAG_RESULT_ERROR;
break;
}
gtk_drag_cancel_internal (info, result);
}
static void
gtk_drag_dnd_finished_cb (GdkDrag *drag,
GtkDragSourceInfo *info)
{
if (gdk_drag_get_selected_action (drag) == GDK_ACTION_MOVE)
{
g_signal_emit_by_name (info->widget,
"drag-data-delete",
drag);
}
gtk_drag_source_info_destroy (info);
}
static gboolean
gtk_drag_abort_timeout (gpointer data)
{
GtkDragSourceInfo *info = data;
info->drop_timeout = 0;
gtk_drag_drop_finished (info, GTK_DRAG_RESULT_TIMEOUT_EXPIRED);
return G_SOURCE_REMOVE;
}
/**
* gtk_drag_check_threshold: (method)
* @widget: a #GtkWidget
* @start_x: X coordinate of start of drag
* @start_y: Y coordinate of start of drag
* @current_x: current X coordinate
* @current_y: current Y coordinate
*
* Checks to see if a mouse drag starting at (@start_x, @start_y) and ending
* at (@current_x, @current_y) has passed the GTK+ drag threshold, and thus
* should trigger the beginning of a drag-and-drop operation.
*
* Returns: %TRUE if the drag threshold has been passed.
*/
gboolean
gtk_drag_check_threshold (GtkWidget *widget,
gint start_x,
gint start_y,
gint current_x,
gint current_y)
{
gint drag_threshold;
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
drag_threshold = gtk_settings_get_dnd_drag_threshold (gtk_widget_get_settings (widget));
return (ABS (current_x - start_x) > drag_threshold ||
ABS (current_y - start_y) > drag_threshold);
}
/**
* gtk_drag_cancel:
* @drag: a drag context, as e.g. returned by gtk_drag_begin()
*
* Cancels an ongoing drag operation on the source side.
*
* If you want to be able to cancel a drag operation in this way,
* you need to keep a pointer to the drag context, either from an
* explicit call to gtk_drag_begin(), or by connecting to
* #GtkWidget::drag-begin.
*
* If @context does not refer to an ongoing drag operation, this
* function does nothing.
*
* If a drag is cancelled in this way, the @result argument of
* #GtkWidget::drag-failed is set to @GTK_DRAG_RESULT_ERROR.
*/
void
gtk_drag_cancel (GdkDrag *drag)
{
GtkDragSourceInfo *info;
g_return_if_fail (GDK_IS_DRAG (drag));
info = gtk_drag_get_source_info (drag, FALSE);
if (info != NULL)
gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_ERROR);
}
-47
View File
@@ -44,58 +44,11 @@ void gtk_drag_get_data (GtkWidget *widget,
GdkDrop *drop,
GdkAtom target);
GDK_AVAILABLE_IN_ALL
GtkWidget *gtk_drag_get_source_widget (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
void gtk_drag_highlight (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_unhighlight (GtkWidget *widget);
/* Source side */
GDK_AVAILABLE_IN_ALL
GdkDrag *gtk_drag_begin (GtkWidget *widget,
GdkDevice *device,
GdkContentFormats *targets,
GdkDragAction actions,
gint x,
gint y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_cancel (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_widget (GdkDrag *drag,
GtkWidget *widget,
gint hot_x,
gint hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_paintable (GdkDrag *drag,
GdkPaintable *paintable,
int hot_x,
int hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_name (GdkDrag *drag,
const gchar *icon_name,
gint hot_x,
gint hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_gicon (GdkDrag *drag,
GIcon *icon,
gint hot_x,
gint hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_default (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
gboolean gtk_drag_check_threshold (GtkWidget *widget,
gint start_x,
gint start_y,
gint current_x,
gint current_y);
G_END_DECLS
+722 -297
View File
File diff suppressed because it is too large Load Diff
+59 -22
View File
@@ -37,36 +37,73 @@
G_BEGIN_DECLS
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set (GtkWidget *widget,
GdkModifierType start_button_mask,
GdkContentFormats *targets,
GdkDragAction actions);
#define GTK_TYPE_DRAG_SOURCE (gtk_drag_source_get_type ())
#define GTK_DRAG_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_DRAG_SOURCE, GtkDragSource))
#define GTK_DRAG_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_DRAG_SOURCE, GtkDragSourceClass))
#define GTK_IS_DRAG_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_DRAG_SOURCE))
#define GTK_IS_DRAG_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_DRAG_SOURCE))
#define GTK_DRAG_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_DRAG_SOURCE, GtkDragSourceClass))
typedef struct _GtkDragSource GtkDragSource;
typedef struct _GtkDragSourceClass GtkDragSourceClass;
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_unset (GtkWidget *widget);
GType gtk_drag_source_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GdkContentFormats * gtk_drag_source_get_target_list (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_target_list (GtkWidget *widget,
GdkContentFormats *target_list);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_add_text_targets (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_add_image_targets (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_add_uri_targets (GtkWidget *widget);
GtkDragSource *gtk_drag_source_new (GdkContentProvider *content,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_name (GtkWidget *widget,
const gchar *icon_name);
void gtk_drag_source_set_content (GtkDragSource *source,
GdkContentProvider *content);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_gicon (GtkWidget *widget,
GIcon *icon);
GdkContentProvider *gtk_drag_source_get_content (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_paintable (GtkWidget *widget,
GdkPaintable *paintable);
void gtk_drag_source_set_actions (GtkDragSource *source,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
GdkDragAction gtk_drag_source_get_actions (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon (GtkDragSource *source,
GdkPaintable *paintable,
int hot_x,
int hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_drag_begin (GtkDragSource *source,
GtkWidget *widget,
GdkDevice *device,
int x,
int y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_drag_cancel (GtkDragSource *sourcei);
GDK_AVAILABLE_IN_ALL
GtkDragSource * gtk_drag_get_source (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_drag_source_get_origin (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
GdkDrag * gtk_drag_source_get_drag (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_attach (GtkDragSource *source,
GtkWidget *widget,
GdkModifierType start_button_mask);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_detach (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
gboolean gtk_drag_check_threshold (GtkWidget *widget,
int start_x,
int start_y,
int current_x,
int current_y);
G_END_DECLS
+19 -19
View File
@@ -70,6 +70,8 @@
#include "gtkwindow.h"
#include "gtknative.h"
#include "gtkgestureclick.h"
#include "gtkdragsource.h"
#include "gtkwidgetpaintable.h"
#include "a11y/gtkentryaccessible.h"
@@ -172,7 +174,7 @@ struct _EntryIconInfo
guint in_drag : 1;
GdkDragAction actions;
GdkContentFormats *target_list;
GdkContentProvider *content;
};
enum {
@@ -1320,8 +1322,7 @@ gtk_entry_finalize (GObject *object)
if (icon_info == NULL)
continue;
if (icon_info->target_list != NULL)
gdk_content_formats_unref (icon_info->target_list);
g_clear_object (&icon_info->content);
gtk_widget_unparent (icon_info->widget);
@@ -1462,17 +1463,21 @@ icon_drag_update_cb (GtkGestureDrag *gesture,
pos = get_icon_position_from_controller (entry, GTK_EVENT_CONTROLLER (gesture));
icon_info = priv->icons[pos];
if (icon_info->target_list != NULL &&
gtk_drag_check_threshold (icon_info->widget,
start_x, start_y,
x, y))
if (icon_info->content != NULL &&
gtk_drag_check_threshold (icon_info->widget, start_x, start_y, x, y))
{
GtkDragSource *source;
GdkPaintable *paintable;
GdkDevice *device;
icon_info->in_drag = TRUE;
gtk_drag_begin (GTK_WIDGET (entry),
gtk_gesture_get_device (GTK_GESTURE (gesture)),
icon_info->target_list,
icon_info->actions,
start_x, start_y);
source = gtk_drag_source_new (icon_info->content, icon_info->actions);
paintable = gtk_widget_paintable_new (icon_info->widget);
gtk_drag_source_set_icon (source, paintable, -2, -2);
g_object_unref (paintable);
device = gtk_gesture_get_device (GTK_GESTURE (gesture));
gtk_drag_source_drag_begin (source, GTK_WIDGET (entry), device, start_x, start_y);
g_object_unref (source);
}
}
@@ -2742,7 +2747,7 @@ gtk_entry_get_icon_at_pos (GtkEntry *entry,
void
gtk_entry_set_icon_drag_source (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GdkContentFormats *formats,
GdkContentProvider *provider,
GdkDragAction actions)
{
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
@@ -2754,12 +2759,7 @@ gtk_entry_set_icon_drag_source (GtkEntry *entry,
if ((icon_info = priv->icons[icon_pos]) == NULL)
icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
if (icon_info->target_list)
gdk_content_formats_unref (icon_info->target_list);
icon_info->target_list = formats;
if (icon_info->target_list)
gdk_content_formats_ref (icon_info->target_list);
g_set_object (&icon_info->content, provider);
icon_info->actions = actions;
}
+1 -1
View File
@@ -266,7 +266,7 @@ gchar * gtk_entry_get_icon_tooltip_markup (GtkEntry *
GDK_AVAILABLE_IN_ALL
void gtk_entry_set_icon_drag_source (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GdkContentFormats *formats,
GdkContentProvider *content,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
gint gtk_entry_get_current_icon_drag_source (GtkEntry *entry);
+19 -18
View File
@@ -1995,7 +1995,7 @@ file_list_drag_data_received_cb (GtkWidget *widget,
/* Allow only drags from other widgets; see bug #533891. */
if (gdk_drop_get_drag (drop) &&
gtk_drag_get_source_widget (gdk_drop_get_drag (drop)) == widget)
gtk_drag_source_get_origin (gtk_drag_get_source (gdk_drop_get_drag (drop))) == widget)
{
g_signal_stop_emission_by_name (widget, "drag-data-received");
return;
@@ -2042,15 +2042,13 @@ file_list_drag_drop_cb (GtkWidget *widget,
}
static void
file_list_drag_begin_cb (GtkWidget *widget,
GdkDrag *drag,
file_list_drag_begin_cb (GtkDragSource *source,
GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GdkDrag *drag = gtk_drag_source_get_drag (source);
gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (priv->places_sidebar),
TRUE,
drag);
gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (priv->places_sidebar), TRUE, drag);
}
/* Disable the normal tree drag motion handler, it makes it look like you're
@@ -2067,16 +2065,13 @@ file_list_drag_motion_cb (GtkWidget *widget,
}
static void
file_list_drag_end_cb (GtkWidget *widget,
GdkDrag *drag,
gpointer user_data)
file_list_drag_end_cb (GtkDragSource *source,
GtkFileChooserWidget *impl)
{
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (user_data);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GdkDrag *drag = gtk_drag_source_get_drag (source);
gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (priv->places_sidebar),
FALSE,
drag);
gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (priv->places_sidebar), FALSE, drag);
}
/* Sensitizes the "Copy files location" and other context menu items if there is actually
@@ -8510,17 +8505,23 @@ post_process_ui (GtkFileChooserWidget *impl)
GtkCellRenderer *cell;
GList *cells;
GFile *file;
GtkDragSource *source;
GdkContentFormats *formats;
/* Setup file list treeview */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_set_select_function (selection,
list_select_func,
impl, NULL);
gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (priv->browse_files_tree_view),
GDK_BUTTON1_MASK,
NULL,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_drag_source_add_uri_targets (priv->browse_files_tree_view);
formats = gdk_content_formats_new (NULL, 0);
formats = gtk_content_formats_add_uri_targets (formats);
source = gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (priv->browse_files_tree_view),
GDK_BUTTON1_MASK,
formats,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gdk_content_formats_unref (formats);
g_signal_connect (source, "drag-begin", G_CALLBACK (file_list_drag_begin_cb), impl);
g_signal_connect (source, "drag-end", G_CALLBACK (file_list_drag_end_cb), impl);
gtk_drag_dest_set (priv->browse_files_tree_view,
GTK_DEST_DEFAULT_ALL,
+1 -1
View File
@@ -37,7 +37,7 @@
#include "gtkgesturelongpressprivate.h"
#include "gtkgestureprivate.h"
#include "gtkmarshalers.h"
#include "gtkdnd.h"
#include "gtkdragsource.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
+67 -68
View File
@@ -48,6 +48,8 @@
#include "gtkwidgetprivate.h"
#include "gtkwindow.h"
#include "gtkeventcontrollerkey.h"
#include "gtkdragsource.h"
#include "gtkselectionprivate.h"
#include "a11y/gtkiconviewaccessibleprivate.h"
@@ -279,15 +281,12 @@ static void update_text_cell (GtkIco
static void update_pixbuf_cell (GtkIconView *icon_view);
/* Source side drag signals */
static void gtk_icon_view_drag_begin (GtkWidget *widget,
GdkDrag *drag);
static void gtk_icon_view_drag_end (GtkWidget *widget,
GdkDrag *drag);
static void gtk_icon_view_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_icon_view_drag_data_delete (GtkWidget *widget,
GdkDrag *drag);
static void gtk_icon_view_drag_begin (GtkDragSource *source,
GtkWidget *widget);
static GBytes * gtk_icon_view_drag_data_get (const char *mime_type,
gpointer data);
static void gtk_icon_view_drag_data_delete (GtkDragSource *source,
GtkWidget *widget);
/* Target side drag signals */
static void gtk_icon_view_drag_leave (GtkWidget *widget,
@@ -360,10 +359,6 @@ gtk_icon_view_class_init (GtkIconViewClass *klass)
widget_class->measure = gtk_icon_view_measure;
widget_class->size_allocate = gtk_icon_view_size_allocate;
widget_class->snapshot = gtk_icon_view_snapshot;
widget_class->drag_begin = gtk_icon_view_drag_begin;
widget_class->drag_end = gtk_icon_view_drag_end;
widget_class->drag_data_get = gtk_icon_view_drag_data_get;
widget_class->drag_data_delete = gtk_icon_view_drag_data_delete;
widget_class->drag_leave = gtk_icon_view_drag_leave;
widget_class->drag_motion = gtk_icon_view_drag_motion;
widget_class->drag_drop = gtk_icon_view_drag_drop;
@@ -5713,27 +5708,27 @@ unset_reorderable (GtkIconView *icon_view)
}
static void
set_source_row (GdkDrag *drag,
set_source_row (GtkDragSource *source,
GtkTreeModel *model,
GtkTreePath *source_row)
{
if (source_row)
g_object_set_data_full (G_OBJECT (drag),
g_object_set_data_full (G_OBJECT (source),
I_("gtk-icon-view-source-row"),
gtk_tree_row_reference_new (model, source_row),
(GDestroyNotify) gtk_tree_row_reference_free);
else
g_object_set_data_full (G_OBJECT (drag),
g_object_set_data_full (G_OBJECT (source),
I_("gtk-icon-view-source-row"),
NULL, NULL);
}
static GtkTreePath*
get_source_row (GdkDrag *drag)
get_source_row (GtkDragSource *source)
{
GtkTreeRowReference *ref;
ref = g_object_get_data (G_OBJECT (drag), "gtk-icon-view-source-row");
ref = g_object_get_data (G_OBJECT (source), "gtk-icon-view-source-row");
if (ref)
return gtk_tree_row_reference_get_path (ref);
@@ -6031,7 +6026,6 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
GdkDevice *device)
{
GtkWidget *widget = GTK_WIDGET (icon_view);
GdkDrag *drag;
GtkTreePath *path = NULL;
GtkTreeModel *model;
gboolean retval = FALSE;
@@ -6063,8 +6057,7 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
goto out;
if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
!gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
path))
!gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model), path))
goto out;
/* FIXME Check whether we're a start button, if not return FALSE and
@@ -6075,14 +6068,13 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
retval = TRUE;
drag = gtk_drag_begin (widget,
device,
gtk_drag_source_get_target_list (widget),
icon_view->priv->source_actions,
icon_view->priv->press_start_x,
icon_view->priv->press_start_y);
gtk_drag_source_drag_begin (icon_view->priv->source,
widget,
device,
icon_view->priv->press_start_x,
icon_view->priv->press_start_y);
set_source_row (drag, model, path);
set_source_row (icon_view->priv->source, model, path);
out:
if (path)
@@ -6093,8 +6085,8 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
/* Source side drag signals */
static void
gtk_icon_view_drag_begin (GtkWidget *widget,
GdkDrag *drag)
gtk_icon_view_drag_begin (GtkDragSource *source,
GtkWidget *widget)
{
GtkIconView *icon_view;
GtkIconViewItem *item;
@@ -6123,40 +6115,34 @@ gtk_icon_view_drag_begin (GtkWidget *widget,
icon = gtk_icon_view_create_drag_icon (icon_view, path);
gtk_tree_path_free (path);
gtk_drag_set_icon_paintable (drag, icon, x, y);
gtk_drag_source_set_icon (source, icon, x, y);
g_object_unref (icon);
}
static void
gtk_icon_view_drag_end (GtkWidget *widget,
GdkDrag *drag)
static GBytes *
gtk_icon_view_drag_data_get (const char *mime_type,
gpointer data)
{
/* do nothing */
}
static void
gtk_icon_view_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
GtkIconView *icon_view;
GtkIconView *icon_view = data;
GtkTreeModel *model;
GtkTreePath *source_row;
GtkSelectionData sdata = { 0, };
sdata.target = g_intern_string (mime_type);
icon_view = GTK_ICON_VIEW (widget);
model = gtk_icon_view_get_model (icon_view);
if (model == NULL)
return;
return NULL;
if (!icon_view->priv->source_set)
return;
return NULL;
source_row = get_source_row (drag);
source_row = get_source_row (icon_view->priv->source);
if (source_row == NULL)
return;
return NULL;
/* We can implement the GTK_TREE_MODEL_ROW target generically for
* any model; for DragSource models there are some other formats
@@ -6164,24 +6150,23 @@ gtk_icon_view_drag_data_get (GtkWidget *widget,
*/
if (GTK_IS_TREE_DRAG_SOURCE (model) &&
gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
source_row,
selection_data))
gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model), source_row, &sdata))
goto done;
/* If drag_data_get does nothing, try providing row data. */
if (gtk_selection_data_get_target (selection_data) == g_intern_static_string ("GTK_TREE_MODEL_ROW"))
gtk_tree_set_row_drag_data (selection_data,
model,
source_row);
if (gtk_selection_data_get_target (&sdata) == g_intern_static_string ("GTK_TREE_MODEL_ROW"))
gtk_tree_set_row_drag_data (&sdata, model, source_row);
done:
gtk_tree_path_free (source_row);
return g_bytes_new_take ((gpointer)gtk_selection_data_get_data (&sdata),
gtk_selection_data_get_length (&sdata));
}
static void
gtk_icon_view_drag_data_delete (GtkWidget *widget,
GdkDrag *drag)
gtk_icon_view_drag_data_delete (GtkDragSource *source,
GtkWidget *widget)
{
GtkTreeModel *model;
GtkIconView *icon_view;
@@ -6196,17 +6181,16 @@ gtk_icon_view_drag_data_delete (GtkWidget *widget,
if (!icon_view->priv->source_set)
return;
source_row = get_source_row (drag);
source_row = get_source_row (source);
if (source_row == NULL)
return;
gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
source_row);
gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model), source_row);
gtk_tree_path_free (source_row);
set_source_row (drag, NULL, NULL);
set_source_row (source, NULL, NULL);
}
/* Target side drag signals */
@@ -6341,16 +6325,17 @@ gtk_icon_view_drag_drop (GtkWidget *widget,
}
static GdkDragAction
gtk_icon_view_get_action (GtkWidget *treeview,
gtk_icon_view_get_action (GtkWidget *widget,
GdkDrop *drop)
{
GtkIconView *iconview = GTK_ICON_VIEW (widget);
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
GtkDragSource *source = drag ? gtk_drag_get_source (drag) : NULL;
GdkDragAction actions;
actions = gdk_drop_get_actions (drop);
if (source_widget == treeview &&
if (source == iconview->priv->source &&
actions & GDK_ACTION_MOVE)
return GDK_ACTION_MOVE;
@@ -6448,6 +6433,7 @@ gtk_icon_view_drag_data_received (GtkWidget *widget,
}
/* Drag-and-Drop support */
/**
* gtk_icon_view_enable_model_drag_source:
* @icon_view: a #GtkIconView
@@ -6458,16 +6444,27 @@ gtk_icon_view_drag_data_received (GtkWidget *widget,
*
* Turns @icon_view into a drag source for automatic DND. Calling this
* method sets #GtkIconView:reorderable to %FALSE.
*
* Returns: (transfer none): the #GtkDragSource that has been attached to @icon_view
**/
void
GtkDragSource *
gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view,
GdkModifierType start_button_mask,
GdkContentFormats *formats,
GdkDragAction actions)
{
g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
GdkContentProvider *content;
gtk_drag_source_set (GTK_WIDGET (icon_view), 0, formats, actions);
g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
content = gdk_content_provider_new_with_formats (formats, gtk_icon_view_drag_data_get, icon_view);
icon_view->priv->source = gtk_drag_source_new (content, actions);
g_object_unref (content);
g_signal_connect (icon_view->priv->source, "drag-begin",
G_CALLBACK (gtk_icon_view_drag_begin), icon_view);
g_signal_connect (icon_view->priv->source, "drag-data-delete",
G_CALLBACK (gtk_icon_view_drag_data_delete), icon_view);
icon_view->priv->start_button_mask = start_button_mask;
icon_view->priv->source_actions = actions;
@@ -6475,6 +6472,8 @@ gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view,
icon_view->priv->source_set = TRUE;
unset_reorderable (icon_view);
return icon_view->priv->source;
}
/**
@@ -6517,7 +6516,7 @@ gtk_icon_view_unset_model_drag_source (GtkIconView *icon_view)
if (icon_view->priv->source_set)
{
gtk_drag_source_unset (GTK_WIDGET (icon_view));
g_clear_object (&icon_view->priv->source);
icon_view->priv->source_set = FALSE;
}
+2 -1
View File
@@ -28,6 +28,7 @@
#include <gtk/gtkcellarea.h>
#include <gtk/gtkselection.h>
#include <gtk/gtktooltip.h>
#include <gtk/gtkdragsource.h>
G_BEGIN_DECLS
@@ -213,7 +214,7 @@ void gtk_icon_view_scroll_to_path (GtkIconView *icon_
/* Drag-and-Drop support */
GDK_AVAILABLE_IN_ALL
void gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view,
GtkDragSource * gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view,
GdkModifierType start_button_mask,
GdkContentFormats *formats,
GdkDragAction actions);
+3
View File
@@ -19,6 +19,7 @@
#include "gtk/gtkcssnodeprivate.h"
#include "gtk/gtkgestureclick.h"
#include "gtk/gtkeventcontrollermotion.h"
#include "gtk/gtkdragsource.h"
#ifndef __GTK_ICON_VIEW_PRIVATE_H__
#define __GTK_ICON_VIEW_PRIVATE_H__
@@ -132,6 +133,8 @@ struct _GtkIconViewPrivate
gint press_start_x;
gint press_start_y;
GtkDragSource *source;
GdkDragAction source_actions;
GdkDragAction dest_actions;
+16 -82
View File
@@ -54,6 +54,7 @@
#include "gtkwindow.h"
#include "gtkpopovermenu.h"
#include "gtknative.h"
#include "gtkdragsource.h"
#include "a11y/gtklabelaccessibleprivate.h"
@@ -501,9 +502,6 @@ static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
static void gtk_label_setup_mnemonic (GtkLabel *label,
GtkWidget *toplevel,
guint last_key);
static void gtk_label_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_label_buildable_interface_init (GtkBuildableIface *iface);
static gboolean gtk_label_buildable_custom_tag_start (GtkBuildable *buildable,
@@ -652,7 +650,6 @@ gtk_label_class_init (GtkLabelClass *class)
widget_class->unroot = gtk_label_unroot;
widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
widget_class->popup_menu = gtk_label_popup_menu;
widget_class->drag_data_get = gtk_label_drag_data_get;
widget_class->grab_focus = gtk_label_grab_focus;
widget_class->focus = gtk_label_focus;
widget_class->get_request_mode = gtk_label_get_request_mode;
@@ -4597,16 +4594,10 @@ connect_mnemonics_visible_notify (GtkLabel *label)
}
}
static void
drag_begin_cb (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
static GdkPaintable *
get_selection_paintable (GtkLabel *label)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GdkPaintable *paintable = NULL;
g_signal_handlers_disconnect_by_func (widget, drag_begin_cb, NULL);
if ((priv->select_info->selection_anchor !=
priv->select_info->selection_end) &&
@@ -4628,20 +4619,10 @@ drag_begin_cb (GtkWidget *widget,
if (start > len)
start = len;
paintable = gtk_text_util_create_drag_icon (widget,
priv->text + start,
end - start);
return gtk_text_util_create_drag_icon (GTK_WIDGET (label), priv->text + start, end - start);
}
if (paintable)
{
gtk_drag_set_icon_paintable (drag, paintable, 0, 0);
g_object_unref (paintable);
}
else
{
gtk_drag_set_icon_default (drag);
}
return NULL;
}
static void
@@ -4734,27 +4715,21 @@ gtk_label_drag_gesture_update (GtkGestureDrag *gesture,
if (info->in_drag)
{
if (gtk_drag_check_threshold (widget,
info->drag_start_x,
info->drag_start_y,
x, y))
if (gtk_drag_check_threshold (widget, info->drag_start_x, info->drag_start_y, x, y))
{
GdkContentFormats *target_list = gdk_content_formats_new (NULL, 0);
GtkDragSource *source;
GdkPaintable *paintable;
GdkDevice *device;
target_list = gtk_content_formats_add_text_targets (target_list);
g_signal_connect (widget, "drag-begin",
G_CALLBACK (drag_begin_cb), NULL);
gtk_drag_begin (widget,
gtk_gesture_get_device (GTK_GESTURE (gesture)),
target_list,
GDK_ACTION_COPY,
info->drag_start_x,
info->drag_start_y);
source = gtk_drag_source_new (info->provider, GDK_ACTION_COPY);
paintable = get_selection_paintable (label);
gtk_drag_source_set_icon (source, paintable, 9, 0);
g_clear_object (&paintable);
device = gtk_gesture_get_device (GTK_GESTURE (gesture));
gtk_drag_source_drag_begin (source, widget, device, info->drag_start_x, info->drag_start_y);
g_object_unref (source);
info->in_drag = FALSE;
gdk_content_formats_unref (target_list);
}
}
else
@@ -5140,47 +5115,6 @@ gtk_label_get_selectable (GtkLabel *label)
return priv->select_info && priv->select_info->selectable;
}
static void
gtk_label_set_selection_text (GtkLabel *label,
GtkSelectionData *selection_data)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
if (priv->select_info &&
(priv->select_info->selection_anchor !=
priv->select_info->selection_end) &&
priv->text)
{
gint start, end;
gint len;
start = MIN (priv->select_info->selection_anchor,
priv->select_info->selection_end);
end = MAX (priv->select_info->selection_anchor,
priv->select_info->selection_end);
len = strlen (priv->text);
if (end > len)
end = len;
if (start > len)
start = len;
gtk_selection_data_set_text (selection_data,
priv->text + start,
end - start);
}
}
static void
gtk_label_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
gtk_label_set_selection_text (GTK_LABEL (widget), selection_data);
}
static void
gtk_label_select_region_index (GtkLabel *label,
gint anchor_index,
+77 -36
View File
@@ -124,10 +124,6 @@ static void gtk_link_button_set_property (GObject *object,
GParamSpec *pspec);
static void gtk_link_button_clicked (GtkButton *button);
static gboolean gtk_link_button_popup_menu (GtkWidget *widget);
static void gtk_link_button_drag_data_get_cb (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection,
gpointer user_data);
static gboolean gtk_link_button_query_tooltip_cb (GtkWidget *widget,
gint x,
gint y,
@@ -251,31 +247,96 @@ gtk_link_button_get_menu_model (void)
return G_MENU_MODEL (menu);
}
#define GTK_TYPE_LINK_CONTENT (gtk_link_content_get_type ())
#define GTK_LINK_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_LINK_CONTENT, GtkLinkContent))
typedef struct _GtkLinkContent GtkLinkContent;
typedef struct _GtkLinkContentClass GtkLinkContentClass;
struct _GtkLinkContent
{
GdkContentProvider parent;
GtkLinkButton *link;
};
struct _GtkLinkContentClass
{
GdkContentProviderClass parent_class;
};
GType gtk_link_content_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GtkLinkContent, gtk_link_content, GDK_TYPE_CONTENT_PROVIDER)
static GdkContentFormats *
gtk_link_content_ref_formats (GdkContentProvider *provider)
{
GtkLinkContent *content = GTK_LINK_CONTENT (provider);
if (content->link)
return gdk_content_formats_union (gdk_content_formats_new_for_gtype (G_TYPE_STRING),
gdk_content_formats_new (link_drop_types, G_N_ELEMENTS (link_drop_types)));
else
return gdk_content_formats_new (NULL, 0);
}
static gboolean
gtk_link_content_get_value (GdkContentProvider *provider,
GValue *value,
GError **error)
{
GtkLinkContent *content = GTK_LINK_CONTENT (provider);
if (G_VALUE_HOLDS (value, G_TYPE_STRING) &&
content->link != NULL)
{
GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (content->link);
char *uri;
uri = g_strdup_printf ("%s\r\n", priv->uri);
g_value_set_string (value, uri);
g_free (uri);
return TRUE;
}
return GDK_CONTENT_PROVIDER_CLASS (gtk_link_content_parent_class)->get_value (provider, value, error);
}
static void
gtk_link_content_class_init (GtkLinkContentClass *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
provider_class->ref_formats = gtk_link_content_ref_formats;
provider_class->get_value = gtk_link_content_get_value;
}
static void
gtk_link_content_init (GtkLinkContent *content)
{
}
static void
gtk_link_button_init (GtkLinkButton *link_button)
{
GtkStyleContext *context;
GdkContentFormats *targets;
GtkGesture *gesture;
GdkContentProvider *content;
GtkDragSource *source;
gtk_button_set_relief (GTK_BUTTON (link_button), GTK_RELIEF_NONE);
gtk_widget_set_state_flags (GTK_WIDGET (link_button), GTK_STATE_FLAG_LINK, FALSE);
gtk_widget_set_has_tooltip (GTK_WIDGET (link_button), TRUE);
g_signal_connect (link_button, "drag-data-get",
G_CALLBACK (gtk_link_button_drag_data_get_cb), NULL);
g_signal_connect (link_button, "query-tooltip",
G_CALLBACK (gtk_link_button_query_tooltip_cb), NULL);
/* enable drag source */
targets = gdk_content_formats_new (link_drop_types, G_N_ELEMENTS (link_drop_types));
gtk_drag_source_set (GTK_WIDGET (link_button),
GDK_BUTTON1_MASK,
targets,
GDK_ACTION_COPY);
gdk_content_formats_unref (targets);
gtk_drag_source_set_icon_name (GTK_WIDGET (link_button), "text-x-generic");
content = g_object_new (GTK_TYPE_LINK_CONTENT, NULL);
GTK_LINK_CONTENT (content)->link = link_button;
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
gtk_drag_source_attach (source, GTK_WIDGET (link_button), GDK_BUTTON1_MASK);
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), FALSE);
@@ -449,26 +510,6 @@ gtk_link_button_popup_menu (GtkWidget *widget)
return TRUE;
}
static void
gtk_link_button_drag_data_get_cb (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection,
gpointer user_data)
{
GtkLinkButton *link_button = GTK_LINK_BUTTON (widget);
GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button);
gchar *uri;
uri = g_strdup_printf ("%s\r\n", priv->uri);
gtk_selection_data_set (selection,
gtk_selection_data_get_target (selection),
8,
(guchar *) uri,
strlen (uri));
g_free (uri);
}
/**
* gtk_link_button_new:
* @uri: a valid URI
+1
View File
@@ -58,6 +58,7 @@ OBJECT:VOID
STRING:DOUBLE
STRING:STRING
VOID:BOOLEAN,BOOLEAN,BOOLEAN
VOID:BOXED
VOID:BOXED,BOXED
VOID:BOXED,BOXED,POINTER
VOID:BOXED,ENUM
+89 -62
View File
@@ -52,6 +52,9 @@
#include "gtktypebuiltins.h"
#include "gtkwidgetpath.h"
#include "gtkwidgetprivate.h"
#include "gtkdragsource.h"
#include "gtkwidgetpaintable.h"
#include "gtkselectionprivate.h"
#include "a11y/gtknotebookaccessible.h"
@@ -695,13 +698,13 @@ static gboolean gtk_notebook_focus (GtkWidget *widget,
GtkDirectionType direction);
/*** Drag and drop Methods ***/
static void gtk_notebook_drag_begin (GtkWidget *widget,
GdkDrag *drag);
static void gtk_notebook_drag_end (GtkWidget *widget,
GdkDrag *drag);
static gboolean gtk_notebook_drag_failed (GtkWidget *widget,
GdkDrag *drag,
GtkDragResult result);
static void gtk_notebook_drag_begin (GtkDragSource *source,
GtkWidget *widget);
static void gtk_notebook_drag_end (GtkDragSource *source,
GtkWidget *widget);
static gboolean gtk_notebook_drag_failed (GtkDragSource *source,
GdkDragCancelReason reason,
GtkWidget *widget);
static gboolean gtk_notebook_drag_motion (GtkWidget *widget,
GdkDrop *drop,
gint x,
@@ -712,9 +715,8 @@ static gboolean gtk_notebook_drag_drop (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y);
static void gtk_notebook_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *data);
static GBytes * gtk_notebook_drag_data_get (const char *mime_type,
gpointer data);
static void gtk_notebook_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *data);
@@ -964,14 +966,10 @@ gtk_notebook_class_init (GtkNotebookClass *class)
widget_class->grab_notify = gtk_notebook_grab_notify;
widget_class->state_flags_changed = gtk_notebook_state_flags_changed;
widget_class->focus = gtk_notebook_focus;
widget_class->drag_begin = gtk_notebook_drag_begin;
widget_class->drag_end = gtk_notebook_drag_end;
widget_class->drag_motion = gtk_notebook_drag_motion;
widget_class->drag_leave = gtk_notebook_drag_leave;
widget_class->drag_drop = gtk_notebook_drag_drop;
widget_class->drag_data_get = gtk_notebook_drag_data_get;
widget_class->drag_data_received = gtk_notebook_drag_data_received;
widget_class->drag_failed = gtk_notebook_drag_failed;
widget_class->compute_expand = gtk_notebook_compute_expand;
container_class->add = gtk_notebook_add;
@@ -2881,12 +2879,23 @@ gtk_notebook_motion (GtkEventController *controller,
if (page->detachable &&
check_threshold (notebook, priv->mouse_x, priv->mouse_y))
{
GdkContentProvider *content;
GtkDragSource *source;
priv->detached_tab = priv->cur_page;
gtk_drag_begin (widget,
gtk_get_current_event_device (),
priv->source_targets, GDK_ACTION_MOVE,
priv->drag_begin_x, priv->drag_begin_y);
content = gdk_content_provider_new_with_formats (priv->source_targets, gtk_notebook_drag_data_get, widget);
source = gtk_drag_source_new (content, GDK_ACTION_MOVE);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_notebook_drag_begin), notebook);
g_signal_connect (source, "drag-end", G_CALLBACK (gtk_notebook_drag_end), notebook);
g_signal_connect (source, "drag-failed", G_CALLBACK (gtk_notebook_drag_failed), notebook);
gtk_drag_source_drag_begin (source, widget,
gtk_get_current_event_device (),
priv->drag_begin_x, priv->drag_begin_y);
g_object_unref (source);
return;
}
@@ -3088,13 +3097,14 @@ update_arrow_nodes (GtkNotebook *notebook)
}
static void
gtk_notebook_drag_begin (GtkWidget *widget,
GdkDrag *drag)
gtk_notebook_drag_begin (GtkDragSource *source,
GtkWidget *widget)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
graphene_rect_t bounds;
GtkWidget *tab_label;
GdkPaintable *paintable;
if (priv->dnd_timer)
{
@@ -3120,14 +3130,16 @@ gtk_notebook_drag_begin (GtkWidget *widget,
gtk_style_context_add_class (gtk_widget_get_style_context (priv->dnd_child), "background");
gtk_drag_set_icon_widget (drag, tab_label, -2, -2);
g_object_set_data (G_OBJECT (priv->dnd_child), "drag-context", drag);
paintable = gtk_widget_paintable_new (tab_label);
gtk_drag_source_set_icon (source, paintable, -2, -2);
g_object_set_data (G_OBJECT (priv->dnd_child), "drag-source", source);
g_object_unref (paintable);
g_object_unref (tab_label);
}
static void
gtk_notebook_drag_end (GtkWidget *widget,
GdkDrag *drag)
gtk_notebook_drag_end (GtkDragSource *source,
GtkWidget *widget)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
@@ -3170,16 +3182,16 @@ gtk_notebook_create_window (GtkNotebook *notebook,
}
static gboolean
gtk_notebook_drag_failed (GtkWidget *widget,
GdkDrag *drag,
GtkDragResult result)
gtk_notebook_drag_failed (GtkDragSource *source,
GdkDragCancelReason reason,
GtkWidget *widget)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
priv->rootwindow_drop = FALSE;
if (result == GTK_DRAG_RESULT_NO_TARGET)
if (reason == GDK_DRAG_CANCEL_NO_TARGET)
{
GtkNotebook *dest_notebook = NULL;
@@ -3251,30 +3263,39 @@ gtk_notebook_drag_motion (GtkWidget *widget,
if (target == tab_target)
{
GQuark group, source_group;
GtkNotebook *source;
GtkWidget *source_child;
GdkDrag *drag = gdk_drop_get_drag (drop);
retval = TRUE;
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;
group = notebook->priv->group;
source_group = source->priv->group;
if (group != 0 && group == source_group &&
!(widget == source_child ||
gtk_widget_is_ancestor (widget, source_child)))
if (!drag)
{
gdk_drop_status (drop, GDK_ACTION_MOVE);
goto out;
gdk_drop_status (drop, 0);
}
else
{
/* it's a tab, but doesn't share
* ID with this notebook */
gdk_drop_status (drop, 0);
GtkDragSource *drag_source = gtk_drag_get_source (drag);
GtkNotebook *source = GTK_NOTEBOOK (gtk_drag_source_get_origin (drag_source));
g_assert (source->priv->cur_page != NULL);
source_child = source->priv->cur_page->child;
group = notebook->priv->group;
source_group = source->priv->group;
if (group != 0 && group == source_group &&
!(widget == source_child ||
gtk_widget_is_ancestor (widget, source_child)))
{
gdk_drop_status (drop, GDK_ACTION_MOVE);
goto out;
}
else
{
/* it's a tab, but doesn't share
* ID with this notebook */
gdk_drop_status (drop, 0);
}
}
}
@@ -3419,30 +3440,32 @@ do_detach_tab (GtkNotebook *from,
gtk_notebook_set_current_page (to, page_num);
}
static void
gtk_notebook_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *data)
static GBytes *
gtk_notebook_drag_data_get (const char *mime_type,
gpointer data)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebook *notebook = GTK_NOTEBOOK (data);
GtkNotebookPrivate *priv = notebook->priv;
GdkAtom target;
GtkSelectionData sdata = { 0, };
target = gtk_selection_data_get_target (data);
if (target == g_intern_static_string ("GTK_NOTEBOOK_TAB"))
sdata.target = g_intern_string (mime_type);
if (sdata.target == g_intern_static_string ("GTK_NOTEBOOK_TAB"))
{
gtk_selection_data_set (data,
target,
gtk_selection_data_set (&sdata,
sdata.target,
8,
(void*) &priv->detached_tab->child,
sizeof (gpointer));
priv->rootwindow_drop = FALSE;
}
else if (target == g_intern_static_string ("application/x-rootwindow-drop"))
else if (sdata.target == g_intern_static_string ("application/x-rootwindow-drop"))
{
gtk_selection_data_set (data, target, 8, NULL, 0);
gtk_selection_data_set (&sdata, sdata.target, 8, NULL, 0);
priv->rootwindow_drop = TRUE;
}
return g_bytes_new_take (sdata.data, sdata.length);
}
static void
@@ -3457,7 +3480,7 @@ gtk_notebook_drag_data_received (GtkWidget *widget,
notebook = GTK_NOTEBOOK (widget);
drag = gdk_drop_get_drag (drop);
source_widget = gtk_drag_get_source_widget (drag);
source_widget = drag ? gtk_drag_source_get_origin (gtk_drag_get_source (drag)) : NULL;
if (source_widget &&
(gdk_drop_get_actions (drop) & GDK_ACTION_MOVE) &&
@@ -4254,10 +4277,10 @@ gtk_notebook_real_remove (GtkNotebook *notebook,
if (priv->operation == DRAG_OPERATION_DETACH && !priv->remove_in_detach)
{
GdkDrag *drag;
GtkDragSource *source;
drag = (GdkDrag *)g_object_get_data (G_OBJECT (priv->dnd_child), "drag-context");
gtk_drag_cancel (drag);
source = (GtkDragSource *)g_object_get_data (G_OBJECT (priv->dnd_child), "drag-source");
gtk_drag_source_drag_cancel (source);
}
}
if (priv->switch_tab == list)
@@ -7099,15 +7122,19 @@ gtk_notebook_get_tab_detachable (GtkNotebook *notebook,
* |[<!-- language="C" -->
* static void
* on_drag_data_received (GtkWidget *widget,
* GdkDrag *drag,
* GdkDrop *drop,
* GtkSelectionData *data,
* guint time,
* gpointer user_data)
* {
* GtkDrag *drag;
* GtkDragSource *source;
* GtkWidget *notebook;
* GtkWidget **child;
*
* notebook = gtk_drag_get_source_widget (drag);
* drag = gtk_drop_get_drag (drop);
* source = gtk_drag_get_source (drag);
* notebook = gtk_drag_source_get_origin (source);
* child = (void*) gtk_selection_data_get_data (data);
*
* // process_widget (*child);
+12 -34
View File
@@ -37,6 +37,7 @@
#include "gtkwidgetpath.h"
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerscroll.h"
#include "gtkdragsource.h"
typedef struct
{
@@ -1240,15 +1241,8 @@ set_button_image (GtkPathBar *path_bar,
static void
button_data_free (ButtonData *button_data)
{
if (button_data->file)
g_object_unref (button_data->file);
button_data->file = NULL;
g_clear_object (&button_data->file);
g_free (button_data->dir_name);
button_data->dir_name = NULL;
button_data->button = NULL;
g_free (button_data);
}
@@ -1312,25 +1306,6 @@ find_button_type (GtkPathBar *path_bar,
return NORMAL_BUTTON;
}
static void
button_drag_data_get_cb (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
gpointer data)
{
ButtonData *button_data;
char *uris[2];
button_data = data;
uris[0] = g_file_get_uri (button_data->file);
uris[1] = NULL;
gtk_selection_data_set_uris (selection_data, uris);
g_free (uris[0]);
}
static ButtonData *
make_directory_button (GtkPathBar *path_bar,
const char *dir_name,
@@ -1341,6 +1316,9 @@ make_directory_button (GtkPathBar *path_bar,
AtkObject *atk_obj;
GtkWidget *child = NULL;
ButtonData *button_data;
GValue value = G_VALUE_INIT;
GdkContentProvider *content;
GtkDragSource *source;
file_is_hidden = !! file_is_hidden;
/* Is it a special button? */
@@ -1387,13 +1365,13 @@ make_directory_button (GtkPathBar *path_bar,
g_object_weak_ref (G_OBJECT (button_data->button),
(GWeakNotify) button_data_free, button_data);
gtk_drag_source_set (button_data->button,
GDK_BUTTON1_MASK,
NULL,
GDK_ACTION_COPY);
gtk_drag_source_add_uri_targets (button_data->button);
g_signal_connect (button_data->button, "drag-data-get",
G_CALLBACK (button_drag_data_get_cb), button_data);
g_value_init (&value, G_TYPE_FILE);
g_value_set_object (&value, button_data->file);
content = gdk_content_provider_new_for_value (&value);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
gtk_drag_source_attach (source, button_data->button, GDK_BUTTON1_MASK);
g_object_unref (content);
g_value_unset (&value);
return button_data;
}
+32 -35
View File
@@ -63,6 +63,8 @@
#include "gtkgestureclick.h"
#include "gtkgesturedrag.h"
#include "gtknative.h"
#include "gtkdragsource.h"
#include "gtkwidgetpaintable.h"
/*< private >
* SECTION:gtkplacessidebar
@@ -1720,13 +1722,13 @@ stop_drop_feedback (GtkPlacesSidebar *sidebar)
}
static void
drag_begin_callback (GtkWidget *widget,
GdkDrag *drag,
drag_begin_callback (GtkDragSource *source,
gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
GtkAllocation allocation;
GtkWidget *drag_widget;
GdkPaintable *paintable;
gtk_widget_get_allocation (sidebar->drag_row, &allocation);
gtk_widget_hide (sidebar->drag_row);
@@ -1737,18 +1739,16 @@ drag_begin_callback (GtkWidget *widget,
gtk_widget_set_opacity (drag_widget, 0.8);
gtk_drag_set_icon_widget (drag,
drag_widget,
sidebar->drag_row_x,
sidebar->drag_row_y);
paintable = gtk_widget_paintable_new (drag_widget);
gtk_drag_source_set_icon (source, paintable, sidebar->drag_row_x, sidebar->drag_row_y);
g_object_unref (paintable);
g_object_set_data_full (G_OBJECT (source), "row-widget", drag_widget, (GDestroyNotify)gtk_widget_destroy);
}
static GtkWidget *
create_placeholder_row (GtkPlacesSidebar *sidebar)
{
return g_object_new (GTK_TYPE_SIDEBAR_ROW,
"placeholder", TRUE,
NULL);
return g_object_new (GTK_TYPE_SIDEBAR_ROW, "placeholder", TRUE, NULL);
}
static gboolean
@@ -1950,23 +1950,16 @@ drop_files_as_bookmarks (GtkPlacesSidebar *sidebar,
}
}
static void
drag_data_get_callback (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *data,
gpointer user_data)
static GBytes *
drag_data_get_callback (const char *mimetype,
gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
GdkAtom target = gtk_selection_data_get_target (data);
if (target == g_intern_static_string ("DND_GTK_SIDEBAR_ROW"))
{
gtk_selection_data_set (data,
target,
8,
(void*)&sidebar->drag_row,
sizeof (gpointer));
}
if (mimetype == g_intern_static_string ("DND_GTK_SIDEBAR_ROW"))
return g_bytes_new_take ((gpointer)&sidebar->drag_row, sizeof (gpointer));
return NULL;
}
static void
@@ -2088,8 +2081,7 @@ out:
}
static void
drag_end_callback (GtkWidget *widget,
GdkDrag *drag,
drag_end_callback (GtkDragSource *source,
gpointer user_data)
{
stop_drop_feedback (GTK_PLACES_SIDEBAR (user_data));
@@ -3778,6 +3770,8 @@ on_row_dragged (GtkGestureDrag *gesture,
{
gdouble start_x, start_y;
gint drag_x, drag_y;
GdkContentProvider *content;
GtkDragSource *source;
gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
gtk_widget_translate_coordinates (GTK_WIDGET (row),
@@ -3787,10 +3781,19 @@ on_row_dragged (GtkGestureDrag *gesture,
sidebar->dragging_over = TRUE;
gtk_drag_begin (GTK_WIDGET (sidebar),
gtk_gesture_get_device (GTK_GESTURE (gesture)),
sidebar->source_targets, GDK_ACTION_MOVE,
drag_x, drag_y);
content = gdk_content_provider_new_with_formats (sidebar->source_targets,
drag_data_get_callback,
sidebar);
source = gtk_drag_source_new (content, GDK_ACTION_MOVE);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin_callback), sidebar);
g_signal_connect (source, "drag-end", G_CALLBACK (drag_end_callback), sidebar);
gtk_drag_source_drag_begin (source,
GTK_WIDGET (sidebar),
gtk_gesture_get_device (GTK_GESTURE (gesture)),
drag_x, drag_y);
g_object_unref (source);
}
g_object_unref (sidebar);
@@ -4090,18 +4093,12 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
sidebar->source_targets = gdk_content_formats_new (dnd_source_targets, G_N_ELEMENTS (dnd_source_targets));
sidebar->source_targets = gtk_content_formats_add_text_targets (sidebar->source_targets);
g_signal_connect (sidebar->list_box, "drag-begin",
G_CALLBACK (drag_begin_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-motion",
G_CALLBACK (drag_motion_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-data-get",
G_CALLBACK (drag_data_get_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-data-received",
G_CALLBACK (drag_data_received_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-drop",
G_CALLBACK (drag_drop_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-end",
G_CALLBACK (drag_end_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-leave",
G_CALLBACK (drag_leave_callback), sidebar);
sidebar->drag_row = NULL;
+39 -92
View File
@@ -67,6 +67,7 @@
#include "gtkwindow.h"
#include "gtknative.h"
#include "gtkactionmuxerprivate.h"
#include "gtkdragsource.h"
#include "a11y/gtktextaccessible.h"
@@ -344,15 +345,6 @@ static void gtk_text_drag_leave (GtkWidget *widget,
static void gtk_text_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data);
static void gtk_text_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_text_drag_data_delete (GtkWidget *widget,
GdkDrag *drag);
static void gtk_text_drag_begin (GtkWidget *widget,
GdkDrag *drag);
static void gtk_text_drag_end (GtkWidget *widget,
GdkDrag *drag);
/* GtkEditable method implementations
@@ -729,8 +721,6 @@ gtk_text_class_init (GtkTextClass *class)
widget_class->snapshot = gtk_text_snapshot;
widget_class->grab_focus = gtk_text_grab_focus;
widget_class->style_updated = gtk_text_style_updated;
widget_class->drag_begin = gtk_text_drag_begin;
widget_class->drag_end = gtk_text_drag_end;
widget_class->direction_changed = gtk_text_direction_changed;
widget_class->state_flags_changed = gtk_text_state_flags_changed;
widget_class->root = gtk_text_root;
@@ -740,8 +730,6 @@ gtk_text_class_init (GtkTextClass *class)
widget_class->drag_motion = gtk_text_drag_motion;
widget_class->drag_leave = gtk_text_drag_leave;
widget_class->drag_data_received = gtk_text_drag_data_received;
widget_class->drag_data_get = gtk_text_drag_data_get;
widget_class->drag_data_delete = gtk_text_drag_data_delete;
class->move_cursor = gtk_text_move_cursor;
class->insert_at_cursor = gtk_text_insert_at_cursor;
@@ -2801,6 +2789,12 @@ gtk_text_motion_controller_motion (GtkEventControllerMotion *controller,
}
}
static void
drag_end (GtkText *self)
{
g_object_set_data (G_OBJECT (self), "drag-source", NULL);
}
static void
gtk_text_drag_gesture_update (GtkGestureDrag *gesture,
double offset_x,
@@ -2837,23 +2831,38 @@ gtk_text_drag_gesture_update (GtkGestureDrag *gesture,
{
int *ranges;
int n_ranges;
GdkContentFormats *target_list = gdk_content_formats_new (NULL, 0);
guint actions = priv->editable ? GDK_ACTION_COPY | GDK_ACTION_MOVE : GDK_ACTION_COPY;
target_list = gtk_content_formats_add_text_targets (target_list);
char *text;
GdkPaintable *paintable;
GtkDragSource *source;
text = _gtk_text_get_selected_text (self);
gtk_text_get_pixel_ranges (self, &ranges, &n_ranges);
gtk_drag_begin (widget,
gdk_event_get_device ((GdkEvent*) event),
target_list, actions,
priv->drag_start_x + ranges[0],
priv->drag_start_y);
paintable = gtk_text_util_create_drag_icon (widget, text, -1);
source = gtk_drag_source_new (priv->selection_content,
priv->editable ? GDK_ACTION_COPY | GDK_ACTION_MOVE
: GDK_ACTION_COPY);
gtk_drag_source_set_icon (source,
paintable,
priv->drag_start_x - ranges[0],
priv->drag_start_y);
g_signal_connect_swapped (source, "drag-data-delete",
G_CALLBACK (gtk_text_delete_selection), self);
g_signal_connect_swapped (source, "drag-end",
G_CALLBACK (drag_end), self);
g_object_set_data_full (G_OBJECT (self), "drag-source", source, g_object_unref);
gtk_drag_source_drag_begin (source,
widget,
gdk_event_get_device ((GdkEvent*) event),
priv->drag_start_x + ranges[0],
priv->drag_start_y);
g_object_unref (paintable);
g_free (ranges);
g_free (text);
priv->in_drag = FALSE;
gdk_content_formats_unref (target_list);
}
}
else
@@ -6094,41 +6103,6 @@ gtk_text_selection_bubble_popup_set (GtkText *self)
g_source_set_name_by_id (priv->selection_bubble_timeout_id, "[gtk] gtk_text_selection_bubble_popup_cb");
}
static void
gtk_text_drag_begin (GtkWidget *widget,
GdkDrag *drag)
{
GtkText *self = GTK_TEXT (widget);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
char *text;
text = _gtk_text_get_selected_text (self);
if (self)
{
int *ranges, n_ranges;
GdkPaintable *paintable;
paintable = gtk_text_util_create_drag_icon (widget, text, -1);
gtk_text_get_pixel_ranges (self, &ranges, &n_ranges);
gtk_drag_set_icon_paintable (drag,
paintable,
priv->drag_start_x - ranges[0],
priv->drag_start_y);
g_free (ranges);
g_object_unref (paintable);
g_free (text);
}
}
static void
gtk_text_drag_end (GtkWidget *widget,
GdkDrag *drag)
{
}
static void
gtk_text_drag_leave (GtkWidget *widget,
GdkDrop *drop)
@@ -6218,14 +6192,17 @@ static GdkDragAction
gtk_text_get_action (GtkText *self,
GdkDrop *drop)
{
GtkWidget *widget = GTK_WIDGET (self);
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
GtkDragSource *source;
GtkDragSource *source1;
GdkDragAction actions;
actions = gdk_drop_get_actions (drop);
if (source_widget == widget &&
source = drag ? gtk_drag_get_source (drag) : NULL;
source1 = (GtkDragSource*)g_object_get_data (G_OBJECT (self), "drag-source");
if (source && source == source1 &&
actions & GDK_ACTION_MOVE)
return GDK_ACTION_MOVE;
@@ -6286,36 +6263,6 @@ gtk_text_drag_data_received (GtkWidget *widget,
g_free (str);
}
static void
gtk_text_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
GtkText *self = GTK_TEXT (widget);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
if (priv->selection_bound != priv->current_pos)
{
char *str = gtk_text_get_display_text (self, priv->selection_bound, priv->current_pos);
gtk_selection_data_set_text (selection_data, str, -1);
g_free (str);
}
}
static void
gtk_text_drag_data_delete (GtkWidget *widget,
GdkDrag *drag)
{
GtkText *self = GTK_TEXT (widget);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
if (priv->editable &&
priv->selection_bound != priv->current_pos)
gtk_text_delete_selection (self);
}
/* We display the cursor when
*
* - the selection is empty, AND
+7
View File
@@ -4078,6 +4078,13 @@ cut_or_copy (GtkTextBuffer *buffer,
}
}
GdkContentProvider *
gtk_text_buffer_get_selection_content (GtkTextBuffer *buffer)
{
return gtk_text_buffer_content_new (buffer);
}
/**
* gtk_text_buffer_cut_clipboard:
* @buffer: a #GtkTextBuffer
+4
View File
@@ -453,6 +453,10 @@ gboolean gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
gboolean interactive,
gboolean default_editable);
GDK_AVAILABLE_IN_ALL
GdkContentProvider *
gtk_text_buffer_get_selection_content (GtkTextBuffer *buffer);
GDK_AVAILABLE_IN_ALL
gboolean gtk_text_buffer_get_can_undo (GtkTextBuffer *buffer);
GDK_AVAILABLE_IN_ALL
+38 -107
View File
@@ -418,17 +418,6 @@ static gboolean get_middle_click_paste (GtkTextView *text_view);
static GtkTextBuffer* gtk_text_view_create_buffer (GtkTextView *text_view);
/* Source side drag signals */
static void gtk_text_view_drag_begin (GtkWidget *widget,
GdkDrag *drag);
static void gtk_text_view_drag_end (GtkWidget *widget,
GdkDrag *drag);
static void gtk_text_view_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_text_view_drag_data_delete (GtkWidget *widget,
GdkDrag *drag);
/* Target side drag signals */
static void gtk_text_view_drag_leave (GtkWidget *widget,
GdkDrop *drop);
@@ -712,10 +701,6 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
widget_class->size_allocate = gtk_text_view_size_allocate;
widget_class->snapshot = gtk_text_view_snapshot;
widget_class->focus = gtk_text_view_focus;
widget_class->drag_begin = gtk_text_view_drag_begin;
widget_class->drag_end = gtk_text_view_drag_end;
widget_class->drag_data_get = gtk_text_view_drag_data_get;
widget_class->drag_data_delete = gtk_text_view_drag_data_delete;
widget_class->drag_leave = gtk_text_view_drag_leave;
widget_class->drag_motion = gtk_text_view_drag_motion;
@@ -6698,8 +6683,7 @@ gtk_text_view_copy_clipboard (GtkTextView *text_view)
{
GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (text_view));
gtk_text_buffer_copy_clipboard (get_buffer (text_view),
clipboard);
gtk_text_buffer_copy_clipboard (get_buffer (text_view), clipboard);
/* on copy do not scroll, we are already onscreen */
}
@@ -7691,30 +7675,15 @@ gtk_text_view_im_context_filter_keypress (GtkTextView *text_view,
*/
static void
drag_begin_cb (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
gtk_text_view_drag_data_delete (GtkTextView *text_view)
{
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);
GtkTextIter start;
GtkTextIter end;
GdkPaintable *paintable = NULL;
gtk_text_buffer_delete_selection (text_view->priv->buffer, TRUE, text_view->priv->editable);
}
g_signal_handlers_disconnect_by_func (widget, drag_begin_cb, NULL);
if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
paintable = gtk_text_util_create_rich_drag_icon (widget, buffer, &start, &end);
if (paintable)
{
gtk_drag_set_icon_paintable (drag, paintable, 0, 0);
g_object_unref (paintable);
}
else
{
gtk_drag_set_icon_default (drag);
}
static void
drag_end (GtkTextView *self)
{
g_object_set_data (G_OBJECT (self), "drag-source", NULL);
}
static void
@@ -7724,78 +7693,36 @@ gtk_text_view_start_selection_dnd (GtkTextView *text_view,
gint x,
gint y)
{
GdkContentFormats *formats;
formats = gdk_content_formats_new_for_gtype (GTK_TYPE_TEXT_BUFFER);
g_signal_connect (text_view, "drag-begin",
G_CALLBACK (drag_begin_cb), NULL);
gtk_drag_begin (GTK_WIDGET (text_view),
gdk_event_get_device (event),
formats,
GDK_ACTION_COPY | GDK_ACTION_MOVE,
x, y);
}
static void
gtk_text_view_drag_begin (GtkWidget *widget,
GdkDrag *drag)
{
/* do nothing */
}
static void
gtk_text_view_drag_end (GtkWidget *widget,
GdkDrag *drag)
{
GtkTextView *text_view;
text_view = GTK_TEXT_VIEW (widget);
text_view->priv->dnd_x = text_view->priv->dnd_y = -1;
}
static void
gtk_text_view_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
GtkWidget *widget = GTK_WIDGET (text_view);
GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);
GtkDragSource *source;
GdkContentProvider *content;
GtkTextIter start, end;
GdkDragAction actions;
GdkDevice *device;
if (gtk_selection_data_get_target (selection_data) == g_intern_static_string ("GTK_TEXT_BUFFER_CONTENTS"))
{
gtk_selection_data_set (selection_data,
g_intern_static_string ("GTK_TEXT_BUFFER_CONTENTS"),
8, /* bytes */
(void*)&buffer,
sizeof (buffer));
}
if (text_view->priv->editable)
actions = GDK_ACTION_COPY | GDK_ACTION_MOVE;
else
actions = GDK_ACTION_COPY;
content = gtk_text_buffer_get_selection_content (buffer);
source = gtk_drag_source_new (content, actions);
g_object_unref (content);
if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
{
GtkTextIter start;
GtkTextIter end;
gchar *str = NULL;
if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
{
/* Extract the selected text */
str = gtk_text_iter_get_visible_text (&start, &end);
}
if (str)
{
gtk_selection_data_set_text (selection_data, str, -1);
g_free (str);
}
GdkPaintable *paintable;
paintable = gtk_text_util_create_rich_drag_icon (widget, buffer, &start, &end);
gtk_drag_source_set_icon (source, paintable, 0, 0);
g_object_unref (paintable);
}
}
static void
gtk_text_view_drag_data_delete (GtkWidget *widget,
GdkDrag *drag)
{
gtk_text_buffer_delete_selection (GTK_TEXT_VIEW (widget)->priv->buffer,
TRUE, GTK_TEXT_VIEW (widget)->priv->editable);
g_signal_connect_swapped (source, "drag-data-delete",
G_CALLBACK (gtk_text_view_drag_data_delete), text_view);
g_signal_connect_swapped (source, "drag-end",
G_CALLBACK (drag_end), text_view);
device = gdk_event_get_device (event);
gtk_drag_source_drag_begin (source, widget, device, x, y);
}
static void
@@ -7969,12 +7896,16 @@ gtk_text_view_get_action (GtkWidget *textview,
GdkDrop *drop)
{
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
GtkDragSource *source;
GtkDragSource *source1;
GdkDragAction actions;
actions = gdk_drop_get_actions (drop);
if (source_widget == textview &&
source = drag ? gtk_drag_get_source (drag) : NULL;
source1 = (GtkDragSource*)g_object_get_data (G_OBJECT (textview), "drag-source");
if (source && source == source1 &&
actions & GDK_ACTION_MOVE)
return GDK_ACTION_MOVE;
+68 -62
View File
@@ -64,6 +64,7 @@
#include "gtkwindowgroup.h"
#include "gtknative.h"
#include "gtkpopover.h"
#include "gtkselectionprivate.h"
#include "a11y/gtktreeviewaccessibleprivate.h"
@@ -300,8 +301,8 @@ struct _GtkTreeViewChild
typedef struct _TreeViewDragInfo TreeViewDragInfo;
struct _TreeViewDragInfo
{
GtkDragSource *source;
GdkModifierType start_button_mask;
GdkDragAction source_actions;
guint source_set : 1;
guint dest_set : 1;
@@ -674,15 +675,14 @@ static void gtk_tree_view_forall (GtkContainer *container,
gpointer callback_data);
/* Source side drag signals */
static void gtk_tree_view_drag_begin (GtkWidget *widget,
GdkDrag *drag);
static void gtk_tree_view_drag_end (GtkWidget *widget,
GdkDrag *drag);
static void gtk_tree_view_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_tree_view_drag_data_delete (GtkWidget *widget,
GdkDrag *drag);
static void gtk_tree_view_drag_begin (GtkDragSource *source,
GtkWidget *widget);
static void gtk_tree_view_drag_end (GtkDragSource *source,
GtkWidget *widget);
static GBytes *gtk_tree_view_drag_data_get (const char *mimetype,
gpointer data);
static void gtk_tree_view_drag_data_delete (GtkDragSource *source,
GtkWidget *widget);
/* Target side drag signals */
static void gtk_tree_view_drag_leave (GtkWidget *widget,
@@ -1016,10 +1016,6 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
widget_class->measure = gtk_tree_view_measure;
widget_class->size_allocate = gtk_tree_view_size_allocate;
widget_class->snapshot = gtk_tree_view_snapshot;
widget_class->drag_begin = gtk_tree_view_drag_begin;
widget_class->drag_end = gtk_tree_view_drag_end;
widget_class->drag_data_get = gtk_tree_view_drag_data_get;
widget_class->drag_data_delete = gtk_tree_view_drag_data_delete;
widget_class->drag_leave = gtk_tree_view_drag_leave;
widget_class->drag_motion = gtk_tree_view_drag_motion;
widget_class->drag_drop = gtk_tree_view_drag_drop;
@@ -6622,21 +6618,21 @@ _gtk_tree_view_column_autosize (GtkTreeView *tree_view,
/* Drag-and-drop */
static void
set_source_row (GdkDrag *drag,
set_source_row (GtkDragSource *source,
GtkTreeModel *model,
GtkTreePath *source_row)
{
g_object_set_data_full (G_OBJECT (drag),
g_object_set_data_full (G_OBJECT (source),
I_("gtk-tree-view-source-row"),
source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
(GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
}
static GtkTreePath*
get_source_row (GdkDrag *drag)
get_source_row (GtkDragSource *source)
{
GtkTreeRowReference *ref =
g_object_get_data (G_OBJECT (drag), "gtk-tree-view-source-row");
g_object_get_data (G_OBJECT (source), "gtk-tree-view-source-row");
if (ref)
return gtk_tree_row_reference_get_path (ref);
@@ -6749,6 +6745,8 @@ get_info (GtkTreeView *tree_view)
static void
destroy_info (TreeViewDragInfo *di)
{
g_clear_object (&di->source);
g_slice_free (TreeViewDragInfo, di);
}
@@ -7058,7 +7056,6 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view)
{
GtkWidget *widget = GTK_WIDGET (tree_view);
gdouble start_x, start_y, offset_x, offset_y;
GdkDrag *drag;
TreeViewDragInfo *di;
GtkTreePath *path = NULL;
gint button;
@@ -7115,13 +7112,12 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view)
gtk_gesture_set_state (GTK_GESTURE (tree_view->drag_gesture),
GTK_EVENT_SEQUENCE_CLAIMED);
drag = gtk_drag_begin (widget,
gtk_gesture_get_device (GTK_GESTURE (tree_view->drag_gesture)),
gtk_drag_source_get_target_list (widget),
di->source_actions,
start_x, start_y);
gtk_drag_source_drag_begin (di->source,
widget,
gtk_gesture_get_device (GTK_GESTURE (tree_view->drag_gesture)),
start_x, start_y);
set_source_row (drag, model, path);
set_source_row (di->source, model, path);
out:
if (path)
@@ -7132,8 +7128,8 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view)
static void
gtk_tree_view_drag_begin (GtkWidget *widget,
GdkDrag *drag)
gtk_tree_view_drag_begin (GtkDragSource *source,
GtkWidget *widget)
{
GtkTreeView *tree_view;
GtkTreePath *path = NULL;
@@ -7168,15 +7164,15 @@ gtk_tree_view_drag_begin (GtkWidget *widget,
row_pix = gtk_tree_view_create_row_drag_icon (tree_view, path);
gtk_drag_set_icon_paintable (drag, row_pix, tree_view->press_start_x + 1, 1);
gtk_drag_source_set_icon (source, row_pix, tree_view->press_start_x + 1, 1);
g_object_unref (row_pix);
gtk_tree_path_free (path);
}
static void
gtk_tree_view_drag_end (GtkWidget *widget,
GdkDrag *drag)
gtk_tree_view_drag_end (GtkDragSource *sourc,
GtkWidget *widget)
{
GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
@@ -7185,32 +7181,32 @@ gtk_tree_view_drag_end (GtkWidget *widget,
}
/* Default signal implementations for the drag signals */
static void
gtk_tree_view_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
static GBytes *
gtk_tree_view_drag_data_get (const char *mime_type,
gpointer data)
{
GtkTreeView *tree_view;
GtkTreeView *tree_view = data;
GtkTreeModel *model;
TreeViewDragInfo *di;
GtkTreePath *source_row;
GtkSelectionData sdata = { 0, };
tree_view = GTK_TREE_VIEW (widget);
sdata.target = g_intern_string (mime_type);
model = gtk_tree_view_get_model (tree_view);
if (model == NULL)
return;
return NULL;
di = get_info (GTK_TREE_VIEW (widget));
di = get_info (tree_view);
if (di == NULL)
return;
return NULL;
source_row = get_source_row (drag);
source_row = get_source_row (di->source);
if (source_row == NULL)
return;
return NULL;
/* We can implement the GTK_TREE_MODEL_ROW target generically for
* any model; for DragSource models there are some other targets
@@ -7220,25 +7216,26 @@ gtk_tree_view_drag_data_get (GtkWidget *widget,
if (GTK_IS_TREE_DRAG_SOURCE (model) &&
gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
source_row,
selection_data))
&sdata))
goto done;
/* If drag_data_get does nothing, try providing row data. */
if (gtk_selection_data_get_target (selection_data) == g_intern_static_string ("GTK_TREE_MODEL_ROW"))
if (mime_type == g_intern_static_string ("GTK_TREE_MODEL_ROW"))
{
gtk_tree_set_row_drag_data (selection_data,
model,
source_row);
gtk_tree_set_row_drag_data (&sdata, model, source_row);
}
done:
gtk_tree_path_free (source_row);
return g_bytes_new_take ((gpointer)gtk_selection_data_get_data (&sdata),
gtk_selection_data_get_length (&sdata));
}
static void
gtk_tree_view_drag_data_delete (GtkWidget *widget,
GdkDrag *drag)
gtk_tree_view_drag_data_delete (GtkDragSource *source,
GtkWidget *widget)
{
TreeViewDragInfo *di;
GtkTreeModel *model;
@@ -7256,7 +7253,7 @@ gtk_tree_view_drag_data_delete (GtkWidget *widget,
if (di == NULL)
return;
source_row = get_source_row (drag);
source_row = get_source_row (source);
if (source_row == NULL)
return;
@@ -7265,7 +7262,7 @@ gtk_tree_view_drag_data_delete (GtkWidget *widget,
gtk_tree_path_free (source_row);
set_source_row (drag, NULL, NULL);
set_source_row (source, NULL, NULL);
}
static void
@@ -7419,16 +7416,20 @@ gtk_tree_view_drag_drop (GtkWidget *widget,
}
static GdkDragAction
gtk_tree_view_get_action (GtkWidget *treeview,
gtk_tree_view_get_action (GtkWidget *widget,
GdkDrop *drop)
{
GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
TreeViewDragInfo *di;
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
GtkDragSource *source = drag ? gtk_drag_get_source (drag) : NULL;
GdkDragAction actions;
di = get_info (tree_view);
actions = gdk_drop_get_actions (drop);
if (source_widget == treeview &&
if (di && source && di->source == source &&
actions & GDK_ACTION_MOVE)
return GDK_ACTION_MOVE;
@@ -12915,29 +12916,34 @@ unset_reorderable (GtkTreeView *tree_view)
*
* Turns @tree_view into a drag source for automatic DND. Calling this
* method sets #GtkTreeView:reorderable to %FALSE.
*
* Returns: (transfer none): the #GtkDragSource that has been attached to @tree_view
**/
void
GtkDragSource *
gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view,
GdkModifierType start_button_mask,
GdkContentFormats *formats,
GdkDragAction actions)
{
TreeViewDragInfo *di;
GdkContentProvider *content;
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
gtk_drag_source_set (GTK_WIDGET (tree_view),
0,
formats,
actions);
g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
di = ensure_info (tree_view);
content = gdk_content_provider_new_with_formats (formats, gtk_tree_view_drag_data_get, tree_view);
di->source = gtk_drag_source_new (content, actions);
g_object_unref (content);
g_signal_connect (di->source, "drag-begin", G_CALLBACK (gtk_tree_view_drag_begin), tree_view);
g_signal_connect (di->source, "drag-end", G_CALLBACK (gtk_tree_view_drag_end), tree_view);
g_signal_connect (di->source, "drag-data-delete", G_CALLBACK (gtk_tree_view_drag_data_delete), tree_view);
di->start_button_mask = start_button_mask;
di->source_actions = actions;
di->source_set = TRUE;
unset_reorderable (tree_view);
return di->source;
}
/**
@@ -12991,7 +12997,7 @@ gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
{
if (di->source_set)
{
gtk_drag_source_unset (GTK_WIDGET (tree_view));
g_clear_object (&di->source);
di->source_set = FALSE;
}
+2 -1
View File
@@ -27,6 +27,7 @@
#include <gtk/gtktreeviewcolumn.h>
#include <gtk/gtkdnd.h>
#include <gtk/gtkentry.h>
#include <gtk/gtkdragsource.h>
G_BEGIN_DECLS
@@ -314,7 +315,7 @@ gboolean gtk_tree_view_is_blank_at_pos (GtkTreeView
/* Drag-and-Drop support */
GDK_AVAILABLE_IN_ALL
void gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view,
GtkDragSource * gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view,
GdkModifierType start_button_mask,
GdkContentFormats *formats,
GdkDragAction actions);
-129
View File
@@ -518,13 +518,9 @@ enum {
MNEMONIC_ACTIVATE,
MOVE_FOCUS,
KEYNAV_FAILED,
DRAG_BEGIN,
DRAG_END,
DRAG_DATA_DELETE,
DRAG_LEAVE,
DRAG_MOTION,
DRAG_DROP,
DRAG_DATA_GET,
DRAG_DATA_RECEIVED,
POPUP_MENU,
ACCEL_CLOSURES_CHANGED,
@@ -920,13 +916,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->focus = gtk_widget_real_focus;
klass->move_focus = gtk_widget_real_move_focus;
klass->keynav_failed = gtk_widget_real_keynav_failed;
klass->drag_begin = NULL;
klass->drag_end = NULL;
klass->drag_data_delete = NULL;
klass->drag_leave = NULL;
klass->drag_motion = NULL;
klass->drag_drop = NULL;
klass->drag_data_received = NULL;
klass->can_activate_accel = gtk_widget_real_can_activate_accel;
klass->query_tooltip = gtk_widget_real_query_tooltip;
klass->style_updated = gtk_widget_real_style_updated;
@@ -1684,96 +1673,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
G_TYPE_NONE, 1,
GDK_TYPE_DROP);
/**
* GtkWidget::drag-begin:
* @widget: the object which received the signal
* @context: the drag context
*
* The ::drag-begin signal is emitted on the drag source when a drag is
* started. A typical reason to connect to this signal is to set up a
* custom drag icon with e.g. gtk_drag_source_set_icon_paintable().
*
* Note that some widgets set up a drag icon in the default handler of
* this signal, so you may have to use g_signal_connect_after() to
* override what the default handler did.
*/
widget_signals[DRAG_BEGIN] =
g_signal_new (I_("drag-begin"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetClass, drag_begin),
NULL, NULL,
NULL,
G_TYPE_NONE, 1,
GDK_TYPE_DRAG);
/**
* GtkWidget::drag-end:
* @widget: the object which received the signal
* @context: the drag context
*
* The ::drag-end signal is emitted on the drag source when a drag is
* finished. A typical reason to connect to this signal is to undo
* things done in #GtkWidget::drag-begin.
*/
widget_signals[DRAG_END] =
g_signal_new (I_("drag-end"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetClass, drag_end),
NULL, NULL,
NULL,
G_TYPE_NONE, 1,
GDK_TYPE_DRAG);
/**
* GtkWidget::drag-data-delete:
* @widget: the object which received the signal
* @context: the drag context
*
* The ::drag-data-delete signal is emitted on the drag source when a drag
* with the action %GDK_ACTION_MOVE is successfully completed. The signal
* handler is responsible for deleting the data that has been dropped. What
* "delete" means depends on the context of the drag operation.
*/
widget_signals[DRAG_DATA_DELETE] =
g_signal_new (I_("drag-data-delete"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetClass, drag_data_delete),
NULL, NULL,
NULL,
G_TYPE_NONE, 1,
GDK_TYPE_DRAG);
/**
* GtkWidget::drag-failed:
* @widget: the object which received the signal
* @context: the drag context
* @result: the result of the drag operation
*
* The ::drag-failed signal is emitted on the drag source when a drag has
* failed. The signal handler may hook custom code to handle a failed DnD
* operation based on the type of error, it returns %TRUE is the failure has
* been already handled (not showing the default "drag operation failed"
* animation), otherwise it returns %FALSE.
*
* Returns: %TRUE if the failed drag operation has been already handled.
*/
widget_signals[DRAG_FAILED] =
g_signal_new (I_("drag-failed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetClass, drag_failed),
_gtk_boolean_handled_accumulator, NULL,
_gtk_marshal_BOOLEAN__OBJECT_ENUM,
G_TYPE_BOOLEAN, 2,
GDK_TYPE_DRAG,
GTK_TYPE_DRAG_RESULT);
g_signal_set_va_marshaller (widget_signals[DRAG_FAILED],
G_TYPE_FROM_CLASS (klass),
_gtk_marshal_BOOLEAN__OBJECT_ENUMv);
/**
* GtkWidget::drag-motion:
* @widget: the object which received the signal
@@ -1913,34 +1812,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
G_TYPE_FROM_CLASS (klass),
_gtk_marshal_BOOLEAN__OBJECT_INT_INTv);
/**
* GtkWidget::drag-data-get:
* @widget: the object which received the signal
* @context: the drag context
* @data: the #GtkSelectionData to be filled with the dragged data
* @info: the info that has been registered with the target in the
* #GtkTargetList
*
* The ::drag-data-get signal is emitted on the drag source when the drop
* site requests the data which is dragged. It is the responsibility of
* the signal handler to fill @data with the data in the format which
* is indicated by @info. See gtk_selection_data_set() and
* gtk_selection_data_set_text().
*/
widget_signals[DRAG_DATA_GET] =
g_signal_new (I_("drag-data-get"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetClass, drag_data_get),
NULL, NULL,
_gtk_marshal_VOID__OBJECT_BOXED,
G_TYPE_NONE, 2,
GDK_TYPE_DRAG,
GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE);
g_signal_set_va_marshaller (widget_signals[DRAG_DATA_GET],
G_TYPE_FROM_CLASS (klass),
_gtk_marshal_VOID__OBJECT_BOXEDv);
/**
* GtkWidget::drag-data-received:
* @widget: the object which received the signal
-24
View File
@@ -187,14 +187,6 @@ struct _GtkWidget
* @focus:
* @move_focus: Signal emitted when a change of focus is requested
* @keynav_failed: Signal emitted if keyboard navigation fails.
* @drag_begin: Signal emitted on the drag source when a drag is
* started.
* @drag_end: Signal emitted on the drag source when a drag is
* finished.
* @drag_data_get: Signal emitted on the drag source when the drop
* site requests the data which is dragged.
* @drag_data_delete: Signal emitted on the drag source when a drag
* with the action %GDK_ACTION_MOVE is successfully completed.
* @drag_leave: Signal emitted on the drop site when the cursor leaves
* the widget.
* @drag_motion: signal emitted on the drop site when the user moves
@@ -203,8 +195,6 @@ struct _GtkWidget
* data onto the widget.
* @drag_data_received: Signal emitted on the drop site when the
* dragged data has been received.
* @drag_failed: Signal emitted on the drag source when a drag has
* failed.
* @popup_menu: Signal emitted whenever a widget should pop up a
* context menu.
* @get_accessible: Returns the accessible object that describes the
@@ -276,17 +266,6 @@ struct _GtkWidgetClass
gboolean (* keynav_failed) (GtkWidget *widget,
GtkDirectionType direction);
/* Source side drag signals */
void (* drag_begin) (GtkWidget *widget,
GdkDrag *drag);
void (* drag_end) (GtkWidget *widget,
GdkDrag *drag);
void (* drag_data_get) (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
void (* drag_data_delete) (GtkWidget *widget,
GdkDrag *drag);
/* Target side drag signals */
void (* drag_leave) (GtkWidget *widget,
GdkDrop *drop);
@@ -301,9 +280,6 @@ struct _GtkWidgetClass
void (* drag_data_received) (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data);
gboolean (* drag_failed) (GtkWidget *widget,
GdkDrag *drag,
GtkDragResult result);
/* Signals used only for keybindings */
gboolean (* popup_menu) (GtkWidget *widget);
-2
View File
@@ -158,9 +158,7 @@
</child>
<signal name="drag-data-received" handler="file_list_drag_data_received_cb" swapped="no"/>
<signal name="drag-drop" handler="file_list_drag_drop_cb" swapped="no"/>
<signal name="drag-begin" handler="file_list_drag_begin_cb" swapped="no"/>
<signal name="drag-motion" handler="file_list_drag_motion_cb" swapped="no"/>
<signal name="drag-end" handler="file_list_drag_end_cb" swapped="no"/>
<signal name="popup-menu" handler="list_popup_menu_cb" swapped="no"/>
<signal name="query-tooltip" handler="file_list_query_tooltip_cb" swapped="no"/>
<signal name="row-activated" handler="list_row_activated" swapped="no"/>
-1
View File
@@ -53,7 +53,6 @@ gtk_tests = [
['testiconview-keynav'],
['testicontheme'],
['testinfobar'],
['testimage'],
['testkineticscrolling'],
['testlist'],
['testlist2'],
+11 -32
View File
@@ -313,8 +313,6 @@ target_drag_motion (GtkWidget *widget,
gint x,
gint y)
{
GtkWidget *source_widget;
GdkDrag *drag;
char *s;
if (!have_drag)
@@ -323,12 +321,6 @@ target_drag_motion (GtkWidget *widget,
gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_open);
}
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_drop_get_formats (drop));
g_print ("%s\n", s);
@@ -416,20 +408,6 @@ label_drag_data_received (GtkWidget *widget,
gdk_drop_finish (drop, 0);
}
void
source_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
gpointer data)
{
if (gtk_selection_data_get_target (selection_data) == g_intern_static_string ("application/x-rootwindow-drop"))
g_print ("I was dropped on the rootwin\n");
else
gtk_selection_data_set (selection_data,
gtk_selection_data_get_target (selection_data),
8, (guchar *) "I'm Data!", 9);
}
/* The following is a rather elaborate example demonstrating/testing
* changing of the window hierarchy during a drag - in this case,
* via a "spring-loaded" popup window.
@@ -564,7 +542,6 @@ popsite_leave (GtkWidget *widget,
void
source_drag_data_delete (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
g_print ("Delete the data!\n");
@@ -587,6 +564,9 @@ main (int argc, char **argv)
GtkWidget *button;
GdkPixbuf *drag_icon;
GdkTexture *texture;
GdkContentProvider *content;
GValue value = G_VALUE_INIT;
GtkDragSource *source;
GdkContentFormats *targets;
test_init ();
@@ -661,12 +641,13 @@ main (int argc, char **argv)
button = gtk_button_new_with_label ("Drag Here\n");
targets = gdk_content_formats_new (target_table, n_targets);
gtk_drag_source_set (button, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
targets,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_drag_source_set_icon_paintable (button, GDK_PAINTABLE (texture));
gdk_content_formats_unref (targets);
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, "I'm data!");
content = gdk_content_provider_new_for_value (&value);
g_value_unset (&value);
source = gtk_drag_source_new (content, GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_drag_source_attach (source, button, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK);
gtk_drag_source_set_icon (source, GDK_PAINTABLE (texture), 0, 0);
g_object_unref (texture);
@@ -674,9 +655,7 @@ 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_CALLBACK (source_drag_data_get), NULL);
g_signal_connect (button, "drag-data-delete",
g_signal_connect (source, "drag-data-delete",
G_CALLBACK (source_drag_data_delete), NULL);
gtk_widget_show (window);
+142 -202
View File
@@ -37,114 +37,12 @@ enum {
BOTTOM_RIGHT
};
static void
image_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
GdkPaintable *paintable;
gint hotspot;
gint hot_x, hot_y;
gint size;
paintable = get_image_paintable (GTK_IMAGE (data), &size);
hotspot = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "hotspot"));
switch (hotspot)
{
default:
case TOP_LEFT:
hot_x = 0;
hot_y = 0;
break;
case CENTER:
hot_x = size / 2;
hot_y = size / 2;
break;
case BOTTOM_RIGHT:
hot_x = size;
hot_y = size;
break;
}
gtk_drag_set_icon_paintable (drag, paintable, hot_x, hot_y);
g_object_unref (paintable);
}
static void
drag_widget_destroyed (GtkWidget *image, gpointer data)
{
GtkWidget *widget = data;
g_print ("drag widget destroyed\n");
g_object_unref (image);
g_object_set_data (G_OBJECT (widget), "drag widget", NULL);
}
static void
window_drag_end (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
GtkWidget *window = data;
gtk_widget_destroy (window);
g_signal_handlers_disconnect_by_func (widget, window_drag_end, data);
}
static void
window_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
GdkPaintable *paintable;
GtkWidget *image;
int hotspot;
int size;
hotspot = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "hotspot"));
image = g_object_get_data (G_OBJECT (widget), "drag widget");
if (image == NULL)
{
g_print ("creating new drag widget\n");
paintable = get_image_paintable (GTK_IMAGE (data), &size);
image = gtk_image_new_from_paintable (paintable);
g_object_unref (paintable);
g_object_ref (image);
g_object_set_data (G_OBJECT (widget), "drag widget", image);
g_signal_connect (image, "destroy", G_CALLBACK (drag_widget_destroyed), widget);
}
else
g_print ("reusing drag widget\n");
gtk_drag_set_icon_widget (drag, image, 0, 0);
if (hotspot == CENTER)
g_signal_connect (widget, "drag-end", G_CALLBACK (window_drag_end), image);
}
static void
update_source_target_list (GtkWidget *image)
{
GdkContentFormats *target_list;
target_list = gdk_content_formats_new (NULL, 0);
target_list = gtk_content_formats_add_image_targets (target_list, FALSE);
if (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME)
target_list = gtk_content_formats_add_text_targets (target_list);
gtk_drag_source_set_target_list (image, target_list);
gdk_content_formats_unref (target_list);
}
static void
update_dest_target_list (GtkWidget *image)
{
GdkContentFormats *target_list;
target_list = gdk_content_formats_new (NULL, 0);
target_list = gtk_content_formats_add_image_targets (target_list, FALSE);
target_list = gtk_content_formats_add_text_targets (target_list);
@@ -191,149 +89,191 @@ image_drag_data_received (GtkWidget *widget,
GtkSelectionData *selection_data,
gpointer data)
{
GdkTexture *texture;
gchar *text;
if (gtk_selection_data_get_length (selection_data) == 0)
return;
if (gtk_selection_data_targets_include_image (selection_data, FALSE))
texture = gtk_selection_data_get_texture (selection_data);
if (texture)
{
GdkTexture *texture;
texture = gtk_selection_data_get_texture (selection_data);
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
gtk_image_set_from_paintable (GTK_IMAGE (widget), GDK_PAINTABLE (texture));
g_object_unref (texture);
return;
}
else if (gtk_selection_data_targets_include_text (selection_data))
text = (gchar *)gtk_selection_data_get_text (selection_data);
if (text)
{
text = (gchar *)gtk_selection_data_get_text (selection_data);
gtk_image_set_from_icon_name (GTK_IMAGE (data), text);
gtk_image_set_from_icon_name (GTK_IMAGE (widget), text);
g_free (text);
}
else
{
g_assert_not_reached ();
}
}
static void
update_source_icon (GtkDragSource *source,
const char *icon_name,
int hotspot)
{
GdkPaintable *paintable;
int hot_x, hot_y;
int size = 48;
paintable = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
icon_name, size, 0, NULL);
switch (hotspot)
{
default:
case TOP_LEFT:
hot_x = 0;
hot_y = 0;
break;
case CENTER:
hot_x = size / 2;
hot_y = size / 2;
break;
case BOTTOM_RIGHT:
hot_x = size;
hot_y = size;
break;
}
gtk_drag_source_set_icon (source, paintable, hot_x, hot_y);
g_object_unref (paintable);
}
static GBytes *
get_data (const char *mimetype,
gpointer data)
{
GtkWidget *image = data;
GdkContentFormats *formats;
gboolean want_text;
formats = gdk_content_formats_new (NULL, 0);
formats = gtk_content_formats_add_text_targets (formats);
want_text = gdk_content_formats_contain_mime_type (formats, mimetype);
gdk_content_formats_unref (formats);
g_print ("get data called for %s\n", mimetype);
if (want_text)
{
const char *text = gtk_image_get_icon_name (GTK_IMAGE (image));
return g_bytes_new (text, strlen (text) + 1);
}
else if (strcmp (mimetype, "image/png") == 0)
{
int size;
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (image), &size);
if (GDK_IS_TEXTURE (paintable))
{
char *name = g_strdup ("drag-data-XXXXXX");
int fd;
char *data;
gsize size;
// FIXME: this is horrible
fd = g_mkstemp (name);
close (fd);
gdk_texture_save_to_png (GDK_TEXTURE (paintable), name);
g_file_get_contents (name, &data, &size, NULL);
g_free (name);
return g_bytes_new_take (data, size);
}
g_clear_object (&paintable);
}
return NULL;
}
static void
drag_begin (GtkDragSource *source)
{
g_print ("drag begin\n");
}
static void
drag_end (GtkDragSource *source)
{
g_print ("drag end\n");
}
static gboolean
drag_failed (GtkDragSource *source, GdkDragCancelReason reason)
{
g_print ("drag failed: %d\n", reason);
return FALSE;
}
GtkWidget *
make_image (const gchar *icon_name, int hotspot)
{
GtkWidget *image;
GtkDragSource *source;
GdkContentFormats *formats;
GdkContentProvider *content;
image = gtk_image_new_from_icon_name (icon_name);
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
update_source_target_list (image);
formats = gdk_content_formats_new (NULL, 0);
formats = gtk_content_formats_add_image_targets (formats, FALSE);
formats = gtk_content_formats_add_text_targets (formats);
g_object_set_data (G_OBJECT (image), "hotspot", GINT_TO_POINTER (hotspot));
content = gdk_content_provider_new_with_formats (formats, get_data, image);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_object_unref (content);
gdk_content_formats_unref (formats);
update_source_icon (source, icon_name, hotspot);
g_signal_connect (image, "drag-begin", G_CALLBACK (image_drag_begin), image);
g_signal_connect (image, "drag-data-get", G_CALLBACK (image_drag_data_get), image);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), NULL);
g_signal_connect (source, "drag-end", G_CALLBACK (drag_end), NULL);
g_signal_connect (source, "drag-failed", G_CALLBACK (drag_failed), NULL);
gtk_drag_source_attach (source, image, GDK_BUTTON1_MASK);
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL, NULL, GDK_ACTION_COPY);
g_signal_connect (image, "drag-data-received", G_CALLBACK (image_drag_data_received), image);
update_dest_target_list (image);
return image;
}
GtkWidget *
make_image2 (const gchar *icon_name, int hotspot)
{
GtkWidget *image;
image = gtk_image_new_from_icon_name (icon_name);
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
update_source_target_list (image);
g_object_set_data (G_OBJECT (image), "hotspot", GINT_TO_POINTER (hotspot));
g_signal_connect (image, "drag-begin", G_CALLBACK (window_drag_begin), image);
g_signal_connect (image, "drag-data-get", G_CALLBACK (image_drag_data_get), image);
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL, NULL, GDK_ACTION_COPY);
g_signal_connect (image, "drag-data-received", G_CALLBACK (image_drag_data_received), image);
g_signal_connect (image, "drag-data-received", G_CALLBACK (image_drag_data_received), NULL);
update_dest_target_list (image);
return image;
}
static void
spinner_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
spinner_drag_begin (GtkDragSource *source,
GtkWidget *widget)
{
GtkWidget *spinner;
GdkPaintable *paintable;
g_print ("GtkWidget::drag-begin\n");
spinner = g_object_new (GTK_TYPE_SPINNER,
"visible", TRUE,
"active", TRUE,
NULL);
gtk_drag_set_icon_widget (drag, spinner, 0, 0);
g_object_set_data (G_OBJECT (drag), "spinner", spinner);
}
static void
spinner_drag_end (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
GtkWidget *spinner;
g_print ("GtkWidget::drag-end\n");
spinner = g_object_get_data (G_OBJECT (drag), "spinner");
gtk_widget_destroy (spinner);
}
static gboolean
spinner_drag_failed (GtkWidget *widget,
GdkDrag *drag,
GtkDragResult result,
gpointer data)
{
GTypeClass *class;
GEnumValue *value;
class = g_type_class_ref (GTK_TYPE_DRAG_RESULT);
value = g_enum_get_value (G_ENUM_CLASS (class), result);
g_print ("GtkWidget::drag-failed %s\n", value->value_nick);
g_type_class_unref (class);
return FALSE;
}
void
spinner_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
gpointer data)
{
g_print ("GtkWidget::drag-data-get\n");
gtk_selection_data_set_text (selection_data, "ACTIVE", -1);
paintable = gtk_widget_paintable_new (widget);
gtk_drag_source_set_icon (source, paintable, 0, 0);
g_object_unref (paintable);
}
static GtkWidget *
make_spinner (void)
{
GtkWidget *spinner;
GtkDragSource *source;
GdkContentProvider *content;
GValue value = G_VALUE_INIT;
spinner = gtk_spinner_new ();
gtk_spinner_start (GTK_SPINNER (spinner));
gtk_drag_source_set (spinner, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
gtk_drag_source_add_text_targets (spinner);
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, "ACTIVE");
content = gdk_content_provider_new_for_value (&value);
source = gtk_drag_source_new (content, GDK_ACTION_COPY);
g_signal_connect (source, "drag-begin", G_CALLBACK (spinner_drag_begin), spinner);
gtk_drag_source_attach (source, spinner, GDK_BUTTON1_MASK);
g_signal_connect (spinner, "drag-begin", G_CALLBACK (spinner_drag_begin), spinner);
g_signal_connect (spinner, "drag-end", G_CALLBACK (spinner_drag_end), spinner);
g_signal_connect (spinner, "drag-failed", G_CALLBACK (spinner_drag_failed), spinner);
g_signal_connect (spinner, "drag-data-get", G_CALLBACK (spinner_drag_data_get), spinner);
g_object_unref (content);
g_value_unset (&value);
return spinner;
}
@@ -367,9 +307,9 @@ main (int argc, char *Argv[])
gtk_grid_attach (GTK_GRID (grid), make_spinner (), 0, 2, 1, 1);
gtk_grid_attach (GTK_GRID (grid), make_image ("weather-clear", CENTER), 1, 2, 1, 1);
gtk_grid_attach (GTK_GRID (grid), make_image2 ("dialog-question", TOP_LEFT), 0, 3, 1, 1);
gtk_grid_attach (GTK_GRID (grid), make_image ("dialog-question", TOP_LEFT), 0, 3, 1, 1);
gtk_grid_attach (GTK_GRID (grid), make_image2 ("dialog-information", CENTER), 1, 3, 1, 1);
gtk_grid_attach (GTK_GRID (grid), make_image ("dialog-information", CENTER), 1, 3, 1, 1);
gtk_widget_show (window);
gtk_main ();
+9 -48
View File
@@ -8,45 +8,6 @@ clear_pressed (GtkEntry *entry, gint icon, gpointer data)
gtk_editable_set_text (GTK_EDITABLE (entry), "");
}
static void
drag_begin_cb (GtkWidget *widget,
GdkDrag *drag,
gpointer user_data)
{
gint pos;
pos = gtk_entry_get_current_icon_drag_source (GTK_ENTRY (widget));
if (pos != -1)
gtk_drag_set_icon_name (drag, "dialog-information", 2, 2);
}
static void
drag_data_get_cb (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *data,
gpointer user_data)
{
gint pos;
pos = gtk_entry_get_current_icon_drag_source (GTK_ENTRY (widget));
if (pos == GTK_ENTRY_ICON_PRIMARY)
{
gint start, end;
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), &start, &end))
{
gchar *str;
str = gtk_editable_get_chars (GTK_EDITABLE (widget), start, end);
gtk_selection_data_set_text (data, str, -1);
g_free (str);
}
else
gtk_selection_data_set_text (data, "XXX", -1);
}
}
static void
set_blank (GtkWidget *button,
GtkEntry *entry)
@@ -127,7 +88,8 @@ main (int argc, char **argv)
GtkWidget *button3;
GtkWidget *button4;
GIcon *icon;
GdkContentFormats *tlist;
GdkContentProvider *content;
GValue value = G_VALUE_INIT;
gtk_init ();
@@ -189,16 +151,15 @@ main (int argc, char **argv)
gtk_entry_set_icon_tooltip_text (GTK_ENTRY (entry),
GTK_ENTRY_ICON_PRIMARY,
"Save a file");
tlist = gdk_content_formats_new (NULL, 0);
tlist = gtk_content_formats_add_text_targets (tlist);
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, "Amazing");
content = gdk_content_provider_new_for_value (&value);
g_value_unset (&value);
gtk_entry_set_icon_drag_source (GTK_ENTRY (entry),
GTK_ENTRY_ICON_PRIMARY,
tlist, GDK_ACTION_COPY);
g_signal_connect_after (entry, "drag-begin",
G_CALLBACK (drag_begin_cb), NULL);
g_signal_connect (entry, "drag-data-get",
G_CALLBACK (drag_data_get_cb), NULL);
gdk_content_formats_unref (tlist);
content, GDK_ACTION_COPY);
g_object_unref (content);
/*
* Search - Uses a helper function
-178
View File
@@ -1,178 +0,0 @@
/* testimage.c
* Copyright (C) 2004 Red Hat, Inc.
*
* 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 <gtk/gtk.h>
#include <gio/gio.h>
static void
drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
GtkWidget *image = GTK_WIDGET (data);
GdkPaintable *paintable;
paintable = gtk_image_get_paintable (GTK_IMAGE (image));
gtk_drag_set_icon_paintable (drag, paintable, -2, -2);
}
void
drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
gpointer data)
{
GtkWidget *image = GTK_WIDGET (data);
GdkPaintable *paintable;
paintable = gtk_image_get_paintable (GTK_IMAGE (image));
if (GDK_IS_TEXTURE (paintable))
gtk_selection_data_set_texture (selection_data, GDK_TEXTURE (paintable));
}
static void
drag_data_received (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
guint info,
guint32 time,
gpointer data)
{
GtkWidget *image = GTK_WIDGET (data);
GdkTexture *texture;
if (gtk_selection_data_get_length (selection_data) < 0)
return;
texture = gtk_selection_data_get_texture (selection_data);
gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (texture));
g_object_unref (texture);
}
static gboolean
idle_func (gpointer data)
{
g_print ("keep me busy\n");
return G_SOURCE_CONTINUE;
}
int
main (int argc, char **argv)
{
GtkWidget *window, *grid;
GtkWidget *label, *image;
GtkIconTheme *theme;
GdkPaintable *paintable;
gchar *icon_name = "help-browser";
gchar *anim_filename = NULL;
GtkIconInfo *icon_info;
GIcon *icon;
GFile *file;
gtk_init ();
if (argc > 1)
icon_name = argv[1];
if (argc > 2)
anim_filename = argv[2];
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
gtk_container_add (GTK_CONTAINER (window), grid);
label = gtk_label_new ("symbolic size");
gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
label = gtk_label_new ("fixed size");
gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1);
label = gtk_label_new ("GTK_IMAGE_PIXBUF");
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
theme = gtk_icon_theme_get_default ();
icon_info = gtk_icon_theme_lookup_icon_for_scale (theme, icon_name, 48, gtk_widget_get_scale_factor (window), GTK_ICON_LOOKUP_GENERIC_FALLBACK);
paintable = gtk_icon_info_load_icon (icon_info, NULL);
g_object_unref (icon_info);
image = gtk_image_new_from_paintable (paintable);
g_object_unref (paintable);
gtk_grid_attach (GTK_GRID (grid), image, 2, 1, 1, 1);
gtk_drag_source_set (image, GDK_BUTTON1_MASK,
NULL,
GDK_ACTION_COPY);
gtk_drag_source_add_image_targets (image);
g_signal_connect (image, "drag_begin", G_CALLBACK (drag_begin), image);
g_signal_connect (image, "drag_data_get", G_CALLBACK (drag_data_get), image);
gtk_drag_dest_set (image,
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_DROP,
NULL, GDK_ACTION_COPY);
gtk_drag_dest_add_image_targets (image);
g_signal_connect (image, "drag_data_received",
G_CALLBACK (drag_data_received), image);
label = gtk_label_new ("GTK_IMAGE_ICON_NAME");
gtk_grid_attach (GTK_GRID (grid), label, 0, 4, 1, 1);
image = gtk_image_new_from_icon_name (icon_name);
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_grid_attach (GTK_GRID (grid), image, 1, 4, 1, 1);
image = gtk_image_new_from_icon_name (icon_name);
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_image_set_pixel_size (GTK_IMAGE (image), 30);
gtk_grid_attach (GTK_GRID (grid), image, 2, 4, 1, 1);
label = gtk_label_new ("GTK_IMAGE_GICON");
gtk_grid_attach (GTK_GRID (grid), label, 0, 5, 1, 1);
icon = g_themed_icon_new_with_default_fallbacks ("folder-remote");
image = gtk_image_new_from_gicon (icon);
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
g_object_unref (icon);
gtk_grid_attach (GTK_GRID (grid), image, 1, 5, 1, 1);
file = g_file_new_for_path ("apple-red.png");
icon = g_file_icon_new (file);
image = gtk_image_new_from_gicon (icon);
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
g_object_unref (icon);
gtk_image_set_pixel_size (GTK_IMAGE (image), 30);
gtk_grid_attach (GTK_GRID (grid), image, 2, 5, 1, 1);
if (anim_filename)
{
label = gtk_label_new ("GTK_IMAGE_ANIMATION (from file)");
gtk_grid_attach (GTK_GRID (grid), label, 0, 6, 1, 1);
image = gtk_image_new_from_file (anim_filename);
gtk_image_set_pixel_size (GTK_IMAGE (image), 30);
gtk_grid_attach (GTK_GRID (grid), image, 2, 6, 1, 1);
/* produce high load */
g_idle_add_full (G_PRIORITY_DEFAULT,
idle_func, NULL, NULL);
}
gtk_widget_show (window);
gtk_main ();
return 0;
}
+12 -23
View File
@@ -5,9 +5,8 @@ static const char *entries[] = {
};
static void
drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
drag_begin (GtkDragSource *source,
GtkWidget *widget)
{
GtkWidget *row;
GtkAllocation alloc;
@@ -19,26 +18,11 @@ drag_begin (GtkWidget *widget,
paintable = gtk_widget_paintable_new (row);
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
gtk_drag_set_icon_paintable (drag, paintable, -x, -y);
gtk_drag_source_set_icon (source, paintable, -x, -y);
g_object_unref (paintable);
}
void
drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
gpointer data)
{
gtk_selection_data_set (selection_data,
g_intern_static_string ("GTK_LIST_BOX_ROW"),
32,
(const guchar *)&widget,
sizeof (gpointer));
}
static void
drag_data_received (GtkWidget *widget,
GdkDrop *drop,
@@ -69,7 +53,10 @@ static GtkWidget *
create_row (const gchar *text)
{
GtkWidget *row, *box, *label, *image;
GBytes *bytes;
GdkContentProvider *content;
GdkContentFormats *targets;
GtkDragSource *source;
row = gtk_list_box_row_new ();
image = gtk_image_new_from_icon_name ("open-menu-symbolic");
@@ -81,11 +68,13 @@ create_row (const gchar *text)
gtk_container_add (GTK_CONTAINER (box), label);
gtk_container_add (GTK_CONTAINER (box), image);
targets = gdk_content_formats_new (entries, 1);
bytes = g_bytes_new (&row, sizeof (gpointer));
content = gdk_content_provider_new_for_bytes ("GTK_LIST_BOX_ROW", bytes);
source = gtk_drag_source_new (content, GDK_ACTION_MOVE);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_drag_source_attach (source, image, GDK_BUTTON1_MASK);
gtk_drag_source_set (image, GDK_BUTTON1_MASK, targets, GDK_ACTION_MOVE);
g_signal_connect (image, "drag-begin", G_CALLBACK (drag_begin), NULL);
g_signal_connect (image, "drag-data-get", G_CALLBACK (drag_data_get), NULL);
targets = gdk_content_formats_new (entries, 1);
gtk_drag_dest_set (row, GTK_DEST_DEFAULT_ALL, targets, GDK_ACTION_MOVE);
g_signal_connect (row, "drag-data-received", G_CALLBACK (drag_data_received), NULL);
-21
View File
@@ -90,21 +90,6 @@ on_page_reordered (GtkNotebook *notebook, GtkWidget *child, guint page_num, gpoi
g_print ("page %d reordered\n", page_num);
}
static void
on_notebook_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
guint page_num;
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (widget));
if (page_num > 2)
gtk_drag_set_icon_name (drag,
(page_num % 2) ? "help-browser" : "process-stop",
0, 0);
}
static gboolean
remove_in_idle (gpointer data)
{
@@ -186,8 +171,6 @@ create_notebook (gchar **labels,
g_signal_connect (GTK_NOTEBOOK (notebook), "page-reordered",
G_CALLBACK (on_page_reordered), NULL);
g_signal_connect_after (G_OBJECT (notebook), "drag-begin",
G_CALLBACK (on_notebook_drag_begin), NULL);
return notebook;
}
@@ -233,8 +216,6 @@ create_notebook_non_dragable_content (gchar **labels,
g_signal_connect (GTK_NOTEBOOK (notebook), "page-reordered",
G_CALLBACK (on_page_reordered), NULL);
g_signal_connect_after (G_OBJECT (notebook), "drag-begin",
G_CALLBACK (on_notebook_drag_begin), NULL);
return notebook;
}
@@ -271,8 +252,6 @@ create_notebook_with_notebooks (gchar **labels,
g_signal_connect (GTK_NOTEBOOK (notebook), "page-reordered",
G_CALLBACK (on_page_reordered), NULL);
g_signal_connect_after (G_OBJECT (notebook), "drag-begin",
G_CALLBACK (on_notebook_drag_begin), NULL);
return notebook;
}
+6 -3
View File
@@ -389,6 +389,8 @@ main (gint argc, gchar **argv)
GtkWidget *hbox, *hbox1, *hbox2, *checkbox, *option_menu, *menu;
gint i;
GdkContentFormats *targets;
GdkContentProvider *content;
GtkDragSource *source;
static const gchar *toolbar_styles[] = { "icons", "text", "both (vertical)",
"both (horizontal)" };
GtkToolItem *item;
@@ -616,9 +618,10 @@ main (gint argc, gchar **argv)
gtk_container_add (GTK_CONTAINER (hbox), checkbox);
targets = gdk_content_formats_new (target_table, G_N_ELEMENTS (target_table));
gtk_drag_source_set (button, GDK_BUTTON1_MASK,
targets,
GDK_ACTION_MOVE);
content = gdk_content_provider_new_for_bytes (target_table[0], g_bytes_new ("", 1));
source = gtk_drag_source_new (content, GDK_ACTION_MOVE);
g_object_unref (content);
gtk_drag_source_attach (source, button, GDK_BUTTON1_MASK);
gtk_drag_dest_set (toolbar, GTK_DEST_DEFAULT_DROP,
targets,
GDK_ACTION_MOVE);