i3.nix (6948B)
1 # modules/features/desktop/i3.nix — i3, the lightweight option, in Rosé Pine. 2 # 3 # OFF unless the generic host sets `desktop = "i3";` (_settings.nix). A tiling 4 # window manager on X11: no compositor, no desktop environment, and it runs in 5 # any VM. In testing, a whole i3 VM with a terminal open sat at about 0.9 GB. The shared look 6 # (greeter, GTK colours, icons, cursor) is x11.nix. 7 # 8 # Super+Return terminal (kitty) Super+d launcher (rofi) 9 # Super+q close window Super+1..9 workspace 10 # Super+h/j/k/l focus Super+Shift+… move 11 # Super+f fullscreen Super+Shift+e log out 12 # Super+Shift+c reload config Super+Shift+r restart i3 13 { self, ... }: 14 { 15 flake.nixosModules.desktop-i3 = 16 { pkgs, lib, user, ... }: 17 let 18 rp = self.lib.rosePine; 19 mod = "Mod4"; 20 in 21 { 22 imports = [ self.nixosModules.desktop-x11 ]; 23 24 services.xserver.windowManager.i3.enable = true; 25 services.displayManager.defaultSession = "none+i3"; 26 fonts.packages = [ pkgs.font-awesome ]; # the bar's icons (i3status-rust awesome6) 27 28 home-manager.users.${user} = hm: { 29 xsession.windowManager.i3 = { 30 enable = true; 31 config = { 32 modifier = mod; 33 # home-manager sorts the bindings, so without this i3 starts on the first 34 # one it reads — Super+0, workspace 10. 35 defaultWorkspace = "workspace number 1"; 36 terminal = "kitty"; 37 menu = "rofi -show drun"; 38 fonts = { names = [ "JetBrainsMono Nerd Font" ]; size = 10.0; }; 39 gaps = { inner = 6; outer = 2; }; 40 window = { border = 2; titlebar = false; }; 41 floating.border = 2; 42 43 colors = { 44 background = rp.base; 45 focused = { border = rp.iris; background = rp.overlay; text = rp.text; indicator = rp.rose; childBorder = rp.iris; }; 46 focusedInactive = { border = rp.overlay; background = rp.base; text = rp.subtle; indicator = rp.overlay; childBorder = rp.overlay; }; 47 unfocused = { border = rp.overlay; background = rp.base; text = rp.muted; indicator = rp.overlay; childBorder = rp.overlay; }; 48 urgent = { border = rp.love; background = rp.love; text = rp.base; indicator = rp.love; childBorder = rp.love; }; 49 }; 50 51 keybindings = lib.mkOptionDefault { 52 "${mod}+q" = "kill"; 53 "${mod}+h" = "focus left"; 54 "${mod}+j" = "focus down"; 55 "${mod}+k" = "focus up"; 56 "${mod}+l" = "focus right"; 57 "${mod}+Shift+h" = "move left"; 58 "${mod}+Shift+j" = "move down"; 59 "${mod}+Shift+k" = "move up"; 60 "${mod}+Shift+l" = "move right"; 61 }; 62 63 startup = [ 64 { command = "xsetroot -solid '${rp.base}'"; notification = false; } 65 ]; 66 67 bars = [ 68 { 69 position = "top"; 70 statusCommand = "i3status-rs ~/.config/i3status-rust/config-top.toml"; 71 fonts = { names = [ "JetBrainsMono Nerd Font" ]; size = 10.0; }; 72 colors = { 73 background = rp.base; 74 statusline = rp.text; 75 separator = rp.muted; 76 focusedWorkspace = { border = rp.iris; background = rp.iris; text = rp.base; }; 77 activeWorkspace = { border = rp.overlay; background = rp.overlay; text = rp.text; }; 78 inactiveWorkspace = { border = rp.base; background = rp.base; text = rp.subtle; }; 79 urgentWorkspace = { border = rp.love; background = rp.love; text = rp.base; }; 80 }; 81 } 82 ]; 83 }; 84 }; 85 86 programs.i3status-rust = { 87 enable = true; 88 bars.top = { 89 theme = "native"; 90 icons = "awesome6"; 91 settings.theme.overrides = { 92 idle_bg = rp.base; 93 idle_fg = rp.text; 94 info_bg = rp.base; 95 info_fg = rp.foam; 96 good_bg = rp.base; 97 good_fg = rp.foam; 98 warning_bg = rp.base; 99 warning_fg = rp.gold; 100 critical_bg = rp.base; 101 critical_fg = rp.love; 102 separator = " "; 103 separator_bg = rp.base; 104 separator_fg = rp.base; 105 }; 106 blocks = [ 107 # the VPN tunnel, so you can see at a glance that you are on it 108 { block = "net"; device = "^tun"; format = " $icon tun $ip "; missing_format = ""; } 109 { block = "cpu"; format = " $icon $utilization "; } 110 { block = "memory"; format = " $icon $mem_used_percents "; } 111 { block = "disk_space"; path = "/"; format = " $icon $available "; } 112 { block = "sound"; } 113 { block = "time"; format = " $timestamp.datetime(f:'%a %d %b %H:%M') "; interval = 30; } 114 ]; 115 }; 116 }; 117 118 programs.rofi = { 119 enable = true; 120 terminal = "kitty"; 121 font = "JetBrainsMono Nerd Font 11"; 122 theme = 123 let inherit (hm.config.lib.formats.rasi) mkLiteral; in 124 { 125 "*" = { 126 background-color = mkLiteral rp.base; 127 text-color = mkLiteral rp.text; 128 border-color = mkLiteral rp.iris; 129 }; 130 window = { border = mkLiteral "2px"; padding = mkLiteral "12px"; width = mkLiteral "40%"; }; 131 inputbar = { padding = mkLiteral "6px"; children = map mkLiteral [ "prompt" "entry" ]; }; 132 prompt = { text-color = mkLiteral rp.iris; padding = mkLiteral "0 8px 0 0"; }; 133 listview = { lines = 10; padding = mkLiteral "6px 0 0 0"; }; 134 element = { padding = mkLiteral "4px 6px"; }; 135 "element selected" = { background-color = mkLiteral rp.overlay; text-color = mkLiteral rp.rose; }; 136 element-text = { background-color = mkLiteral "inherit"; text-color = mkLiteral "inherit"; }; 137 element-icon = { background-color = mkLiteral "inherit"; size = mkLiteral "1.2em"; }; 138 }; 139 }; 140 141 services.dunst = { 142 enable = true; 143 settings = { 144 global = { 145 font = "JetBrainsMono Nerd Font 10"; 146 frame_color = rp.iris; 147 frame_width = 2; 148 offset = "12x40"; 149 }; 150 urgency_low = { background = rp.base; foreground = rp.subtle; }; 151 urgency_normal = { background = rp.base; foreground = rp.text; }; 152 urgency_critical = { background = rp.base; foreground = rp.love; frame_color = rp.love; }; 153 }; 154 }; 155 156 home.packages = with pkgs; [ xorg.xsetroot pavucontrol ]; 157 fonts.fontconfig.enable = true; 158 }; 159 }; 160 }