335 lines
13 KiB
Nix
335 lines
13 KiB
Nix
{ lib, pkgs, config, ...}: let
|
|
inherit (lib) mkIf mkEnableOption mkOption types optionals optionalAttrs;
|
|
cfg = config.chuj.stuff.i3;
|
|
user = config.chuj.system.user;
|
|
in {
|
|
options.chuj.stuff.i3 = {
|
|
enable = mkEnableOption "i3";
|
|
workspaceOutput = mkOption {
|
|
type = types.attrsOf types.str;
|
|
default = {};
|
|
};
|
|
communicators = mkOption {
|
|
type = types.submodule {
|
|
options = {
|
|
autostart = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
workspace = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
};
|
|
};
|
|
};
|
|
default = {};
|
|
};
|
|
battery = mkEnableOption "battery";
|
|
mediaKeys = mkOption {
|
|
type = types.submodule {
|
|
options = let
|
|
mkKeyOpt = default: mkOption { inherit default; type = types.str; };
|
|
in {
|
|
musicMenu = mkKeyOpt "F5";
|
|
musicPlay = mkKeyOpt "F7";
|
|
musicPrev = mkKeyOpt "F6";
|
|
musicNext = mkKeyOpt "F8";
|
|
audioMute = mkKeyOpt "F9";
|
|
audioDown = mkKeyOpt "F10";
|
|
audioUp = mkKeyOpt "F11";
|
|
};
|
|
};
|
|
default = {};
|
|
};
|
|
};
|
|
|
|
config = let
|
|
hmCfg = config.home-manager.users.${user};
|
|
|
|
exec = what: "exec --no-startup-id ${what}";
|
|
|
|
i3-msg = lib.getExe' hmCfg.xsession.windowManager.i3.package "i3-msg";
|
|
terminal = if (config.chuj.stuff.alacritty.enable)
|
|
then (lib.getExe hmCfg.programs.alacritty.package)
|
|
else (lib.getExe' hmCfg.xsession.windowManager.i3.package "i3-sensible-terminal");
|
|
firefox = lib.getExe hmCfg.programs.firefox.package;
|
|
schildichat = lib.getExe pkgs.schildichat-desktop;
|
|
flameshot = lib.getExe hmCfg.services.flameshot.package;
|
|
dunst = lib.getExe' hmCfg.services.dunst.package "dunst";
|
|
dunstify = lib.getExe' hmCfg.services.dunst.package "dunstify";
|
|
dmenu_run = lib.getExe' pkgs.dmenu "dmenu_run";
|
|
dmenu = lib.getExe pkgs.dmenu;
|
|
yad = lib.getExe pkgs.yad;
|
|
mpc = lib.getExe pkgs.mpc-cli;
|
|
mpdstatus = lib.getExe config.chuj.stuff.mpd.mpdstatusPackage;
|
|
pamixer = lib.getExe pkgs.pamixer;
|
|
xdotool = lib.getExe pkgs.xdotool;
|
|
xkill = lib.getExe pkgs.xorg.xkill;
|
|
killall = lib.getExe pkgs.killall;
|
|
sync = lib.getExe' pkgs.coreutils "sync";
|
|
tail = lib.getExe' pkgs.coreutils "tail";
|
|
find = lib.getExe' pkgs.findutils "find";
|
|
sed = lib.getExe pkgs.gnused;
|
|
|
|
i3custom-window-actions = lib.getExe (pkgs.writeShellScriptBin "i3custom-window-actions" ''
|
|
${yad} --splash --mouse \
|
|
--title="i3 window actions" \
|
|
--gtkrc="${../../files/i3gtk.css}" \
|
|
--text="i3 window actions" \
|
|
--button float:0 --button kill:1
|
|
|
|
case $? in
|
|
0) ${i3-msg} "floating toggle";;
|
|
1) ${i3-msg} "kill";;
|
|
-1) ;;
|
|
esac
|
|
'');
|
|
|
|
musicsel = lib.getExe (pkgs.writeShellScriptBin "musicsel" ''
|
|
cd ~/Music
|
|
path=$(${find} . -maxdepth 1 -type d | ${tail} -n +2 | ${sed} 's|^./||g' | ${dmenu})
|
|
${dunstify} "playing from \"$path\""
|
|
${mpc} update
|
|
${mpc} rescan
|
|
${mpc} add "$path"
|
|
${mpc} random on
|
|
${mpc} repeat on
|
|
${mpc} play
|
|
'');
|
|
|
|
i3custom-center-mouse-on-focus = lib.getExe (pkgs.writeShellScriptBin "i3custom-center-mouse-on-focus" ''
|
|
eval $(${xdotool} getwindowfocus getwindowgeometry --shell)
|
|
MX=$(($X + $WIDTH / 2))
|
|
MY=$(($Y + $HEIGHT / 2))
|
|
${xdotool} mousemove $MX $MY
|
|
'');
|
|
in mkIf cfg.enable {
|
|
services.xserver.windowManager.i3.enable = true;
|
|
home-manager.users.${user} = {
|
|
xsession.windowManager.i3 = {
|
|
enable = true;
|
|
config = rec {
|
|
assigns = mkIf (cfg.communicators.workspace != "") {
|
|
${cfg.communicators.workspace} = [
|
|
{ class = "discord"; }
|
|
{ class = "SchildiChat"; }
|
|
{ class = "element"; }
|
|
];
|
|
};
|
|
|
|
window = {
|
|
border = 1;
|
|
titlebar = true;
|
|
};
|
|
|
|
floating = {
|
|
border = 1;
|
|
titlebar = true;
|
|
criteria = [
|
|
{ class = "zenity"; }
|
|
{ class = "fceux"; }
|
|
{ title = "Friends List"; } # steam
|
|
];
|
|
};
|
|
|
|
gaps = {
|
|
inner = 0;
|
|
outer = 0;
|
|
};
|
|
|
|
fonts = {
|
|
names = [ "monospace" ];
|
|
size = 10.0;
|
|
};
|
|
|
|
defaultWorkspace = "workspace number 1";
|
|
|
|
# transforms
|
|
# { "<workspace>" = "<output>"; }
|
|
# into
|
|
# [{ workspace = "<workspace>"; output = "<output>"; }]
|
|
workspaceOutputAssign = lib.mapAttrsToList
|
|
(workspace: output: { inherit workspace output; })
|
|
cfg.workspaceOutput;
|
|
|
|
focus = {
|
|
followMouse = true;
|
|
mouseWarping = true;
|
|
newWindow = "urgent";
|
|
};
|
|
|
|
startup = []
|
|
++ optionals config.chuj.stuff.dunst.enable [{ command = "${dunst} &"; notification = false; }]
|
|
++ optionals config.chuj.stuff.flameshot.enable [{ command = "${flameshot} &"; notification = false; }]
|
|
++ optionals cfg.communicators.autostart [{ command = "${schildichat} &"; notification = false; }]
|
|
++ optionals config.chuj.stuff.mpd.enable [{ command = "${mpdstatus} &"; notification = false; }];
|
|
|
|
modes = {
|
|
resize = {
|
|
"Left" = "resize shrink width 10 px or 10 ppt; ${exec i3custom-center-mouse-on-focus}";
|
|
"Right" = "resize grow width 10 px or 10 ppt; ${exec i3custom-center-mouse-on-focus}";
|
|
"Up" = "resize shrink height 10 px or 10 ppt; ${exec i3custom-center-mouse-on-focus}";
|
|
"Down" = "resize grow height 10 px or 10 ppt; ${exec i3custom-center-mouse-on-focus}";
|
|
"Escape" = "mode default";
|
|
};
|
|
};
|
|
|
|
modifier = "Mod4";
|
|
floating.modifier = "Mod4";
|
|
|
|
keybindings = with config.chuj.stuff.i3.mediaKeys; let
|
|
mod = modifier;
|
|
update_mpdstatus = "${killall} -USR1 mpdstatus && ${sync} ${config.chuj.stuff.mpd.statusFile}";
|
|
update_i3status = "${killall} -USR1 i3status";
|
|
center_mouse = exec i3custom-center-mouse-on-focus;
|
|
in {
|
|
# Program keybinds
|
|
"${mod}+Return" = exec terminal;
|
|
"${mod}+d" = exec dmenu_run;
|
|
"${mod}+Shift+s" = mkIf config.chuj.stuff.flameshot.enable (exec "${flameshot} gui");
|
|
"${mod}+b" = mkIf config.chuj.stuff.firefox.enable (exec firefox);
|
|
"--release ${mod}+k" = exec xkill;
|
|
|
|
# Volume control
|
|
"Ctrl+${audioMute}" = exec "${pamixer} --toggle-mute && ${update_i3status}";
|
|
"Ctrl+${audioDown}" = exec "${pamixer} --decrease 5 && ${update_i3status}";
|
|
"Ctrl+${audioUp}" = exec "${pamixer} --increase 5 && ${update_i3status}";
|
|
|
|
# General i3 keybindings
|
|
"${mod}+Shift+q" = "kill; ${center_mouse}";
|
|
"${mod}+f" = "fullscreen toggle; ${center_mouse}";
|
|
"${mod}+r" = "mode resize";
|
|
"${mod}+Shift+r" = "restart";
|
|
"--border button3" = exec i3custom-window-actions;
|
|
|
|
"${mod}+Left" = "focus left; ${center_mouse}";
|
|
"${mod}+Right" = "focus right; ${center_mouse}";
|
|
"${mod}+Up" = "focus up; ${center_mouse}";
|
|
"${mod}+Down" = "focus down; ${center_mouse}";
|
|
"${mod}+Shift+Left" = "move left; ${center_mouse}";
|
|
"${mod}+Shift+Right" = "move right; ${center_mouse}";
|
|
"${mod}+Shift+Up" = "move up; ${center_mouse}";
|
|
"${mod}+Shift+Down" = "move down; ${center_mouse}";
|
|
|
|
"${mod}+q" = "layout stacking; ${center_mouse}";
|
|
"${mod}+w" = "layout tabbed; ${center_mouse}";
|
|
"${mod}+e" = "layout toggle split; ${center_mouse}";
|
|
|
|
"${mod}+Shift+space" = "floating toggle; ${center_mouse}";
|
|
"${mod}+space" = "focus mode_toggle; ${center_mouse}";
|
|
|
|
"${mod}+1" = "workspace number 1; ${center_mouse}";
|
|
"${mod}+2" = "workspace number 2; ${center_mouse}";
|
|
"${mod}+3" = "workspace number 3; ${center_mouse}";
|
|
"${mod}+4" = "workspace number 4; ${center_mouse}";
|
|
"${mod}+5" = "workspace number 5; ${center_mouse}";
|
|
"${mod}+6" = "workspace number 6; ${center_mouse}";
|
|
"${mod}+7" = "workspace number 7; ${center_mouse}";
|
|
"${mod}+8" = "workspace number 8; ${center_mouse}";
|
|
"${mod}+9" = "workspace number 9; ${center_mouse}";
|
|
"${mod}+0" = "workspace number 10; ${center_mouse}";
|
|
|
|
"${mod}+Shift+1" = "move container to workspace number 1; ${center_mouse}";
|
|
"${mod}+Shift+2" = "move container to workspace number 2; ${center_mouse}";
|
|
"${mod}+Shift+3" = "move container to workspace number 3; ${center_mouse}";
|
|
"${mod}+Shift+4" = "move container to workspace number 4; ${center_mouse}";
|
|
"${mod}+Shift+5" = "move container to workspace number 5; ${center_mouse}";
|
|
"${mod}+Shift+6" = "move container to workspace number 6; ${center_mouse}";
|
|
"${mod}+Shift+7" = "move container to workspace number 7; ${center_mouse}";
|
|
"${mod}+Shift+8" = "move container to workspace number 8; ${center_mouse}";
|
|
"${mod}+Shift+9" = "move container to workspace number 9; ${center_mouse}";
|
|
"${mod}+Shift+0" = "move container to workspace number 10; ${center_mouse}";
|
|
} // (optionalAttrs config.chuj.stuff.mpd.enable {
|
|
# MPD controls
|
|
"Ctrl+${musicMenu}" = exec "${musicsel} && ${update_mpdstatus} && ${update_i3status}";
|
|
"Ctrl+${musicPrev}" = exec "${mpc} prev && ${update_mpdstatus} && ${update_i3status}";
|
|
"Ctrl+${musicNext}" = exec "${mpc} next && ${update_mpdstatus} && ${update_i3status}";
|
|
"Ctrl+${musicPlay}" = exec "${mpc} toggle && ${update_mpdstatus} && ${update_i3status}";
|
|
"Ctrl+Shift+${musicPlay}" = exec "${mpc} clear && ${update_mpdstatus} && ${update_i3status}";
|
|
"Ctrl+Shift+${musicPrev}" = exec "${mpc} seek -3";
|
|
"Ctrl+Shift+${musicNext}" = exec "${mpc} seek +3";
|
|
"Ctrl+Shift+${audioDown}" = exec ''${mpc} volume -5 && ${dunstify} "mpc $(${mpc} volume)" -r 420'';
|
|
"Ctrl+Shift+${audioUp}" = exec ''${mpc} volume +5 && ${dunstify} "mpc $(${mpc} volume)" -r 420'';
|
|
});
|
|
|
|
bars = [{
|
|
inherit fonts;
|
|
trayOutput = "primary";
|
|
statusCommand = "${lib.getExe hmCfg.programs.i3status.package}";
|
|
extraConfig = ''
|
|
height 24
|
|
'';
|
|
}];
|
|
};
|
|
};
|
|
|
|
programs.i3status = {
|
|
enable = true;
|
|
enableDefault = false;
|
|
|
|
general = {
|
|
interval = 1;
|
|
colors = true;
|
|
color_good = "#91d956";
|
|
color_bad = "#f43841";
|
|
color_degraded = "#ffdd33";
|
|
output_format = "i3bar";
|
|
};
|
|
|
|
modules = {
|
|
"cpu_usage" = {
|
|
position = 0;
|
|
settings = {
|
|
format = "cpu: %usage";
|
|
};
|
|
};
|
|
"memory" = {
|
|
position = 1;
|
|
settings = {
|
|
format = "mem: %used";
|
|
threshold_degraded = "1G";
|
|
format_degraded = "MEMORY < %available";
|
|
};
|
|
};
|
|
"volume master" = {
|
|
position = 2;
|
|
settings = {
|
|
color_degraded = "#333333";
|
|
format = "vol: %volume";
|
|
format_muted = "vol: ---";
|
|
};
|
|
};
|
|
"tztime local" = {
|
|
position = 4;
|
|
settings = {
|
|
format = "%Y-%m-%d %H:%M:%S (%A)";
|
|
};
|
|
};
|
|
} // (optionalAttrs cfg.battery {
|
|
"battery 0" = {
|
|
position = 3;
|
|
settings = {
|
|
format = "bat%status: %percentage";
|
|
status_chr = "(+)";
|
|
status_bat = "";
|
|
status_unk = "(?)";
|
|
status_full = "(+)";
|
|
status_idle = "";
|
|
low_threshold = 30;
|
|
};
|
|
};
|
|
}) // (optionalAttrs config.chuj.stuff.mpd.enable {
|
|
"read_file mpd" = {
|
|
position = -1;
|
|
settings = {
|
|
format = "%content";
|
|
format_bad = "mpdstatus file not found";
|
|
path = config.chuj.stuff.mpd.statusFile;
|
|
color_good = "#ffffff";
|
|
};
|
|
};
|
|
});
|
|
};
|
|
};
|
|
};
|
|
}
|