[PATCH wayland 2/2] protocol: Add DnD actions

Jonas Ådahl jadahl at gmail.com
Tue Dec 22 04:36:45 PST 2015


On Tue, Dec 22, 2015 at 12:20:35PM +0100, Carlos Garnacho wrote:
> Hey!,
> 
> On Tue, Dec 22, 2015 at 4:12 AM, Jonas Ådahl <jadahl at gmail.com> wrote:
> > On Tue, Dec 22, 2015 at 02:33:33AM +0100, Carlos Garnacho wrote:
> >> These 2 requests have been added:
> >>
> >> - wl_data_source.set_actions: Notifies the compositor of the available
> >>   actions on the data source.
> >> - wl_data_offer.set_actions: Notifies the compositor of the available
> >>   actions on the destination side, plus the preferred action.
> >>
> >> Out of the data from these requests, the compositor can determine the action
> >> both parts agree on (and let the user play a role through eg. keyboard
> >> modifiers). The chosen option will be notified to both parties
> >> through the following two requests:
> >>
> >> - wl_data_source.action
> >> - wl_data_offer.action
> >>
> >> In addition, the destination side can peek the source side actions through
> >> wl_data_offer.source_actions.
> >>
> >> Compared to the XDND protocol, there's two notable changes:
> >>
> >> - XDND lets the source suggest an action, whereas wl_data_device lets
> >>   the destination prefer a given action. The difference is subtle here,
> >>   it comes off as convenience because it is the drag destination which
> >>   receives the motion events (unlike in X) and can perform action updates.
> >>
> >>   The drag destination seems also in a better position to update the
> >>   preferred action based on things like the data being transferred, the
> >>   place being dropped, and whether the drag is client-local.
> >>
> >> - That same source-side preferred action is used in XDND to convey the
> >>   modifier-induced action to the drag destination, which would then ack
> >>   it, or reply with another action that's accepted (or none), this makes
> >>   the XdndPosition/XdndStatus messaging very verbose, and synchronous
> >>   because the drag source always needs to know the latest status/action
> >>   for every position+action sent.
> >>
> >>   Here it's the compositor which takes care of modifiers and matching
> >>   available/accepted actions, this allows for the signaling to happen
> >>   only whenever the actions/modifiers change for real.
> >>
> >> Roughly based on previous work by Giulio Camuffo <giuliocamuffo at gmail.com>
> >>
> >> Changes since v5:
> >> - Applied rewording suggestions from Jonas Ådahl. Dropped slot reservation
> >>   scheme for actions. Fixed indentation and other minor formatting issues.
> >>
> >> Changes since v4:
> >> - Minor rewording.
> >>
> >> Changes since v3:
> >> - Splitted from DnD progress notification changes.
> >> - Further rationales in commit log.
> >>
> >> Changes since v2:
> >> - Renamed notify_actions to set_actions on both sides, seems more consistent
> >>   with the rest of the protocol.
> >> - Spelled out better which events may be triggered on the compositor side
> >>   by the requests, the circumstances in which events are emitted, and
> >>   what are events useful for in clients.
> >> - Defined a minimal common ground wrt compositor-side action picking and
> >>   keybindings.
> >> - Acknowledge the possibility of compositor/toolkit defined actions, even
> >>   though none are used at the moment.
> >> Changes since v1:
> >> - Added wl_data_offer.source_actions to let know of the actions offered
> >>   by a data source.
> >> - Renamed wl_data_source.finished to "drag_finished" for clarity
> >> - Improved wording as suggested by Bryce
> >>
> >> Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
> >> Reviewed-by: Michael Catanzaro <mcatanzaro at igalia.com>
> >> Reviewed-by: Mike Blumenkrantz <zmike at samsung.com>
> >
> >
> >
> >> ---
> >>  protocol/wayland.xml | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  1 file changed, 122 insertions(+)
> >>
> >> diff --git a/protocol/wayland.xml b/protocol/wayland.xml
> >> index ae5ef21..001d811 100644
> >> --- a/protocol/wayland.xml
> >> +++ b/protocol/wayland.xml
> >> @@ -486,6 +486,55 @@
> >>       wl_data_offer.destroy after this one.
> >>        </description>
> >>      </request>
> >> +
> >> +    <request name="set_actions" since="3">
> >> +      <description summary="set the available/preferred drag-and-drop actions">
> >> +     Sets the actions that the destination side client supports for
> >> +     this operation. This request may trigger the emission of
> >> +     wl_data_source.action and wl_data_offer.action events if the compositor
> >> +     needs changing the selected action.
> >> +
> >> +     This request can be called multiple times throughout the
> >> +     drag-and-drop operation, typically in response to wl_data_device.enter
> >> +     or wl_data_device.motion events.
> >> +
> >> +     This request determines the final result of the drag-and-drop
> >> +     operation. If the end result is that no action is accepted,
> >> +     the drag source will receive wl_drag_source.cancelled.
> >> +      </description>
> >> +      <arg name="dnd_actions" type="uint"/>
> >> +      <arg name="preferred_action" type="uint"/>
> >> +    </request>
> >> +
> >> +    <event name="source_actions" since="3">
> >> +      <description summary="notify the source-side available actions">
> >> +     This event indicates the actions offered by the data source. It
> >> +     will be sent right after wl_data_device.enter, or anytime the source
> >> +     side changes its offered actions through wl_data_source.set_actions.
> >> +      </description>
> >> +      <arg name="source_actions" type="uint"/>
> >> +    </event>
> >> +
> >> +    <event name="action" since="3">
> >> +      <description summary="notify the selected action">
> >> +     This event indicates the action selected by the compositor after
> >> +     matching the source/destination side actions. Only one action (or
> >> +     none) will be offered here.
> >> +
> >> +     This event can be emitted multiple times during the drag-and-drop
> >> +     operation, mainly in response to source side changes (through
> >> +     wl_data_source.set_actions), destination side changes (through
> >> +     wl_data_offer.set_actions), and as the pointer enters/leaves
> >> +     surfaces.
> >> +
> >> +     Compositors may also change the selected action on the fly, mainly
> >> +     in response to keyboard modifier changes during the drag-and-drop
> >> +     operation.
> >> +
> >> +     The most recent action received is always the valid one.
> >
> > How can we describe this more precisely? "most recent" is ambigous, and
> > it makes it seem possible to have the destination and client o have
> > different ideas of what action is actually used.
> >
> > I suppose it is a bit problematic. For "move"/"copy" it's simpler,
> > because no changes will be made after wl_data_device.drop and that
> > event could act as a barrier, but for "ask" it is tricky.
> >
> > When "ask" is used, I assume the destination will call
> > wl_data_offer.set_actions to something other than "ask" (this doesn't
> > seem spelled out anywhere btw, should probably describe what "ask"
> > actually is). After this is done, should the compositor reply with the
> > actual action after having made sure the source supports the newly set
> > action, with the client waiting for a reply. Or should the destination
> > make sure to choose from one of the "source_actions" actions (while the
> > compositor would terminate any client choosing an unavailable action)?
> >
> >> +      </description>
> >> +      <arg name="dnd_action" type="uint"/>
> >> +    </event>
> >>    </interface>
> >>
> >>    <interface name="wl_data_source" version="3">
> >> @@ -542,6 +591,9 @@
> >>       - The drag-and-drop operation was performed, but the drop destination
> >>         did not accept any of the mimetypes offered through
> >>         wl_data_source.target.
> >> +     - The drag-and-drop operation was performed, but the drop destination
> >> +       did not select any action present in the mask offered through
> >> +       wl_data_source.action.
> >>       - The drag-and-drop operation was performed but didn't happen over a
> >>         surface.
> >>       - The compositor cancelled the drag-and-drop operation (e.g. compositor
> >> @@ -557,6 +609,16 @@
> >>
> >>      <!-- Version 3 additions -->
> >>
> >> +    <request name="set_actions" since="3">
> >> +      <description summary="set the available drag-and-drop actions">
> >> +        Sets the actions that the source side client supports for this
> >> +        operation. This request may trigger a wl_data_source.action event and
> >> +        wl_data_offer.action events if the compositor needs changing the
> >> +        selected action.
> >> +      </description>
> >> +      <arg name="dnd_actions" type="uint"/>
> >> +    </request>
> >> +
> >>      <event name="dnd_drop_performed" since="3">
> >>        <description summary="the drag-and-drop operation physically finished">
> >>       The user performed the drop action. This event does not indicate
> >> @@ -576,8 +638,34 @@
> >>       The drop destination finished interoperating with this data
> >>       source, the client is now free to destroy this data source and
> >>       free all associated data.
> >> +
> >> +     If the action used to perform the operation was "move", the
> >> +     source can now delete the transferred data.
> >>        </description>
> >>      </event>
> >> +
> >> +    <event name="action" since="3">
> >> +      <description summary="notify the selected action">
> >> +        This event indicates the action selected by the compositor after
> >> +        matching the source/destination side actions. Only one action (or
> >> +        none) will be offered here.
> >> +
> >> +        This event can be emitted multiple times during the drag-and-drop
> >> +        operation, mainly in response to source side changes (through
> >> +        wl_data_source.set_actions), destination side changes (through
> >> +        wl_data_offer.set_actions), and as pointer enters/leaves surfaces.
> >> +
> >> +        Compositors may also change the selected action on the fly, mainly
> >> +        in response to keyboard modifier changes during the drag-and-drop
> >> +        operation.
> >> +
> >> +        The most recent action received is always the valid one.
> >
> > Here as well I'd still like to see something more like "the last action
> > received before X" to describe what will be the final action. I guess
> > it's the last .action event emitted before .send (or .finished if no
> > data transfer was made for some odd reason)?
> 
> Oh, right, this didn't get much more verbosity... Right, since the
> action is to take effect in wl_data_source.dnd_finished, it would be
> the last one received at that point, so if a drag-and-drop operation
> starts as "ask", and the user selects "move", the action that must
> take effect on .dnd_finished is indeed "move".
> 
> I've locally added the following blurb to wl_data_source.action:
> 
>    The most recent action received is always the valid one. The chosen
>    action may change alongside negotiation (e.g. an "ask" action can turn
>    into a "move" operation), so the effects of the final action must be
>    always applied in wl_data_offer.dnd_finished.
> 
> And this one to wl_data_offer.action:
> 
>    The most recent action received is always the valid one. Prior to
>    receiving wl_data_device.drop, the chosen action may change (e.g.
>    due to keyboard modifiers being pressed). At the time of receiving
>    wl_data_device.drop the drag-and-drop destination must honor the
>    last action received.
> 
>    Action changes may still happen after wl_data_device.drop,
>    especially on "ask" actions, where the drag-and-drop destination
>    may choose another action afterwards. Action changes happening
>    at this stage are always the result of inter-client negotiation, the
>    compositor shall no longer be able to induce a different action.

This is much better I think. What I think can be added is the
event/request flow for "ask". Here it sounds like for "ask" after the
destination sent the last wl_data_offer.set_actions with the chosen
action(s), it still need to do a roundtrip to make sure that maybe
emitted wl_data_offer.action is received. It'd be more clear if this is
actually spelled out.

Or should it be like that? The wl_data_offer do have the information it
needs to make a decision (it has the wl_data_source's actions, and the
compositor will have no say anyway as you wrote above), so we could
avoid the roundtrip by just having the client make the decision while
the compositor just acts as a guard and terminates a client that tries
to set more than one action or any action not supported by the data
source.

Doing that we need to write it so that the wl_data_source may call
set_actions after some point so that the wl_data_offer, wl_data_source
and the compositor will have the same idea of what actions all parts
support.


Jonas

> 
> Cheers,
>   Carlos


More information about the wayland-devel mailing list