223 lines
8.8 KiB
Nix
223 lines
8.8 KiB
Nix
# nwg-panel: a wayland status bar (like waybar, etc)
|
|
# documentation is in the GitHub Wiki:
|
|
# - <https://github.com/nwg-piotr/nwg-panel/wiki/Configuration>
|
|
#
|
|
# interactively configure with: `nwg-panel-config`
|
|
# ^ note that this may interfere with the `nwg-panel` service
|
|
{ config, lib, pkgs, ... }:
|
|
let
|
|
cfg = config.sane.programs.nwg-panel;
|
|
mkEnableOption' = default: description: lib.mkOption {
|
|
type = lib.types.bool;
|
|
inherit default description;
|
|
};
|
|
playerctl = pkgs.playerctl.overrideAttrs (upstream: {
|
|
patches = (upstream.patches or []) ++ [
|
|
(pkgs.fetchpatch {
|
|
# playerctl, when used as a library, doesn't expect its user to `unref` it inside a glib signal.
|
|
# nwg-panel does this though, and then segfaults.
|
|
# playerctl project looks dead as of 2024/06/19, no hope for upstreaming this.
|
|
# - <https://github.com/altdesktop/playerctl/>
|
|
# TODO: consider removing this if nwg-panel code is changed to not trigger this.
|
|
# - <https://github.com/nwg-piotr/nwg-panel/issues/233>
|
|
name = "dbus_name_owner_changed_callback: acquire a ref on the manager before using it";
|
|
url = "https://git.uninsane.org/colin/playerctl/commit/bbcbbe4e03da93523b431ffee5b64e10b17b4f9f.patch";
|
|
hash = "sha256-l/w+ozga8blAB2wtEd1SPBE6wpHNXWk7NrOL7x10oUI=";
|
|
})
|
|
];
|
|
});
|
|
in
|
|
{
|
|
sane.programs.torch-toggle = {
|
|
packageUnwrapped = pkgs.static-nix-shell.mkBash {
|
|
pname = "torch-toggle";
|
|
pkgs = [ "brightnessctl" ];
|
|
srcRoot = ./.;
|
|
};
|
|
|
|
suggestedPrograms = [
|
|
"brightnessctl"
|
|
];
|
|
sandbox = config.sane.programs.brightnessctl.sandbox;
|
|
};
|
|
|
|
sane.programs.nwg-panel = {
|
|
configOption = with lib; mkOption {
|
|
default = {};
|
|
type = types.submodule {
|
|
options = {
|
|
clockFontSize = mkOption {
|
|
type = types.int;
|
|
# what looks good:
|
|
# - 15px on moby
|
|
# - 24px on lappy
|
|
# there's about 10px padding total around this (above + below)
|
|
default = lib.min 24 (cfg.config.height - 11);
|
|
};
|
|
fontSize = mkOption {
|
|
type = types.int;
|
|
default = 16;
|
|
};
|
|
height = mkOption {
|
|
type = types.int;
|
|
default = 40;
|
|
description = ''
|
|
height of the top bar in px.
|
|
'';
|
|
};
|
|
locker = mkOption {
|
|
type = types.str;
|
|
default = config.sane.programs.swayidle.config.actions.lock.service;
|
|
description = ''
|
|
service to start which can lock the screen
|
|
'';
|
|
};
|
|
torch = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = ''
|
|
device name for the torch (flashlight), if any.
|
|
find with `brightnessctl -l`
|
|
'';
|
|
example = "white:flash";
|
|
};
|
|
battery = mkEnableOption' true "display battery status";
|
|
brightness = mkEnableOption' true "display backlight level and slider";
|
|
mediaTitle = mkEnableOption' true "display title of current song/media";
|
|
mediaPrevNext = mkEnableOption' true "display prev/next button in media";
|
|
sysload = mkEnableOption' true "display system load info (cpu/memory)";
|
|
windowIcon = mkEnableOption' true "display icon of active window";
|
|
windowTitle = mkEnableOption' true "display title of active window";
|
|
workspaceNumbers = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [
|
|
# TODO: workspace 10 should be rendered as "TV"
|
|
"1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
|
|
];
|
|
description = ''
|
|
workspaces to monitor
|
|
'';
|
|
};
|
|
workspaceHideEmpty = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
packageUnwrapped = (pkgs.nwg-panel.override {
|
|
inherit playerctl;
|
|
}).overrideAttrs (base: {
|
|
# patches = (base.patches or []) ++ lib.optionals (!cfg.config.mediaPrevNext) [
|
|
# ./playerctl-no-prev-next.diff
|
|
# ];
|
|
patches = (base.patches or []) ++ [
|
|
(pkgs.fetchpatch {
|
|
# upstreaming: <https://github.com/nwg-piotr/nwg-panel/pull/309>
|
|
url = "https://git.uninsane.org/colin/nwg-panel/commit/a714e4100c409feb02c454874d030d192bfb0ae5.patch";
|
|
name = "playerctl: add settings to control which elements are displayed";
|
|
hash = "sha256-OofS46wAI3EDE3JbYs/Nn+Vkw9TP1mwSFvk+vBERg2s=";
|
|
})
|
|
];
|
|
|
|
# - disable the drop-down chevron by the controls.
|
|
# it's precious space on moby, doesn't do much to help on lappy either.
|
|
# - disable brightness indicator for same reason.
|
|
# - *leave* the volume indicator: one *could* remove it, however on desko that would leave the controls pane empty
|
|
# making the dropdown inaccessible
|
|
# also, remove padding from the items. i can manage that in css and the python padding prevents that.
|
|
postPatch = (base.postPatch or "") + ''
|
|
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
|
'self.box.pack_start(box, False, False, 6)' \
|
|
'self.box.pack_start(box, False, False, 0)'
|
|
|
|
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
|
'box.pack_start(self.pan_image, False, False, 4)' \
|
|
'# box.pack_start(self.pan_image, False, False, 0)'
|
|
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
|
'box.pack_start(self.bri_image, False, False, 4)' \
|
|
'# box.pack_start(self.bri_image, False, False, 0)'
|
|
|
|
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
|
'box.pack_start(self.vol_image, False, False, 4)' \
|
|
'box.pack_start(self.vol_image, False, False, 0)'
|
|
'';
|
|
|
|
# XXX(2024/06/13) the bluetooth stuff doesn't cross compile, so disable it
|
|
propagatedBuildInputs = lib.filter (p: p.pname != "pybluez") base.propagatedBuildInputs;
|
|
|
|
strictDeps = true;
|
|
});
|
|
|
|
suggestedPrograms = [
|
|
"brightnessctl"
|
|
"pactl" # pactl required by `per-app-volume` component.
|
|
] ++ lib.optionals (cfg.config.torch != null) [
|
|
"torch-toggle"
|
|
];
|
|
|
|
fs.".config/nwg-panel/style.css".symlink.target = pkgs.substituteAll {
|
|
src = ./style.css;
|
|
inherit (cfg.config) fontSize clockFontSize;
|
|
};
|
|
fs.".config/nwg-panel/common-settings.json".symlink.target = ./common-settings.json;
|
|
fs.".config/nwg-panel/config".symlink.target = pkgs.writers.writeJSON "config" (import ./config.nix {
|
|
inherit (cfg.config) locker height mediaPrevNext windowIcon windowTitle workspaceHideEmpty workspaceNumbers;
|
|
# component order matters, mostly for the drop-down.
|
|
# default for most tools (e.g. swaync) is brightness control above volume.
|
|
controlsSettingsComponents =
|
|
lib.optionals cfg.config.brightness [
|
|
"brightness"
|
|
] ++ [
|
|
"volume"
|
|
# "per-app-volume"
|
|
] ++ lib.optionals cfg.config.battery [
|
|
"battery"
|
|
]
|
|
;
|
|
controlsSettingsCustomItems = lib.optionals (cfg.config.torch != null) [
|
|
{
|
|
name = "Torch";
|
|
# icons: find them in /etc/profiles/per-user/colin/share/icons
|
|
# display-brightness-symbolic, keyboard-brightness-symbolic, night-light-symbolic
|
|
icon = "display-brightness-symbolic";
|
|
cmd = "torch-toggle ${cfg.config.torch}";
|
|
}
|
|
];
|
|
modulesRight = [
|
|
"playerctl"
|
|
] ++ lib.optionals cfg.config.sysload [
|
|
"executor-sysload"
|
|
];
|
|
playerctlChars = if cfg.config.mediaTitle then 60 else 0;
|
|
});
|
|
|
|
sandbox.whitelistAudio = true;
|
|
sandbox.whitelistDri = true;
|
|
sandbox.whitelistSystemctl = true;
|
|
sandbox.whitelistWayland = true;
|
|
sandbox.whitelistMpris.controlPlayers = true;
|
|
sandbox.whitelistDbus.user.call."org.erikreider.swaync.cc" = "*";
|
|
sandbox.extraPaths = [
|
|
"/sys/class/backlight"
|
|
"/sys/class/leds" #< for torch/flashlight on moby
|
|
"/sys/class/power_supply" #< for the battery indicator
|
|
"/sys/devices"
|
|
];
|
|
sandbox.extraRuntimePaths = [ "sway" ];
|
|
sandbox.keepPidsAndProc = true; #< nwg-panel restarts itself on display dis/connect, by killing all other instances (TODO: fix to just exit on display attach?)
|
|
|
|
services.nwg-panel = {
|
|
description = "nwg-panel status/topbar for wayland";
|
|
partOf = [ "graphical-session" ];
|
|
|
|
# to debug styling, run with GTK_DEBUG=interactive
|
|
# N.B.: G_MESSAGES_DEBUG=all causes the swaync icon to not render
|
|
# command = "env G_MESSAGES_DEBUG=all nwg-panel";
|
|
# XXX: try `nwg-panel & ; kill $$`. the inner nwg-panel doesn't die (without sane-die-with-parent), and hence the service would be prone to maintaining _multiple_ bars.
|
|
command = "nwg-panel";
|
|
};
|
|
};
|
|
}
|