Add missed imports

This commit is contained in:
Jimbo 2024-09-23 16:36:46 -04:00
parent 7759fd1fa9
commit cebc7be1bf
58 changed files with 15 additions and 23 deletions

84
home/sway/README.md Normal file
View file

@ -0,0 +1,84 @@
# Sway Window Manager Hotkeys
## Application Launchers
| Key Combination | Action |
|----------------------|-------------------------------------------|
| Win + F1 | Launch **LibreWolf** (Jim profile) |
| Win + F2 | Launch **LibreWolf** (Alt profile) |
| Win + F3 | Launch **LibreWolf** (Misc profile) |
| Win + F4 | Launch **Discord** |
| Win + F5 | Launch **Steam** |
| Win + F6 | Launch **Heroic Games** |
| Win + F7 | Launch **Looking Glass** VM Client |
| Win + F10 | Launch **Virt-Manager** |
| Win + F11 | Open **Rofi Scratchpads** |
| Win + F12 | Open **NixOS Configuration Files** |
## Window Management
| Key Combination | Action |
|----------------------|-------------------------------------------|
| Win + Arrows | Focus in the specified direction |
| Win + Shift + Arrows | Move window in the specified direction |
| Win + Shift + Space | Toggle window floating |
| Win + Space | Switch focus between floating/tiled |
| Win + Shift + {1-9} | Move window to a workspace and focus |
| Win + {1-9} | Switch to specified workspace |
| Win + 0 | Pin window and toggle border |
| Win + F | Toggle fullscreen |
| Win + Shift + R | Reload configuration |
| Win + Q | Close the current window |
## Layout Management
| Key Combination | Action |
|----------------------|-------------------------------------------|
| Win + W | Toggle split layout |
| Win + E | Toggle tabbed/stacking layout |
| Win + H/V | Split window horizontally/vertically |
| Win + A/D | Focus parent/child container |
## Volume and Media Controls
| Key Combination | Action |
|----------------------|-------------------------------------------|
| XF86AudioRaiseVolume | Raise system volume |
| XF86AudioLowerVolume | Lower system volume |
| XF86AudioMute | Mute/unmute audio |
| XF86AudioPlay | Toggle media playback |
| XF86AudioNext | Skip to the next track |
| XF86AudioPrev | Go to the previous track |
## Screenshot and Brightness Controls
| Key Combination | Action |
|----------------------|-------------------------------------------|
| Print | Take a screenshot |
| Shift + Print | Screenshot of the current window |
| Brightness Up + Down | Change screen brightness |
## Scratchpads
| Key Combination | Action |
|----------------------|-------------------------------------------|
| Ctrl + Shift + Escape | Open **Gotop** (monitoring) |
| Win + Shift + M | Open **Music** scratchpad |
| Win + Shift + V | Open **Sound Settings** scratchpad |
| Win + Shift + Backslash | Open **EasyEffects** scratchpad |
## Special Sway Tools
| Key Combination | Action |
|----------------------|-------------------------------------------|
| Win + Escape | **Kill** selected window |
| Win + Ctrl + X | **Inspect** window properties |
| Win + Ctrl + Prior/Next | Switch OBS scene to **Main**/**Guest** |
## Miscellaneous
| Key Combination | Action |
|----------------------|-------------------------------------------|
| Win + Return | Open **Foot terminal** |
| Win + S | Open **Rofi (run commands)** |
| Win + C | Open **Clipman (clipboard manager)** |
| Win + X | Open **Power Menu** |
| Win + B | Show/Hide **Waybar** |
## Workspaces (Alternate)
| Key Combination | Action |
|----------------------|-------------------------------------------|
| Alt + F1-F9 | Switch to alternate workspace |
| Alt + Shift + F1-F9 | Move window to alt workspace and focus |

33
home/sway/autostart.nix Normal file
View file

@ -0,0 +1,33 @@
{config, pkgs, ...}: {
# Enable Sway and write some scripts
wayland.windowManager.sway = {
config = {
# Use Waybar rather than Sway's
bars = [{command = "waybar";}];
startup = [
# Scratchpads
{command = "foot -a gotop -T Gotop gotop";}
{command = "foot -a music -T Music ncmpcpp";}
{command = "foot -a sound -T Sound pulsemixer";}
{command = "easyeffects";}
# Daemons and tray apps
{command = "wl-paste -t text --watch clipman store -P";}
{command = "wl-copy";}
{command = "mako";}
{command = "sunshine";}
{command = "${pkgs.rot8}/bin/rot8";}
# Polkit agent
{command = "${pkgs.mate.mate-polkit}/libexec/polkit-mate-authentication-agent-1";}
# Foreground apps
{command = "librewolf -P Misc --name=MiscBrowser";}
{command = "vesktop";}
{command = "element-desktop";}
{command = "thunderbird";}
];
};
};
}

51
home/sway/hardware.nix Normal file
View file

@ -0,0 +1,51 @@
{config, pkgs, outputs, ...}: {
wayland.windowManager.sway = {
config = {
# Define monitors
output = {
${outputs.displays.d1} = {
pos = "1920 405";
mode = "1920x1080@143.980Hz";
max_render_time = "3";
bg = "~/.wallpapers/1.png fill";
scale = "1";
adaptive_sync = "on";
};
${outputs.displays.d2} = {
pos = "0 405";
mode = "1920x1080@60Hz";
max_render_time = "3";
bg = "~/.wallpapers/2.png fill";
};
${outputs.displays.d3} = {
pos = "3840 0";
mode = "1680x1050@59.883Hz";
transform = "270";
max_render_time = "3";
bg = "~/.wallpapers/3.png fill";
};
"*" = {
bg = "~/.wallpapers/1.png fill";
};
};
# HID device config
input = {
"9610:4103:SINOWEALTH_Game_Mouse" = {
pointer_accel = "-0.9";
};
"9639:64097:Compx_2.4G_Receiver_Mouse" = {
pointer_accel = "-0.82";
};
"1452:627:bcm5974" = {
scroll_factor = "0.3";
};
"*" = {
accel_profile = "flat";
dwt = "disabled";
natural_scroll = "disabled";
};
};
};
};
}

270
home/sway/hotkeys.nix Normal file
View file

@ -0,0 +1,270 @@
{config, pkgs, outputs, ...}: {
wayland.windowManager.sway = {
config = let
# Set default modifier and variables
primeMod = "Mod4";
secMod = "Mod1";
resizeAmount = ''55'';
sendNotif = ''notify-send --expire-time=1500'';
in {
# Hotkeys
modifier = "${primeMod}";
keybindings = let
# Define scripts specific to Sway
pinWindow = pkgs.writeScript "pin-window" ''
# Get the current border style of the focused window
current_style=$(swaymsg -t get_tree | jq -r '.. | select(.focused?).border')
# Toggle between "normal" (default) and "pixel ${outputs.look.border.string}" border styles
if [ "$current_style" == "none" ]; then
swaymsg "sticky disable, border pixel ${outputs.look.border.string}"
else
swaymsg "sticky enable, border none"
fi
'';
# Kill a window or probe it for info
swayTools = pkgs.writeScript "swaytools" ''
# List the app name and whether or not it uses wayland
swayprop() {
selected_window=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)"' | slurp -r -c ${outputs.look.colors.prime} -B 00000066 -b 00000000)
if [ -n "$selected_window" ]; then
app_id=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | select("\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)" == "'"$selected_window"'") | .app_id')
system=$(sed 's/xdg_shell/Wayland/g; s/xwayland/Xorg/g' < <(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | select("\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)" == "'"$selected_window"'") | .shell'))
notify-send "$(echo -e "Window's app_id: $app_id\nWindow System: $system")"
fi
}
# Kill a selected window
swaykill() {
selected_window=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)"' | slurp -r -c ${outputs.look.colors.prime} -B 00000066 -b 00000000)
if [ -n "$selected_window" ]; then
pid=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | select("\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)" == "'"$selected_window"'") | .pid')
kill -9 "$pid"
fi
}
# Handle which tool we use
if [ "$1" == "--prop" ]; then
swayprop
elif [ "$1" == "--kill" ]; then
swaykill
fi
'';
in {
## Launcher keys
# LibreWolf profiles
"${primeMod}+F1" = ''exec librewolf -P Jimbo --name=JimBrowser | ${sendNotif} "Main Browser"'';
"${primeMod}+F2" = ''exec librewolf -P Alt --name=AltBrowser | ${sendNotif} "Alternate Browser"'';
"${primeMod}+F3" = ''exec librewolf -P Misc --name=MiscBrowser | ${sendNotif} "Miscellaneous Browser"'';
# Discord
"${primeMod}+F4" = ''exec vesktop --ozone-platform-hint=auto | ${sendNotif} "Discord"'';
# Games
"${primeMod}+F5" = ''exec steam | ${sendNotif} "Steam"'';
"${primeMod}+F6" = ''exec heroic | ${sendNotif} "Heroic Games"'';
# Looking glass for VMs
"${primeMod}+F7" = ''exec looking-glass-client input:rawMouse=yes | ${sendNotif} "Looking Glass"'';
# Virtual Machines
"${primeMod}+F10" = ''exec virt-manager | ${sendNotif} "Virtual Machines"'';
# BeMenu scripts
"${primeMod}+F11" = ''exec rofiscripts --scratchpads | ${sendNotif} "Scratchpads"'';
"${primeMod}+${secMod}+Ctrl+r" = ''exec rofiscripts --resolutions'';
# Open NixOS configuration files
"${primeMod}+F12" = ''exec foot ${outputs.cmd.nixcfg} | ${sendNotif} "Nix Config"'';
# Terminal, rofi, clipmenu, media script, power menu, show/hide waybar
"${primeMod}+Return" = ''exec foot'';
"${primeMod}+s" = ''exec rofi -show run -p Command'';
"${primeMod}+c" = ''exec clipman pick -t rofi'';
"${primeMod}+x" = ''exec rofiscripts --power'';
"${primeMod}+b" = ''exec pkill -USR1 waybar'';
"${primeMod}+Escape" = ''exec ${swayTools} --kill'';
# PCManFM, Emoji Picker, Rofi Launcher, Bluetooth, Ranger
"${primeMod}+Shift+t" = ''exec pcmanfm-qt'';
"${primeMod}+Shift+e" = ''exec BEMOJI_PICKER_CMD="rofi -dmenu -i -p Emoji" bemoji -n -P 0'';
"${primeMod}+Shift+s" = ''exec rofi -show drun -modi drun -drun-display-format {name} -show-icons -disable-history'';
"${primeMod}+Shift+b" = ''exec rofi-bluetooth'';
"${primeMod}+Shift+Return" = ''exec foot ranger'';
# Swaytools prop, colorpicker, obs-cmd
"${primeMod}+Ctrl+x" = ''exec ${swayTools} --prop'';
"${primeMod}+Ctrl+c" = ''exec ${pkgs.hyprpicker}/bin/hyprpicker -an && ${sendNotif} "Color copied to clipboard"'';
"${primeMod}+Ctrl+Prior" = ''exec ${pkgs.obs-cmd}/bin/obs-cmd scene switch "Main"'';
"${primeMod}+Ctrl+Next" = ''exec ${pkgs.obs-cmd}/bin/obs-cmd scene switch "Guest"'';
## Media keys
# Volume control
"XF86AudioRaiseVolume" = ''exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+'';
"XF86AudioLowerVolume" = ''exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-'';
# MPV volume control
"${secMod}+XF86AudioRaiseVolume" = ''exec mpc volume +3'';
"${secMod}+XF86AudioLowerVolume" = ''exec mpc volume -3'';
# Mute, Stop
"XF86AudioMute" = ''exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle'';
"XF86AudioStop" = ''exec mpc stop'';
# Play MPD, Firefox, or MPV
"XF86AudioPlay" = ''exec mpc toggle'';
"${secMod}+XF86AudioPlay" = ''exec playerctl --player=librewolf play-pause'';
"Ctrl+XF86AudioPlay" = ''exec playerctl --player=mpv play-pause'';
# Next/Previous
"XF86AudioNext" = ''exec mpc next'';
"XF86AudioPrev" = ''exec mpc prev'';
# Seek
"${secMod}+Shift+XF86AudioNext" = ''exec mpc seek +5'';
"${secMod}+Shift+XF86AudioPrev" = ''exec mpc seek -5'';
## Notification keys
# Toggle mako
"${primeMod}+n" = ''exec makotoggle'';
"${primeMod}+Shift+n" = ''exec makoctl restore'';
"${primeMod}+Ctrl+n" = ''exec makoctl dismiss -a'';
## Miscellaneous keys
# Screenshots
"Print" = ''exec swayshot --swappy'';
"${primeMod}+Shift+f" = ''exec swayshot --swappy'';
"Shift+Print" = ''exec swayshot --current'';
"Ctrl+Print" = ''exec swayshot --all'';
# Server SSH
"${primeMod}+Ctrl+Return" = ''exec foot ssh server -p 2222'';
# Display Brightness and Keyboard Brightness
"XF86MonBrightnessUp" = ''exec light -A 5'';
"XF86MonBrightnessDown" = ''exec light -U 5'';
"Shift+XF86MonBrightnessUp" = ''exec light -A 1'';
"Shift+XF86MonBrightnessDown" = ''exec light -U 1'';
"XF86KbdBrightnessUp" = ''exec light -s sysfs/leds/smc::kbd_backlight -A 5'';
"XF86KbdBrightnessDown" = ''exec light -s sysfs/leds/smc::kbd_backlight -U 5'';
## Window manager keys
"${primeMod}+q" = ''kill'';
"${primeMod}+Shift+r" = ''reload'';
# Switch to workspaces
"${primeMod}+grave" = ''workspace ${outputs.ws.w0}'';
"${primeMod}+1" = ''workspace ${outputs.ws.w1}'';
"${primeMod}+2" = ''workspace ${outputs.ws.w2}'';
"${primeMod}+3" = ''workspace ${outputs.ws.w3}'';
"${primeMod}+4" = ''workspace ${outputs.ws.w4}'';
"${primeMod}+5" = ''workspace ${outputs.ws.w5}'';
"${primeMod}+6" = ''workspace ${outputs.ws.w6}'';
"${primeMod}+7" = ''workspace ${outputs.ws.w7}'';
"${primeMod}+8" = ''workspace ${outputs.ws.w8}'';
"${primeMod}+9" = ''workspace ${outputs.ws.w9}'';
# Switch to alternate workspaces
"${secMod}+F1" = ''workspace ${outputs.ws.w1a}'';
"${secMod}+F2" = ''workspace ${outputs.ws.w2a}'';
"${secMod}+F3" = ''workspace ${outputs.ws.w3a}'';
"${secMod}+F4" = ''workspace ${outputs.ws.w4a}'';
"${secMod}+F5" = ''workspace ${outputs.ws.w5a}'';
"${secMod}+F6" = ''workspace ${outputs.ws.w6a}'';
"${secMod}+F7" = ''workspace ${outputs.ws.w7a}'';
"${secMod}+F8" = ''workspace ${outputs.ws.w8a}'';
"${secMod}+F9" = ''workspace ${outputs.ws.w9a}'';
# Move window to and focus new workspace
"${primeMod}+Shift+grave" = ''move container to workspace ${outputs.ws.w0}; workspace ${outputs.ws.w0}'';
"${primeMod}+Shift+1" = ''move container to workspace ${outputs.ws.w1}; workspace ${outputs.ws.w1}'';
"${primeMod}+Shift+2" = ''move container to workspace ${outputs.ws.w2}; workspace ${outputs.ws.w2}'';
"${primeMod}+Shift+3" = ''move container to workspace ${outputs.ws.w3}; workspace ${outputs.ws.w3}'';
"${primeMod}+Shift+4" = ''move container to workspace ${outputs.ws.w4}; workspace ${outputs.ws.w4}'';
"${primeMod}+Shift+5" = ''move container to workspace ${outputs.ws.w5}; workspace ${outputs.ws.w5}'';
"${primeMod}+Shift+6" = ''move container to workspace ${outputs.ws.w6}; workspace ${outputs.ws.w6}'';
"${primeMod}+Shift+7" = ''move container to workspace ${outputs.ws.w7}; workspace ${outputs.ws.w7}'';
"${primeMod}+Shift+8" = ''move container to workspace ${outputs.ws.w8}; workspace ${outputs.ws.w8}'';
"${primeMod}+Shift+9" = ''move container to workspace ${outputs.ws.w9}; workspace ${outputs.ws.w9}'';
# Move window to and focus new alternate workspace
"${secMod}+Shift+F1" = ''move container to workspace ${outputs.ws.w1a}; workspace ${outputs.ws.w1a}'';
"${secMod}+Shift+F2" = ''move container to workspace ${outputs.ws.w2a}; workspace ${outputs.ws.w2a}'';
"${secMod}+Shift+F3" = ''move container to workspace ${outputs.ws.w3a}; workspace ${outputs.ws.w3a}'';
"${secMod}+Shift+F4" = ''move container to workspace ${outputs.ws.w4a}; workspace ${outputs.ws.w4a}'';
"${secMod}+Shift+F5" = ''move container to workspace ${outputs.ws.w5a}; workspace ${outputs.ws.w5a}'';
"${secMod}+Shift+F6" = ''move container to workspace ${outputs.ws.w6a}; workspace ${outputs.ws.w6a}'';
"${secMod}+Shift+F7" = ''move container to workspace ${outputs.ws.w7a}; workspace ${outputs.ws.w7a}'';
"${secMod}+Shift+F8" = ''move container to workspace ${outputs.ws.w8a}; workspace ${outputs.ws.w8a}'';
"${secMod}+Shift+F9" = ''move container to workspace ${outputs.ws.w9a}; workspace ${outputs.ws.w9a}'';
# Change focus across windows
"${primeMod}+Up" = ''focus up'';
"${primeMod}+Down" = ''focus down'';
"${primeMod}+Left" = ''focus left'';
"${primeMod}+Right" = ''focus right'';
# Switch focus across outputs
"${primeMod}+j" = ''focus output ${outputs.displays.d2}'';
"${primeMod}+k" = ''focus output ${outputs.displays.d1}'';
"${primeMod}+l" = ''focus output ${outputs.displays.d3}'';
# Move focused window
"${primeMod}+Shift+Up" = ''move up ${resizeAmount} px'';
"${primeMod}+Shift+Down" = ''move down ${resizeAmount} px'';
"${primeMod}+Shift+Left" = ''move left ${resizeAmount} px'';
"${primeMod}+Shift+Right" = ''move right ${resizeAmount} px'';
# Move window across outputs
"${primeMod}+Shift+j" = ''move output ${outputs.displays.d2}; focus output ${outputs.displays.d2}'';
"${primeMod}+Shift+k" = ''move output ${outputs.displays.d1}; focus output ${outputs.displays.d1}'';
"${primeMod}+Shift+l" = ''move output ${outputs.displays.d3}; focus output ${outputs.displays.d3}'';
# Change focus between floating/tiled, toggle floating
"${primeMod}+space" = ''focus mode_toggle'';
"${primeMod}+Shift+space" = ''floating toggle'';
# Allow a window to be visible on all workspaces, toggle border
"${primeMod}+0" = ''exec ${pinWindow}'';
# Toggle fullscreen
"${primeMod}+f" = ''fullscreen toggle'';
"${primeMod}+${secMod}+Ctrl+f" = ''fullscreen toggle global'';
# Change container layout
"${primeMod}+w" = ''layout toggle split'';
"${primeMod}+e" = ''layout toggle tabbed stacking'';
# Change split direction
"${primeMod}+h" = ''split h'';
"${primeMod}+v" = ''split v'';
# Focus parent / child
"${primeMod}+a" = ''focus parent'';
"${primeMod}+d" = ''focus child'';
# Resize windows
"${primeMod}+${secMod}+Up" = ''resize grow height ${resizeAmount} px or 5 ppt'';
"${primeMod}+${secMod}+Down" = ''resize shrink height ${resizeAmount} px or 5 ppt'';
"${primeMod}+${secMod}+Left" = ''resize shrink width ${resizeAmount} px or 5 ppt'';
"${primeMod}+${secMod}+Right" = ''resize grow width ${resizeAmount} px or 5 ppt'';
# Adjust gap size
"${primeMod}+Shift+equal" = ''gaps inner current set 5'';
"${primeMod}+equal" = ''gaps inner current plus 5'';
"${primeMod}+minus" = ''gaps inner current minus 5'';
# Scratchpads
"Ctrl+Shift+Escape" = ''[app_id="gotop"] scratchpad show, move position center, resize set 1216 888'';
"${primeMod}+Shift+m" = ''[app_id="music"] scratchpad show, move position center, resize set 1006 657'';
"${primeMod}+Shift+v" = ''[app_id="sound"] scratchpad show, move position center, resize set 1000 800'';
"${primeMod}+Shift+Backslash" = ''[app_id="com.github.wwmm.easyeffects"] scratchpad show, move position center, resize set 1000 800'';
};
};
};
}

132
home/sway/rules.nix Normal file
View file

@ -0,0 +1,132 @@
{config, pkgs, outputs, ...}: {
# Enable Sway and write some scripts
wayland.windowManager.sway = {
config = {
# Assign workspaces to outputs
workspaceOutputAssign = let
workspaces1 = [
"${outputs.ws.w0}"
"${outputs.ws.w1}"
"${outputs.ws.w2}"
"${outputs.ws.w3}"
"${outputs.ws.w1a}"
"${outputs.ws.w2a}"
"${outputs.ws.w3a}"
];
workspaces2 = [
"${outputs.ws.w4}"
"${outputs.ws.w5}"
"${outputs.ws.w6}"
"${outputs.ws.w4a}"
"${outputs.ws.w5a}"
"${outputs.ws.w6a}"
];
workspaces3 = [
"${outputs.ws.w7}"
"${outputs.ws.w8}"
"${outputs.ws.w9}"
"${outputs.ws.w7a}"
"${outputs.ws.w8a}"
"${outputs.ws.w9a}"
];
assign = output: workspaces:
map (workspace: {
inherit workspace;
inherit output;
})
workspaces;
in
(assign "${outputs.displays.d1}" workspaces1) ++
(assign "${outputs.displays.d2}" workspaces2) ++
(assign "${outputs.displays.d3}" workspaces3);
# Rules
window = {
border = outputs.look.border.int;
titlebar = false;
commands = [
# Scratchpads
{
criteria = {con_mark = "scratchpad";};
command = ''floating enable, sticky enable, move scratchpad, mark borderless'';
}
{
criteria = {app_id = "gotop";};
command = ''mark scratchpad'';
}
{
criteria = {app_id = "music";};
command = ''mark scratchpad'';
}
{
criteria = {app_id = "sound";};
command = ''mark scratchpad'';
}
{
criteria = {app_id = "com.github.wwmm.easyeffects";};
command = ''mark scratchpad, opacity 0.9'';
}
# Create a "Scratchpad" for apps I don't want to be seen when launched
{
criteria = {con_mark = "hiddenaway";};
command = ''move scratchpad'';
}
# Give apps that don't have them borders
{
criteria = {con_mark = "borderless";};
command = ''border pixel ${outputs.look.border.string}'';
}
{
criteria = {app_id = "com.github.wwmm.easyeffects";};
command = ''mark borderless'';
}
{
criteria = {class = "steam";};
command = ''mark borderless'';
}
{
criteria = {app_id = "swappy";};
command = ''mark borderless'';
}
{
criteria = {app_id = "virt-manager";};
command = ''mark borderless'';
}
{
criteria = {window_role = "pop-up";};
command = ''mark borderless'';
}
# Floating or fullscreen rules
{
criteria = {app_id = "float";};
command = ''floating enable'';
}
{
criteria = {title = "^GlobalShot";};
command = ''floating enable, fullscreen enable global'';
}
];
};
assigns = {
# Brooutputs.wsers
"${outputs.ws.w1}" = [{app_id = "JimBrooutputs.wser";}];
"${outputs.ws.w1a}" = [{app_id = "AltBrooutputs.wser";}];
# Communication
"${outputs.ws.w3a}" = [{class = "zoom";}];
"${outputs.ws.w7}" = [{app_id = "MiscBrooutputs.wser";} {app_id = "vesktop";} {class = "vesktop";}];
"${outputs.ws.w8}" = [{app_id = "Element";} {class = "Element";}];
"${outputs.ws.w9}" = [{app_id = "thunderbird";}];
# Else
"${outputs.ws.w2}" = [{class = "steam";} {app_id = "heroic";}];
"${outputs.ws.w2a}" = [{app_id = "looking-glass-client";}];
"${outputs.ws.w4a}" = [{app_id = "com.obsproject.Studio";}];
};
focus.newWindow = "focus";
};
};
}

38
home/sway/sway.nix Normal file
View file

@ -0,0 +1,38 @@
{config, pkgs, outputs, ...}: {
# Import modules
imports = [
#"./swayfx.nix"
./hardware.nix
./theme.nix
./hotkeys.nix
./rules.nix
./autostart.nix
./waybar.nix
./swayshot.nix
];
# Enable Sway and write some scripts
wayland.windowManager.sway = {
enable = true;
package = null;
wrapperFeatures.gtk = true;
checkConfig = false;
extraConfig = ''
# Options I can't find in Nix yet
default_floating_border pixel ${outputs.look.border.string}
hide_edge_borders --i3 smart
titlebar_padding 10 1
primary_selection disabled
# Include extra window icons
include ${pkgs.fetchurl {
url = "https://raw.githubusercontent.com/iguanajuice/sway-font-awesome/6b7a9d08974eea1b9cddb8d444e1c89d6837083a/icons";
sha256 = "09ki5qw1h91kd33k3fwzq7cb6ck8sq4haswgizrsy387sfr2a75x";
}}
# Switch to workspace 1
workspace ${outputs.ws.w7}
workspace ${outputs.ws.w1}
'';
};
}

14
home/sway/swayfx.nix Normal file
View file

@ -0,0 +1,14 @@
{config, pkgs, ...}: {
# Enable Sway and write some scripts
wayland.windowManager.sway = {
package = pkgs.unstable.sway;
extraConfig = ''
# SwayFX specific options
blur enable
blur_passes 3
blur_radius 5
layer_effects 'rofi' blur enable
layer_effects 'notifications' blur enable; blur_ignore_transparent enable
'';
};
}

63
home/sway/swaylock.nix Normal file
View file

@ -0,0 +1,63 @@
{config, pkgs, outputs, ...}: let
swayLock = pkgs.writeScriptBin "swaylock" ''
# Set the lock script
lockscript() {
BLANK='#00000000'
CLEAR='#FFFFFF22'
DEFAULT='#${outputs.look.colors.prime}FF'
TEXT='#FFFFFFFF'
WRONG='#${outputs.look.colors.split}FF'
VERIFYING='#${outputs.look.colors.accent}FF'
${pkgs.swaylock-effects}/bin/swaylock -f -e \
--key-hl-color=$VERIFYING \
--bs-hl-color=$WRONG \
\
--ring-clear-color=$CLEAR \
--ring-ver-color=$VERIFYING \
--ring-wrong-color=$WRONG \
--ring-color=$DEFAULT \
--ring-clear-color=$VERIFYING \
\
--inside-color=$CLEAR \
--inside-ver-color=$CLEAR \
--inside-wrong-color=$CLEAR \
--inside-clear-color=$CLEAR \
\
--text-color=$TEXT \
--text-clear-color=$TEXT \
--text-ver-color=$TEXT \
--text-caps-lock-color=$TEXT \
--text-wrong-color=$TEXT \
\
--indicator \
--indicator-radius=80 \
--image=~/.wallpapers/lock.png \
--clock \
--font=${outputs.look.fonts.main} \
--font-size=30 \
--timestr="%I:%M%p" \
--datestr="%a %b %d %Y"
}
# Handle whether to lock or sleep
if [ "$1" == "--sleep" ]; then
lockscript &
exec ${pkgs.swayidle}/bin/swayidle -w \
timeout 1 'swaymsg "output * dpms off"' \
resume 'swaymsg "output * dpms on"; pkill -9 swayidle'
else
lockscript
fi
'';
in {
# Enable Sway and write some scripts
home.packages = with pkgs; [
swayLock
];
# Enable Sway lock on startup
wayland.windowManager.sway.config.startup = [
{command = "swaylock";}
];
}

84
home/sway/swayshot.nix Normal file
View file

@ -0,0 +1,84 @@
{pkgs, outputs, ...}: {
home.packages = let
# Use grim and slurp to take screenshots in multiple ways
swayShot = pkgs.writeScriptBin "swayshot" ''
# Swappy
handle_swappy() {
# Create an imv window to act as a static screen
grim -t jpeg - | imv -w "GlobalShot" - & imv_pid=$!
# Capture the screenshot of the selected area and save to a temporary file
selected_area=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"'\
| XCURSOR_SIZE=40 slurp -w ${outputs.look.border.string} -c ${outputs.look.colors.prime} -B 00000066 -b 00000099)
temp_file=$(mktemp -u).png
grim -g "$selected_area" "$temp_file"
# Kill the imv window
kill $imv_pid
# Copy the screenshot to the clipboard
swappy -f - < "$temp_file"
# Clean up the temporary file
rm "$temp_file"
}
# Current
handle_current() {
# Take a screenshot and save it to the temporary file
temp_file=$(mktemp -u).png
grim -o $(swaymsg -t get_outputs | jq -r '.[] | select(.focused) | .name') "$temp_file"
# Check if the screenshot was successfully taken
if [ $? -eq 0 ]; then
# Copy the screenshot to the clipboard
wl-copy < "$temp_file"
# Show a notification with the screenshot
notify-send -i "$temp_file" "Current screen copied."
# Remove the temporary file
rm "$temp_file"
else
# If the screenshot capture failed, show an error notification
notify-send "Error: Unable to capture screenshot."
fi
}
# All screens
handle_all() {
# Take a screenshot and save it to the temporary file
temp_file=$(mktemp -u).png
grim -t jpeg "$temp_file"
# Check if the screenshot was successfully taken
if [ $? -eq 0 ]; then
# Copy the screenshot to the clipboard
wl-copy < "$temp_file"
# Show a notification with the screenshot
notify-send -i "$temp_file" "All screen copied."
# Remove the temporary file
rm "$temp_file"
else
# If the screenshot capture failed, show an error notification
notify-send "Error: Unable to capture screenshot."
fi
}
# Check for command-line arguments
if [ "$1" == "--swappy" ]; then
handle_swappy
elif [ "$1" == "--current" ]; then
handle_current
elif [ "$1" == "--all" ]; then
handle_all
else
echo "Please use the arguments swappy, current, or all."
fi
'';
in with pkgs; [
swayShot
];
}

50
home/sway/theme.nix Normal file
View file

@ -0,0 +1,50 @@
{config, pkgs, outputs, ...}: {
# Enable Sway and write some scripts
wayland.windowManager.sway = {
enable = true;
#package = pkgs.unstable.sway;
wrapperFeatures.gtk = true;
checkConfig = false;
config = {
# Theming settings
colors = {
focused = {
border = "#${outputs.look.colors.prime}";
background = "#${outputs.look.colors.prime}";
text = "#FFFFFF";
indicator = "#${outputs.look.colors.actSplit}";
childBorder = "#${outputs.look.colors.prime}";
};
focusedInactive = {
border = "#${outputs.look.colors.accent}";
background = "#${outputs.look.colors.accent}";
text = "#${outputs.look.colors.text}";
indicator = "#${outputs.look.colors.split}";
childBorder = "#${outputs.look.colors.accent}";
};
unfocused = {
border = "#${outputs.look.colors.dark}";
background = "#${outputs.look.colors.dark}";
text = "#${outputs.look.colors.text}";
indicator = "#${outputs.look.colors.split}";
childBorder = "#${outputs.look.colors.split}";
};
urgent = {
border = "#${outputs.look.colors.urgent}";
background = "#${outputs.look.colors.urgent}";
text = "#${outputs.look.colors.text}";
indicator = "#${outputs.look.colors.urgent}";
childBorder = "#${outputs.look.colors.urgent}";
};
};
fonts = {
names = ["${outputs.look.fonts.main}"];
size = 10.5;
};
gaps = {
inner = 5;
smartGaps = true;
};
};
};
}

478
home/sway/waybar.nix Normal file
View file

@ -0,0 +1,478 @@
{pkgs, outputs, ...}: {
programs.waybar = let
swayWorkspacesModule = {
format = "{name}";
enable-bar-scroll = true;
warp-on-scroll = false;
disable-scroll-wraparound = true;
};
swayWindowsModule = {
icon = true;
icon-size = 15;
all-outputs = true;
tooltip = false;
rewrite = {
"(.*) LibreWolf" = " $1";
"LibreWolf" = " Firefox";
"(.*) - LibreWolf Firefox" = "󰗃 $1";
};
};
pulseModule = {
format = "{icon} {volume}%";
format-bluetooth = "{icon} {volume}%";
format-muted = " muted";
format-icons = {
headphone = "󰋋 ";
headset = "󰋋 ";
default = [" " " "];
};
on-click = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
on-click-middle = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 100%";
on-click-right = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 60%";
ignored-sinks = ["Easy Effects Sink" "USB FS AUDIO Analog Stereo"];
};
# CPU, Ram and Vram
cpuModule = {
format = " {usage}%";
interval = 3;
};
ramModule = {
format = " {used}G";
tooltip = false;
};
vramModule = {
exec = pkgs.writeScript "vramScript" ''
# Don't run the script if running on integrated graphics
if lspci -k | grep "Kernel driver in use: nvidia" &> /dev/null || lspci -k | grep "Kernel driver in use: amdgpu" &> /dev/null; then
# Run the nvidia-smi command and capture the VRAM usage and GPU utilization output
if lspci -k | grep "Kernel driver in use: nvidia" &> /dev/null; then
vram_usage_mb=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits)
temperature=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits)
# Check the drm memory if an AMD GPU is present
elif lspci -k | grep "Kernel driver in use: amdgpu" &> /dev/null; then
vram_usage_mb=$(echo "$(cat /sys/class/drm/card0/device/mem_info_vram_used || cat /sys/class/drm/card1/device/mem_info_vram_used) / 1024 / 1024" | bc)
temperature=$(sensors | grep 'edge' | awk '{print $2}' | sed 's/[^0-9.-]//g')
fi
# Check if VRAM usage is under 1GB
if [ $vram_usage_mb -lt 1024 ]; then
vram_usage_display="$(echo $vram_usage_mb)M"
else
# Convert MB to GiB
vram_usage_gib=$(bc <<< "scale=2; $vram_usage_mb / 1024")
vram_usage_display="$(echo $vram_usage_gib)G"
fi
# Print the VRAM usage in MB or GiB, and include GPU utilization and temperature
echo "{\"text\":\"󰢮 $(echo $vram_usage_display)\",\"tooltip\":\"$(echo $temperature)°C\"}"
else
:
fi
'';
format = "{}";
return-type = "json";
interval = 3;
};
# Clocks
longClockModule = {
exec = pkgs.writeScript "longClock" ''
# Long clock format, with a numeric date and military time tooltip
time=$(date +'%a %b %d %l:%M:%S%p' | tr -s ' ')
date=$(date "+%Y-%m-%d")
echo "{\"text\":\" $time\",\"tooltip\":\"$date\"}"
'';
on-click = ''wl-copy $(date "+%Y-%m-%d-%H%M%S"); notify-send "Date copied."'';
format = "{}";
return-type = "json";
interval = 1;
tooltip = true;
};
shortClockModule = {
exec = "echo ' '$(date +'%l:%M%p' | sed 's/^ //')";
on-click = ''wl-copy $(date "+%Y-%m-%d-%H%M%S"); notify-send "Date copied."'';
interval = 60;
tooltip = false;
};
# Tray, gamemode, bluetooth, and network tray modules
trayModule = {
spacing = 5;
};
networkModule = {
format-ethernet = "󰈀";
format-wifi = "";
format-disconnected = "󰖪";
format-linked = "";
tooltip-format-ethernet = "{ipaddr}\n{ifname} ";
tooltip-format-wifi = "{ipaddr}\n{essid} ({signalStrength}%)";
tooltip-format-disconnected = "Disconnected";
};
bluetoothModule = {
format = "";
format-disabled = "";
format-no-controller = "";
tooltip-format-on = "No devices connected.";
tooltip-format-connected = "{num_connections} connected\n{device_enumerate}";
tooltip-format-enumerate-connected = "{device_alias}";
tooltip-format-enumerate-connected-battery = "{device_alias} {device_battery_percentage}%";
on-click = "rofi-bluetooth";
};
scratchpadModule = {
format = " {count}";
show-empty = false;
tooltip = true;
tooltip-format = "{title}";
};
gamemodeModule = {
format = "{glyph}";
glyph = "󰖺";
hide-not-running = true;
use-icon = true;
icon-spacing = 3;
icon-size = 19;
tooltip = true;
tooltip-format = "Gamemode On";
};
# Special per-bar modules
mediaModule = {
exec-if = "mpc status | grep -q '^\\[playing\\] \\|^\\[paused\\]'";
exec = pkgs.writeScript "mpvMetadata" ''
get_metadata() {
mpc --format "%file%" | head -n 1 | sed -E 's/\.(mp3|mp4|m4a|mov|flac|opus|oga)$//; s/&/&amp;/g'
}
truncate_string() {
local str="$1"
local max_length=30
if [ $(expr length "$str") -gt $max_length ]; then
str=$(expr substr "$str" 1 $max_length)...
fi
echo "$str"
}
if mpc status 2>/dev/null | grep -q playing; then
song_name=$(get_metadata | awk -F ' - ' '{print $2}')
if [ -z "$song_name" ]; then
song_name=$(get_metadata)
fi
echo "{\"text\":\"$(truncate_string " $song_name")\",\"tooltip\":\"$(get_metadata)\"}"
elif mpc status 2>/dev/null | grep -q paused; then
artist_name=$(get_metadata | awk -F ' - ' '{print $1}')
if [ -z "$artist_name" ]; then
artist_name=$(get_metadata)
fi
echo "{\"text\":\"$(truncate_string " $artist_name")\",\"tooltip\":\"$(get_metadata)\",\"class\":\"paused\"}"
fi
'';
format = "{}";
return-type = "json";
interval = 2;
max-length = 30;
on-click = "mpc toggle";
};
notificationModule = {
exec = pkgs.writeScript "notificationScript" ''
# Run makoctl mode and store the output in a variable
mode_output=$(makoctl mode)
# Extract the second line after "default"
mode_line=$(echo "$mode_output" | sed -n '/default/{n;p}')
# Print the notification status with the tooltip
if [[ "$mode_line" == "do-not-disturb" ]]; then
printf '{"text":"󱆥 Off","class":"disabled","tooltip":"Notifications Disabled."}'
else
printf '{"text":" On","tooltip":"Notifications Enabled."}';
fi
'';
format = "{}";
return-type = "json";
interval = 2;
on-click = "makotoggle";
};
weatherModule = {
exec = let
weatherConf = pkgs.writeText "weather.jsonc" ''
{
"logo": {
"source": "none"
},
"modules": [
{
"type": "weather",
"outputFormat": "%0A%t%0A%C%0A%l"
}
]
}
'';
in pkgs.writeScript "weatherScript" ''
# Fetch weather data
fetch=$(fastfetch -c ${weatherConf} | sed 's/[[:space:]]*$//')
temp=$(echo "$fetch" | sed -n '2s/^\+//p')
condition=$(echo "$fetch" | sed -n '3p')
location=$(echo "$fetch" | sed -n '4p')
# Map weather conditions to emojis
case "$condition" in
"Clear"|"Sunny") emoji="";;
"Cloudy"|"Partly cloudy"|"Overcast") emoji="";;
"Rain") emoji="🌧";;
"Drizzle") emoji="🌦";;
"Thunderstorm") emoji="";;
"Snow") emoji="";;
"Mist"|"Fog"|"Haze") emoji="🌫";;
*) emoji="🌍";; # Default emoji for unknown
esac
# Display weather emoji and temperature
echo {\"text\":\"$emoji $temp\",\"tooltip\":\"$location: $condition\"}
'';
format = "<span font_size='11pt'>{}</span>";
return-type = "json";
interval = 150;
};
# Laptop modules
backlightModule = {
format = "{icon} {percent}%";
format-icons = ["" "󰖨"];
tooltip = false;
};
batteryModule = {
interval = 60;
states = {
warning = 30;
critical = 15;
};
format = "{icon} {capacity}%";
format-icons = ["" "" "" "" ""];
};
in {
enable = true;
settings = {
display1 = {
name = "bar1";
position = "top";
layer = "bottom";
output = [outputs.displays.d1 "VGA-1"];
modules-left = ["sway/workspaces" "sway/window"];
modules-right = [
"pulseaudio"
"cpu"
"memory"
"custom/vram"
"custom/clock-long"
"gamemode"
"sway/scratchpad"
"tray"
"bluetooth"
"network"
];
"sway/workspaces" = swayWorkspacesModule;
"sway/window" = swayWindowsModule;
"pulseaudio" = pulseModule;
"cpu" = cpuModule;
"memory" = ramModule;
"custom/vram" = vramModule;
"custom/clock-long" = longClockModule;
"gamemode" = gamemodeModule;
"sway/scratchpad" = scratchpadModule;
"tray" = trayModule;
"bluetooth" = bluetoothModule;
"network" = networkModule // {interface = "enp*";};
};
display2 = {
name = "bar2";
position = "top";
layer = "bottom";
output = [outputs.displays.d2];
modules-left = ["sway/workspaces" "sway/window"];
modules-right = [
"pulseaudio"
"custom/media"
"custom/notifs"
"cpu"
"memory"
"custom/vram"
"custom/clock-long"
];
"sway/workspaces" = swayWorkspacesModule;
"sway/window" = swayWindowsModule;
"pulseaudio" = pulseModule;
"custom/media" = mediaModule;
"custom/notifs" = notificationModule;
"cpu" = cpuModule;
"memory" = ramModule;
"custom/vram" = vramModule;
"custom/clock-long" = longClockModule;
};
display3 = {
name = "bar3";
position = "top";
layer = "bottom";
output = [outputs.displays.d3];
modules-left = ["sway/workspaces" "sway/window"];
modules-right = [
"pulseaudio"
"custom/weather"
"cpu"
"memory"
"custom/vram"
"custom/clock-short"
];
"sway/workspaces" = swayWorkspacesModule;
"sway/window" = swayWindowsModule;
"pulseaudio" = pulseModule;
"custom/weather" = weatherModule;
"cpu" = cpuModule;
"memory" = ramModule;
"custom/vram" = vramModule;
"custom/clock-short" = shortClockModule;
};
displayLap = {
name = "laptop";
position = "top";
layer = "bottom";
output = ["eDP-1" "LVDS-1" "DSI-1" "HDMI-A-1"];
modules-left = ["sway/workspaces" "sway/window"];
modules-right = [
"pulseaudio"
"custom/media"
"custom/notifs"
"custom/weather2"
"cpu"
"memory"
"custom/vram"
"backlight"
"battery"
"custom/clock-long"
"gamemode"
"sway/scratchpad"
"tray"
"bluetooth"
"network"
];
"sway/workspaces" = swayWorkspacesModule;
"sway/window" = swayWindowsModule;
"pulseaudio" = pulseModule;
"custom/media" = mediaModule;
"custom/notifs" = notificationModule;
"custom/weather2" = weatherModule;
"cpu" = cpuModule;
"memory" = ramModule;
"custom/vram" = vramModule;
"backlight" = backlightModule;
"battery" = batteryModule;
"custom/clock-long" = longClockModule;
"sway/scratchpad" = scratchpadModule;
"tray" = trayModule;
"bluetooth" = bluetoothModule;
"network" = networkModule;
};
};
style = ''
* {
border: 0;
border-radius: 0;
min-height: 0;
font-family: ${outputs.look.fonts.main}, ${outputs.look.fonts.nerd};
font-size: 15.5px;
color: #${outputs.look.colors.text};
}
#waybar {
background: #${outputs.look.colors.dark};
}
#workspaces {
padding: 0 6px 0 0;
}
#tray {
padding: 0 2px 0 5px;
}
#network {
padding: 0 10px 0 4px;
}
#network.disconnected,#bluetooth.off {
color: #424242;
}
#bluetooth {
margin: 0 6px 0 4px;
font-size: 13.4px;
}
#workspaces button {
padding: 0 3px;
color: white;
border-bottom: 3px solid transparent;
min-width: 20px;
}
#workspaces button.visible {
border-bottom: 3px solid #${outputs.look.colors.prime};
background: #${outputs.look.colors.mid};
}
#workspaces button.urgent {
border-bottom: 3px solid #${outputs.look.colors.urgent};
}
#workspaces button:hover {
box-shadow: none;
background: #${outputs.look.colors.light};
}
#scratchpad {
margin-left: 2px;
}
#cpu, #memory, #custom-vram, #custom-media, #custom-clock-long, #custom-clock-short, #backlight, #battery, #custom-weather, #custom-weather2, #custom-notifs {
margin: 0 5px 0 2px;
}
#cpu {
border-bottom: 3px solid #f90000;
}
#memory {
border-bottom: 3px solid #4bffdc;
}
#custom-vram {
border-bottom: 3px solid #33FF00;
}
#custom-media {
border-bottom: 3px solid #ffb066;
}
#custom-clock-long {
border-bottom: 3px solid #0a6cf5;
}
#custom-clock-short {
border-bottom: 3px solid #0a6cf5;
}
#backlight {
border-bottom: 3px solid #5ffca3;
}
#battery {
border-bottom: 3px solid #fcfc16;
}
#custom-media.paused {
color: #888;
}
#custom-weather {
border-bottom: 3px solid #${outputs.look.colors.prime};
}
#custom-weather2 {
border-bottom: 3px solid #c75bd3;
}
#custom-notifs {
border-bottom: 3px solid #${outputs.look.colors.prime};
}
#custom-notifs.disabled {
color: #888;
}
#pulseaudio {
margin-right: 5px;
}
#pulseaudio.muted {
color: #424242;
}
'';
};
}