gtk/tests/testdnd2.c
Matthias Clasen 7733f646d6 gdk: Rename GdkDragContext to GdkDrag
This is to go along with the newly introduced GdkDrop.

This commit includes the necessary updates to the X11, Wayland
and Broadway backends. Other backends have to be updated separately.
2018-07-02 14:59:26 +02:00

379 lines
11 KiB
C

#include <gtk/gtk.h>
static GdkPaintable *
get_image_paintable (GtkImage *image,
int *out_size)
{
GtkIconTheme *icon_theme;
const char *icon_name;
int width = 48;
GdkPaintable *paintable;
GtkIconInfo *icon_info;
switch (gtk_image_get_storage_type (image))
{
case GTK_IMAGE_PAINTABLE:
paintable = gtk_image_get_paintable (image);
*out_size = gdk_paintable_get_intrinsic_width (paintable);
return g_object_ref (paintable);
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (image);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
*out_size = width;
icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, width, GTK_ICON_LOOKUP_GENERIC_FALLBACK);
paintable = GDK_PAINTABLE (gtk_icon_info_load_texture (icon_info));
g_object_unref (icon_info);
return paintable;
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
return NULL;
}
}
enum {
TOP_LEFT,
CENTER,
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);
gtk_drag_dest_set_target_list (image, target_list);
gdk_content_formats_unref (target_list);
}
void
image_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
gpointer data)
{
GdkPaintable *paintable;
const gchar *name;
int size;
if (gtk_selection_data_targets_include_image (selection_data, TRUE))
{
paintable = get_image_paintable (GTK_IMAGE (data), &size);
if (GDK_IS_TEXTURE (paintable))
gtk_selection_data_set_texture (selection_data, GDK_TEXTURE (paintable));
if (paintable)
g_object_unref (paintable);
}
else if (gtk_selection_data_targets_include_text (selection_data))
{
if (gtk_image_get_storage_type (GTK_IMAGE (data)) == GTK_IMAGE_ICON_NAME)
name = gtk_image_get_icon_name (GTK_IMAGE (data));
else
name = "Boo!";
gtk_selection_data_set_text (selection_data, name, -1);
}
else
{
g_assert_not_reached ();
}
}
static void
image_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data,
gpointer data)
{
gchar *text;
if (gtk_selection_data_get_length (selection_data) == 0)
return;
if (gtk_selection_data_targets_include_image (selection_data, FALSE))
{
GdkTexture *texture;
texture = gtk_selection_data_get_texture (selection_data);
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
g_object_unref (texture);
}
else if (gtk_selection_data_targets_include_text (selection_data))
{
text = (gchar *)gtk_selection_data_get_text (selection_data);
gtk_image_set_from_icon_name (GTK_IMAGE (data), text);
g_free (text);
}
else
{
g_assert_not_reached ();
}
}
GtkWidget *
make_image (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 (image_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);
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);
update_dest_target_list (image);
return image;
}
static void
spinner_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
GtkWidget *spinner;
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);
}
static GtkWidget *
make_spinner (void)
{
GtkWidget *spinner;
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_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);
return spinner;
}
int
main (int argc, char *Argv[])
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *entry;
gtk_init ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Drag And Drop");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
grid = gtk_grid_new ();
g_object_set (grid,
"margin", 20,
"row-spacing", 20,
"column-spacing", 20,
NULL);
gtk_container_add (GTK_CONTAINER (window), grid);
gtk_grid_attach (GTK_GRID (grid), make_image ("dialog-warning", TOP_LEFT), 0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid), make_image ("process-stop", BOTTOM_RIGHT), 1, 0, 1, 1);
entry = gtk_entry_new ();
gtk_grid_attach (GTK_GRID (grid), entry, 0, 1, 2, 1);
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_image2 ("dialog-information", CENTER), 1, 3, 1, 1);
gtk_widget_show (window);
gtk_main ();
return 0;
}