summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@sif')
-rw-r--r--accounts/gkleen@sif/niri/default.nix291
-rw-r--r--accounts/gkleen@sif/niri/waybar.nix16
-rw-r--r--accounts/gkleen@sif/systemd.nix14
3 files changed, 281 insertions, 40 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix
index 6a8d10a0..fa39fdd4 100644
--- a/accounts/gkleen@sif/niri/default.nix
+++ b/accounts/gkleen@sif/niri/default.nix
@@ -1,10 +1,101 @@
1{ config, pkgs, lib, ... }: 1{ config, hostConfig, pkgs, lib, ... }:
2let 2let
3 niri = config.programs.niri.package; 3 niri = config.programs.niri.package;
4 terminal = lib.getExe config.programs.kitty.package; 4 terminal = lib.getExe config.programs.kitty.package;
5 lightctl = lib.getExe' config.services.avizo.package "lightctl"; 5 lightctl = lib.getExe' config.services.avizo.package "lightctl";
6 volumectl = lib.getExe' config.services.avizo.package "volumectl"; 6 volumectl = lib.getExe' config.services.avizo.package "volumectl";
7 dunstctl = lib.getExe' config.services.dunst.package "dunstctl"; 7 dunstctl = lib.getExe' config.services.dunst.package "dunstctl";
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 && $active_workspace != "$(jq -r '.id' <<<"$workspace_json")" ]] || 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);
8in { 99in {
9 imports = [ 100 imports = [
10 ./waybar.nix 101 ./waybar.nix
@@ -21,7 +112,9 @@ in {
21 Service = { 112 Service = {
22 Type = "notify"; 113 Type = "notify";
23 NotifyAccess = "all"; 114 NotifyAccess = "all";
24 ExecStart = lib.getExe pkgs.xwayland-satellite-unstable; 115 Environment = [ "DISPLAY=:0" ];
116 ExecStart = ''${lib.getExe pkgs.xwayland-satellite-unstable} ''${DISPLAY}'';
117 ExecStartPre = "${systemctl} --user import-environment DISPLAY";
25 StandardOutput = "journal"; 118 StandardOutput = "journal";
26 }; 119 };
27 Install = { 120 Install = {
@@ -29,16 +122,44 @@ in {
29 }; 122 };
30 }; 123 };
31 124
125 services.swayidle = {
126 events = [
127 { event = "after-resume"; command = "${lib.getExe niri} msg action power-on-monitors"; }
128 ];
129 timeouts = [
130 { timeout = 300;
131 command = "${lib.getExe niri} msg action power-off-monitors";
132 }
133 ];
134 };
135
32 programs.niri.settings = { 136 programs.niri.settings = {
33 prefer-no-csd = true; 137 prefer-no-csd = true;
34 screenshot-path = "${config.home.homeDirectory}/screenshots"; 138 screenshot-path = "${config.home.homeDirectory}/screenshots";
35 139
140 hotkey-overlay.skip-at-startup = true;
141
36 input = { 142 input = {
37 keyboard.xkb = { 143 keyboard.xkb = {
38 layout = "us,"; 144 layout = "us,us";
39 variant = "dvp,"; 145 variant = "dvp,";
40 options = "compose:caps,grp:win_space_toggle"; 146 options = "compose:caps,grp:win_space_toggle";
41 }; 147 };
148
149 workspace-auto-back-and-forth = true;
150 # focus-follows-mouse.enable = true;
151 warp-mouse-to-focus = true;
152 };
153
154 outputs = {
155 "Samsung Display Corp. 0x4141 Unknown" = {
156 scale = 1.5;
157 position = { x = 0; y = 0; };
158 };
159 "Ancor Communications Inc ASUS PB287Q 0x0000DD9B" = {
160 scale = 1.5;
161 position = { x = 2560; y = 0; };
162 };
42 }; 163 };
43 164
44 environment = { 165 environment = {
@@ -48,14 +169,123 @@ in {
48 SDL_VIDEODRIVER = "wayland"; 169 SDL_VIDEODRIVER = "wayland";
49 }; 170 };
50 171
172 layout = {
173 gaps = 8;
174 struts = { left = 0; right = 0; top = 0; bottom = 0; };
175 focus-ring = {
176 width = 2;
177 };
178
179 preset-column-widths = [
180 { proportion = 1. / 4.; }
181 { proportion = 1. / 3.; }
182 { proportion = 1. / 2.; }
183 { proportion = 2. / 3.; }
184 { proportion = 3. / 4.; }
185 ];
186 default-column-width.proportion = 1. / 2.;
187 preset-window-heights = [
188 { proportion = 1. / 3.; }
189 { proportion = 1. / 2.; }
190 { proportion = 2. / 3.; }
191 { proportion = 1.; }
192 ];
193
194 always-center-single-column = true;
195 };
196
51 cursor.hide-when-typing = true; 197 cursor.hide-when-typing = true;
52 198
199 workspaces = {
200 "001".name = "pwctl";
201 "002".name = "kpxc";
202 "003".name = "bmgr";
203 "004".name = "term";
204 "005".name = "edit";
205 "101".name = "comm";
206 "102".name = "web";
207 "104".name = "read";
208 "105".name = "mon";
209 "110".name = "vid";
210 };
211
212 window-rules = [
213 {
214 geometry-corner-radius =
215 let
216 allCorners = r: { bottom-left = r; bottom-right = r; top-left = r; top-right = r; };
217 in allCorners 4.;
218 clip-to-geometry = true;
219 open-focused = true;
220 }
221 {
222 matches = [ { app-id = "^com\.saivert\.pwvucontrol$"; } ];
223 open-on-workspace = "pwctl";
224 }
225 {
226 matches = [ { app-id = "^\.blueman-manager-wrapped$"; } ];
227 open-on-workspace = "bmgr";
228 }
229 {
230 matches = [ { app-id = "^org\.keepassxc\.KeePassXC$"; } ];
231 excludes = [
232 { title = "^Unlock Database"; }
233 { title = "^Access Request"; }
234 { title = "^Passkey credentials"; }
235 ];
236 open-on-workspace = "kpxc";
237 open-focused = false;
238 }
239 {
240 matches = [ { app-id = "^kitty-scratch$"; } ];
241 open-on-workspace = "term";
242 }
243 {
244 matches = [ { title = "^scratch$"; app-id = "^emacs$"; } ];
245 open-on-workspace = "edit";
246 }
247 {
248 matches = [
249 { app-id = "^thunderbird$"; }
250 { app-id = "^Element$"; }
251 ];
252 open-on-workspace = "comm";
253 }
254 {
255 matches = [ { app-id = "^firefox$"; } ];
256 open-on-workspace = "web";
257 }
258 {
259 matches = [
260 { app-id = "^evince$"; }
261 { app-id = "^imv$"; }
262 { app-id = "^org\.pwmt\.zathura$"; }
263 ];
264 open-on-workspace = "read";
265 }
266 {
267 matches = [ { app-id = "^mpv$"; } ];
268 open-on-workspace = "vid";
269 }
270 {
271 matches = [
272 { app-id = "^qemu$"; }
273 { app-id = "^virt-manager$"; }
274 ];
275 open-on-workspace = "mon";
276 }
277 ];
278
53 binds = with config.lib.niri.actions; { 279 binds = with config.lib.niri.actions; {
280 "Mod+Slash".action = show-hotkey-overlay;
281
54 "Mod+Return".action = spawn terminal; 282 "Mod+Return".action = spawn terminal;
55 "Mod+Q".action = close-window; 283 "Mod+Q".action = close-window;
56 "Mod+D".action = spawn (lib.getExe config.programs.fuzzel.package); 284 "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"; 285 "Mod+Shift+D".action = spawn (lib.getExe config.programs.fuzzel.package) "--list-executables-in-path";
58 286
287 "Mod+Alt+E".action = spawn (lib.getExe' config.services.emacs.package "emacsclient") "-c";
288
59 "Mod+H".action = focus-column-left; 289 "Mod+H".action = focus-column-left;
60 "Mod+T".action = focus-window-down; 290 "Mod+T".action = focus-window-down;
61 "Mod+N".action = focus-window-up; 291 "Mod+N".action = focus-window-up;
@@ -76,23 +306,44 @@ in {
76 "Mod+Shift+Control+N".action = move-workspace-to-monitor-up; 306 "Mod+Shift+Control+N".action = move-workspace-to-monitor-up;
77 "Mod+Shift+Control+S".action = move-workspace-to-monitor-right; 307 "Mod+Shift+Control+S".action = move-workspace-to-monitor-right;
78 308
79 "Mod+G".action = focus-workspace-down; 309 "Mod+G".action = focus-adjacent-workspace "down";
80 "Mod+C".action = focus-workspace-up; 310 "Mod+C".action = focus-adjacent-workspace "up";
311
312 "Mod+Shift+G".action = move-column-to-adjacent-workspace "down";
313 "Mod+Shift+C".action = move-column-to-adjacent-workspace "up";
314
315 "Mod+Shift+Control+G".action = move-workspace-down;
316 "Mod+Shift+Control+C".action = move-workspace-up;
317
318 "Mod+ParenLeft".action = focus-workspace "comm";
319 "Mod+Shift+ParenLeft".action = move-column-to-workspace "comm";
81 320
82 "Mod+Control+G".action = move-column-to-workspace-down; 321 "Mod+ParenRight".action = focus-workspace "web";
83 "Mod+Control+C".action = move-column-to-workspace-up; 322 "Mod+Shift+ParenRight".action = move-column-to-workspace "web";
84 323
85 "Mod+Shift+G".action = move-workspace-down; 324 "Mod+BraceRight".action = focus-workspace "read";
86 "Mod+Shift+C".action = move-workspace-up; 325 "Mod+Shift+BraceRight".action = move-column-to-workspace "read";
87 326
88 "Mod+M".action = consume-window-into-column; 327 "Mod+BraceLeft".action = focus-workspace "mon";
89 "Mod+W".action = expel-window-from-column; 328 "Mod+Shift+BraceLeft".action = move-column-to-workspace "mon";
90 329
91 "Mod+F".action = maximize-column; 330 "Mod+Asterisk".action = focus-workspace "vid";
92 "Mod+Shift+F".action = fullscreen-window; 331 "Mod+Shift+Asterisk".action = move-column-to-workspace "vid";
93 332
94 "Mod+Space".action = switch-focus-between-floating-and-tiling; 333 "Mod+Plus".action = with-unnamed-workspace-action ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}'';
95 "Mod+Shift+Space".action = toggle-window-floating; 334 "Mod+Shift+Plus".action = with-unnamed-workspace-action ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}}}}'';
335
336 "Mod+M".action = consume-or-expel-window-left;
337 "Mod+W".action = consume-or-expel-window-right;
338
339 "Mod+R".action = switch-preset-column-width;
340 "Mod+Shift+R".action = switch-preset-window-height;
341 "Mod+F".action = center-column;
342 "Mod+Shift+F".action = maximize-column;
343 "Mod+Shift+Ctrl+F".action = fullscreen-window;
344
345 "Mod+B".action = switch-focus-between-floating-and-tiling;
346 "Mod+Shift+B".action = toggle-window-floating;
96 347
97 "Mod+Left".action = set-column-width "-10%"; 348 "Mod+Left".action = set-column-width "-10%";
98 "Mod+Down".action = set-window-height "-10%"; 349 "Mod+Down".action = set-window-height "-10%";
@@ -103,6 +354,10 @@ in {
103 action = spawn (lib.getExe niri) "msg" "action" "power-off-monitors"; 354 action = spawn (lib.getExe niri) "msg" "action" "power-off-monitors";
104 allow-when-locked = true; 355 allow-when-locked = true;
105 }; 356 };
357 "Mod+Shift+L" = {
358 action = spawn loginctl "lock-session";
359 };
360 "Mod+Shift+E".action = quit;
106 361
107 "XF86MonBrightnessUp" = { 362 "XF86MonBrightnessUp" = {
108 action = spawn lightctl "-d" "-e4" "-n1" "up"; 363 action = spawn lightctl "-d" "-e4" "-n1" "up";
@@ -133,6 +388,12 @@ in {
133 "Mod+Shift+Semicolon".action = spawn dunstctl "close-all"; 388 "Mod+Shift+Semicolon".action = spawn dunstctl "close-all";
134 "Mod+Period".action = spawn dunstctl "context"; 389 "Mod+Period".action = spawn dunstctl "context";
135 "Mod+Comma".action = spawn dunstctl "history-pop"; 390 "Mod+Comma".action = spawn dunstctl "history-pop";
391
392 "Mod+Control+A".action = focus-or-spawn-action-app_id "com.saivert.pwvucontrol" "pwctl" "pwvucontrol";
393 "Mod+Control+P".action = focus-or-spawn-action-app_id "org.keepassxc.KeePassXC" "kpxc" "keepassxc";
394 "Mod+Control+B".action = focus-or-spawn-action-app_id ".blueman-manager-wrapped" "bmgr" "blueman-manager";
395 "Mod+Control+Return".action = focus-or-spawn-action-app_id "kitty-scratch" "term" "kitty" "--app-id" "kitty-scratch";
396 "Mod+Control+E".action = focus-or-spawn-action "select(.app_id == \"emacs\" and .title == \"scratch\")" "edit" "emacsclient" "-c" "--frame-parameters=(quote (name . \"scratch\"))";
136 }; 397 };
137 }; 398 };
138 }; 399 };
diff --git a/accounts/gkleen@sif/niri/waybar.nix b/accounts/gkleen@sif/niri/waybar.nix
index 1a25b581..2d00c6d8 100644
--- a/accounts/gkleen@sif/niri/waybar.nix
+++ b/accounts/gkleen@sif/niri/waybar.nix
@@ -80,9 +80,7 @@
80 exec = "${lib.getExe pkgs.worktime} today"; 80 exec = "${lib.getExe pkgs.worktime} today";
81 tooltip = false; 81 tooltip = false;
82 }; 82 };
83 "niri/workspaces" = { 83 "niri/workspaces" = {};
84 all-outputs = true;
85 };
86 "niri/window" = { 84 "niri/window" = {
87 separate-outputs = true; 85 separate-outputs = true;
88 icon = true; 86 icon = true;
@@ -166,9 +164,7 @@
166 modules-center = [ "niri/window" ]; 164 modules-center = [ "niri/window" ];
167 modules-right = [ "clock" ]; 165 modules-right = [ "clock" ];
168 166
169 "niri/workspaces" = { 167 "niri/workspaces" = {};
170 all-outputs = false;
171 };
172 "niri/window" = { 168 "niri/window" = {
173 separate-outputs = true; 169 separate-outputs = true;
174 icon = true; 170 icon = true;
@@ -215,13 +211,11 @@
215 } 211 }
216 212
217 #workspaces button { 213 #workspaces button {
218 color: @grey;
219 }
220 #workspaces button.hosting-monitor {
221 color: @white; 214 color: @white;
215 padding: 2px 5px;
222 } 216 }
223 #workspaces button.visible { 217 #workspaces button.empty {
224 color: @blue; 218 color: @grey;
225 } 219 }
226 #workspaces button.active { 220 #workspaces button.active {
227 color: @green; 221 color: @green;
diff --git a/accounts/gkleen@sif/systemd.nix b/accounts/gkleen@sif/systemd.nix
index c8400c28..119d8cc3 100644
--- a/accounts/gkleen@sif/systemd.nix
+++ b/accounts/gkleen@sif/systemd.nix
@@ -204,20 +204,6 @@ in {
204 WatchdogSec = "2s"; 204 WatchdogSec = "2s";
205 }; 205 };
206 }; 206 };
207 polkit-gnome-authentication-agent-1 = {
208 Install = {
209 WantedBy = ["graphical-session.target"];
210 };
211 Unit = {
212 PartOf = ["graphical-session.target"];
213 Requires = ["graphical-session-pre.target"];
214 After = ["graphical-session-pre.target"];
215 };
216 Service = {
217 ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1";
218 Restart = "on-failure";
219 };
220 };
221 gtklock = { 207 gtklock = {
222 Unit = { 208 Unit = {
223 Requisite = ["graphical-session.target"]; 209 Requisite = ["graphical-session.target"];