feat(session): start graphical-session.target through a systemd user unit (#21)
- commit
- 509f0eb677592fba8de2ecb32925b564be063512
- author
- bnema · · 2026-09-27 14:15 UTC
- committer
- GitHub · · 2026-09-27 14:15 UTC
- parent
- 3e6f9e9
- signature
- GPG Unverified
B5690EEEBB952194The key is unknown
11 files · +92 -4
M README.md +1 -1
| @@ -77,7 +77,7 @@ make pkg # builds dist/neferwl-*.pkg.tar.zst fr | |||
| 77 | 77 | sudo pacman -U dist/neferwl-*.pkg.tar.zst | |
| 78 | 78 | ``` | |
| 79 | 79 | ||
| 80 | - | The package installs `neferwl` and a **NeferWL** session for display managers such as Ly, GDM and SDDM. The session runs `neferwl --session`, which passes `WAYLAND_DISPLAY` and `DISPLAY` to D-Bus and systemd user services so that portals and notification daemons can connect. | |
| 80 | + | The package installs `neferwl` and a **NeferWL** session for display managers such as Ly, GDM and SDDM. The session runs `neferwl-session`, which starts `neferwl.service` under systemd. This starts `graphical-session.target` and services bound to it (bars, notification daemons, portals, and XDG autostart) with NeferWL and stops them with it. Running `neferwl --session` alone still exports the display environment to D-Bus and systemd user services. | |
| 81 | 81 | ||
| 82 | 82 | On other distributions, `make build` builds `bin/neferwl`. | |
| 83 | 83 | ||
| @@ -77,7 +77,7 @@ make pkg # builds dist/neferwl-*.pkg.tar.zst fr | |||||
| 77 | sudo pacman -U dist/neferwl-*.pkg.tar.zst | 77 | sudo pacman -U dist/neferwl-*.pkg.tar.zst | ||
| 78 | ``` | 78 | ``` | ||
| 79 | 79 | ||||
| 80 | - | The package installs `neferwl` and a **NeferWL** session for display managers such as Ly, GDM and SDDM. The session runs `neferwl --session`, which passes `WAYLAND_DISPLAY` and `DISPLAY` to D-Bus and systemd user services so that portals and notification daemons can connect. | 80 | + | The package installs `neferwl` and a **NeferWL** session for display managers such as Ly, GDM and SDDM. The session runs `neferwl-session`, which starts `neferwl.service` under systemd. This starts `graphical-session.target` and services bound to it (bars, notification daemons, portals, and XDG autostart) with NeferWL and stops them with it. Running `neferwl --session` alone still exports the display environment to D-Bus and systemd user services. |
| 81 | 81 | ||||
| 82 | On other distributions, `make build` builds `bin/neferwl`. | 82 | On other distributions, `make build` builds `bin/neferwl`. | ||
| 83 | 83 | ||||
M cmd/neferwl/main.go +1 -1
| @@ -122,7 +122,7 @@ func run() error { | |||
| 122 | 122 | timeout := flags.Duration("timeout", 0, "duration before exit (0 disables timeout)") | |
| 123 | 123 | debugFlag := flags.String("debug", "", "debug components (comma-separated or all; input-motion logs every pointer motion)") | |
| 124 | 124 | configFlag := flags.String("config", "", "config path (empty uses XDG default)") | |
| 125 | - | session := flags.Bool("session", false, "run as the login session: share WAYLAND_DISPLAY and DISPLAY with systemd and D-Bus user services") | |
| 125 | + | session := flags.Bool("session", false, "run as the login session: share WAYLAND_DISPLAY and DISPLAY with systemd and D-Bus user services; notify systemd when ready") | |
| 126 | 126 | if err := flags.Parse(os.Args[1:]); err != nil { | |
| 127 | 127 | if errors.Is(err, flag.ErrHelp) { | |
| 128 | 128 | return err | |
| @@ -122,7 +122,7 @@ func run() error { | |||||
| 122 | timeout := flags.Duration("timeout", 0, "duration before exit (0 disables timeout)") | 122 | timeout := flags.Duration("timeout", 0, "duration before exit (0 disables timeout)") | ||
| 123 | debugFlag := flags.String("debug", "", "debug components (comma-separated or all; input-motion logs every pointer motion)") | 123 | debugFlag := flags.String("debug", "", "debug components (comma-separated or all; input-motion logs every pointer motion)") | ||
| 124 | configFlag := flags.String("config", "", "config path (empty uses XDG default)") | 124 | configFlag := flags.String("config", "", "config path (empty uses XDG default)") | ||
| 125 | - | session := flags.Bool("session", false, "run as the login session: share WAYLAND_DISPLAY and DISPLAY with systemd and D-Bus user services") | 125 | + | session := flags.Bool("session", false, "run as the login session: share WAYLAND_DISPLAY and DISPLAY with systemd and D-Bus user services; notify systemd when ready") |
| 126 | if err := flags.Parse(os.Args[1:]); err != nil { | 126 | if err := flags.Parse(os.Args[1:]); err != nil { | ||
| 127 | if errors.Is(err, flag.ErrHelp) { | 127 | if errors.Is(err, flag.ErrHelp) { | ||
| 128 | return err | 128 | return err | ||
M internal/adapters/launcher/launcher_test.go +1 -1
| @@ -14,7 +14,7 @@ import ( | |||
| 14 | 14 | ) | |
| 15 | 15 | ||
| 16 | 16 | func TestChildEnv(t *testing.T) { | |
| 17 | - | got := ChildEnv([]string{"TERM=x", "DISPLAY=:0", "WAYLAND_SOCKET=4", "WAYLAND_DISPLAY=old", "HOME=/home/me", "PATH=/bin", "LC_ALL=C", "XDG_RUNTIME_DIR=old", "XCURSOR_THEME=Adwaita", "XCURSOR_PATH=/icons", "SECRET=bad", "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/me/bus"}, "wayland-7", "/run/me", 24) | |
| 17 | + | got := ChildEnv([]string{"TERM=x", "DISPLAY=:0", "WAYLAND_SOCKET=4", "WAYLAND_DISPLAY=old", "HOME=/home/me", "PATH=/bin", "LC_ALL=C", "XDG_RUNTIME_DIR=old", "XCURSOR_THEME=Adwaita", "XCURSOR_PATH=/icons", "SECRET=bad", "NOTIFY_SOCKET=/tmp/notify", "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/me/bus"}, "wayland-7", "/run/me", 24) | |
| 18 | 18 | want := []string{"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/me/bus", "HOME=/home/me", "LC_ALL=C", "PATH=/bin", "WAYLAND_DISPLAY=wayland-7", "XCURSOR_PATH=/icons", "XCURSOR_SIZE=24", "XCURSOR_THEME=Adwaita", "XDG_CURRENT_DESKTOP=neferwl", "XDG_RUNTIME_DIR=/run/me", "XDG_SESSION_TYPE=wayland"} | |
| 19 | 19 | if !reflect.DeepEqual(got, want) { | |
| 20 | 20 | t.Fatalf("got %v want %v", got, want) | |
| @@ -14,7 +14,7 @@ import ( | |||||
| 14 | ) | 14 | ) | ||
| 15 | 15 | ||||
| 16 | func TestChildEnv(t *testing.T) { | 16 | func TestChildEnv(t *testing.T) { | ||
| 17 | - | got := ChildEnv([]string{"TERM=x", "DISPLAY=:0", "WAYLAND_SOCKET=4", "WAYLAND_DISPLAY=old", "HOME=/home/me", "PATH=/bin", "LC_ALL=C", "XDG_RUNTIME_DIR=old", "XCURSOR_THEME=Adwaita", "XCURSOR_PATH=/icons", "SECRET=bad", "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/me/bus"}, "wayland-7", "/run/me", 24) | 17 | + | got := ChildEnv([]string{"TERM=x", "DISPLAY=:0", "WAYLAND_SOCKET=4", "WAYLAND_DISPLAY=old", "HOME=/home/me", "PATH=/bin", "LC_ALL=C", "XDG_RUNTIME_DIR=old", "XCURSOR_THEME=Adwaita", "XCURSOR_PATH=/icons", "SECRET=bad", "NOTIFY_SOCKET=/tmp/notify", "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/me/bus"}, "wayland-7", "/run/me", 24) |
| 18 | want := []string{"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/me/bus", "HOME=/home/me", "LC_ALL=C", "PATH=/bin", "WAYLAND_DISPLAY=wayland-7", "XCURSOR_PATH=/icons", "XCURSOR_SIZE=24", "XCURSOR_THEME=Adwaita", "XDG_CURRENT_DESKTOP=neferwl", "XDG_RUNTIME_DIR=/run/me", "XDG_SESSION_TYPE=wayland"} | 18 | want := []string{"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/me/bus", "HOME=/home/me", "LC_ALL=C", "PATH=/bin", "WAYLAND_DISPLAY=wayland-7", "XCURSOR_PATH=/icons", "XCURSOR_SIZE=24", "XCURSOR_THEME=Adwaita", "XDG_CURRENT_DESKTOP=neferwl", "XDG_RUNTIME_DIR=/run/me", "XDG_SESSION_TYPE=wayland"} | ||
| 19 | if !reflect.DeepEqual(got, want) { | 19 | if !reflect.DeepEqual(got, want) { | ||
| 20 | t.Fatalf("got %v want %v", got, want) | 20 | t.Fatalf("got %v want %v", got, want) | ||
M internal/adapters/launcher/session.go +19 -0
| @@ -2,6 +2,7 @@ package launcher | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "context" | |
| 5 | + | "net" | |
| 5 | 6 | "os/exec" | |
| 6 | 7 | "time" | |
| 7 | 8 | ||
| @@ -50,3 +51,21 @@ func runSessionCommand(ctx context.Context, env []string, log zerowrap.Logger, a | |||
| 50 | 51 | } | |
| 51 | 52 | log.Info().Strs("vars", sessionVars).Msg(done) | |
| 52 | 53 | } | |
| 54 | + | ||
| 55 | + | // NotifyReady tells the systemd user manager that the compositor is ready. | |
| 56 | + | func NotifyReady(socket string, log zerowrap.Logger) { | |
| 57 | + | if socket == "" { | |
| 58 | + | return | |
| 59 | + | } | |
| 60 | + | conn, err := net.DialUnix("unixgram", nil, &net.UnixAddr{Name: socket, Net: "unixgram"}) | |
| 61 | + | if err != nil { | |
| 62 | + | log.Warn().Err(err).Msg("session readiness notification failed") | |
| 63 | + | return | |
| 64 | + | } | |
| 65 | + | defer conn.Close() | |
| 66 | + | if _, err := conn.Write([]byte("READY=1")); err != nil { | |
| 67 | + | log.Warn().Err(err).Msg("session readiness notification failed") | |
| 68 | + | return | |
| 69 | + | } | |
| 70 | + | log.Info().Msg("session ready") | |
| 71 | + | } | |
| @@ -2,6 +2,7 @@ package launcher | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "context" | 4 | "context" | ||
| 5 | + | "net" | |||
| 5 | "os/exec" | 6 | "os/exec" | ||
| 6 | "time" | 7 | "time" | ||
| 7 | 8 | ||||
| @@ -50,3 +51,21 @@ func runSessionCommand(ctx context.Context, env []string, log zerowrap.Logger, a | |||||
| 50 | } | 51 | } | ||
| 51 | log.Info().Strs("vars", sessionVars).Msg(done) | 52 | log.Info().Strs("vars", sessionVars).Msg(done) | ||
| 52 | } | 53 | } | ||
| 54 | + | ||||
| 55 | + | // NotifyReady tells the systemd user manager that the compositor is ready. | |||
| 56 | + | func NotifyReady(socket string, log zerowrap.Logger) { | |||
| 57 | + | if socket == "" { | |||
| 58 | + | return | |||
| 59 | + | } | |||
| 60 | + | conn, err := net.DialUnix("unixgram", nil, &net.UnixAddr{Name: socket, Net: "unixgram"}) | |||
| 61 | + | if err != nil { | |||
| 62 | + | log.Warn().Err(err).Msg("session readiness notification failed") | |||
| 63 | + | return | |||
| 64 | + | } | |||
| 65 | + | defer conn.Close() | |||
| 66 | + | if _, err := conn.Write([]byte("READY=1")); err != nil { | |||
| 67 | + | log.Warn().Err(err).Msg("session readiness notification failed") | |||
| 68 | + | return | |||
| 69 | + | } | |||
| 70 | + | log.Info().Msg("session ready") | |||
| 71 | + | } | |||
M internal/adapters/launcher/session_test.go +26 -0
| @@ -2,10 +2,12 @@ package launcher | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "context" | |
| 5 | + | "net" | |
| 5 | 6 | "os" | |
| 6 | 7 | "path/filepath" | |
| 7 | 8 | "strings" | |
| 8 | 9 | "testing" | |
| 10 | + | "time" | |
| 9 | 11 | ||
| 10 | 12 | "github.com/bnema/neferwl/internal/logging" | |
| 11 | 13 | ) | |
| @@ -40,3 +42,27 @@ func TestExportSession(t *testing.T) { | |||
| 40 | 42 | t.Fatal(string(data)) | |
| 41 | 43 | } | |
| 42 | 44 | } | |
| 45 | + | ||
| 46 | + | func TestNotifyReady(t *testing.T) { | |
| 47 | + | ctx := context.Background() | |
| 48 | + | log := logging.For(ctx, "launcher") | |
| 49 | + | NotifyReady("", log) | |
| 50 | + | path := filepath.Join(t.TempDir(), "notify") | |
| 51 | + | listener, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Name: path, Net: "unixgram"}) | |
| 52 | + | if err != nil { | |
| 53 | + | t.Fatal(err) | |
| 54 | + | } | |
| 55 | + | defer listener.Close() | |
| 56 | + | NotifyReady(path, log) | |
| 57 | + | if err := listener.SetReadDeadline(time.Now().Add(time.Second)); err != nil { | |
| 58 | + | t.Fatal(err) | |
| 59 | + | } | |
| 60 | + | buf := make([]byte, 64) | |
| 61 | + | n, _, err := listener.ReadFromUnix(buf) | |
| 62 | + | if err != nil { | |
| 63 | + | t.Fatal(err) | |
| 64 | + | } | |
| 65 | + | if string(buf[:n]) != "READY=1" { | |
| 66 | + | t.Fatalf("notification: %q", buf[:n]) | |
| 67 | + | } | |
| 68 | + | } | |
| @@ -2,10 +2,12 @@ package launcher | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "context" | 4 | "context" | ||
| 5 | + | "net" | |||
| 5 | "os" | 6 | "os" | ||
| 6 | "path/filepath" | 7 | "path/filepath" | ||
| 7 | "strings" | 8 | "strings" | ||
| 8 | "testing" | 9 | "testing" | ||
| 10 | + | "time" | |||
| 9 | 11 | ||||
| 10 | "github.com/bnema/neferwl/internal/logging" | 12 | "github.com/bnema/neferwl/internal/logging" | ||
| 11 | ) | 13 | ) | ||
| @@ -40,3 +42,27 @@ func TestExportSession(t *testing.T) { | |||||
| 40 | t.Fatal(string(data)) | 42 | t.Fatal(string(data)) | ||
| 41 | } | 43 | } | ||
| 42 | } | 44 | } | ||
| 45 | + | ||||
| 46 | + | func TestNotifyReady(t *testing.T) { | |||
| 47 | + | ctx := context.Background() | |||
| 48 | + | log := logging.For(ctx, "launcher") | |||
| 49 | + | NotifyReady("", log) | |||
| 50 | + | path := filepath.Join(t.TempDir(), "notify") | |||
| 51 | + | listener, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Name: path, Net: "unixgram"}) | |||
| 52 | + | if err != nil { | |||
| 53 | + | t.Fatal(err) | |||
| 54 | + | } | |||
| 55 | + | defer listener.Close() | |||
| 56 | + | NotifyReady(path, log) | |||
| 57 | + | if err := listener.SetReadDeadline(time.Now().Add(time.Second)); err != nil { | |||
| 58 | + | t.Fatal(err) | |||
| 59 | + | } | |||
| 60 | + | buf := make([]byte, 64) | |||
| 61 | + | n, _, err := listener.ReadFromUnix(buf) | |||
| 62 | + | if err != nil { | |||
| 63 | + | t.Fatal(err) | |||
| 64 | + | } | |||
| 65 | + | if string(buf[:n]) != "READY=1" { | |||
| 66 | + | t.Fatalf("notification: %q", buf[:n]) | |||
| 67 | + | } | |||
| 68 | + | } | |||
M internal/app/app.go +1 -0
| @@ -133,6 +133,7 @@ func run(ctx context.Context, opts Options, inject func(chan<- ports.InputEvent) | |||
| 133 | 133 | } | |
| 134 | 134 | if opts.Session { | |
| 135 | 135 | launcher.ExportSession(ctx, childEnv, logging.For(ctx, "launcher")) | |
| 136 | + | launcher.NotifyReady(os.Getenv("NOTIFY_SOCKET"), logging.For(ctx, "launcher")) | |
| 136 | 137 | defer launcher.UnexportSession(childEnv, logging.For(ctx, "launcher")) | |
| 137 | 138 | } | |
| 138 | 139 | child := launcher.New(childEnv, logging.For(ctx, "launcher")) | |
| @@ -133,6 +133,7 @@ func run(ctx context.Context, opts Options, inject func(chan<- ports.InputEvent) | |||||
| 133 | } | 133 | } | ||
| 134 | if opts.Session { | 134 | if opts.Session { | ||
| 135 | launcher.ExportSession(ctx, childEnv, logging.For(ctx, "launcher")) | 135 | launcher.ExportSession(ctx, childEnv, logging.For(ctx, "launcher")) | ||
| 136 | + | launcher.NotifyReady(os.Getenv("NOTIFY_SOCKET"), logging.For(ctx, "launcher")) | |||
| 136 | defer launcher.UnexportSession(childEnv, logging.For(ctx, "launcher")) | 137 | defer launcher.UnexportSession(childEnv, logging.For(ctx, "launcher")) | ||
| 137 | } | 138 | } | ||
| 138 | child := launcher.New(childEnv, logging.For(ctx, "launcher")) | 139 | child := launcher.New(childEnv, logging.For(ctx, "launcher")) | ||
M packaging/arch/PKGBUILD +3 -0
| @@ -39,6 +39,9 @@ check() { | |||
| 39 | 39 | package() { | |
| 40 | 40 | cd "$pkgname-$pkgver" | |
| 41 | 41 | install -Dm755 neferwl "$pkgdir/usr/bin/neferwl" | |
| 42 | + | install -Dm755 packaging/neferwl-session "$pkgdir/usr/bin/neferwl-session" | |
| 43 | + | install -Dm644 packaging/neferwl.service "$pkgdir/usr/lib/systemd/user/neferwl.service" | |
| 44 | + | install -Dm644 packaging/neferwl-shutdown.target "$pkgdir/usr/lib/systemd/user/neferwl-shutdown.target" | |
| 42 | 45 | install -Dm644 packaging/neferwl.desktop "$pkgdir/usr/share/wayland-sessions/neferwl.desktop" | |
| 43 | 46 | install -Dm644 packaging/neferwl-portals.conf "$pkgdir/usr/share/xdg-desktop-portal/neferwl-portals.conf" | |
| 44 | 47 | install -Dm644 examples/config "$pkgdir/usr/share/doc/neferwl/config.example" | |
| @@ -39,6 +39,9 @@ check() { | |||||
| 39 | package() { | 39 | package() { | ||
| 40 | cd "$pkgname-$pkgver" | 40 | cd "$pkgname-$pkgver" | ||
| 41 | install -Dm755 neferwl "$pkgdir/usr/bin/neferwl" | 41 | install -Dm755 neferwl "$pkgdir/usr/bin/neferwl" | ||
| 42 | + | install -Dm755 packaging/neferwl-session "$pkgdir/usr/bin/neferwl-session" | |||
| 43 | + | install -Dm644 packaging/neferwl.service "$pkgdir/usr/lib/systemd/user/neferwl.service" | |||
| 44 | + | install -Dm644 packaging/neferwl-shutdown.target "$pkgdir/usr/lib/systemd/user/neferwl-shutdown.target" | |||
| 42 | install -Dm644 packaging/neferwl.desktop "$pkgdir/usr/share/wayland-sessions/neferwl.desktop" | 45 | install -Dm644 packaging/neferwl.desktop "$pkgdir/usr/share/wayland-sessions/neferwl.desktop" | ||
| 43 | install -Dm644 packaging/neferwl-portals.conf "$pkgdir/usr/share/xdg-desktop-portal/neferwl-portals.conf" | 46 | install -Dm644 packaging/neferwl-portals.conf "$pkgdir/usr/share/xdg-desktop-portal/neferwl-portals.conf" | ||
| 44 | install -Dm644 examples/config "$pkgdir/usr/share/doc/neferwl/config.example" | 47 | install -Dm644 examples/config "$pkgdir/usr/share/doc/neferwl/config.example" | ||
A packaging/neferwl-session +19 -0
| @@ -0,0 +1,19 @@ | |||
| 1 | + | #!/bin/sh | |
| 2 | + | if [ "${1:-}" != '-l' ] && [ -n "${SHELL:-}" ] && [ -x "$SHELL" ] && grep -Fxq "$SHELL" /etc/shells; then | |
| 3 | + | case "$SHELL" in | |
| 4 | + | */false|*/nologin) ;; | |
| 5 | + | *) exec "$SHELL" -l -c 'exec neferwl-session -l' ;; | |
| 6 | + | esac | |
| 7 | + | fi | |
| 8 | + | if systemctl --user -q is-active neferwl.service; then | |
| 9 | + | echo 'A NeferWL session is already running.' >&2 | |
| 10 | + | exit 1 | |
| 11 | + | fi | |
| 12 | + | systemctl --user reset-failed | |
| 13 | + | systemctl --user import-environment | |
| 14 | + | if command -v dbus-update-activation-environment >/dev/null 2>&1; then | |
| 15 | + | dbus-update-activation-environment --all | |
| 16 | + | fi | |
| 17 | + | systemctl --user --wait start neferwl.service | |
| 18 | + | systemctl --user start --job-mode=replace-irreversibly neferwl-shutdown.target | |
| 19 | + | systemctl --user unset-environment WAYLAND_DISPLAY DISPLAY XDG_SESSION_TYPE XDG_CURRENT_DESKTOP NEFERWL_STATE | |
| @@ -0,0 +1,19 @@ | |||||
| 1 | + | #!/bin/sh | |||
| 2 | + | if [ "${1:-}" != '-l' ] && [ -n "${SHELL:-}" ] && [ -x "$SHELL" ] && grep -Fxq "$SHELL" /etc/shells; then | |||
| 3 | + | case "$SHELL" in | |||
| 4 | + | */false|*/nologin) ;; | |||
| 5 | + | *) exec "$SHELL" -l -c 'exec neferwl-session -l' ;; | |||
| 6 | + | esac | |||
| 7 | + | fi | |||
| 8 | + | if systemctl --user -q is-active neferwl.service; then | |||
| 9 | + | echo 'A NeferWL session is already running.' >&2 | |||
| 10 | + | exit 1 | |||
| 11 | + | fi | |||
| 12 | + | systemctl --user reset-failed | |||
| 13 | + | systemctl --user import-environment | |||
| 14 | + | if command -v dbus-update-activation-environment >/dev/null 2>&1; then | |||
| 15 | + | dbus-update-activation-environment --all | |||
| 16 | + | fi | |||
| 17 | + | systemctl --user --wait start neferwl.service | |||
| 18 | + | systemctl --user start --job-mode=replace-irreversibly neferwl-shutdown.target | |||
| 19 | + | systemctl --user unset-environment WAYLAND_DISPLAY DISPLAY XDG_SESSION_TYPE XDG_CURRENT_DESKTOP NEFERWL_STATE | |||
A packaging/neferwl-shutdown.target +6 -0
| @@ -0,0 +1,6 @@ | |||
| 1 | + | [Unit] | |
| 2 | + | Description=Shutdown running NeferWL session | |
| 3 | + | DefaultDependencies=no | |
| 4 | + | StopWhenUnneeded=true | |
| 5 | + | Conflicts=graphical-session.target graphical-session-pre.target | |
| 6 | + | After=graphical-session.target graphical-session-pre.target | |
| @@ -0,0 +1,6 @@ | |||||
| 1 | + | [Unit] | |||
| 2 | + | Description=Shutdown running NeferWL session | |||
| 3 | + | DefaultDependencies=no | |||
| 4 | + | StopWhenUnneeded=true | |||
| 5 | + | Conflicts=graphical-session.target graphical-session-pre.target | |||
| 6 | + | After=graphical-session.target graphical-session-pre.target | |||
M packaging/neferwl.desktop +1 -1
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | [Desktop Entry] | |
| 2 | 2 | Name=NeferWL | |
| 3 | 3 | Comment=Minimal Wayland compositor with column tiling | |
| 4 | - | Exec=neferwl --session | |
| 4 | + | Exec=neferwl-session | |
| 5 | 5 | Type=Application | |
| 6 | 6 | DesktopNames=neferwl | |
| @@ -1,6 +1,6 @@ | |||||
| 1 | [Desktop Entry] | 1 | [Desktop Entry] | ||
| 2 | Name=NeferWL | 2 | Name=NeferWL | ||
| 3 | Comment=Minimal Wayland compositor with column tiling | 3 | Comment=Minimal Wayland compositor with column tiling | ||
| 4 | - | Exec=neferwl --session | 4 | + | Exec=neferwl-session |
| 5 | Type=Application | 5 | Type=Application | ||
| 6 | DesktopNames=neferwl | 6 | DesktopNames=neferwl | ||
A packaging/neferwl.service +14 -0
| @@ -0,0 +1,14 @@ | |||
| 1 | + | [Unit] | |
| 2 | + | Description=NeferWL Wayland compositor | |
| 3 | + | Documentation=https://github.com/bnema/neferwl | |
| 4 | + | BindsTo=graphical-session.target | |
| 5 | + | Before=graphical-session.target | |
| 6 | + | Wants=graphical-session-pre.target | |
| 7 | + | After=graphical-session-pre.target | |
| 8 | + | Wants=xdg-desktop-autostart.target | |
| 9 | + | Before=xdg-desktop-autostart.target | |
| 10 | + | ||
| 11 | + | [Service] | |
| 12 | + | Slice=session.slice | |
| 13 | + | Type=notify | |
| 14 | + | ExecStart=/usr/bin/neferwl --session | |
| @@ -0,0 +1,14 @@ | |||||
| 1 | + | [Unit] | |||
| 2 | + | Description=NeferWL Wayland compositor | |||
| 3 | + | Documentation=https://github.com/bnema/neferwl | |||
| 4 | + | BindsTo=graphical-session.target | |||
| 5 | + | Before=graphical-session.target | |||
| 6 | + | Wants=graphical-session-pre.target | |||
| 7 | + | After=graphical-session-pre.target | |||
| 8 | + | Wants=xdg-desktop-autostart.target | |||
| 9 | + | Before=xdg-desktop-autostart.target | |||
| 10 | + | ||||
| 11 | + | [Service] | |||
| 12 | + | Slice=session.slice | |||
| 13 | + | Type=notify | |||
| 14 | + | ExecStart=/usr/bin/neferwl --session | |||