mortie / swaylock-effects

Swaylock, with fancy effects
MIT License
698 stars 44 forks source link

Feature request: launch subprocess to draw background #62

Open mstoeckl opened 3 years ago

mstoeckl commented 3 years ago

I was originally going to ask about a feature to rotate background images every N minutes, but now I think that would lead to a horribly complicated interface after a few years of feature expansion.

Instead, I would like to propose a plugin/subprocess architecture, in which swaylock-effects runs a background-drawing program (like swaybg, or a shell script to periodically rerun swaybg) inside a nested Wayland compositor, and uses the surfaces that the nested process provides to draw its own background. This can be done efficiently, because swaylock already uses a separate surface to draw the text and indicator icon, so it only has to provide the buffers already submitted by the subprogram .

To check that this is possible, I made a prototype! Expand for details. * Source code available at: https://github.com/mstoeckl/swaylock-plugin . It requires that the subprograms implement a rarely used but simple to implement protocol, [fullscreen-shell-unstable-v1](https://wayland.app/protocols/fullscreen-shell-unstable-v1) . I have a branch of swaybg which implements the protocol at mstoeckl/swaybg/fullscreen-shell, https://github.com/mstoeckl/swaybg/commit/24557b1758c96b45c750bca02785fe417be95bad . I also converted a few XScreenSaver backgrounds to run using this protocol, see https://git.sr.ht/~mstoeckl/wscreensaver , and have an animated background of my own at https://git.sr.ht/~mstoeckl/rwalkbg . * Example usage: `swaylock --command 'swaybg -i test.jpg'`, or `swaylock --command 'voronoi --wayland'`. * Limitations of the prototype: it doesn't have a way to restart the background process if it dies or replace it with a new swaybg. It does a weird and possibly unnecessary subsurface trick to render the background surface. It requires an Mesa-specific protocol to render OpenGL backgrounds. It does not support resizing or removing outputs at runtime. It doesn't support subprocesses that support only layer-shell. It is currently based on upstream swaylock, not on swaylock-effects, so the prototype lacks all of swaylock-effect's options. * Good things: it's not a very invasive change -- adding the nested Wayland server is a small change to the event loop, a few extra protocols in the build, a few extra struct fields, maybe 50 changed lines to existing functions, and about 800 lines which could safely be put in their own file. The nested compositor ensures that the background process does not receive any user input, and runs independently of swaylock, so swaylock can immediately start and listen for input instead of waiting for the background to load/screenshot to blur. Unfortunately, I can't guarantee that I will have time to bring my prototype to completion, but probably can do a 90%-correct fix for any of the above limitations if asked. The last 10% are tricky.

Since a subprocess implementation might add 500-2K lines of code, this is a rather large feature request; but hopefully something others are interested in and which could integrate well with current swaylock-effects.

girst commented 2 years ago

This is a great idea and I'd love to see this come to light (fancy screensavers is the only thing I miss from sway right now)!

First, some minor fixes:

  1. in your swaylock-effects fork: sed -i 1116s/free/fclose/ main.c
  2. in wscreensaver: sed -i /utils.h/d colors.c hsv.c

However, then I'm stuck linking all the wscreensaver hacks. For each hack, this is the error:

[5/21] Linking target voronoi
FAILED: voronoi
cc  -o voronoi voronoi.p/voronoi.c.o voronoi.p/colors.c.o voronoi.p/hsv.c.o -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group libmain_lib.a /usr/lib64/libwayland-client.so -pthread /usr/lib64/libSDL2.so -lm /usr/lib64/libGL.so /usr/lib64/libGLU.so /usr/lib64/libwayland-egl.so /usr/lib64/libEGL.so /usr/lib64/libpng16.so /usr/lib64/libz.so -Wl,--end-group
/usr/bin/ld: libmain_lib.a(meson-generated_wlr-layer-shell-unstable-v1-protocol.c.o):(.data.rel+0x48): undefined reference to `xdg_popup_interface'
collect2: error: ld returned 1 exit status
[7/21] Compiling C object flurry.p/flurry-spark.c.o
ninja: build stopped: subcommand failed.

xdg_popup_interface is declared extern in wlr-layer-shell-unstable-v1-protocol.c; removing the extern makes it link, but then crashes the whole sway session on exit when used with swaylock.

What's the proper way to solve this?

mstoeckl commented 2 years ago

What's the proper way to solve this?

This was an issue where the generated files for the wlr-layer-shell-unstable-v1 protocol had a dependency on the files that would be generated for the xdg-shell protocol ; I've added the xdg-shell protocol to the build. I've also updated the fullscreen-plugin branch.

mstoeckl commented 1 year ago

I've decided to maintain a fork of the original swaylock which provides this feature; see https://github.com/mstoeckl/swaylock-plugin .