Merge branch 'dnd-fixes' into 'master'

dnd: Add another assertion

See merge request GNOME/gtk!3689
This commit is contained in:
Matthias Clasen 2021-06-24 15:01:29 +00:00
commit 6a29b64850
7 changed files with 67 additions and 7 deletions

View File

@ -1,7 +1,7 @@
/* Peg Solitaire
* #Keywords: GtkGridView, game
*
* This demo demonstrates how to use drag'n'drop to implement peg solitaire.
* This demo demonstrates how to use drag-and-drop to implement peg solitaire.
*
*/
@ -98,7 +98,7 @@ solitaire_peg_init (SolitairePeg *peg)
/* Add a little setter for the peg's position.
* We want to track those so that we can check for legal moves
* during drag'n'drop operations.
* during drag-and-drop operations.
*/
static void
solitaire_peg_set_position (SolitairePeg *peg,

View File

@ -0,0 +1,54 @@
Title: Drag-and-Drop in GTK
Drag-and-Drop (DND) is a user interaction pattern where users drag a UI element
from one place to another, either inside a single application or between
different application windows.
When the element is 'dropped', data is transferred from the source to the
destination, according to the drag action that is negotiated between both
sides. Most commonly, that is a _copy_, but it can also be a _move_ or a
_link_, depending on the kind of data and how the drag operation has been
set up.
This chapter gives an overview over how Drag-and-Drop is handled with event
controllers in GTK.
## Drag sources
To make data available via DND, you create a [class@Gtk.DragSource]. Drag sources
are event controllers, which initiate a Drag-and-Drop operation when the user clicks
and drags the widget.
A drag source can be set up ahead of time, with the desired drag action(s) and the data
to be transferred. But it is also possible to provide the data when a drag operation
is about to begin, by connecting to the [signal@Gtk.DragSource::prepare] signal.
The GtkDragSource emits the [signal@Gtk.DragSource::drag-begin] signal when the DND
operation starts, and the [signal@Gtk.DragSource::drag-end] signal when it is done.
But it is not normally necessary to handle these signals. One case in which a ::drag-end
handler is necessary is to implement `GDK_ACTION_MOVE`.
## Drop targets
To receive data via DND, you create a [class@Gtk.DropTarget], and tell it what kind of
data to accept. You need to connect to the [signal@Gtk.DropTarget::drop] signal to receive
the data when a DND operation occurs.
While a DND operation is ongoing, GTK provides updates when the pointer moves over
the widget to which the drop target is associated. The [signal@Gtk.DropTarget::enter],
[signal@Gtk.DropTarget::leave] and [signal@Gtk.DropTarget::motion] signals get emitted
for this purpose.
GtkDropTarget provides a simple API, and only provides the data when it has been completely
transferred. If you need to handle the data transfer yourself (for example to provide progress
information during the transfer), you can use the more complicated [class@Gtk.DropTargetAsync].
## Other considerations
It is sometimes necessary to update the UI of the destination while a DND operation is ongoing,
say to scroll or expand a view, or to switch pages. Typically, such UI changes are triggered
by hovering over the widget in question.
[class@Gtk.DropControllerMotion] is an event controller that can help with implementing such
behaviors. It is very similar to [class@Gtk.EventControllerMotion], but provides events during
a DND operation.

View File

@ -57,6 +57,7 @@ content_files = [
"initialization.md",
"actions.md",
"input-handling.md",
"drag-and-drop.md",
"drawing-model.md",
"css-overview.md",
"css-properties.md",

View File

@ -294,8 +294,11 @@ gdk_drop_finalize (GObject *object)
/* someone forgot to send a LEAVE signal */
g_warn_if_fail (!priv->entered);
/* Should we emit finish() here if necessary?
* For now that's the backends' job */
* For now that's the backends' job
*/
g_warn_if_fail (priv->state != GDK_DROP_STATE_DROPPING);
g_clear_object (&priv->device);
g_clear_object (&priv->drag);
@ -571,7 +574,7 @@ gdk_drop_get_drag (GdkDrop *self)
* the ones provided by [method@Gdk.Drop.get_actions]. Those actions may
* change in the future, even depending on the actions you provide here.
*
* The @preferred action is a hint to the drag'n'drop mechanism about which
* The @preferred action is a hint to the drag-and-drop mechanism about which
* action to use when multiple actions are possible.
*
* This function should be called by drag destinations in response to
@ -862,7 +865,7 @@ gdk_drop_read_value_internal (GdkDrop *self,
* then call [method@Gdk.Drop.read_value_finish] to get the resulting
* `GValue`.
*
* For local drag'n'drop operations that are available in the given
* For local drag-and-drop operations that are available in the given
* `GType`, the value will be copied directly. Otherwise, GDK will
* try to use [func@Gdk.content_deserialize_async] to convert the data.
*/

View File

@ -163,6 +163,7 @@ gdk_wayland_drag_cancel (GdkDrag *drag,
GdkDragCancelReason reason)
{
gdk_drag_set_cursor (drag, NULL);
gdk_drag_drop_done (drag, FALSE);
}
static void
@ -290,6 +291,7 @@ data_source_dnd_finished (void *data,
GdkDrag *drag = data;
g_signal_emit_by_name (drag, "dnd-finished");
gdk_drag_drop_done (drag, TRUE);
}
static void

View File

@ -512,7 +512,7 @@ gtk_drag_icon_get_child (GtkDragIcon *self)
* If GTK does not know how to create a widget for a given value,
* it will return %NULL.
*
* This method is used to set the default drag icon on drag'n'drop
* This method is used to set the default drag icon on drag-and-drop
* operations started by `GtkDragSource`, so you don't need to set
* a drag icon using this function there.
*

View File

@ -824,7 +824,7 @@ gtk_drop_target_class_init (GtkDropTargetClass *class)
* and no further processing is necessary.
*
* Otherwise, the handler returns %TRUE. In this case, this handler will
* accept the drop. The handler is responsible for rading the given @value
* accept the drop. The handler is responsible for using the given @value
* and performing the drop operation.
*
* Returns: whether the drop was accepted at the given pointer position