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

Jonas Ådahl jadahl at gmail.com
Tue Dec 22 18:10:31 PST 2015


On Tue, Dec 22, 2015 at 06:56:05PM +0100, Carlos Garnacho wrote:
> Hey,
> 
> On Tue, Dec 22, 2015 at 1:36 PM, Jonas Ådahl <jadahl at gmail.com> wrote:
> > 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.
> 
> Yeah, right. As you say the drag dest can preempt the final action
> through wl_data_offer.source_actions, that's also in fact useful for
> "ask" actions, as otherwise you have to probe the available actions.
> I've added the following blurb, again to wl_data_offer.action:
> 
>    Upon "ask" actions, the drag-and-drop destination is expected to
>    possibly choose different a different action and/or mime type,
>    based on wl_data_offer.source_actions and finally chosen by the
>    user (e.g. popping up a menu with the available options). The
>    final wl_data_offer.set_action and wl_data_offer.accept requests
>    must happen before the call to wl_data_offer.finish.

Should it also be added that in this particular case, the
wl_data_offer.action will not be emitted, and that if
wl_data_offer.set_actions is set with more than one or an unsupported
action an error will be sent?


Jonas

> 
> Cheers,
>   Carlos


More information about the wayland-devel mailing list