summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@sif')
-rw-r--r--accounts/gkleen@sif/default.nix309
-rw-r--r--accounts/gkleen@sif/hyprland.nix425
-rw-r--r--accounts/gkleen@sif/niri/default.nix139
-rw-r--r--accounts/gkleen@sif/niri/waybar.nix288
4 files changed, 433 insertions, 728 deletions
diff --git a/accounts/gkleen@sif/default.nix b/accounts/gkleen@sif/default.nix
index 83dcf989..bcfd1224 100644
--- a/accounts/gkleen@sif/default.nix
+++ b/accounts/gkleen@sif/default.nix
@@ -92,6 +92,7 @@ in {
92 home-manager.users.${userName} = { 92 home-manager.users.${userName} = {
93 imports = [ 93 imports = [
94 ./libvirt 94 ./libvirt
95 ./niri
95 flakeInputs.nix-index-database.hmModules.nix-index 96 flakeInputs.nix-index-database.hmModules.nix-index
96 flakeInputs.impermanence.nixosModules.home-manager.impermanence 97 flakeInputs.impermanence.nixosModules.home-manager.impermanence
97 ]; 98 ];
@@ -250,287 +251,6 @@ in {
250 "kitty_mod+m" = "detach_window ask"; 251 "kitty_mod+m" = "detach_window ask";
251 }; 252 };
252 }; 253 };
253 waybar = {
254 enable = true;
255 systemd = {
256 enable = true;
257 target = "hyprland-session.target";
258 };
259 settings = let
260 windowRewrites = {
261 "(.*) — Mozilla Firefox" = "$1";
262 "(.*) - Mozilla Thunderbird" = "$1";
263 "(.*) - mpv" = "$1";
264 };
265 iconSize = 11;
266 in [
267 {
268 layer = "top";
269 position = "top";
270 height = 14;
271 output = [ "eDP-1" "DP-2" "DP-3" ];
272 modules-left = [ "hyprland/workspaces" ];
273 modules-center = [ "hyprland/window" ];
274 modules-right = [ # "custom/worktime" "custom/worktime-today"
275 "custom/weather" "custom/keymap" "privacy" "tray" "wireplumber" "backlight" "battery" "idle_inhibitor" "clock" ];
276
277 "custom/weather" = {
278 format = "{}";
279 tooltip = true;
280 interval = 3600;
281 exec = "${lib.getExe pkgs.wttrbar} --hide-conditions --nerd --custom-indicator \"<span font=\\\"Symbols Nerd Font Mono\\\" size=\\\"120%\\\">{ICON}</span> {FeelsLikeC}°\"";
282 return-type = "json";
283 };
284 "custom/keymap" = {
285 format = "{}";
286 tooltip = true;
287 return-type = "json";
288 exec = pkgs.writers.writePython3 "keymap" {} ''
289 import os
290 import socket
291 import re
292 import subprocess
293 import json
294
295
296 def output(keymap):
297 short = keymap
298 if keymap == "English (programmer Dvorak)":
299 short = "dvp"
300 elif keymap == "English (US)":
301 short = "<span color=\"#ffffff\">us</span>"
302 print(json.dumps({'text': short, 'tooltip': keymap}, separators=(',', ':')), flush=True) # noqa: E501
303
304
305 r = subprocess.run(["hyprctl", "devices", "-j"], check=True, stdout=subprocess.PIPE, text=True) # noqa: E501
306 for keyboard in json.loads(r.stdout)['keyboards']:
307 if keyboard['name'] != "at-translated-set-2-keyboard":
308 continue
309 output(keyboard['active_keymap'])
310
311 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
312 sock.connect(os.environ["XDG_RUNTIME_DIR"] + "/hypr/" + os.environ["HYPRLAND_INSTANCE_SIGNATURE"] + "/.socket2.sock") # noqa: E501
313 expected = re.compile(r'^activelayout>>at-translated-set-2-keyboard,(?P<keymap>.+)$') # noqa: E501
314 for line in sock.makefile(buffering=1, encoding='utf-8'):
315 if match := expected.match(line):
316 output(match.group("keymap"))
317 '';
318 on-click = "hyprctl switchxkblayout at-translated-set-2-keyboard next";
319 };
320 "custom/worktime" = {
321 interval = 60;
322 exec = getExe pkgs.worktime;
323 tooltip = false;
324 };
325 "custom/worktime-today" = {
326 interval = 60;
327 exec = "${getExe pkgs.worktime} today";
328 tooltip = false;
329 };
330 "hyprland/workspaces" = {
331 all-outputs = true;
332 };
333 "hyprland/window" = {
334 separate-outputs = true;
335 icon = true;
336 icon-size = 14;
337 rewrite = windowRewrites;
338 };
339 clock = {
340 interval = 1;
341 # timezone = "Europe/Berlin";
342 format = "W{:%V-%u %F %H:%M:%S%Ez}";
343 tooltip-format = "<tt><small>{calendar}</small></tt>";
344 calendar = {
345 mode = "year";
346 mode-mon-col = 3;
347 weeks-pos = "left";
348 on-scroll = 1;
349 format = {
350 months = "<span color='#ffead3'><b>{}</b></span>";
351 days = "{}";
352 weeks = "<span color='#99ffdd'><b>{}</b></span>";
353 weekdays = "<span color='#ffcc66'><b>{}</b></span>";
354 today = "<span color='#ff6699'><b>{}</b></span>";
355 };
356 };
357 };
358 battery = {
359 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
360 icon-size = iconSize - 2;
361 states = { warning = 30; critical = 15; };
362 format-icons = ["&#xf008e;" "&#xf007a;" "&#xf007b;" "&#xf007c;" "&#xf007d;" "&#xf007e;" "&#xf007f;" "&#xf0080;" "&#xf0081;" "&#xf0082;" "&#xf0079;" ];
363 format-charging = "&#xf0084;";
364 format-plugged = "&#xf06a5;";
365 tooltip-format = "{capacity}% {timeTo}";
366 interval = 20;
367 };
368 tray = {
369 icon-size = 16;
370 # show-passive-items = true;
371 spacing = 1;
372 };
373 privacy = {
374 icon-spacing = 7;
375 icon-size = iconSize;
376 modules = [
377 { type = "screenshare"; }
378 { type = "audio-in"; }
379 ];
380 };
381 idle_inhibitor = {
382 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
383 icon-size = iconSize;
384 format-icons = { activated = "&#xf0208;"; deactivated = "&#xf0209;"; };
385 timeout = 120;
386 };
387 backlight = {
388 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
389 icon-size = iconSize;
390 tooltip-format = "{percent}%";
391 format-icons = ["&#xf00da;" "&#xf00db;" "&#xf00dc;" "&#xf00dd;" "&#xf00de;" "&#xf00df;" "&#xf00e0;"];
392 on-scroll-up = "lightctl -d -e4 -n1 up";
393 on-scroll-down = "lightctl -d -e4 -n1 down";
394 };
395 wireplumber = {
396 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
397 icon-size = iconSize;
398 tooltip-format = "{volume}% {node_name}";
399 format-icons = ["&#xf057f;" "&#xf0580;" "&#xf057e;"];
400 format-muted = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">&#xf075f;</span>";
401 # ignored-sinks = ["Easy Effects Sink"];
402 on-scroll-up = "volumectl -d -u up";
403 on-scroll-down = "volumectl -d -u down";
404 on-click = "volumectl -d toggle-mute";
405 };
406 }
407 {
408 layer = "top";
409 position = "top";
410 height = 14;
411 output = [ "!eDP-1" "!DP-2" "!DP-3" ];
412 modules-left = [ "hyprland/workspaces" ];
413 modules-center = [ "hyprland/window" ];
414 modules-right = [ "clock" ];
415
416 "hyprland/workspaces" = {
417 all-outputs = false;
418 };
419 "hyprland/window" = {
420 separate-outputs = true;
421 icon = true;
422 icon-size = 14;
423 rewrite = windowRewrites;
424 };
425 clock = {
426 interval = 1;
427 # timezone = "Europe/Berlin";
428 format = "{:%H:%M}";
429 tooltip-format = "W{:%V-%u %F %H:%M:%S%Ez}";
430 };
431 }
432 ];
433 style = ''
434 @define-color white #ffffff;
435 @define-color grey #555555;
436 @define-color blue #1a8fff;
437 @define-color green #23fd00;
438 @define-color orange #f28a21;
439 @define-color red #f2201f;
440
441 * {
442 border: none;
443 font-family: "Fira Sans Nerd Font";
444 font-size: 10pt;
445 min-height: 0;
446 }
447
448 window#waybar {
449 background-color: rgba(0, 0, 0, 0.66);
450 color: @white;
451 }
452
453 .modules-left {
454 margin-left: 9px;
455 }
456 .modules-right {
457 margin-right: 9px;
458 }
459
460 .module {
461 margin: 0 5px;
462 }
463
464 #workspaces button {
465 color: @grey;
466 }
467 #workspaces button.hosting-monitor {
468 color: @white;
469 }
470 #workspaces button.visible {
471 color: @blue;
472 }
473 #workspaces button.active {
474 color: @green;
475 }
476 #workspaces button.urgent {
477 color: @red;
478 }
479
480 #custom-weather, #custom-keymap, #custom-worktime, #custom-worktime-today {
481 color: @grey;
482 margin: 0 5px;
483 }
484 #custom-weather, #custom-worktime-today {
485 margin-right: 3px;
486 }
487 #custom-keymap, #custom-weather {
488 margin-left: 3px;
489 }
490
491 #tray {
492 margin: 0;
493 }
494 #battery, #idle_inhibitor, #backlight, #wireplumber {
495 color: @grey;
496 margin: 0 5px 0 2px;
497 }
498 #idle_inhibitor {
499 margin-right: 2px;
500 margin-left: 3px;
501 }
502 #battery {
503 margin-right: 3px;
504 }
505 #battery.discharging {
506 color: @white;
507 }
508 #battery.warning {
509 color: @orange;
510 }
511 #battery.critical {
512 color: @red;
513 }
514 #battery.charging {
515 color: @white;
516 }
517 #idle_inhibitor.activated {
518 color: @white;
519 }
520
521 #idle_inhibitor {
522 padding-top: 1px;
523 }
524
525 #privacy {
526 color: @red;
527 margin: -1px 2px 0px 5px;
528 }
529 #clock {
530 /* margin-right: 5px; */
531 }
532 '';
533 };
534 wpaperd = { 254 wpaperd = {
535 enable = true; 255 enable = true;
536 settings.default = { 256 settings.default = {
@@ -543,7 +263,7 @@ in {
543 enable = true; 263 enable = true;
544 settings = { 264 settings = {
545 main = { 265 main = {
546 terminal = lib.getExe pkgs.kitty; 266 terminal = lib.getExe cfg.programs.kitty.package;
547 layer = "overlay"; 267 layer = "overlay";
548 icon-theme = "Paper"; 268 icon-theme = "Paper";
549 font = "Fira Sans"; 269 font = "Fira Sans";
@@ -639,13 +359,13 @@ in {
639 enable = true; 359 enable = true;
640 events = [ 360 events = [
641 { event = "before-sleep"; command = lockCommand; } 361 { event = "before-sleep"; command = lockCommand; }
642 { event = "after-resume"; command = "${cfg.wayland.windowManager.hyprland.package}/bin/hyprctl dispatch dpms on"; } 362 # { event = "after-resume"; command = "${cfg.wayland.windowManager.hyprland.package}/bin/hyprctl dispatch dpms on"; }
643 { event = "lock"; command = lockCommand; } 363 { event = "lock"; command = lockCommand; }
644 ]; 364 ];
645 timeouts = [ 365 timeouts = [
646 { timeout = 300; 366 # { timeout = 300;
647 command = "${cfg.wayland.windowManager.hyprland.package}/bin/hyprctl dispatch dpms off"; 367 # command = "${cfg.wayland.windowManager.hyprland.package}/bin/hyprctl dispatch dpms off";
648 } 368 # }
649 { timeout = 330; command = lockCommand; } 369 { timeout = 330; command = lockCommand; }
650 ]; 370 ];
651 extraArgs = [ 371 extraArgs = [
@@ -927,23 +647,6 @@ in {
927 color-scheme = "prefer-dark"; 647 color-scheme = "prefer-dark";
928 }; 648 };
929 }; 649 };
930
931 wayland.windowManager.hyprland = {
932 enable = true;
933 settings = import ./hyprland.nix inputs;
934 };
935
936 xdg.portal = {
937 enable = true;
938 xdgOpenUsePortal = true;
939 config = {
940 common.default = [ "gtk" ];
941 hyprland.default = [ "gtk" "kde" "hyprland" ];
942 };
943 extraPortals = with pkgs; [
944 xdg-desktop-portal-kde xdg-desktop-portal-gtk xdg-desktop-portal-wlr xdg-desktop-portal-hyprland
945 ];
946 };
947 }; 650 };
948 }; 651 };
949} 652}
diff --git a/accounts/gkleen@sif/hyprland.nix b/accounts/gkleen@sif/hyprland.nix
deleted file mode 100644
index 90ae689a..00000000
--- a/accounts/gkleen@sif/hyprland.nix
+++ /dev/null
@@ -1,425 +0,0 @@
1{ pkgs, lib, config, userName, ... }:
2let
3 cfg = config.home-manager.users.${userName};
4in {
5 monitor = [
6 ",preferred,auto,auto,bitdepth,8"
7 "eDP-1,3840x2160@60,auto,1.5,bitdepth,8"
8 ];
9
10 "$terminal" = "kitty";
11 "$menu" = "fuzzel";
12
13 env = [
14 "NIXOS_OZONE_WL,1"
15 "QT_QPA_PLATFORM,wayland"
16 "QT_WAYLAND_DISABLE_WINDOWDECORATION,1"
17 "GDK_BACKEND,wayland"
18 "GDK_SCALE,0.66"
19 "QT_AUTO_SCREEN_SCALE_FACTOR,1"
20 "SDL_VIDEODRIVER,wayland"
21 # "AQ_DRM_DEVICES,/dev/dri/by-path/pci-0000:01:00.0-card"
22 "__NV_PRIME_RENDER_OFFLOAD,1"
23 "__NV_PRIME_RENDER_OFFLOAD_PROVIDER,NVIDIA-G0"
24 "__GLX_VENDOR_LIBRARY_NAME,nvidia"
25 "__VK_LAYER_NV_optimus,NVIDIA_only"
26 ];
27
28 xwayland.force_zero_scaling = true;
29
30 general = {
31 gaps_in = 3;
32 gaps_out = 9;
33 "col.active_border" = "rgba(33ccffee) rgba(00ff95ee) 45deg";
34 "col.inactive_border" = "rgba(595959aa)";
35
36 resize_on_border = false;
37
38 allow_tearing = false;
39
40 layout = "dwindle";
41 };
42
43 decoration = {
44 rounding = 5;
45 dim_special = 0.0;
46 };
47
48 animations = {
49 enabled = true;
50 bezier = "myBezier, 0.05, 0.9, 0.1, 1.05";
51 animation = [
52 "windows, 1, 1, default, popin 80%"
53 "windowsMove, 0"
54 # "windows, 1, 7, myBezier"
55 # "windowsOut, 1, 7, myBezier, popin 80%"
56 "border, 1, 10, default"
57 "borderangle, 1, 8, default"
58 "fade, 1, 1, default"
59 "workspaces, 1, 1, default, fade"
60 # "workspaces, 1, 6, default"
61 ];
62 };
63
64 dwindle = {
65 pseudotile = false;
66 preserve_split = true;
67 };
68
69 master = {
70 new_status = "master";
71 };
72
73 misc = {
74 disable_hyprland_logo = true;
75 disable_splash_rendering = true;
76 # focus_on_activate = true;
77 mouse_move_enables_dpms = true;
78 key_press_enables_dpms = true;
79 new_window_takes_over_fullscreen = 1;
80 exit_window_retains_fullscreen = true;
81 };
82
83 cursor = {
84 use_cpu_buffer = true;
85 hide_on_key_press = true;
86 # no_hardware_cursors = 0;
87 };
88
89 input = {
90 kb_layout = "us,us";
91 kb_variant = "dvp,";
92 kb_model = "";
93 kb_options = "compose:caps,grp:win_space_toggle";
94 kb_rules = "";
95
96 follow_mouse = 1;
97
98 sensitivity = 0;
99
100 touchpad = {
101 natural_scroll = false;
102 };
103 };
104
105 device = [
106 { name = "synaptics-tm3512-010";
107 sensitivity = 0.4;
108 }
109 { name = "tpps/2-elan-trackpoint";
110 sensitivity = 0.2;
111 }
112 { name = "logitech-ergo-m575";
113 sensitivity = 1.333;
114 }
115 ];
116
117 gestures = {
118 workspace_swipe = false;
119 };
120
121 dwindle = {
122 # no_gaps_when_only = 1;
123 };
124
125 "$mainMod" = "SUPER";
126
127 bind = [
128 "$mainMod, return, exec, $terminal"
129 "$mainMod, Q, killactive"
130 "$mainMod SHIFT, Q, exec, hyprctl kill"
131 "$mainMod, V, togglefloating"
132 "$mainMod, D, exec, $menu"
133 "$mainMod SHIFT, D, exec, $menu --list-executables-in-path"
134 # "$mainMod, J, togglesplit,"
135
136 "$mainMod SHIFT, L, exec, loginctl lock-session"
137 "$mainMod SHIFT, E, exit"
138
139 "$mainMod, left, movefocus, l"
140 "$mainMod, right, movefocus, r"
141 "$mainMod, up, movefocus, u"
142 "$mainMod, down, movefocus, d"
143 "$mainMod SHIFT, left, swapwindow, l"
144 "$mainMod SHIFT, right, swapwindow, r"
145 "$mainMod SHIFT, up, swapwindow, u"
146 "$mainMod SHIFT, down, swapwindow, d"
147
148 "$mainMod, N, cyclenext, tiled"
149 "$mainMod, T, cyclenext, prev tiled"
150 "$mainMod SHIFT, N, swapnext"
151 "$mainMod SHIFT, T, swapnext, prev"
152
153 "$mainMod, G, focusmonitor, 0"
154 "$mainMod, C, focusmonitor, 1"
155 "$mainMod, R, focusmonitor, 2"
156 "$mainMod, L, focusmonitor, 3"
157
158 "$mainMod CTRL, G, movecurrentworkspacetomonitor, 0"
159 "$mainMod CTRL, C, movecurrentworkspacetomonitor, 1"
160 "$mainMod CTRL, R, movecurrentworkspacetomonitor, 2"
161 "$mainMod CTRL, L, movecurrentworkspacetomonitor, 3"
162
163 "$mainMod, F, fullscreen, 1"
164 "$mainMod SHIFT, F, fullscreen, 0"
165 "$mainMod CTRL SHIFT, F, fullscreenstate, 1, 2"
166
167 "$mainMod, code:14, workspace, 1"
168 "$mainMod, code:17, workspace, 2"
169 "$mainMod, code:13, workspace, 3"
170 "$mainMod, code:18, workspace, 4"
171 "$mainMod, code:12, workspace, 5"
172 "$mainMod, code:19, workspace, 6"
173 "$mainMod, code:11, workspace, 7"
174 "$mainMod, code:20, workspace, 8"
175 "$mainMod, code:15, workspace, 9"
176 "$mainMod, code:16, workspace, 10"
177
178 "$mainMod SHIFT, code:14, movetoworkspacesilent, 1"
179 "$mainMod SHIFT, code:17, movetoworkspacesilent, 2"
180 "$mainMod SHIFT, code:13, movetoworkspacesilent, 3"
181 "$mainMod SHIFT, code:18, movetoworkspacesilent, 4"
182 "$mainMod SHIFT, code:12, movetoworkspacesilent, 5"
183 "$mainMod SHIFT, code:19, movetoworkspacesilent, 6"
184 "$mainMod SHIFT, code:11, movetoworkspacesilent, 7"
185 "$mainMod SHIFT, code:20, movetoworkspacesilent, 8"
186 "$mainMod SHIFT, code:15, movetoworkspacesilent, 9"
187 "$mainMod SHIFT, code:16, movetoworkspacesilent, 10"
188
189 "$mainMod, semicolon, exec, dunstctl close"
190 "$mainMod SHIFT, semicolon, exec, dunstctl close-all"
191 "$mainMod, period, exec, dunstctl context"
192 "$mainMod, comma, exec, dunstctl history-pop"
193
194 "$mainMod ALT, E, exec, emacsclient -c"
195 "$mainMod ALT, Y, exec, ${pkgs.writeShellScript "yt-dlp" ''
196 export PATH="${lib.makeBinPath (with pkgs; [ wl-clipboard-rs socat ])}:$PATH"
197 socat STDIO UNIX-CONNECT:"$XDG_RUNTIME_DIR"/yt-dlp.sock <<<$'{ "urls": ["'"$(wl-paste)"$'"] }'
198 ''}"
199 "$mainMod ALT, L, exec, ${pkgs.writeShellScript "mpv" ''
200 export PATH="${lib.makeBinPath (with pkgs; [ wl-clipboard-rs ])}:$PATH"
201 exec mpv "$(wl-paste)"
202 ''}"
203
204 ", Print, exec, ${pkgs.writeShellScript "screenshot" ''
205 export PATH="${lib.makeBinPath (with pkgs; [ grim slurp wl-clipboard-rs coreutils ])}:$PATH"
206
207 outFile="$HOME/screenshots/$(date +"%Y-%m-%dT%H:%M:%S").png"
208 grim -g "$(slurp -b 00000080 -c FFFFFFFF -s 00000000 -w 1)" "$outFile"
209 wl-copy --type image/png <"$outFile"
210 ''}"
211 "SHIFT, Print, exec, ${pkgs.writeShellScript "screenshot" ''
212 export PATH="${lib.makeBinPath (with pkgs; [ grim jq wl-clipboard-rs coreutils ])}:$PATH"
213
214 outFile="$HOME/screenshots/$(date +"%Y-%m-%dT%H:%M:%S").png"
215 grim -o "$(hyprctl monitors -j | jq -r '.[] | select(.focused) | .name')" "$outFile"
216 wl-copy --type image/png <"$outFile"
217 ''}"
218 "CTRL SHIFT, Print, exec, ${pkgs.runCommand "picker" {
219 buildInputs = [ pkgs.makeWrapper ];
220 } ''
221 makeWrapper ${lib.getExe pkgs.hyprpicker} $out \
222 --prefix PATH : ${lib.makeBinPath [pkgs.wl-clipboard-rs]}
223 ''} -a"
224 "$mainMod, M, exec, ${pkgs.writeShellScript "qalc-fuzzel" ''
225 export PATH="${lib.makeBinPath (with pkgs; [ wl-clipboard-rs libqalculate cfg.programs.fuzzel.package coreutils findutils libnotify gnugrep ])}:$PATH"
226
227 RESULTS_DIR="$HOME/.cache/qalc-fuzzel"
228 prev() {
229 FOUND=false
230 while IFS= read -r line; do
231 [[ -n "$line" ]] || continue
232 FOUND=true
233 echo $line
234 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)
235 $FOUND || echo
236 }
237 FUZZEL_RES=$(prev | fuzzel --dmenu --prompt "qalc> ") || exit $?
238 if [[ "$FUZZEL_RES" =~ .*\ =\ .* ]]; then
239 QALC_RES="$FUZZEL_RES"
240 QALC_RET=0
241 else
242 QALC_RES=$(qalc "$FUZZEL_RES" 2>&1)
243 QALC_RET=$?
244 fi
245 [[ -n "$QALC_RES" ]] || exit 1
246 EXISTING=false
247 fgrep -xrl "$QALC_RES" "$RESULTS_DIR" | xargs -r touch
248 [[ ''${PIPESTATUS[0]} -eq 0 ]] && EXISTING=true
249 if [[ $QALC_RET -eq 0 ]] && ! $EXISTING; then
250 RES_FILE="$RESULTS_DIR"/$(date -uIs).$(tr -Cd 'a-zA-Z0-9' </dev/random | head -c 10)
251 cat >"$RES_FILE" <<<"$QALC_RES"
252 fi
253 [[ "$QALC_RES" =~ .*\ =\ (.*) ]] && QALC_RES="''${BASH_REMATCH[1]}"
254 [[ $QALC_RET -eq 0 ]] && wl-copy "$QALC_RES"
255 notify-send "$QALC_RES"
256 ''}"
257 "$mainMod, E, exec, ${pkgs.writeShellScript "emoji-fuzzel" ''
258 export PATH="${lib.makeBinPath (with pkgs; [ cfg.programs.fuzzel.package wtype wl-clipboard-rs ])}:$PATH"
259
260 FUZZEL_RES=$(fuzzel --dmenu --prompt "emoji> " <$HOME/.local/share/emoji-data/list.txt) || exit $?
261 [[ -n "$FUZZEL_RES" ]] || exit 1
262 wl-copy "$(cut -d ':' -f 1 <<<"$FUZZEL_RES" | tr -d '\n')" && wtype -k XF86Paste
263 ''}"
264 "$mainMod, B, exec, ${pkgs.writeShellScript "bring" ''
265 export PATH="${lib.makeBinPath (with pkgs; [ cfg.programs.fuzzel.package gawk gojq cfg.wayland.windowManager.hyprland.package ])}:$PATH"
266
267 state="$(hyprctl -j clients)"
268 active_window="$(hyprctl -j activewindow)"
269 active_workspace="$(hyprctl -j activeworkspace | gojq -r '.id')"
270
271 current_addr="$(echo "$active_window" | gojq -r '.address')"
272
273 window="$(echo "$state" |
274 gojq -r '.[] | select(.workspace.id == '"$active_workspace"') | select(.monitor != -1 ) | "\(.title)\t\(.address)"' |
275 fuzzel --log-level=warning --dmenu)"
276
277 addr="$(echo "$window" | awk -F $'\t' '{print $2}')"
278
279 if [[ "$addr" = "$current_addr" ]]; then
280 exit 0
281 fi
282
283 fullscreen_on_same_ws="$(echo "$state" | gojq -r '.[] | select(.fullscreen == true) | select(.workspace.id == '"$active_workspace"') | .address')"
284
285 if [[ "$window" != "" ]]; then
286 if [[ "$fullscreen_on_same_ws" == "" ]]; then
287 hyprctl dispatch focuswindow address:"''${addr}"
288 else
289 # If we want to focus app_A and app_B is fullscreen on the same workspace,
290 # app_A will get focus, but app_B will remain on top.
291 # This monstrosity is to make sure app_A will end up on top instead.
292 # XXX: doesn't handle fullscreen 0, but I don't care.
293 hyprctl --batch "dispatch focuswindow address:''${fullscreen_on_same_ws}; dispatch fullscreen 1; dispatch focuswindow address:''${addr}; dispatch fullscreen 1"
294 fi
295 fi
296 ''}"
297 "$mainMod SHIFT, B, exec, ${pkgs.writeShellScript "bring" ''
298 export PATH="${lib.makeBinPath (with pkgs; [ cfg.programs.fuzzel.package gawk gojq cfg.wayland.windowManager.hyprland.package ])}:$PATH"
299
300 state="$(hyprctl -j clients)"
301 active_window="$(hyprctl -j activewindow)"
302
303 current_addr="$(echo "$active_window" | gojq -r '.address')"
304
305 window="$(echo "$state" |
306 gojq -r '.[] | select(.monitor != -1 ) | "\(.title)\t\(.workspace.name)\t\(.address)"' |
307 fuzzel --log-level=warning --dmenu)"
308
309 addr="$(echo "$window" | awk -F $'\t' '{print $3}')"
310 ws="$(echo "$window" | awk -F $'\t' '{print $2}')"
311
312 if [[ "$addr" = "$current_addr" ]]; then
313 exit 0
314 fi
315
316 fullscreen_on_same_ws="$(echo "$state" | gojq -r ".[] | select(.fullscreen == true) | select(.workspace.name == \"$ws\") | .address")"
317
318 if [[ "$window" != "" ]]; then
319 if [[ "$fullscreen_on_same_ws" == "" ]]; then
320 hyprctl dispatch focuswindow address:"''${addr}"
321 else
322 # If we want to focus app_A and app_B is fullscreen on the same workspace,
323 # app_A will get focus, but app_B will remain on top.
324 # This monstrosity is to make sure app_A will end up on top instead.
325 # XXX: doesn't handle fullscreen 0, but I don't care.
326 hyprctl --batch "dispatch focuswindow address:''${fullscreen_on_same_ws}; dispatch fullscreen 1; dispatch focuswindow address:''${addr}; dispatch fullscreen 1"
327 fi
328 fi
329 ''}"
330
331 "$mainMod CTRL, return, togglespecialworkspace, term"
332 "$mainMod CTRL, e, togglespecialworkspace, edit"
333 "$mainMod CTRL, a, togglespecialworkspace, pwvucontrol"
334 "$mainMod CTRL, o, togglespecialworkspace, easyeffects"
335 "$mainMod CTRL, b, togglespecialworkspace, blueman"
336 "$mainMod CTRL, p, togglespecialworkspace, keepass"
337 ];
338 bindm = [
339 "$mainMod, mouse:272, movewindow"
340 "$mainMod, mouse:273, resizewindow"
341 ];
342 bindel = [
343 ", XF86MonBrightnessUp, exec, lightctl -d -e4 -n1 up"
344 ", XF86MonBrightnessDown, exec, lightctl -d -e4 -n1 down"
345 ", XF86AudioRaiseVolume, exec, volumectl -d -u up"
346 ", XF86AudioLowerVolume, exec, volumectl -d -u down"
347 ];
348 bindl = [
349 ", XF86AudioMute, exec, volumectl -d toggle-mute"
350 ", XF86AudioMicMute, exec, volumectl -d -m toggle-mute"
351 "$mainMod SHIFT, S, exec, systemctl suspend"
352
353 ", switch:off:Lid Switch,exec,hyprctl dispatch dpms on eDP-1"
354 ", switch:on:Lid Switch,exec,hyprctl dispatch dpms off eDP-1"
355
356 ", switch:off:Lid Switch,exec,${pkgs.writeShellScript "clamshell-off" ''
357 export PATH="${lib.makeBinPath (with pkgs; [ jq ])}:$PATH"
358 [[ $(hyprctl monitors -j | jq '.[] | select(.name == "eDP-1") | .disabled') = "true" ]] || exit 0
359
360 hyprctl keyword monitor "eDP-1,3840x2160@60,auto,1.5"
361 ''}"
362 ", switch:on:Lid Switch,exec,${pkgs.writeShellScript "clamshell-on" ''
363 export PATH="${lib.makeBinPath (with pkgs; [ jq ])}:$PATH"
364
365 [[ $(hyprctl monitors -j | jq 'reduce (.[] | select(.disabled == false)) as $_ (0; .+1)') -gt 1 ]] || exit 0
366
367 hyprctl keyword monitor "eDP-1,disable"
368 ''}"
369 ];
370
371 windowrulev2 = [
372 "suppressevent maximize fullscreen, class:.*"
373
374 # "maximize, class:^(Element|thunderbird)$"
375 "workspace special:pwvucontrol, class:^com\.saivert\.pwvucontrol$"
376 "workspace special:easyeffects, class:^com\.github\.wwmm\.easyeffects$"
377 "workspace special:blueman, class:^\.blueman-manager-wrapped$"
378 "workspace special:keepass silent, class:^org\.keepassxc\.KeePassXC$, title:^(?!Unlock Database.*)(?!.*(Access Request|Passkey credentials)).*$"
379 # "group set always lock invade, class:^Element$"
380 "workspace 2, class:^firefox$"
381 "workspace 4, class:^evince$"
382 "workspace 4, class:^imv$"
383 "workspace 4, class:^org\.pwmt\.zathura$"
384 "workspace 10, class:^mpv$"
385 "workspace 1, class:^Element$"
386 "workspace 1, class:^thunderbird$"
387 "workspace 5, class:^virt-manager$"
388 "workspace 5, class:^qemu$"
389 "float, class:^org\.keepassxc\.KeePassXC$, title:^.*Access Request$"
390 "center, class:^org\.keepassxc\.KeePassXC$, title:^.*Access Request$"
391 "float, class:^org\.keepassxc\.KeePassXC$, title:^.*Passkey credentials$"
392 "center, class:^org\.keepassxc\.KeePassXC$, title:^.*Passkey credentials$"
393 "float, class:^org\.keepassxc\.KeePassXC$, title:^Unlock Database.*$"
394 "center, class:^org\.keepassxc\.KeePassXC$, title:^Unlock Database.*$"
395 "float, class:^xdg-desktop-portal-gtk$"
396 "center, class:^xdg-desktop-portal-gtk$"
397
398 "bordercolor rgba(ffaa33ee) rgba(bfff00ee) 45deg, fullscreen:1"
399 "bordercolor rgba(3366ffee) rgba(6a00ffee) 45deg, xwayland:1"
400 "bordercolor rgba(6633ffee) rgba(ea00ffee) 45deg, xwayland:1, fullscreen:1"
401 ];
402
403 workspace = [
404 "s[true], gapsout:100"
405
406 "special:term, on-created-empty:kitty"
407 "special:edit, on-created-empty:emacsclient -c"
408 "special:pwvucontrol, on-created-empty:pwvucontrol"
409 "special:easyeffects, on-created-empty:easyeffects"
410 "special:blueman, on-created-empty:blueman-manager"
411 "special:keepass, on-created-empty:keepassxc"
412
413 "1, defaultName:comm"
414 "2, defaultName:web"
415 "3, defaultName:work"
416 "4, defaultName:read"
417 ];
418
419 layerrule = [
420 "blur, waybar"
421 "blur, launcher"
422 "noanim, notifications"
423 "blur, notifications"
424 ];
425}
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix
new file mode 100644
index 00000000..6a8d10a0
--- /dev/null
+++ b/accounts/gkleen@sif/niri/default.nix
@@ -0,0 +1,139 @@
1{ config, pkgs, lib, ... }:
2let
3 niri = config.programs.niri.package;
4 terminal = lib.getExe config.programs.kitty.package;
5 lightctl = lib.getExe' config.services.avizo.package "lightctl";
6 volumectl = lib.getExe' config.services.avizo.package "volumectl";
7 dunstctl = lib.getExe' config.services.dunst.package "dunstctl";
8in {
9 imports = [
10 ./waybar.nix
11 ];
12
13 config = {
14 systemd.user.services.xwayland-satellite = {
15 Unit = {
16 BindsTo = [ "graphical-session.target" ];
17 PartOf = [ "graphical-session.target" ];
18 After = [ "graphical-session.target" ];
19 Requisite = [ "graphical-session.target" ];
20 };
21 Service = {
22 Type = "notify";
23 NotifyAccess = "all";
24 ExecStart = lib.getExe pkgs.xwayland-satellite-unstable;
25 StandardOutput = "journal";
26 };
27 Install = {
28 WantedBy = [ "graphical-session.target" ];
29 };
30 };
31
32 programs.niri.settings = {
33 prefer-no-csd = true;
34 screenshot-path = "${config.home.homeDirectory}/screenshots";
35
36 input = {
37 keyboard.xkb = {
38 layout = "us,";
39 variant = "dvp,";
40 options = "compose:caps,grp:win_space_toggle";
41 };
42 };
43
44 environment = {
45 NIXOS_OZONE_WL = "1";
46 QT_QPA_PLATFORM = "wayland";
47 GDK_BACKEND = "wayland";
48 SDL_VIDEODRIVER = "wayland";
49 };
50
51 cursor.hide-when-typing = true;
52
53 binds = with config.lib.niri.actions; {
54 "Mod+Return".action = spawn terminal;
55 "Mod+Q".action = close-window;
56 "Mod+D".action = spawn (lib.getExe config.programs.fuzzel.package);
57 "Mod+Shift+D".action = spawn (lib.getExe config.programs.fuzzel.package) "--list-executables-in-path";
58
59 "Mod+H".action = focus-column-left;
60 "Mod+T".action = focus-window-down;
61 "Mod+N".action = focus-window-up;
62 "Mod+S".action = focus-column-right;
63
64 "Mod+Shift+H".action = move-column-left;
65 "Mod+Shift+T".action = move-window-down;
66 "Mod+Shift+N".action = move-window-up;
67 "Mod+Shift+S".action = move-column-right;
68
69 "Mod+Control+H".action = focus-monitor-left;
70 "Mod+Control+T".action = focus-monitor-down;
71 "Mod+Control+N".action = focus-monitor-up;
72 "Mod+Control+S".action = focus-monitor-right;
73
74 "Mod+Shift+Control+H".action = move-workspace-to-monitor-left;
75 "Mod+Shift+Control+T".action = move-workspace-to-monitor-down;
76 "Mod+Shift+Control+N".action = move-workspace-to-monitor-up;
77 "Mod+Shift+Control+S".action = move-workspace-to-monitor-right;
78
79 "Mod+G".action = focus-workspace-down;
80 "Mod+C".action = focus-workspace-up;
81
82 "Mod+Control+G".action = move-column-to-workspace-down;
83 "Mod+Control+C".action = move-column-to-workspace-up;
84
85 "Mod+Shift+G".action = move-workspace-down;
86 "Mod+Shift+C".action = move-workspace-up;
87
88 "Mod+M".action = consume-window-into-column;
89 "Mod+W".action = expel-window-from-column;
90
91 "Mod+F".action = maximize-column;
92 "Mod+Shift+F".action = fullscreen-window;
93
94 "Mod+Space".action = switch-focus-between-floating-and-tiling;
95 "Mod+Shift+Space".action = toggle-window-floating;
96
97 "Mod+Left".action = set-column-width "-10%";
98 "Mod+Down".action = set-window-height "-10%";
99 "Mod+Up".action = set-window-height "+10%";
100 "Mod+Right".action = set-column-width "+10%";
101
102 "Mod+Shift+Z" = {
103 action = spawn (lib.getExe niri) "msg" "action" "power-off-monitors";
104 allow-when-locked = true;
105 };
106
107 "XF86MonBrightnessUp" = {
108 action = spawn lightctl "-d" "-e4" "-n1" "up";
109 allow-when-locked = true;
110 };
111 "XF86MonBrightnessDown" = {
112 action = spawn lightctl "-d" "-e4" "-n1" "down";
113 allow-when-locked = true;
114 };
115 "XF86AudioRaiseVolume" = {
116 action = spawn volumectl "-d" "-u" "up";
117 allow-when-locked = true;
118 };
119 "XF86AudioLowerVolume" = {
120 action = spawn volumectl "-d" "-u" "down";
121 allow-when-locked = true;
122 };
123 "XF86AudioMute" = {
124 action = spawn volumectl "-d" "toggle-mute";
125 allow-when-locked = true;
126 };
127 "XF86AudioMicMute" = {
128 action = spawn volumectl "-d" "-m" "toggle-mute";
129 allow-when-locked = true;
130 };
131
132 "Mod+Semicolon".action = spawn dunstctl "close";
133 "Mod+Shift+Semicolon".action = spawn dunstctl "close-all";
134 "Mod+Period".action = spawn dunstctl "context";
135 "Mod+Comma".action = spawn dunstctl "history-pop";
136 };
137 };
138 };
139}
diff --git a/accounts/gkleen@sif/niri/waybar.nix b/accounts/gkleen@sif/niri/waybar.nix
new file mode 100644
index 00000000..1a25b581
--- /dev/null
+++ b/accounts/gkleen@sif/niri/waybar.nix
@@ -0,0 +1,288 @@
1{ lib, pkgs, ... }:
2{
3 config = {
4 programs.waybar = {
5 enable = true;
6 systemd = {
7 enable = true;
8 target = "graphical-session.target";
9 };
10 settings = let
11 windowRewrites = {
12 "(.*) — Mozilla Firefox" = "$1";
13 "(.*) - Mozilla Thunderbird" = "$1";
14 "(.*) - mpv" = "$1";
15 };
16 iconSize = 11;
17 in [
18 {
19 layer = "top";
20 position = "top";
21 height = 14;
22 output = [ "eDP-1" "DP-2" "DP-3" ];
23 modules-left = [ "niri/workspaces" ];
24 modules-center = [ "niri/window" ];
25 modules-right = [ # "custom/worktime" "custom/worktime-today"
26 "custom/weather"
27 # "custom/keymap"
28 "privacy" "tray" "wireplumber" "backlight" "battery" "idle_inhibitor" "clock" ];
29
30 "custom/weather" = {
31 format = "{}";
32 tooltip = true;
33 interval = 3600;
34 exec = "${lib.getExe pkgs.wttrbar} --hide-conditions --nerd --custom-indicator \"<span font=\\\"Symbols Nerd Font Mono\\\" size=\\\"120%\\\">{ICON}</span> {FeelsLikeC}°\"";
35 return-type = "json";
36 };
37 "custom/keymap" = {
38 format = "{}";
39 tooltip = true;
40 return-type = "json";
41 exec = pkgs.writers.writePython3 "keymap" {} ''
42 import os
43 import socket
44 import re
45 import subprocess
46 import json
47
48
49 def output(keymap):
50 short = keymap
51 if keymap == "English (programmer Dvorak)":
52 short = "dvp"
53 elif keymap == "English (US)":
54 short = "<span color=\"#ffffff\">us</span>"
55 print(json.dumps({'text': short, 'tooltip': keymap}, separators=(',', ':')), flush=True) # noqa: E501
56
57
58 r = subprocess.run(["hyprctl", "devices", "-j"], check=True, stdout=subprocess.PIPE, text=True) # noqa: E501
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
64 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
66 expected = re.compile(r'^activelayout>>at-translated-set-2-keyboard,(?P<keymap>.+)$') # noqa: E501
67 for line in sock.makefile(buffering=1, encoding='utf-8'):
68 if match := expected.match(line):
69 output(match.group("keymap"))
70 '';
71 on-click = "hyprctl switchxkblayout at-translated-set-2-keyboard next";
72 };
73 "custom/worktime" = {
74 interval = 60;
75 exec = lib.getExe pkgs.worktime;
76 tooltip = false;
77 };
78 "custom/worktime-today" = {
79 interval = 60;
80 exec = "${lib.getExe pkgs.worktime} today";
81 tooltip = false;
82 };
83 "niri/workspaces" = {
84 all-outputs = true;
85 };
86 "niri/window" = {
87 separate-outputs = true;
88 icon = true;
89 icon-size = 14;
90 rewrite = windowRewrites;
91 };
92 clock = {
93 interval = 1;
94 # timezone = "Europe/Berlin";
95 format = "W{:%V-%u %F %H:%M:%S%Ez}";
96 tooltip-format = "<tt><small>{calendar}</small></tt>";
97 calendar = {
98 mode = "year";
99 mode-mon-col = 3;
100 weeks-pos = "left";
101 on-scroll = 1;
102 format = {
103 months = "<span color='#ffead3'><b>{}</b></span>";
104 days = "{}";
105 weeks = "<span color='#99ffdd'><b>{}</b></span>";
106 weekdays = "<span color='#ffcc66'><b>{}</b></span>";
107 today = "<span color='#ff6699'><b>{}</b></span>";
108 };
109 };
110 };
111 battery = {
112 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
113 icon-size = iconSize - 2;
114 states = { warning = 30; critical = 15; };
115 format-icons = ["&#xf008e;" "&#xf007a;" "&#xf007b;" "&#xf007c;" "&#xf007d;" "&#xf007e;" "&#xf007f;" "&#xf0080;" "&#xf0081;" "&#xf0082;" "&#xf0079;" ];
116 format-charging = "&#xf0084;";
117 format-plugged = "&#xf06a5;";
118 tooltip-format = "{capacity}% {timeTo}";
119 interval = 20;
120 };
121 tray = {
122 icon-size = 16;
123 # show-passive-items = true;
124 spacing = 1;
125 };
126 privacy = {
127 icon-spacing = 7;
128 icon-size = iconSize;
129 modules = [
130 { type = "screenshare"; }
131 { type = "audio-in"; }
132 ];
133 };
134 idle_inhibitor = {
135 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
136 icon-size = iconSize;
137 format-icons = { activated = "&#xf0208;"; deactivated = "&#xf0209;"; };
138 timeout = 120;
139 };
140 backlight = {
141 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
142 icon-size = iconSize;
143 tooltip-format = "{percent}%";
144 format-icons = ["&#xf00da;" "&#xf00db;" "&#xf00dc;" "&#xf00dd;" "&#xf00de;" "&#xf00df;" "&#xf00e0;"];
145 on-scroll-up = "lightctl -d -e4 -n1 up";
146 on-scroll-down = "lightctl -d -e4 -n1 down";
147 };
148 wireplumber = {
149 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
150 icon-size = iconSize;
151 tooltip-format = "{volume}% {node_name}";
152 format-icons = ["&#xf057f;" "&#xf0580;" "&#xf057e;"];
153 format-muted = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">&#xf075f;</span>";
154 # ignored-sinks = ["Easy Effects Sink"];
155 on-scroll-up = "volumectl -d -u up";
156 on-scroll-down = "volumectl -d -u down";
157 on-click = "volumectl -d toggle-mute";
158 };
159 }
160 {
161 layer = "top";
162 position = "top";
163 height = 14;
164 output = [ "!eDP-1" "!DP-2" "!DP-3" ];
165 modules-left = [ "niri/workspaces" ];
166 modules-center = [ "niri/window" ];
167 modules-right = [ "clock" ];
168
169 "niri/workspaces" = {
170 all-outputs = false;
171 };
172 "niri/window" = {
173 separate-outputs = true;
174 icon = true;
175 icon-size = 14;
176 rewrite = windowRewrites;
177 };
178 clock = {
179 interval = 1;
180 # timezone = "Europe/Berlin";
181 format = "{:%H:%M}";
182 tooltip-format = "W{:%V-%u %F %H:%M:%S%Ez}";
183 };
184 }
185 ];
186 style = ''
187 @define-color white #ffffff;
188 @define-color grey #555555;
189 @define-color blue #1a8fff;
190 @define-color green #23fd00;
191 @define-color orange #f28a21;
192 @define-color red #f2201f;
193
194 * {
195 border: none;
196 font-family: "Fira Sans Nerd Font";
197 font-size: 10pt;
198 min-height: 0;
199 }
200
201 window#waybar {
202 background-color: rgba(0, 0, 0, 0.66);
203 color: @white;
204 }
205
206 .modules-left {
207 margin-left: 9px;
208 }
209 .modules-right {
210 margin-right: 9px;
211 }
212
213 .module {
214 margin: 0 5px;
215 }
216
217 #workspaces button {
218 color: @grey;
219 }
220 #workspaces button.hosting-monitor {
221 color: @white;
222 }
223 #workspaces button.visible {
224 color: @blue;
225 }
226 #workspaces button.active {
227 color: @green;
228 }
229 #workspaces button.urgent {
230 color: @red;
231 }
232
233 #custom-weather, #custom-keymap, #custom-worktime, #custom-worktime-today {
234 color: @grey;
235 margin: 0 5px;
236 }
237 #custom-weather, #custom-worktime-today {
238 margin-right: 3px;
239 }
240 #custom-keymap, #custom-weather {
241 margin-left: 3px;
242 }
243
244 #tray {
245 margin: 0;
246 }
247 #battery, #idle_inhibitor, #backlight, #wireplumber {
248 color: @grey;
249 margin: 0 5px 0 2px;
250 }
251 #idle_inhibitor {
252 margin-right: 2px;
253 margin-left: 3px;
254 }
255 #battery {
256 margin-right: 3px;
257 }
258 #battery.discharging {
259 color: @white;
260 }
261 #battery.warning {
262 color: @orange;
263 }
264 #battery.critical {
265 color: @red;
266 }
267 #battery.charging {
268 color: @white;
269 }
270 #idle_inhibitor.activated {
271 color: @white;
272 }
273
274 #idle_inhibitor {
275 padding-top: 1px;
276 }
277
278 #privacy {
279 color: @red;
280 margin: -1px 2px 0px 5px;
281 }
282 #clock {
283 /* margin-right: 5px; */
284 }
285 '';
286 };
287 };
288}