dnd: Split GtkDragSourceSite into its own file

This commit is contained in:
Benjamin Otte 2015-11-22 05:26:08 +01:00
parent ee3397388f
commit 415030d25f
13 changed files with 551 additions and 849 deletions

View File

@ -168,6 +168,7 @@ gtk_public_h_sources = \
gtkdebug.h \
gtkdialog.h \
gtkdnd.h \
gtkdragsource.h \
gtkdrawingarea.h \
gtkeditable.h \
gtkentry.h \
@ -686,6 +687,7 @@ gtk_base_c_sources = \
gtkcssvalue.c \
gtkcsswidgetnode.c \
gtkdialog.c \
gtkdragsource.c \
gtkdrawingarea.c \
gtkeditable.c \
gtkentry.c \

View File

@ -40,6 +40,7 @@
#include "gtkselection.h"
#include "gtkcolorutils.h"
#include "gtkdnd.h"
#include "gtkdragsource.h"
#include "gtkdrawingarea.h"
#include "gtkframe.h"
#include "gtkgrid.h"

View File

@ -84,6 +84,7 @@
#include <gtk/gtkdebug.h>
#include <gtk/gtkdialog.h>
#include <gtk/gtkdnd.h>
#include <gtk/gtkdragsource.h>
#include <gtk/gtkdrawingarea.h>
#include <gtk/gtkeditable.h>
#include <gtk/gtkentry.h>

View File

@ -37,6 +37,7 @@
#include "gtkcolorchooserdialog.h"
#include "gtkcolorswatchprivate.h"
#include "gtkdnd.h"
#include "gtkdragsource.h"
#include "gtkmarshalers.h"
#include "gtkprivate.h"
#include "gtkintl.h"

View File

