glfw icon indicating copy to clipboard operation
glfw copied to clipboard

Add window hint to render as shell layer (e.g. desktop background)

Open vmedea opened this issue 2 years ago • 4 comments

This adds a wayland specific hint GLFW_WAYLAND_SHELL_LAYER to make it possible to render to one of wayland's full screen layers using the wlr-layer-shell-unstable-v1 wayland interface. This can be used to, for example, render to the desktop background, or as an overlay.

It can take any of the values from zwlr_layer_shell_v1::layer, or -1 (default) to create an application window.

I've included the protocol xml file (similar to what swaybg does) because it doesn't seem to be generally available in package managers, like debian's wayland-protocols package.

Edit: I'm not entirely sure I like this interface much from a user point of view, it is the most specific and flexible for wayland, but something like a "render to desktop wallpaper" hint could be cross-platform.

vmedea avatar Mar 22 '22 23:03 vmedea

It appears the layer-shell protocol extension is supported in Sway, as well as every Wayland compositor based on wlroots. But It doesn't exist on GNOME, there are no plans to implement it , nor is there (as far as i could find) any equivalent there.

For X11 there's the _NET_WM_WINDOW_TYPE property that can be set to _NET_WM_WINDOW_TYPE_DESKTOP.

vmedea avatar May 09 '22 06:05 vmedea

Thank you for adding this hint! I've tried the window hint GLFW_WAYLAND_SHELL_LAYER, and setting the desktop background is working perfectly!

There's one thing that I wanted to mention, which is a use case that I came across, and it's regarding the layer shell's Top Layer = 2:

I was building a Panel for the desktop using GLFW, which is supposed to be on the Top layer. When I assigned Layer 2 to that Panel application using the GLFW_WAYLAND_SHELL_LAYER and enabled Window Transparency, I couldn't interact with the rest of the desktop applications (the other desktop applications were registering my keyboard input but not mouse input or anything). This is probably an expected behavior since the GLFW window (in this case, my panel) becomes full screen, and the other application windows stay on -1; therefore they don't register anything except the keyboard input. I tried to enable GLFW_MOUSE_PASSTHROUGH, but that's not registering mouse inputs to applications windows either.

Changing window sizes doesn't make sense here since they will become fullscreen anyways due to the nature of the layer shell. I was wondering if there's any other workarounds for this specific use case.

bootkernel avatar Jul 30 '22 12:07 bootkernel

Thanks for testing. I haven't tried to use this for any other layers than background, myself.

I couldn't interact with the rest of the desktop applications (the other desktop applications were registering my keyboard input but not mouse input or anything).

I thought I handled that case by setting an empty input region:

        // Empty input region (background shouldn't capture events).
        struct wl_region *input_region =
                wl_compositor_create_region(_glfw.wl.compositor);
        wl_surface_set_input_region(window->wl.surface, input_region);
        wl_region_destroy(input_region);

But clearly, that in itself isn't enough to be transparent to events. I remember the main use of the top payer is captive UI such as screen lockers so maybe it's unavoidable, I'm not sure!

vmedea avatar Jul 30 '22 13:07 vmedea

I thought I handled that case by setting an empty input region:

        // Empty input region (background shouldn't capture events).
        struct wl_region *input_region =
                wl_compositor_create_region(_glfw.wl.compositor);
        wl_surface_set_input_region(window->wl.surface, input_region);
        wl_region_destroy(input_region);

Yes, I've looked at this piece of code earlier, I, infact, commented out this piece of code and recompiled to check if it makes any difference in the Top layer.

But clearly, that in itself isn't enough to be transparent to events. I remember the main use of the top payer is captive UI such as screen lockers so maybe it's unavoidable, I'm not sure!

Yes, you're right, not enough to be transparent to events. The Top layer is usually for Panels, maybe notifications and lock screen that sort of things, the background layer is for desktop background and so on. I'm also adding a link to this talk which I found very informative: Drew DeVault - Building Wayland desktop components with layer shell (Demo Track)

Anyways, I will reach out to the people at wlroots and see if they have any insights regarding this issue - will post here if I gain further information regarding this particular issue.

bootkernel avatar Jul 30 '22 15:07 bootkernel

Per protocol, setting an empty input region should make the layer not receive pointer-like events: https://gitlab.freedesktop.org/wlroots/wlr-protocols/-/blob/master/unstable/wlr-layer-shell-unstable-v1.xml#L278-280

If it does, that looks like a compositor issue.

But It doesn't exist on GNOME, there are no plans to implement it , nor is there (as far as i could find) any equivalent there.

IMHO this is absolutely not a reason not to support this. Guhnome's developers are quite special and the only other way we have is to not support this at all. (KDE does support this protocol, btw)

There is an ext- version in the works, but it's very similiar to wlr, so if it eventually lands, it's pretty much just a matter of pasting a new xml and renaming some functions called. If Guhnome decides to support the ext- version, great, but there is still no guarantee.

Edit: Tested on latest Hyprland, the LS does not seem to receive input events. However, some layers might want that. (example: interactive wallpaper) Maybe we should make a flag/method for that?

What I'd also suggest is to use the unused title parameter as the namespace for the layerSurface, as currently it's hardcoded to "wallpaper"

vaxerski avatar Apr 15 '23 15:04 vaxerski

Have you checked if this functionality is available on other platforms? I found kCGDesktopWindowLevelKey for MacOS. I can check later if this suits the functionality of this PR.

ws909 avatar Apr 15 '23 20:04 ws909

If it is, we could just apply a more neutral-sounding name for the hint and push this one forwards, and then add support for other platforms in subsequent MRs.

vaxerski avatar Apr 15 '23 20:04 vaxerski

Several platforms (if not all?) have the concept of window levels. You can’t specify or query these in GLFW. Maybe instead of just supporting a single level as a hint, multiple levels/layers can be supported?

ws909 avatar Apr 15 '23 20:04 ws909

We could also do that, though there is a question about portability here, wayland supports 4, for instance. Windows/Mac/MS-DOS/whatever else might support a different number.

We could choose the one that supports the most and truncate others (e.g. if 4 is max and windows supports 2, 1,2 go to 1 and 3,4 go to 2)

vaxerski avatar Apr 15 '23 20:04 vaxerski

Well, we can either choose a conservative approach, and only expose those supported by all platforms. Or, we can support all, and emit GLFW_PLATFORM_UNAVAILABLE if the attempted level is unavailable, and clearly state the supported ones for each and all platforms in the documentation. We should gather a list of all supported modes for each platform before making a decision. Will come back to this later.

ws909 avatar Apr 15 '23 20:04 ws909

Sounds reasonable. If implementations across platforms are similiar enough, it would make sense to unify them. +1 Thanks!

vaxerski avatar Apr 15 '23 20:04 vaxerski

I opened a new issue for the cross-platform support, and gathering of information.

  • #2318

ws909 avatar Apr 16 '23 00:04 ws909