From 75373ebdc1e65ac38caa6b9fa399687bf02f54ab Mon Sep 17 00:00:00 2001 From: alexion Date: Fri, 24 Jul 2026 14:07:00 -0400 Subject: [PATCH] feat(desktop): show volume and brightness changes with a SwayOSD popup Route the volume and brightness keys through swayosd-client, which raises a transient on-screen popup that auto-hides a moment after the last press, so the level is visible while adjusting without a permanent widget. A new osd module runs the server for the graphical session and makes the backlight node group-writable so it dims without root. Supersedes the plain brightnessctl binds, whose control swayosd bundles. --- modules/desktop/brightness.nix | 23 --------------- modules/desktop/desktop.nix | 2 +- modules/desktop/hyprland/hyprland.nix | 16 +++++------ modules/desktop/osd.nix | 40 +++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 32 deletions(-) delete mode 100644 modules/desktop/brightness.nix create mode 100644 modules/desktop/osd.nix diff --git a/modules/desktop/brightness.nix b/modules/desktop/brightness.nix deleted file mode 100644 index f37e886..0000000 --- a/modules/desktop/brightness.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: -# Screen backlight control via brightnessctl. -let - cfg = config.modules.desktop.brightness; - user = config.user.name; -in -{ - options.modules.desktop.brightness.enable = lib.mkEnableOption "brightnessctl backlight control"; - - config = lib.mkIf cfg.enable { - environment.systemPackages = [ pkgs.brightnessctl ]; - - # The udev rule chgrps each backlight's brightness node to `video` and adds - # group write, so a member can dim the panel without root. - services.udev.packages = [ pkgs.brightnessctl ]; - users.users.${user}.extraGroups = [ "video" ]; - }; -} diff --git a/modules/desktop/desktop.nix b/modules/desktop/desktop.nix index adfb79d..78c3d5d 100644 --- a/modules/desktop/desktop.nix +++ b/modules/desktop/desktop.nix @@ -25,6 +25,6 @@ in modules.desktop.theming.enable = lib.mkDefault true; modules.desktop.waybar.enable = lib.mkDefault true; modules.desktop.audio.enable = lib.mkDefault true; - modules.desktop.brightness.enable = lib.mkDefault true; + modules.desktop.osd.enable = lib.mkDefault true; }; } diff --git a/modules/desktop/hyprland/hyprland.nix b/modules/desktop/hyprland/hyprland.nix index 6e6b586..9c816b8 100644 --- a/modules/desktop/hyprland/hyprland.nix +++ b/modules/desktop/hyprland/hyprland.nix @@ -141,19 +141,19 @@ in ] ++ workspaceBinds; - # Volume and brightness keys repeat while held. Volume is capped at 150 - # percent; brightnessctl floors the panel at its minimum so a full hold - # cannot black the screen out. + # Volume and brightness keys repeat while held, each raising a popup + # through the OSD client. Volume is capped at 150 percent; the client + # floors brightness so a full hold cannot black the screen out. binde = [ - ", XF86AudioRaiseVolume, exec, ${pkgs.wireplumber}/bin/wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+" - ", XF86AudioLowerVolume, exec, ${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" - ", XF86MonBrightnessUp, exec, ${pkgs.brightnessctl}/bin/brightnessctl set 5%+" - ", XF86MonBrightnessDown, exec, ${pkgs.brightnessctl}/bin/brightnessctl set 5%-" + ", XF86AudioRaiseVolume, exec, ${pkgs.swayosd}/bin/swayosd-client --output-volume raise --max-volume 150" + ", XF86AudioLowerVolume, exec, ${pkgs.swayosd}/bin/swayosd-client --output-volume lower" + ", XF86MonBrightnessUp, exec, ${pkgs.swayosd}/bin/swayosd-client --brightness raise" + ", XF86MonBrightnessDown, exec, ${pkgs.swayosd}/bin/swayosd-client --brightness lower" ]; # Mute and media transport still fire while the session is locked. bindl = [ - ", XF86AudioMute, exec, ${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" + ", XF86AudioMute, exec, ${pkgs.swayosd}/bin/swayosd-client --output-volume mute-toggle" ", XF86AudioPlay, exec, ${pkgs.playerctl}/bin/playerctl play-pause" ", XF86AudioNext, exec, ${pkgs.playerctl}/bin/playerctl next" ", XF86AudioPrev, exec, ${pkgs.playerctl}/bin/playerctl previous" diff --git a/modules/desktop/osd.nix b/modules/desktop/osd.nix new file mode 100644 index 0000000..a794c72 --- /dev/null +++ b/modules/desktop/osd.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + pkgs, + ... +}: +# SwayOSD: a transient on-screen popup for volume and brightness changes. +let + cfg = config.modules.desktop.osd; + user = config.user.name; +in +{ + options.modules.desktop.osd.enable = lib.mkEnableOption "the SwayOSD volume and brightness popup"; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ pkgs.swayosd ]; + + # The udev rule chgrps each backlight's brightness node to `video` and adds + # group write, so the server dims the panel without root. Membership below + # grants the running session that access. + services.udev.packages = [ pkgs.swayosd ]; + users.users.${user}.extraGroups = [ "video" ]; + + # The server draws the popups, so it runs for the whole graphical session. + # Bound to the target uwsm activates, like the bar, rather than an + # exec-once in the compositor config. + home-manager.users.${user}.systemd.user.services.swayosd = { + Unit = { + Description = "SwayOSD on-screen display server"; + PartOf = [ "graphical-session.target" ]; + After = [ "graphical-session.target" ]; + }; + Service = { + ExecStart = "${pkgs.swayosd}/bin/swayosd-server"; + Restart = "on-failure"; + }; + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; +}