Dotfiles/setup/modules/Desktop-Environments/hyprland.sh

417 lines
21 KiB
Bash
Executable File

#!/bin/bash
# =============================================================================
# hyprland.sh — Hyprland Desktop Environment installer (legacy hyprlang config)
# =============================================================================
# Part of the Dotfiles setup system for Arch Linux.
#
# Hyprland is a dynamic tiling Wayland compositor built in C++ with a focus on
# animations, eye-candy, and a powerful plugin system (hyprpm).
#
# This is the LEGACY variant that uses hyprlang (.conf) configuration files.
# The newer hyprlua.sh uses Lua for configuration instead. Both installers
# share a nearly identical package list; the key differences are:
# - EWW and config source paths point to desktopenvs/hyprland/ (not hyprlua/)
# - hypr-usr/ device-specific .conf files are placed at ~/.config/ root level
# and sourced by hyprland.conf via 'source' directives
# - hyprlua.sh additionally installs python-opencv and v4l-utils for the
# webcam-based presence/idle detection daemon
#
# High-level install flow:
# 1. System update + Flatpak
# 2. pacman packages (compositor, audio, networking, tools, fonts)
# 3. systemd service enablement (NetworkManager, ly display manager, udisks2)
# 4. AUR packages via yay
# 5. EWW status-bar (interactive form-factor selection + Rust compilation)
# 6. Themes, icons, ly config, terminal symlink, SSH askpass
# 7. Nordzy left-hand cursor theme
# 8. Bluetooth / iwd wireless services
# 9. Config file deployment from Dotfiles
# 10. Wallpaper + resource files
# 11. Python venv for helper scripts
# 12. Udiskie tray-icon symlink fix
# 13. config-updater symlinks + apply-theme.sh
#
# Prerequisites: internet access, yay (AUR helper), rustup, git, wget, cargo.
# =============================================================================
# Exit immediately if any command fails — partial DE installs can leave the
# system in a broken graphical state, so aborting early is safer.
set -e
# Load shared logging helpers (log, warn, err) from the setup library.
source "$(dirname "${BASH_SOURCE[0]}")/../lib/logging.sh"
log "Starting Hyprland installer (legacy — hyprlang config)..."
# ---------------------------------------------------------------------------
# 1. Update system and install Flatpak
# ---------------------------------------------------------------------------
# Run a full system upgrade first to avoid Arch partial-upgrade issues (on a
# rolling release, installing new packages against an un-updated system can
# cause library ABI mismatches). Flatpak is installed early so AUR steps that
# depend on it can find it.
log "Updating system and installing Flatpak..."
sudo pacman -Syu --noconfirm --needed flatpak
# ---------------------------------------------------------------------------
# 2. Install required packages
# ---------------------------------------------------------------------------
log "Installing required packages..."
# Packages live in an array so each can carry an inline comment. A single
# backslash-continued `pacman` command cannot: bash treats the first inline
# comment as the end of the command, silently dropping every later package
# (which then get run as shell commands and abort under `set -e`).
HYPRLAND_PACKAGES=(
hyprland # the Wayland compositor / window manager
hyprcursor # hardware-accelerated cursor rendering for Hyprland
wl-clipboard # wl-copy / wl-paste; clipboard tools for Wayland
hyprpaper # wallpaper utility with per-monitor and animation support
hyprlock # GPU-accelerated screen locker (Hyprland-native)
wofi # Wayland application launcher (rofi replacement)
kitty # GPU-accelerated terminal (default terminal in this setup)
dunst # lightweight, scriptable notification daemon
nwg-dock-hyprland # dock/taskbar with Hyprland workspace awareness
nwg-drawer # application drawer (grid-style launcher)
nwg-menu # GTK menu used in the panel's app button
nwg-look # GTK/cursor/icon theme picker for wlroots sessions
# Build tools needed to compile EWW (Rust) and AUR packages (C/C++/Ruby)
python cmake meson cpio pkgconf ruby-pkg-config
hyprsunset # blue-light filter / night-mode daemon for Hyprland
hypridle # idle daemon that triggers lock/suspend after inactivity
ksshaskpass # Qt SSH passphrase dialog (registered as ssh-askpass)
nm-connection-editor # GTK GUI for editing NetworkManager profiles
network-manager-applet # system-tray applet showing Wi-Fi/VPN status
blueman # GTK Bluetooth manager with tray icon
bluez # core Linux Bluetooth protocol stack
pipewire # modern audio/video routing daemon
alsa-utils # ALSA CLI tools (amixer, aplay) for low-level audio
firefox # web browser
greetd-tuigreet # TUI login greeter (text-based, no GPU needed at DM)
grim # Wayland screenshot tool (outputs to file or stdout)
slurp # interactive region selector (used with grim)
gst-plugin-pipewire # GStreamer plugin bridging through PipeWire
imagemagick # image processing (screenshot effects, compositing)
nerd-fonts # all Nerd Font patched families (icon glyphs in bar)
otf-font-awesome # Font Awesome icon glyphs for EWW/dunst
# Compatibility layers: let ALSA, JACK, and PulseAudio apps route through
# PipeWire without requiring code changes in those apps
pipewire-alsa pipewire-jack pipewire-pulse
qt5-wayland # Qt5 platform plugin for native Wayland rendering
qt6-wayland # Qt6 platform plugin for native Wayland rendering
swww # smooth animated wallpaper daemon
ttf-jetbrains-mono # monospace font for terminals and the EWW bar
wireplumber # PipeWire session/policy manager
qt6ct # Qt6 colour/style configurator (run as user)
xdg-desktop-portal-hyprland # Hyprland XDG portal (screen share, file pick)
xdg-utils # xdg-open / MIME handling helpers
xorg-server # X server for XWayland (legacy X11 apps)
xorg-xinit # startx / xinitrc support for XWayland
papirus-icon-theme # icon theme used system-wide and by udiskie
cool-retro-term # retro CRT-style terminal emulator
qalculate-gtk # powerful GTK calculator with unit conversion
iwd # Intel Wireless Daemon (lightweight Wi-Fi back-end)
dbus # D-Bus inter-process communication daemon
thunar # lightweight GTK file manager (XFCE project)
tumbler # thumbnail service for Thunar
thunar-archive-plugin # right-click archive (zip/tar) integration
thunar-shares-plugin # Samba share management from Thunar
thunar-volman # automatic volume/device mounting in Thunar
hyprpicker # colour picker outputting hex/rgb/hsl under Hyprland
pcmanfm-qt # Qt file manager kept as fallback
udisks2 # D-Bus service for querying and managing storage devices
ly # minimal TUI display manager (replaces getty on tty1)
kew # terminal music player
hyprpolkitagent # Hyprland-native Polkit authentication agent
pavucontrol # PulseAudio/PipeWire volume control GUI
playerctl # MPRIS media player controller (play/pause CLI)
wf-recorder # screen recorder for wlroots compositors
sound-theme-freedesktop # standard freedesktop sound event library
)
sudo pacman -Syu --noconfirm --needed -- "${HYPRLAND_PACKAGES[@]}"
# ---------------------------------------------------------------------------
# 3. Enable essential services
# ---------------------------------------------------------------------------
log "Enabling essential services..."
# NetworkManager must be active on boot for network connectivity.
sudo systemctl enable NetworkManager.service
# getty@tty1 is the default text-mode login prompt; we replace it with ly.
# '|| true' prevents abort if the unit is already disabled or doesn't exist.
sudo systemctl disable getty@tty1.service || true
# ly is the TUI display manager that runs on tty1 and launches Hyprland after
# the user logs in.
sudo systemctl enable ly@tty1.service
# udisks2 provides the D-Bus API for block devices; required by udiskie for
# automatic USB/external drive mounting.
sudo systemctl enable udisks2.service
# ---------------------------------------------------------------------------
# 4. Install AUR packages
# ---------------------------------------------------------------------------
log "Installing AUR packages..."
# Activate the stable Rust toolchain so AUR packages that compile Rust code
# (and EWW compiled below) use a known-good toolchain version.
rustup default stable
# yay flags:
# --answerdiff None — skip PKGBUILD diff display (non-interactive)
# --answerclean All — always clean build dirs between builds
# --noconfirm — no confirmation prompts
#
# Packages:
# hyprland-workspaces — EWW workspace widget reading Hyprland IPC socket
# vicinae-bin — pre-built vicinae (vim-like keybind layer for scripts)
# bluetuith — TUI Bluetooth manager (used in the menus)
# wvkbd — on-screen virtual keyboard for Wayland (touch)
# iwmenu — wofi-based Wi-Fi network picker using iwd
# pinta — simple image editor
# walker-bin — fast app launcher / runner (pre-built binary)
# ulauncher — extensible app launcher with plugin ecosystem
# bzmenu — quick Bluetooth device connect menu for the bar
# udiskie — automounter with tray icon (built on udisks2)
# wofi-calc — inline calculator pop-up inside wofi
# bri — brightness control CLI helper for bar widgets
# chamel — theme-switching helper (applies colour palettes)
yay -Syu --answerdiff None --answerclean All --noconfirm \
hyprland-workspaces vicinae-bin bluetuith wvkbd iwmenu pinta \
walker-bin ulauncher bzmenu udiskie \
wofi-calc bri chamel
# ---------------------------------------------------------------------------
# 5. EWW bar selection and compilation
# ---------------------------------------------------------------------------
# EWW (Elkowar's Wacky Widgets) is a Rust widget framework that powers the
# custom status bar. Three layouts exist for different hardware form factors:
# eww/ — Notebook layout (includes battery widget)
# eww-nobattery/ — Desktop PC layout (no battery bar)
# eww-touch/ — Tablet layout (larger touch targets)
log "Setting up EWW bar..."
# Wipe any previous EWW config to avoid stale widget definitions conflicting
# with the freshly copied one.
rm -rf ~/.config/eww
# Prompt for form factor with a single keypress (no Enter needed).
read -n1 -p "Install eww bar for PC, Notebook or Tablet [P/N/T]: " doit
echo # Print newline so subsequent output starts on a fresh line
case $doit in
# Notebook: copy the battery-aware layout
n|N) cp -rf ~/Dotfiles/desktopenvs/hyprland/eww/ ~/.config/ ;;
# Desktop PC: copy the no-battery layout
p|P) cp -rf ~/Dotfiles/desktopenvs/hyprland/eww-nobattery/ ~/.config/eww ;;
# Tablet: copy touch-optimised layout
t|T) cp -rf ~/Dotfiles/desktopenvs/hyprland/eww-touch/ ~/.config/eww ;;
# Unknown key: warn and skip; the user must copy manually later
*) warn "No valid choice — skipping EWW copy. Run manually later." ;;
esac
log "Compiling EWW..."
# EWW is not in the official repos so we compile from source.
# ~/install-tmp is a staging area for source trees fetched during installation.
mkdir -p ~/install-tmp
cd ~/install-tmp
git clone https://github.com/elkowar/eww
cd eww
# --release → optimised binary (significantly faster than debug)
# --no-default-features → disable the X11 backend entirely
# --features=wayland → enable only the Wayland backend
cargo build --release --no-default-features --features=wayland
chmod +x target/release/eww
# Install system-wide so any autostart entry or script can call 'eww' directly.
sudo cp target/release/eww /usr/bin/
cd ~ # Return home so subsequent relative-path steps work correctly
# ---------------------------------------------------------------------------
# 6. Theme and icon setup
# ---------------------------------------------------------------------------
log "Installing themes and icons..."
# Install the cyberqueer GTK theme system-wide so GTK2/3/4 apps pick it up.
sudo cp -r ~/Dotfiles/gtk-themes/cyberqueer /usr/share/themes
# Install the matching btop colour theme for the terminal system monitor.
sudo cp ~/Dotfiles/desktopenvs/hyprland/btop/themes/cyberqueer.theme /usr/share/btop/themes
# Deploy the ly display-manager config (login screen appearance, session list).
sudo cp -f ~/Dotfiles/etc-ly-config.ini /etc/ly/config.ini
# Register kitty as the system-default terminal for xdg-terminal-exec so
# file managers and scripts that call "Open Terminal Here" launch kitty.
sudo ln -sf /usr/bin/kitty /usr/bin/xdg-terminal-exec
# Register ksshaskpass as the SSH passphrase helper.
# When SSH needs a passphrase in a non-terminal context (e.g. git push from a
# script), it invokes /usr/lib/ssh/ssh-askpass; this link provides a GUI dialog.
sudo ln -sf /usr/bin/ksshaskpass /usr/lib/ssh/ssh-askpass
# ---------------------------------------------------------------------------
# 7. Cursor setup
# ---------------------------------------------------------------------------
# Nordzy-cursors-lefthand is a Nord-palette left-handed cursor theme.
# Downloaded from GitHub Releases rather than the AUR because the AUR build
# may lag behind the upstream release schedule.
log "Installing cursor theme..."
mkdir -p ~/.icons
wget -O ~/install-tmp/Nordzy-cursors-lefthand.tar.gz \
https://github.com/guillaumeboehm/Nordzy-cursors/releases/download/v2.3.0/Nordzy-cursors-lefthand.tar.gz
# Extract directly into ~/.icons/ so the theme is immediately discoverable by
# Hyprland (via hyprcursor) and by GTK applications.
tar -zxf ~/install-tmp/Nordzy-cursors-lefthand.tar.gz -C ~/.icons/
# ---------------------------------------------------------------------------
# 8. Enable Bluetooth and wireless services
# ---------------------------------------------------------------------------
log "Enabling Bluetooth and wireless services..."
# bluez: core Bluetooth protocol stack (powers and manages adapters on boot)
sudo systemctl enable bluez
# bluetooth.service: high-level service handling pairing and profiles
sudo systemctl enable bluetooth.service
# iwd: modern Wi-Fi daemon from Intel; used by iwmenu for the bar Wi-Fi picker
sudo systemctl enable iwd.service
# ---------------------------------------------------------------------------
# 9. Hyprland plugins (must be run from inside a live Hyprland session)
# ---------------------------------------------------------------------------
# hyprpm links against the exact compositor binary, so it cannot run from the
# installer. Execute these commands manually after first login:
# hyprpm update
# hyprpm add https://github.com/hyprwm/hyprland-plugins
# ---------------------------------------------------------------------------
# 10. Copy configs
# ---------------------------------------------------------------------------
log "Copying configs..."
# Each entry in CONFIGS maps to a sub-directory (or file) inside
# desktopenvs/hyprland/ that is deployed verbatim to ~/.config/.
# Old copies are wiped first to prevent stale files from prior installs
# interfering with the fresh deployment.
CONFIGS=(kitty mimeapps.list vicinae walker ulauncher hypr xfce4 wofi dunst alacritty nwg-dock-hyprland nwg-drawer nwg-panel scripts btop gtk-3.0)
for cfg in "${CONFIGS[@]}"; do
rm -rf ~/.config/"$cfg"
cp -r ~/Dotfiles/desktopenvs/hyprland/"$cfg" ~/.config/
done
# hypr-usr/ holds device-specific overrides (monitor layout, keybinds, envvars).
# In the legacy hyprlang setup these are .conf files at the ~/.config/ root
# level; hyprland.conf sources them with 'source = ~/.config/monitors.conf' etc.
cp ~/Dotfiles/desktopenvs/hyprland/hypr-usr/* ~/.config/
# colors.conf defines the shared colour palette used by EWW, dunst, and scripts.
cp ~/Dotfiles/colors.conf ~/.config/colors.conf
# ---------------------------------------------------------------------------
# 11. Wallpaper and resources
# ---------------------------------------------------------------------------
log "Copying wallpaper and resources..."
mkdir -p ~/Pictures
# Firefox logo SVG used as the dock/launcher shortcut icon.
cp ~/Dotfiles/resources/fflogo.svg ~/Pictures/fflogo.svg
# Download the personalised wallpaper from the owner's Nextcloud instance.
# ?v=15 is a cache-buster version parameter on the Nextcloud theming API.
wget "https://cloud.abdelbaki.eu/apps/theming/image/background?v=15" -O ~/Pictures/background.jpg
# ---------------------------------------------------------------------------
# 12. Python venv for scripts
# ---------------------------------------------------------------------------
# Many EWW and Hyprland helper scripts are written in Python and need these
# third-party libraries. An isolated venv avoids polluting the system Python
# and prevents conflicts with pacman-managed Python packages.
log "Setting up Python venv for scripts..."
python -m venv ~/.config/python-script
~/.config/python-script/bin/pip install \
speedtest-cli `# Internet speed test widget for the EWW bar` \
requests `# HTTP client used by various widgets and scripts` \
pint `# Unit conversion library for the calculator script` \
simpleeval `# Safe maths expression evaluator (wofi-calc backend)` \
parsedatetime `# Natural-language date/time parser for timer scripts`
# ---------------------------------------------------------------------------
# 13. Udiskie icon fix
# ---------------------------------------------------------------------------
# udiskie uses freedesktop icon names (udiskie-checkbox-checked, etc.) that
# most icon themes do not ship. We symlink them from Papirus-Dark's existing
# checkbox icons as a close visual match. Placing symlinks in the hicolor
# theme ensures every GTK app can find them as hicolor is the last-resort
# fallback in the icon theme lookup chain.
log "Applying Udiskie icon fix..."
PAPIRUS_DIR="/usr/share/icons/Papirus-Dark/status"
HICOLOR_DIR="/usr/share/icons/hicolor/scalable/status"
if [ -d "$PAPIRUS_DIR" ]; then
sudo ln -sf "$PAPIRUS_DIR/checkbox-checked.svg" "$HICOLOR_DIR/udiskie-checkbox-checked.svg"
sudo ln -sf "$PAPIRUS_DIR/checkbox-unchecked.svg" "$HICOLOR_DIR/udiskie-checkbox-unchecked.svg"
# Rebuild the icon cache so GTK discovers the new symlinked entries without
# requiring a full logout/login.
sudo gtk-update-icon-cache -f -t /usr/share/icons/hicolor
else
warn "Papirus-Dark not found — skipping udiskie icon fix."
fi
# ---------------------------------------------------------------------------
# 14. Enable udiskie
# ---------------------------------------------------------------------------
# udiskie is the auto-mounter / tray-icon daemon that surfaces mounted volumes.
# Enable the systemd user unit and start it immediately so this session already
# benefits from auto-mounting without requiring a reboot.
log "Enabling udiskie service..."
sudo systemctl enable udiskie.service
sudo systemctl start udiskie.service
# ---------------------------------------------------------------------------
# 15. Install config updater and theme script
# ---------------------------------------------------------------------------
# config-updater is a lightweight mechanism that re-syncs selected config files
# from the Dotfiles repo without running the full installer again.
# updater.conf lists which files to keep in sync; update-configs.sh performs
# the actual copy operation.
#
# Symlinks (ln -sf) are used so that 'git pull' in ~/Dotfiles immediately takes
# effect the next time update-configs.sh is run.
log "Installing config updater and theme script..."
mkdir -p ~/.config/config-updater
ln -sf ~/Dotfiles/desktopenvs/hyprland/config-updater/updater.conf ~/.config/config-updater/updater.conf
ln -sf ~/Dotfiles/desktopenvs/hyprland/config-updater/update-configs.sh ~/update-configs.sh
# apply-theme.sh applies the cyberqueer colour palette across all running apps
# (sets GTK/Qt themes, reloads dunst config, refreshes EWW colour variables).
# Copied (not symlinked) to ~ so it works even if ~/Dotfiles is unmounted.
cp ~/Dotfiles/apply-theme.sh ~/apply-theme.sh
chmod +x ~/apply-theme.sh
# ---------------------------------------------------------------------------
# 16. WallRizz (run manually after login — requires a running desktop session)
# ---------------------------------------------------------------------------
# WallRizz generates a colour scheme from the active wallpaper and applies it
# to EWW, dunst, and terminals. It requires a live Wayland session and cannot
# be safely run from this installer script.
# Uncomment and run manually after your first login:
# curl -sL "$(curl -s https://api.github.com/repos/5hubham5ingh/WallRizz/releases/latest \
# | grep -Po '"browser_download_url": "\K[^"]+' | grep WallRizz)" | tar -xz \
# && sudo mv WallRizz /usr/bin/
log "Hyprland installation complete. Reboot to start."