diff --git a/README.md b/README.md index 040746a..fefaae8 100755 --- a/README.md +++ b/README.md @@ -36,6 +36,171 @@ EndSection ``` ![stones](./screenshots/Screenshot_20240503_095414.png) +## Installing dependencies + +Package availability differs between distros — Arch has everything below in the +official/multilib repos, no AUR needed. Gentoo's main tree is missing a few +newer tools (noted below); those need the [GURU overlay](https://wiki.gentoo.org/wiki/Project:GURU) +or manual/cargo install. + +### Window manager & session (both i3 and sway) + +**Arch** +```bash +sudo pacman -S i3-wm i3status i3blocks sway swaybg swaylock swayidle \ + waybar polybar rofi alacritty dex snixembed \ + xss-lock xorg-xset xclip scrot imagemagick i3lock \ + network-manager-applet blueman gnome-keyring \ + pipewire wireplumber pipewire-pulse pipewire-alsa pipewire-jack \ + pasystray playerctl brightnessctl \ + fcitx5 fcitx5-im fcitx5-configtool +``` + +**Gentoo** +```bash +sudo emerge --ask \ + x11-wm/i3 x11-misc/i3status x11-misc/i3blocks \ + gui-wm/sway gui-apps/swaybg gui-apps/swaylock gui-apps/swayidle \ + gui-apps/waybar x11-misc/polybar x11-misc/rofi x11-terms/alacritty \ + x11-misc/dex x11-misc/snixembed \ + x11-misc/xss-lock x11-apps/xset x11-misc/xclip media-gfx/scrot \ + media-gfx/imagemagick x11-misc/i3lock \ + net-misc/networkmanager net-misc/network-manager-applet net-wireless/blueman \ + app-crypt/gnome-keyring \ + media-video/pipewire media-video/wireplumber media-sound/playerctl \ + app-i18n/fcitx app-i18n/fcitx-qt app-i18n/fcitx-gtk +``` +- `brightnessctl` is **not in the main Gentoo tree** — install from the GURU + overlay (`sudo emerge --ask brightnessctl`, after enabling GURU below) or + build from source. Add your user to the `video` and `input` groups either way. +- PipeWire's PulseAudio/ALSA/JACK compatibility on Gentoo is controlled by + USE flags (`pulseaudio`/`alsa`/`jack`... check `equery u media-video/pipewire`) + rather than separate packages. +- `pasystray` (systray volume icon) is not in the main tree either; the GURU + overlay or `pavucontrol` are common substitutes. + +Enable the GURU overlay once, needed by several packages below: +```bash +sudo eselect repository enable guru +sudo emerge --sync guru +``` + +### Wayland screenshots, clipboard, and screen sharing (sway) + +These are the pieces the Print-key bindings and screen sharing/recording in +`sway/config` depend on — without `xdg-desktop-portal-wlr` specifically, +no app (browser tab share, Discord, OBS) can capture the screen at all. + +**Arch** +```bash +sudo pacman -S grim slurp wl-clipboard cliphist \ + xdg-desktop-portal xdg-desktop-portal-wlr xdg-desktop-portal-gtk \ + wf-recorder obs-studio +``` + +**Gentoo** +```bash +sudo emerge --ask \ + gui-apps/grim gui-apps/slurp gui-apps/wl-clipboard \ + sys-apps/xdg-desktop-portal gui-libs/xdg-desktop-portal-wlr sys-apps/xdg-desktop-portal-gtk \ + media-video/wf-recorder media-video/obs-studio +``` +- `cliphist` (clipboard history) is not in the main tree — GURU overlay. + +After installing the portal packages, restart the portal service so it picks +up the new backend: +```bash +systemctl --user restart xdg-desktop-portal +``` + +### AMD GPU stack (mesa/RADV/amdgpu) + +**Arch** +```bash +sudo pacman -S mesa lib32-mesa vulkan-radeon lib32-vulkan-radeon \ + xf86-video-amdgpu linux-firmware-amdgpu libvdpau-va-gl +``` +Mesa on current Arch already bundles the VA-API driver (`radeonsi_drv_video.so`) +and there's no separate `mesa-vdpau`/`lib32-mesa-vdpau` package anymore — +`libvdpau-va-gl` is the VDPAU-to-VA-API translation layer that replaces it. + +**Gentoo** +```bash +# In /etc/portage/make.conf: +# VIDEO_CARDS="amdgpu radeonsi" +sudo emerge --ask media-libs/mesa media-libs/vulkan-loader \ + x11-drivers/xf86-video-amdgpu media-video/libvdpau media-libs/libvdpau-va-gl +``` +Make sure `mesa` is built with `USE="vulkan"` and, for 32-bit/Steam +compatibility, `ABI_X86="32 64"` in `package.use`. + +### Gaming & performance + +**Arch** +```bash +sudo pacman -S gamemode lib32-gamemode mangohud lib32-mangohud +``` + +**Gentoo** +```bash +sudo emerge --ask games-util/gamemode +``` +- `mangohud` is **not in the main Gentoo tree** — GURU overlay + (`sudo emerge --ask games-util/mangohud` after enabling GURU). + +### GPU monitoring & tuning + +**Arch** +```bash +sudo pacman -S radeontop amdgpu_top nvtop lact lm_sensors +``` + +**Gentoo** +```bash +sudo emerge --ask app-misc/radeontop sys-process/nvtop sys-power/lm-sensors +``` +- `amdgpu_top`, `lact`, and `corectrl` (fan curves/overclocking GUIs) are not + in the main tree — GURU overlay, or install `lact`/`amdgpu_top` via `cargo` + since both are Rust tools. + +### Razer peripherals (polling rate, DPI, RGB) + +**Arch** +```bash +sudo pacman -S openrazer-daemon openrazer-meta polychromatic +sudo gpasswd -a $USER plugdev +``` + +**Gentoo** +```bash +sudo emerge --ask sys-apps/openrazer +sudo gpasswd -a $USER plugdev +``` +- Gentoo ships a single unified `sys-apps/openrazer` package (driver + + daemon together) rather than split `-daemon`/`-meta` packages. + `polychromatic` (GUI) is not in the main tree — GURU overlay. + +### Notifications & fonts + +**Arch** +```bash +sudo pacman -S ttf-firacode-nerd +# tiramisu (notification daemon) is AUR-only on Arch: yay -S tiramisu +``` + +**Gentoo** +```bash +sudo emerge --ask media-fonts/nerd-fonts +``` +- `tiramisu` is not in the main Gentoo tree — GURU overlay or build from + source (https://github.com/Sweets/tiramisu). + +### PipeWire launcher (Gentoo only) + +`sway/config` calls `gentoo-pipewire-launcher`, the community launcher script +documented on the [Gentoo PipeWire wiki page](https://wiki.gentoo.org/wiki/PipeWire) — +it's a shell script you place on your `PATH` yourself, not a portage package. + ## Vim ### Vimplug diff --git a/i3/config b/i3/config index db9eb5a..41af263 100755 --- a/i3/config +++ b/i3/config @@ -10,7 +10,7 @@ # Please see https://i3wm.org/docs/userguide.html for a complete reference! set $mod Mod1 -set $wallpaper_dir /sync/images/wallpapers +set $wallpaper_dir /media/sync/images/wallpapers set $terminal 'alacritty' # Font for window titles. Will also be used by the bar unless a different font # is used in the bar {} block below. @@ -29,7 +29,6 @@ exec --no-startup-id dex --autostart --environment i3 #exec --no-startup-id /usr/bin/gnome-keyring-daemon --start --components=gpg,pkcs11,secrets,ssh # xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the # screen before suspend. Use systemctl lock-session to lock your screen. -exec --no-startup-id xrandr --output HDMI-0 --mode 1920x1080 --rate 120 # burn-in prevention: blank after 5min, DPMS off after 10min, skip lock if fullscreen exec --no-startup-id xset b off @@ -55,7 +54,7 @@ exec --no-startup-id blueman-applet exec --no-startup-id /usr/bin/gnome-keyring-daemon --start --components=ssh,pkcs11 exec --no-startup-id /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 exec --no-startup-id ~/.config/i3/scripts/wallpaper-rotate $wallpaper_dir -#exec --no-startup-id pasystray +exec --no-startup-id pasystray exec --no-startup-id polybar set $refresh_i3status killall -SIGUSR1 i3status @@ -260,7 +259,7 @@ bindsym $mod+r mode "resize" for_window [class="signal"] floating enable for_window [class="Dino"] floating enable for_window [class="firefox"] move container to workspace 1 -for_window [class="thunderbird"] move container to workspace 4 +for_window [class="eu.betterbird.Betterbird"] move container to workspace 4 for_window [class="Thunar"] move container to workspace 3 for_window [class="steam_app_1364781"] border none, fullscreen enable diff --git a/i3/scripts/volume_brightness.sh b/i3/scripts/volume_brightness.sh deleted file mode 100755 index 676c6d3..0000000 --- a/i3/scripts/volume_brightness.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env bash - -# original source: https://gitlab.com/Nmoleo/i3-volume-brightness-indicator -# changed to use brightnessctl [xbacklight is non functional on modern hardware] -# by joekamprad [Aug 2025] - -bar_color="#7f7fff" -volume_step=1 -brightness_step=5 -max_volume=100 -notification_timeout=1000 # in ms - -# Uses regex to get volume from pactl -function get_volume { - pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '[0-9]{1,3}(?=%)' | head -1 -} - -# Uses regex to get mute status from pactl -function get_mute { - pactl get-sink-mute @DEFAULT_SINK@ | grep -Po '(?<=Mute: )(yes|no)' -} - -# Uses brightnessctl instead of xbacklight -function get_brightness { - brightnessctl g | awk '{print int($1)}' - # You could also use: brightnessctl info | grep -Po '(?<=Current brightness: )[0-9]+' -} - -# Calculates brightness percentage -function get_brightness_percent { - current=$(brightnessctl g) - max=$(brightnessctl m) - percent=$(( 100 * current / max )) - echo $percent -} - -function get_volume_icon { - volume=$(get_volume) - mute=$(get_mute) - if [ "$volume" -eq 0 ] || [ "$mute" == "yes" ] ; then - volume_icon="" - elif [ "$volume" -lt 50 ]; then - volume_icon="" - else - volume_icon="" - fi -} - -function get_brightness_icon { - brightness_icon="" -} - -function show_volume_notif { - volume=$(get_volume) - get_volume_icon - notify-send -i volume_icon -t 1000 "Volume" "$volume_icon $volume%" -h int:value:$volume -h string:x-canonical-private-synchronous:volume -} - - -function show_brightness_notif { - get_brightness_icon - brightness=$(get_brightness_percent) - notify-send -i brightness_icon -t $notification_timeout -h string:x-dunst-stack-tag:brightness_notif -h int:value:$brightness "$brightness_icon $brightness%" -} - - - -case $1 in - volume_up) - pactl set-sink-mute @DEFAULT_SINK@ 0 - volume=$(get_volume) - if [ $(( "$volume" + "$volume_step" )) -gt $max_volume ]; then - pactl set-sink-volume @DEFAULT_SINK@ $max_volume% - else - pactl set-sink-volume @DEFAULT_SINK@ +$volume_step% - fi - show_volume_notif - ;; - volume_down) - pactl set-sink-volume @DEFAULT_SINK@ -$volume_step% - show_volume_notif - ;; - volume_mute) - pactl set-sink-mute @DEFAULT_SINK@ toggle - show_volume_notif - ;; - brightness_up) - brightnessctl s +$brightness_step% > /dev/null - show_brightness_notif - ;; - brightness_down) - brightnessctl s $brightness_step%- > /dev/null - show_brightness_notif - ;; -esac diff --git a/sway/config b/sway/config index b86642d..ba8608f 100755 --- a/sway/config +++ b/sway/config @@ -14,40 +14,50 @@ set $mod Mod1 #set $up k #set $right l # Your preferred terminal emulator -set $term xfce4-terminal +set $term alacritty # Your preferred application launcher # Note: pass the final command to swaymsg so that the resulting window can be opened # on the original workspace that the command was run on. #set $menu wofi --show drun set $menu rofi -show drun +# Font for window titles. +font pango:NotoSans 12 + ### Output configuration # -# Default wallpaper (more resolutions are available in /usr/share/backgrounds/sway/) -set $bg /data/sync/images/wallpapers/0002.png -set $screenlock 'swaylock -i $bg' -set $images $(xdg-user-dir PICTURES)/$(date +'%s_grim.png') +set $wallpaper_dir /media/sync/images/wallpapers +set $screenlock '~/.config/sway/scripts/lock-now $wallpaper_dir' # -exec --no-startup-id swaybg -m fill -i $bg +exec --no-startup-id ~/.config/sway/scripts/wallpaper-rotate $wallpaper_dir # Example configuration: # #output HDMI-A-1 resolution 1920x1080@120hz position 1920,0 # # You can get the names of your outputs by running: swaymsg -t get_outputs +output DP-2 adaptive_sync on ### Idle configuration # +# Import the compositor socket into the systemd --user environment. Without +# this, systemd-managed services (and dbus-activated apps like portals) can't +# reach the compositor at all - this is why swayidle silently failed to run +# after being restarted via systemd earlier. +exec --no-startup-id systemctl --user import-environment WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP DISPLAY +exec --no-startup-id hash dbus-update-activation-environment 2>/dev/null && dbus-update-activation-environment --systemd WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP DISPLAY +# # Example configuration: # exec swayidle -w \ - timeout 900 $screenlock \ - timeout 1800 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \ + timeout 300 $screenlock \ + timeout 900 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \ before-sleep $screenlock # -# This will lock your screen after 300 seconds of inactivity, then turn off -# your displays after another 300 seconds, and turn your screens back on when -# resumed. It will also lock your screen before your computer goes to sleep. +# This will lock your screen after 300 seconds (5 min) of inactivity, then +# turn off your displays after 900 seconds (15 min), and turn your screens +# back on when resumed. It will also lock your screen before your computer +# goes to sleep. ### Input configuration input "type:touchpad" { @@ -70,7 +80,7 @@ exec swayidle -w \ input "2:7:SynPS/2_Synaptics_TouchPad" { events disabled_on_external_mouse } -input "5426:156:Razer_Razer_DeathAdder_V2_X_HyperSpeed" { +input "5426:156:Razer_Razer_DeathAdder_V2_X_HyperSpeed_Mouse" { accel_profile "flat" # disable mouse acceleration (enabled by default; to set it manually, use "adaptive" instead of "flat") pointer_accel 0.5 # set mouse sensitivity (between -1 and 1) } @@ -117,8 +127,8 @@ bindsym $mod+Shift+comma exec playerctl previous bindsym $mod+Shift+period exec playerctl next bindsym $mod+Shift+slash exec playerctl play-pause -bindsym Print exec grim -g "$(slurp)" - | wl-copy -bindsym $mod+Print exec grim -o $images +bindsym Print exec --no-startup-id bash -c 'f="$(xdg-user-dir PICTURES)/$(date +%s_grim.png)" && grim -g "$(slurp)" "$f" && wl-copy < "$f" && notify-send "Screenshot saved" "$f"' +bindsym $mod+Print exec --no-startup-id bash -c 'f="$(xdg-user-dir PICTURES)/$(date +%s_grim.png)" && grim "$f" && wl-copy < "$f" && notify-send "Screenshot saved" "$f"' ### Key bindings # # Basics: @@ -132,16 +142,19 @@ bindsym $mod+Shift+q kill # Start your launcher bindsym $mod+d exec $menu # -bindsym $mod+l exec $screenlock +bindsym $mod+l exec ~/.config/sway/scripts/lock-now $wallpaper_dir +bindsym $mod+Shift+o exec ~/.config/sway/scripts/lock-now $wallpaper_dir && systemctl suspend # Drag floating windows by holding down $mod and left mouse button. # Resize them with right mouse button + $mod. # Despite the name, also works for non-floating windows. # Change normal to inverse to use left mouse button for resizing and right # mouse button for dragging. -floating_modifier $mod normal +floating_modifier $mod # Reload the configuration file bindsym $mod+Shift+c reload +# restart sway in place (preserves your layout/session, can be used to upgrade sway) +bindsym $mod+Shift+r restart # Exit sway (logs you out of your Wayland session) #bindsym $mod+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' @@ -197,10 +210,10 @@ bindsym $mod+Shift+0 move container to workspace number 10 # Layout stuff: # # You can "split" the current object of your focus with -# $mod+b or $mod+v, for horizontal and vertical splits +# $mod+h or $mod+v, for horizontal and vertical splits # respectively. -bindsym $mod+b splith -bindsym $mod+v splitv +bindsym $mod+h split h +bindsym $mod+v split v # Switch the current container between different layout styles bindsym $mod+s layout stacking @@ -208,7 +221,7 @@ bindsym $mod+w layout tabbed bindsym $mod+e layout toggle split # Make the current focus fullscreen -bindsym $mod+Shift+space fullscreen +bindsym $mod+Shift+space fullscreen toggle # Toggle the current focus between tiling and floating mode bindsym $mod+f floating toggle @@ -259,15 +272,21 @@ mode "resize" { } bindsym $mod+r mode "resize" -# -# Status Bar: -# -# Read `man 5 sway-bar` for more information about this section. -bar { -} +# Status bar is provided by waybar (started above); no built-in sway bar. + + # class border bground text indicator child_border + client.focused #3A7CA5 #3A7CA5 #E2EBF0 #0D1B27 #3A7CA5 + client.placeholder #0D1B27 #0D1B27 #BDD5E4 #0D1B27 #0D1B27 + client.unfocused #0D1B27 #152535 #6A8DA0 #0D1B27 #152535 + client.focused_inactive #1A3347 #1A3347 #6A8DA0 #1A3347 #1A3347 for_window [class="^.*"] border pixel 1 +# Don't lock or blank the screen while a fullscreen window (game, video, +# presentation) is focused - ties into the same idle protocol swayidle uses. +for_window [app_id="^.*"] inhibit_idle fullscreen +for_window [class="^.*"] inhibit_idle fullscreen + #floating for_window [app_id="signal"] floating enable for_window [app_id="fluffychat"] floating enable diff --git a/sway/scripts/lock-now b/sway/scripts/lock-now new file mode 100755 index 0000000..0ca6094 --- /dev/null +++ b/sway/scripts/lock-now @@ -0,0 +1,8 @@ +#!/bin/bash +wall_dir="${1:?wallpaper directory required}" +img=$(find "$wall_dir" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) | shuf -n1) +if [ -n "$img" ]; then + exec swaylock -i "$img" +else + exec swaylock +fi diff --git a/sway/scripts/wallpaper-rotate b/sway/scripts/wallpaper-rotate new file mode 100755 index 0000000..e6e3e5c --- /dev/null +++ b/sway/scripts/wallpaper-rotate @@ -0,0 +1,48 @@ +#!/bin/bash +wall_dir="${1:?wallpaper directory required}" +interval="${2:-1800}" + +pick_wall() { + find "$wall_dir" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) | shuf -n1 +} + +set_wall() { + [ -n "$1" ] || return + pkill -x swaybg + swaybg -m fill -i "$1" & +} + +has_fullscreen() { + python3 - <<'EOF' +import json, subprocess, sys + +def is_fullscreen(node): + if node.get('window') and node.get('fullscreen_mode', 0) > 0: return True + return any(is_fullscreen(c) for c in node.get('nodes', []) + node.get('floating_nodes', [])) + +def find_ws(node, name): + if node.get('type') == 'workspace' and node.get('name') == name: return node + for c in node.get('nodes', []) + node.get('floating_nodes', []): + r = find_ws(c, name) + if r: return r + +try: + wss = json.loads(subprocess.check_output(['swaymsg', '-t', 'get_workspaces'], stderr=subprocess.DEVNULL)) + tree = json.loads(subprocess.check_output(['swaymsg', '-t', 'get_tree'], stderr=subprocess.DEVNULL)) + for ws in wss: + if ws.get('visible'): + node = find_ws(tree, ws['name']) + if node and is_fullscreen(node): + sys.exit(0) +except Exception: + pass +sys.exit(1) +EOF +} + +# Initial wallpaper +set_wall "$(pick_wall)" + +while sleep "$interval"; do + has_fullscreen || set_wall "$(pick_wall)" +done diff --git a/sway/swaylock.conf b/sway/swaylock.conf index adeb4c7..e055111 100755 --- a/sway/swaylock.conf +++ b/sway/swaylock.conf @@ -1,5 +1,4 @@ -# Set a background image -image=/data/sync/images/wallpapers/0002.png +# Background image is picked at lock time by scripts/lock-now (-i flag) # Set the scaling mode for the image scaling=fill