Add sway/wofi/foot Wayland desktop stack with per-host toggle
New opt-in feature for x86_64 desktops: sway + wofi + foot + swaybg +
swaylock + swayidle + grim + slurp + waybar + wl-clipboard. mako on
arch, dunst on debian (mako isn't packaged for debian).
Files:
- .chezmoi.yaml.tmpl: added data.sway flag (true on miche/byte/kaiser,
false on Pis). Override per host with ~/.config/chezmoi/features/sway
or ~/.config/chezmoi/features/no-sway marker files.
- run_once_40-install-sway.sh.tmpl: installs packages if .sway=true,
exits 0 otherwise. Sets up the marker file.
- dot_config/{sway,foot,wofi,waybar,mako}/: existing configs from miche.
Per-host toggle workflow:
# On any box, enable sway:
touch ~/.config/chezmoi/features/sway
chezmoi apply
# On a sway-enabled box, disable it:
touch ~/.config/chezmoi/features/no-sway
rm ~/.config/chezmoi/features/sway
chezmoi apply
Currently sway packages are already installed on miche (existed before
this commit). Byte will get them via the new run_once_40 script.
Pis (rye, crouton) are unaffected — install script early-returns.
This commit is contained in:
parent
fe73bbecba
commit
6bbaa8f2f5
21 changed files with 965 additions and 1 deletions
88
dot_config/foot/foot.ini
Normal file
88
dot_config/foot/foot.ini
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# foot terminal — gruvbox dark, Maple Mono 14pt with Terminus fallback
|
||||
# Reference: man foot.ini
|
||||
|
||||
[main]
|
||||
font=Maple Mono CN:size=14,Terminus:size=14
|
||||
font-bold=Maple Mono CN:weight=bold:size=14
|
||||
font-italic=Maple Mono CN:slant=italic:size=14
|
||||
font-bold-italic=Maple Mono CN:weight=bold:slant=italic:size=14
|
||||
font-size-adjustment=0.5
|
||||
pad=8x8
|
||||
term=foot
|
||||
# (Previously set to "foot-extra", but that terminfo is not installed in the
|
||||
# CachyOS foot package; only foot, foot+base, foot-direct are. Setting
|
||||
# TERM=foot-extra breaks every ncurses program — htop, nvtop, vim, etc. —
|
||||
# with "cannot initialize terminal type". "foot" has 256 colors and
|
||||
# everything modern tools need.)
|
||||
# kaiser runs zsh as the login shell (SHELL=/bin/fish was misleading — that
|
||||
# comes from sway's inherited env, not the user's actual shell). Hardcode
|
||||
# /usr/bin/zsh here. foot does NOT expand $SHELL in the shell= value (it
|
||||
# passes the literal string to its child), so don't try the sh,-c trick —
|
||||
# it just makes foot spawn a binary literally named "${SHELL:-/bin/bash}"
|
||||
# and exit with "No such file or directory".
|
||||
shell=/usr/bin/zsh
|
||||
|
||||
# PTY
|
||||
# utmphelper is not packaged with foot on this CachyOS build. Leave it unset
|
||||
# to disable utmp logging for foot sessions; harmless and not required.
|
||||
|
||||
# Initial geometry
|
||||
initial-window-size-chars=120x32
|
||||
|
||||
[scrollback]
|
||||
lines=10000
|
||||
indicator-position=relative
|
||||
|
||||
[cursor]
|
||||
style=block
|
||||
blink=yes
|
||||
blink-rate=500
|
||||
beam-thickness=2px
|
||||
|
||||
[mouse]
|
||||
hide-when-typing=yes
|
||||
alternate-scroll-mode=true
|
||||
|
||||
[colors-dark]
|
||||
# Gruvbox dark palette (gruvbox-community) — bg0_h / fg / 16 ANSI
|
||||
# https://github.com/gruvbox-community/gruvbox
|
||||
background=1d2021
|
||||
foreground=ebdbb2
|
||||
# Slight transparency — 0.90 alpha. Foot 1.27+ uses a separate alpha key
|
||||
# (in [colors-dark], not 8-digit hex — that was foot 1.24 syntax).
|
||||
alpha=0.90
|
||||
|
||||
# Regular ANSI (0-7)
|
||||
regular0=282828
|
||||
regular1=cc241d
|
||||
regular2=98971a
|
||||
regular3=d79921
|
||||
regular4=458588
|
||||
regular5=b16286
|
||||
regular6=689d6a
|
||||
regular7=a89984
|
||||
|
||||
# Bright ANSI (8-15)
|
||||
bright0=928374
|
||||
bright1=fb4934
|
||||
bright2=b8bb26
|
||||
bright3=fabd2f
|
||||
bright4=83a598
|
||||
bright5=d3869b
|
||||
bright6=8ec07c
|
||||
bright7=ebdbb2
|
||||
|
||||
# Selection (FG BG pair)
|
||||
selection-foreground=1d2021
|
||||
selection-background=ebdbb2
|
||||
# Search box (FG BG pairs)
|
||||
search-box-match=ebdbb2 458588
|
||||
search-box-no-match=ebdbb2 cc241d
|
||||
|
||||
[bell]
|
||||
urgent=no
|
||||
notify=no
|
||||
visual=no
|
||||
|
||||
[url]
|
||||
launch=xdg-open {url}
|
||||
25
dot_config/foot/patch.py
Normal file
25
dot_config/foot/patch.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
from pathlib import Path
|
||||
p = Path("/home/rain/.config/foot/foot.ini")
|
||||
text = p.read_text()
|
||||
old_lines = [
|
||||
"# foot does not expand env variables in the `shell=` value, so we have to",
|
||||
"# go through `sh -c` to make the parent's $SHELL take effect. When foot",
|
||||
"# is launched from a fish session, $SHELL is /bin/fish, and foot runs fish.",
|
||||
"# When launched from bash, $SHELL is /bin/bash, and foot runs bash. The",
|
||||
"# default fallback is /bin/bash if $SHELL is unset for any reason.",
|
||||
'shell=sh,-c,"exec ${SHELL:-/bin/bash} -i"',
|
||||
]
|
||||
new_lines = [
|
||||
"# kaiser runs zsh as the login shell. Hardcode /usr/bin/zsh here.",
|
||||
"# foot does NOT expand $SHELL in shell= (it passes the literal string",
|
||||
"# to its child process), so the sh,-c trick makes foot try to exec a",
|
||||
'# binary literally named "${SHELL:-/bin/bash}" and die with',
|
||||
'# "No such file or directory". Point shell= at the binary directly.',
|
||||
"shell=/usr/bin/zsh",
|
||||
]
|
||||
old = "\n".join(old_lines)
|
||||
new = "\n".join(new_lines)
|
||||
assert old in text, "old block not found in foot.ini"
|
||||
text = text.replace(old, new, 1)
|
||||
p.write_text(text)
|
||||
print("OK, new size:", len(text))
|
||||
22
dot_config/mako/config
Normal file
22
dot_config/mako/config
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# mako gruvbox-material-dark-hard
|
||||
font=Maple Mono NF 11
|
||||
background-color=#1d2021
|
||||
text-color=#ebdbb2
|
||||
border-size=2
|
||||
border-color=#d79921
|
||||
border-radius=0
|
||||
default-timeout=5000
|
||||
padding=10
|
||||
margin=8
|
||||
width=400
|
||||
|
||||
[urgency=high]
|
||||
border-color=#fb4934
|
||||
default-timeout=0
|
||||
|
||||
[urgency=normal]
|
||||
border-color=#d79921
|
||||
|
||||
[urgency=low]
|
||||
border-color=#504945
|
||||
default-timeout=3000
|
||||
24
dot_config/sway/caffeine.sh
Executable file
24
dot_config/sway/caffeine.sh
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
# caffeine.sh — toggle caffeine mode by killing/restarting swayidle
|
||||
# When ON: kill swayidle (no idle lock/screen-off)
|
||||
# When OFF: restart swayidle with normal timeouts
|
||||
|
||||
WALLPAPER="$HOME/.local/share/wallpapers/teach-invaders-gruvbox.png"
|
||||
FLAG="/tmp/caffeine-inhibit"
|
||||
|
||||
if [ -f "$FLAG" ]; then
|
||||
# Turn OFF caffeine — restart swayidle
|
||||
rm -f "$FLAG"
|
||||
killall swayidle 2>/dev/null
|
||||
swayidle -w \
|
||||
timeout 300 "swaylock -f -i $WALLPAPER" \
|
||||
timeout 600 'swaymsg "output * power off"' \
|
||||
resume 'swaymsg "output * power on"' \
|
||||
before-sleep "swaylock -f -i $WALLPAPER" &
|
||||
notify-send -t 2000 "☕ Caffeine OFF" "Idle sleep enabled" 2>/dev/null
|
||||
else
|
||||
# Turn ON caffeine — kill swayidle
|
||||
touch "$FLAG"
|
||||
killall swayidle 2>/dev/null
|
||||
notify-send -t 2000 "☕ Caffeine ON" "Idle sleep disabled" 2>/dev/null
|
||||
fi
|
||||
48
dot_config/sway/cheatsheet.md
Normal file
48
dot_config/sway/cheatsheet.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# === sway keybinds cheatsheet ===
|
||||
# generated from ~/.config/sway/config — `Super` = the Windows key (Mod4)
|
||||
# reload this view with: Super + /
|
||||
|
||||
# LAUNCHERS
|
||||
Super+Enter open foot terminal
|
||||
Super+D open wofi app launcher
|
||||
Super+E open thunar (file manager)
|
||||
Super+B open firefox
|
||||
Super+/ show this cheatsheet (in foot, via less)
|
||||
Super+Shift+E exit sway (with prompt)
|
||||
|
||||
# WINDOW MANAGEMENT
|
||||
Super+Q kill focused window
|
||||
Super+F fullscreen toggle
|
||||
Super+V split toggle (vertical <-> horizontal)
|
||||
Super+S stacking layout
|
||||
Super+W tabbed layout
|
||||
Super+Space floating toggle
|
||||
|
||||
# FOCUS / MOVE
|
||||
Super+arrows focus window in direction
|
||||
Super+Shift+arrows move window in direction
|
||||
|
||||
# WORKSPACES
|
||||
Super+1 .. Super+0 switch to workspace N (0 = 10)
|
||||
Super+Tab toggle back to previous workspace
|
||||
Super+Shift+1..0 move focused window to workspace N
|
||||
|
||||
# SCREENSHOTS
|
||||
Print region screenshot to file
|
||||
Super+Print full-screen screenshot to file
|
||||
Super+Shift+S region screenshot to clipboard
|
||||
|
||||
# SCRATCHPAD
|
||||
Super+` toggle dropdown foot (sway scratchpad)
|
||||
|
||||
# RESIZE MODE (Super+R enters, Esc/Enter exits)
|
||||
resize mode:
|
||||
arrows shrink/grow 30px in direction
|
||||
Esc / Enter exit resize mode
|
||||
|
||||
# LOCK / IDLE
|
||||
Ctrl+Alt+L lock now
|
||||
5 min idle auto-lock
|
||||
10 min idle auto screen-off
|
||||
|
||||
# TIP: Super+Shift+C reloads this config without logging out.
|
||||
4
dot_config/sway/cheatsheet.sh
Executable file
4
dot_config/sway/cheatsheet.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
# cheatsheet.sh — opens the sway keybind cheatsheet in a new foot terminal
|
||||
# running less. Press q to quit.
|
||||
exec foot sh -c 'exec less -SRFX "$HOME/.config/sway/cheatsheet.md"'
|
||||
148
dot_config/sway/config
Normal file
148
dot_config/sway/config
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
# === ~/.config/sway/config ===
|
||||
# MINIMAL — single file, no includes. Tier-1+2+3 in one go.
|
||||
# We can split into includes later once this is proven to boot.
|
||||
|
||||
# === variables ===
|
||||
set $mod Mod4
|
||||
set $term foot
|
||||
set $menu wofi --show drun --insensitive -p "launch"
|
||||
set $browser zen
|
||||
set $fileManager thunar
|
||||
|
||||
# === output / input ===
|
||||
# Gruvbox wallpaper — sway's native bg command manages swaybg lifecycle internally
|
||||
output * bg $HOME/.local/share/wallpapers/teach-invaders-gruvbox.png fill
|
||||
|
||||
# Touchpad: tap-to-click, natural scroll, drag
|
||||
input type:touchpad {
|
||||
tap enabled
|
||||
tap_button_map lrm
|
||||
natural_scroll enabled
|
||||
dwt enabled
|
||||
accel_profile adaptive
|
||||
}
|
||||
|
||||
# === window borders (gruvbox-hard) ===
|
||||
default_border pixel 2
|
||||
default_floating_border pixel 2
|
||||
gaps inner 8
|
||||
gaps outer 4
|
||||
smart_borders on
|
||||
smart_gaps on
|
||||
|
||||
# gruvbox-orange focus border (replaces the default "generic blue")
|
||||
client.focused #d79921 #1d2021 #ebdbb2 #d79921 #d79921
|
||||
client.unfocused #3c3836 #1d2021 #a89984 #3c3836 #3c3836
|
||||
client.focused_inactive #504945 #1d2021 #a89984 #504945 #504945
|
||||
client.urgent #fb4934 #1d2021 #ebdbb2 #fb4934 #fb4934
|
||||
|
||||
# === swaybar (replaced by waybar — keeping as fallback) ===
|
||||
# If waybar isn't installed yet, this provides a basic bar.
|
||||
bar {
|
||||
swaybar_command waybar
|
||||
}
|
||||
|
||||
# === autostart (kept tiny, all stderr silenced) ===
|
||||
# Make user-local themes/icons visible to GTK and Qt
|
||||
exec sh -c 'export XDG_DATA_DIRS="$HOME/.local/share:$HOME/.local/share/flatpak/exports/share:/usr/local/share:/usr/share"; export XDG_DATA_HOME="$HOME/.local/share"; export XDG_CONFIG_HOME="$HOME/.config"; systemctl --user import-environment XDG_DATA_DIRS XDG_DATA_HOME XDG_CONFIG_HOME 2>/dev/null; dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway'
|
||||
exec /usr/libexec/polkit-gnome-authentication-agent-1
|
||||
exec clipmenud
|
||||
exec sh -c 'systemctl --user start xdg-desktop-portal xdg-desktop-portal-wlr 2>/dev/null || true'
|
||||
exec sh -c 'gsettings set org.gnome.desktop.interface gtk-theme Gruvbox-Material-Dark-Hard 2>/dev/null; gsettings set org.gnome.desktop.interface icon-theme Gruvbox-Material-Dark 2>/dev/null; gsettings set org.gnome.desktop.interface color-scheme prefer-dark 2>/dev/null; true'
|
||||
exec gnome-keyring-daemon --start --components=secrets
|
||||
exec mako
|
||||
exec wlsunset -l 39.96 -L -82.99
|
||||
exec sworkstyle
|
||||
|
||||
# === idle / lock ===
|
||||
exec swayidle -w \
|
||||
timeout 300 '$HOME/.config/sway/lock-fancy.sh' \
|
||||
timeout 600 'swaymsg "output * power off"' \
|
||||
resume 'swaymsg "output * power on"' \
|
||||
before-sleep '$HOME/.config/sway/lock-fancy.sh'
|
||||
|
||||
# === keybinds ===
|
||||
bindsym $mod+Return exec $term
|
||||
bindsym $mod+d exec $menu
|
||||
bindsym $mod+e exec $fileManager
|
||||
bindsym $mod+b exec $browser
|
||||
bindsym $mod+q kill
|
||||
bindsym $mod+Shift+c reload
|
||||
bindsym Ctrl+Alt+l exec $HOME/.config/sway/lock-fancy.sh
|
||||
bindsym $mod+slash exec $HOME/.config/sway/cheatsheet.sh
|
||||
bindsym $mod+question exec $HOME/.config/sway/cheatsheet.sh
|
||||
bindsym $mod+Shift+e exec swaynag -t warning -m 'Exit Sway?' -B 'Yes, exit Sway' 'swaymsg exit'
|
||||
|
||||
bindsym $mod+Left focus left
|
||||
bindsym $mod+Down focus down
|
||||
bindsym $mod+Up focus up
|
||||
bindsym $mod+Right focus right
|
||||
bindsym $mod+Shift+Left move left
|
||||
bindsym $mod+Shift+Down move down
|
||||
bindsym $mod+Shift+Up move up
|
||||
bindsym $mod+Shift+Right move right
|
||||
|
||||
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+Tab workspace back_and_forth
|
||||
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
|
||||
|
||||
bindsym $mod+f fullscreen
|
||||
bindsym $mod+v split toggle splitv
|
||||
bindsym $mod+s layout stacking
|
||||
bindsym $mod+w layout tabbed
|
||||
bindsym $mod+space exec $menu
|
||||
bindsym $mod+Shift+space floating toggle
|
||||
|
||||
bindsym Print exec grim -g "$(slurp)" ~/Pictures/screenshot-$(date +%Y%m%d-%H%M%S).png
|
||||
bindsym $mod+Print exec grim ~/Pictures/screenshot-$(date +%Y%m%d-%H%M%S).png
|
||||
bindsym $mod+Shift+s exec grim -g "$(slurp)" - | wl-copy
|
||||
|
||||
mode "resize" {
|
||||
bindsym Left resize shrink width 30px
|
||||
bindsym Down resize grow height 30px
|
||||
bindsym Up resize shrink height 30px
|
||||
bindsym Right resize grow width 30px
|
||||
bindsym Escape mode "default"
|
||||
bindsym Return mode "default"
|
||||
}
|
||||
bindsym $mod+r mode "resize"
|
||||
|
||||
# === F12 dropdown terminal ===
|
||||
# F12 opens a floating foot. Uses -a dropdown so for_window only floats
|
||||
# the dropdown, not regular foot windows from Super+Enter.
|
||||
# Close it with Super+Q or Ctrl+D.
|
||||
bindsym F12 exec foot -a dropdown
|
||||
bindsym $mod+grave exec foot -a dropdown
|
||||
for_window [app_id="dropdown"] floating enable, sticky enable, resize set width 1100 height 600, move position center
|
||||
|
||||
# === media keys ===
|
||||
bindsym --locked XF86AudioRaiseVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindsym --locked XF86AudioLowerVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindsym --locked XF86AudioMute exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindsym --locked XF86AudioMicMute exec wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindsym --locked XF86AudioPlay exec playerctl play-pause 2>/dev/null || true
|
||||
bindsym --locked XF86AudioNext exec playerctl next 2>/dev/null || true
|
||||
bindsym --locked XF86AudioPrev exec playerctl previous 2>/dev/null || true
|
||||
bindsym --locked XF86MonBrightnessUp exec sh -c 'echo $(( $(cat /sys/class/backlight/acpi_video0/brightness) + 1 > $(cat /sys/class/backlight/acpi_video0/max_brightness) ? $(cat /sys/class/backlight/acpi_video0/max_brightness) : $(cat /sys/class/backlight/acpi_video0/brightness) + 1 )) | sudo tee /sys/class/backlight/acpi_video0/brightness'
|
||||
bindsym --locked XF86MonBrightnessDown exec sh -c 'echo $(( $(cat /sys/class/backlight/acpi_video0/brightness) - 1 < 0 ? 0 : $(cat /sys/class/backlight/acpi_video0/brightness) - 1 )) | sudo tee /sys/class/backlight/acpi_video0/brightness'
|
||||
|
||||
# pointer / mouse — the gruvbox-material-gtk repo doesn't ship an xcursor theme,
|
||||
# so leave the default alone. (Cursor shows fine on the default theme.)
|
||||
18
dot_config/sway/config.d/00-gruvbox.conf
Normal file
18
dot_config/sway/config.d/00-gruvbox.conf
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# === ~/.config/sway/config.d/00-gruvbox.conf ===
|
||||
# gruvbox material dark hard — wired through gsettings so Thunar, Firefox chrome,
|
||||
# and any GTK3/4 app pick it up the moment sway starts.
|
||||
|
||||
# Run gsettings in a sh -c wrapper so we can pipe stderr to /dev/null.
|
||||
# This is necessary because the very first exec block runs before dbus is
|
||||
# always reachable, and gsettings prints a long bar-warning to stderr when
|
||||
# it can't find the bus. We don't want the red bar to surface that.
|
||||
exec_always {
|
||||
gsettings set org.gnome.desktop.interface gtk-theme 'Gruvbox-Material-Dark-Hard' 2>/dev/null
|
||||
gsettings set org.gnome.desktop.interface icon-theme 'Gruvbox-Material-Dark' 2>/dev/null
|
||||
gsettings set org.gnome.desktop.interface cursor-theme 'Gruvbox-Material-Dark' 2>/dev/null
|
||||
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' 2>/dev/null
|
||||
gsettings set org.cinnamon.desktop.interface gtk-theme 'Gruvbox-Material-Dark-Hard' 2>/dev/null
|
||||
}
|
||||
|
||||
# gnome-keyring (in case any GTK app needs secret service for ssh-agent bridge)
|
||||
exec gnome-keyring-daemon --start --components=secrets
|
||||
76
dot_config/sway/config.d/10-keybinds.conf
Normal file
76
dot_config/sway/config.d/10-keybinds.conf
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# === ~/.config/sway/config.d/10-keybinds.conf ===
|
||||
# sway keybindings. Mint+Cinnamon muscle memory → Super (Mod4).
|
||||
|
||||
# === essentials ===
|
||||
bindsym $mod+Return exec $term
|
||||
bindsym $mod+d exec $menu
|
||||
bindsym $mod+e exec $fileManager
|
||||
bindsym $mod+b exec $browser
|
||||
bindsym $mod+q kill
|
||||
bindsym $mod+Shift+c reload
|
||||
bindsym $mod+Shift+e exec swaynag -t warning \
|
||||
-m 'Exit Sway?' \
|
||||
-B 'Yes, exit Sway' 'swaymsg exit'
|
||||
|
||||
# === move focus ===
|
||||
bindsym $mod+Left focus left
|
||||
bindsym $mod+Down focus down
|
||||
bindsym $mod+Up focus up
|
||||
bindsym $mod+Right focus right
|
||||
bindsym $mod+Shift+Left move left
|
||||
bindsym $mod+Shift+Down move down
|
||||
bindsym $mod+Shift+Up move up
|
||||
bindsym $mod+Shift+Right move right
|
||||
|
||||
# === workspace navigation ===
|
||||
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+Tab workspace back_and_forth
|
||||
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+f fullscreen
|
||||
bindsym $mod+v split toggle splitv
|
||||
bindsym $mod+s layout stacking
|
||||
bindsym $mod+w layout tabbed
|
||||
bindsym $mod+space floating toggle
|
||||
bindsym $mod+Shift+space focus mode_toggle
|
||||
|
||||
# === screenshot (grim + slurp) ===
|
||||
bindsym Print exec grim -g "$(slurp)" ~/Pictures/screenshot-$(date +%Y%m%d-%H%M%S).png
|
||||
bindsym $mod+Print exec grim ~/Pictures/screenshot-$(date +%Y%m%d-%H%M%S).png
|
||||
bindsym $mod+Shift+s exec grim -g "$(slurp)" - | wl-copy
|
||||
|
||||
# === resize ===
|
||||
mode "resize" {
|
||||
bindsym Left resize shrink width 30px
|
||||
bindsym Down resize grow height 30px
|
||||
bindsym Up resize shrink height 30px
|
||||
bindsym Right resize grow width 30px
|
||||
bindsym Escape mode "default"
|
||||
bindsym Return mode "default"
|
||||
}
|
||||
bindsym $mod+r mode "resize"
|
||||
|
||||
# === scratchpads (quick terminal / browser) ===
|
||||
# Start a headless foot server, then a dropdown client window. Toggle with $mod+grave.
|
||||
bindsym $mod+grave exec foot --server
|
||||
bindsym $mod+apostrophe exec foot -a dropdown
|
||||
for_window [app_id="dropdown"] floating enable, sticky enable, resize set width 1100 height 600, move position center
|
||||
15
dot_config/sway/config.d/20-autostart.conf
Normal file
15
dot_config/sway/config.d/20-autostart.conf
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# === ~/.config/sway/config.d/20-autostart.conf ===
|
||||
# background services started when sway comes up.
|
||||
|
||||
# polkit agent — needed for gparted, mount UIs in thunar, etc.
|
||||
exec /usr/libexec/polkit-gnome-authentication-agent-1
|
||||
|
||||
# clipboard — start clipmenud directly (it watches the clipboard internally)
|
||||
# Drop the wl-paste --watch wrapper to avoid bar noise if the socket isn't ready.
|
||||
exec clipmenud
|
||||
|
||||
# xdg-desktop-portal — required for native file/screen sharing in Firefox/Chromium.
|
||||
# Skip if services aren't enabled; the user can enable with:
|
||||
# systemctl --user enable --now xdg-desktop-portal xdg-desktop-portal-wlr
|
||||
# Until then, those systemctl lines are quiet no-ops.
|
||||
exec sh -c 'systemctl --user start xdg-desktop-portal xdg-desktop-portal-wlr 2>/dev/null || true'
|
||||
17
dot_config/sway/config.d/50-launchers.conf
Normal file
17
dot_config/sway/config.d/50-launchers.conf
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# ~/.config/sway/config.d/50-launchers.conf
|
||||
# Launcher keybinds. The base $menu var in config is the drun launcher.
|
||||
# These add run mode, window switcher, and the powermenu.
|
||||
|
||||
# $mod+grave already used by foot dropdown — don't clobber.
|
||||
# $mod+Tab already used by workspace back_and_forth — don't clobber.
|
||||
# $mod+slash is the cheatsheet — keep it.
|
||||
|
||||
# Exec ad-hoc command (not in $PATH discovery)
|
||||
bindsym $mod+F12 exec wofi --show run --prompt "exec"
|
||||
|
||||
# Sway window switcher (replaces `swayr`-style overview)
|
||||
bindsym $mod+F11 exec wofi --show window
|
||||
|
||||
# Power menu — dmenu mode driven by wofi-powermenu script.
|
||||
# wofi has no custom-mode feature; the script does the dispatch.
|
||||
bindsym $mod+Escape exec $HOME/.local/bin/wofi-powermenu
|
||||
34
dot_config/sway/lock-fancy.sh
Executable file
34
dot_config/sway/lock-fancy.sh
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
# lock-fancy.sh — fancy swaylock: snapshot the screen, dim+blur it, and use as background.
|
||||
# grim + ffmpeg (both already installed). No swaylock-effects overlay needed.
|
||||
|
||||
set -e
|
||||
|
||||
TMP=/tmp/lock-bg-483833.png
|
||||
DIM=/tmp/lock-bg-dim-483833.png
|
||||
|
||||
# Snapshot the current screen
|
||||
grim -t png "$TMP" 2>/dev/null
|
||||
|
||||
# Dim + blur via ffmpeg (much faster than ImageMagick)
|
||||
if [ -f "$TMP" ] && command -v ffmpeg >/dev/null; then
|
||||
ffmpeg -loglevel error -y -i "$TMP" -vf "boxblur=12:1,eq=brightness=-0.30:saturation=0.6" -frames:v 1 "$DIM"
|
||||
IMG="$DIM"
|
||||
else
|
||||
# Fallback to the regular wallpaper
|
||||
IMG="$HOME/.local/share/wallpapers/teach-invaders-gruvbox.png"
|
||||
fi
|
||||
|
||||
# Launch swaylock
|
||||
swaylock -f -i "$IMG" \
|
||||
--indicator-radius 100 \
|
||||
--indicator-thickness 6 \
|
||||
--ring-color ebdbb2 \
|
||||
--inside-color 1d202180 \
|
||||
--key-hl-color fe8019 \
|
||||
--bs-hl-color fb4934 \
|
||||
--text-color ebdbb2 \
|
||||
--separator-color 00000000 \
|
||||
--fade-in 0.3
|
||||
|
||||
rm -f "$TMP" "$DIM" 2>/dev/null
|
||||
58
dot_config/sway/toggle-dropdown.sh
Executable file
58
dot_config/sway/toggle-dropdown.sh
Executable file
|
|
@ -0,0 +1,58 @@
|
|||
#!/bin/bash
|
||||
# toggle-dropdown.sh — toggle the dropdown foot terminal
|
||||
# Writes debug info to /tmp/sway-f12.log so we can diagnose from SSH
|
||||
|
||||
LOG=/tmp/sway-f12.log
|
||||
echo "=== $(date) F12/Super+grave pressed ===" >> "$LOG"
|
||||
echo "WAYLAND_DISPLAY=$WAYLAND_DISPLAY" >> "$LOG"
|
||||
echo "USER=$USER XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR" >> "$LOG"
|
||||
|
||||
# Find the sway socket
|
||||
SOCK=$(ls -t /run/user/$(id -u)/sway-ipc.*.sock 2>/dev/null | head -1)
|
||||
echo "SOCK=$SOCK" >> "$LOG"
|
||||
|
||||
if [ -z "$SOCK" ]; then
|
||||
echo "ERROR: no sway socket found" >> "$LOG"
|
||||
notify-send -t 2000 "sway: no IPC socket" 2>>"$LOG" || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if a foot window is in the scratchpad (hidden)
|
||||
HIDDEN=$(SWAYSOCK=$SOCK swaymsg -t get_tree 2>>"$LOG" | python3 -c "
|
||||
import sys, json
|
||||
try:
|
||||
tree = json.load(sys.stdin)
|
||||
def find_app(node, app_id):
|
||||
if node.get('app_id') == app_id and node.get('name', '').startswith('__i3'):
|
||||
return node
|
||||
for c in node.get('nodes', []) + node.get('floating_nodes', []):
|
||||
r = find_app(c, app_id)
|
||||
if r is not None:
|
||||
return r
|
||||
return None
|
||||
dd = find_app(tree, 'foot')
|
||||
print('hidden' if dd is not None else 'none')
|
||||
except Exception as e:
|
||||
print(f'err:{e}')
|
||||
" 2>>"$LOG")
|
||||
|
||||
echo "HIDDEN=$HIDDEN" >> "$LOG"
|
||||
|
||||
if [ "$HIDDEN" = "hidden" ]; then
|
||||
SWAYSOCK=$SOCK swaymsg '[app_id="foot"] scratchpad show' >>"$LOG" 2>&1
|
||||
echo "toggled: scratchpad show" >> "$LOG"
|
||||
else
|
||||
# Spawn a new foot. Pass through WAYLAND_DISPLAY explicitly.
|
||||
if [ -n "$WAYLAND_DISPLAY" ]; then
|
||||
WAYLAND_DISPLAY=$WAYLAND_DISPLAY foot >>"$LOG" 2>&1 &
|
||||
else
|
||||
# try to find wayland-1 socket
|
||||
if [ -S "/run/user/$(id -u)/wayland-1" ]; then
|
||||
WAYLAND_DISPLAY=wayland-1 foot >>"$LOG" 2>&1 &
|
||||
else
|
||||
foot >>"$LOG" 2>&1 &
|
||||
fi
|
||||
fi
|
||||
echo "spawned foot" >> "$LOG"
|
||||
fi
|
||||
echo "=== done ===" >> "$LOG"
|
||||
29
dot_config/sway/wifi-menu.sh
Executable file
29
dot_config/sway/wifi-menu.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
# wifi-menu.sh — wofi-based WiFi network picker using nmcli
|
||||
# Lists available networks, connects on selection.
|
||||
|
||||
# Get list of networks: SSID, signal, security
|
||||
SELECTED=$(nmcli -t -f SSID,SIGNAL,SECURITY device wifi list --rescan yes 2>/dev/null | \
|
||||
grep -v '^$' | \
|
||||
sort -t: -k2 -nr | \
|
||||
awk -F: '{
|
||||
sig = $2 + 0
|
||||
if (sig > 75) bars = "████"
|
||||
else if (sig > 50) bars = "███░"
|
||||
else if (sig > 25) bars = "██░░"
|
||||
else bars = "█░░░"
|
||||
sec = ($3 != "" && $3 != "--") ? " " : ""
|
||||
printf "%s %s%s\n", bars, $1, sec
|
||||
}' | \
|
||||
wofi --dmenu --insensitive --prompt "WiFi" -W 400 -H 500 2>/dev/null)
|
||||
|
||||
# Exit if nothing selected
|
||||
[ -z "$SELECTED" ] && exit 0
|
||||
|
||||
# Extract SSID (everything after the signal bars + spaces)
|
||||
SSID=$(echo "$SELECTED" | sed 's/^[█░ ]* //; s/ 🔒$//')
|
||||
|
||||
# Connect
|
||||
nmcli device wifi connect "$SSID" 2>&1 | grep -q "successfully" && \
|
||||
notify-send -t 3000 "WiFi" "Connected to $SSID" || \
|
||||
notify-send -t 5000 "WiFi" "Failed to connect to $SSID"
|
||||
102
dot_config/waybar/config
Normal file
102
dot_config/waybar/config
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
{
|
||||
"layer": "top",
|
||||
"position": "top",
|
||||
"height": 32,
|
||||
"spacing": 0,
|
||||
"modules-left": [
|
||||
"sway/workspaces",
|
||||
"sway/mode"
|
||||
],
|
||||
"modules-center": [
|
||||
"clock",
|
||||
"custom/caffeine"
|
||||
],
|
||||
"modules-right": [
|
||||
"pulseaudio",
|
||||
"battery",
|
||||
"cpu",
|
||||
"memory",
|
||||
"tray",
|
||||
"network"
|
||||
],
|
||||
"sway/workspaces": {
|
||||
"disable-scroll": true,
|
||||
"format": "{name}",
|
||||
"format-icons": {
|
||||
"focused": "\u25cf",
|
||||
"default": "\u25cb"
|
||||
}
|
||||
},
|
||||
"clock": {
|
||||
"format": " {:%a %b %d %H:%M}",
|
||||
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
|
||||
"format-alt": " {:%Y-%m-%d}"
|
||||
},
|
||||
"pulseaudio": {
|
||||
"format": "{icon} {volume}%",
|
||||
"format-muted": "\udb81\udd81 muted",
|
||||
"format-icons": {
|
||||
"default": [
|
||||
"\udb81\udd7f",
|
||||
"\udb81\udd80",
|
||||
"\udb81\udd7e"
|
||||
]
|
||||
},
|
||||
"scroll-step": 5,
|
||||
"on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
|
||||
"on-click-right": "pavucontrol"
|
||||
},
|
||||
"battery": {
|
||||
"states": {
|
||||
"good": 80,
|
||||
"warning": 30,
|
||||
"critical": 15
|
||||
},
|
||||
"format": "{icon} {capacity}%",
|
||||
"format-charging": "\udb80\udc84 {capacity}%",
|
||||
"format-plugged": "\udb80\udc84 {capacity}%",
|
||||
"format-icons": [
|
||||
"\udb80\udc8e",
|
||||
"\udb80\udc7a",
|
||||
"\udb80\udc7b",
|
||||
"\udb80\udc7c",
|
||||
"\udb80\udc7d",
|
||||
"\udb80\udc7e",
|
||||
"\udb80\udc7f",
|
||||
"\udb80\udc80",
|
||||
"\udb80\udc81",
|
||||
"\udb80\udc82",
|
||||
"\udb80\udc79"
|
||||
]
|
||||
},
|
||||
"cpu": {
|
||||
"format": "\udb83\udee0 {usage}%",
|
||||
"tooltip": true
|
||||
},
|
||||
"memory": {
|
||||
"format": "\udb80\udf5b {}%",
|
||||
"tooltip-format": "{used:0.1f}G / {total:0.1f}G"
|
||||
},
|
||||
"network": {
|
||||
"format-wifi": "\udb82\udd28 {essid}",
|
||||
"format-ethernet": "\udb80\ude00 {ipaddr}",
|
||||
"format-disconnected": "\udb82\udd2d disconnected",
|
||||
"format-linked": "\udb82\udd2a {ifname}",
|
||||
"tooltip-format": "{ifname} \u2014 {ipaddr}",
|
||||
"on-click": "$HOME/.config/sway/wifi-menu.sh"
|
||||
},
|
||||
"custom/caffeine": {
|
||||
"format": "{icon}",
|
||||
"format-icons": {
|
||||
"default": "\udb80\udd76",
|
||||
"active": "\u2615"
|
||||
},
|
||||
"exec": "if [ -f /tmp/caffeine-inhibit ]; then echo '{\"alt\":\"active\",\"text\":\"caffeine\"}'; else echo '{\"alt\":\"default\",\"text\":\"caffeine\"}'; fi",
|
||||
"exec-interval": 2,
|
||||
"return-type": "json",
|
||||
"on-click": "$HOME/.config/sway/caffeine.sh"
|
||||
},
|
||||
"tray": {
|
||||
"spacing": 8
|
||||
}
|
||||
}
|
||||
92
dot_config/waybar/style.css
Normal file
92
dot_config/waybar/style.css
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/* === waybar — gruvbox-material-dark-hard, polished === */
|
||||
|
||||
* {
|
||||
font-family: "Maple Mono NF";
|
||||
font-size: 14px;
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* transparent bar so the desktop bleeds through at the edges */
|
||||
window#waybar {
|
||||
background-color: rgba(29, 32, 33, 0.92);
|
||||
color: #ebdbb2;
|
||||
border-bottom: 1px solid #3c3836;
|
||||
}
|
||||
|
||||
window#waybar.hidden { opacity: 0.2; }
|
||||
|
||||
/* workspaces */
|
||||
#workspaces button {
|
||||
padding: 0 12px;
|
||||
background: transparent;
|
||||
color: #a89984;
|
||||
box-shadow: inset 0 -2px transparent;
|
||||
transition: all 200ms ease;
|
||||
}
|
||||
#workspaces button:hover {
|
||||
background: #3c3836;
|
||||
color: #ebdbb2;
|
||||
}
|
||||
#workspaces button.focused {
|
||||
color: #fabd2f;
|
||||
box-shadow: inset 0 -2px #fabd2f;
|
||||
}
|
||||
#workspaces button.urgent {
|
||||
color: #fb4934;
|
||||
animation: blink 1s linear infinite alternate;
|
||||
}
|
||||
|
||||
#mode {
|
||||
color: #fb4934;
|
||||
background: #282828;
|
||||
padding: 0 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#clock {
|
||||
color: #ebdbb2;
|
||||
font-weight: bold;
|
||||
padding: 0 16px;
|
||||
border-left: 1px solid #3c3836;
|
||||
border-right: 1px solid #3c3836;
|
||||
}
|
||||
#clock:hover { color: #fabd2f; }
|
||||
|
||||
/* right-side modules — shared layout, individual color */
|
||||
#pulseaudio, #battery, #cpu, #memory, #network, #tray, #custom-caffeine {
|
||||
padding: 0 12px;
|
||||
border-left: 1px solid #3c3836;
|
||||
transition: all 200ms ease;
|
||||
}
|
||||
#pulseaudio:hover, #battery:hover, #cpu:hover, #memory:hover, #network:hover, #tray:hover, #custom-caffeine:hover {
|
||||
background: #3c3836;
|
||||
}
|
||||
|
||||
#pulseaudio { color: #b8bb26; }
|
||||
#pulseaudio.muted { color: #928374; }
|
||||
#battery { color: #d79921; }
|
||||
#battery.charging { color: #b8bb26; }
|
||||
#battery.good { color: #b8bb26; }
|
||||
#battery.warning { color: #fe8019; }
|
||||
#battery.critical {
|
||||
color: #fb4934;
|
||||
animation: blink 1s linear infinite alternate;
|
||||
}
|
||||
#cpu { color: #83a598; }
|
||||
#memory { color: #d3869b; }
|
||||
#network { color: #fabd2f; }
|
||||
#network.disconnected { color: #fb4934; }
|
||||
#tray { padding: 0 10px; }
|
||||
|
||||
#custom-caffeine { color: #a89984; }
|
||||
#custom-caffeine.active { color: #fabd2f; }
|
||||
#custom-caffeine.active:hover { background: #3c3836; }
|
||||
|
||||
#sway-workspaces { margin: 0 4px; }
|
||||
|
||||
@keyframes blink {
|
||||
to { opacity: 0.3; }
|
||||
}
|
||||
19
dot_config/wofi/config
Normal file
19
dot_config/wofi/config
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# ~/.config/wofi/config — gruvbox launcher defaults
|
||||
# Loaded by wofi before style.css. CLI flags still win.
|
||||
|
||||
[window]
|
||||
location=top
|
||||
width=620
|
||||
height=420
|
||||
|
||||
[prompt]
|
||||
prompt=go
|
||||
insensitive=true
|
||||
|
||||
[search]
|
||||
matching=fuzzy
|
||||
sort_order=default
|
||||
|
||||
[keybindings]
|
||||
return=activate
|
||||
escape=close
|
||||
12
dot_config/wofi/powermenu.config
Normal file
12
dot_config/wofi/powermenu.config
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# ~/.config/wofi/powermenu.config — plain INI, not rasi
|
||||
# wofi's config format is INI. There is no rasi-style `configuration { }`
|
||||
# block. The icon theme comes from gsettings / dconf, not from here.
|
||||
|
||||
location=top
|
||||
yoffset=32
|
||||
width=420
|
||||
height=280
|
||||
prompt=power
|
||||
insensitive=true
|
||||
hide_scroll=true
|
||||
matching=exact
|
||||
57
dot_config/wofi/style.css
Normal file
57
dot_config/wofi/style.css
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* wofi gruvbox-material-dark-hard — extended rice */
|
||||
window {
|
||||
margin: 0px;
|
||||
border: 2px solid #d79921;
|
||||
border-radius: 10px;
|
||||
background-color: #1d2021;
|
||||
background-image: linear-gradient(to bottom, #1d2021, #282828);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
|
||||
font-family: "Maple Mono NF";
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#input {
|
||||
margin: 0px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 10px 10px 0 0;
|
||||
color: #ebdbb2;
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
#inner-box {
|
||||
margin: 0px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#outer-box {
|
||||
margin: 0px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#scroll {
|
||||
margin: 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#text {
|
||||
margin: 0px;
|
||||
padding: 6px 10px;
|
||||
border: none;
|
||||
color: #ebdbb2;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#entry {
|
||||
transition: background-color 120ms ease-out;
|
||||
}
|
||||
|
||||
#entry:selected {
|
||||
background-color: #3c3836;
|
||||
}
|
||||
|
||||
#entry:selected #text {
|
||||
color: #fabd2f;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue