summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif/niri/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@sif/niri/default.nix')
-rw-r--r--accounts/gkleen@sif/niri/default.nix577
1 files changed, 577 insertions, 0 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix
new file mode 100644
index 00000000..165eb5fa
--- /dev/null
+++ b/accounts/gkleen@sif/niri/default.nix
@@ -0,0 +1,577 @@
1{ config, hostConfig, 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 makoctl = lib.getExe' config.services.mako.package "makoctl";
8 loginctl = lib.getExe' hostConfig.systemd.package "loginctl";
9 systemctl = lib.getExe' hostConfig.systemd.package "systemctl";
10
11 focus_or_spawn = pkgs.writeShellApplication {
12 name = "focus-or-spawn";
13 runtimeInputs = [ niri pkgs.gojq pkgs.gnugrep pkgs.socat ];
14 text = ''
15 window_select="$1"
16 shift
17 workspace_name="$1"
18 shift
19
20 workspaces_json="$(niri msg -j workspaces)"
21 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")"
23 active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")"
24 if [[ $workspace_output != "$active_output" ]]; then
25 niri msg action move-workspace-to-monitor --output "$active_output" "$workspace_name"
26 socat STDIO "$NIRI_SOCKET" <<<'{"Action":{"FocusWorkspace":{"reference":{"Id":'"''${active_workspace}"'}}}}'
27 niri msg action move-workspace-to-index --index 1 "$workspace_name"
28 fi
29
30 while IFS=$'\n' read -r window_json; do
31 if [[ -n $(jq -c "$window_select" <<<"$window_json") ]]; then
32 niri msg action focus-window --id "$(jq -r '.id' <<<"$window_json")"
33 exit 0
34 fi
35 done < <(niri msg -j windows | jq -c '.[]')
36
37 exec "$@"
38 '';
39 };
40 focus-or-spawn-action = config.lib.niri.actions.spawn (lib.getExe focus_or_spawn);
41 focus-or-spawn-action-app_id = app_id: focus-or-spawn-action ''select(.app_id == "${app_id}")'';
42
43 with_adjacent_workspace = pkgs.writeShellApplication {
44 name = "with-adjacent-workspace";
45 runtimeInputs = [ niri pkgs.gojq pkgs.socat ];
46 text = ''
47 blacklist="$1"
48 shift
49 direction="$1"
50 shift
51 action="$1"
52 shift
53
54 workspaces_json="$(niri msg -j workspaces)"
55 active_workspace="$(jq -r '.[] | select(.is_focused) | .id' <<<"$workspaces_json")"
56 workspace_output="$(jq -r --arg active_workspace "$active_workspace" '.[] | select(.id == ($active_workspace | tonumber)) | .output' <<<"$workspaces_json")"
57 workspace_idx="$(jq -r '.[] | select(.is_focused) | .idx' <<<"$workspaces_json")"
58
59 jq_script='map(select('
60 case "$direction" in
61 down)
62 # shellcheck disable=SC2016
63 jq_script=''${jq_script}'.idx > ($workspace_idx | tonumber)';;
64 up)
65 # shellcheck disable=SC2016
66 jq_script=''${jq_script}'.idx < ($workspace_idx | tonumber)';;
67 esac
68 # shellcheck disable=SC2016
69 jq_script=''${jq_script}' and .output == $workspace_output and ((.name == null) or (.name | test($blacklist) | not)))) | sort_by(.idx)'
70 [[ $direction == "up" ]] && jq_script=''${jq_script}' | reverse'
71 jq_script=''${jq_script}' | .[0]'
72
73 workspace_json=$(jq -c --arg blacklist "$blacklist" --arg workspace_output "$workspace_output" --arg workspace_idx "$workspace_idx" "$jq_script" <<<"$workspaces_json")
74 [[ -n $workspace_json && $workspace_json != null ]] || exit 0
75 jq --arg active_workspace "$active_workspace" -c "$action" <<<"$workspace_json" | tee /dev/stderr | socat STDIO "$NIRI_SOCKET"
76 '';
77 };
78 with-adjacent-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_adjacent_workspace) "^pwctl|kpxc|bmgr|edit|term$";
79 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}}}}'';
81
82 with_unnamed_workspace = pkgs.writeShellApplication {
83 name = "with-unnamed-workspace";
84 runtimeInputs = [ niri pkgs.gojq pkgs.socat ];
85 text = ''
86 action="$1"
87 shift
88
89 workspaces_json="$(niri msg -j workspaces)"
90 active_output="$(jq -r '.[] | select(.is_focused) | .output' <<<"$workspaces_json")"
91 active_workspace="$(jq -r '.[] | select(.is_focused) | .id' <<<"$workspaces_json")"
92
93 workspace_json="$(jq -c --arg active_output "$active_output" 'map(select(.output == $active_output and .name == null)) | sort_by(.idx) | .[0]' <<<"$workspaces_json")"
94 [[ -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"
96 '';
97 };
98 with-unnamed-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_unnamed_workspace);
99
100 with_select_window = pkgs.writeShellApplication {
101 name = "with-unnamed-workspace";
102 runtimeInputs = [ niri pkgs.gojq pkgs.socat config.programs.fuzzel.package pkgs.gawk ];
103 text = ''
104 window_select="$1"
105 shift
106 action="$1"
107 shift
108
109 windows_json="$(niri msg -j windows)"
110 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)"
112 window_id="$(awk -F $'\t' '{print $2}' <<<"$window")"
113 window_json="$(jq -r --arg window_id "$window_id" '.[] | select(.id == ($window_id | tonumber))' <<<"$windows_json")"
114
115 [[ -z "$window_json" ]] && exit 1
116
117 jq -c "$action" <<<"$window_json" | socat STDIO "$NIRI_SOCKET"
118 '';
119 };
120 with-select-window-action = config.lib.niri.actions.spawn (lib.getExe with_select_window);
121in {
122 imports = [
123 ./waybar.nix
124 ./mako.nix
125 ];
126
127 config = {
128 systemd.user.services.xwayland-satellite = {
129 Unit = {
130 BindsTo = [ "graphical-session.target" ];
131 PartOf = [ "graphical-session.target" ];
132 After = [ "graphical-session.target" ];
133 Requisite = [ "graphical-session.target" ];
134 };
135 Service = {
136 Type = "notify";
137 NotifyAccess = "all";
138 Environment = [ "DISPLAY=:0" ];
139 ExecStart = ''${lib.getExe pkgs.xwayland-satellite-unstable} ''${DISPLAY}'';
140 ExecStartPre = "${systemctl} --user import-environment DISPLAY";
141 StandardOutput = "journal";
142 };
143 Install = {
144 WantedBy = [ "graphical-session.target" ];
145 };
146 };
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
159 programs.niri.settings = {
160 prefer-no-csd = true;
161 screenshot-path = "${config.home.homeDirectory}/screenshots";
162
163 hotkey-overlay.skip-at-startup = true;
164
165 input = {
166 keyboard.xkb = {
167 layout = "us,us";
168 variant = "dvp,";
169 options = "compose:caps,grp:win_space_toggle";
170 };
171
172 workspace-auto-back-and-forth = true;
173 # focus-follows-mouse.enable = true;
174 warp-mouse-to-focus = true;
175 };
176
177 outputs = {
178 "eDP-1" = {
179 scale = 1.5;
180 position = { x = 0; y = 0; };
181 };
182 "Ancor Communications Inc ASUS PB287Q 0x0000DD9B" = {
183 scale = 1.5;
184 position = { x = 2560; y = 0; };
185 };
186 "HP Inc. HP 727pu CN4417143K" = {
187 mode = { width = 2560; height = 1440; refresh = 119.998; };
188 scale = 1;
189 position = { x = 2560; y = 0; };
190 variable-refresh-rate = "on-demand";
191 };
192 };
193
194 environment = {
195 NIXOS_OZONE_WL = "1";
196 QT_QPA_PLATFORM = "wayland";
197 QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
198 GDK_BACKEND = "wayland";
199 SDL_VIDEODRIVER = "wayland";
200 DISPLAY = ":0";
201 };
202
203 layout = {
204 gaps = 8;
205 struts = { left = 0; right = 0; top = 0; bottom = 0; };
206 focus-ring = {
207 width = 2;
208 active.gradient = {
209 from = "hsla(195 100% 60% 0.75)";
210 to = "hsla(155 100% 50% 0.75)";
211 angle = 29;
212 relative-to = "workspace-view";
213 };
214 inactive.gradient = {
215 from = "hsla(0 0% 42% 0.66)";
216 to = "hsla(0 0% 35% 0.66)";
217 angle = 29;
218 relative-to = "workspace-view";
219 };
220 };
221
222 preset-column-widths = [
223 { proportion = 1. / 4.; }
224 { proportion = 1. / 3.; }
225 { proportion = 1. / 2.; }
226 { proportion = 2. / 3.; }
227 { proportion = 3. / 4.; }
228 ];
229 default-column-width.proportion = 1. / 2.;
230 preset-window-heights = [
231 { proportion = 1. / 3.; }
232 { proportion = 1. / 2.; }
233 { proportion = 2. / 3.; }
234 { proportion = 1.; }
235 ];
236
237 always-center-single-column = true;
238 };
239
240 cursor.hide-when-typing = true;
241
242 workspaces = {
243 "001" = { name = "pwctl"; open-on-output = "eDP-1"; };
244 "002" = { name = "kpxc"; open-on-output = "eDP-1"; };
245 "003" = { name = "bmgr"; open-on-output = "eDP-1"; };
246 "004" = { name = "term"; open-on-output = "eDP-1"; };
247 "005" = { name = "edit"; open-on-output = "eDP-1"; };
248 "101".name = "comm";
249 "102".name = "web";
250 # "104".name = "read";
251 # "105".name = "mon";
252 "110".name = "vid";
253 };
254
255 window-rules = [
256 # {
257 # geometry-corner-radius =
258 # let
259 # allCorners = r: { bottom-left = r; bottom-right = r; top-left = r; top-right = r; };
260 # in allCorners 4.;
261 # clip-to-geometry = true;
262 # }
263 {
264 matches = [ { app-id = "^com\.saivert\.pwvucontrol$"; } ];
265 open-on-workspace = "pwctl";
266 open-maximized = true;
267 }
268 {
269 matches = [ { app-id = "^\.blueman-manager-wrapped$"; } ];
270 open-on-workspace = "bmgr";
271 open-maximized = true;
272 }
273 {
274 matches = [ { app-id = "^org\.keepassxc\.KeePassXC$"; } ];
275 block-out-from = "screencast";
276 }
277 {
278 matches = [ { app-id = "^org\.keepassxc\.KeePassXC$"; } ];
279 excludes = [
280 { title = "^Unlock Database.*"; }
281 { title = "^Access Request.*"; }
282 { title = ".*Passkey credentials$"; }
283 ];
284 open-on-workspace = "kpxc";
285 open-maximized = true;
286 open-focused = false;
287 }
288 {
289 matches = [
290 { app-id = "^org\.keepassxc\.KeePassXC$"; title = "^Unlock Database.*"; }
291 { app-id = "^org\.keepassxc\.KeePassXC$"; title = "^Access Request.*"; }
292 { app-id = "^org\.keepassxc\.KeePassXC$"; title = ".*Passkey credentials$"; }
293 ];
294 open-focused = true;
295 }
296 {
297 matches = [ { app-id = "^kitty-scratch$"; } ];
298 open-on-workspace = "term";
299 open-maximized = true;
300 }
301 {
302 matches = [ { title = "^scratch$"; app-id = "^emacs$"; } ];
303 open-on-workspace = "edit";
304 open-maximized = true;
305 }
306 {
307 matches = [
308 { app-id = "^emacs$"; }
309 { app-id = "^firefox$"; }
310 ];
311 default-column-width.proportion = 2. / 3.;
312 }
313 {
314 matches = [
315 { app-id = "^kitty$"; }
316 { app-id = "^kitty-play$"; }
317 ];
318 default-column-width.proportion = 1. / 3.;
319 }
320 {
321 matches = [
322 { app-id = "^thunderbird$"; }
323 { app-id = "^Element$"; }
324 ];
325 open-on-workspace = "comm";
326 }
327 {
328 matches = [ { app-id = "^firefox$"; } ];
329 open-on-workspace = "web";
330 open-maximized = true;
331 variable-refresh-rate = true;
332 }
333 # {
334 # matches = [
335 # { app-id = "^evince$"; }
336 # { app-id = "^imv$"; }
337 # { app-id = "^org\.pwmt\.zathura$"; }
338 # ];
339 # open-on-workspace = "read";
340 # }
341 {
342 matches = [ { app-id = "^mpv$"; } ];
343 open-on-workspace = "vid";
344 default-column-width.proportion = 1.;
345 variable-refresh-rate = true;
346 }
347 {
348 matches = [ { app-id = "^kitty-play$"; } ];
349 open-on-workspace = "vid";
350 open-focused = false;
351 }
352 # {
353 # matches = [
354 # { app-id = "^qemu$"; }
355 # { app-id = "^virt-manager$"; }
356 # ];
357 # open-on-workspace = "mon";
358 # }
359 ];
360 layer-rules = [
361 { matches = [
362 { namespace = "^notifications$"; }
363 { namespace = "^waybar$"; }
364 ];
365 block-out-from = "screencast";
366 }
367 ];
368
369 binds = with config.lib.niri.actions; {
370 "Mod+Slash".action = show-hotkey-overlay;
371
372 "Mod+Return".action = spawn terminal;
373 "Mod+Q".action = close-window;
374 "Mod+O".action = spawn (lib.getExe config.programs.fuzzel.package);
375 "Mod+Shift+O".action = spawn (lib.getExe config.programs.fuzzel.package) "--list-executables-in-path";
376
377 "Mod+Alt+E".action = spawn (lib.getExe' config.services.emacs.package "emacsclient") "-c";
378 "Mod+Alt+Y".action = spawn (lib.getExe (pkgs.writeShellApplication {
379 name = "queue-yt-dlp";
380 runtimeInputs = with pkgs; [ wl-clipboard-rs socat ];
381 text = ''
382 socat STDIO UNIX-CONNECT:"$XDG_RUNTIME_DIR"/yt-dlp.sock <<<$'{ "urls": ["'"$(wl-paste)"$'"] }'
383 '';
384 }));
385 "Mod+Alt+L".action = spawn (lib.getExe (pkgs.writeShellApplication {
386 name = "queue-yt-dlp";
387 runtimeInputs = with pkgs; [ wl-clipboard-rs config.programs.kitty.package ];
388 text = ''
389 exec -- kitty --app-id kitty-play --directory "$HOME"/media mpv "$(wl-paste)"
390 '';
391 }));
392
393 "Mod+U".action = spawn (lib.getExe (pkgs.writeShellApplication {
394 name = "qalc-fuzzel";
395 runtimeInputs = with pkgs; [ wl-clipboard-rs libqalculate config.programs.fuzzel.package coreutils findutils libnotify gnugrep ];
396 text = ''
397 RESULTS_DIR="$HOME/.cache/qalc-fuzzel"
398 prev() {
399 FOUND=false
400 while IFS= read -r line; do
401 [[ -n "$line" ]] || continue
402 FOUND=true
403 echo "$line"
404 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)
405 $FOUND || echo
406 }
407 FUZZEL_RES=$(prev | fuzzel --dmenu --prompt "qalc> ") || exit $?
408 if [[ "$FUZZEL_RES" =~ .*\ =\ .* ]]; then
409 QALC_RES="$FUZZEL_RES"
410 QALC_RET=0
411 else
412 QALC_RES=$(qalc "$FUZZEL_RES" 2>&1)
413 QALC_RET=$?
414 fi
415 [[ -n "$QALC_RES" ]] || exit 1
416 EXISTING=false
417 set +e
418 grep -Fxrl "$QALC_RES" "$RESULTS_DIR" | xargs -r touch
419 [[ ''${PIPESTATUS[0]} -eq 0 ]] && EXISTING=true
420 set -e
421 if [[ $QALC_RET -eq 0 ]] && ! $EXISTING; then
422 RES_FILE="$RESULTS_DIR"/$(date -uIs).$(tr -Cd 'a-zA-Z0-9' </dev/random | head -c 10)
423 cat >"$RES_FILE" <<<"$QALC_RES"
424 fi
425 [[ "$QALC_RES" =~ .*\ =\ (.*) ]] && QALC_RES="''${BASH_REMATCH[1]}"
426 [[ $QALC_RET -eq 0 ]] && wl-copy "$QALC_RES"
427 notify-send "$QALC_RES"
428 '';
429 }));
430 "Mod+E".action = spawn (lib.getExe (pkgs.writeShellApplication {
431 name = "emoji-fuzzel";
432 runtimeInputs = with pkgs; [ config.programs.fuzzel.package wtype wl-clipboard-rs ];
433 text = ''
434 FUZZEL_RES=$(fuzzel --dmenu --prompt "emoji> " <"$HOME"/.local/share/emoji-data/list.txt) || exit $?
435 [[ -n "$FUZZEL_RES" ]] || exit 1
436 wl-copy "$(cut -d ':' -f 1 <<<"$FUZZEL_RES" | tr -d '\n')" && wtype -k XF86Paste
437 '';
438 }));
439 "Print".action = spawn (lib.getExe (pkgs.writeShellApplication {
440 name = "screenshot";
441 runtimeInputs = with pkgs; [ grim slurp wl-clipboard-rs coreutils ];
442 text = ''
443 grim -g "$(slurp -b 00000080 -c FFFFFFFF -s 00000000 -w 1)" - \
444 | tee "$HOME/screenshots/$(date +"%Y-%m-%dT%H:%M:%S").png" \
445 | wl-copy --type image/png
446 '';
447 }));
448 "Shift+Print".action = spawn (lib.getExe (pkgs.writeShellApplication {
449 name = "screenshot";
450 runtimeInputs = with pkgs; [ grim niri gojq wl-clipboard-rs coreutils ];
451 text = ''
452 grim -o "$(niri msg -j workspaces | jq -r '.[] | select(.is_focused) | .output')" - \
453 | tee "$HOME/screenshots/$(date +"%Y-%m-%dT%H:%M:%S").png" \
454 | wl-copy --type image/png
455 '';
456 }));
457 "Mod+B".action = with-select-window-action ".workspace_id == ($active_workspace | tonumber)" "{\"Action\":{\"FocusWindow\":{\"id\": .id}}}";
458 "Mod+Shift+B".action = with-select-window-action "true" "{\"Action\":{\"FocusWindow\":{\"id\": .id}}}";
459
460 "Mod+H".action = focus-column-left;
461 "Mod+T".action = focus-window-down;
462 "Mod+N".action = focus-window-up;
463 "Mod+S".action = focus-column-right;
464
465 "Mod+Shift+H".action = move-column-left;
466 "Mod+Shift+T".action = move-window-down;
467 "Mod+Shift+N".action = move-window-up;
468 "Mod+Shift+S".action = move-column-right;
469
470 "Mod+Control+H".action = focus-monitor-left;
471 "Mod+Control+T".action = focus-monitor-down;
472 "Mod+Control+N".action = focus-monitor-up;
473 "Mod+Control+S".action = focus-monitor-right;
474
475 "Mod+Shift+Control+H".action = move-workspace-to-monitor-left;
476 "Mod+Shift+Control+T".action = move-workspace-to-monitor-down;
477 "Mod+Shift+Control+N".action = move-workspace-to-monitor-up;
478 "Mod+Shift+Control+S".action = move-workspace-to-monitor-right;
479
480 "Mod+G".action = focus-adjacent-workspace "down";
481 "Mod+C".action = focus-adjacent-workspace "up";
482
483 "Mod+Shift+G".action = move-column-to-adjacent-workspace "down";
484 "Mod+Shift+C".action = move-column-to-adjacent-workspace "up";
485
486 "Mod+Shift+Control+G".action = move-workspace-down;
487 "Mod+Shift+Control+C".action = move-workspace-up;
488
489 "Mod+ParenLeft".action = focus-workspace "comm";
490 "Mod+Shift+ParenLeft".action = move-column-to-workspace "comm";
491
492 "Mod+ParenRight".action = focus-workspace "web";
493 "Mod+Shift+ParenRight".action = move-column-to-workspace "web";
494
495 "Mod+BraceRight".action = focus-workspace "read";
496 "Mod+Shift+BraceRight".action = move-column-to-workspace "read";
497
498 "Mod+BraceLeft".action = focus-workspace "mon";
499 "Mod+Shift+BraceLeft".action = move-column-to-workspace "mon";
500
501 "Mod+Asterisk".action = focus-workspace "vid";
502 "Mod+Shift+Asterisk".action = move-column-to-workspace "vid";
503
504 "Mod+Plus".action = with-unnamed-workspace-action ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}'';
505 "Mod+Shift+Plus".action = with-unnamed-workspace-action ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}}}}'';
506
507 "Mod+M".action = consume-or-expel-window-left;
508 "Mod+W".action = consume-or-expel-window-right;
509
510 "Mod+R".action = switch-preset-column-width;
511 "Mod+Shift+R".action = switch-preset-window-height;
512 "Mod+F".action = center-column;
513 "Mod+Shift+F".action = maximize-column;
514 "Mod+Shift+Ctrl+F".action = fullscreen-window;
515
516 "Mod+V".action = switch-focus-between-floating-and-tiling;
517 "Mod+Shift+V".action = toggle-window-floating;
518
519 "Mod+Left".action = set-column-width "-10%";
520 "Mod+Down".action = set-window-height "-10%";
521 "Mod+Up".action = set-window-height "+10%";
522 "Mod+Right".action = set-column-width "+10%";
523
524 "Mod+Shift+Z" = {
525 action = spawn (lib.getExe niri) "msg" "action" "power-off-monitors";
526 allow-when-locked = true;
527 };
528 "Mod+Shift+L".action = spawn loginctl "lock-session";
529 "Mod+Shift+E".action = quit;
530 "Mod+Shift+Minus" = {
531 action = spawn systemctl "suspend";
532 allow-when-locked = true;
533 };
534 "Mod+Shift+Control+Minus" = {
535 action = spawn systemctl "hibernate";
536 allow-when-locked = true;
537 };
538
539 "XF86MonBrightnessUp" = {
540 action = spawn lightctl "-d" "-e4" "-n1" "up";
541 allow-when-locked = true;
542 };
543 "XF86MonBrightnessDown" = {
544 action = spawn lightctl "-d" "-e4" "-n1" "down";
545 allow-when-locked = true;
546 };
547 "XF86AudioRaiseVolume" = {
548 action = spawn volumectl "-d" "-u" "up";
549 allow-when-locked = true;
550 };
551 "XF86AudioLowerVolume" = {
552 action = spawn volumectl "-d" "-u" "down";
553 allow-when-locked = true;
554 };
555 "XF86AudioMute" = {
556 action = spawn volumectl "-d" "toggle-mute";
557 allow-when-locked = true;
558 };
559 "XF86AudioMicMute" = {
560 action = spawn volumectl "-d" "-m" "toggle-mute";
561 allow-when-locked = true;
562 };
563
564 "Mod+Semicolon".action = spawn makoctl "dismiss" "--group";
565 "Mod+Shift+Semicolon".action = spawn makoctl "dismiss" "--all";
566 "Mod+Period".action = spawn makoctl "menu" (lib.getExe config.programs.fuzzel.package) "--dmenu";
567 "Mod+Comma".action = spawn makoctl "restore";
568
569 "Mod+Control+A".action = focus-or-spawn-action-app_id "com.saivert.pwvucontrol" "pwctl" "pwvucontrol";
570 "Mod+Control+P".action = focus-or-spawn-action-app_id "org.keepassxc.KeePassXC" "kpxc" "keepassxc";
571 "Mod+Control+B".action = focus-or-spawn-action-app_id ".blueman-manager-wrapped" "bmgr" "blueman-manager";
572 "Mod+Control+Return".action = focus-or-spawn-action-app_id "kitty-scratch" "term" "kitty" "--app-id" "kitty-scratch";
573 "Mod+Control+E".action = focus-or-spawn-action "select(.app_id == \"emacs\" and .title == \"scratch\")" "edit" "emacsclient" "-c" "--frame-parameters=(quote (name . \"scratch\"))";
574 };
575 };
576 };
577}