diff --git a/modules/desktop/themes/catppuccin/waybar.css b/modules/desktop/themes/catppuccin/waybar.css
index f9f3d55..09990f0 100644
--- a/modules/desktop/themes/catppuccin/waybar.css
+++ b/modules/desktop/themes/catppuccin/waybar.css
@@ -168,7 +168,7 @@ window#waybar.floating #window {
color: @red;
}
-#custom-wallpaper {
+#custom-wallpaper, #custom-rgb {
color: @overlay1;
}
diff --git a/modules/desktop/waybar.nix b/modules/desktop/waybar.nix
index 4212cd6..066f1b7 100644
--- a/modules/desktop/waybar.nix
+++ b/modules/desktop/waybar.nix
@@ -24,301 +24,314 @@ in {
package = cfg.package;
settings = {
- mainBar = {
- layer = "top";
- position = "top";
- spacing = 4;
- 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 = "{calendar}";
- calendar = {
- mode = "year";
- mode-mon-col = 3;
- weeks-pos = "right";
- on-scroll = 1;
- on-click-right = "mode";
- format = {
- months = "{}";
- days = "{}";
- weeks = "W{}";
- weekdays = "{}";
- today = "{}";
- };
- 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;
+ mainBar = mkMerge [
+ {
+ layer = "top";
+ position = "top";
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
+ 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"
+ ];
- lon=""
- lat=""
+ "group/playback" = {
+ orientation = "inherit";
+ modules = [
+ "mpris"
+ ];
+ };
- 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)
+ "group/status" = {
+ orientation = "inherit";
+ modules = [
+ "pulseaudio"
+ "backlight"
+ "cpu"
+ "memory"
+ "network"
+ "power-profiles-daemon"
+ "battery"
+ "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
- # 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";
- };
- };
+ 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}";
+ };
+ "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 = "{calendar}";
+ calendar = {
+ mode = "year";
+ mode-mon-col = 3;
+ weeks-pos = "right";
+ on-scroll = 1;
+ on-click-right = "mode";
+ format = {
+ months = "{}";
+ days = "{}";
+ weeks = "W{}";
+ weekdays = "{}";
+ today = "{}";
+ };
+ 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}";
+ };
+ })
+ ];
};
};
};
diff --git a/modules/hardware/rgb.nix b/modules/hardware/rgb.nix
index 610723f..85c8f19 100644
--- a/modules/hardware/rgb.nix
+++ b/modules/hardware/rgb.nix
@@ -5,10 +5,38 @@ let
cfg = config.modules.hardware.rgb;
in {
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 {
services.hardware.openrgb.enable = true;
+ services.hardware.openrgb.package = cfg.package;
};
}