summaryrefslogtreecommitdiff
path: root/accounts
diff options
context:
space:
mode:
Diffstat (limited to 'accounts')
-rw-r--r--accounts/gkleen@sif/default.nix58
-rw-r--r--accounts/gkleen@sif/emacs.el1
-rw-r--r--accounts/gkleen@sif/libvirt/default.nix1
-rw-r--r--accounts/gkleen@sif/niri/default.nix273
-rw-r--r--accounts/gkleen@sif/niri/mako.nix67
-rw-r--r--accounts/gkleen@sif/niri/swayosd.nix65
-rw-r--r--accounts/gkleen@sif/niri/waybar.nix49
-rw-r--r--accounts/gkleen@sif/systemd.nix135
8 files changed, 522 insertions, 127 deletions
diff --git a/accounts/gkleen@sif/default.nix b/accounts/gkleen@sif/default.nix
index 7d5a9c25..58cfb425 100644
--- a/accounts/gkleen@sif/default.nix
+++ b/accounts/gkleen@sif/default.nix
@@ -80,7 +80,7 @@ let
80 ]; 80 ];
81 }; 81 };
82 82
83 lockCommand = "${config.systemd.package}/bin/systemctl --user start gtklock.service"; 83 lockCommand = "${lib.getExe' config.systemd.package "systemctl"} --user start gtklock.service";
84in { 84in {
85 imports = with flake.nixosModules.userProfiles.${userName}; [ 85 imports = with flake.nixosModules.userProfiles.${userName}; [
86 mpv yt-dlp (args: import ./xcompose.nix (inputs // args)) 86 mpv yt-dlp (args: import ./xcompose.nix (inputs // args))
@@ -185,7 +185,12 @@ in {
185 }; 185 };
186 }; 186 };
187 187
188 zathura.enable = true; 188 zathura = {
189 enable = true;
190 options = {
191 scroll-page-aware = true;
192 };
193 };
189 imv.enable = true; 194 imv.enable = true;
190 195
191 mpv.config = { 196 mpv.config = {
@@ -313,8 +318,11 @@ in {
313 device_mounted = []; 318 device_mounted = [];
314 }; 319 };
315 device_config = [ 320 device_config = [
316 { mount_path = "/run/etc-metadata"; ignore = true; } 321 { loop_file = "/nix/store/*-etc-metadata.erofs"; is_mounted = false; ignore = true; }
322 { mount_path = "/run/nixos-etc-metadata"; ignore = true; }
323 { mount_path = "/run/nixos-etc-metadata.*"; ignore = true; }
317 ]; 324 ];
325 icon_names.media = ["drive-removable-media-symbolic"];
318 }; 326 };
319 }; 327 };
320 network-manager-applet.enable = true; 328 network-manager-applet.enable = true;
@@ -351,31 +359,17 @@ in {
351 enable = true; 359 enable = true;
352 events = [ 360 events = [
353 { event = "before-sleep"; command = lockCommand; } 361 { event = "before-sleep"; command = lockCommand; }
354 # { event = "after-resume"; command = "${cfg.wayland.windowManager.hyprland.package}/bin/hyprctl dispatch dpms on"; }
355 { event = "lock"; command = lockCommand; } 362 { event = "lock"; command = lockCommand; }
356 ]; 363 ];
357 timeouts = [ 364 timeouts = [
358 # { timeout = 300;
359 # command = "${cfg.wayland.windowManager.hyprland.package}/bin/hyprctl dispatch dpms off";
360 # }
361 { timeout = 330; command = lockCommand; } 365 { timeout = 330; command = lockCommand; }
362 ]; 366 ];
363 extraArgs = [ 367 extraArgs = [
368 "-w"
364 "idlehint" "30" 369 "idlehint" "30"
365 ]; 370 ];
366 }; 371 };
367 poweralertd.enable = true; 372 poweralertd.enable = true;
368 avizo = {
369 enable = true;
370 settings.default = {
371 time = "1.0";
372 background = "rgba(0, 0, 0, 0.8)";
373 border-color = "rgba(0, 0, 0, 1)";
374 bar-fg-color = "rgba(160, 160, 160, 1)";
375 bar-bg-color = "rgba(32, 32, 32, 0.96)";
376 # y-offset = "0.25";
377 };
378 };
379 }; 373 };
380 374
381 home.pointerCursor = { 375 home.pointerCursor = {
@@ -416,16 +410,18 @@ in {
416 fira fira-code pwvucontrol wrappedKeepassxc wl-clipboard-rs 410 fira fira-code pwvucontrol wrappedKeepassxc wl-clipboard-rs
417 mumble pulseaudio-ctl pamixer libnotify screen-message 411 mumble pulseaudio-ctl pamixer libnotify screen-message
418 wrappedYTMDesktop libsForQt5.qt5ct playerctl evince 412 wrappedYTMDesktop libsForQt5.qt5ct playerctl evince
419 thunderbird zoom-us steam steam-run wireshark virt-manager 413 thunderbird zoom-us xdg-desktop-portal steam steam-run
420 rclone cached-nix-shell worktime fira-code-symbols 414 wireshark virt-manager rclone cached-nix-shell worktime
421 libreoffice xournalpp google-chrome nixos-shell virt-viewer 415 fira-code-symbols libreoffice xournalpp google-chrome
422 freerdp gnome-icon-theme paper-icon-theme sshpassSecret 416 nixos-shell virt-viewer freerdp gnome-icon-theme
423 weechat element-desktop matrix-synapse-tools.synadm 417 paper-icon-theme sshpassSecret weechat element-desktop
418 matrix-synapse-tools.synadm
424 flakeInputs.deploy-rs.packages.${config.nixpkgs.system}.deploy-rs 419 flakeInputs.deploy-rs.packages.${config.nixpkgs.system}.deploy-rs
425 sieve-connect gimp inkscape udiskie glab nitrokey-app 420 sieve-connect gimp inkscape udiskie glab nitrokey-app
426 pynitrokey gtklock wlrctl remmina openscad spice-record 421 pynitrokey gtklock wlrctl remmina openscad spice-record
427 libguestfs-with-appliance nerd-fonts.fira-mono 422 libguestfs-with-appliance nerd-fonts.fira-mono
428 nerd-fonts.symbols-only nerd-fonts.fira-code powerline-fonts 423 nerd-fonts.symbols-only nerd-fonts.fira-code powerline-fonts
424 swtpm
429 ]; 425 ];
430 426
431 file = { 427 file = {
@@ -491,6 +487,18 @@ in {
491 }; 487 };
492 }; 488 };
493 "emacs/init.el".source = ./emacs.el; 489 "emacs/init.el".source = ./emacs.el;
490 "systemd/user/xdg-desktop-portal.service.d/after-graphical-session.conf".text = ''
491 [Unit]
492 After=graphical-session.target
493 '';
494 "systemd/user/home-manager.service.d/before-graphical-session.conf".text = ''
495 [Unit]
496 Before=graphical-session-pre.target
497 '';
498 "pdfpc/pdfpcrc".text = ''
499 mouse 8 prev
500 mouse 9 next
501 '';
494 }; 502 };
495 503
496 xdg.dataFile = { 504 xdg.dataFile = {
@@ -608,7 +616,6 @@ in {
608 --property 'CPUAccounting=yes' --property 'CPUQuotaPeriodSec=50ms' \ 616 --property 'CPUAccounting=yes' --property 'CPUQuotaPeriodSec=50ms' \
609 --property 'Environment=DSCP=46' \ 617 --property 'Environment=DSCP=46' \
610 -- ${pkgs.dscp}/bin/dscp ${pkgs.google-chrome}/bin/google-chrome-stable \ 618 -- ${pkgs.dscp}/bin/dscp ${pkgs.google-chrome}/bin/google-chrome-stable \
611 --force-device-scale-factor=1.5 \
612 --class=Rainbow \ 619 --class=Rainbow \
613 --kiosk "https://web.openrainbow.com" \ 620 --kiosk "https://web.openrainbow.com" \
614 --user-data-dir=''${HOME}/.config/google-chrome-rainbow 621 --user-data-dir=''${HOME}/.config/google-chrome-rainbow
@@ -617,6 +624,9 @@ in {
617 url = "https://web.openrainbow.com/rb/2.139.17/assets/skins/rainbow/images/homepage/logo__rainbow.svg"; 624 url = "https://web.openrainbow.com/rb/2.139.17/assets/skins/rainbow/images/homepage/logo__rainbow.svg";
618 hash = "sha256-5fmo8rDqVDpzkGaPjk4Y+SsSZpAsY7VUQSFW6WdHwuU="; 625 hash = "sha256-5fmo8rDqVDpzkGaPjk4Y+SsSZpAsY7VUQSFW6WdHwuU=";
619 }; 626 };
627 settings = {
628 StartupWMClass = "Rainbow";
629 };
620 }; 630 };
621 }; 631 };
622 632
diff --git a/accounts/gkleen@sif/emacs.el b/accounts/gkleen@sif/emacs.el
index 183cb322..5cee16b0 100644
--- a/accounts/gkleen@sif/emacs.el
+++ b/accounts/gkleen@sif/emacs.el
@@ -228,6 +228,7 @@ necessarily running."
228 (global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling)) 228 (global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling))
229 229
230(add-hook 'server-switch-hook 'install-emacsclient-wrapped-kill-buffer) 230(add-hook 'server-switch-hook 'install-emacsclient-wrapped-kill-buffer)
231(add-hook 'server-switch-hook #'raise-frame)
231 232
232(defun move-file (new-location) 233(defun move-file (new-location)
233 "Write this file to NEW-LOCATION, and delete the old one." 234 "Write this file to NEW-LOCATION, and delete the old one."
diff --git a/accounts/gkleen@sif/libvirt/default.nix b/accounts/gkleen@sif/libvirt/default.nix
index 70ac22b9..4e5a9b90 100644
--- a/accounts/gkleen@sif/libvirt/default.nix
+++ b/accounts/gkleen@sif/libvirt/default.nix
@@ -7,6 +7,7 @@ with flakeInputs.nixVirt.lib;
7 config = { 7 config = {
8 virtualisation.libvirt = { 8 virtualisation.libvirt = {
9 enable = true; 9 enable = true;
10 swtpm.enable = true;
10 connections."qemu:///session" = { 11 connections."qemu:///session" = {
11 domains = [ 12 domains = [
12 { definition = domain.writeXML (updateManyAttrsByPath [ 13 { definition = domain.writeXML (updateManyAttrsByPath [
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix
index 0c4a58e5..7e187c84 100644
--- a/accounts/gkleen@sif/niri/default.nix
+++ b/accounts/gkleen@sif/niri/default.nix
@@ -2,11 +2,10 @@
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";
6 volumectl = lib.getExe' config.services.avizo.package "volumectl";
7 makoctl = lib.getExe' config.services.mako.package "makoctl"; 5 makoctl = lib.getExe' config.services.mako.package "makoctl";
8 loginctl = lib.getExe' hostConfig.systemd.package "loginctl"; 6 loginctl = lib.getExe' hostConfig.systemd.package "loginctl";
9 systemctl = lib.getExe' hostConfig.systemd.package "systemctl"; 7 systemctl = lib.getExe' hostConfig.systemd.package "systemctl";
8 swayosd-client = lib.getExe' config.services.swayosd.package "swayosd-client";
10 9
11 focus_or_spawn = pkgs.writeShellApplication { 10 focus_or_spawn = pkgs.writeShellApplication {
12 name = "focus-or-spawn"; 11 name = "focus-or-spawn";
@@ -19,17 +18,21 @@ let
19 18
20 workspaces_json="$(niri msg -j workspaces)" 19 workspaces_json="$(niri msg -j workspaces)"
21 workspace_output="$(jq -r --arg workspace_name "$workspace_name" '.[] | select(.name == $workspace_name) | .output' <<<"$workspaces_json")" 20 workspace_output="$(jq -r --arg workspace_name "$workspace_name" '.[] | select(.name == $workspace_name) | .output' <<<"$workspaces_json")"
22 active_workspace="$(jq -r --arg workspace_output "$workspace_output" '.[] | select(.output == $workspace_output and .is_active) | .id' <<<"$workspaces_json")" 21 # active_workspace="$(jq -r --arg workspace_output "$workspace_output" '.[] | select(.output == $workspace_output and .is_active) | .id' <<<"$workspaces_json")"
23 active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")" 22 active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")"
24 if [[ $workspace_output != "$active_output" ]]; then 23 if [[ $workspace_output != "$active_output" ]]; then
25 niri msg action move-workspace-to-monitor --output "$active_output" "$workspace_name" 24 niri msg action move-workspace-to-monitor --reference "$workspace_name" "$active_output"
26 socat STDIO "$NIRI_SOCKET" <<<'{"Action":{"FocusWorkspace":{"reference":{"Id":'"''${active_workspace}"'}}}}' 25 # socat STDIO "$NIRI_SOCKET" <<<'{"Action":{"FocusWorkspace":{"reference":{"Id":'"''${active_workspace}"'}}}}'
27 niri msg action move-workspace-to-index --index 1 "$workspace_name" 26 # niri msg action move-workspace-to-index --reference "$workspace_name" 1
28 fi 27 fi
29 28
30 while IFS=$'\n' read -r window_json; do 29 while IFS=$'\n' read -r window_json; do
31 if [[ -n $(jq -c "$window_select" <<<"$window_json") ]]; then 30 if [[ -n $(jq -c "$window_select" <<<"$window_json") ]]; then
32 niri msg action focus-window --id "$(jq -r '.id' <<<"$window_json")" 31 if jq -e '.is_focused' <<<"$window_json" >/dev/null; then
32 niri msg action focus-workspace-previous
33 else
34 niri msg action focus-window --id "$(jq -r '.id' <<<"$window_json")"
35 fi
33 exit 0 36 exit 0
34 fi 37 fi
35 done < <(niri msg -j windows | jq -c '.[]') 38 done < <(niri msg -j windows | jq -c '.[]')
@@ -75,7 +78,7 @@ let
75 jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET" 78 jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET"
76 ''; 79 '';
77 }; 80 };
78 with-adjacent-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_adjacent_workspace) "^pwctl|kpxc|bmgr|edit|term$"; 81 with-adjacent-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_adjacent_workspace) "^pwctl|eff|kpxc|bmgr|edit|term$";
79 focus-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}''; 82 focus-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}'';
80 move-column-to-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}}}}''; 83 move-column-to-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}}}}'';
81 84
@@ -90,7 +93,8 @@ let
90 active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")" 93 active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")"
91 active_workspace="$(jq -r '.[] | select(.is_focused) | .id' <<<"$workspaces_json")" 94 active_workspace="$(jq -r '.[] | select(.is_focused) | .id' <<<"$workspaces_json")"
92 95
93 workspace_json="$(jq -c --arg active_output "$active_output" 'map(select(.output == $active_output and .name == null)) | sort_by(.idx) | .[0]' <<<"$workspaces_json")" 96 history_json="$(socat STDIO UNIX-CONNECT:"$XDG_RUNTIME_DIR"/niri-workspace-history.sock)"
97 workspace_json="$(jq -c --arg active_output "$active_output" --argjson history "$history_json" 'map(select(.output == $active_output and .name == null)) | map({"value": ., "history_idx": ((. as $workspace | ($history[$active_output] | index($workspace | .id))) as $active_idx | if $active_idx then $active_idx else ($history[$active_output] | length) + 1 end)}) | sort_by(.history_idx, .value.idx) | map(.value) | .[0]' <<<"$workspaces_json")"
94 [[ -n $workspace_json && $workspace_json != null ]] || exit 0 98 [[ -n $workspace_json && $workspace_json != null ]] || exit 0
95 jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET" 99 jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET"
96 ''; 100 '';
@@ -98,7 +102,7 @@ let
98 with-unnamed-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_unnamed_workspace); 102 with-unnamed-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_unnamed_workspace);
99 103
100 with_select_window = pkgs.writeShellApplication { 104 with_select_window = pkgs.writeShellApplication {
101 name = "with-unnamed-workspace"; 105 name = "with-select-window";
102 runtimeInputs = [ niri pkgs.gojq pkgs.socat config.programs.fuzzel.package pkgs.gawk ]; 106 runtimeInputs = [ niri pkgs.gojq pkgs.socat config.programs.fuzzel.package pkgs.gawk ];
103 text = '' 107 text = ''
104 window_select="$1" 108 window_select="$1"
@@ -108,9 +112,9 @@ let
108 112
109 windows_json="$(niri msg -j windows)" 113 windows_json="$(niri msg -j windows)"
110 active_workspace="$(jq -r '.[] | select(.is_focused) | .workspace_id' <<<"$windows_json")" 114 active_workspace="$(jq -r '.[] | select(.is_focused) | .workspace_id' <<<"$windows_json")"
111 window="$(gojq -r --arg active_workspace "$active_workspace" '.[] | select('"$window_select"') | "\(.title)\t\(.id)"' <<<"$windows_json" | fuzzel --log-level=warning --dmenu)" 115 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)"
112 window_id="$(awk -F $'\t' '{print $2}' <<<"$window")" 116 # shellcheck disable=SC2016
113 window_json="$(jq -r --arg window_id "$window_id" '.[] | select(.id == ($window_id | tonumber))' <<<"$windows_json")" 117 window_json="$(gojq -rc --arg active_workspace "$active_workspace" --arg window_ix "$window_ix" 'map(select('"$window_select"')) | .[($window_ix | tonumber)]' <<<"$windows_json")"
114 118
115 [[ -z "$window_json" ]] && exit 1 119 [[ -z "$window_json" ]] && exit 1
116 120
@@ -122,6 +126,7 @@ in {
122 imports = [ 126 imports = [
123 ./waybar.nix 127 ./waybar.nix
124 ./mako.nix 128 ./mako.nix
129 ./swayosd.nix
125 ]; 130 ];
126 131
127 config = { 132 config = {
@@ -156,6 +161,113 @@ in {
156 ]; 161 ];
157 }; 162 };
158 163
164 systemd.user.sockets.niri-workspace-history = {
165 Socket = {
166 ListenStream = "%t/niri-workspace-history.sock";
167 SocketMode = "0600";
168 };
169 };
170 systemd.user.services.niri-workspace-history = {
171 Unit = {
172 BindsTo = [ "niri.service" ];
173 After = [ "niri.service" ];
174 };
175 Install = {
176 WantedBy = [ "niri.service" ];
177 };
178 Service = {
179 Type = "simple";
180 Sockets = [ "niri-workspace-history.socket" ];
181 ExecStart = pkgs.writers.writePython3 "niri-workspace-history" {} ''
182 import os
183 import socket
184 import json
185 import sys
186 from collections import defaultdict
187 from threading import Thread, Lock
188 from socketserver import StreamRequestHandler, ThreadingTCPServer
189 from contextlib import contextmanager
190 from io import TextIOWrapper
191
192
193 @contextmanager
194 def detaching(thing):
195 try:
196 yield thing
197 finally:
198 thing.detach()
199
200
201 workspace_history = defaultdict(list)
202 history_lock = Lock()
203
204
205 def monitor_niri():
206 workspaces = list()
207
208 def focus_workspace(output, workspace):
209 global workspace_history, history_lock
210
211 with history_lock:
212 workspace_history[output] = [workspace] + [ws for ws in workspace_history[output] if ws != workspace] # noqa: E501
213 print(json.dumps(workspace_history), file=sys.stderr)
214
215 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
216 sock.connect(os.environ["NIRI_SOCKET"])
217 sock.send(b"\"EventStream\"\n")
218 for line in sock.makefile(buffering=1, encoding='utf-8'):
219 if line_json := json.loads(line):
220 if "WorkspacesChanged" in line_json:
221 workspaces = line_json["WorkspacesChanged"]["workspaces"]
222 for ws in workspaces:
223 if ws["is_focused"]:
224 focus_workspace(ws["output"], ws["id"])
225 if "WorkspaceActivated" in line_json:
226 for ws in workspaces:
227 if ws["id"] != line_json["WorkspaceActivated"]["id"]:
228 continue
229 focus_workspace(ws["output"], ws["id"])
230 break
231
232
233 class RequestHandler(StreamRequestHandler):
234 def handle(self):
235 global workspace_history, history_lock
236
237 with detaching(TextIOWrapper(self.wfile, encoding='utf-8', write_through=True)) as out: # noqa: E501
238 with history_lock:
239 json.dump(workspace_history, out)
240
241
242 class Server(ThreadingTCPServer):
243 def __init__(self):
244 ThreadingTCPServer.__init__(self, ("", 8000), RequestHandler, bind_and_activate=False) # noqa: E501
245 self.socket = socket.fromfd(3, self.address_family, self.socket_type)
246
247
248 def run_server():
249 with Server() as server:
250 server.serve_forever()
251
252
253 niri = Thread(target=monitor_niri)
254 niri.daemon = True
255 niri.start()
256
257 server_thread = Thread(target=run_server)
258 server_thread.daemon = True
259 server_thread.start()
260
261 while True:
262 server_thread.join(timeout=0.5)
263 niri.join(timeout=0.5)
264
265 if not (niri.is_alive() and server_thread.is_alive()):
266 break
267 '';
268 };
269 };
270
159 programs.niri.settings = { 271 programs.niri.settings = {
160 prefer-no-csd = true; 272 prefer-no-csd = true;
161 screenshot-path = "${config.home.homeDirectory}/screenshots"; 273 screenshot-path = "${config.home.homeDirectory}/screenshots";
@@ -163,10 +275,15 @@ in {
163 hotkey-overlay.skip-at-startup = true; 275 hotkey-overlay.skip-at-startup = true;
164 276
165 input = { 277 input = {
166 keyboard.xkb = { 278 keyboard = {
167 layout = "us,us"; 279 repeat-delay = 300;
168 variant = "dvp,"; 280 repeat-rate = 50;
169 options = "compose:caps,grp:win_space_toggle"; 281
282 xkb = {
283 layout = "us,us";
284 variant = "dvp,";
285 options = "compose:caps,grp:win_space_toggle";
286 };
170 }; 287 };
171 288
172 workspace-auto-back-and-forth = true; 289 workspace-auto-back-and-forth = true;
@@ -183,13 +300,28 @@ in {
183 scale = 1.5; 300 scale = 1.5;
184 position = { x = 2560; y = 0; }; 301 position = { x = 2560; y = 0; };
185 }; 302 };
303 "HP Inc. HP 727pu CN4417143K" = {
304 mode = { width = 2560; height = 1440; refresh = 119.998; };
305 scale = 1;
306 position = { x = 2560; y = 0; };
307 variable-refresh-rate = "on-demand";
308 };
186 }; 309 };
187 310
188 environment = { 311 environment = {
189 NIXOS_OZONE_WL = "1"; 312 NIXOS_OZONE_WL = "1";
190 QT_QPA_PLATFORM = "wayland"; 313 QT_QPA_PLATFORM = "wayland";
314 QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
191 GDK_BACKEND = "wayland"; 315 GDK_BACKEND = "wayland";
192 SDL_VIDEODRIVER = "wayland"; 316 SDL_VIDEODRIVER = "wayland";
317 DISPLAY = ":0";
318 };
319
320 debug.render-drm-device = "/dev/dri/by-path/pci-0000:00:02.0-render";
321
322 animations = {
323 slowdown = 0.5;
324 workspace-switch = null;
193 }; 325 };
194 326
195 layout = { 327 layout = {
@@ -231,34 +363,56 @@ in {
231 363
232 cursor.hide-when-typing = true; 364 cursor.hide-when-typing = true;
233 365
366 input = {
367 touchpad.enable = false;
368 trackball = {
369 scroll-method = "on-button-down";
370 scroll-button = 278;
371 };
372 };
373
234 workspaces = { 374 workspaces = {
235 "001" = { name = "pwctl"; open-on-output = "eDP-1"; }; 375 "001" = { name = "pwctl"; open-on-output = "eDP-1"; };
236 "002" = { name = "kpxc"; open-on-output = "eDP-1"; }; 376 "002" = { name = "kpxc"; open-on-output = "eDP-1"; };
237 "003" = { name = "bmgr"; open-on-output = "eDP-1"; }; 377 "003" = { name = "bmgr"; open-on-output = "eDP-1"; };
238 "004" = { name = "term"; open-on-output = "eDP-1"; }; 378 "004" = { name = "term"; open-on-output = "eDP-1"; };
239 "005" = { name = "edit"; open-on-output = "eDP-1"; }; 379 "005" = { name = "edit"; open-on-output = "eDP-1"; };
380 "006" = { name = "eff"; open-on-output = "eDP-1"; };
240 "101".name = "comm"; 381 "101".name = "comm";
241 "102".name = "web"; 382 "102".name = "web";
242 # "104".name = "read"; 383 # "104".name = "read";
243 # "105".name = "mon"; 384 # "105".name = "mon";
244 "110".name = "vid"; 385 "110".name = "vid";
386 "120".name = "bmr";
245 }; 387 };
246 388
247 window-rules = [ 389 window-rules = [
248 # { 390 {
249 # geometry-corner-radius = 391 matches = [ { is-floating = true; } ];
250 # let 392 geometry-corner-radius =
251 # allCorners = r: { bottom-left = r; bottom-right = r; top-left = r; top-right = r; }; 393 let
252 # in allCorners 4.; 394 allCorners = r: { bottom-left = r; bottom-right = r; top-left = r; top-right = r; };
253 # clip-to-geometry = true; 395 in allCorners 8.;
254 # } 396 clip-to-geometry = true;
397 }
255 { 398 {
256 matches = [ { app-id = "^com\.saivert\.pwvucontrol$"; } ]; 399 matches = [ { app-id = "^com\.saivert\.pwvucontrol$"; } ];
257 open-on-workspace = "pwctl"; 400 open-on-workspace = "pwctl";
401 open-maximized = true;
402 }
403 {
404 matches = [ { app-id = "^com\.github\.wwmm\.easyeffects$"; } ];
405 open-on-workspace = "eff";
406 open-maximized = true;
258 } 407 }
259 { 408 {
260 matches = [ { app-id = "^\.blueman-manager-wrapped$"; } ]; 409 matches = [ { app-id = "^\.blueman-manager-wrapped$"; } ];
261 open-on-workspace = "bmgr"; 410 open-on-workspace = "bmgr";
411 open-maximized = true;
412 }
413 {
414 matches = [ { app-id = "^org\.keepassxc\.KeePassXC$"; } ];
415 block-out-from = "screencast";
262 } 416 }
263 { 417 {
264 matches = [ { app-id = "^org\.keepassxc\.KeePassXC$"; } ]; 418 matches = [ { app-id = "^org\.keepassxc\.KeePassXC$"; } ];
@@ -268,6 +422,7 @@ in {
268 { title = ".*Passkey credentials$"; } 422 { title = ".*Passkey credentials$"; }
269 ]; 423 ];
270 open-on-workspace = "kpxc"; 424 open-on-workspace = "kpxc";
425 open-maximized = true;
271 open-focused = false; 426 open-focused = false;
272 } 427 }
273 { 428 {
@@ -277,25 +432,45 @@ in {
277 { app-id = "^org\.keepassxc\.KeePassXC$"; title = ".*Passkey credentials$"; } 432 { app-id = "^org\.keepassxc\.KeePassXC$"; title = ".*Passkey credentials$"; }
278 ]; 433 ];
279 open-focused = true; 434 open-focused = true;
435 open-floating = true;
280 } 436 }
281 { 437 {
282 matches = [ { app-id = "^kitty-scratch$"; } ]; 438 matches = [ { app-id = "^kitty-scratch$"; } ];
283 open-on-workspace = "term"; 439 open-on-workspace = "term";
440 open-maximized = true;
284 } 441 }
285 { 442 {
286 matches = [ { title = "^scratch$"; app-id = "^emacs$"; } ]; 443 matches = [ { title = "^scratch$"; app-id = "^emacs$"; } ];
287 open-on-workspace = "edit"; 444 open-on-workspace = "edit";
445 open-maximized = true;
446 }
447 {
448 matches = [
449 { app-id = "^emacs$"; }
450 { app-id = "^firefox$"; }
451 ];
452 default-column-width.proportion = 2. / 3.;
453 }
454 {
455 matches = [
456 { app-id = "^kitty$"; }
457 { app-id = "^kitty-play$"; }
458 ];
459 default-column-width.proportion = 1. / 3.;
288 } 460 }
289 { 461 {
290 matches = [ 462 matches = [
291 { app-id = "^thunderbird$"; } 463 { app-id = "^thunderbird$"; }
292 { app-id = "^Element$"; } 464 { app-id = "^Element$"; }
465 { app-id = "^Rainbow$"; }
293 ]; 466 ];
294 open-on-workspace = "comm"; 467 open-on-workspace = "comm";
295 } 468 }
296 { 469 {
297 matches = [ { app-id = "^firefox$"; } ]; 470 matches = [ { app-id = "^firefox$"; } ];
298 open-on-workspace = "web"; 471 open-on-workspace = "web";
472 open-maximized = true;
473 variable-refresh-rate = true;
299 } 474 }
300 # { 475 # {
301 # matches = [ 476 # matches = [
@@ -309,11 +484,11 @@ in {
309 matches = [ { app-id = "^mpv$"; } ]; 484 matches = [ { app-id = "^mpv$"; } ];
310 open-on-workspace = "vid"; 485 open-on-workspace = "vid";
311 default-column-width.proportion = 1.; 486 default-column-width.proportion = 1.;
487 variable-refresh-rate = true;
312 } 488 }
313 { 489 {
314 matches = [ { app-id = "^kitty-play$"; } ]; 490 matches = [ { app-id = "^kitty-play$"; } ];
315 open-on-workspace = "vid"; 491 open-on-workspace = "vid";
316 default-column-width.proportion = 1. / 3.;
317 open-focused = false; 492 open-focused = false;
318 } 493 }
319 # { 494 # {
@@ -323,6 +498,31 @@ in {
323 # ]; 498 # ];
324 # open-on-workspace = "mon"; 499 # open-on-workspace = "mon";
325 # } 500 # }
501 {
502 matches = [ { app-id = "^pdfpc$"; } ];
503 default-column-width.proportion = 1.;
504 }
505 {
506 matches = [ { app-id = "^pdfpc$"; title = "^pdfpc - presentation"; } ];
507 open-on-workspace = "bmr";
508 open-fullscreen = true;
509 }
510 {
511 matches = [
512 { app-id = "^Gimp-"; title = "^Quit GIMP$"; }
513 { app-id = "^org\.kde\.polkit-kde-authentication-agent-1$"; }
514 { app-id = "^xdg-desktop-portal-gtk$"; }
515 ];
516 open-floating = true;
517 }
518 ];
519 layer-rules = [
520 { matches = [
521 { namespace = "^notifications$"; }
522 { namespace = "^waybar$"; }
523 ];
524 block-out-from = "screencast";
525 }
326 ]; 526 ];
327 527
328 binds = with config.lib.niri.actions; { 528 binds = with config.lib.niri.actions; {
@@ -373,12 +573,14 @@ in {
373 fi 573 fi
374 [[ -n "$QALC_RES" ]] || exit 1 574 [[ -n "$QALC_RES" ]] || exit 1
375 EXISTING=false 575 EXISTING=false
376 set +e 576 set +o pipefail
377 grep -Fxrl "$QALC_RES" "$RESULTS_DIR" | xargs -r touch 577 grep -Fxrl "$QALC_RES" "$RESULTS_DIR" | xargs -r touch
378 [[ ''${PIPESTATUS[0]} -eq 0 ]] && EXISTING=true 578 [[ ''${PIPESTATUS[0]} -eq 0 ]] && EXISTING=true
379 set -e 579 set -o pipefail
380 if [[ $QALC_RET -eq 0 ]] && ! $EXISTING; then 580 if [[ $QALC_RET -eq 0 ]] && ! $EXISTING; then
581 set +o pipefail
381 RES_FILE="$RESULTS_DIR"/$(date -uIs).$(tr -Cd 'a-zA-Z0-9' </dev/random | head -c 10) 582 RES_FILE="$RESULTS_DIR"/$(date -uIs).$(tr -Cd 'a-zA-Z0-9' </dev/random | head -c 10)
583 set -o pipefail
382 cat >"$RES_FILE" <<<"$QALC_RES" 584 cat >"$RES_FILE" <<<"$QALC_RES"
383 fi 585 fi
384 [[ "$QALC_RES" =~ .*\ =\ (.*) ]] && QALC_RES="''${BASH_REMATCH[1]}" 586 [[ "$QALC_RES" =~ .*\ =\ (.*) ]] && QALC_RES="''${BASH_REMATCH[1]}"
@@ -494,29 +696,33 @@ in {
494 action = spawn systemctl "hibernate"; 696 action = spawn systemctl "hibernate";
495 allow-when-locked = true; 697 allow-when-locked = true;
496 }; 698 };
699 "Mod+Shift+P" = {
700 action = spawn (lib.getExe pkgs.playerctl) "-a" "pause";
701 allow-when-locked = true;
702 };
497 703
498 "XF86MonBrightnessUp" = { 704 "XF86MonBrightnessUp" = {
499 action = spawn lightctl "-d" "-e4" "-n1" "up"; 705 action = spawn swayosd-client "--brightness" "raise";
500 allow-when-locked = true; 706 allow-when-locked = true;
501 }; 707 };
502 "XF86MonBrightnessDown" = { 708 "XF86MonBrightnessDown" = {
503 action = spawn lightctl "-d" "-e4" "-n1" "down"; 709 action = spawn swayosd-client "--brightness" "lower";
504 allow-when-locked = true; 710 allow-when-locked = true;
505 }; 711 };
506 "XF86AudioRaiseVolume" = { 712 "XF86AudioRaiseVolume" = {
507 action = spawn volumectl "-d" "-u" "up"; 713 action = spawn swayosd-client "--output-volume" "raise";
508 allow-when-locked = true; 714 allow-when-locked = true;
509 }; 715 };
510 "XF86AudioLowerVolume" = { 716 "XF86AudioLowerVolume" = {
511 action = spawn volumectl "-d" "-u" "down"; 717 action = spawn swayosd-client "--output-volume" "lower";
512 allow-when-locked = true; 718 allow-when-locked = true;
513 }; 719 };
514 "XF86AudioMute" = { 720 "XF86AudioMute" = {
515 action = spawn volumectl "-d" "toggle-mute"; 721 action = spawn swayosd-client "--output-volume" "mute-toggle";
516 allow-when-locked = true; 722 allow-when-locked = true;
517 }; 723 };
518 "XF86AudioMicMute" = { 724 "XF86AudioMicMute" = {
519 action = spawn volumectl "-d" "-m" "toggle-mute"; 725 action = spawn swayosd-client "--input-volume" "mute-toggle";
520 allow-when-locked = true; 726 allow-when-locked = true;
521 }; 727 };
522 728
@@ -526,6 +732,7 @@ in {
526 "Mod+Comma".action = spawn makoctl "restore"; 732 "Mod+Comma".action = spawn makoctl "restore";
527 733
528 "Mod+Control+A".action = focus-or-spawn-action-app_id "com.saivert.pwvucontrol" "pwctl" "pwvucontrol"; 734 "Mod+Control+A".action = focus-or-spawn-action-app_id "com.saivert.pwvucontrol" "pwctl" "pwvucontrol";
735 "Mod+Control+O".action = focus-or-spawn-action-app_id "com.github.wwmm.easyeffects" "eff" "easyeffects";
529 "Mod+Control+P".action = focus-or-spawn-action-app_id "org.keepassxc.KeePassXC" "kpxc" "keepassxc"; 736 "Mod+Control+P".action = focus-or-spawn-action-app_id "org.keepassxc.KeePassXC" "kpxc" "keepassxc";
530 "Mod+Control+B".action = focus-or-spawn-action-app_id ".blueman-manager-wrapped" "bmgr" "blueman-manager"; 737 "Mod+Control+B".action = focus-or-spawn-action-app_id ".blueman-manager-wrapped" "bmgr" "blueman-manager";
531 "Mod+Control+Return".action = focus-or-spawn-action-app_id "kitty-scratch" "term" "kitty" "--app-id" "kitty-scratch"; 738 "Mod+Control+Return".action = focus-or-spawn-action-app_id "kitty-scratch" "term" "kitty" "--app-id" "kitty-scratch";
diff --git a/accounts/gkleen@sif/niri/mako.nix b/accounts/gkleen@sif/niri/mako.nix
index 8abf14d8..0a10555a 100644
--- a/accounts/gkleen@sif/niri/mako.nix
+++ b/accounts/gkleen@sif/niri/mako.nix
@@ -1,4 +1,4 @@
1{ config, lib, ... }: 1{ config, lib, pkgs, ... }:
2{ 2{
3 config = { 3 config = {
4 services.mako = { 4 services.mako = {
@@ -13,6 +13,7 @@
13 extraConfig = '' 13 extraConfig = ''
14 outer-margin=1 14 outer-margin=1
15 max-history=100 15 max-history=100
16 max-icon-size=48
16 17
17 [grouped] 18 [grouped]
18 format=<b>(%g)</b> <i>%s</i>\n%b 19 format=<b>(%g)</b> <i>%s</i>\n%b
@@ -29,6 +30,14 @@
29 [mode=silent] 30 [mode=silent]
30 invisible=1 31 invisible=1
31 ''; 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 };
32 }; 41 };
33 systemd.user.services.mako = { 42 systemd.user.services.mako = {
34 Unit = { 43 Unit = {
@@ -46,5 +55,61 @@
46 Restart = "always"; 55 Restart = "always";
47 }; 56 };
48 }; 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 };
49 }; 114 };
50} 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 79c429f8..3f1f8119 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,7 +24,7 @@
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" "custom/mako" "clock" ]; 30 "privacy" "tray" "wireplumber" "backlight" "battery" "idle_inhibitor" "custom/mako" "clock" ];
@@ -59,7 +61,7 @@
59 text = f"<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>" # noqa: E501 61 text = f"<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>" # noqa: E501
60 if is_silent: 62 if is_silent:
61 text = f"<span color=\"#ffffff\">{text}</span>" 63 text = f"<span color=\"#ffffff\">{text}</span>"
62 print(json.dumps({'text': text}, separators=(',', ':')), flush=True) # noqa: E501 64 print(json.dumps({'text': text, 'tooltip': ', '.join(modes)}, separators=(',', ':')), flush=True) # noqa: E501
63 65
64 async def on_properties_changed(interface_name, changed_properties, invalidated_properties): # noqa: E501 66 async def on_properties_changed(interface_name, changed_properties, invalidated_properties): # noqa: E501
65 if "Modes" not in invalidated_properties: 67 if "Modes" not in invalidated_properties:
@@ -120,16 +122,16 @@
120 }; 122 };
121 "custom/worktime" = { 123 "custom/worktime" = {
122 interval = 60; 124 interval = 60;
123 exec = lib.getExe pkgs.worktime; 125 exec = "${lib.getExe pkgs.worktime} time --waybar";
124 tooltip = false; 126 return-type = "json";
125 }; 127 };
126 "custom/worktime-today" = { 128 "custom/worktime-today" = {
127 interval = 60; 129 interval = 60;
128 exec = "${lib.getExe pkgs.worktime} today"; 130 exec = "${lib.getExe pkgs.worktime} today --waybar";
129 tooltip = false; 131 return-type = "json";
130 }; 132 };
131 "niri/workspaces" = { 133 "niri/workspaces" = {
132 ignore = ["pwctl" "kpxc" "bmgr" "edit" "term"]; 134 ignore = ["eff" "pwctl" "kpxc" "bmgr" "edit" "term"];
133 }; 135 };
134 "niri/window" = { 136 "niri/window" = {
135 separate-outputs = true; 137 separate-outputs = true;
@@ -190,8 +192,8 @@
190 icon-size = iconSize; 192 icon-size = iconSize;
191 tooltip-format = "{percent}%"; 193 tooltip-format = "{percent}%";
192 format-icons = ["&#xf00da;" "&#xf00db;" "&#xf00dc;" "&#xf00dd;" "&#xf00de;" "&#xf00df;" "&#xf00e0;"]; 194 format-icons = ["&#xf00da;" "&#xf00db;" "&#xf00dc;" "&#xf00dd;" "&#xf00de;" "&#xf00df;" "&#xf00e0;"];
193 on-scroll-up = "lightctl -d -e4 -n1 up"; 195 on-scroll-up = "${swayosd-client} --brightness raise";
194 on-scroll-down = "lightctl -d -e4 -n1 down"; 196 on-scroll-down = "${swayosd-client} --brightness lower";
195 }; 197 };
196 wireplumber = { 198 wireplumber = {
197 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>"; 199 format = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">{icon}</span>";
@@ -200,9 +202,9 @@
200 format-icons = ["&#xf057f;" "&#xf0580;" "&#xf057e;"]; 202 format-icons = ["&#xf057f;" "&#xf0580;" "&#xf057e;"];
201 format-muted = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">&#xf075f;</span>"; 203 format-muted = "<span font=\"Symbols Nerd Font Mono\" size=\"90%\">&#xf075f;</span>";
202 # ignored-sinks = ["Easy Effects Sink"]; 204 # ignored-sinks = ["Easy Effects Sink"];
203 on-scroll-up = "volumectl -d -u up"; 205 on-scroll-up = "${swayosd-client} --output-volume raise";
204 on-scroll-down = "volumectl -d -u down"; 206 on-scroll-down = "${swayosd-client} --output-volume lower";
205 on-click = "volumectl -d toggle-mute"; 207 on-click = "${swayosd-client} --output-volume mute-toggle";
206 }; 208 };
207 } 209 }
208 { 210 {
@@ -241,7 +243,7 @@
241 243
242 * { 244 * {
243 border: none; 245 border: none;
244 font-family: "Fira Sans Nerd Font"; 246 font-family: "Fira Sans";
245 font-size: 10pt; 247 font-size: 10pt;
246 min-height: 0; 248 min-height: 0;
247 } 249 }
@@ -252,10 +254,10 @@
252 } 254 }
253 255
254 .modules-left { 256 .modules-left {
255 margin-left: 8px; 257 margin-left: 12px;
256 } 258 }
257 .modules-right { 259 .modules-right {
258 margin-right: 8px; 260 margin-right: 12px;
259 } 261 }
260 262
261 .module { 263 .module {
@@ -280,11 +282,12 @@
280 color: @grey; 282 color: @grey;
281 margin: 0 5px; 283 margin: 0 5px;
282 } 284 }
283 #custom-weather, #custom-worktime-today { 285 #custom-weather {
284 margin-right: 3px; 286 margin-right: 3px;
285 } 287 }
286 #custom-keymap, #custom-weather { 288 #custom-keymap {
287 margin-left: 3px; 289 margin-left: 3px;
290 margin-right: 3px;
288 } 291 }
289 292
290 #tray { 293 #tray {
@@ -320,6 +323,12 @@
320 #idle_inhibitor.activated { 323 #idle_inhibitor.activated {
321 color: @white; 324 color: @white;
322 } 325 }
326 #custom-worktime.running, #custom-worktime-today.running {
327 color: @white;
328 }
329 #custom-worktime.over, #custom-worktime-today.over {
330 color: @orange;
331 }
323 332
324 #idle_inhibitor { 333 #idle_inhibitor {
325 padding-top: 1px; 334 padding-top: 1px;
@@ -327,7 +336,7 @@
327 336
328 #privacy { 337 #privacy {
329 color: @red; 338 color: @red;
330 margin: -1px 2px 0px 5px; 339 margin: -1px 4px 0px 3px;
331 } 340 }
332 #clock { 341 #clock {
333 /* margin-right: 5px; */ 342 /* margin-right: 5px; */
diff --git a/accounts/gkleen@sif/systemd.nix b/accounts/gkleen@sif/systemd.nix
index cefcf4ea..a89b46c2 100644
--- a/accounts/gkleen@sif/systemd.nix
+++ b/accounts/gkleen@sif/systemd.nix
@@ -123,7 +123,8 @@ in {
123 }; 123 };
124 emacs = { 124 emacs = {
125 Unit = { 125 Unit = {
126 After = ["graphical-session-pre.target"]; 126 After = [ "graphical-session.target" ];
127 BindsTo = [ "graphical-session.target" ];
127 }; 128 };
128 }; 129 };
129 keepassxc = { 130 keepassxc = {
@@ -135,8 +136,8 @@ in {
135 Environment = [ "QT_QPA_PLATFORM=wayland" ]; 136 Environment = [ "QT_QPA_PLATFORM=wayland" ];
136 }; 137 };
137 Unit = { 138 Unit = {
138 Requires = ["graphical-session-pre.target"]; 139 After = [ "graphical-session.target" ];
139 After = ["graphical-session-pre.target"]; 140 BindsTo = [ "graphical-session.target" ];
140 }; 141 };
141 }; 142 };
142 mpris-proxy = { 143 mpris-proxy = {
@@ -184,8 +185,8 @@ in {
184 WantedBy = ["graphical-session.target"]; 185 WantedBy = ["graphical-session.target"];
185 }; 186 };
186 Unit = { 187 Unit = {
187 Requires = ["graphical-session-pre.target"]; 188 After = [ "graphical-session.target" ];
188 After = ["graphical-session-pre.target"]; 189 PartOf = [ "graphical-session.target" ];
189 }; 190 };
190 Service = { 191 Service = {
191 ExecStart = lib.getExe pkgs.psi-notify; 192 ExecStart = lib.getExe pkgs.psi-notify;
@@ -198,6 +199,7 @@ in {
198 gtklock = { 199 gtklock = {
199 Unit = { 200 Unit = {
200 Requisite = ["graphical-session.target"]; 201 Requisite = ["graphical-session.target"];
202 After = [ "graphical-session.target" ];
201 PartOf = ["graphical-session.target"]; 203 PartOf = ["graphical-session.target"];
202 }; 204 };
203 Service = { 205 Service = {
@@ -205,53 +207,55 @@ in {
205 RuntimeDirectory = "gtklock"; 207 RuntimeDirectory = "gtklock";
206 CacheDirectory = "gtklock"; 208 CacheDirectory = "gtklock";
207 ExecStartPre = [ 209 ExecStartPre = [
208 "${pkgs.libsForQt5.qt5.qttools.bin}/bin/qdbus org.keepassxc.KeePassXC.MainWindow /keepassxc org.keepassxc.KeePassXC.MainWindow.lockAllDatabases" 210 "-${lib.getExe' pkgs.libsForQt5.qt5.qttools.bin "qdbus"} org.keepassxc.KeePassXC.MainWindow /keepassxc org.keepassxc.KeePassXC.MainWindow.lockAllDatabases"
209 "${config.systemd.package}/bin/systemctl --user stop gpg-agent.service" 211 "-${lib.getExe' config.systemd.package "systemctl"} --user stop gpg-agent.service"
210 (pkgs.writeShellScript "generate-css" '' 212 "-${lib.getExe pkgs.playerctl} -a pause"
211 set -x 213 "-${lib.getExe (pkgs.writeShellApplication {
212 export PATH="${lib.makeBinPath [cfg.programs.wpaperd.package pkgs.jq pkgs.coreutils pkgs.imagemagick pkgs.findutils]}:$PATH" 214 name = "generate-css";
215 runtimeInputs = with pkgs; [cfg.programs.wpaperd.package jq coreutils imagemagick findutils];
216 text = ''
217 declare -A monitors
218 monitors=()
219 while IFS= read -r entry; do
220 path=$(jq -r ".path" <<<"$entry")
221 [[ -z "$path" || ! -f "$path" ]] && continue
222 blurred_path="$CACHE_DIRECTORY"/"$(b2sum -l 128 <<<"$path" | cut -d' ' -f1)"."''${path##*.}"
223 monitor=$(jq -r ".display" <<<"$entry")
224 if [[ ! -f "$blurred_path" ]]; then
225 mkdir -p "$(dirname "$blurred_path")"
226 magick "$path" -filter Gaussian -resize 6.25% -define filter:sigma=2.5 -resize 1600% "$blurred_path" &
227 fi
228 monitors+=([$monitor]="$blurred_path")
229 done < <(wpaperctl all-wallpapers -j | jq -c ".[]")
230 # wait
213 231
214 declare -A monitors 232 cp --no-preserve=mode ${pkgs.writeText "gtklock.css" ''
215 monitors=() 233 #window-box {
216 while IFS= read -r entry; do 234 padding: 64px;
217 path=$(jq -r ".path" <<<"$entry") 235 /* border: 1px solid black; */
218 [[ -z "$path" || ! -f "$path" ]] && continue 236 border-radius: 4px;
219 blurred_path="$CACHE_DIRECTORY"/"$(b2sum -l 128 <<<"$path" | cut -d' ' -f1)"."''${path##*.}" 237 box-shadow: rgba(0, 0, 0, 0.8) 0px 4px 12px;
220 monitor=$(jq -r ".display" <<<"$entry") 238 /* background-color: white; */
221 if [[ ! -f "$blurred_path" ]]; then 239 background-color: rgba(0, 0, 0, 0.5);
222 mkdir -p "$(dirname "$blurred_path")" 240 }
223 magick "$path" -filter Gaussian -resize 6.25% -define filter:sigma=2.5 -resize 1600% "$blurred_path" & 241 ''} "$RUNTIME_DIRECTORY"/style.css
224 fi 242 for monitor in "''${!monitors[@]}"; do
225 monitors+=([$monitor]="$blurred_path") 243 cat >>"$RUNTIME_DIRECTORY"/style.css <<EOF
226 done < <(wpaperctl all-wallpapers -j | jq -c ".[]") 244 window#''${monitor} {
227 wait 245 background-image: url("''${monitors[$monitor]}");
228 246 background-repeat: no-repeat;
229 cp --no-preserve=mode ${pkgs.writeText "gtklock.css" '' 247 background-size: 100% 100%;
230 #window-box { 248 background-origin: content-box;
231 padding: 64px;
232 /* border: 1px solid black; */
233 border-radius: 4px;
234 box-shadow: rgba(0, 0, 0, 0.8) 0px 4px 12px;
235 /* background-color: white; */
236 background-color: rgba(0, 0, 0, 0.5);
237 } 249 }
238 ''} "$RUNTIME_DIRECTORY"/style.css 250 EOF
239 for monitor in "''${!monitors[@]}"; do 251 done
240 cat >>"$RUNTIME_DIRECTORY"/style.css <<EOF 252 '';
241 window#''${monitor} { 253 })}"
242 background-image: url("''${monitors[$monitor]}");
243 background-repeat: no-repeat;
244 background-size: 100% 100%;
245 background-origin: content-box;
246 }
247 EOF
248 done
249 '')
250 ]; 254 ];
251 NotifyAccess = "all"; 255 NotifyAccess = "all";
252 ExecStart = ''${lib.getExe pkgs.gtklock} -s "''${RUNTIME_DIRECTORY}/style.css" -L ${pkgs.writeShellScript "after-lock" '' 256 ExecStart = ''${lib.getExe pkgs.gtklock} -s "''${RUNTIME_DIRECTORY}/style.css" -L ${pkgs.writeShellScript "after-lock" ''
253 ${cfg.wayland.windowManager.hyprland.package}/bin/hyprctl dispatch dpms off 257 ${lib.getExe cfg.programs.niri.package} msg action power-off-monitors
254 ${config.systemd.package}/bin/systemd-notify --ready 258 ${lib.getExe' config.systemd.package "systemd-notify"} --ready
255 ''}''; 259 ''}'';
256 }; 260 };
257 }; 261 };
@@ -304,8 +308,8 @@ in {
304 WantedBy = ["graphical-session.target"]; 308 WantedBy = ["graphical-session.target"];
305 }; 309 };
306 Unit = { 310 Unit = {
307 BindsTo = ["graphical-session-pre.target"]; 311 After = [ "graphical-session.target" ];
308 After = ["graphical-session-pre.target"]; 312 PartOf = [ "graphical-session.target" ];
309 }; 313 };
310 Service = { 314 Service = {
311 ExecStart = lib.getExe cfg.programs.wpaperd.package; 315 ExecStart = lib.getExe cfg.programs.wpaperd.package;
@@ -314,6 +318,36 @@ in {
314 RestartSec = "2s"; 318 RestartSec = "2s";
315 }; 319 };
316 }; 320 };
321 xembed-sni-proxy = {
322 Unit = {
323 PartOf = lib.mkForce ["tray.target"];
324 BindsTo = ["xwayland-satellite.service"];
325 After = ["xwayland-satellite.service"];
326 };
327 };
328 poweralertd = {
329 Unit = {
330 After = ["graphical-session.target"];
331 };
332 };
333 network-manager-applet = {
334 Unit = {
335 PartOf = lib.mkForce ["tray.target"];
336 };
337 };
338 udiskie = {
339 Unit = {
340 PartOf = lib.mkForce ["tray.target"];
341 };
342 };
343 blueman-applet = {
344 Unit = {
345 PartOf = lib.mkForce ["tray.target"];
346 };
347 Install = {
348 WantedBy = lib.mkForce ["tray.target"];
349 };
350 };
317 } // listToAttrs (map ({host, port}: nameValuePair "proxy-to-autossh-socks@${toString port}" { 351 } // listToAttrs (map ({host, port}: nameValuePair "proxy-to-autossh-socks@${toString port}" {
318 Unit = { 352 Unit = {
319 Requires = ["autossh-socks@${host}:${toString (port + 1)}.service" "proxy-to-autossh-socks@${toString port}.socket"]; 353 Requires = ["autossh-socks@${host}:${toString (port + 1)}.service" "proxy-to-autossh-socks@${toString port}.socket"];
@@ -364,6 +398,9 @@ in {
364 }; 398 };
365 tray = { 399 tray = {
366 Unit = { 400 Unit = {
401 PartOf = [ "graphical-session.target" ];
402 Requires = [ "waybar.service" ];
403 After = [ "graphical-session.target" "waybar.service" ];
367 Wants = ["blueman-applet.service" "udiskie.service" "network-manager-applet.service"]; 404 Wants = ["blueman-applet.service" "udiskie.service" "network-manager-applet.service"];
368 }; 405 };
369 }; 406 };