@ -30,6 +30,7 @@
#include "gdk/gdk.h"
#include "gtkdnd.h"
#include "gtkdndprivate.h"
#include "deprecated/gtkiconfactory.h"
#include "gtkicontheme.h"
#include "gtkimageprivate.h"
@ -44,7 +45,6 @@
#include "gtksettings.h"
#include "gtkiconhelperprivate.h"
typedef struct _GtkDragSourceSite GtkDragSourceSite;
typedef struct _GtkDragSourceInfo GtkDragSourceInfo;
typedef struct _GtkDragDestSite GtkDragDestSite;
typedef struct _GtkDragDestInfo GtkDragDestInfo;
@ -68,26 +68,6 @@ static void gtk_drag_drop_finished (GtkDragSourceInfo *info,
extern GdkDragContext *gdk_quartz_drag_source_context (); /* gdk/quartz/gdkdnd-quartz.c */
struct _GtkDragSourceSite
{
GdkModifierType start_button_mask;
GtkTargetList *target_list; /* Targets for drag data */
GdkDragAction actions; /* Possible actions */
/* Drag icon */
GtkImageType icon_type;
union
{
GtkImagePixbufData pixbuf;
GtkImageStockData stock;
GtkImageIconNameData name;
} icon_data;
/* Stored button press information to detect drag beginning */
gint state;
gint x, y;
};
struct _GtkDragSourceInfo
{
GtkWidget *source_widget;
@ -1405,373 +1385,6 @@ gtk_drag_cancel (GdkDragContext *context)
gtk_drag_drop_finished (info, GTK_DRAG_RESULT_ERROR);
}
static gboolean
gtk_drag_source_event_cb (GtkWidget *widget,
GdkEvent *event,
gpointer data)
{
GtkDragSourceSite *site;
gboolean retval = FALSE;
site = (GtkDragSourceSite *)data;
switch (event->type)
{
case GDK_BUTTON_PRESS:
if ((GDK_BUTTON1_MASK << (event->button.button - 1)) & site->start_button_mask)
{
site->state |= (GDK_BUTTON1_MASK << (event->button.button - 1));
site->x = event->button.x;
site->y = event->button.y;
}
break;
case GDK_BUTTON_RELEASE:
if ((GDK_BUTTON1_MASK << (event->button.button - 1)) & site->start_button_mask)
site->state &= ~(GDK_BUTTON1_MASK << (event->button.button - 1));
break;
case GDK_MOTION_NOTIFY:
if (site->state & event->motion.state & site->start_button_mask)
{
/* FIXME: This is really broken and can leave us
* with a stuck grab
*/
int i;
for (i=1; i<6; i++)
{
if (site->state & event->motion.state &
GDK_BUTTON1_MASK << (i - 1))
break;
}
if (gtk_drag_check_threshold (widget, site->x, site->y,
event->motion.x, event->motion.y))
{
site->state = 0;
gtk_drag_begin_internal (widget, site, site->target_list,
site->actions, i, event, -1, -1);
retval = TRUE;
}
}
break;
default: /* hit for 2/3BUTTON_PRESS */
break;
}
return retval;
}
/**
* gtk_drag_source_set: (method)
* @widget: a #GtkWidget
* @start_button_mask: the bitmask of buttons that can start the drag
* @targets: (allow-none) (array length=n_targets): the table of targets that the drag will support,
* may be %NULL
* @n_targets: the number of items in @targets
* @actions: the bitmask of possible actions for a drag from this widget
*/
void
gtk_drag_source_set (GtkWidget *widget,
GdkModifierType start_button_mask,
const GtkTargetEntry *targets,
gint n_targets,
GdkDragAction actions)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
gtk_widget_add_events (widget,
gtk_widget_get_events (widget) |
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_BUTTON_MOTION_MASK);
if (site)
{
if (site->target_list)
gtk_target_list_unref (site->target_list);
}
else
{
site = g_new0 (GtkDragSourceSite, 1);
site->icon_type = GTK_IMAGE_EMPTY;
g_signal_connect (widget, "button-press-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_signal_connect (widget, "button-release-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_signal_connect (widget, "motion-notify-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_object_set_data_full (G_OBJECT (widget),
I_("gtk-site-data"),
site, gtk_drag_source_site_destroy);
}
site->start_button_mask = start_button_mask;
site->target_list = gtk_target_list_new (targets, n_targets);
site->actions = actions;
}
/**
* gtk_drag_source_unset: (method)
* @widget: a #GtkWidget
*/
void
gtk_drag_source_unset (GtkWidget *widget)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
if (site)
{
g_signal_handlers_disconnect_by_func (widget,
gtk_drag_source_event_cb,
site);
g_object_set_data (G_OBJECT (widget), I_("gtk-site-data"), NULL);
}
}
/**
* gtk_drag_source_get_target_list: (method)
* @widget: a #GtkWidget
*
* Returns: (transfer none):
*/
GtkTargetList *
gtk_drag_source_get_target_list (GtkWidget *widget)
{
GtkDragSourceSite *site;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
return site ? site->target_list : NULL;
}
/**
* gtk_drag_source_set_target_list: (method)
* @widget: a #GtkWidget thats a drag source
* @target_list: (allow-none): list of draggable targets, or %NULL for none
*/
void
gtk_drag_source_set_target_list (GtkWidget *widget,
GtkTargetList *target_list)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
if (site == NULL)
{
g_warning ("gtk_drag_source_set_target_list() requires the widget "
"to already be a drag source.");
return;
}
if (target_list)
gtk_target_list_ref (target_list);
if (site->target_list)
gtk_target_list_unref (site->target_list);
site->target_list = target_list;
}
/**
* gtk_drag_source_add_text_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the text targets supported by #GtkSelection to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_target_list_add_text_targets() and
* gtk_drag_source_set_target_list().
*
* Since: 2.6
**/
void
gtk_drag_source_add_text_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_text_targets (target_list, 0);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
/**
* gtk_drag_source_add_image_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*/
void
gtk_drag_source_add_image_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_image_targets (target_list, 0, TRUE);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
/**
* gtk_drag_source_add_uri_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*/
void
gtk_drag_source_add_uri_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_uri_targets (target_list, 0);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
static void
gtk_drag_source_unset_icon (GtkDragSourceSite *site)
{
switch (site->icon_type)
{
case GTK_IMAGE_EMPTY:
break;
case GTK_IMAGE_PIXBUF:
g_object_unref (site->icon_data.pixbuf.pixbuf);
break;
case GTK_IMAGE_STOCK:
g_free (site->icon_data.stock.stock_id);
break;
case GTK_IMAGE_ICON_NAME:
g_free (site->icon_data.name.icon_name);
break;
default:
g_assert_not_reached();
break;
}
site->icon_type = GTK_IMAGE_EMPTY;
}
static void
gtk_drag_source_site_destroy (gpointer data)
{
GtkDragSourceSite *site = data;
if (site->target_list)
gtk_target_list_unref (site->target_list);
gtk_drag_source_unset_icon (site);
g_free (site);
}
/**
* gtk_drag_source_set_icon_pixbuf: (method)
* @widget: a #GtkWidget
* @pixbuf: the #GdkPixbuf for the drag icon
*/
void
gtk_drag_source_set_icon_pixbuf (GtkWidget *widget,
GdkPixbuf *pixbuf)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
g_object_ref (pixbuf);
gtk_drag_source_unset_icon (site);
site->icon_type = GTK_IMAGE_PIXBUF;
site->icon_data.pixbuf.pixbuf = pixbuf;
}
/**
* gtk_drag_source_set_icon_stock: (method)
* @widget: a #GtkWidget
* @stock_id: the ID of the stock icon to use
*
* Sets the icon that will be used for drags from a particular source
* to a stock icon.
**/
void
gtk_drag_source_set_icon_stock (GtkWidget *widget,
const gchar *stock_id)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (stock_id != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
gtk_drag_source_unset_icon (site);
site->icon_type = GTK_IMAGE_STOCK;
site->icon_data.stock.stock_id = g_strdup (stock_id);
}
/**
* gtk_drag_source_set_icon_name: (method)
* @widget: a #GtkWidget
* @icon_name: name of icon to use
*
* Sets the icon that will be used for drags from a particular source
* to a themed icon. See the docs for #GtkIconTheme for more details.
*
* Since: 2.8
**/
void
gtk_drag_source_set_icon_name (GtkWidget *widget,
const gchar *icon_name)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (icon_name != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
gtk_drag_source_unset_icon (site);
site->icon_type = GTK_IMAGE_ICON_NAME;
site->icon_data.name.icon_name = g_strdup (icon_name);
}
/**
* gtk_drag_set_icon_widget: (method)

View File

@ -76,7 +76,6 @@
static GSList *source_widgets = NULL;
typedef struct _GtkDragSourceSite GtkDragSourceSite;
typedef struct _GtkDragSourceInfo GtkDragSourceInfo;
typedef struct _GtkDragDestSite GtkDragDestSite;
typedef struct _GtkDragDestInfo GtkDragDestInfo;
@ -90,16 +89,6 @@ typedef enum
GTK_DRAG_STATUS_DROP
} GtkDragStatus;
struct _GtkDragSourceSite
{
GdkModifierType start_button_mask;
GtkTargetList *target_list; /* Targets for drag data */
GdkDragAction actions; /* Possible actions */
GtkIconHelper *icon_helper;
GtkGesture *drag_gesture;
};
struct _GtkDragSourceInfo
{
GtkWidget *widget;
@ -252,13 +241,6 @@ static void gtk_drag_cancel_internal (GtkDragSourceInfo *info,
GtkDragResult result,
guint32 time);
static void gtk_drag_source_gesture_begin (GtkGesture *gesture,
GdkEventSequence *sequence,
gpointer data);
static gboolean gtk_drag_source_event_cb (GtkWidget *widget,
GdkEvent *event,
gpointer data);
static void gtk_drag_source_site_destroy (gpointer data);
static void gtk_drag_selection_get (GtkWidget *widget,
GtkSelectionData *selection_data,
guint sel_info,
@ -2354,7 +2336,7 @@ gtk_drag_dest_drop (GtkWidget *widget,
/* Like gtk_drag_begin(), but also takes a GtkIconHelper
* so that we can set the icon from the source site information
*/
static GdkDragContext *
GdkDragContext *
gtk_drag_begin_internal (GtkWidget *widget,
GtkIconHelper *icon_helper,
GtkTargetList *target_list,
@ -2658,338 +2640,6 @@ gtk_drag_begin (GtkWidget *widget,
actions, button, event, -1, -1);
}
/**
* gtk_drag_source_set: (method)
* @widget: a #GtkWidget
* @start_button_mask: the bitmask of buttons that can start the drag
* @targets: (allow-none) (array length=n_targets): the table of targets
* that the drag will support, may be %NULL
* @n_targets: the number of items in @targets
* @actions: the bitmask of possible actions for a drag from this widget
*
* Sets up a widget so that GTK+ will start a drag operation when the user
* clicks and drags on the widget. The widget must have a window.
*/
void
gtk_drag_source_set (GtkWidget *widget,
GdkModifierType start_button_mask,
const GtkTargetEntry *targets,
gint n_targets,
GdkDragAction actions)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
gtk_widget_add_events (widget,
gtk_widget_get_events (widget) |
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_BUTTON_MOTION_MASK);
if (site)
{
if (site->target_list)
gtk_target_list_unref (site->target_list);
}
else
{
site = g_slice_new0 (GtkDragSourceSite);
site->icon_helper = _gtk_icon_helper_new ();
site->drag_gesture = gtk_gesture_drag_new (widget);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (site->drag_gesture),
GTK_PHASE_NONE);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (site->drag_gesture), 0);
g_signal_connect (site->drag_gesture, "begin",
G_CALLBACK (gtk_drag_source_gesture_begin),
site);
g_signal_connect (widget, "button-press-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_signal_connect (widget, "button-release-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_signal_connect (widget, "motion-notify-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_object_set_data_full (G_OBJECT (widget),
I_("gtk-site-data"),
site, gtk_drag_source_site_destroy);
}
site->start_button_mask = start_button_mask;
site->target_list = gtk_target_list_new (targets, n_targets);
site->actions = actions;
}
/**
* gtk_drag_source_unset: (method)
* @widget: a #GtkWidget
*
* Undoes the effects of gtk_drag_source_set().
*/
void
gtk_drag_source_unset (GtkWidget *widget)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
if (site)
{
g_signal_handlers_disconnect_by_func (widget,
gtk_drag_source_event_cb,
site);
g_object_set_data (G_OBJECT (widget), I_("gtk-site-data"), NULL);
}
}
/**
* gtk_drag_source_get_target_list: (method)
* @widget: a #GtkWidget
*
* Gets the list of targets this widget can provide for
* drag-and-drop.
*
* Returns: (transfer none): the #GtkTargetList, or %NULL if none
*
* Since: 2.4
*/
GtkTargetList *
gtk_drag_source_get_target_list (GtkWidget *widget)
{
GtkDragSourceSite *site;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
return site ? site->target_list : NULL;
}
/**
* gtk_drag_source_set_target_list: (method)
* @widget: a #GtkWidget thats a drag source
* @target_list: (allow-none): list of draggable targets, or %NULL for none
*
* Changes the target types that this widget offers for drag-and-drop.
* The widget must first be made into a drag source with
* gtk_drag_source_set().
*
* Since: 2.4
*/
void
gtk_drag_source_set_target_list (GtkWidget *widget,
GtkTargetList *target_list)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
if (site == NULL)
{
g_warning ("gtk_drag_source_set_target_list() requires the widget "
"to already be a drag source.");
return;
}
if (target_list)
gtk_target_list_ref (target_list);
if (site->target_list)
gtk_target_list_unref (site->target_list);
site->target_list = target_list;
}
/**
* gtk_drag_source_add_text_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the text targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_target_list_add_text_targets() and
* gtk_drag_source_set_target_list().
*
* Since: 2.6
*/
void
gtk_drag_source_add_text_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_text_targets (target_list, 0);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
/**
* gtk_drag_source_add_image_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the writable image targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_target_list_add_image_targets() and
* gtk_drag_source_set_target_list().
*
* Since: 2.6
*/
void
gtk_drag_source_add_image_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_image_targets (target_list, 0, TRUE);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
/**
* gtk_drag_source_add_uri_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the URI targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_target_list_add_uri_targets() and
* gtk_drag_source_set_target_list().
*
* Since: 2.6
*/
void
gtk_drag_source_add_uri_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_uri_targets (target_list, 0);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
/**
* gtk_drag_source_set_icon_pixbuf: (method)
* @widget: a #GtkWidget
* @pixbuf: the #GdkPixbuf for the drag icon
*
* Sets the icon that will be used for drags from a particular widget
* from a #GdkPixbuf. GTK+ retains a reference for @pixbuf and will
* release it when it is no longer needed.
*/
void
gtk_drag_source_set_icon_pixbuf (GtkWidget *widget,
GdkPixbuf *pixbuf)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
g_object_ref (pixbuf);
_gtk_icon_helper_set_pixbuf (site->icon_helper, pixbuf);
}
/**
* gtk_drag_source_set_icon_stock: (method)
* @widget: a #GtkWidget
* @stock_id: the ID of the stock icon to use
*
* Sets the icon that will be used for drags from a particular source
* to a stock icon.
*
* Deprecated: 3.10: Use gtk_drag_source_set_icon_name() instead.
*/
void
gtk_drag_source_set_icon_stock (GtkWidget *widget,
const gchar *stock_id)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (stock_id != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
_gtk_icon_helper_set_stock_id (site->icon_helper, stock_id, GTK_ICON_SIZE_DND);
}
/**
* gtk_drag_source_set_icon_name: (method)
* @widget: a #GtkWidget
* @icon_name: name of icon to use
*
* Sets the icon that will be used for drags from a particular source
* to a themed icon. See the docs for #GtkIconTheme for more details.
*
* Since: 2.8
*/
void
gtk_drag_source_set_icon_name (GtkWidget *widget,
const gchar *icon_name)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (icon_name != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
_gtk_icon_helper_set_icon_name (site->icon_helper, icon_name, GTK_ICON_SIZE_DND);
}
/**
* gtk_drag_source_set_icon_gicon: (method)
* @widget: a #GtkWidget
* @icon: A #GIcon
*
* Sets the icon that will be used for drags from a particular source
* to @icon. See the docs for #GtkIconTheme for more details.
*
* Since: 3.2
*/
void
gtk_drag_source_set_icon_gicon (GtkWidget *widget,
GIcon *icon)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (icon != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
_gtk_icon_helper_set_gicon (site->icon_helper, icon, GTK_ICON_SIZE_DND);
}
static void
gtk_drag_update_icon (GtkDragSourceInfo *info)
{
@ -3730,76 +3380,6 @@ gtk_drag_drop (GtkDragSourceInfo *info,
/*
* Source side callbacks.
*/
static void
gtk_drag_source_gesture_begin (GtkGesture *gesture,
GdkEventSequence *sequence,
gpointer data)
{
GtkDragSourceSite *site = data;
guint button;
if (gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture)))
button = 1;
else
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
if (!site->start_button_mask ||
!(site->start_button_mask & (GDK_BUTTON1_MASK << (button - 1))))
gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED);
}
static gboolean
gtk_drag_source_event_cb (GtkWidget *widget,
GdkEvent *event,
gpointer data)
{
gdouble start_x, start_y, offset_x, offset_y;
GtkDragSourceSite *site = data;
gtk_event_controller_handle_event (GTK_EVENT_CONTROLLER (site->drag_gesture), event);
if (gtk_gesture_is_recognized (site->drag_gesture))
{
gtk_gesture_drag_get_start_point (GTK_GESTURE_DRAG (site->drag_gesture),
&start_x, &start_y);
gtk_gesture_drag_get_offset (GTK_GESTURE_DRAG (site->drag_gesture),
&offset_x, &offset_y);
if (gtk_drag_check_threshold (widget, start_x, start_y,
start_x + offset_x, start_y + offset_y))
{
GdkEventSequence *sequence;
const GdkEvent *last_event;
guint button;
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (site->drag_gesture));
last_event = gtk_gesture_get_last_event (site->drag_gesture, sequence);
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (site->drag_gesture));
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (site->drag_gesture));
gtk_drag_begin_internal (widget, site->icon_helper, site->target_list,
site->actions, button, last_event,
start_x, start_y);
return TRUE;
}
}
return FALSE;
}
static void
gtk_drag_source_site_destroy (gpointer data)
{
GtkDragSourceSite *site = data;
if (site->target_list)
gtk_target_list_unref (site->target_list);
g_clear_object (&site->icon_helper);
g_clear_object (&site->drag_gesture);
g_slice_free (GtkDragSourceSite, site);
}
static void
gtk_drag_selection_get (GtkWidget *widget,
GtkSelectionData *selection_data,

View File

@ -148,41 +148,6 @@ gboolean gtk_drag_dest_get_track_motion (GtkWidget *widget);
/* Source side */
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set (GtkWidget *widget,
GdkModifierType start_button_mask,
const GtkTargetEntry *targets,
gint n_targets,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_unset (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
GtkTargetList* gtk_drag_source_get_target_list (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_target_list (GtkWidget *widget,
GtkTargetList *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);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_pixbuf (GtkWidget *widget,
GdkPixbuf *pixbuf);
GDK_DEPRECATED_IN_3_10_FOR(gtk_drag_source_set_icon_name)
void gtk_drag_source_set_icon_stock (GtkWidget *widget,
const gchar *stock_id);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_name (GtkWidget *widget,
const gchar *icon_name);
GDK_AVAILABLE_IN_3_2
void gtk_drag_source_set_icon_gicon (GtkWidget *widget,
GIcon *icon);
GDK_AVAILABLE_IN_3_10
GdkDragContext *gtk_drag_begin_with_coordinates (GtkWidget *widget,
GtkTargetList *targets,

View File

@ -23,13 +23,22 @@
#include <gtk/gtkwidget.h>
#include <gtk/gtkselection.h>
#include "gtkiconhelperprivate.h"
G_BEGIN_DECLS
void _gtk_drag_source_handle_event (GtkWidget *widget,
GdkEvent *event);
void _gtk_drag_dest_handle_event (GtkWidget *toplevel,
GdkEvent *event);
GdkDragContext * gtk_drag_begin_internal (GtkWidget *widget,
GtkIconHelper *icon_helper,
GtkTargetList *target_list,
GdkDragAction actions,
gint button,
const GdkEvent *event,
int x,
int y);
void _gtk_drag_source_handle_event (GtkWidget *widget,
GdkEvent *event);
void _gtk_drag_dest_handle_event (GtkWidget *toplevel,
GdkEvent *event);
G_END_DECLS

449
gtk/gtkdragsource.c Normal file
View File

@ -0,0 +1,449 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include "gtkdragsource.h"
#include "gtkdnd.h"
#include "gtkdndprivate.h"
#include "gtkgesturedrag.h"
#include "gtkiconhelperprivate.h"
#include "gtkintl.h"
typedef struct _GtkDragSourceSite GtkDragSourceSite;
struct _GtkDragSourceSite
{
GdkModifierType start_button_mask;
GtkTargetList *target_list; /* Targets for drag data */
GdkDragAction actions; /* Possible actions */
GtkIconHelper *icon_helper;
GtkGesture *drag_gesture;
};
static void
gtk_drag_source_gesture_begin (GtkGesture *gesture,
GdkEventSequence *sequence,
gpointer data)
{
GtkDragSourceSite *site = data;
guint button;
if (gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture)))
button = 1;
else
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
if (!site->start_button_mask ||
!(site->start_button_mask & (GDK_BUTTON1_MASK << (button - 1))))
gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED);
}
static gboolean
gtk_drag_source_event_cb (GtkWidget *widget,
GdkEvent *event,
gpointer data)
{
gdouble start_x, start_y, offset_x, offset_y;
GtkDragSourceSite *site = data;
gtk_event_controller_handle_event (GTK_EVENT_CONTROLLER (site->drag_gesture), event);
if (gtk_gesture_is_recognized (site->drag_gesture))
{
gtk_gesture_drag_get_start_point (GTK_GESTURE_DRAG (site->drag_gesture),
&start_x, &start_y);
gtk_gesture_drag_get_offset (GTK_GESTURE_DRAG (site->drag_gesture),
&offset_x, &offset_y);
if (gtk_drag_check_threshold (widget, start_x, start_y,
start_x + offset_x, start_y + offset_y))
{
GdkEventSequence *sequence;
const GdkEvent *last_event;
guint button;
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (site->drag_gesture));
last_event = gtk_gesture_get_last_event (site->drag_gesture, sequence);
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (site->drag_gesture));
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (site->drag_gesture));
gtk_drag_begin_internal (widget, site->icon_helper, site->target_list,
site->actions, button, last_event,
start_x, start_y);
return TRUE;
}
}
return FALSE;
}
static void
gtk_drag_source_site_destroy (gpointer data)
{
GtkDragSourceSite *site = data;
if (site->target_list)
gtk_target_list_unref (site->target_list);
g_clear_object (&site->icon_helper);
g_clear_object (&site->drag_gesture);
g_slice_free (GtkDragSourceSite, site);
}
/**
* gtk_drag_source_set: (method)
* @widget: a #GtkWidget
* @start_button_mask: the bitmask of buttons that can start the drag
* @targets: (allow-none) (array length=n_targets): the table of targets
* that the drag will support, may be %NULL
* @n_targets: the number of items in @targets
* @actions: the bitmask of possible actions for a drag from this widget
*
* Sets up a widget so that GTK+ will start a drag operation when the user
* clicks and drags on the widget. The widget must have a window.
*/
void
gtk_drag_source_set (GtkWidget *widget,
GdkModifierType start_button_mask,
const GtkTargetEntry *targets,
gint n_targets,
GdkDragAction actions)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
gtk_widget_add_events (widget,
gtk_widget_get_events (widget) |
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_BUTTON_MOTION_MASK);
if (site)
{
if (site->target_list)
gtk_target_list_unref (site->target_list);
}
else
{
site = g_slice_new0 (GtkDragSourceSite);
site->icon_helper = _gtk_icon_helper_new ();
site->drag_gesture = gtk_gesture_drag_new (widget);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (site->drag_gesture),
GTK_PHASE_NONE);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (site->drag_gesture), 0);
g_signal_connect (site->drag_gesture, "begin",
G_CALLBACK (gtk_drag_source_gesture_begin),
site);
g_signal_connect (widget, "button-press-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_signal_connect (widget, "button-release-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_signal_connect (widget, "motion-notify-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
g_object_set_data_full (G_OBJECT (widget),
I_("gtk-site-data"),
site, gtk_drag_source_site_destroy);
}
site->start_button_mask = start_button_mask;
site->target_list = gtk_target_list_new (targets, n_targets);
site->actions = actions;
}
/**
* gtk_drag_source_unset: (method)
* @widget: a #GtkWidget
*
* Undoes the effects of gtk_drag_source_set().
*/
void
gtk_drag_source_unset (GtkWidget *widget)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
if (site)
{
g_signal_handlers_disconnect_by_func (widget,
gtk_drag_source_event_cb,
site);
g_object_set_data (G_OBJECT (widget), I_("gtk-site-data"), NULL);
}
}
/**
* gtk_drag_source_get_target_list: (method)
* @widget: a #GtkWidget
*
* Gets the list of targets this widget can provide for
* drag-and-drop.
*
* Returns: (transfer none): the #GtkTargetList, or %NULL if none
*
* Since: 2.4
*/
GtkTargetList *
gtk_drag_source_get_target_list (GtkWidget *widget)
{
GtkDragSourceSite *site;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
return site ? site->target_list : NULL;
}
/**
* gtk_drag_source_set_target_list: (method)
* @widget: a #GtkWidget thats a drag source
* @target_list: (allow-none): list of draggable targets, or %NULL for none
*
* Changes the target types that this widget offers for drag-and-drop.
* The widget must first be made into a drag source with
* gtk_drag_source_set().
*
* Since: 2.4
*/
void
gtk_drag_source_set_target_list (GtkWidget *widget,
GtkTargetList *target_list)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
if (site == NULL)
{
g_warning ("gtk_drag_source_set_target_list() requires the widget "
"to already be a drag source.");
return;
}
if (target_list)
gtk_target_list_ref (target_list);
if (site->target_list)
gtk_target_list_unref (site->target_list);
site->target_list = target_list;
}
/**
* gtk_drag_source_add_text_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the text targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_target_list_add_text_targets() and
* gtk_drag_source_set_target_list().
*
* Since: 2.6
*/
void
gtk_drag_source_add_text_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_text_targets (target_list, 0);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
/**
* gtk_drag_source_add_image_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the writable image targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_target_list_add_image_targets() and
* gtk_drag_source_set_target_list().
*
* Since: 2.6
*/
void
gtk_drag_source_add_image_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_image_targets (target_list, 0, TRUE);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
/**
* gtk_drag_source_add_uri_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the URI targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_target_list_add_uri_targets() and
* gtk_drag_source_set_target_list().
*
* Since: 2.6
*/
void
gtk_drag_source_add_uri_targets (GtkWidget *widget)
{
GtkTargetList *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gtk_target_list_ref (target_list);
else
target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_uri_targets (target_list, 0);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
/**
* gtk_drag_source_set_icon_pixbuf: (method)
* @widget: a #GtkWidget
* @pixbuf: the #GdkPixbuf for the drag icon
*
* Sets the icon that will be used for drags from a particular widget
* from a #GdkPixbuf. GTK+ retains a reference for @pixbuf and will
* release it when it is no longer needed.
*/
void
gtk_drag_source_set_icon_pixbuf (GtkWidget *widget,
GdkPixbuf *pixbuf)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
g_object_ref (pixbuf);
_gtk_icon_helper_set_pixbuf (site->icon_helper, pixbuf);
}
/**
* gtk_drag_source_set_icon_stock: (method)
* @widget: a #GtkWidget
* @stock_id: the ID of the stock icon to use
*
* Sets the icon that will be used for drags from a particular source
* to a stock icon.
*
* Deprecated: 3.10: Use gtk_drag_source_set_icon_name() instead.
*/
void
gtk_drag_source_set_icon_stock (GtkWidget *widget,
const gchar *stock_id)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (stock_id != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
_gtk_icon_helper_set_stock_id (site->icon_helper, stock_id, GTK_ICON_SIZE_DND);
}
/**
* gtk_drag_source_set_icon_name: (method)
* @widget: a #GtkWidget
* @icon_name: name of icon to use
*
* Sets the icon that will be used for drags from a particular source
* to a themed icon. See the docs for #GtkIconTheme for more details.
*
* Since: 2.8
*/
void
gtk_drag_source_set_icon_name (GtkWidget *widget,
const gchar *icon_name)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (icon_name != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
_gtk_icon_helper_set_icon_name (site->icon_helper, icon_name, GTK_ICON_SIZE_DND);
}
/**
* gtk_drag_source_set_icon_gicon: (method)
* @widget: a #GtkWidget
* @icon: A #GIcon
*
* Sets the icon that will be used for drags from a particular source
* to @icon. See the docs for #GtkIconTheme for more details.
*
* Since: 3.2
*/
void
gtk_drag_source_set_icon_gicon (GtkWidget *widget,
GIcon *icon)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (icon != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
_gtk_icon_helper_set_gicon (site->icon_helper, icon, GTK_ICON_SIZE_DND);
}

