497 lines
16 KiB
Nix
497 lines
16 KiB
Nix
{ config, lib, pkgs, ... }:
|
||
|
||
with lib;
|
||
|
||
let
|
||
cfg = config.home.roles.i3_sway;
|
||
wallpaperConfig = import ../../wallpapers;
|
||
currentWallpaper = builtins.elemAt wallpaperConfig.wallpapers wallpaperConfig.currentIndex;
|
||
|
||
shared_config = recursiveUpdate rec {
|
||
modifier = "Mod4";
|
||
terminal = "ghostty";
|
||
defaultWorkspace = "workspace number 1";
|
||
|
||
keybindings = {
|
||
"${shared_config.modifier}+Return" = "exec ${terminal}";
|
||
"${shared_config.modifier}+Shift+Return" = "exec ${cfg.browser}";
|
||
"${shared_config.modifier}+Shift+q" = "kill";
|
||
|
||
"${shared_config.modifier}+a" = "focus parent";
|
||
"${shared_config.modifier}+Shift+a" = "focus child";
|
||
|
||
"${shared_config.modifier}+h" = "focus left";
|
||
"${shared_config.modifier}+j" = "focus down";
|
||
"${shared_config.modifier}+k" = "focus up";
|
||
"${shared_config.modifier}+l" = "focus right";
|
||
|
||
"${shared_config.modifier}+Shift+h" = "move left";
|
||
"${shared_config.modifier}+Shift+j" = "move down";
|
||
"${shared_config.modifier}+Shift+k" = "move up";
|
||
"${shared_config.modifier}+Shift+l" = "move right";
|
||
|
||
"${shared_config.modifier}+Left" = "focus left";
|
||
"${shared_config.modifier}+Down" = "focus down";
|
||
"${shared_config.modifier}+Up" = "focus up";
|
||
"${shared_config.modifier}+Right" = "focus right";
|
||
|
||
"${shared_config.modifier}+Shift+Left" = "move left";
|
||
"${shared_config.modifier}+Shift+Down" = "move down";
|
||
"${shared_config.modifier}+Shift+Up" = "move up";
|
||
"${shared_config.modifier}+Shift+Right" = "move right";
|
||
|
||
#"${shared_config.modifier}+h" = "split h";
|
||
"${shared_config.modifier}+v" = "split v";
|
||
"${shared_config.modifier}+Shift+f" = "fullscreen toggle";
|
||
|
||
"${shared_config.modifier}+s" = "layout stacking";
|
||
"${shared_config.modifier}+w" = "layout tabbed";
|
||
"${shared_config.modifier}+e" = "layout toggle split";
|
||
|
||
"${shared_config.modifier}+Shift+space" = "floating toggle";
|
||
"${shared_config.modifier}+space" = "focus mode_toggle";
|
||
|
||
"${shared_config.modifier}+Shift+minus" = "move scratchpad";
|
||
"${shared_config.modifier}+minus" = "scratchpad show";
|
||
|
||
"${shared_config.modifier}+1" = "workspace number 1";
|
||
"${shared_config.modifier}+2" = "workspace number 2";
|
||
"${shared_config.modifier}+3" = "workspace number 3";
|
||
"${shared_config.modifier}+4" = "workspace number 4";
|
||
"${shared_config.modifier}+5" = "workspace number 5";
|
||
"${shared_config.modifier}+6" = "workspace number 6";
|
||
"${shared_config.modifier}+7" = "workspace number 7";
|
||
"${shared_config.modifier}+8" = "workspace number 8";
|
||
"${shared_config.modifier}+9" = "workspace number 9";
|
||
"${shared_config.modifier}+0" = "workspace number 10";
|
||
|
||
"${shared_config.modifier}+Shift+1" =
|
||
"move container to workspace number 1";
|
||
"${shared_config.modifier}+Shift+2" =
|
||
"move container to workspace number 2";
|
||
"${shared_config.modifier}+Shift+3" =
|
||
"move container to workspace number 3";
|
||
"${shared_config.modifier}+Shift+4" =
|
||
"move container to workspace number 4";
|
||
"${shared_config.modifier}+Shift+5" =
|
||
"move container to workspace number 5";
|
||
"${shared_config.modifier}+Shift+6" =
|
||
"move container to workspace number 6";
|
||
"${shared_config.modifier}+Shift+7" =
|
||
"move container to workspace number 7";
|
||
"${shared_config.modifier}+Shift+8" =
|
||
"move container to workspace number 8";
|
||
"${shared_config.modifier}+Shift+9" =
|
||
"move container to workspace number 9";
|
||
"${shared_config.modifier}+Shift+0" =
|
||
"move container to workspace number 10";
|
||
|
||
"${shared_config.modifier}+Shift+c" = "reload";
|
||
"${shared_config.modifier}+Shift+r" = "restart";
|
||
|
||
"${shared_config.modifier}+r" = "mode resize";
|
||
|
||
"XF86MonBrightnessUp" = "exec ddcutil setvcp 10 + 5";
|
||
"XF86MonBrightnessDown" = "exec ddcutil setvcp 10 - 5";
|
||
};
|
||
} cfg.extraSharedConfig;
|
||
in {
|
||
options.home.roles.i3_sway = {
|
||
enable = mkEnableOption "i3 and Sway tiling window managers with waybar and rofi";
|
||
|
||
browser = mkOption {
|
||
type = types.str;
|
||
default = "firefox --new-window";
|
||
description = "Browser to use for new window keybinding";
|
||
};
|
||
|
||
extraSharedConfig = mkOption {
|
||
type = types.attrs;
|
||
default = {};
|
||
description = "Extra configuration shared between i3 and sway";
|
||
};
|
||
|
||
extraI3Config = mkOption {
|
||
type = types.attrs;
|
||
default = {};
|
||
description = "Extra i3-specific configuration";
|
||
};
|
||
|
||
extraSwayConfig = mkOption {
|
||
type = types.attrs;
|
||
default = {};
|
||
description = "Extra sway-specific configuration";
|
||
};
|
||
};
|
||
|
||
config = mkIf cfg.enable {
|
||
# i3blocks configuration file
|
||
home.file.".config/i3blocks/config".text = ''
|
||
# i3blocks config - replicating waybar setup
|
||
separator_block_width=15
|
||
markup=pango
|
||
|
||
[disk]
|
||
command=df -h / | awk 'NR==2 {print "💾 " $5}'
|
||
interval=30
|
||
separator=true
|
||
|
||
[cpu]
|
||
command=top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print "🧠 " int(100 - $1) "%"}'
|
||
interval=2
|
||
separator=true
|
||
|
||
[memory]
|
||
command=free | awk 'NR==2 {printf "🐏 %.0f%%\n", $3*100/$2}'
|
||
interval=5
|
||
separator=true
|
||
|
||
[pulseaudio]
|
||
command=${pkgs.writeShellScript "i3blocks-pulseaudio" ''
|
||
volume=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -1)
|
||
muted=$(pactl get-sink-mute @DEFAULT_SINK@ | grep -o 'yes')
|
||
if [ "$muted" = "yes" ]; then
|
||
echo "🔇"
|
||
else
|
||
vol_num=''${volume%\%}
|
||
if [ $vol_num -le 33 ]; then
|
||
echo "🔈 $volume"
|
||
elif [ $vol_num -le 66 ]; then
|
||
echo "🔉 $volume"
|
||
else
|
||
echo "🔊 $volume"
|
||
fi
|
||
fi
|
||
''}
|
||
interval=1
|
||
signal=10
|
||
separator=true
|
||
|
||
[backlight]
|
||
command=${pkgs.writeShellScript "i3blocks-backlight" ''
|
||
if command -v ddcutil &>/dev/null; then
|
||
# Handle mouse scroll events
|
||
case $BLOCK_BUTTON in
|
||
4) ddcutil setvcp 10 + 5 ;; # Scroll up - increase brightness
|
||
5) ddcutil setvcp 10 - 5 ;; # Scroll down - decrease brightness
|
||
esac
|
||
|
||
# Display current brightness
|
||
brightness=$(ddcutil getvcp 10 2>/dev/null | grep -oP 'current value =\s*\K\d+')
|
||
if [ -n "$brightness" ]; then
|
||
echo "☀️ $brightness%"
|
||
fi
|
||
fi
|
||
''}
|
||
interval=5
|
||
separator=true
|
||
|
||
[network]
|
||
command=${pkgs.writeShellScript "i3blocks-network" ''
|
||
if iwgetid -r &>/dev/null; then
|
||
ssid=$(iwgetid -r)
|
||
signal=$(grep "^\s*w" /proc/net/wireless | awk '{print int($3 * 100 / 70)}')
|
||
echo "📶 $ssid ($signal%)"
|
||
else
|
||
ip=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
|
||
if [ -n "$ip" ]; then
|
||
echo "🔌 $ip"
|
||
else
|
||
echo "❌"
|
||
fi
|
||
fi
|
||
''}
|
||
interval=5
|
||
separator=true
|
||
|
||
[battery]
|
||
command=${pkgs.writeShellScript "i3blocks-battery" ''
|
||
if [ -d /sys/class/power_supply/BAT0 ]; then
|
||
capacity=$(cat /sys/class/power_supply/BAT0/capacity)
|
||
status=$(cat /sys/class/power_supply/BAT0/status)
|
||
|
||
if [ "$status" = "Charging" ]; then
|
||
echo "⚡ $capacity%"
|
||
else
|
||
echo "🔋 $capacity%"
|
||
fi
|
||
fi
|
||
''}
|
||
interval=10
|
||
separator=true
|
||
|
||
[time]
|
||
command=date '+%Y-%m-%d %H:%M'
|
||
interval=1
|
||
separator=false
|
||
'';
|
||
|
||
xsession.windowManager.i3 = let
|
||
base_i3_config = recursiveUpdate shared_config {
|
||
bars = [{
|
||
position = "bottom";
|
||
statusCommand = "${pkgs.i3blocks}/bin/i3blocks";
|
||
trayOutput = "primary"; # Enable system tray on primary output
|
||
fonts = {
|
||
names = [ "Fira Code" "monospace" ];
|
||
size = 11.0;
|
||
};
|
||
colors = {
|
||
background = "#000000";
|
||
statusline = "#ffffff";
|
||
separator = "#666666";
|
||
|
||
# Workspace button colors (matching waybar)
|
||
focusedWorkspace = {
|
||
border = "#285577";
|
||
background = "#285577";
|
||
text = "#ffffff";
|
||
};
|
||
activeWorkspace = {
|
||
border = "#5f676a";
|
||
background = "#5f676a";
|
||
text = "#ffffff";
|
||
};
|
||
inactiveWorkspace = {
|
||
border = "#222222";
|
||
background = "#222222";
|
||
text = "#888888";
|
||
};
|
||
urgentWorkspace = {
|
||
border = "#900000";
|
||
background = "#900000";
|
||
text = "#ffffff";
|
||
};
|
||
};
|
||
}];
|
||
keybindings = shared_config.keybindings // {
|
||
"${shared_config.modifier}+d" = "exec rofi -show drun";
|
||
"${shared_config.modifier}+Shift+e" =
|
||
"exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'";
|
||
};
|
||
startup = [
|
||
# GNOME polkit authentication agent
|
||
{
|
||
command = "/run/current-system/sw/libexec/polkit-gnome-authentication-agent-1";
|
||
always = false;
|
||
notification = false;
|
||
}
|
||
# Picom compositor for smooth rendering and no tearing (important for Nvidia)
|
||
{
|
||
command = "picom --backend glx -b";
|
||
always = false;
|
||
notification = false;
|
||
}
|
||
# NetworkManager system tray applet
|
||
{
|
||
command = "nm-applet";
|
||
always = false;
|
||
notification = false;
|
||
}
|
||
# Set wallpaper with feh
|
||
{
|
||
command = "feh ${currentWallpaper.feh} ${currentWallpaper.file}";
|
||
always = false;
|
||
notification = false;
|
||
}
|
||
];
|
||
};
|
||
in {
|
||
enable = true;
|
||
config = recursiveUpdate base_i3_config cfg.extraI3Config;
|
||
};
|
||
|
||
wayland.windowManager.sway = let
|
||
base_sway_config = recursiveUpdate shared_config {
|
||
bars = []; # Disable default bar, use waybar instead
|
||
keybindings = shared_config.keybindings // {
|
||
"${shared_config.modifier}+d" = "exec wofi --show drun";
|
||
"${shared_config.modifier}+Shift+e" =
|
||
"exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'";
|
||
};
|
||
input = {
|
||
"type:keyboard" = {
|
||
xkb_options = "caps:escape";
|
||
};
|
||
"type:touchpad" = {
|
||
tap = "enabled";
|
||
tap_button_map = "lrm";
|
||
drag = "enabled";
|
||
natural_scroll = "disabled";
|
||
dwt = "enabled";
|
||
};
|
||
};
|
||
output = {
|
||
"*" = {
|
||
bg = "${currentWallpaper.file} ${currentWallpaper.sway}";
|
||
};
|
||
};
|
||
startup = [
|
||
# Launch waybar status bar
|
||
{
|
||
command = "waybar";
|
||
always = false;
|
||
}
|
||
];
|
||
};
|
||
in {
|
||
enable = true;
|
||
extraOptions = [ "--unsupported-gpu" ];
|
||
config = recursiveUpdate base_sway_config cfg.extraSwayConfig;
|
||
};
|
||
|
||
programs.waybar = {
|
||
enable = true;
|
||
systemd.enable = false; # Don't auto-start via systemd - only launch in sway
|
||
settings = {
|
||
mainBar = {
|
||
layer = "top";
|
||
position = "bottom";
|
||
height = 30;
|
||
spacing = 4;
|
||
|
||
modules-left = [ "sway/workspaces" "sway/mode" ];
|
||
modules-center = [ ];
|
||
modules-right = [ "disk" "cpu" "memory" "pulseaudio" "custom/backlight-ddc" "backlight" "network" "battery" "tray" "clock" ];
|
||
|
||
"sway/workspaces" = {
|
||
disable-scroll = true;
|
||
all-outputs = true;
|
||
};
|
||
|
||
"clock" = {
|
||
format = "{:%Y-%m-%d %H:%M}";
|
||
tooltip-format = "<tt><small>{calendar}</small></tt>";
|
||
calendar = {
|
||
mode = "year";
|
||
mode-mon-col = 3;
|
||
weeks-pos = "right";
|
||
on-scroll = 1;
|
||
format = {
|
||
months = "<span color='#ffead3'><b>{}</b></span>";
|
||
days = "<span color='#ecc6d9'><b>{}</b></span>";
|
||
weeks = "<span color='#99ffdd'><b>W{}</b></span>";
|
||
weekdays = "<span color='#ffcc66'><b>{}</b></span>";
|
||
today = "<span color='#ff6699'><b><u>{}</u></b></span>";
|
||
};
|
||
};
|
||
};
|
||
|
||
"disk" = {
|
||
interval = 30;
|
||
format = "💾 {percentage_used}%";
|
||
path = "/";
|
||
tooltip-format = "Used: {used} / {total} ({percentage_used}%)\nFree: {free} ({percentage_free}%)";
|
||
};
|
||
|
||
"cpu" = {
|
||
format = "🧠 {usage}%";
|
||
tooltip = false;
|
||
};
|
||
|
||
"memory" = {
|
||
format = "🐏 {percentage}%";
|
||
tooltip-format = "RAM: {used:0.1f}G / {total:0.1f}G";
|
||
};
|
||
|
||
"pulseaudio" = {
|
||
format = "{icon} {volume}%";
|
||
format-muted = "🔇";
|
||
format-icons = {
|
||
headphone = "🎧";
|
||
default = [ "🔈" "🔉" "🔊" ];
|
||
};
|
||
on-click = "pavucontrol";
|
||
};
|
||
|
||
"backlight" = {
|
||
format = "☀️ {percent}%";
|
||
tooltip = false;
|
||
};
|
||
|
||
"custom/backlight-ddc" = {
|
||
exec = pkgs.writeShellScript "waybar-backlight-ddc" ''
|
||
if command -v ddcutil &>/dev/null; then
|
||
# Display current brightness
|
||
brightness=$(ddcutil getvcp 10 --brief 2>/dev/null | awk '{print $4}')
|
||
if [ -n "$brightness" ]; then
|
||
echo "☀️ $brightness%"
|
||
fi
|
||
fi
|
||
'';
|
||
interval = 5;
|
||
format = "{}";
|
||
on-scroll-up = "ddcutil setvcp 10 + 5 2>/dev/null &";
|
||
on-scroll-down = "ddcutil setvcp 10 - 5 2>/dev/null &";
|
||
tooltip = false;
|
||
};
|
||
|
||
"network" = {
|
||
format-wifi = "📶 {essid} ({signalStrength}%)";
|
||
format-ethernet = "🔌 {ipaddr}";
|
||
format-disconnected = "❌";
|
||
tooltip-format = "{ifname}: {ipaddr}/{cidr}";
|
||
};
|
||
|
||
"battery" = {
|
||
states = {
|
||
warning = 30;
|
||
critical = 15;
|
||
};
|
||
format = "{icon} {capacity}%";
|
||
format-charging = "⚡ {capacity}%";
|
||
format-icons = [ "🪫" "🔋" "🔋" "🔋" "🔋" ];
|
||
};
|
||
|
||
"tray" = {
|
||
spacing = 10;
|
||
};
|
||
};
|
||
};
|
||
style = ''
|
||
* {
|
||
padding: 0 4px;
|
||
font-family: "Fira Code", monospace;
|
||
font-size: 13px;
|
||
}
|
||
|
||
#workspaces button {
|
||
padding: 0 8px;
|
||
background-color: #333333;
|
||
color: #ffffff;
|
||
border: none;
|
||
}
|
||
|
||
#workspaces button.focused {
|
||
background-color: #285577;
|
||
font-weight: bold;
|
||
}
|
||
|
||
#workspaces button.visible {
|
||
background-color: #5f676a;
|
||
}
|
||
|
||
#workspaces button.urgent {
|
||
background-color: #900000;
|
||
}
|
||
'';
|
||
};
|
||
|
||
programs.rofi = {
|
||
enable = true;
|
||
theme = "solarized";
|
||
extraConfig = {
|
||
modi = "drun,run,window";
|
||
show-icons = true;
|
||
drun-display-format = "{name}";
|
||
disable-history = false;
|
||
hide-scrollbar = true;
|
||
display-drun = " Apps";
|
||
display-run = " Run";
|
||
display-window = " Windows";
|
||
sidebar-mode = true;
|
||
};
|
||
};
|
||
};
|
||
}
|