{ lib, pkgs, ... }:
{
config = {
programs.waybar = {
enable = true;
systemd = {
enable = true;
target = "graphical-session.target";
};
settings = let
windowRewrites = {
"(.*) — Mozilla Firefox" = "$1";
"(.*) - Mozilla Thunderbird" = "$1";
"(.*) - mpv" = "$1";
};
iconSize = 11;
in [
{
layer = "top";
position = "top";
height = 14;
output = [ "eDP-1" "DP-2" "DP-3" ];
modules-left = [ "niri/workspaces" ];
modules-center = [ "niri/window" ];
modules-right = [ # "custom/worktime" "custom/worktime-today"
"custom/weather"
# "custom/keymap"
"privacy" "tray" "wireplumber" "backlight" "battery" "idle_inhibitor" "clock" ];
"custom/weather" = {
format = "{}";
tooltip = true;
interval = 3600;
exec = "${lib.getExe pkgs.wttrbar} --hide-conditions --nerd --custom-indicator \"{ICON} {FeelsLikeC}°\"";
return-type = "json";
};
"custom/keymap" = {
format = "{}";
tooltip = true;
return-type = "json";
exec = pkgs.writers.writePython3 "keymap" {} ''
import os
import socket
import re
import subprocess
import json
def output(keymap):
short = keymap
if keymap == "English (programmer Dvorak)":
short = "dvp"
elif keymap == "English (US)":
short = "us"
print(json.dumps({'text': short, 'tooltip': keymap}, separators=(',', ':')), flush=True) # noqa: E501
r = subprocess.run(["hyprctl", "devices", "-j"], check=True, stdout=subprocess.PIPE, text=True) # noqa: E501
for keyboard in json.loads(r.stdout)['keyboards']:
if keyboard['name'] != "at-translated-set-2-keyboard":
continue
output(keyboard['active_keymap'])
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(os.environ["XDG_RUNTIME_DIR"] + "/hypr/" + os.environ["HYPRLAND_INSTANCE_SIGNATURE"] + "/.socket2.sock") # noqa: E501
expected = re.compile(r'^activelayout>>at-translated-set-2-keyboard,(?P.+)$') # noqa: E501
for line in sock.makefile(buffering=1, encoding='utf-8'):
if match := expected.match(line):
output(match.group("keymap"))
'';
on-click = "hyprctl switchxkblayout at-translated-set-2-keyboard next";
};
"custom/worktime" = {
interval = 60;
exec = lib.getExe pkgs.worktime;
tooltip = false;
};
"custom/worktime-today" = {
interval = 60;
exec = "${lib.getExe pkgs.worktime} today";
tooltip = false;
};
"niri/workspaces" = {};
"niri/window" = {
separate-outputs = true;
icon = true;
icon-size = 14;
rewrite = windowRewrites;
};
clock = {
interval = 1;
# timezone = "Europe/Berlin";
format = "W{:%V-%u %F %H:%M:%S%Ez}";
tooltip-format = "{calendar}";
calendar = {
mode = "year";
mode-mon-col = 3;
weeks-pos = "left";
on-scroll = 1;
format = {
months = "{}";
days = "{}";
weeks = "{}";
weekdays = "{}";
today = "{}";
};
};
};
battery = {
format = "{icon}";
icon-size = iconSize - 2;
states = { warning = 30; critical = 15; };
format-icons = ["" "" "" "" "" "" "" "" "" "" "" ];
format-charging = "";
format-plugged = "";
tooltip-format = "{capacity}% {timeTo}";
interval = 20;
};
tray = {
icon-size = 16;
# show-passive-items = true;
spacing = 1;
};
privacy = {
icon-spacing = 7;
icon-size = iconSize;
modules = [
{ type = "screenshare"; }
{ type = "audio-in"; }
];
};
idle_inhibitor = {
format = "{icon}";
icon-size = iconSize;
format-icons = { activated = ""; deactivated = ""; };
timeout = 120;
};
backlight = {
format = "{icon}";
icon-size = iconSize;
tooltip-format = "{percent}%";
format-icons = ["" "" "" "" "" "" ""];
on-scroll-up = "lightctl -d -e4 -n1 up";
on-scroll-down = "lightctl -d -e4 -n1 down";
};
wireplumber = {
format = "{icon}";
icon-size = iconSize;
tooltip-format = "{volume}% {node_name}";
format-icons = ["" "" ""];
format-muted = "";
# ignored-sinks = ["Easy Effects Sink"];
on-scroll-up = "volumectl -d -u up";
on-scroll-down = "volumectl -d -u down";
on-click = "volumectl -d toggle-mute";
};
}
{
layer = "top";
position = "top";
height = 14;
output = [ "!eDP-1" "!DP-2" "!DP-3" ];
modules-left = [ "niri/workspaces" ];
modules-center = [ "niri/window" ];
modules-right = [ "clock" ];
"niri/workspaces" = {};
"niri/window" = {
separate-outputs = true;
icon = true;
icon-size = 14;
rewrite = windowRewrites;
};
clock = {
interval = 1;
# timezone = "Europe/Berlin";
format = "{:%H:%M}";
tooltip-format = "W{:%V-%u %F %H:%M:%S%Ez}";
};
}
];
style = ''
@define-color white #ffffff;
@define-color grey #555555;
@define-color blue #1a8fff;
@define-color green #23fd00;
@define-color orange #f28a21;
@define-color red #f2201f;
* {
border: none;
font-family: "Fira Sans Nerd Font";
font-size: 10pt;
min-height: 0;
}
window#waybar {
background-color: rgba(0, 0, 0, 0.66);
color: @white;
}
.modules-left {
margin-left: 9px;
}
.modules-right {
margin-right: 9px;
}
.module {
margin: 0 5px;
}
#workspaces button {
color: @white;
padding: 2px 5px;
}
#workspaces button.empty {
color: @grey;
}
#workspaces button.active {
color: @green;
}
#workspaces button.urgent {
color: @red;
}
#custom-weather, #custom-keymap, #custom-worktime, #custom-worktime-today {
color: @grey;
margin: 0 5px;
}
#custom-weather, #custom-worktime-today {
margin-right: 3px;
}
#custom-keymap, #custom-weather {
margin-left: 3px;
}
#tray {
margin: 0;
}
#battery, #idle_inhibitor, #backlight, #wireplumber {
color: @grey;
margin: 0 5px 0 2px;
}
#idle_inhibitor {
margin-right: 2px;
margin-left: 3px;
}
#battery {
margin-right: 3px;
}
#battery.discharging {
color: @white;
}
#battery.warning {
color: @orange;
}
#battery.critical {
color: @red;
}
#battery.charging {
color: @white;
}
#idle_inhibitor.activated {
color: @white;
}
#idle_inhibitor {
padding-top: 1px;
}
#privacy {
color: @red;
margin: -1px 2px 0px 5px;
}
#clock {
/* margin-right: 5px; */
}
'';
};
};
}