78
gtk/gtkdragsource.h Normal file
View File

@ -0,0 +1,78 @@
/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_DRAG_SOURCE_H__
#define __GTK_DRAG_SOURCE_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkselection.h>
#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set (GtkWidget *widget,
GdkModifierType start_button_mask,
const GtkTargetEntry *targets,
gint n_targets,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_unset (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
GtkTargetList* gtk_drag_source_get_target_list (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_target_list (GtkWidget *widget,
GtkTargetList *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);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_pixbuf (GtkWidget *widget,
GdkPixbuf *pixbuf);
GDK_DEPRECATED_IN_3_10_FOR(gtk_drag_source_set_icon_name)
void gtk_drag_source_set_icon_stock (GtkWidget *widget,
const gchar *stock_id);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_name (GtkWidget *widget,
const gchar *icon_name);
GDK_AVAILABLE_IN_3_2
void gtk_drag_source_set_icon_gicon (GtkWidget *widget,
GIcon *icon);
G_END_DECLS
#endif /* __GTK_DRAG_SOURCE_H__ */

View File

@ -30,8 +30,8 @@
#include "gtkcheckmenuitem.h"
#include "gtkclipboard.h"
#include "gtkcomboboxtext.h"
#include "gtkdragsource.h"
#include "gtkentry.h"
#include "gtkstack.h"
#include "gtkexpander.h"
#include "gtkfilechooserprivate.h"
#include "gtkfilechooserdialog.h"
@ -59,6 +59,7 @@
#include "gtksettings.h"
#include "gtksizegroup.h"
#include "gtksizerequest.h"
#include "gtkstack.h"
#include "gtktooltip.h"
#include "gtktreednd.h"
#include "gtktreeprivate.h"

View File

@ -24,6 +24,7 @@
#include "gtkbox.h"
#include "gtkdnd.h"
#include "gtkdragsource.h"
#include "gtkicontheme.h"
#include "gtkimage.h"
#include "gtkintl.h"

View File

@ -38,6 +38,7 @@
#include "gtkcheckmenuitem.h"
#include "gtkclipboard.h"
#include "gtkcomboboxtext.h"
#include "gtkdragsource.h"
#include "gtkentry.h"
#include "gtkeventbox.h"
#include "gtkexpander.h"