How to implement OSD overlay in Wayland/Weston

Guillermo Rodriguez guillerodriguez.dev at gmail.com
Tue Nov 19 11:48:10 UTC 2019


El mar., 19 nov. 2019 a las 11:47, Pekka Paalanen
(<ppaalanen at gmail.com>) escribió:
>
> On Tue, 19 Nov 2019 09:53:39 +0100
> Guillermo Rodriguez <guillerodriguez.dev at gmail.com> wrote:
>
> > Hi all,
> >
> > This is a follow up to my earlier email "Let pointer events pass through".
> >
> > I have an use case where there is one full screen application (I'll
> > call this the "main" application) and I need to show a OSD overlay on
> > top of it. The OSD overlay is actually based on GStreamer (think PiP)
> > and is managed by a different process.
> > The OSD overlay should not handle pointer events; these should pass
> > through to the main application, which knows how to handle them.
> >
> > I am not sure how to approach this in Wayland/Weston. I have
> > considered the following:
> >
> > 1.
> > Use wl_surface::set_input_region so that pointer events are not
> > delivered to the OSD overlay, but instead pass through and are handled
> > by the main application.
> > This "almost" works, however when the main application receives the
> > event, Weston brings it on top, thus hiding the OSD overlay.
> > I searched for a way to specify that a given surface should always
> > stay "on top". This does not seem to be supported in Wayland.
>
> Hi,
>
> yes. I'm not aware of any Wayland extension that would allow clients to
> dictate always-on-top behaviour on the desktop. It has an obvious
> attack vector (malicious or misbehaving app setting always-on-top
> without user's consent) and a simple corner case (how do you stack
> multiple always-on-top windows).
>
> OSD as a concept seems like a desktop component, not a normal app.
> Hence I would expect such a client to use a domain-specific or custom
> protocol extension to set always-on-top. If your use case is not a
> generic desktop but some special environment, then a domain-specific

It is actually a special environment; a single fullscreen app on an
embedded system.

> protocol extension would be a way to go. For generic desktop
> environments you'd integrate with the particular DE specifically, e.g.
> a gnome-shell plugin or something.
>
> That is, if the OSD really is an independent separate program and not a
> part of some fullscreen application.
>
> If the OSD is just a piece of a bigger application and only needs to be
> on top of that application's windows, you could probably use xdg
> extensions or a sub-surface to realize it. This does mean that the OSD
> component must be in-process with the main app and share the same
> wl_display instance.

The OSD is conceptually part of the fullscreen application but due to
several reasons it is implemented as a separate process with a CLI
that controls the OSD contents and PiP function; the main application
communicates with the OSD process by writing commands to the OSD
process' stdin, and reading responses from the OSD process' stdout.

There are several reasons for this approach, but the main one is that
if there are any issues in the GStreamer side this should not crash
the whole application. With the current approach, the main application
can just respawn the OSD process if it dies.

> I think this should be possible also with GStreamer.

Not in the current implementation of the waylandsink plugin -- it
always creates its own top level window
(https://gstreamer.freedesktop.org/documentation/waylandsink/index.html?gi-language=c),
and does not support drawing to an existing surface. But this could be
patched if needed.

>
> > 2.
> > Setup things so that the OSD overlay is not an additional top level
> > surface, but a child surface owned by the main application.
> > This would mean having the main application create a child surface for
> > the OSD, and pass this surface to the OSD process.
> > In X this could be achieved by passing a Windows ID. In Wayland
> > apparently it is not possible to share surfaces between processes.
>
> I'd avoid a design with two separate processes. As Ilia wrote,
> xdg-foreign exists, but I'm not sure which compositors implement it.
>
> In Wayland, all protocol objects are private to the Wayland connection
> (wl_display) where they were created. xdg-foreign is a way to work
> around that, but I'd leave xdg-foreign only to cases that really need
> to have separate processes for e.g. security reasons.
>
> > 3.
> > Let the OSD overlay actually handle pointer events, but "send" them to
> > the main application.
> > In X this could be achieved with XSendEvent. In Wayland apparently it
> > is not possible to have one process send events to another process.
>
> Once an input event has been delivered to a client, there is no way to
> send it back or to another client in Wayland. Input event routing is
> one-way.
>
> In Wayland, each client is isolated by default, and we try hard to keep
> things that way so there is no spying or injection.

OK, so it seems that 2 and 3 are going to be difficult due to
architectural reasons. Let's go back to 1.

I understand that my main problem is controlling the Z-order of
top-level surfaces. If that is not possible at the application level,
then I guess I need to mess around with Weston.

>From what I see
(https://vignatti.com/2013/03/05/ui-customization-on-wayland/), Weston
supports the concept of plugabble shells that are in charge of
defining "how surfaces will be mapped on the screen". I guess then
that I would need to write a custom shell controlling Z-order of the
surfaces. Does this make sense?

I have been looking for documentation on this (the API for custom
Weston shells), but I cannot find anything. Can you point me in the
right direction?

Thanks,

Guillermo


More information about the wayland-devel mailing list