dnd: Allow programmatic drag cancellation

Add a gtk_drag_cancel() function that can be used on the
source side to cancel an ongoing drag operation. This can
be useful, e.g. if the data that is being dragged becomes
unavailable.
This commit is contained in:
Matthias Clasen 2015-01-29 23:49:48 -05:00
parent f2cfe9ed74
commit c160ba0696
3 changed files with 46 additions and 10 deletions

View File

@ -6536,6 +6536,7 @@ gtk_drag_unhighlight
<SUBSECTION Source Side> <SUBSECTION Source Side>
gtk_drag_begin gtk_drag_begin
gtk_drag_begin_with_coordinates gtk_drag_begin_with_coordinates
gtk_drag_cancel
gtk_drag_set_icon_widget gtk_drag_set_icon_widget
gtk_drag_set_icon_pixbuf gtk_drag_set_icon_pixbuf
gtk_drag_set_icon_stock gtk_drag_set_icon_stock

View File

@ -245,7 +245,7 @@ static void gtk_drag_drop (GtkDragSourceInfo *info,
static void gtk_drag_drop_finished (GtkDragSourceInfo *info, static void gtk_drag_drop_finished (GtkDragSourceInfo *info,
GtkDragResult result, GtkDragResult result,
guint time); guint time);
static void gtk_drag_cancel (GtkDragSourceInfo *info, static void gtk_drag_cancel_internal (GtkDragSourceInfo *info,
GtkDragResult result, GtkDragResult result,
guint32 time); guint32 time);
@ -4226,7 +4226,7 @@ gtk_drag_end (GtkDragSourceInfo *info,
* or programmatically. * or programmatically.
*/ */
static void static void
gtk_drag_cancel (GtkDragSourceInfo *info, gtk_drag_cancel_internal (GtkDragSourceInfo *info,
GtkDragResult result, GtkDragResult result,
guint32 time) guint32 time)
{ {
@ -4285,7 +4285,7 @@ gtk_drag_key_cb (GtkWidget *widget,
switch (event->keyval) switch (event->keyval)
{ {
case GDK_KEY_Escape: case GDK_KEY_Escape:
gtk_drag_cancel (info, GTK_DRAG_RESULT_USER_CANCELLED, event->time); gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_USER_CANCELLED, event->time);
return TRUE; return TRUE;
case GDK_KEY_space: case GDK_KEY_space:
@ -4301,7 +4301,7 @@ gtk_drag_key_cb (GtkWidget *widget,
} }
else else
{ {
gtk_drag_cancel (info, GTK_DRAG_RESULT_NO_TARGET, event->time); gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_NO_TARGET, event->time);
} }
return TRUE; return TRUE;
@ -4368,7 +4368,7 @@ gtk_drag_grab_broken_event_cb (GtkWidget *widget,
|| event->grab_window == gtk_widget_get_window (info->ipc_widget)) || event->grab_window == gtk_widget_get_window (info->ipc_widget))
return FALSE; return FALSE;
gtk_drag_cancel (info, GTK_DRAG_RESULT_GRAB_BROKEN, gtk_get_current_event_time ()); gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_GRAB_BROKEN, gtk_get_current_event_time ());
return TRUE; return TRUE;
} }
@ -4385,9 +4385,10 @@ gtk_drag_grab_notify_cb (GtkWidget *widget,
if (gtk_widget_device_is_shadowed (widget, pointer)) if (gtk_widget_device_is_shadowed (widget, pointer))
{ {
/* We have to block callbacks to avoid recursion here, because /* We have to block callbacks to avoid recursion here, because
gtk_drag_cancel calls gtk_grab_remove (via gtk_drag_end) */ * gtk_drag_cancel_internal calls gtk_grab_remove (via gtk_drag_end)
*/
g_signal_handlers_block_by_func (widget, gtk_drag_grab_notify_cb, data); g_signal_handlers_block_by_func (widget, gtk_drag_grab_notify_cb, data);
gtk_drag_cancel (info, GTK_DRAG_RESULT_GRAB_BROKEN, gtk_get_current_event_time ()); gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_GRAB_BROKEN, gtk_get_current_event_time ());
g_signal_handlers_unblock_by_func (widget, gtk_drag_grab_notify_cb, data); g_signal_handlers_unblock_by_func (widget, gtk_drag_grab_notify_cb, data);
} }
} }
@ -4411,7 +4412,7 @@ gtk_drag_button_release_cb (GtkWidget *widget,
} }
else else
{ {
gtk_drag_cancel (info, GTK_DRAG_RESULT_NO_TARGET, event->time); gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_NO_TARGET, event->time);
} }
return TRUE; return TRUE;
@ -4464,3 +4465,34 @@ gtk_drag_check_threshold (GtkWidget *widget,
return (ABS (current_x - start_x) > drag_threshold || return (ABS (current_x - start_x) > drag_threshold ||
ABS (current_y - start_y) > drag_threshold); ABS (current_y - start_y) > drag_threshold);
} }
/**
* gtk_drag_cancel:
* @context: a #GdkDragContext, as e.g. returned by gtk_drag_begin_with_coordinates()
*
* 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_with_coordinates(), 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.
*
* Since: 3.16
*/
void
gtk_drag_cancel (GdkDragContext *context)
{
GtkDragSourceInfo *info;
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
info = gtk_drag_get_source_info (context, FALSE);
if (info != NULL)
gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_ERROR, gtk_get_current_event_time ());
}

View File

@ -203,6 +203,9 @@ GdkDragContext *gtk_drag_begin (GtkWidget *widget,
gint button, gint button,
GdkEvent *event); GdkEvent *event);
GDK_AVAILABLE_IN_3_16
void gtk_drag_cancel (GdkDragContext *context);
/* Set the image being dragged around /* Set the image being dragged around
*/ */
GDK_AVAILABLE_IN_ALL GDK_AVAILABLE_IN_ALL