# ── Variables ───────────────────────────────────────────────────────────────── set $mod Mod4 set $term ghostty set $menu fuzzel # ── Appearance ──────────────────────────────────────────────────────────────── font mono 8 default_border pixel 1 default_floating_border pixel 1 gaps inner 0 gaps outer 0 # Gruvbox dark colors # class border bg text indicator child_border client.focused #fabd2f #282828 #ebdbb2 #fabd2f #fabd2f client.focused_inactive #3c3836 #282828 #928374 #3c3836 #3c3836 client.unfocused #3c3836 #282828 #928374 #3c3836 #3c3836 client.urgent #fb4934 #282828 #ebdbb2 #fb4934 #fb4934 # ── Input ───────────────────────────────────────────────────────────────────── input type:keyboard { xkb_layout us xkb_variant altgr-intl xkb_options caps:escape,compose:rctrl repeat_delay 300 repeat_rate 50 } input type:touchpad { tap enabled natural_scroll enabled dwt enabled } # ── Behavior ────────────────────────────────────────────────────────────────── focus_follows_mouse yes mouse_warping container seat * hide_cursor 3000 seat * xcursor_theme Adwaita 24 # ── Output ──────────────────────────────────────────────────────────────────── output * bg #282828 solid_color # Per-output enable/disable/position is written by display-toggle.sh and # re-read by sway on every reload. Sway's `include` silently no-ops if the # file doesn't exist (first boot, before the script has run). include ~/.config/sway/outputs.conf # ── Window rules ────────────────────────────────────────────────────────────── for_window [class="feh"] floating enable for_window [app_id="imv"] floating enable for_window [app_id="floating"] floating enable for_window [class="Tor Browser"] floating enable for_window [app_id="org.mozilla.thunderbird" title=".*Mozilla Thunderbird$"] mark --add tb-main for_window [shell=".*"] inhibit_idle fullscreen # virt-viewer / virt-manager grab the Mod key via the keyboard-shortcuts-inhibit # Wayland protocol. Refuse so $mod+... bindings keep working while the VM has focus. for_window [app_id="virt-viewer"] shortcuts_inhibitor disable for_window [app_id="remote-viewer"] shortcuts_inhibitor disable for_window [app_id="virt-manager"] shortcuts_inhibitor disable for_window [app_id="^[Ww]aydroid.*"] shortcuts_inhibitor disable # ── Standard keybinds (sway defaults) ───────────────────────────────────────── bindsym $mod+Return exec $term bindsym $mod+Shift+Return exec $term -e yazi bindsym $mod+Shift+q kill bindsym $mod+d exec $menu bindsym $mod+Shift+b exec flatpak run io.gitlab.librewolf-community # Navigation bindsym $mod+h focus left bindsym $mod+j focus down bindsym $mod+k focus up bindsym $mod+l focus right # Move windows bindsym $mod+Shift+h move left bindsym $mod+Shift+j move down bindsym $mod+Shift+k move up bindsym $mod+Shift+l move right # Workspaces # Re-pressing $mod+N (or clicking the active workspace in waybar) jumps back # to the previously focused workspace — bspwm-style toggle. workspace_auto_back_and_forth yes bindsym $mod+1 workspace number 1 bindsym $mod+2 workspace number 2 bindsym $mod+3 workspace number 3 bindsym $mod+4 workspace number 4 bindsym $mod+5 workspace number 5 bindsym $mod+6 workspace number 6 bindsym $mod+7 workspace number 7 bindsym $mod+8 workspace number 8 bindsym $mod+9 workspace number 9 bindsym $mod+0 workspace number 10 bindsym $mod+Shift+1 move container to workspace number 1 bindsym $mod+Shift+2 move container to workspace number 2 bindsym $mod+Shift+3 move container to workspace number 3 bindsym $mod+Shift+4 move container to workspace number 4 bindsym $mod+Shift+5 move container to workspace number 5 bindsym $mod+Shift+6 move container to workspace number 6 bindsym $mod+Shift+7 move container to workspace number 7 bindsym $mod+Shift+8 move container to workspace number 8 bindsym $mod+Shift+9 move container to workspace number 9 bindsym $mod+Shift+0 move container to workspace number 10 # Layout bindsym $mod+b splith bindsym $mod+v splitv bindsym $mod+s layout stacking bindsym $mod+w layout tabbed bindsym $mod+e layout toggle split bindsym $mod+f fullscreen bindsym $mod+Shift+space floating toggle bindsym $mod+space focus mode_toggle bindsym $mod+a focus parent # Cycle windows within tabbed/stacked container (monocle-style) bindsym $mod+bracketright focus next bindsym $mod+bracketleft focus prev # Scratchpad bindsym $mod+Shift+minus move scratchpad bindsym $mod+minus scratchpad show # Resize mode mode "resize" { bindsym h resize shrink width 10px bindsym j resize grow height 10px bindsym k resize shrink height 10px bindsym l resize grow width 10px bindsym Escape mode "default" bindsym Return mode "default" } bindsym $mod+r mode "resize" # Reload / session bindsym $mod+Shift+c reload bindsym $mod+Shift+e exec ~/.config/sway/power-menu.sh # ── Personal keybinds ───────────────────────────────────────────────────────── # Workspace cycling bindsym $mod+Tab workspace next_on_output bindsym $mod+Shift+Tab workspace prev_on_output # Volume bindsym XF86AudioRaiseVolume exec ~/.config/sway/vol-osd.sh up bindsym XF86AudioLowerVolume exec ~/.config/sway/vol-osd.sh down bindsym XF86AudioMute exec ~/.config/sway/vol-osd.sh mute bindsym $mod+Ctrl+k exec ~/.config/sway/vol-osd.sh up bindsym $mod+Ctrl+j exec ~/.config/sway/vol-osd.sh down bindsym $mod+Shift+m exec ~/.config/sway/vol-osd.sh mute bindsym $mod+m exec pactl set-source-mute @DEFAULT_SOURCE@ toggle # Media bindsym XF86AudioPlay exec playerctl play-pause bindsym XF86AudioNext exec playerctl next bindsym XF86AudioPrev exec playerctl previous bindsym $mod+Ctrl+space exec playerctl play-pause bindsym $mod+Ctrl+l exec playerctl next bindsym $mod+Ctrl+h exec playerctl previous # Brightness bindsym XF86MonBrightnessUp exec ~/.config/sway/brightness-osd.sh up bindsym XF86MonBrightnessDown exec ~/.config/sway/brightness-osd.sh down bindsym $mod+Ctrl+bracketright exec ~/.config/sway/brightness-osd.sh up bindsym $mod+Ctrl+bracketleft exec ~/.config/sway/brightness-osd.sh down # ThinkPad multimedia keys bindsym XF86AudioMicMute exec pactl set-source-mute @DEFAULT_SOURCE@ toggle bindsym XF86Bluetooth exec ~/.config/sway/bt-toggle.sh bindsym XF86ScreenSaver exec "playerctl -a pause; swaylock -f -e -c 000000" bindsym XF86Sleep exec systemctl suspend bindsym XF86WLAN exec ~/.config/waybar/wifi-toggle.sh bindsym XF86RFKill exec rfkill toggle all # Screenshots bindsym Print exec sh -c 'grim -g "$(slurp)" - | tee ~/pics/screenshots/$(date +%Y-%m-%d-%H-%M-%S).png | wl-copy' bindsym Shift+Print exec sh -c 'grim - | tee ~/pics/screenshots/$(date +%Y-%m-%d-%H-%M-%S).png | wl-copy' # Dictation (push-to-talk toggle, whisper.cpp) bindsym $mod+i exec ~/.local/bin/dictate # OCR — crop a region, copy text to clipboard (tesseract) bindsym $mod+Shift+o exec ~/.local/bin/ocr # Lock & pause bindsym $mod+Shift+s exec "playerctl -a pause; swaylock -f -e -c 000000" # Notifications bindsym $mod+n exec makoctl dismiss bindsym $mod+Shift+n exec makoctl dismiss --all bindsym $mod+Ctrl+n exec makoctl restore # Clipboard history bindsym $mod+p exec ~/.config/waybar/clip-picker.sh pick bindsym $mod+Shift+p exec ~/.config/waybar/clip-picker.sh delete # Emoji picker (bemoji → wofi → wtype + clipboard) bindsym $mod+period exec ~/.config/sway/emoji-picker.sh # Display mode switching bindsym --no-repeat XF86Display exec ~/.config/sway/display-toggle.sh # Multimedia hardware keys (uncommon) bindsym XF86Tools exec $term --class=floating -e pulsemixer bindsym XF86Keyboard exec $term --class=floating -e glow -p ~/dotfiles/KEYBINDS.md bindsym XF86Favorites exec ~/.config/waybar/notification-picker.py # Quick scratch tools bindsym $mod+Shift+t exec $term --class=floating -e sh -c 'nvim "$XDG_RUNTIME_DIR/scratch-$(date +%s).txt"' bindsym $mod+c exec $term --class=floating -e ipython # QR codes (Super+z then r=read or w=write) mode "qr" { bindsym r exec ~/.local/bin/rqr, mode "default" bindsym w exec ~/.local/bin/wqr, mode "default" bindsym Escape mode "default" bindsym Return mode "default" } bindsym $mod+z mode "qr" # System / hardware submode — non-XF86 alternatives for the rarely used # hardware toggles and TUI launchers above. Enter with Super+x; mnemonic # letters (b=bluetooth, w=wifi, r=rfkill, s=sleep, d=display, # v=volume-mixer, k=keybinds, m=notification-picker). mode "system" { bindsym b exec ~/.config/sway/bt-toggle.sh, mode "default" bindsym w exec ~/.config/waybar/wifi-toggle.sh, mode "default" bindsym r exec rfkill toggle all, mode "default" bindsym s exec systemctl suspend, mode "default" bindsym d exec ~/.config/sway/display-toggle.sh, mode "default" bindsym v exec $term --class=floating -e pulsemixer, mode "default" bindsym k exec $term --class=floating -e glow -p ~/dotfiles/KEYBINDS.md, mode "default" bindsym m exec ~/.config/waybar/notification-picker.py, mode "default" bindsym n exec makoctl mode -t do-not-disturb, mode "default" bindsym Escape mode "default" bindsym Return mode "default" } bindsym $mod+x mode "system" # Thunderbird toggle: main window stashed in the scratchpad; this pulls it to # the current workspace (tiled) or sends it back. Child windows (compose, # viewer, calendar, prefs) tile normally wherever Thunderbird spawns them. bindsym $mod+t exec ~/.config/sway/tb-toggle.sh # ── Bar ─────────────────────────────────────────────────────────────────────── # Managed by waybar.service (pulled in via sway-session.target). # ── Autostart ───────────────────────────────────────────────────────────────── # Propagate the login-shell env (zprofile already ran by the time sway # executes its config) into the systemd --user manager AND the DBus # activation environment. Without this, user services like waybar.service # inherit the bare pre-login PATH (no ~/.nix-profile/bin, no ~/.local/bin), # and modules invoking nix-provisioned binaries (pass / python3 / ncat # from common.nix) silently pick up the system copies instead — manifests # as waybar modules printing different output from the same script run # interactively. PATH is the critical one; GNUPGHOME / GPG_TTY keep # pass-otp + pinentry consistent with the interactive shell. exec systemctl --user import-environment PATH DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE XDG_SESSION_DESKTOP PASSWORD_STORE_DIR GNUPGHOME GPG_TTY exec dbus-update-activation-environment --systemd PATH DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE XDG_SESSION_DESKTOP PASSWORD_STORE_DIR GNUPGHOME GPG_TTY exec "sleep 2 && ~/.config/sway/display-toggle.sh apply" exec systemctl --user start sway-session.target exec ~/.config/sway/tb-autostart.sh # GTK4 reads dark mode from gsettings (settings.ini's prefer-dark is GTK3 only). exec gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'