fix(swayidle): move startup to systemd #42

deleted
opened by a.starrysky.fyi targeting main from private/minion/push-ovoxqswvtxsu

Previously we were starting swayidle on niri. Unfortunately, this caused a race condition where niri idle inhibitions were not respected. As niri gets idle inhibitions from, say, browsers when playing video, this meant we had to do nasty hacks such as manually systemd-inhibiting via a shell

By moving startup to systemd, we can start swayidle later - and in much the same way as starting our SSH agent later avoids its race conditions, starting swayidle later fixes this issue...

Changed files
+277 -262
packetmix
homes
+1 -1
packetmix/homes/coded/niri.nix
··· 5 { 6 ingredient.niri.enable = true; 7 8 - ingredient.niri.niri.timers = { 9 lock = 900; 10 sleep = 1800; 11 };
··· 5 { 6 ingredient.niri.enable = true; 7 8 + ingredient.niri.swayidle.timers = { 9 lock = 900; 10 sleep = 1800; 11 };
+234 -261
packetmix/homes/niri/niri.nix
··· 33 ''; 34 }; 35 }; 36 - timers = { 37 - lock = lib.mkOption { 38 - type = lib.types.int; 39 - description = "How long while idling before locking the device (in seconds)"; 40 - default = 300; 41 - }; 42 - sleep = lib.mkOption { 43 - type = lib.types.addCheck lib.types.int (x: x >= config.ingredient.niri.niri.timers.lock); 44 - description = "How long while idling before sleeping the device (in seconds)"; 45 - default = 450; 46 - }; 47 }; 48 overviewBackground = lib.mkOption { 49 type = lib.types.path; ··· 62 }; 63 64 config = { 65 - programs.niri = 66 - let 67 - lock = ''${config.programs.niri.package}/bin/niri msg action do-screen-transition && ${pkgs.swaylock}/bin/swaylock -i ${config.ingredient.niri.niri.lockscreen} -s fill -f''; 68 - in 69 - { 70 - enable = true; 71 - 72 - package = pkgs.niri; 73 - 74 - settings = { 75 - xwayland-satellite = { 76 - enable = true; 77 - path = "${pkgs.xwayland-satellite}/bin/xwayland-satellite"; 78 - }; 79 - environment.NIXOS_OZONE_WL = "1"; 80 - 81 - input.keyboard = { 82 - track-layout = "window"; 83 - repeat-delay = 200; 84 - repeat-rate = 25; 85 - 86 - xkb = lib.mkIf (config.home.keyboard != null) { 87 - layout = if config.home.keyboard.layout == null then "" else config.home.keyboard.layout; 88 - model = if config.home.keyboard.model == null then "" else config.home.keyboard.model; 89 - options = builtins.concatStringsSep "," config.home.keyboard.options; 90 - variant = if config.home.keyboard.variant == null then "" else config.home.keyboard.variant; 91 - }; 92 - }; 93 94 - input.touchpad.natural-scroll = true; 95 - input.touchpad.click-method = "clickfinger"; 96 97 - input.warp-mouse-to-focus.enable = true; 98 - input.focus-follows-mouse = { 99 - enable = true; 100 - max-scroll-amount = "0%"; 101 }; 102 103 - input.power-key-handling.enable = false; 104 - 105 - binds = 106 - let 107 - mod = "Super"; 108 - mod1 = "Alt"; 109 - 110 - generateWorkspaceBindings = workspaceNumber: { 111 - "${mod}+${builtins.toString (lib.mod workspaceNumber 10)}".action.focus-workspace = [ 112 - workspaceNumber 113 - ]; 114 - "${mod}+Shift+${builtins.toString (lib.mod workspaceNumber 10)}".action.move-column-to-workspace = [ 115 - workspaceNumber 116 - ]; 117 - }; 118 - joinAttrsetList = listOfAttrsets: lib.fold (a: b: a // b) { } listOfAttrsets; 119 - in 120 - { 121 - # General Keybinds 122 - "${mod}+Q".action.close-window = [ ]; 123 - "${mod}+Shift+Q".action.quit = [ ]; 124 - "${mod}+Return".action.spawn = "${pkgs.ghostty}/bin/ghostty"; 125 - "${mod}+L".action.spawn = [ 126 - "sh" 127 - "-c" 128 - lock 129 - ]; 130 - "${mod}+P".action.power-off-monitors = [ ]; 131 - 132 - "${mod}+R".action.screenshot = [ ]; 133 - "${mod}+Ctrl+R".action.screenshot-screen = [ ]; 134 - "${mod}+Shift+R".action.screenshot-window = [ ]; 135 - "Print".action.screenshot = [ ]; 136 - "Ctrl+Print".action.screenshot-screen = [ ]; 137 - "Shift+Print".action.screenshot-window = [ ]; 138 139 - "${mod}+Space".action.switch-layout = [ "next" ]; 140 - "${mod}+Shift+Space".action.switch-layout = [ "prev" ]; 141 142 - "${mod}+Shift+Slash".action.show-hotkey-overlay = [ ]; 143 144 - "${mod}+V".action.set-dynamic-cast-monitor = [ ]; 145 - "${mod}+W".action.set-dynamic-cast-window = [ ]; 146 - "${mod}+Shift+V".action.clear-dynamic-cast-target = [ ]; 147 - "${mod}+Shift+W".action.clear-dynamic-cast-target = [ ]; 148 149 - "${mod}+N".action.spawn = [ 150 - "sh" 151 - "-c" 152 - "${pkgs.systemd}/bin/systemctl --user start swaync && ${pkgs.swaynotificationcenter}/bin/swaync-client -t" 153 ]; 154 - # We need to ensure swaync is started, since as it isn't usually until we get a notification 155 - } 156 - // 157 - # Workspace Keybinds 158 - (lib.pipe (lib.range 1 10) [ 159 - (map generateWorkspaceBindings) 160 - joinAttrsetList 161 - ]) 162 - // 163 - # Window Manipulation Bindings 164 - ({ 165 - "${mod}+BracketLeft".action.consume-or-expel-window-left = [ ]; 166 - "${mod}+BracketRight".action.consume-or-expel-window-right = [ ]; 167 - "${mod}+Shift+BracketLeft".action.consume-window-into-column = [ ]; 168 - "${mod}+Shift+BracketRight".action.expel-window-from-column = [ ]; 169 - "${mod}+Slash".action.switch-preset-column-width = [ ]; 170 - "${mod}+${mod1}+F".action.fullscreen-window = [ ]; 171 - "${mod}+${mod1}+Shift+F".action.toggle-windowed-fullscreen = [ ]; 172 - 173 - # Focus 174 - "${mod}+Up".action.focus-window-or-workspace-up = [ ]; 175 - "${mod}+Down".action.focus-window-or-workspace-down = [ ]; 176 - 177 - # Non Jump Movement 178 - "${mod}+Shift+Up".action.move-window-up-or-to-workspace-up = [ ]; 179 - "${mod}+Shift+Down".action.move-window-down-or-to-workspace-down = [ ]; 180 - "${mod}+Shift+Left".action.consume-or-expel-window-left = [ ]; 181 - "${mod}+Shift+Right".action.consume-or-expel-window-right = [ ]; 182 - 183 - # To Monitor 184 - "${mod}+Shift+Ctrl+Up".action.move-window-to-monitor-up = [ ]; 185 - "${mod}+Shift+Ctrl+Down".action.move-window-to-monitor-down = [ ]; 186 - "${mod}+Shift+Ctrl+Left".action.move-window-to-monitor-left = [ ]; 187 - "${mod}+Shift+Ctrl+Right".action.move-window-to-monitor-right = [ ]; 188 - 189 - # To Workspace 190 - "${mod}+Ctrl+Up".action.move-window-to-workspace-up = [ ]; 191 - "${mod}+Ctrl+Down".action.move-window-to-workspace-down = [ ]; 192 - 193 - # Sizing 194 - "${mod}+Equal".action.set-window-height = [ "+5%" ]; 195 - "${mod}+Minus".action.set-window-height = [ "-5%" ]; 196 - }) 197 - // 198 - # Column Manipulation Bindings 199 - ({ 200 - # Focus 201 - "${mod}+Left".action.focus-column-left = [ ]; 202 - "${mod}+Right".action.focus-column-right = [ ]; 203 - "${mod}+${mod1}+C".action.center-column = [ ]; 204 - "${mod}+F".action.maximize-column = [ ]; 205 - 206 - # Non Monitor Movement 207 - "${mod}+${mod1}+Shift+Up".action.move-column-to-workspace-up = [ ]; 208 - "${mod}+${mod1}+Shift+Down".action.move-column-to-workspace-down = [ ]; 209 - "${mod}+${mod1}+Shift+Left".action.move-column-left = [ ]; 210 - "${mod}+${mod1}+Shift+Right".action.move-column-right = [ ]; 211 - 212 - # To Monitor 213 - "${mod}+${mod1}+Shift+Ctrl+Up".action.move-column-to-monitor-up = [ ]; 214 - "${mod}+${mod1}+Shift+Ctrl+Down".action.move-column-to-monitor-down = [ ]; 215 - "${mod}+${mod1}+Shift+Ctrl+Left".action.move-column-to-monitor-left = [ ]; 216 - "${mod}+${mod1}+Shift+Ctrl+Right".action.move-column-to-monitor-right = [ ]; 217 - 218 - # Sizing 219 - "${mod}+${mod1}+Equal".action.set-column-width = [ "+5%" ]; 220 - "${mod}+${mod1}+Minus".action.set-column-width = [ "-5%" ]; 221 - }) 222 - // 223 - # Workspace Manipulation Bindings 224 - ({ 225 - # Focus 226 - "${mod}+Page_Up".action.focus-workspace-up = [ ]; 227 - "${mod}+Page_Down".action.focus-workspace-down = [ ]; 228 - 229 - # Within Itself 230 - "${mod}+Shift+Page_Up".action.move-workspace-up = [ ]; 231 - "${mod}+Shift+Page_Down".action.move-workspace-down = [ ]; 232 - 233 - # To Monitor 234 - "${mod}+Shift+Ctrl+Page_Up".action.move-workspace-to-monitor-up = [ ]; 235 - "${mod}+Shift+Ctrl+Page_Down".action.move-workspace-to-monitor-down = [ ]; 236 - "${mod}+Shift+Ctrl+Home".action.move-workspace-to-monitor-left = [ ]; 237 - "${mod}+Shift+Ctrl+End".action.move-workspace-to-monitor-right = [ ]; 238 - 239 - "${mod}+Space" = { 240 - action.toggle-overview = [ ]; 241 - repeat = false; 242 - }; 243 - }) 244 - // { 245 - # Audio 246 - "XF86AudioRaiseVolume" = { 247 - allow-when-locked = true; 248 - action.spawn = [ 249 - "${pkgs.wireplumber}/bin/wpctl" 250 - "set-volume" 251 - "@DEFAULT_AUDIO_SINK@" 252 - "0.05+" 253 - ]; 254 - }; 255 - "XF86AudioLowerVolume" = { 256 - allow-when-locked = true; 257 - action.spawn = [ 258 - "${pkgs.wireplumber}/bin/wpctl" 259 - "set-volume" 260 - "@DEFAULT_AUDIO_SINK@" 261 - "0.05-" 262 - ]; 263 - }; 264 - "XF86AudioMute" = { 265 - allow-when-locked = true; 266 - action.spawn = [ 267 - "${pkgs.wireplumber}/bin/wpctl" 268 - "set-mute" 269 - "@DEFAULT_AUDIO_SINK@" 270 - "toggle" 271 - ]; 272 - }; 273 - "XF86AudioMicMute" = { 274 - allow-when-locked = true; 275 - action.spawn = [ 276 - "${pkgs.wireplumber}/bin/wpctl" 277 - "set-mute" 278 - "@DEFAULT_AUDIO_SOURCE@" 279 - "toggle" 280 - ]; 281 }; 282 }; 283 284 - layout = { 285 - gaps = 16; 286 - 287 - center-focused-column = "on-overflow"; 288 289 - preset-column-widths = [ 290 - { proportion = 1. / 4.; } 291 - { proportion = 1. / 3.; } 292 - { proportion = 1. / 2.; } 293 - { proportion = 2. / 3.; } 294 - { proportion = 9. / 10.; } 295 - ]; # TODO: clicks to PR a docs update for niri-flake 296 - }; 297 298 - prefer-no-csd = true; # No "client-side-decorations" (i.e. client-side window open/close buttons) 299 - hotkey-overlay.skip-at-startup = true; 300 - screenshot-path = null; 301 - 302 - spawn-at-startup = [ 303 - { 304 - command = [ 305 - "${pkgs.swaybg}/bin/swaybg" 306 - "-i" 307 - "${config.ingredient.niri.niri.wallpaper}" 308 - "-m" 309 - "fill" 310 - ]; 311 - } 312 - { 313 - command = [ 314 - "${pkgs.swayidle}/bin/swayidle" 315 - "-w" 316 - "timeout" 317 - (toString config.ingredient.niri.niri.timers.lock) 318 - lock 319 - "timeout" 320 - (toString config.ingredient.niri.niri.timers.sleep) 321 - "niri msg action power-off-monitors" 322 - "resume" 323 - "niri msg action power-on-monitors" # Not sure if this is really needed - niri normally powers on monitors on a movement action anyway, but maybe this can affect resuming in different ways? 324 - "before-sleep" 325 - lock 326 - ]; 327 - } 328 - ]; 329 }; 330 }; 331 332 programs.bash.profileExtra = lib.mkBefore '' 333 if [ -z $WAYLAND_DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then
··· 33 ''; 34 }; 35 }; 36 + lockCommand = lib.mkOption { 37 + type = lib.types.str; 38 + description = "The command run when you lock your computer, or when it is locked automatically"; 39 + default = ''${config.programs.niri.package}/bin/niri msg action do-screen-transition && ${pkgs.swaylock}/bin/swaylock -i ${config.ingredient.niri.niri.lockscreen} -s fill -f''; 40 }; 41 overviewBackground = lib.mkOption { 42 type = lib.types.path; ··· 55 }; 56 57 config = { 58 + programs.niri = { 59 + enable = true; 60 61 + package = pkgs.niri; 62 63 + settings = { 64 + xwayland-satellite = { 65 + enable = true; 66 + path = "${pkgs.xwayland-satellite}/bin/xwayland-satellite"; 67 + }; 68 + environment.NIXOS_OZONE_WL = "1"; 69 + 70 + input.keyboard = { 71 + track-layout = "window"; 72 + repeat-delay = 200; 73 + repeat-rate = 25; 74 + 75 + xkb = lib.mkIf (config.home.keyboard != null) { 76 + layout = if config.home.keyboard.layout == null then "" else config.home.keyboard.layout; 77 + model = if config.home.keyboard.model == null then "" else config.home.keyboard.model; 78 + options = builtins.concatStringsSep "," config.home.keyboard.options; 79 + variant = if config.home.keyboard.variant == null then "" else config.home.keyboard.variant; 80 }; 81 + }; 82 83 + input.touchpad.natural-scroll = true; 84 + input.touchpad.click-method = "clickfinger"; 85 86 + input.warp-mouse-to-focus.enable = true; 87 + input.focus-follows-mouse = { 88 + enable = true; 89 + max-scroll-amount = "0%"; 90 + }; 91 92 + input.power-key-handling.enable = false; 93 94 + binds = 95 + let 96 + mod = "Super"; 97 + mod1 = "Alt"; 98 99 + generateWorkspaceBindings = workspaceNumber: { 100 + "${mod}+${builtins.toString (lib.mod workspaceNumber 10)}".action.focus-workspace = [ 101 + workspaceNumber 102 ]; 103 + "${mod}+Shift+${builtins.toString (lib.mod workspaceNumber 10)}".action.move-column-to-workspace = [ 104 + workspaceNumber 105 + ]; 106 + }; 107 + joinAttrsetList = listOfAttrsets: lib.fold (a: b: a // b) { } listOfAttrsets; 108 + in 109 + { 110 + # General Keybinds 111 + "${mod}+Q".action.close-window = [ ]; 112 + "${mod}+Shift+Q".action.quit = [ ]; 113 + "${mod}+Return".action.spawn = "${pkgs.ghostty}/bin/ghostty"; 114 + "${mod}+L".action.spawn = [ 115 + "sh" 116 + "-c" 117 + config.ingredient.niri.niri.lockCommand 118 + ]; 119 + "${mod}+P".action.power-off-monitors = [ ]; 120 + 121 + "${mod}+R".action.screenshot = [ ]; 122 + "${mod}+Ctrl+R".action.screenshot-screen = [ ]; 123 + "${mod}+Shift+R".action.screenshot-window = [ ]; 124 + "Print".action.screenshot = [ ]; 125 + "Ctrl+Print".action.screenshot-screen = [ ]; 126 + "Shift+Print".action.screenshot-window = [ ]; 127 + 128 + "${mod}+Space".action.switch-layout = [ "next" ]; 129 + "${mod}+Shift+Space".action.switch-layout = [ "prev" ]; 130 + 131 + "${mod}+Shift+Slash".action.show-hotkey-overlay = [ ]; 132 + 133 + "${mod}+V".action.set-dynamic-cast-monitor = [ ]; 134 + "${mod}+W".action.set-dynamic-cast-window = [ ]; 135 + "${mod}+Shift+V".action.clear-dynamic-cast-target = [ ]; 136 + "${mod}+Shift+W".action.clear-dynamic-cast-target = [ ]; 137 + 138 + "${mod}+N".action.spawn = [ 139 + "sh" 140 + "-c" 141 + "${pkgs.systemd}/bin/systemctl --user start swaync && ${pkgs.swaynotificationcenter}/bin/swaync-client -t" 142 + ]; 143 + # We need to ensure swaync is started, since as it isn't usually until we get a notification 144 + } 145 + // 146 + # Workspace Keybinds 147 + (lib.pipe (lib.range 1 10) [ 148 + (map generateWorkspaceBindings) 149 + joinAttrsetList 150 + ]) 151 + // 152 + # Window Manipulation Bindings 153 + ({ 154 + "${mod}+BracketLeft".action.consume-or-expel-window-left = [ ]; 155 + "${mod}+BracketRight".action.consume-or-expel-window-right = [ ]; 156 + "${mod}+Shift+BracketLeft".action.consume-window-into-column = [ ]; 157 + "${mod}+Shift+BracketRight".action.expel-window-from-column = [ ]; 158 + "${mod}+Slash".action.switch-preset-column-width = [ ]; 159 + "${mod}+${mod1}+F".action.fullscreen-window = [ ]; 160 + "${mod}+${mod1}+Shift+F".action.toggle-windowed-fullscreen = [ ]; 161 + 162 + # Focus 163 + "${mod}+Up".action.focus-window-or-workspace-up = [ ]; 164 + "${mod}+Down".action.focus-window-or-workspace-down = [ ]; 165 + 166 + # Non Jump Movement 167 + "${mod}+Shift+Up".action.move-window-up-or-to-workspace-up = [ ]; 168 + "${mod}+Shift+Down".action.move-window-down-or-to-workspace-down = [ ]; 169 + "${mod}+Shift+Left".action.consume-or-expel-window-left = [ ]; 170 + "${mod}+Shift+Right".action.consume-or-expel-window-right = [ ]; 171 + 172 + # To Monitor 173 + "${mod}+Shift+Ctrl+Up".action.move-window-to-monitor-up = [ ]; 174 + "${mod}+Shift+Ctrl+Down".action.move-window-to-monitor-down = [ ]; 175 + "${mod}+Shift+Ctrl+Left".action.move-window-to-monitor-left = [ ]; 176 + "${mod}+Shift+Ctrl+Right".action.move-window-to-monitor-right = [ ]; 177 + 178 + # To Workspace 179 + "${mod}+Ctrl+Up".action.move-window-to-workspace-up = [ ]; 180 + "${mod}+Ctrl+Down".action.move-window-to-workspace-down = [ ]; 181 + 182 + # Sizing 183 + "${mod}+Equal".action.set-window-height = [ "+5%" ]; 184 + "${mod}+Minus".action.set-window-height = [ "-5%" ]; 185 + }) 186 + // 187 + # Column Manipulation Bindings 188 + ({ 189 + # Focus 190 + "${mod}+Left".action.focus-column-left = [ ]; 191 + "${mod}+Right".action.focus-column-right = [ ]; 192 + "${mod}+${mod1}+C".action.center-column = [ ]; 193 + "${mod}+F".action.maximize-column = [ ]; 194 + 195 + # Non Monitor Movement 196 + "${mod}+${mod1}+Shift+Up".action.move-column-to-workspace-up = [ ]; 197 + "${mod}+${mod1}+Shift+Down".action.move-column-to-workspace-down = [ ]; 198 + "${mod}+${mod1}+Shift+Left".action.move-column-left = [ ]; 199 + "${mod}+${mod1}+Shift+Right".action.move-column-right = [ ]; 200 + 201 + # To Monitor 202 + "${mod}+${mod1}+Shift+Ctrl+Up".action.move-column-to-monitor-up = [ ]; 203 + "${mod}+${mod1}+Shift+Ctrl+Down".action.move-column-to-monitor-down = [ ]; 204 + "${mod}+${mod1}+Shift+Ctrl+Left".action.move-column-to-monitor-left = [ ]; 205 + "${mod}+${mod1}+Shift+Ctrl+Right".action.move-column-to-monitor-right = [ ]; 206 + 207 + # Sizing 208 + "${mod}+${mod1}+Equal".action.set-column-width = [ "+5%" ]; 209 + "${mod}+${mod1}+Minus".action.set-column-width = [ "-5%" ]; 210 + }) 211 + // 212 + # Workspace Manipulation Bindings 213 + ({ 214 + # Focus 215 + "${mod}+Page_Up".action.focus-workspace-up = [ ]; 216 + "${mod}+Page_Down".action.focus-workspace-down = [ ]; 217 + 218 + # Within Itself 219 + "${mod}+Shift+Page_Up".action.move-workspace-up = [ ]; 220 + "${mod}+Shift+Page_Down".action.move-workspace-down = [ ]; 221 + 222 + # To Monitor 223 + "${mod}+Shift+Ctrl+Page_Up".action.move-workspace-to-monitor-up = [ ]; 224 + "${mod}+Shift+Ctrl+Page_Down".action.move-workspace-to-monitor-down = [ ]; 225 + "${mod}+Shift+Ctrl+Home".action.move-workspace-to-monitor-left = [ ]; 226 + "${mod}+Shift+Ctrl+End".action.move-workspace-to-monitor-right = [ ]; 227 + 228 + "${mod}+Space" = { 229 + action.toggle-overview = [ ]; 230 + repeat = false; 231 }; 232 + }) 233 + // { 234 + # Audio 235 + "XF86AudioRaiseVolume" = { 236 + allow-when-locked = true; 237 + action.spawn = [ 238 + "${pkgs.wireplumber}/bin/wpctl" 239 + "set-volume" 240 + "@DEFAULT_AUDIO_SINK@" 241 + "0.05+" 242 + ]; 243 }; 244 + "XF86AudioLowerVolume" = { 245 + allow-when-locked = true; 246 + action.spawn = [ 247 + "${pkgs.wireplumber}/bin/wpctl" 248 + "set-volume" 249 + "@DEFAULT_AUDIO_SINK@" 250 + "0.05-" 251 + ]; 252 + }; 253 + "XF86AudioMute" = { 254 + allow-when-locked = true; 255 + action.spawn = [ 256 + "${pkgs.wireplumber}/bin/wpctl" 257 + "set-mute" 258 + "@DEFAULT_AUDIO_SINK@" 259 + "toggle" 260 + ]; 261 + }; 262 + "XF86AudioMicMute" = { 263 + allow-when-locked = true; 264 + action.spawn = [ 265 + "${pkgs.wireplumber}/bin/wpctl" 266 + "set-mute" 267 + "@DEFAULT_AUDIO_SOURCE@" 268 + "toggle" 269 + ]; 270 + }; 271 + }; 272 273 + layout = { 274 + gaps = 16; 275 276 + center-focused-column = "on-overflow"; 277 278 + preset-column-widths = [ 279 + { proportion = 1. / 4.; } 280 + { proportion = 1. / 3.; } 281 + { proportion = 1. / 2.; } 282 + { proportion = 2. / 3.; } 283 + { proportion = 9. / 10.; } 284 + ]; # TODO: clicks to PR a docs update for niri-flake 285 }; 286 + 287 + prefer-no-csd = true; # No "client-side-decorations" (i.e. client-side window open/close buttons) 288 + hotkey-overlay.skip-at-startup = true; 289 + screenshot-path = null; 290 + 291 + spawn-at-startup = [ 292 + { 293 + command = [ 294 + "${pkgs.swaybg}/bin/swaybg" 295 + "-i" 296 + "${config.ingredient.niri.niri.wallpaper}" 297 + "-m" 298 + "fill" 299 + ]; 300 + } 301 + ]; 302 }; 303 + }; 304 305 programs.bash.profileExtra = lib.mkBefore '' 306 if [ -z $WAYLAND_DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then
+42
packetmix/homes/niri/swayidle.nix
···
··· 1 + { 2 + pkgs, 3 + lib, 4 + config, 5 + ... 6 + }: 7 + { 8 + options.ingredient.niri.swayidle.timers = { 9 + lock = lib.mkOption { 10 + type = lib.types.int; 11 + description = "How long while idling before locking the device (in seconds)"; 12 + default = 300; 13 + }; 14 + sleep = lib.mkOption { 15 + type = lib.types.addCheck lib.types.int (x: x >= config.ingredient.niri.swayidle.timers.lock); 16 + description = "How long while idling before sleeping the device (in seconds)"; 17 + default = 450; 18 + }; 19 + }; 20 + 21 + config.systemd.user.services.swayidle = { 22 + Unit.After = [ "niri.service" ]; 23 + Install.WantedBy = [ "niri.service" ]; 24 + 25 + Service.ExecStart = builtins.concatStringsSep " " ( 26 + map (arg: "'${arg}'") [ 27 + "${pkgs.swayidle}/bin/swayidle" 28 + "-w" 29 + "timeout" 30 + (toString config.ingredient.niri.swayidle.timers.lock) 31 + config.ingredient.niri.niri.lockCommand 32 + "timeout" 33 + (toString config.ingredient.niri.swayidle.timers.sleep) 34 + "niri msg action power-off-monitors" 35 + "resume" 36 + "niri msg action power-on-monitors" # Not sure if this is really needed - niri normally powers on monitors on a movement action anyway, but maybe this can affect resuming in different ways? 37 + "before-sleep" 38 + config.ingredient.niri.niri.lockCommand 39 + ] 40 + ); # There's some nastiness here around "what happens if your commands contain single quotes"... at the moment, don't :) 41 + }; 42 + }