1
0
Fork 0
nixos/lwad/applications/i3/default.nix

516 lines
21 KiB
Nix

{ config, lib, pkgs, ... }:
with lib; {
options.lwad.applications.i3 = {
enable = mkEnableOption "i3wm";
modifiers = {
primary = mkOption {
default = "Mod4";
description = "Primary modifier to use.";
type = types.str;
};
alternative = mkOption {
default = "Mod1";
description = "Alternative modifier to use.";
type = types.str;
};
};
};
imports = [
./audioControls.nix
./autoRun.nix
./backlight.nix
./displayProperties.nix
./moveDisplayUp.nix
./outputWorkspaceMappings.nix
];
config = let cfg = config.lwad.applications.i3;
in mkIf cfg.enable {
home-manager.users.${config.lwad.definitions.username} =
let colors = config.lwad.definitions.theme.colors;
in {
programs.rofi = {
enable = true;
font = "FiraCode Nerd Font 11";
location = "top";
package = pkgs.rofi;
terminal = config.lwad.applications.terminalEmulator.default;
theme = builtins.toFile "rofi-theme" ''
* {
/* Colors. */
red: rgba ( 190, 42, 73, 100 % );
blue: rgba ( 167, 214, 247, 100 % );
/* Selected entry (normal). */
selected-normal-foreground: ${colors.text};
selected-normal-background: ${colors.menu_background};
/* Selected entry (active). */
selected-active-foreground: @selected-normal-foreground;
selected-active-background: @selected-normal-background;
/* Selected entry (urgent). */
selected-urgent-foreground: @selected-normal-foreground;
selected-urgent-background: @selected-normal-background;
/* Unselected entry (normal). */
foreground: ${colors.text};
background: ${colors.background};
normal-foreground: @foreground;
normal-background: @background;
/* Unselected entry (active). */
active-foreground: @normal-foreground;
active-background: @normal-background;
/* Unselected entry (urgent). */
urgent-foreground: @normal-foreground;
urgent-background: @normal-background;
/* Unselected entry (alternate). */
alternate-normal-foreground: @normal-foreground;
alternate-normal-background: @normal-background;
/* Unselected entry (alternate active). */
alternate-active-foreground: @normal-foreground;
alternate-active-background: @normal-background;
/* Unselected entry (alternate urgent). */
alternate-urgent-foreground: @normal-foreground;
alternate-urgent-background: @normal-background;
/* Search box. */
background-color: @normal-background;
/* Other. */
spacing: 0;
border-color: ${colors.highlight};
separatorcolor: @normal-background;
/* Unknown. */
lightfg: rgba ( 0, 0, 0, 0 % );
lightbg: rgba ( 0, 0, 0, 0 % );
}
window {
background-color: @background;
border: 3;
padding: 3;
}
mainbox {
border: 0;
padding: 0;
}
message {
border: 2px 0px 0px ;
border-color: @separatorcolor;
padding: 1px ;
}
textbox {
text-color: @foreground;
}
listview {
fixed-height: 0;
border: 2px 0px 0px ;
border-color: @separatorcolor;
scrollbar: true;
padding: 2px 0px 0px ;
}
element {
border: 0;
padding: @spacing;
}
element-text {
background-color: inherit;
text-color: inherit;
}
element.normal.normal {
background-color: @normal-background;
text-color: @normal-foreground;
}
element.normal.urgent {
background-color: @urgent-background;
text-color: @urgent-foreground;
}
element.normal.active {
background-color: @active-background;
text-color: @active-foreground;
}
element.selected.normal {
background-color: @selected-normal-background;
text-color: @selected-normal-foreground;
}
element.selected.urgent {
background-color: @selected-urgent-background;
text-color: @selected-urgent-foreground;
}
element.selected.active {
background-color: @selected-active-background;
text-color: @selected-active-foreground;
}
element.alternate.normal {
background-color: @alternate-normal-background;
text-color: @alternate-normal-foreground;
}
element.alternate.urgent {
background-color: @alternate-urgent-background;
text-color: @alternate-urgent-foreground;
}
element.alternate.active {
background-color: @alternate-active-background;
text-color: @alternate-active-foreground;
}
scrollbar {
width: 0;
border: 0;
handle-color: @normal-foreground;
handle-width: 0;
padding: 0;
}
mode-switcher {
border: 2px 0px 0px ;
border-color: @separatorcolor;
}
button {
spacing: 0;
text-color: @normal-foreground;
}
button.selected {
background-color: @selected-normal-background;
text-color: @selected-normal-foreground;
}
inputbar {
spacing: 0;
text-color: @normal-foreground;
padding: 1px ;
}
case-indicator {
spacing: 0;
text-color: @normal-foreground;
}
entry {
spacing: 0;
text-color: @normal-foreground;
}
prompt {
spacing: 0;
text-color: @normal-foreground;
}
inputbar {
children: [ prompt,textbox-prompt-colon,entry,case-indicator ];
}
textbox-prompt-colon {
expand: false;
str: ":";
margin: 0px 0.3em 0em 0em ;
text-color: @normal-foreground;
}
'';
};
xsession.windowManager.i3 = {
enable = true;
config = let
mod = cfg.modifiers.primary;
alt = cfg.modifiers.alternative;
in {
bars = mkForce [ ];
colors = {
background = colors.near_black;
focused = {
background = colors.near_black;
border = colors.highlight;
childBorder = colors.highlight;
indicator = colors.highlight_darker;
text = colors.text;
};
focusedInactive = {
background = colors.near_black;
border = colors.near_black;
childBorder = colors.near_black;
indicator = colors.near_black;
text = colors.text;
};
placeholder = {
background = colors.near_black;
border = colors.near_black;
childBorder = colors.near_black;
indicator = colors.near_black;
text = colors.text;
};
unfocused = {
background = colors.near_black;
border = colors.near_black;
childBorder = colors.near_black;
indicator = colors.near_black;
text = colors.text;
};
urgent = {
background = colors.near_black;
border = "#F8E85F";
childBorder = "#F8E85F";
indicator = "#F4631A";
text = colors.text;
};
};
floating = {
modifier = mod;
titlebar = false;
};
keybindings = mkMerge [
# Meta.
{
"${mod}+Shift+c" = "reload";
"${mod}+Shift+r" = "restart";
}
# Focus movement.
{
"${mod}+1" = "workspace 1";
"${mod}+2" = "workspace 2";
"${mod}+3" = "workspace 3";
"${mod}+4" = "workspace 4";
"${mod}+5" = "workspace 5";
"${alt}+1" = "workspace 6";
"${alt}+2" = "workspace 7";
"${alt}+3" = "workspace 8";
"${alt}+4" = "workspace 9";
"${alt}+5" = "workspace 10";
"${mod}+h" = "focus left";
"${mod}+j" = "focus down";
"${mod}+k" = "focus up";
"${mod}+l" = "focus right";
"${mod}+a" = "focus parent";
"${mod}+x" = "focus child";
"${mod}+space" = "focus mode_toggle";
}
# Window movement.
{
"${mod}+Shift+1" = "move container to workspace 1";
"${mod}+Shift+2" = "move container to workspace 2";
"${mod}+Shift+3" = "move container to workspace 3";
"${mod}+Shift+4" = "move container to workspace 4";
"${mod}+Shift+5" = "move container to workspace 5";
"${alt}+Shift+1" = "move container to workspace 6";
"${alt}+Shift+2" = "move container to workspace 7";
"${alt}+Shift+3" = "move container to workspace 8";
"${alt}+Shift+4" = "move container to workspace 9";
"${alt}+Shift+5" = "move container to workspace 10";
"${mod}+Shift+h" = "move left";
"${mod}+Shift+j" = "move down";
"${mod}+Shift+k" = "move up";
"${mod}+Shift+l" = "move right";
"${mod}+Shift+space" = "floating toggle";
}
# Window other.
{
"${mod}+Shift+q" = "kill";
"${mod}+f" = "fullscreen toggle";
"${mod}+e" = "layout toggle split";
"${mod}+v" = "split v";
}
# Scratchpad management.
{
"${mod}+w" = "exec --no-startup-id ${
let
i3-msg = "${pkgs.i3}/bin/i3-msg";
jq = "${pkgs.jq}/bin/jq";
in pkgs.writeScript "show_from_scratchpad.sh" ''
class="$(${i3-msg} -t get_tree | ${jq} '.nodes | map(select(.name == "__i3")) | .[].nodes[].nodes[].floating_nodes[].nodes[].window_properties.class' --raw-output | ${pkgs.coreutils}/bin/sort | ${pkgs.coreutils}/bin/uniq | ${pkgs.rofi}/bin/rofi -dmenu -p "Window Class" -i)"
[[ "$class" != "" ]] && ${i3-msg} [ class="$class" ] scratchpad show
''
}";
"${mod}+Shift+w" = "exec --no-startup-id ${
let
i3-msg = "${pkgs.i3}/bin/i3-msg";
jq = "${pkgs.jq}/bin/jq";
in pkgs.writeScript "move_to_scratchpad.sh" ''
${i3-msg} "move scratchpad" > /dev/null
last_window_id=$(${i3-msg} -t get_tree \
| ${jq} 'recurse(.nodes[]) | select(.name == "__i3_scratch").floating_nodes[-1].nodes[0].id')
if [ "$last_window_id" != "null" ]; then
${i3-msg} "[con_id=\"$last_window_id\"] scratchpad show, resize set 1280 px 75 ppt, move position center, move scratchpad" > /dev/null
fi
''
}";
"${mod}+Tab" = ''[class="(Alacritty|kitty)"] scratchpad show'';
}
# Draw to float.
{
"${mod}+q" = "exec --no-startup-id ${
let xdotool = "${pkgs.xdotool}/bin/xdotool";
in pkgs.writeScript "float_on_selection.sh" ''
color="${colors.highlight}"
color="''${color:1}"
eval "$(${pkgs.perl}/bin/perl -e "printf('R=%.3f G=%.3f B=%.3f ',0x''${color:0:2}/255,0x''${color:2:2}/255,0x''${color:4:2}/255)")"
slopped="$(${pkgs.slop}/bin/slop -t 0 -c ''${R},''${G},''${B} -b 2 -f "X=%x Y=%y W=%w H=%h")"
[[ "$slopped" == "" ]] && exit 1
eval "$slopped"
${pkgs.i3}/bin/i3-msg floating enable \
&& ${xdotool} getactivewindow windowmove $X $Y \
&& ${xdotool} getactivewindow windowsize $W $H
''
}";
}
# Launch.
{
"${mod}+Return" = mkIf
(config.lwad.applications.terminalEmulator.default != null)
"exec --no-startup-id ${config.lwad.applications.terminalEmulator.default}";
"${mod}+Shift+Return" =
"exec --no-startup-id ${pkgs.pcmanfm}/bin/pcmanfm";
"${mod}+d" =
"exec --no-startup-id ${pkgs.rofi}/bin/rofi -show drun";
"${alt}+Shift+s" = mkIf
config.lwad.applications.terminalEmulator.alacritty.enable
"exec --no-startup-id alacritty -e sh -c '(read target && ssh \"$target\")'";
"${mod}+s" = "exec --no-startup-id ${
pkgs.writeScript "web_search.sh" ''
searchString=$(${pkgs.rofi}/bin/rofi -dmenu -p "Search" -i -theme-str "listview {lines: 0;}" | ${pkgs.jq}/bin/jq -Rsj @uri | ${pkgs.gnused}/bin/sed -e "s/%0A\$//")
[[ "$searchString" == "" ]] || ${pkgs.librewolf}/bin/librewolf --new-tab "https://duckduckgo.com/?q=''${searchString}"
''
}";
}
# Screenshots.
{
"${mod}+shift+s" = " exec --no-startup-id ${
let scrot = "${pkgs.scrot}/bin/scrot";
in pkgs.writeScript "copy_screenshot.sh" ''
SCREENSHOT_FILE="/tmp/$(date +"%y%m%d%H%M%S").png"
case "$(echo -e "desktop\nwindow\nselection" | ${pkgs.rofi}/bin/rofi -dmenu -p "Screenshot Type" -i)" in
desktop)
${scrot} -F "$SCREENSHOT_FILE" || exit 1
;;
window)
${scrot} -u -b -F "$SCREENSHOT_FILE" || exit 1
;;
selection)
color="${colors.highlight}"
color="''${color:1}"
eval "$(${pkgs.perl}/bin/perl -e "printf('R=%.3f G=%.3f B=%.3f ',0x''${color:0:2}/255,0x''${color:2:2}/255,0x''${color:4:2}/255)")"
slopped="$(${pkgs.slop}/bin/slop -t 0 -c ''${R},''${G},''${B} -b 2 -f "X=%x Y=%y W=%w H=%h")"
[[ "$slopped" == "" ]] && exit 1
eval "$slopped"
${scrot} -F "$SCREENSHOT_FILE" -a $X,$Y,$W,$H
;;
*)
exit 1
;;
esac
${pkgs.xclip}/bin/xclip -selection clipboard -i "$SCREENSHOT_FILE" -t image/png
''
}";
}
# Media.
(let
change_volume = command: step: boost:
"exec --no-startup-id ${pamixer} ${
if boost then "--allow-boost" else ""
} -${command} ${
if (command == "t") then "" else toString step
} && ${show_volume_notification} ${command}";
pamixer = "${pkgs.pamixer}/bin/pamixer";
playerctl = "${pkgs.playerctl}/bin/playerctl";
show_volume_notification =
pkgs.writeScript "show_volume_notification.sh" ''
volume="$(${pamixer} --get-volume)"
if [[ $(${pamixer} --get-mute) == "true" ]]; then
icon="audio-volume-muted"
elif [[ "$1" == "down" ]]; then
icon="audio-volume-medium"
else
icon="audio-volume-high"
fi
${pkgs.dunst}/bin/dunstify -a "changeVolume" -u low -i "$icon" -h string:x-dunst-stack-tag:changeVolume -h int:value:"$volume" "$volume%" -t 750
'';
in {
"${alt}+k" = "${change_volume "i" 2 false}";
"${alt}+j" = "${change_volume "d" 2 false}";
"${alt}+shift+k" = "${change_volume "i" 10 false}";
"${alt}+shift+j" = "${change_volume "d" 10 false}";
"${alt}+control+k" = "${change_volume "i" 2 true}";
"${alt}+control+j" = "${change_volume "d" 2 true}";
"${alt}+control+shift+k" = "${change_volume "i" 10 true}";
"${alt}+control+shift+j" = "${change_volume "d" 10 true}";
"XF86AudioRaiseVolume" = "${change_volume "i" 2 false}";
"XF86AudioLowerVolume" = "${change_volume "d" 2 false}";
"XF86AudioMute" = "${change_volume "t" 0 false}";
"XF86AudioPlay" =
"exec --no-startup-id ${playerctl} play-pause";
"XF86AudioPause" =
"exec --no-startup-id ${playerctl} play-pause";
"XF86AudioPrev" = "exec --no-startup-id ${playerctl} previous";
"XF86AudioNext" = "exec --no-startup-id ${playerctl} next";
})
# Modes.
{
"${mod}+p" = "mode power";
"${mod}+r" = "mode resize";
}
];
modes = {
resize = {
"h" = "resize shrink width 20 px";
"j" = "resize grow height 20 px";
"k" = "resize shrink height 20 px";
"l" = "resize grow width 20 px";
"Escape" = ''mode "default"'';
};
power = let
systemctl = "${pkgs.systemd}/bin/systemctl";
lockCommand =
"pkill xcompmgr; XSECURELOCK_PASSWORD_PROMPT=time_hex ${pkgs.xsecurelock}/bin/xsecurelock && (${pkgs.xcompmgr}/bin/xcompmgr & sleep 1 && ${pkgs.i3}/bin/i3-msg restart)";
in {
"l" = ''exec --no-startup-id "${lockCommand}", mode "default"'';
"e" = ''
exec --no-startup-id ${pkgs.i3}/bin/i3-msg exit, mode "default"'';
"s" = ''
exec --no-startup-id "${lockCommand}", exec --no-startup-id ${systemctl} suspend, mode "default"'';
"r" =
''exec --no-startup-id ${systemctl} reboot, mode "default"'';
"Shift+s" = ''
exec --no-startup-id ${systemctl} poweroff, mode "default"'';
"Escape" = ''mode "default"'';
};
};
startup = [
{
command = "${pkgs.caffeine-ng}/bin/caffeine start --activate";
notification = false;
}
{
command = "${pkgs.xcompmgr}/bin/xcompmgr";
notification = false;
}
];
window = {
commands = [{
command = "floating disable";
criteria = {
class = "librewolf";
floating = true;
title = "^Extension:.*Bitwarden.*";
};
}];
hideEdgeBorders = "smart";
titlebar = false;
};
};
};
};
services.xserver = {
displayManager.defaultSession = "none+i3";
windowManager.i3 = {
enable = true;
package = pkgs.i3;
};
};
};
}