about summary refs log tree commit diff
path: root/modules/i3/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/i3/default.nix')
-rw-r--r--modules/i3/default.nix129
1 files changed, 129 insertions, 0 deletions
diff --git a/modules/i3/default.nix b/modules/i3/default.nix
new file mode 100644
index 00000000..bca88cca
--- /dev/null
+++ b/modules/i3/default.nix
@@ -0,0 +1,129 @@
+{ pkgs, lib, config, ... }:
+
+with lib;
+
+let
+  inherit (config.services.xserver) xrandrHeads;
+
+  # The symbols if you press shift and a number key.
+  wsNumberSymbols = [
+    "exclam" "at" "numbersign" "dollar" "percent"
+    "asciicircum" "ampersand" "asterisk" "parenleft" "parenright"
+  ];
+
+  wsCount = length wsNumberSymbols;
+
+  headCount = length xrandrHeads;
+  wsPerHead = wsCount / headCount;
+  excessWs = wsCount - (headCount * wsPerHead);
+  headModifier = if config.vuizvui.i3.reverseHeads then reverseList else id;
+  getHeadAt = elemAt (headModifier xrandrHeads);
+
+  mkDefaultWorkspace = number: numberSymbol: {
+    name = toString number;
+    value = mkDefault {
+      label = null;
+      labelPrefix = "${toString number}: ";
+      keys.switchTo = "$mod+${if number == 10 then "0" else toString number}";
+      keys.moveTo = "$mod+Shift+${numberSymbol}";
+      head = if headCount == 0 then null
+             else getHeadAt ((number - (excessWs + 1)) / wsPerHead);
+    };
+  };
+
+  wsCfgList = mapAttrsToList (_: getAttr "config") config.vuizvui.i3.workspaces;
+  wsConfig = concatStrings wsCfgList;
+  defaultWorkspaces = listToAttrs (imap mkDefaultWorkspace wsNumberSymbols);
+
+  conky = import ./conky.nix {
+    inherit pkgs;
+    timeout = config.vuizvui.i3.networkTimeout;
+  };
+
+  mkBar = output: statusCmd: singleton ''
+    bar {
+      ${optionalString (output != null) "output ${output}"}
+      ${optionalString (statusCmd != null) "status_command ${statusCmd}"}
+      colors {
+        focused_workspace  #5c5cff #e5e5e5
+        active_workspace   #ffffff #0000ee
+        inactive_workspace #00cdcd #0000ee
+        urgent_workspace   #ffff00 #cd0000
+      }
+    }
+  '';
+
+  barConfig = let
+    barHeads = headModifier xrandrHeads;
+    bars = if headCount == 0 then mkBar null conky.single
+      else if headCount == 1 then mkBar (head barHeads) conky.single
+      else let inner = take (length barHeads - 2) (tail barHeads);
+           in mkBar (head barHeads) conky.left
+           ++ map (flip mkBar null) inner
+           ++ mkBar (last barHeads) conky.right;
+  in concatStrings (headModifier bars);
+
+in
+{
+  options.vuizvui.i3 = {
+    enable = mkEnableOption "i3";
+
+    workspaces = mkOption {
+      type = types.attrsOf (types.submodule (import ./workspace.nix));
+      default = listToAttrs (imap mkDefaultWorkspace wsNumberSymbols);
+      description = ''
+        Workspace to monitor assignment.
+
+        Workspaces are by default assigned starting from the leftmost monitor
+        being workspace 1 and the rightmost monitor being workspace 10. The
+        workspaces are divided by the number of available heads, so if you have
+        a dual head system, you'll end up having workspace 1 to 5 on the left
+        monitor and 6 to 10 on the right.
+      '';
+    };
+
+    reverseHeads = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Reverse the order of the heads, so if enabled and you have two heads,
+        you'll end up having workspaces 1 to 5 on the right head and 6 to 10 on
+        the left head.
+      '';
+    };
+
+    networkTimeout = mkOption {
+      type = types.int;
+      default = 300;
+      description = ''
+        Maximum number of seconds to wait for network device detection.
+      '';
+    };
+  };
+
+  config.vuizvui.i3.workspaces = defaultWorkspaces;
+
+  config.services.xserver.windowManager = mkIf config.vuizvui.i3.enable {
+    default = "i3";
+
+    i3.enable = true;
+    i3.configFile = pkgs.substituteAll {
+      name = "i3.conf";
+      src = ./i3.conf;
+
+      inherit (pkgs) dmenu xterm pvolctrl;
+      inherit (pkgs.xorg) xsetroot;
+      inherit wsConfig barConfig;
+
+      lockall = pkgs.writeScript "lockvt.sh" ''
+        #!${pkgs.stdenv.shell}
+        "${pkgs.socat}/bin/socat" - UNIX-CONNECT:/run/console-lock.sock \
+          < /dev/null
+      '';
+
+      postInstall = ''
+        ${pkgs.i3}/bin/i3 -c "$target" -C
+      '';
+    };
+  };
+}