[PATCH] xdg-shell - yet another proposal (this time for real).

Gregory Merchan gregory.merchan at gmail.com
Thu Nov 7 12:34:24 PST 2013


I failed to reply to all. I hope copying and pasting hasn't messed up anything.

On Thu, Nov 7, 2013 at 3:32 AM, Rafael Antognolli
<rafael.antognolli at intel.com> wrote:
> Hello all,
>
> Following is the same description as in my previous wrong email, but with the
> correct patch attached.
>
> I'm trying to summarize part of the discussion in this new patch, but it's not
> the final one.
>
> As far as I understood, the goal is to end up with something like this for
> keyboard focus:
>
> W = compositor
> A, Z = client surfaces
>
> Viewport change:
> W to Z: You are deactivated.
> W to A: You are activated.
> A to W: Do these things.
>
> So, I added "activated" and "deactivated" events, that the compositor can use
> to inform clients what they are. And there's a take_focus request that can be
> used by a client to ask for activation, but it's up to the compositor to
> decide.

That's only part of it. When I wrote about W, A, and Z, the discussion
had been narrowed to a subset of reasons for changing focus that
included things like viewport changes.

The name "take_focus" sounds like it's about something different from
"activated" and "deactivated". It's is also similar to a request on X
which window managers make of clients, "WM_TAKE_FOCUS", and this
invites confusion. It also sounds more like a request to deactivate,
as in, "Please take focus away from me."

The obvious name for the request, "activate", is only one letter
different from the name of the event "activated", so perhaps that
should be avoided. I think "set_active" is in line with other names.
If that's not suitable, only "please_activate" and "make_active" come
to my mind. I will use "set_active" for the remainder of this message.

I described the need for signatures allowing the compositor to
validate requests. I believe the simplest suitable signature is a
timestamp as provided by some events. This allows the compositor to
associate the request with an event and to invalidate requests which
have been superseded by later requests. The timestamp of
wl_pointer::button and other user-generated events seems to be the
thing to use.

The "activated" event must provide a valid timestamp which the client
can use as a signature to make a "set_active" request. This allows the
client to activate the correct surface (such as a modal dialog) when
the compositor has activated the wrong surface. The "deactivated"
event does not really need a timestamp, because merely being
deactivated is no reason to request activation, but clients could use
such a timestamp to avoid making requests which will fail because
their timestamps came before the deactivation. The name and type of
the timestamp should be "time" and "uint", just like the
user-generated wl_pointer::button, wl_keyboard::key, and
wl_touch::down events.

The "set_active" request should have a "time" argument of type "uint",
just like the aforementioned events.

These events, requests, and timestamps do not suffice to make a good
system; a good division of responsibilities is also needed. The only
division of responsibilities which allows for all of the expected
features of modern GUIs is as follows.

Clients:
1. Must request activation when they need it, as indicated by
user-generated events or other sources of timestamps.
2. Must expect activation from the compositor, which will happen for
events of which clients cannot be aware.

Compositors:
3. Must not activate surfaces when clients could request activation
but have not done so.
4. May activate surfaces in response to requests or events of which
clients are not aware.

You may note that this is different from what MS Windows and all
extant X11 window managers do; it is at least similar to what MacOS
does.

Why this division? I'll go through each.

1.
A. When the user presses a button over a client surface, only that
client is aware of the contents of the surface and thus whether the
surface should remain inactive or be activated. If the button press is
on something in the surface that might be dragged to another surface,
such as file icon, a client would remain inactive so as not to be
raised and obscure the drop target. If the button press is on a
control that could be used without changing keyboard focus, like a
tool palette or a scroll bar, a client would remain inactive to allow
other work to proceed without moving keyboard focus back and forth.
B. Events may occur in other clients, and not the compositor, which
provide a client with a reason to request activation. The most obvious
is when one client starts another client, as a file manager might
start a text editor to open a document. The starting client should
provide to the started client the timestamp of the event which is the
reason for starting it, and then the started client should request
activation using that timestamp when it is ready to do so. This allows
for a smooth flow of work between applications. Because clients can
only request activation, the compositor, checking timestamps, can
prevent a client which took too long to start from stealing activation
from a client that was activated during the delay.
C. Clients may need to request activation when they already have it.
Using the file manager example again, if the user decides to not to
wait on a slow loading application and instead does something else
with the file manager, the file manager, even though active, should
again request activation so the compositor will have a last activation
timestamp more recent than the one the slow app will use. Such a
technique may be used in terminal emulators so that applications
opened from a command line do not steal activation from the terminal
if the user continues to use the terminal. If the pointer leaves an
activated surface, enters it again, and a button is pressed, the
client should again request activation of the still active surface, so
that slow clients, seeking activation from when the active client lost
pointer focus, do not steal activation. (Perhaps I should write an
essay, "Has your activation gone stale? Preventing activation
stealing.")

2. The compositor is the final arbiter of activation and may deem it
necessary despite the expectations of a client. Clients cannot refuse
activation, but they are not without options in response to it. They
may: a) request another of their surfaces be activated, using the
timestamp from the "activated" event; b) destroy the surface; or c)
ignore activation by not repainting their windows, processing
keystrokes, etc. (This last option is not recommended.) Clients should
not delay their responses in an attempt to second-guess the
compositor.

