diff --git a/patches/systemd/README.md b/patches/systemd/README.md new file mode 100644 index 0000000..a861b5e --- /dev/null +++ b/patches/systemd/README.md @@ -0,0 +1,33 @@ +### Description +This is a simple patch that runs `systemctl --user import-environment WAYLAND_DISPLAY DISPLAY`, and `systemctl --user start dwl-session.target` after Dwl initializes, and then `systemctl --user stop dwl-session.target` when Dwl quits. This allows you to handle graceful startup and shutdown of your graphical systemd services, with the proper environment variables set. This is similar to [uwsm](https://github.com/Vladimir-csp/uwsm?tab=readme-ov-file), but it integrates natively with your existing systemd user services, and doesn't have uwsm's runtime overhead. + +You must have a `dwl-session.target` created that binds to `graphical-session.target`. You can then set the WantedBy of your systemd services to either `graphical-session.target`, or `dwl-session.target`, depending on whether you want them to start for just Dwl, or for every graphical session. + +Below is the Nix home-manager configuration I use to generate `dwl-session.target`, and its resulting output. +``` +systemd.user.targets.dwl-session.Unit = { + Description = "dwl compositor session"; + Documentation = [ "man:systemd.special(7)" ]; + BindsTo = [ "graphical-session.target" ]; + Wants = [ "graphical-session-pre.target" ]; + After = [ "graphical-session-pre.target" ]; +}; +``` + +``` +[Unit] +After=graphical-session-pre.target +BindsTo=graphical-session.target +Description=dwl compositor session +Documentation=man:systemd.special(7) +Wants=graphical-session-pre.target +``` + +### Download +- [git branch](https://github.com/Shringe/dwl/tree/systemd) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/systemd/systemd-0.7.patch) + +### Authors +- [Shringe](https://codeberg.org/Shringe) +- shringe_ at [dwl Discord](https://discord.gg/jJxZnrGPWN) + diff --git a/patches/systemd/systemd-0.7.patch b/patches/systemd/systemd-0.7.patch new file mode 100644 index 0000000..f911997 --- /dev/null +++ b/patches/systemd/systemd-0.7.patch @@ -0,0 +1,64 @@ +From 43b3026b0744d54287eada71c84ea8be174950c3 Mon Sep 17 00:00:00 2001 +From: Shringe +Date: Sat, 12 Jul 2025 01:00:46 -0500 +Subject: [PATCH] basic implementation + +--- + dwl.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/dwl.c b/dwl.c +index c717c1d..4ba134d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -680,6 +680,15 @@ cleanup(void) + wlr_xwayland_destroy(xwayland); + xwayland = NULL; + #endif ++ /* Stop systemd target */ ++ if (fork() == 0) { ++ setsid(); ++ execvp("systemctl", (char *const[]) { ++ "systemctl", "--user", "stop", "dwl-session.target", NULL ++ }); ++ exit(1); ++ } ++ + wl_display_destroy_clients(dpy); + if (child_pid > 0) { + kill(-child_pid, SIGTERM); +@@ -2222,6 +2231,31 @@ run(char *startup_cmd) + die("startup: display_add_socket_auto"); + setenv("WAYLAND_DISPLAY", socket, 1); + ++ /* Import environment variables then start systemd target */ ++ if (fork() == 0) { ++ setsid(); ++ ++ /* First: import environment variables */ ++ pid_t import_pid = fork(); ++ if (import_pid == 0) { ++ execvp("systemctl", (char *const[]) { ++ "systemctl", "--user", "import-environment", ++ "DISPLAY", "WAYLAND_DISPLAY", NULL ++ }); ++ exit(1); ++ } ++ ++ /* Wait for import to complete */ ++ waitpid(import_pid, NULL, 0); ++ ++ /* Second: start target */ ++ execvp("systemctl", (char *const[]) { ++ "systemctl", "--user", "start", "dwl-session.target", NULL ++ }); ++ ++ exit(1); ++ } ++ + /* Start the backend. This will enumerate outputs and inputs, become the DRM + * master, etc */ + if (!wlr_backend_start(backend)) +-- +2.49.0 +