rgb on waybar

This commit is contained in:
Reid 2026-04-05 17:00:30 -07:00
parent 96d02ac12e
commit d25752f468
Signed by: reidlab
GPG key ID: DAF5EAF6665839FD
3 changed files with 334 additions and 293 deletions

View file

@ -168,7 +168,7 @@ window#waybar.floating #window {
color: @red; color: @red;
} }
#custom-wallpaper { #custom-wallpaper, #custom-rgb {
color: @overlay1; color: @overlay1;
} }

View file

@ -24,301 +24,314 @@ in {
package = cfg.package; package = cfg.package;
settings = { settings = {
mainBar = { mainBar = mkMerge [
layer = "top"; {
position = "top"; layer = "top";
spacing = 4; position = "top";
height = 32;
margin-top = 6;
margin-left = 6;
margin-right = 6;
margin-bottom = 0;
modules-left = [
"niri/workspaces"
"niri/window"
];
modules-center = [
"clock"
];
modules-right = [
"group/playback"
"group/status"
"tray"
"group/power"
];
"group/playback" = {
orientation = "inherit";
modules = [
"mpris"
];
};
"group/status" = {
orientation = "inherit";
modules = [
"pulseaudio"
"backlight"
"cpu"
"memory"
"network"
"power-profiles-daemon"
"battery"
"custom/weather"
"privacy"
"custom/wallpaper"
];
};
"group/power" = {
orientation = "inherit";
modules = [
"custom/power"
];
};
"custom/power" = let
powerMenuScript = pkgs.writeShellScript "power-menu" ''
set -euo pipefail
cmd=$(echo ' shutdown| reboot|󰒲 sleep| hibernate| lock| exit desktop environment' | ${lib.getExe config.modules.desktop.rofi.package} -dmenu -sep '|' -i -p 'what to do ?')
case "$cmd" in
" shutdown")
poweroff
;;
" reboot")
reboot
;;
"󰒲 sleep")
systemctl suspend
;;
" hibernate")
systemctl hibernate
;;
" lock")
${pkgs.systemd}/bin/loginctl lock-session
;;
" exit desktop environment")
${pkgs.systemd}/bin/loginctl terminate-session $XDG_SESSION_ID
;;
esac
'';
in {
format = "";
tooltip = true;
tooltip-format = "Power menu";
on-click = "${powerMenuScript}";
};
"custom/wallpaper" = {
format = "";
tooltip = true;
tooltip-format = "Change wallpaper";
on-click = "${config.modules.desktop.swww.swapScript}";
};
"niri/workspaces" = {
format = "{icon}";
format-icons = {
urgent = "";
focused = "";
default = "";
};
};
"niri/window" = {
format = "{}";
icon = true;
icon-size = 16;
rewrite = {
"(.*) Mozilla Firefox" = "$1"; # the dash here is SLIGHTLY different. Wow
"(.*) - Visual Studio Code" = "$1";
"(.*\\.nix\\s.*)" = " $1";
"(\\S+\\.html\\s.*)" = " $1";
"(\\S+\\.css\\s.*)" = " $1";
"(\\S+\\.js\\s.*)" = " $1";
"(\\S+\\.ts\\s.*)" = " $1";
"(\\S+\\.go\\s.*)" = " $1";
"(\\S+\\.lua\\s.*)" = " $1";
"(\\S+\\.java\\s.*)" = " $1";
"(\\S+\\.rb\\s.*)" = " $1";
"(\\S+\\.php\\s.*)" = " $1";
"(\\S+\\.jsonc?\\s.*)" = " $1";
"(\\S+\\.md\\s.*)" = " $1";
"(\\S+\\.txt\\s.*)" = " $1";
"(\\S+\\.cs\\s.*)" = "󰌛 $1";
"(\\S+\\.c\\s.*)" = " $1";
"(\\S+\\.cpp\\s.*)" = " $1";
"(\\S+\\.zig\\s.*)" = " $1";
"(\\S+\\.rs\\s.*)" = " $1";
"(\\S+\\.hs\\s.*)" = " $1";
".*Discord \\| (.*)" = "$1";
};
separate-outputs = true;
};
pulseaudio = {
format = "{icon} {volume}%";
format-bluetooth = "{icon} {volume}%";
format-muted = " {volume}%";
format-icons = {
headphone = "";
default = ["" "" ""];
};
scroll-step = 1;
on-click = "${lib.getExe pkgs.pwvucontrol}";
ignored-sinks = ["Easy Effects Sink"];
};
backlight = {
format = "{icon} {percent}%";
format-icons = ["" ""];
scroll-step = 1;
};
cpu = {
interval = 4;
format = " {usage}%";
on-click = "${lib.getExe pkgs.mission-center}";
};
# bluetooth = {
#
# };
memory = {
interval = 4;
format = " {percentage}%";
tooltip = true;
tooltip-format = "{used:0.1f}GiB/{avail:0.1f}GiB used\n{swapUsed:0.1f}GiB/{swapAvail:0.1f}GiB swap";
on-click = "${lib.getExe pkgs.mission-center}";
states = {
warning = 80;
critical = 90;
};
};
network = {
format = "{icon}";
tooltip = true;
tooltip-format-wifi = "{essid} ({signalStrength}%)";
tooltip-format-ethernet = "{ifname}";
tooltip-format-linked = "{ifname} (no ip)";
tooltip-format-disabled = "Disabled";
tooltip-format-disconnected = "Disconnected";
format-icons = {
wifi = "";
ethernet = ""; # TODO: change symbol to ethernet, this represents lan
linked = ""; # TODO: this symbol is deprecated
disabled = "";
disconnected = "";
};
on-click = "${pkgs.networkmanagerapplet}/bin/nm-connection-editor";
};
power-profiles-daemon = {
format = "{icon}";
tooltip = true;
tooltip-format = "Power profile: {profile}\nDriver: {driver}";
format-icons = {
default = "";
performance = " perf";
balanced = " balance";
power-saver = " save";
};
};
battery = {
interval = 30;
states = {
warning = 20;
critical = 10;
};
design-capacity = false;
format = "{icon} {capacity}%";
format-icons = ["" "" "" "" ""];
format-critical = " {capacity}%";
format-charging = " {capacity}%";
tooltip = true;
tooltip-format = "{timeTo} ({power}W)";
};
privacy = {
icon-spacing = 0;
icon-size = 12;
transition-duration = 250;
modules = [
{ type = "screenshare"; }
{ type = "audio-in"; }
];
};
mpris = {
format = "{status_icon} {dynamic}";
dynamic-len = 32;
title-len = 32;
dynamic-order = [ "artist" "title" ];
dynamic-importance-order = [ "title" "artist" ];
tooltip = true;
tooltip-format = "{player} | {status_icon} {artist} - {title} from {album} ({position}/{length})";
interval = 1;
status-icons = {
playing = "";
paused = "";
};
};
clock = {
format = "{:%H:%M}";
format-alt = "{:%a %b %d %R}";
tooltip = true;
tooltip-format = "<tt><small>{calendar}</small></tt>";
calendar = {
mode = "year";
mode-mon-col = 3;
weeks-pos = "right";
on-scroll = 1;
on-click-right = "mode";
format = {
months = "<span color='#ffead3'><b>{}</b></span>";
days = "<span color='#ecc6d9'><b>{}</b></span>";
weeks = "<span color='#99ffdd'><b>W{}</b></span>";
weekdays = "<span color='#ffcc66'><b>{}</b></span>";
today = "<span color='#ff6699'><b><u>{}</u></b></span>";
};
actions = {
on-click-right = "mode";
on-click-forward = "tz_up";
on-click-backward = "tz_down";
on-scroll-up = "shift_up";
on-scroll-down = "shift_down";
};
};
};
tray = {
icon-size = 16;
spacing = 4; spacing = 4;
}; height = 32;
"custom/weather" = let margin-top = 6;
# this *should* be from coordinates, but we have to make it city because... margin-left = 6;
# https://github.com/chubin/wttr.in/issues/795 margin-right = 6;
# i was NOT going to let ip-based location be a thing. i was suprisingly medicated when i wrote this margin-bottom = 0;
locationScript = pkgs.writeShellScript "location" '' modules-left = [
set -euo pipefail "niri/workspaces"
"niri/window"
];
modules-center = [
"clock"
];
modules-right = [
"group/playback"
"group/status"
"tray"
"group/power"
];
lon="" "group/playback" = {
lat="" orientation = "inherit";
modules = [
"mpris"
];
};
while IFS= read -r line; do "group/status" = {
if [[ "$line" == *"Latitude"* ]]; then orientation = "inherit";
lat=$(echo "$line" | awk '{ gsub(/[" ]/, "", $2); printf("%.2f", $2) }') modules = [
elif [[ "$line" == *"Longitude"* ]]; then "pulseaudio"
lon=$(echo "$line" | awk '{ gsub(/[" ]/, "", $2); printf("%.2f", $2) }') "backlight"
fi "cpu"
if [[ -n "$lat" && -n "$lon" ]]; then "memory"
break "network"
fi "power-profiles-daemon"
# -a 4 -- set accuracy to city "battery"
done < <(${pkgs.geoclue2}/libexec/geoclue-2.0/demos/where-am-i -a 4) "custom/weather"
"privacy"
"custom/wallpaper"
"custom/rgb"
];
};
"group/power" = {
orientation = "inherit";
modules = [
"custom/power"
];
};
"custom/power" = let
powerMenuScript = pkgs.writeShellScript "power-menu" ''
set -euo pipefail
# i've had issues including country *and* state here, so state has higher priority and falls back to country. works fine for my current place and home town, so good enough <3 cmd=$(echo ' shutdown| reboot|󰒲 sleep| hibernate| lock| exit desktop environment' | ${lib.getExe config.modules.desktop.rofi.package} -dmenu -sep '|' -i -p 'what to do ?')
# zoom=10 -- set zoom to city case "$cmd" in
# addressdetails=1 -- get address details, includes neighborhood (if requested) to city " shutdown")
echo $(curl "https://nominatim.openstreetmap.org/reverse?lat=''${lat}&lon=''${lon}&addressdetails=1&zoom=10&format=json" | ${lib.getExe pkgs.jq} -r '.address | "\((to_entries[0].value)), \(.state // "\(.country)")"') poweroff
''; ;;
in { " reboot")
format = "{}°"; reboot
tooltip = true; ;;
on-click = "${lib.getExe pkgs.gnome-weather}"; "󰒲 sleep")
interval = 600; systemctl suspend
exec = ''${lib.getExe pkgs.wttrbar} --location "$(${locationScript})" --hide-conditions --fahrenheit --mph''; ;;
return-type = "json"; " hibernate")
}; systemctl hibernate
}; ;;
" lock")
${pkgs.systemd}/bin/loginctl lock-session
;;
" exit desktop environment")
${pkgs.systemd}/bin/loginctl terminate-session $XDG_SESSION_ID
;;
esac
'';
in {
format = "";
tooltip = true;
tooltip-format = "Power menu";
on-click = "${powerMenuScript}";
};
"niri/workspaces" = {
format = "{icon}";
format-icons = {
urgent = "";
focused = "";
default = "";
};
};
"niri/window" = {
format = "{}";
icon = true;
icon-size = 16;
rewrite = {
"(.*) Mozilla Firefox" = "$1"; # the dash here is SLIGHTLY different. Wow
"(.*) - Visual Studio Code" = "$1";
"(.*\\.nix\\s.*)" = " $1";
"(\\S+\\.html\\s.*)" = " $1";
"(\\S+\\.css\\s.*)" = " $1";
"(\\S+\\.js\\s.*)" = " $1";
"(\\S+\\.ts\\s.*)" = " $1";
"(\\S+\\.go\\s.*)" = " $1";
"(\\S+\\.lua\\s.*)" = " $1";
"(\\S+\\.java\\s.*)" = " $1";
"(\\S+\\.rb\\s.*)" = " $1";
"(\\S+\\.php\\s.*)" = " $1";
"(\\S+\\.jsonc?\\s.*)" = " $1";
"(\\S+\\.md\\s.*)" = " $1";
"(\\S+\\.txt\\s.*)" = " $1";
"(\\S+\\.cs\\s.*)" = "󰌛 $1";
"(\\S+\\.c\\s.*)" = " $1";
"(\\S+\\.cpp\\s.*)" = " $1";
"(\\S+\\.zig\\s.*)" = " $1";
"(\\S+\\.rs\\s.*)" = " $1";
"(\\S+\\.hs\\s.*)" = " $1";
".*Discord \\| (.*)" = "$1";
};
separate-outputs = true;
};
pulseaudio = {
format = "{icon} {volume}%";
format-bluetooth = "{icon} {volume}%";
format-muted = " {volume}%";
format-icons = {
headphone = "";
default = ["" "" ""];
};
scroll-step = 1;
on-click = "${lib.getExe pkgs.pwvucontrol}";
ignored-sinks = ["Easy Effects Sink"];
};
backlight = {
format = "{icon} {percent}%";
format-icons = ["" ""];
scroll-step = 1;
};
cpu = {
interval = 4;
format = " {usage}%";
on-click = "${lib.getExe pkgs.mission-center}";
};
# bluetooth = {
#
# };
memory = {
interval = 4;
format = " {percentage}%";
tooltip = true;
tooltip-format = "{used:0.1f}GiB/{avail:0.1f}GiB used\n{swapUsed:0.1f}GiB/{swapAvail:0.1f}GiB swap";
on-click = "${lib.getExe pkgs.mission-center}";
states = {
warning = 80;
critical = 90;
};
};
network = {
format = "{icon}";
tooltip = true;
tooltip-format-wifi = "{essid} ({signalStrength}%)";
tooltip-format-ethernet = "{ifname}";
tooltip-format-linked = "{ifname} (no ip)";
tooltip-format-disabled = "Disabled";
tooltip-format-disconnected = "Disconnected";
format-icons = {
wifi = "";
ethernet = ""; # TODO: change symbol to ethernet, this represents lan
linked = ""; # TODO: this symbol is deprecated
disabled = "";
disconnected = "";
};
on-click = "${pkgs.networkmanagerapplet}/bin/nm-connection-editor";
};
power-profiles-daemon = {
format = "{icon}";
tooltip = true;
tooltip-format = "Power profile: {profile}\nDriver: {driver}";
format-icons = {
default = "";
performance = " perf";
balanced = " balance";
power-saver = " save";
};
};
battery = {
interval = 30;
states = {
warning = 20;
critical = 10;
};
design-capacity = false;
format = "{icon} {capacity}%";
format-icons = ["" "" "" "" ""];
format-critical = " {capacity}%";
format-charging = " {capacity}%";
tooltip = true;
tooltip-format = "{timeTo} ({power}W)";
};
privacy = {
icon-spacing = 0;
icon-size = 12;
transition-duration = 250;
modules = [
{ type = "screenshare"; }
{ type = "audio-in"; }
];
};
mpris = {
format = "{status_icon} {dynamic}";
dynamic-len = 32;
title-len = 32;
dynamic-order = [ "artist" "title" ];
dynamic-importance-order = [ "title" "artist" ];
tooltip = true;
tooltip-format = "{player} | {status_icon} {artist} - {title} from {album} ({position}/{length})";
interval = 1;
status-icons = {
playing = "";
paused = "";
};
};
clock = {
format = "{:%H:%M}";
format-alt = "{:%a %b %d %R}";
tooltip = true;
tooltip-format = "<tt><small>{calendar}</small></tt>";
calendar = {
mode = "year";
mode-mon-col = 3;
weeks-pos = "right";
on-scroll = 1;
on-click-right = "mode";
format = {
months = "<span color='#ffead3'><b>{}</b></span>";
days = "<span color='#ecc6d9'><b>{}</b></span>";
weeks = "<span color='#99ffdd'><b>W{}</b></span>";
weekdays = "<span color='#ffcc66'><b>{}</b></span>";
today = "<span color='#ff6699'><b><u>{}</u></b></span>";
};
actions = {
on-click-right = "mode";
on-click-forward = "tz_up";
on-click-backward = "tz_down";
on-scroll-up = "shift_up";
on-scroll-down = "shift_down";
};
};
};
tray = {
icon-size = 16;
spacing = 4;
};
"custom/weather" = let
# this *should* be from coordinates, but we have to make it city because...
# https://github.com/chubin/wttr.in/issues/795
# i was NOT going to let ip-based location be a thing. i was suprisingly medicated when i wrote this
locationScript = pkgs.writeShellScript "location" ''
set -euo pipefail
lon=""
lat=""
while IFS= read -r line; do
if [[ "$line" == *"Latitude"* ]]; then
lat=$(echo "$line" | awk '{ gsub(/[" ]/, "", $2); printf("%.2f", $2) }')
elif [[ "$line" == *"Longitude"* ]]; then
lon=$(echo "$line" | awk '{ gsub(/[" ]/, "", $2); printf("%.2f", $2) }')
fi
if [[ -n "$lat" && -n "$lon" ]]; then
break
fi
# -a 4 -- set accuracy to city
done < <(${pkgs.geoclue2}/libexec/geoclue-2.0/demos/where-am-i -a 4)
# i've had issues including country *and* state here, so state has higher priority and falls back to country. works fine for my current place and home town, so good enough <3
# zoom=10 -- set zoom to city
# addressdetails=1 -- get address details, includes neighborhood (if requested) to city
echo $(curl "https://nominatim.openstreetmap.org/reverse?lat=''${lat}&lon=''${lon}&addressdetails=1&zoom=10&format=json" | ${lib.getExe pkgs.jq} -r '.address | "\((to_entries[0].value)), \(.state // "\(.country)")"')
'';
in {
format = "{}°";
tooltip = true;
on-click = "${lib.getExe pkgs.gnome-weather}";
interval = 600;
exec = ''${lib.getExe pkgs.wttrbar} --location "$(${locationScript})" --hide-conditions --fahrenheit --mph'';
return-type = "json";
};
}
(mkIf config.modules.desktop.swww.enable {
"custom/wallpaper" = {
format = "";
tooltip = true;
tooltip-format = "Change wallpaper";
on-click = "${config.modules.desktop.swww.swapScript}";
};
})
(mkIf config.modules.hardware.rgb.enable {
"custom/rgb" = {
format = ""; # TODO: better icon (paintbrush or palette?)
tooltip = true;
tooltip-format = "Change OpenRGB profile";
on-click = "${config.modules.hardware.rgb.swapScript}";
};
})
];
}; };
}; };
}; };

