summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif/niri
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@sif/niri')
-rw-r--r--accounts/gkleen@sif/niri/default.nix555
-rw-r--r--accounts/gkleen@sif/niri/mako.nix115
-rw-r--r--accounts/gkleen@sif/niri/swayosd.nix65
-rw-r--r--accounts/gkleen@sif/niri/waybar.nix139
4 files changed, 802 insertions, 72 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix
index 6a8d10a0..4a207589 100644
--- a/accounts/gkleen@sif/niri/default.nix
+++ b/accounts/gkleen@sif/niri/default.nix
@@ -1,13 +1,127 @@
1{ config, pkgs, lib, ... }: 1{ config, hostConfig, pkgs, lib, ... }:
2let 2let
3 niri = config.programs.niri.package; 3 niri = config.programs.niri.package;
4 terminal = lib.getExe config.programs.kitty.package; 4 terminal = lib.getExe config.programs.kitty.package;
5 lightctl = lib.getExe' config.services.avizo.package "lightctl"; 5 makoctl = lib.getExe' config.services.mako.package "makoctl";
6 volumectl = lib.getExe' config.services.avizo.package "volumectl"; 6 loginctl = lib.getExe' hostConfig.systemd.package "loginctl";
7 dunstctl = lib.getExe' config.services.dunst.package "dunstctl"; 7 systemctl = lib.getExe' hostConfig.systemd.package "systemctl";
8 swayosd-client = lib.getExe' config.services.swayosd.package "swayosd-client";
9
10 focus_or_spawn = pkgs.writeShellApplication {
11 name = "focus-or-spawn";
12 runtimeInputs = [ niri pkgs.gojq pkgs.gnugrep pkgs.socat ];
13 text = ''
14 window_select="$1"
15 shift
16 workspace_name="$1"
17 shift
18
19 workspaces_json="$(niri msg -j workspaces)"
20 workspace_output="$(jq -r --arg workspace_name "$workspace_name" '.[] | select(.name == $workspace_name) | .output' <<<"$workspaces_json")"
21 # active_workspace="$(jq -r --arg workspace_output "$workspace_output" '.[] | select(.output == $workspace_output and .is_active) | .id' <<<"$workspaces_json")"
22 active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")"
23 if [[ $workspace_output != "$active_output" ]]; then
24 niri msg action move-workspace-to-monitor --reference "$workspace_name" "$active_output"
25 # socat STDIO "$NIRI_SOCKET" <<<'{"Action":{"FocusWorkspace":{"reference":{"Id":'"''${active_workspace}"'}}}}'
26 # niri msg action move-workspace-to-index --reference "$workspace_name" 1
27 fi
28
29 while IFS=$'\n' read -r window_json; do
30 if [[ -n $(jq -c "$window_select" <<<"$window_json") ]]; then
31 niri msg action focus-window --id "$(jq -r '.id' <<<"$window_json")"
32 exit 0
33 fi
34 done < <(niri msg -j windows | jq -c '.[]')
35
36 exec "$@"
37 '';
38 };
39 focus-or-spawn-action = config.lib.niri.actions.spawn (lib.getExe focus_or_spawn);
40 focus-or-spawn-action-app_id = app_id: focus-or-spawn-action ''select(.app_id == "${app_id}")'';
41
42 with_adjacent_workspace = pkgs.writeShellApplication {
43 name = "with-adjacent-workspace";
44 runtimeInputs = [ niri pkgs.gojq pkgs.socat ];
45 text = ''
46 blacklist="$1"
47 shift
48 direction="$1"
49 shift
50 action="$1"
51 shift
52
53 workspaces_json="$(niri msg -j workspaces)"
54 active_workspace="$(jq -r '.[] | select(.is_focused) | .id' <<<"$workspaces_json")"
55 workspace_output="$(jq -r --arg active_workspace "$active_workspace" '.[] | select(.id == ($active_workspace | tonumber)) | .output' <<<"$workspaces_json")"
56 workspace_idx="$(jq -r '.[] | select(.is_focused) | .idx' <<<"$workspaces_json")"
57
58 jq_script='map(select('
59 case "$direction" in
60 down)
61 # shellcheck disable=SC2016
62 jq_script=''${jq_script}'.idx > ($workspace_idx | tonumber)';;
63 up)
64 # shellcheck disable=SC2016
65 jq_script=''${jq_script}'.idx < ($workspace_idx | tonumber)';;
66 esac
67 # shellcheck disable=SC2016
68 jq_script=''${jq_script}' and .output == $workspace_output and ((.name == null) or (.name | test($blacklist) | not)))) | sort_by(.idx)'
69 [[ $direction == "up" ]] && jq_script=''${jq_script}' | reverse'
70 jq_script=''${jq_script}' | .[0]'
71
72 workspace_json=$(jq -c --arg blacklist "$blacklist" --arg workspace_output "$workspace_output" --arg workspace_idx "$workspace_idx" "$jq_script" <<<"$workspaces_json")
73 [[ -n $workspace_json && $workspace_json != null ]] || exit 0
74 jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET"
75 '';
76 };
77 with-adjacent-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_adjacent_workspace) "^pwctl|eff|kpxc|bmgr|edit|term$";
78 focus-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}'';
79 move-column-to-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}}}}'';
80
81 with_unnamed_workspace = pkgs.writeShellApplication {
82 name = "with-unnamed-workspace";
83 runtimeInputs = [ niri pkgs.gojq pkgs.socat ];
84 text = ''
85 action="$1"
86 shift
87
88 workspaces_json="$(niri msg -j workspaces)"
89 active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")"
90 active_workspace="$(jq -r '.[] | select(.is_focused) | .id' <<<"$workspaces_json")"
91
92 workspace_json="$(jq -c --arg active_output "$active_output" 'map(select(.output == $active_output and .name == null)) | sort_by(.idx) | .[0]' <<<"$workspaces_json")"
93 [[ -n $workspace_json && $workspace_json != null ]] || exit 0
94 jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET"
95 '';
96 };
97 with-unnamed-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_unnamed_workspace);
98
99 with_select_window = pkgs.writeShellApplication {
100 name = "with-select-window";
101 runtimeInputs = [ niri pkgs.gojq pkgs.socat config.programs.fuzzel.package pkgs.gawk ];
102 text = ''
103 window_select="$1"
104 shift
105 action="$1"
106 shift
107
108 windows_json="$(niri msg -j windows)"
109 active_workspace="$(jq -r '.[] | select(.is_focused) | .workspace_id' <<<"$windows_json")"
110 window_ix="$(gojq -r --arg active_workspace "$active_workspace" '.[] | select('"$window_select"') | "\(.title)\u0000icon\u001f\(.app_id)"' <<<"$windows_json" | fuzzel --log-level=warning --dmenu --index)"
111 # shellcheck disable=SC2016
112 window_json="$(gojq -rc --arg active_workspace "$active_workspace" --arg window_ix "$window_ix" 'map(select('"$window_select"')) | .[($window_ix | tonumber)]' <<<"$windows_json")"
113
114 [[ -z "$window_json" ]] && exit 1
115
116 jq -c "$action" <<<"$window_json" | socat STDIO "$NIRI_SOCKET"
117 '';
118 };
119 with-select-window-action = config.lib.niri.actions.spawn (lib.getExe with_select_window);
8in { 120in {
9 imports = [ 121 imports = [
10 ./waybar.nix 122 ./waybar.nix
123 ./mako.nix
124 ./swayosd.nix
11 ]; 125 ];
12 126
13 config = { 127 config = {
@@ -21,7 +135,9 @@ in {
21 Service = { 135 Service = {
22 Type = "notify"; 136 Type = "notify";
23 NotifyAccess = "all"; 137 NotifyAccess = "all";
24 ExecStart = lib.getExe pkgs.xwayland-satellite-unstable; 138 Environment = [ "DISPLAY=:0" ];
139 ExecStart = ''${lib.getExe pkgs.xwayland-satellite-unstable} ''${DISPLAY}'';
140 ExecStartPre = "${systemctl} --user import-environment DISPLAY";
25 StandardOutput = "journal"; 141 StandardOutput = "journal";
26 }; 142 };
27 Install = { 143 Install = {
@@ -29,32 +145,363 @@ in {
29 }; 145 };
30 }; 146 };
31 147
148 services.swayidle = {
149 events = [
150 { event = "after-resume"; command = "${lib.getExe niri} msg action power-on-monitors"; }
151 ];
152 timeouts = [
153 { timeout = 300;
154 command = "${lib.getExe niri} msg action power-off-monitors";
155 }
156 ];
157 };
158
32 programs.niri.settings = { 159 programs.niri.settings = {
33 prefer-no-csd = true; 160 prefer-no-csd = true;
34 screenshot-path = "${config.home.homeDirectory}/screenshots"; 161 screenshot-path = "${config.home.homeDirectory}/screenshots";
35 162
163 hotkey-overlay.skip-at-startup = true;
164
36 input = { 165 input = {
37 keyboard.xkb = { 166 keyboard = {
38 layout = "us,"; 167 repeat-delay = 300;
39 variant = "dvp,"; 168 repeat-rate = 50;
40 options = "compose:caps,grp:win_space_toggle"; 169
170 xkb = {
171 layout = "us,us";
172 variant = "dvp,";
173 options = "compose:caps,grp:win_space_toggle";
174 };
175 };
176
177 workspace-auto-back-and-forth = true;
178 # focus-follows-mouse.enable = true;
179 warp-mouse-to-focus = true;
180 };
181
182 outputs = {
183 "eDP-1" = {
184 scale = 1.5;
185 position = { x = 0; y = 0; };
186 };
187 "Ancor Communications Inc ASUS PB287Q 0x0000DD9B" = {
188 scale = 1.5;
189 position = { x = 2560; y = 0; };
190 };
191 "HP Inc. HP 727pu CN4417143K" = {
192 mode = { width = 2560; height = 1440; refresh = 119.998; };
193 scale = 1;
194 position = { x = 2560; y = 0; };
195 variable-refresh-rate = "on-demand";
41 }; 196 };
42 }; 197 };
43 198
44 environment = { 199 environment = {
45 NIXOS_OZONE_WL = "1"; 200 NIXOS_OZONE_WL = "1";
46 QT_QPA_PLATFORM = "wayland"; 201 QT_QPA_PLATFORM = "wayland";
202 QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
47 GDK_BACKEND = "wayland"; 203 GDK_BACKEND = "wayland";
48 SDL_VIDEODRIVER = "wayland"; 204 SDL_VIDEODRIVER = "wayland";
205 DISPLAY = ":0";
206 };
207
208 debug.render-drm-device = "/dev/dri/by-path/pci-0000:00:02.0-render";
209
210 animations = {
211 slowdown = 0.5;
212 };
213
214 layout = {
215 gaps = 8;
216 struts = { left = 0; right = 0; top = 0; bottom = 0; };
217 focus-ring = {
218 width = 2;
219 active.gradient = {
220 from = "hsla(195 100% 60% 0.75)";
221 to = "hsla(155 100% 50% 0.75)";
222 angle = 29;
223 relative-to = "workspace-view";
224 };
225 inactive.gradient = {
226 from = "hsla(0 0% 42% 0.66)";
227 to = "hsla(0 0% 35% 0.66)";
228 angle = 29;
229 relative-to = "workspace-view";
230 };
231 };
232
233 preset-column-widths = [
234 { proportion = 1. / 4.; }
235 { proportion = 1. / 3.; }
236 { proportion = 1. / 2.; }
237 { proportion = 2. / 3.; }
238 { proportion = 3. / 4.; }
239 ];
240 default-column-width.proportion = 1. / 2.;
241 preset-window-heights = [
242 { proportion = 1. / 3.; }
243 { proportion = 1. / 2.; }
244 { proportion = 2. / 3.; }
245 { proportion = 1.; }
246 ];
247
248 always-center-single-column = true;
49 }; 249 };
50 250
51 cursor.hide-when-typing = true; 251 cursor.hide-when-typing = true;
52 252
253 input = {
254 touchpad.enable = false;
255 trackball = {
256 scroll-method = "on-button-down";
257 scroll-button = 278;
258 };
259 };
260
261 workspaces = {
262 "001" = { name = "pwctl"; open-on-output = "eDP-1"; };
263 "002" = { name = "kpxc"; open-on-output = "eDP-1"; };
264 "003" = { name = "bmgr"; open-on-output = "eDP-1"; };
265 "004" = { name = "term"; open-on-output = "eDP-1"; };
266 "005" = { name = "edit"; open-on-output = "eDP-1"; };
267 "006" = { name = "eff"; open-on-output = "eDP-1"; };
268 "101".name = "comm";
269 "102".name = "web";
270 # "104".name = "read";
271 # "105".name = "mon";
272 "110".name = "vid";
273 "120".name = "bmr";
274 };
275
276 window-rules = [
277 # {
278 # geometry-corner-radius =
279 # let
280 # allCorners = r: { bottom-left = r; bottom-right = r; top-left = r; top-right = r; };
281 # in allCorners 4.;
282 # clip-to-geometry = true;
283 # }
284 {
285 matches = [ { app-id = "^com\.saivert\.pwvucontrol$"; } ];
286 open-on-workspace = "pwctl";
287 open-maximized = true;
288 }
289 {
290 matches = [ { app-id = "^com\.github\.wwmm\.easyeffects$"; } ];
291 open-on-workspace = "eff";
292 open-maximized = true;
293 }
294 {
295 matches = [ { app-id = "^\.blueman-manager-wrapped$"; } ];
296 open-on-workspace = "bmgr";
297 open-maximized = true;
298 }
299 {
300 matches = [ { app-id = "^org\.keepassxc\.KeePassXC$"; } ];
301 block-out-from = "screencast";
302 }
303 {
304 matches = [ { app-id = "^org\.keepassxc\.KeePassXC$"; } ];
305 excludes = [
306 { title = "^Unlock Database.*"; }
307 { title = "^Access Request.*"; }
308 { title = ".*Passkey credentials$"; }
309 ];
310 open-on-workspace = "kpxc";
311 open-maximized = true;
312 open-focused = false;
313 }
314 {
315 matches = [
316 { app-id = "^org\.keepassxc\.KeePassXC$"; title = "^Unlock Database.*"; }
317 { app-id = "^org\.keepassxc\.KeePassXC$"; title = "^Access Request.*"; }
318 { app-id = "^org\.keepassxc\.KeePassXC$"; title = ".*Passkey credentials$"; }
319 ];
320 open-focused = true;
321 open-floating = true;
322 }
323 {
324 matches = [ { app-id = "^kitty-scratch$"; } ];
325 open-on-workspace = "term";
326 open-maximized = true;
327 }
328 {
329 matches = [ { title = "^scratch$"; app-id = "^emacs$"; } ];
330 open-on-workspace = "edit";
331 open-maximized = true;
332 }
333 {
334 matches = [
335 { app-id = "^emacs$"; }
336 { app-id = "^firefox$"; }
337 ];
338 default-column-width.proportion = 2. / 3.;
339 }
340 {
341 matches = [
342 { app-id = "^kitty$"; }
343 { app-id = "^kitty-play$"; }
344 ];
345 default-column-width.proportion = 1. / 3.;
346 }
347 {
348 matches = [
349 { app-id = "^thunderbird$"; }
350 { app-id = "^Element$"; }
351 { app-id = "^Rainbow$"; }
352 ];
353 open-on-workspace = "comm";
354 }
355 {
356 matches = [ { app-id = "^firefox$"; } ];
357 open-on-workspace = "web";
358 open-maximized = true;
359 variable-refresh-rate = true;
360 }
361 # {
362 # matches = [
363 # { app-id = "^evince$"; }
364 # { app-id = "^imv$"; }
365 # { app-id = "^org\.pwmt\.zathura$"; }
366 # ];
367 # open-on-workspace = "read";
368 # }
369 {
370 matches = [ { app-id = "^mpv$"; } ];
371 open-on-workspace = "vid";
372 default-column-width.proportion = 1.;
373 variable-refresh-rate = true;
374 }
375 {
376 matches = [ { app-id = "^kitty-play$"; } ];
377 open-on-workspace = "vid";
378 open-focused = false;
379 }
380 # {
381 # matches = [
382 # { app-id = "^qemu$"; }
383 # { app-id = "^virt-manager$"; }
384 # ];
385 # open-on-workspace = "mon";
386 # }
387 {
388 matches = [ { app-id = "^pdfpc$"; } ];
389 default-column-width.proportion = 1.;
390 }
391 {
392 matches = [ { app-id = "^pdfpc$"; title = "^pdfpc - presentation"; } ];
393 open-on-workspace = "bmr";
394 open-fullscreen = true;
395 }
396 {
397 matches = [
398 { app-id = "^Gimp-"; title = "^Quit GIMP$"; }
399 { app-id = "^org\.kde\.polkit-kde-authentication-agent-1$"; }
400 ];
401 open-floating = true;
402 }
403 ];
404 layer-rules = [
405 { matches = [
406 { namespace = "^notifications$"; }
407 { namespace = "^waybar$"; }
408 ];
409 block-out-from = "screencast";
410 }
411 ];
412
53 binds = with config.lib.niri.actions; { 413 binds = with config.lib.niri.actions; {
414 "Mod+Slash".action = show-hotkey-overlay;
415
54 "Mod+Return".action = spawn terminal; 416 "Mod+Return".action = spawn terminal;
55 "Mod+Q".action = close-window; 417 "Mod+Q".action = close-window;
56 "Mod+D".action = spawn (lib.getExe config.programs.fuzzel.package); 418 "Mod+O".action = spawn (lib.getExe config.programs.fuzzel.package);
57 "Mod+Shift+D".action = spawn (lib.getExe config.programs.fuzzel.package) "--list-executables-in-path"; 419 "Mod+Shift+O".action = spawn (lib.getExe config.programs.fuzzel.package) "--list-executables-in-path";
420
421 "Mod+Alt+E".action = spawn (lib.getExe' config.services.emacs.package "emacsclient") "-c";
422 "Mod+Alt+Y".action = spawn (lib.getExe (pkgs.writeShellApplication {
423 name = "queue-yt-dlp";
424 runtimeInputs = with pkgs; [ wl-clipboard-rs socat ];
425 text = ''
426 socat STDIO UNIX-CONNECT:"$XDG_RUNTIME_DIR"/yt-dlp.sock <<<$'{ "urls": ["'"$(wl-paste)"$'"] }'
427 '';
428 }));
429 "Mod+Alt+L".action = spawn (lib.getExe (pkgs.writeShellApplication {
430 name = "queue-yt-dlp";
431 runtimeInputs = with pkgs; [ wl-clipboard-rs config.programs.kitty.package ];
432 text = ''
433 exec -- kitty --app-id kitty-play --directory "$HOME"/media mpv "$(wl-paste)"
434 '';
435 }));
436
437 "Mod+U".action = spawn (lib.getExe (pkgs.writeShellApplication {
438 name = "qalc-fuzzel";
439 runtimeInputs = with pkgs; [ wl-clipboard-rs libqalculate config.programs.fuzzel.package coreutils findutils libnotify gnugrep ];
440 text = ''
441 RESULTS_DIR="$HOME/.cache/qalc-fuzzel"
442 prev() {
443 FOUND=false
444 while IFS= read -r line; do
445 [[ -n "$line" ]] || continue
446 FOUND=true
447 echo "$line"
448 done < <(export LC_ALL=C.UTF-8; echo; find "$RESULTS_DIR" -type f -printf $'%T@ %p\n' | sort -n | cut -d' ' -f2- | xargs -r cat)
449 $FOUND || echo
450 }
451 FUZZEL_RES=$(prev | fuzzel --dmenu --prompt "qalc> ") || exit $?
452 if [[ "$FUZZEL_RES" =~ .*\ =\ .* ]]; then
453 QALC_RES="$FUZZEL_RES"
454 QALC_RET=0
455 else
456 QALC_RES=$(qalc "$FUZZEL_RES" 2>&1)
457 QALC_RET=$?
458 fi
459 [[ -n "$QALC_RES" ]] || exit 1
460 EXISTING=false
461 set +o pipefail
462 grep -Fxrl "$QALC_RES" "$RESULTS_DIR" | xargs -r touch
463 [[ ''${PIPESTATUS[0]} -eq 0 ]] && EXISTING=true
464 set -o pipefail
465 if [[ $QALC_RET -eq 0 ]] && ! $EXISTING; then
466 set +o pipefail
467 RES_FILE="$RESULTS_DIR"/$(date -uIs).$(tr -Cd 'a-zA-Z0-9' </dev/random | head -c 10)
468 set -o pipefail
469 cat >"$RES_FILE" <<<"$QALC_RES"
470 fi
471 [[ "$QALC_RES" =~ .*\ =\ (.*) ]] && QALC_RES="''${BASH_REMATCH[1]}"
472 [[ $QALC_RET -eq 0 ]] && wl-copy "$QALC_RES"
473 notify-send "$QALC_RES"
474 '';
475 }));
476 "Mod+E".action = spawn (lib.getExe (pkgs.writeShellApplication {
477 name = "emoji-fuzzel";
478 runtimeInputs = with pkgs; [ config.programs.fuzzel.package wtype wl-clipboard-rs ];
479 text = ''
480 FUZZEL_RES=$(fuzzel --dmenu --prompt "emoji> " <"$HOME"/.local/share/emoji-data/list.txt) || exit $?
481 [[ -n "$FUZZEL_RES" ]] || exit 1
482 wl-copy "$(cut -d ':' -f 1 <<<"$FUZZEL_RES" | tr -d '\n')" && wtype -k XF86Paste
483 '';
484 }));
485 "Print".action = spawn (lib.getExe (pkgs.writeShellApplication {
486 name = "screenshot";
487 runtimeInputs = with pkgs; [ grim slurp wl-clipboard-rs coreutils ];
488 text = ''
489 grim -g "$(slurp -b 00000080 -c FFFFFFFF -s 00000000 -w 1)" - \
490 | tee "$HOME/screenshots/$(date +"%Y-%m-%dT%H:%M:%S").png" \
491 | wl-copy --type image/png
492 '';
493 }));
494 "Shift+Print".action = spawn (lib.getExe (pkgs.writeShellApplication {
495 name = "screenshot";
496 runtimeInputs = with pkgs; [ grim niri gojq wl-clipboard-rs coreutils ];
497 text = ''
498 grim -o "$(niri msg -j workspaces | jq -r '.[] | select(.is_focused) | .output')" - \
499 | tee "$HOME/screenshots/$(date +"%Y-%m-%dT%H:%M:%S").png" \
500 | wl-copy --type image/png
501 '';
502 }));
503 "Mod+B".action = with-select-window-action ".workspace_id == ($active_workspace | tonumber)" "{\"Action\":{\"FocusWindow\":{\"id\": .id}}}";
504 "Mod+Shift+B".action = with-select-window-action "true" "{\"Action\":{\"FocusWindow\":{\"id\": .id}}}";
58 505
59 "Mod+H".action = focus-column-left; 506 "Mod+H".action = focus-column-left;
60 "Mod+T".action = focus-window-down; 507 "Mod+T".action = focus-window-down;
@@ -76,23 +523,44 @@ in {
76 "Mod+Shift+Control+N".action = move-workspace-to-monitor-up; 523 "Mod+Shift+Control+N".action = move-workspace-to-monitor-up;
77 "Mod+Shift+Control+S".action = move-workspace-to-monitor-right; 524 "Mod+Shift+Control+S".action = move-workspace-to-monitor-right;
78 525
79 "Mod+G".action = focus-workspace-down; 526 "Mod+G".action = focus-adjacent-workspace "down";
80 "Mod+C".action = focus-workspace-up; 527 "Mod+C".action = focus-adjacent-workspace "up";
528
529 "Mod+Shift+G".action = move-column-to-adjacent-workspace "down";
530 "Mod+Shift+C".action = move-column-to-adjacent-workspace "up";
531
532 "Mod+Shift+Control+G".action = move-workspace-down;
533 "Mod+Shift+Control+C".action = move-workspace-up;
534
535 "Mod+ParenLeft".action = focus-workspace "comm";
536 "Mod+Shift+ParenLeft".action = move-column-to-workspace "comm";
537
538 "Mod+ParenRight".action = focus-workspace "web";
539 "Mod+Shift+ParenRight".action = move-column-to-workspace "web";
540
541 "Mod+BraceRight".action = focus-workspace "read";
542 "Mod+Shift+BraceRight".action = move-column-to-workspace "read";
543
544 "Mod+BraceLeft".action = focus-workspace "mon";
545 "Mod+Shift+BraceLeft".action = move-column-to-workspace "mon";
81 546
82 "Mod+Control+G".action = move-column-to-workspace-down; 547 "Mod+Asterisk".action = focus-workspace "vid";
83 "Mod+Control+C".action = move-column-to-workspace-up; 548 "Mod+Shift+Asterisk".action = move-column-to-workspace "vid";
84 549
85 "Mod+Shift+G".action = move-workspace-down; 550 "Mod+Plus".action = with-unnamed-workspace-action ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}'';
86 "Mod+Shift+C".action = move-workspace-up; 551 "Mod+Shift+Plus".action = with-unnamed-workspace-action ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}}}}'';
87 552
88 "Mod+M".action = consume-window-into-column; 553 "Mod+M".action = consume-or-expel-window-left;
89 "Mod+W".action = expel-window-from-column; 554 "Mod+W".action = consume-or-expel-window-right;
90 555
91 "Mod+F".action = maximize-column; 556 "Mod+R".action = switch-preset-column-width;
92 "Mod+Shift+F".action = fullscreen-window; 557 "Mod+Shift+R".action = switch-preset-window-height;
558 "Mod+F".action = center-column;
559 "Mod+Shift+F".action = maximize-column;
560 "Mod+Shift+Ctrl+F".action = fullscreen-window;
93 561
94 "Mod+Space".action = switch-focus-between-floating-and-tiling; 562 "Mod+V".action = switch-focus-between-floating-and-tiling;
95 "Mod+Shift+Space".action = toggle-window-floating; 563 "Mod+Shift+V".action = toggle-window-floating;
96 564
97 "Mod+Left".action = set-column-width "-10%"; 565 "Mod+Left".action = set-column-width "-10%";
98 "Mod+Down".action = set-window-height "-10%"; 566 "Mod+Down".action = set-window-height "-10%";
@@ -103,36 +571,57 @@ in {
103 action = spawn (lib.getExe niri) "msg" "action" "power-off-monitors"; 571 action = spawn (lib.getExe niri) "msg" "action" "power-off-monitors";
104 allow-when-locked = true; 572 allow-when-locked = true;
105 }; 573 };
574 "Mod+Shift+L".action = spawn loginctl "lock-session";
575 "Mod+Shift+E".action = quit;
576 "Mod+Shift+Minus" = {
577 action = spawn systemctl "suspend";
578 allow-when-locked = true;
579 };
580 "Mod+Shift+Control+Minus" = {
581 action = spawn systemctl "hibernate";
582 allow-when-locked = true;
583 };
584 "Mod+Shift+P" = {
585 action = spawn (lib.getExe pkgs.playerctl) "-a" "pause";
586 allow-when-locked = true;
587 };
106 588
107 "XF86MonBrightnessUp" = { 589 "XF86MonBrightnessUp" = {
108 action = spawn lightctl "-d" "-e4" "-n1" "up"; 590 action = spawn swayosd-client "--brightness" "raise";
109 allow-when-locked = true; 591 allow-when-locked = true;
110 }; 592 };
111 "XF86MonBrightnessDown" = { 593 "XF86MonBrightnessDown" = {
112 action = spawn lightctl "-d" "-e4" "-n1" "down"; 594 action = spawn swayosd-client "--brightness" "lower";
113 allow-when-locked = true; 595 allow-when-locked = true;
114 }; 596 };
115 "XF86AudioRaiseVolume" = { 597 "XF86AudioRaiseVolume" = {
116 action = spawn volumectl "-d" "-u" "up"; 598 action = spawn swayosd-client "--output-volume" "raise";
117 allow-when-locked = true; 599 allow-when-locked = true;
118 }; 600 };
119 "XF86AudioLowerVolume" = { 601 "XF86AudioLowerVolume" = {
120 action = spawn volumectl "-d" "-u" "down"; 602 action = spawn swayosd-client "--output-volume" "lower";
121 allow-when-locked = true; 603 allow-when-locked = true;
122 }; 604 };
123 "XF86AudioMute" = { 605 "XF86AudioMute" = {
124 action = spawn volumectl "-d" "toggle-mute"; 606 action = spawn swayosd-client "--output-volume" "mute-toggle";
125 allow-when-locked = true; 607 allow-when-locked = true;
126 }; 608 };
127 "XF86AudioMicMute" = { 609 "XF86AudioMicMute" = {
128 action = spawn volumectl "-d" "-m" "toggle-mute"; 610 action = spawn swayosd-client "--input-volume" "mute-toggle";
129 allow-when-locked = true; 611 allow-when-locked = true;
130 }; 612 };
131 613
132 "Mod+Semicolon".action = spawn dunstctl "close"; 614 "Mod+Semicolon".action = spawn makoctl "dismiss" "--group";
133 "Mod+Shift+Semicolon".action = spawn dunstctl "close-all"; 615 "Mod+Shift+Semicolon".action = spawn makoctl "dismiss" "--all";
134 "Mod+Period".action = spawn dunstctl "context"; 616 "Mod+Period".action = spawn makoctl "menu" (lib.getExe config.programs.fuzzel.package) "--dmenu";
135 "Mod+Comma".action = spawn dunstctl "history-pop"; 617 "Mod+Comma".action = spawn makoctl "restore";
618
619 "Mod+Control+A".action = focus-or-spawn-action-app_id "com.saivert.pwvucontrol" "pwctl" "pwvucontrol";
620 "Mod+Control+O".action = focus-or-spawn-action-app_id "com.github.wwmm.easyeffects" "eff" "easyeffects";
621 "Mod+Control+P".action = focus-or-spawn-action-app_id "org.keepassxc.KeePassXC" "kpxc" "keepassxc";
622 "Mod+Control+B".action = focus-or-spawn-action-app_id ".blueman-manager-wrapped" "bmgr" "blueman-manager";
623 "Mod+Control+Return".action = focus-or-spawn-action-app_id "kitty-scratch" "term" "kitty" "--app-id" "kitty-scratch";
624 "Mod+Control+E".action = focus-or-spawn-action "select(.app_id == \"emacs\" and .title == \"scratch\")" "edit" "emacsclient" "-c" "--frame-parameters=(quote (name . \"scratch\"))";
136 }; 625 };
137 }; 626 };
138 }; 627 };
diff --git a/accounts/gkleen@sif/niri/mako.nix b/accounts/gkleen@sif/niri/mako.nix
new file mode 100644
index 00000000..0a10555a
--- /dev/null
+++ b/accounts/gkleen@sif/niri/mako.nix
@@ -0,0 +1,115 @@
1{ config, lib, pkgs, ... }:
2{
3 config = {
4 services.mako = {
5 enable = true;
6 font = "Fira Sans 10";
7 format = "<i>%s</i>\\n%b";
8 margin = "2";
9 maxVisible = -1;
10 backgroundColor = "#000000dd";
11 progressColor = "source #223544ff";
12 width = 384;
13 extraConfig = ''
14 outer-margin=1
15 max-history=100
16 max-icon-size=48
17
18 [grouped]
19 format=<b>(%g)</b> <i>%s</i>\n%b
20
21 [urgency=low]
22 text-color=#999999ff
23
24 [urgency=critical]
25 background-color=#900000dd
26
27 [app-name=Element]
28 group-by=summary
29
30 [mode=silent]
31 invisible=1
32 '';
33 package = pkgs.symlinkJoin {
34 name = "${pkgs.mako.name}-wrapped";
35 paths = with pkgs; [ mako ];
36 inherit (pkgs.mako) meta;
37 postBuild = ''
38 rm -r $out/share/dbus-1
39 '';
40 };
41 };
42 systemd.user.services.mako = {
43 Unit = {
44 Description = "Mako notification daemon";
45 PartOf = [ "graphical-session.target" ];
46 };
47 Install = {
48 WantedBy = [ "graphical-session.target" ];
49 };
50 Service = {
51 Type = "dbus";
52 BusName = "org.freedesktop.Notifications";
53 ExecStart = lib.getExe config.services.mako.package;
54 RestartSec = 5;
55 Restart = "always";
56 };
57 };
58
59 systemd.user.services.mako-follows-focus = {
60 Unit = {
61 BindsTo = [ "niri.service" "mako.service" ];
62 After = [ "niri.service" "mako.service" ];
63 };
64 Service = {
65 Type = "simple";
66 Restart = "always";
67 ExecStart = pkgs.writers.writePython3 "mako-follows-focus" {
68 libraries = with pkgs.python3Packages; [];
69 } ''
70 import os
71 import socket
72 import json
73 import subprocess
74
75
76 current_output = None
77 workspaces = []
78
79
80 def output_changed(new_output):
81 global current_output
82
83 if current_output == new_output:
84 return
85
86 current_output = new_output
87 subprocess.run(["makoctl", "reload"])
88
89
90 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
91 sock.connect(os.environ["NIRI_SOCKET"])
92 sock.send(b"\"EventStream\"\n")
93 for line in sock.makefile(buffering=1, encoding='utf-8'):
94 if line_json := json.loads(line):
95 if "WorkspacesChanged" in line_json:
96 workspaces = line_json["WorkspacesChanged"]["workspaces"]
97 for workspace in workspaces:
98 if not workspace["is_focused"]:
99 continue
100 output_changed(workspace["output"])
101 break
102 if "WorkspaceActivated" in line_json and line_json["WorkspaceActivated"]["focused"]: # noqa: E501
103 for workspace in workspaces:
104 if not workspace["id"] == line_json["WorkspaceActivated"]["id"]: # noqa: E501
105 continue
106 output_changed(workspace["output"])
107 break
108 '';
109 };
110 Install = {
111 WantedBy = [ "mako.service" ];
112 };
113 };
114 };
115}
diff --git a/accounts/gkleen@sif/niri/swayosd.nix b/accounts/gkleen@sif/niri/swayosd.nix
new file mode 100644
index 00000000..984927c2
--- /dev/null
+++ b/accounts/gkleen@sif/niri/swayosd.nix
@@ -0,0 +1,65 @@
1{ pkgs, ... }:
2{
3 config = {
4 services.swayosd = {
5 enable = true;
6 topMargin = 0.946154;
7 stylePath = pkgs.runCommand "style.css" {
8 src = pkgs.writeText "style.scss" ''
9 window#osd {
10 padding: 12px 20px;
11 border-radius: 999px;
12 border: none;
13 background: rgba(0, 0, 0, 0.87);
14
15 #container {
16 margin: 16px;
17 }
18
19 image,
20 label {
21 color: rgb(255, 255, 255);
22
23 &:disabled {
24 opacity: 1;
25 color: rgb(84, 84, 84);
26 }
27 }
28
29 progressbar {
30 min-height: 6px;
31 border-radius: 999px;
32 background: transparent;
33 border: none;
34
35 trough, progress {
36 min-height: inherit;
37 border-radius: inherit;
38 border: none;
39 }
40
41 trough {
42 background: rgb(127, 127, 127);
43 }
44 progress {
45 background: rgb(255, 255, 255);
46 }
47
48 &:disabled {
49 opacity: 1;
50
51 trough {
52 background: rgb(19, 19, 19);
53 }
54 progress {
55 background: rgb(38, 38, 38);
56 }
57 }
58 }
59 }
60 '';
61 buildInputs = with pkgs; [sass];
62 } "scss -C --sourcemap=none --style=compact $src $out";
63 };
64 };
65}
diff --git a/accounts/gkleen@sif/niri/waybar.nix b/accounts/gkleen@sif/niri/waybar.nix
index 1a25b581..56a1b648 100644
--- a/accounts/gkleen@sif/niri/waybar.nix
+++ b/accounts/gkleen@sif/niri/waybar.nix
@@ -1,5 +1,7 @@
1{ lib, pkgs, ... }: 1{ lib, config, pkgs, ... }:
2{ 2let
3 swayosd-client = lib.getExe' config.services.swayosd.package "swayosd-client";
4in {
3 config = { 5 config = {
4 programs.waybar = { 6 programs.waybar = {
5 enable = true; 7 enable = true;
@@ -22,16 +24,66 @@
22 output = [ "eDP-1" "DP-2" "DP-3" ]; 24 output = [ "eDP-1" "DP-2" "DP-3" ];
23 modules-left = [ "niri/workspaces" ]; 25 modules-left = [ "niri/workspaces" ];
24 modules-center = [ "niri/window" ]; 26 modules-center = [ "niri/window" ];
25 modules-right = [ # "custom/worktime" "custom/worktime-today" 27 modules-right = [ "custom/worktime" "custom/worktime-today"
26 "custom/weather" 28 "custom/weather"
27 # "custom/keymap" 29 "custom/keymap"
28 "privacy" "tray" "wireplumber" "backlight" "battery" "idle_inhibitor" "clock" ]; 30 "privacy" "tray" "wireplumber" "backlight" "battery" "idle_inhibitor" "custom/mako" "clock" ];
29 31
32 "custom/mako" = {
33 format = "{}";
34 return-type = "json";
35 exec = pkgs.writers.writePython3 "mako-silent" { libraries = [ pkgs.python3Packages.dbus-next ]; } ''
36 from dbus_next.aio import MessageBus
37
38 import asyncio
39
40 import json
41
42
43 loop = asyncio.new_event_loop()
44 asyncio.set_event_loop(loop)
45
46
47 async def main():
48 bus = await MessageBus().connect()
49 # the introspection xml would normally be included in your project, but
50 # this is convenient for development
51 introspection = await bus.introspect('org.freedesktop.Notifications', '/fr/emersion/Mako') # noqa: E501
52
53 obj = bus.get_proxy_object('org.freedesktop.Notifications', '/fr/emersion/Mako', introspection) # noqa: E501
54 mako = obj.get_interface('fr.emersion.Mako')
55 properties = obj.get_interface('org.freedesktop.DBus.Properties')
56
57 async def print_mode():
58 modes = await mako.get_modes()
59 is_silent = "silent" in modes
60 icon = "&#xf009b;" if is_silent else "&#xf009a;"
61 text = f"<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>" # noqa: E501
62 if is_silent:
63 text = f"<span color=\"#ffffff\">{text}</span>"
64 print(json.dumps({'text': text}, separators=(',', ':')), flush=True) # noqa: E501
65
66 async def on_properties_changed(interface_name, changed_properties, invalidated_properties): # noqa: E501
67 if "Modes" not in invalidated_properties:
68 return
69
70 await print_mode()
71
72 properties.on_properties_changed(on_properties_changed)
73 await print_mode()
74
75 await loop.create_future()
76
77
78 loop.run_until_complete(main())
79 '';
80 on-click = "makoctl mode -t silent";
81 };
30 "custom/weather" = { 82 "custom/weather" = {
31 format = "{}"; 83 format = "{}";
32 tooltip = true; 84 tooltip = true;
33 interval = 3600; 85 interval = 3600;
34 exec = "${lib.getExe pkgs.wttrbar} --hide-conditions --nerd --custom-indicator \"<span font=\\\"Symbols Nerd Font Mono\\\" size=\\\"120%\\\">{ICON}</span> {FeelsLikeC}°\""; 86 exec = "${lib.getExe pkgs.wttrbar} --hide-conditions --nerd --custom-indicator \"<span font=\\\"Symbols Nerd Font Mono\\\" size=\\\"100%\\\">{ICON}</span> {FeelsLikeC}°\"";
35 return-type = "json"; 87 return-type = "json";
36 }; 88 };
37 "custom/keymap" = { 89 "custom/keymap" = {
@@ -41,8 +93,6 @@
41 exec = pkgs.writers.writePython3 "keymap" {} '' 93 exec = pkgs.writers.writePython3 "keymap" {} ''
42 import os 94 import os
43 import socket 95 import socket
44 import re
45 import subprocess
46 import json 96 import json
47 97
48 98
@@ -55,33 +105,35 @@
55 print(json.dumps({'text': short, 'tooltip': keymap}, separators=(',', ':')), flush=True) # noqa: E501 105 print(json.dumps({'text': short, 'tooltip': keymap}, separators=(',', ':')), flush=True) # noqa: E501
56 106
57 107
58 r = subprocess.run(["hyprctl", "devices", "-j"], check=True, stdout=subprocess.PIPE, text=True) # noqa: E501 108 keyboard_layouts = []
59 for keyboard in json.loads(r.stdout)['keyboards']:
60 if keyboard['name'] != "at-translated-set-2-keyboard":
61 continue
62 output(keyboard['active_keymap'])
63 109
64 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 110 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
65 sock.connect(os.environ["XDG_RUNTIME_DIR"] + "/hypr/" + os.environ["HYPRLAND_INSTANCE_SIGNATURE"] + "/.socket2.sock") # noqa: E501 111 sock.connect(os.environ["NIRI_SOCKET"])
66 expected = re.compile(r'^activelayout>>at-translated-set-2-keyboard,(?P<keymap>.+)$') # noqa: E501 112 sock.send(b"\"EventStream\"\n")
67 for line in sock.makefile(buffering=1, encoding='utf-8'): 113 for line in sock.makefile(buffering=1, encoding='utf-8'):
68 if match := expected.match(line): 114 if line_json := json.loads(line):
69 output(match.group("keymap")) 115 if "KeyboardLayoutsChanged" in line_json:
116 keyboard_layouts = line_json["KeyboardLayoutsChanged"]["keyboard_layouts"]["names"] # noqa: E501
117 output(keyboard_layouts[line_json["KeyboardLayoutsChanged"]["keyboard_layouts"]["current_idx"]]) # noqa: E501
118 if "KeyboardLayoutSwitched" in line_json:
119 output(keyboard_layouts[line_json["KeyboardLayoutSwitched"]["idx"]]) # noqa: E501
70 ''; 120 '';
71 on-click = "hyprctl switchxkblayout at-translated-set-2-keyboard next"; 121 on-click = "niri msg action switch-layout next";
72 }; 122 };
73 "custom/worktime" = { 123 "custom/worktime" = {
74 interval = 60; 124 interval = 60;
75 exec = lib.getExe pkgs.worktime; 125 exec = "${lib.getExe pkgs.worktime} time --waybar";
126 return-type = "json";
76 tooltip = false; 127 tooltip = false;
77 }; 128 };
78 "custom/worktime-today" = { 129 "custom/worktime-today" = {
79 interval = 60; 130 interval = 60;
80 exec = "${lib.getExe pkgs.worktime} today"; 131 exec = "${lib.getExe pkgs.worktime} today --waybar";
132 return-type = "json";
81 tooltip = false; 133 tooltip = false;
82 }; 134 };
83 "niri/workspaces" = { 135 "niri/workspaces" = {
84 all-outputs = true; 136 ignore = ["eff" "pwctl" "kpxc" "bmgr" "edit" "term"];
85 }; 137 };
86 "niri/window" = { 138 "niri/window" = {
87 separate-outputs = true; 139 separate-outputs = true;
@@ -142,8 +194,8 @@
142 icon-size = iconSize; 194 icon-size = iconSize;
143 tooltip-format = "{percent}%"; 195 tooltip-format = "{percent}%";
144 format-icons = ["&#xf00da;" "&#xf00db;" "&#xf00dc;" "&#xf00dd;" "&#xf00de;" "&#xf00df;" "&#xf00e0;"]; 196 format-icons = ["&#xf00da;" "&#xf00db;" "&#xf00dc;" "&#xf00dd;" "&#xf00de;" "&#xf00df;" "&#xf00e0;"];
145 on-scroll-up = "lightctl -d -e4 -n1 up"; 197 on-scroll-up = "${swayosd-client} --brightness raise";
146 on-scroll-down = "lightctl -d -e4 -n1 down"; 198 on-scroll-down = "${swayosd-client} --brightness lower";
147 }; 199 };
148 wireplumber = { 200 wireplumber = {
149 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>"; 201 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
@@ -152,9 +204,9 @@
152 format-icons = ["&#xf057f;" "&#xf0580;" "&#xf057e;"]; 204 format-icons = ["&#xf057f;" "&#xf0580;" "&#xf057e;"];
153 format-muted = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">&#xf075f;</span>"; 205 format-muted = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">&#xf075f;</span>";
154 # ignored-sinks = ["Easy Effects Sink"]; 206 # ignored-sinks = ["Easy Effects Sink"];
155 on-scroll-up = "volumectl -d -u up"; 207 on-scroll-up = "${swayosd-client} --output-volume raise";
156 on-scroll-down = "volumectl -d -u down"; 208 on-scroll-down = "${swayosd-client} --output-volume lower";
157 on-click = "volumectl -d toggle-mute"; 209 on-click = "${swayosd-client} --output-volume mute-toggle";
158 }; 210 };
159 } 211 }
160 { 212 {
@@ -167,7 +219,7 @@
167 modules-right = [ "clock" ]; 219 modules-right = [ "clock" ];
168 220
169 "niri/workspaces" = { 221 "niri/workspaces" = {
170 all-outputs = false; 222 ignore = ["pwctl" "kpxc" "bmgr" "edit" "term"];
171 }; 223 };
172 "niri/window" = { 224 "niri/window" = {
173 separate-outputs = true; 225 separate-outputs = true;
@@ -193,7 +245,7 @@
193 245
194 * { 246 * {
195 border: none; 247 border: none;
196 font-family: "Fira Sans Nerd Font"; 248 font-family: "Fira Sans";
197 font-size: 10pt; 249 font-size: 10pt;
198 min-height: 0; 250 min-height: 0;
199 } 251 }
@@ -204,10 +256,10 @@
204 } 256 }
205 257
206 .modules-left { 258 .modules-left {
207 margin-left: 9px; 259 margin-left: 12px;
208 } 260 }
209 .modules-right { 261 .modules-right {
210 margin-right: 9px; 262 margin-right: 12px;
211 } 263 }
212 264
213 .module { 265 .module {
@@ -215,13 +267,11 @@
215 } 267 }
216 268
217 #workspaces button { 269 #workspaces button {
218 color: @grey;
219 }
220 #workspaces button.hosting-monitor {
221 color: @white; 270 color: @white;
271 padding: 2px 5px;
222 } 272 }
223 #workspaces button.visible { 273 #workspaces button.empty {
224 color: @blue; 274 color: @grey;
225 } 275 }
226 #workspaces button.active { 276 #workspaces button.active {
227 color: @green; 277 color: @green;
@@ -234,21 +284,26 @@
234 color: @grey; 284 color: @grey;
235 margin: 0 5px; 285 margin: 0 5px;
236 } 286 }
237 #custom-weather, #custom-worktime-today { 287 #custom-weather {
238 margin-right: 3px; 288 margin-right: 3px;
239 } 289 }
240 #custom-keymap, #custom-weather { 290 #custom-keymap {
241 margin-left: 3px; 291 margin-left: 3px;
292 margin-right: 3px;
242 } 293 }
243 294
244 #tray { 295 #tray {
245 margin: 0; 296 margin: 0;
246 } 297 }
247 #battery, #idle_inhibitor, #backlight, #wireplumber { 298 #battery, #idle_inhibitor, #backlight, #wireplumber, #custom-mako {
248 color: @grey; 299 color: @grey;
249 margin: 0 5px 0 2px; 300 margin: 0 5px 0 2px;
250 } 301 }
251 #idle_inhibitor { 302 #idle_inhibitor {
303 margin-right: 4px;
304 margin-left: 6px;
305 }
306 #custom-mako {
252 margin-right: 2px; 307 margin-right: 2px;
253 margin-left: 3px; 308 margin-left: 3px;
254 } 309 }
@@ -270,6 +325,12 @@
270 #idle_inhibitor.activated { 325 #idle_inhibitor.activated {
271 color: @white; 326 color: @white;
272 } 327 }
328 #custom-worktime.running, #custom-worktime-today.running {
329 color: @white;
330 }
331 #custom-worktime.over, #custom-worktime-today.over {
332 color: @orange;
333 }
273 334
274 #idle_inhibitor { 335 #idle_inhibitor {
275 padding-top: 1px; 336 padding-top: 1px;
@@ -277,7 +338,7 @@
277 338
278 #privacy { 339 #privacy {
279 color: @red; 340 color: @red;
280 margin: -1px 2px 0px 5px; 341 margin: -1px 4px 0px 3px;
281 } 342 }
282 #clock { 343 #clock {
283 /* margin-right: 5px; */ 344 /* margin-right: 5px; */