From 93343775bd2c4a4afc573e842f24ef08bf350895 Mon Sep 17 00:00:00 2001 From: John Titor <50095635+JohnRTitor@users.noreply.github.com> Date: Sun, 18 Aug 2024 19:22:34 +0530 Subject: [PATCH] nixos/uwsm: init [UWSM](https://github.com/Vladimir-csp/uwsm) is a session manager that wraps a wayland window compositor with useful systemd units like `graphical-session-pre.target`, `graphical-session.target`, `xdg-desktop-autostart.target`. This is useful for Wayland Compositors that do not start these units on these own. Example for Hyprland: ```nix programs.hyprland.enable = true; programs.uwsm.enable = true; programs.uwsm.waylandCompositors = { hyprland = { compositorPrettyName = "Hyprland"; compositorComment = "Hyprland compositor managed by UWSM"; compositorBinPath = "/run/current-system/sw/bin/Hyprland"; }; }; ``` Co-authored-by: Kai Norman Clasen --- .../manual/release-notes/rl-2411.section.md | 2 + nixos/modules/module-list.nix | 1 + nixos/modules/programs/wayland/uwsm.nix | 129 ++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 nixos/modules/programs/wayland/uwsm.nix diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md index e4b366b70528..61343d9287bc 100644 --- a/nixos/doc/manual/release-notes/rl-2411.section.md +++ b/nixos/doc/manual/release-notes/rl-2411.section.md @@ -33,6 +33,8 @@ - [Goatcounter](https://www.goatcounter.com/), Easy web analytics. No tracking of personal data. Available as [services.goatcounter](options.html#opt-services.goatcocunter.enable). +- [UWSM](https://github.com/Vladimir-csp/uwsm), a wayland session manager to wrap Wayland Compositors into useful systemd units such as `graphical-session.target`. Available as [programs.uwsm](#opt-programs.uwsm.enable). + - [Open-WebUI](https://github.com/open-webui/open-webui), a user-friendly WebUI for LLMs. Available as [services.open-webui](#opt-services.open-webui.enable) service. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 9b8c627d4e1d..a20b52b2e4ce 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -310,6 +310,7 @@ ./programs/wayland/miracle-wm.nix ./programs/wayland/river.nix ./programs/wayland/sway.nix + ./programs/wayland/uwsm.nix ./programs/wayland/waybar.nix ./programs/wayland/wayfire.nix ./programs/weylus.nix diff --git a/nixos/modules/programs/wayland/uwsm.nix b/nixos/modules/programs/wayland/uwsm.nix new file mode 100644 index 000000000000..5497cc269ebe --- /dev/null +++ b/nixos/modules/programs/wayland/uwsm.nix @@ -0,0 +1,129 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.programs.uwsm; + + # Helper function to create desktop entry files for UWSM-managed compositors + mk_uwsm_desktop_entry = + opts: + (pkgs.writeTextFile { + name = "${opts.name}-uwsm"; + text = '' + [Desktop Entry] + Name=${opts.prettyName} (UWSM) + Comment=${opts.comment} + Exec=${lib.getExe cfg.package} start -S -F ${opts.binPath} + Type=Application + ''; + destination = "/share/wayland-sessions/${opts.name}-uwsm.desktop"; + derivationArgs = { + passthru.providedSessions = [ "${opts.name}-uwsm" ]; + }; + }); +in +{ + options.programs.uwsm = { + enable = lib.mkEnableOption '' + uwsm, which wraps standalone Wayland compositors with a set + of Systemd units on the fly. This essentially + binds the wayland compositor into `graphical-session-pre.target`, + `graphical-session.target`, `xdg-desktop-autostart.target`. + + This is useful for Wayland compositors like Hyprland, Sway, Wayfire, + etc. that do not start these targets and services on their own. + + ::: {.note} + You must configure `waylandCompositors` suboptions as well + so that UWSM knows which compositors to manage. + + Additionally, this by default uses `dbus-broker` as the dbus + implementation for better compatibility. If you dislike this behavior + you can set `services.dbus.implementation = lib.mkForce "dbus"` + in your configuration. + ::: + + If you are having trouble starting a service that depends on + `graphical-session.target`, while using a WM, enabling this option + might help + ''; + package = lib.mkPackageOption pkgs "uwsm" { }; + + waylandCompositors = lib.mkOption { + description = '' + Configuration for UWSM-managed Wayland Compositors. This + creates a desktop entry file which will be used by Display + Managers like GDM, to allow starting the UWSM managed session. + ''; + type = lib.types.attrsOf ( + lib.types.submodule ( + { ... }: + { + options = { + prettyName = lib.mkOption { + type = lib.types.str; + description = "The full name of the desktop entry file."; + example = "ExampleWaylandCompositor"; + }; + comment = lib.mkOption { + type = lib.types.str; + description = "The comment field of the desktop entry file."; + default = "An intelligent Wayland compositor managed by UWSM."; + }; + binPath = lib.mkOption { + type = lib.types.path; + description = '' + The wayland-compositor binary path that will be called by UWSM. + + It is recommended to use the `/run/current-system/sw/bin/` path + instead of `lib.getExe pkgs.` to avoid version mismatch + of the compositor used by UWSM and the one installed in the system. + ''; + example = "/run/current-system/sw/bin/ExampleCompositor"; + }; + }; + } + ) + ); + example = lib.literalExpression '' + hyprland = { + prettyName = "Hyprland"; + comment = "Hyprland compositor managed by UWSM"; + binPath = "/run/current-system/sw/bin/Hyprland"; + }; + sway = { + prettyName = "Sway"; + comment = "Sway compositor managed by UWSM"; + binPath = "/run/current-system/sw/bin/sway"; + }; + ''; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + systemd.packages = [ cfg.package ]; + environment.pathsToLink = [ "/share/uwsm" ]; + + services.graphical-desktop.enable = true; + + # UWSM recommends dbus broker for better compatibility + services.dbus.implementation = "broker"; + + services.displayManager.sessionPackages = lib.mapAttrsToList ( + name: value: + mk_uwsm_desktop_entry { + inherit name; + inherit (value) prettyName comment binPath; + } + ) cfg.waylandCompositors; + }; + + meta.maintainers = with lib.maintainers; [ + johnrtitor + kai-tub + ]; +}