[PATCH] protocol: Add DnD actions
Carlos Garnacho
carlosg at gnome.org
Tue May 26 08:52:26 PDT 2015
Hey Jonas,
Late reply, let's try to pick this up again...
On mar, 2015-04-21 at 14:29 +0800, Jonas Ådahl wrote:
> On Sat, Apr 18, 2015 at 04:53:46PM +0200, Carlos Garnacho wrote:
> > Hey Jonas,
>
> Hi,
>
> Thanks for the explanations. I'll reply inline.
>
> >
> > On vie, 2015-04-17 at 15:50 +0800, Jonas Ådahl wrote:
> >
> > <snip>
> > >
> > > > For the touch case, depending on how the grab is implemented,
> > > > with
> > > > the
> > > > current guidelines the only 2 choices are "leave the client in
> > > > inconsistent state" or "make the client still receives ongoing
> > > > touches
> > > > despite the pointer grab" (same applies if the grab is touch
> > > > triggered, only with the other touches that didn't trigger the
> > > > grab).
> > > >
> > > > More on topic, keyboards are also funky if we keep focus on
> > > > clients,
> > > > you can conceivably Esc/Ctrl-Q/... to close the app you're
> > > > dragging
> > > > from. IMO the way forward is precisely this, the compositor
> > > > becomes in
> > > > control of the keyboard, and we offer the missing semantics to
> > > > cover
> > > > for this.
> > >
> > > Meaning its the compositor that decides whether a drag is a copy
> > > or a
> > > move? I.e. either we hard code "Ctrl" to be copy in the
> > > protocol, or
> > > DND
> > > will behave different on each compositor. Not sure I like any of
> > > those
> > > options.
> >
> > Yes, this would be implementation-dependent in the compositor as
> > my
> > proposal goes. We have 3 players here, whoever gets to handle the
> > modifier->action translation, there's room for confusion in cross-
> > DE/toolkit cases.
>
> The problem as I see it is that it'd be even confusing for DND within
> the same application as it would be depending on the DE how it'd
> work.
> >
> > Focusing on actions, I see the following possible data flows here
> > (depicting the same situation on all: initial negotiation, changes
> > on
> > the dest on say pointer motion, and a modifier change):
> >
> > 1. If handled purely by the source:
> >
> > wl_data_source compositor wl_data_offer
> > ============== ========== =============
> > -> notify_actions <-
> > dest_actions <-
> > -> preferred_action
> > action <- -> action
> >
> > ...
> > (pointer moves across
> > widgets)
> > notify_actions <-
> > dest_actions <-
> > -> preferred_action
> > action <- -> action
> >
> > ...
> > (modifiers change)
> > modifiers <-
> > -> preferred_action
> > action <- -> action
> >
> >
> > 2. If handled purely by the dest:
> >
> > wl_data_source compositor wl_data_offer
> > ============== ========== =============
> > -> notify_actions
> > -> source_actions
> > notify_actions <-
> > preferred_action <-
> > action <- -> action
> >
> > ...
> > (pointer moves across
> > widgets)
> > notify_actions <-
> > preferred_action <-
> > action <- -> action
> >
> > ...
> > (modifiers change)
> > -> modifiers
> > preferred_action <-
> > action <- -> action
> >
> >
> > 3. If handled purely by the compositor:
> >
> > wl_data_source compositor wl_data_offer
> > ============== ========== =============
> > -> notify_actions <-
> > action <- -> action
> >
> > ...
> > (pointer moves across
> > widgets)
> > notify_actions <-
> > action <- -> action
> >
> > ...
> > (modifiers change)
> > action <- -> action
> >
> >
> > Options #1 and #2 involve roundtrips, option #3 doesn't. Options
> > #1
> > and #2 would still need some validation on the compositor to avoid
> > picking options unknown to either side.
>
> I think its wrong to refer to these as roundtrips. A roundtrip is
> typically a client that need to wait for a reply from a server, but
> here
> in any of the three options no one is waiting for anything, thus we
> have
> no round trips at all.
Here I was referring to the places where the compositor sends an event
to either side, and awaits an immediate reply for it. It is true that
those are non blocking, the compositor is free to keep doing stuff in
between everywhere else, except wrt the DnD operation.
If these don't account as "roundtrips" in your book, I'll call them
"avoidable hops" instead :).
> The main differences as I see it are:
>
> In option 1 and 2 we pass an additional modifier state, and make
> either
> side be responsible for choosing. In option 3 we move this and make
> it
> compositor choose (either with hard coded policy in the protocol or
> some
> arbitrary policy given some private state inside the compositor).
>
> In option 1 and 2, we have a slightly longer delay in visual feedback
> regarding the action (caused by the outsourcing of the decision
> making).
> I'd say these delays are in most cases insignificantly small. In any
> solution we end up with latency as we are dealing with 3 entities
> communicating asynchronously. Note that option 3 has this delay as
> well,
> but for chosen mime type visual feedback.
TBH, this is something I've only seen on weston-dnd, and I've always
thought it's due to the lack of DnD actions.
Most normally, you don't care if the drag dest requests plain text,
rtf, html or whatnot, you are dragging the same text, and the drag
surface is either a surface with that text, or a generic "text" icon.
It's been though the cursor surface what has traditionally changed to
reflect the action being taken, which should only happen on the
wl_data_source.action event handler as per the proposal.
>
> In option 2, "actions" would be handled identical to mime types. The
> modifier change would be semantically equivalent to a motion event.
> We'd
> have all the decision making (mime type, action) on one side. I
> suppose
> this should be considered most "consistent" with the existing DND
> protocol if that matters in any way.
I see your point wrt consistency, although having worked lately on
wayland/X11 DnD interoperation on mutter, I see this option very hard
to reconcile in that scenario, with both working in its own terms and
state machine:
- When dragging from X11 to wayland clients, the drag source announces
one modifier-induced action in its XdndPosition messages, the drag dest
is expecting though .modifier() events in order to pick an action. As
long as both parts agree, this is merely awkward/inconvenient.
- When dragging from wayland to X11 clients, both sides are left
awaiting for the other side to pick an action, so none does in the end,
as it's the counterpart which usually would.
>
> In option 1, we'd be slightly more close to how XDND works, but
> splits
> the decision making between the two end points which might not be
> very
> nice. We'd also have one extra (probably also insignificant) delay
> since
> the compositor needs to make the let the source decide the action
> before
> performing the drop on the destination. We'd also need to delay the
> drop
> so the source can make a final decision, which doesn't seem very
> nice.
>
> Assuming the extra visual feedback delay can be considered
> insignificant
> I think we have 3 major paths to take:
>
> 1) Actions are chosen arbitrarily by the compositor
> 2) Policy is hard coded into the protocol (Ctrl means copy etc)
> 3) Pass additional state (modifier) to the decision making client
>
> Personally, by just looking at how the protocol would look and how
> data
> would flow, option 3 with the destination making the choice seems to
> make most sense to me, since it'd be most consistent with how it
> currently works and it doesn't split up the decision making nor add
> policy or undefined behavior to the protocol.
After some time playing with the different options, I will stand for my
v2 proposal as-is.
- Passing modifiers to the drag source is completely backwards to the
rest of the protocol, passing to the drag dest is more natural protocol
-wise, but is unworkable wrt X11 interoperation.
- In the "current action is chosen by the compositor" land, I've also
tried to streamline action picking on the dest side, so it doesn't have
to provide its action mask and does just pick an option, but I always
end up seeing one major flaw: the drag destination would receive
wl_data_offer.action twice each time the action changes, one as the
tentative new action, and another after the drag dest has picked one.
We may split that in 2 separate tentative/definitive events, but still
doesn't strike me as trivial or race-free, plus we end up with both the
compositor and the drag dest trying to retain part of the state in
order to avoid messaging ping-pong. It does seem cleaner to me
retaining all state in the compositor and only emitting the relevant
signals in either way when anything changes.
In case anybody wonders how XDND solves this, it demands that every
XdndPosition message is replied with a XdndStatus one, and the drag
source state machine blocks until this happens, so you can't get DnD
started in between, because it's the drag source which decides when
does it start.
So, for simplicity sake, I'm chosing #2 in your options above, and
adding some modifier/button recommendations for compositors. I'll
double check the patches and send the necessary updates again.
Cheers,
Carlos
More information about the wayland-devel
mailing list