3. If a compositor activates a surface when a client could just as
well request activation, it will prevent more sophisticated
interactions such as raise-less drag-and-drop, fluid palette use, and
churn-free scrolling. I may also cause focus stealing by errantly
activating new surfaces. Clients creating new surfaces, even new
clients, should be requesting activation with timestamps provided by
events or other clients. A new client without a timestamp to activate
its surfaces should use "demands_attention" instead.

4. There are events which clients do not receive but nonetheless are a
reason for client surfaces to be activated. The destruction of another
client's surface, a viewport change, and window switching by keystroke
(Alt+Tab), are examples of such events. For these, if a surface is to
be activated, it must be the compositor which does so despite no
request from the client. Because the compositor is not aware of the
internal state of the client, it may choose to activate the wrong
surface. For this reason, the "activated" event must have a timestamp,
like a user-generated event, which allows the client to activate the
correct surface.

It should be recognized that in the absence of sophisticated
interactions like drag-and-drop a client receiving a button press
event already has been or is about to be activated; the crossing
events preceded button events, so point-to-focus policies activate
earlier than click-to-focus polices would.

Clients can support both point-to-focus policies and click-to-focus
polices by using both crossing events and button events to request
activation. A surface using a button event in addition to a crossing
event will not create a problem for point-to-focus users, because the
surface, compositor permitting, will already be active when the button
event occurs. It will not create a problem for click-to-focus users
because they can instruct the compositor to ignore requests from
crossing events, but this is not without cost because otherwise silent
clients will be chattering with requests which will be denied.
Conversely, clients not using crossing events to request activation
may appear to be non-responsive or slowly responsive to point-to-focus
users. The compositor could force a point-to-focus policy, but would
do so at the cost of the aforementioned sophisticated interactions.

I believe a flag of some sort from the compositor to indicate the
user's preference is a good way to reduce chatter, support both kinds
of policies, and allow for sophistication. I recommend a signed
integer value, perhaps "crossing_activation_timeout", interpreted as
follows:

n = -1: Clients should not expect crossing event activation requests
will be honored.
n >= 0: Clients should expect crossing event activation request to be
honored n milliseconds after the timestamp, if at all.

In the latter case, clients should expect the compositor to handle the
timing and so not delay their requests. I imagine clients may be able
to make use of the timing information, but if that is not so, then a
simple boolean like "crossing_activation_accepted" should suffice.

The compositor should be able to handle deactivation for the
PointerRoot focus policy, if anybody even uses that.

I have neglected to mention pointer warping because I hope nobody does
that anymore.


> Regarding the surface fullscreen, maximized, etc, I added surface states as
> enum's, that can be set/unset, and events from the compositor to request that a
> given state should be set/unset.
>
> For those states that take parameters, I added separate requests for setting
> the parameters before setting the state. It should all take place after commit
> anyway, so that shouldn't matter much. Take a look at the docs and say what you
> think.
>
> I didn't change transient/popup surface types yet, but from what has been said
> in the ML thread, I think they also should be surface states now. Correct me if
> I'm wrong. Otherwise I'm going to send an updated version with those changes
> tomorrow.
>
> I also talked to jekstrand (I think) about stacking, will send an updated
> version with what I understood from that tomorrow. Should be simple.

I have of course assumed that surfaces would not normally be raised in
the absence of activation. I believe stacking can and should be left
to clients within constraints imposed by the compositor except for
those special cases, like window switching, where it makes sense for
the compositor to shuffle windows around.

Because a new surface may remain not activated, I believe compositors
should initially place them beneath the active surface and possible
below all the normal surfaces. (Not below a desktop window, obviously,
for that would forever obscure it.)

> Any feedback is appreciated, and thank you guys for the input so far and the
> patience.
>
>
> Rafael Antognolli (1):
>   xdg_shell: Add a new shell protocol.
>
>  protocol/Makefile.am     |   2 +-
>  protocol/xdg-surface.xml | 381 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 382 insertions(+), 1 deletion(-)
>  create mode 100644 protocol/xdg-surface.xml
>
> --
> 1.8.3.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel

One of these days I shall learn brevity.


More information about the wayland-devel mailing list