View file

@ -5,10 +5,38 @@ let
cfg = config.modules.hardware.rgb; cfg = config.modules.hardware.rgb;
in { in {
options.modules.hardware.rgb = { options.modules.hardware.rgb = {
enable = mkEnableOption "Enable support for rgb devices through openrgb"; enable = mkEnableOption "Enable support for rgb devices through OpenRGB";
package = mkOption {
type = types.package;
default = pkgs.openrgb;
example = "pkgs.openrgb";
};
swapScript = mkOption {
type = types.package;
default = pkgs.writeShellScript "openrgb-swap" ''
set -euo pipefail
mapfile -t files < <(
find "$XDG_CONFIG_HOME/OpenRGB" -name "*.orp"
find /var/lib/OpenRGB -name "*.orp" 2>/dev/null
)
selected=$(printf '%s\n' "''${files[@]}" | xargs -n1 basename | ${lib.getExe config.modules.desktop.rofi.package} -dmenu -i -p "select profile")
[[ -z "$selected" ]] && exit 0
for f in "''${files[@]}"; do
if [[ $(basename "$f") == "$selected" ]]; then
${lib.getExe cfg.package} -p "$f"
break
fi
done
'';
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.hardware.openrgb.enable = true; services.hardware.openrgb.enable = true;
services.hardware.openrgb.package = cfg.package;
}; };
} }