diff --git a/modules/services/window-managers/bspwm/default.nix b/modules/services/window-managers/bspwm/default.nix
index b14ffccd9..f20c01221 100644
--- a/modules/services/window-managers/bspwm/default.nix
+++ b/modules/services/window-managers/bspwm/default.nix
@@ -10,7 +10,19 @@ let
builtins.replaceStrings upperChars (map (c: "_${c}") lowerChars);
formatMonitor = monitor: desktops:
- "bspc monitor ${escapeShellArg monitor} -d ${escapeShellArgs desktops}";
+ let
+ resetDesktops =
+ "bspc monitor ${escapeShellArg monitor} -d ${escapeShellArgs desktops}";
+ defaultDesktopName =
+ "Desktop"; # https://github.com/baskerville/bspwm/blob/master/src/desktop.h
+ in if cfg.alwaysResetDesktops then
+ resetDesktops
+ else ''
+ if [[ $(bspc query --desktops --names --monitor ${
+ escapeShellArg monitor
+ }) == ${defaultDesktopName} ]]; then
+ ${resetDesktops}
+ fi'';
formatValue = v:
if isList v then
diff --git a/modules/services/window-managers/bspwm/options.nix b/modules/services/window-managers/bspwm/options.nix
index 60a06c5a0..57a1d874a 100644
--- a/modules/services/window-managers/bspwm/options.nix
+++ b/modules/services/window-managers/bspwm/options.nix
@@ -185,6 +185,19 @@ in {
example = { "HDMI-0" = [ "web" "terminal" "III" "IV" ]; };
};
+ alwaysResetDesktops = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ If set to true, desktops configured in will be reset
+ every time the config is run.
+
+ If set to false, desktops will only be configured the first time the config is run.
+ This is useful if you want to dynamically add desktops and you don't want them to be destroyed if you
+ re-run bspwmrc.
+ '';
+ };
+
rules = mkOption {
type = types.attrsOf rule;
default = { };
diff --git a/tests/modules/services/window-managers/bspwm/bspwmrc b/tests/modules/services/window-managers/bspwm/bspwmrc
index 7ebb64aca..ba0da830a 100755
--- a/tests/modules/services/window-managers/bspwm/bspwmrc
+++ b/tests/modules/services/window-managers/bspwm/bspwmrc
@@ -1,4 +1,6 @@
-bspc monitor 'focused' -d 'desktop 1' 'd'\''esk top'
+if [[ $(bspc query --desktops --names --monitor 'focused') == Desktop ]]; then
+ bspc monitor 'focused' -d 'desktop 1' 'd'\''esk top'
+fi
bspc config 'border_width' '2'
bspc config 'external_rules_command' '/path/to/external rules command'
diff --git a/tests/modules/services/window-managers/bspwm/configuration.nix b/tests/modules/services/window-managers/bspwm/configuration.nix
index 8018a3ac1..e4aec0f6c 100644
--- a/tests/modules/services/window-managers/bspwm/configuration.nix
+++ b/tests/modules/services/window-managers/bspwm/configuration.nix
@@ -8,6 +8,7 @@ with lib;
enable = true;
monitors.focused =
[ "desktop 1" "d'esk top" ]; # pathological desktop names
+ alwaysResetDesktops = false;
settings = {
border_width = 2;
split_ratio = 0.52;