Phase 6: Desktop Environment

Phase 6: Desktop Environment

NVIDIA GPU

RTX 5090 requires the open kernel module β€” the proprietary nvidia package doesn’t exist for this GPU generation.

# nvidia-open for main kernel, nvidia-open-lts for LTS fallback kernel
sudo pacman -S nvidia-open nvidia-open-lts nvidia-utils nvidia-settings lib32-nvidia-utils

Sync Kernels to ESP

The nvidia install regenerated initramfs images on /boot (ext4). systemd-boot reads from the ESP β€” sync now, then set up a pacman hook so it’s automatic.

sudo cp /boot/vmlinuz-linux /boot/efi/
sudo cp /boot/vmlinuz-linux-lts /boot/efi/
sudo cp /boot/initramfs-linux.img /boot/efi/
sudo cp /boot/initramfs-linux-lts.img /boot/efi/
sudo cp /boot/intel-ucode.img /boot/efi/
# Verify
ls -lh /boot/efi/vmlinuz-* /boot/efi/initramfs-* /boot/efi/intel-ucode.img
df -h /boot/efi

Pacman Hook: Auto-Sync Kernels to ESP

Without this, every kernel or nvidia update requires manual copy. This hook runs automatically after pacman upgrades.

sudo mkdir -p /etc/pacman.d/hooks
sudo tee /etc/pacman.d/hooks/99-esp-kernel-sync.hook << 'HOOKEOF'
[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = boot/*

[Action]
Description = Syncing kernels and initramfs to ESP...
When = PostTransaction
Exec = /bin/sh -c 'cp /boot/vmlinuz-* /boot/efi/ && cp /boot/initramfs-linux.img /boot/initramfs-linux-lts.img /boot/intel-ucode.img /boot/efi/'
HOOKEOF
cat /etc/pacman.d/hooks/99-esp-kernel-sync.hook

Reboot for NVIDIA Module

sudo reboot

SSH back in, then verify:

nvidia-smi

Hyprland Stack

sudo pacman -S \
    hyprland xdg-desktop-portal-hyprland \
    waybar wofi mako \
    hyprlock hypridle hyprpaper \
    grim slurp wl-clipboard cliphist swappy

Terminals

sudo pacman -S kitty
yay -S ghostty

Fonts

sudo pacman -S \
    ttf-jetbrains-mono-nerd ttf-nerd-fonts-symbols ttf-font-awesome \
    noto-fonts noto-fonts-emoji noto-fonts-cjk

Audio

sudo pacman -S pipewire pipewire-alsa pipewire-pulse pipewire-jack wireplumber pavucontrol
systemctl --user enable --now pipewire pipewire-pulse wireplumber

Audio Verification

The P16g has onboard Dolby Atmos speakers that require Intel Sound Open Firmware (SOF).

# Install SOF firmware (REQUIRED for onboard speakers)
sudo pacman -S sof-firmware
Reboot required after installing sof-firmware β€” firmware loads at kernel boot.
# After reboot: verify PipeWire sees real audio devices (not "Dummy Output")
wpctl status
# List audio sinks (should show onboard speakers, not just HDMI)
pactl list sinks short
# Set default sink (if multiple sinks detected)
wpctl set-default <SINK_ID>
# Test audio output (pw-play is native PipeWire β€” no alsa-utils dependency)
pw-play /usr/share/sounds/freedesktop/stereo/bell.oga
# Target a specific sink by ID (find IDs with: wpctl status)
pw-play --target <SINK_ID> /usr/share/sounds/freedesktop/stereo/bell.oga
# Volume control (CLI)
wpctl set-volume @DEFAULT_AUDIO_SINK@ 50%
# GUI volume control
pavucontrol &

Audio Troubleshooting

Symptom Fix

Dummy Output only, no real sinks

sof-firmware not installed. Install + reboot.

RTX 5090 HDMI audio detected but no speakers

Same β€” sof-firmware missing. HDMI audio is from GPU, onboard needs SOF.

PipeWire not running

systemctl --user enable --now pipewire pipewire-pulse wireplumber

No sound after reboot

Check wpctl status, verify correct sink is default, check pactl list sinks

Crackling/distortion

pw-top to check for xruns. Try PIPEWIRE_LATENCY=256/48000 in environment.

Bluetooth

sudo pacman -S bluez bluez-utils blueman
sudo systemctl enable --now bluetooth

Bluetooth Verification & Pairing

Start Bluetooth Service

# Enable and start (if not already)
sudo systemctl enable --now bluetooth.service
# Verify running
systemctl is-active bluetooth.service

Pair a Device (Interactive)

bluetoothctl

Inside bluetoothctl:

# Power on the adapter
power on

# Enable scanning
scan on

# Wait for your device to appear (e.g., Galaxy Buds3 Pro)
# Look for the MAC address in the output

# Pair with the device
pair XX:XX:XX:XX:XX:XX

# Trust (auto-connect on future boots)
trust XX:XX:XX:XX:XX:XX

# Connect
connect XX:XX:XX:XX:XX:XX

# Stop scanning and exit
scan off
quit

Verify Bluetooth Audio

After pairing Bluetooth headphones/earbuds:

# Should show Bluetooth audio sink
wpctl status
# Switch audio output to Bluetooth device
wpctl set-default <BT_SINK_ID>
# Test audio through Bluetooth
pw-play /usr/share/sounds/freedesktop/stereo/bell.oga

Bluetooth Troubleshooting

Symptom Fix

bluetoothctl shows no controller

sudo systemctl restart bluetooth.service β€” adapter may need reset

Device not discovered during scan

Put device in pairing mode (varies by device). Check rfkill list for soft block.

Paired but no audio

Check wpctl status β€” Bluetooth sink may not be default. Run wpctl set-default <ID>.

Audio stutters over Bluetooth

Switch codec: pactl list cards then pactl set-card-profile <card> a2dp-sink-sbc_xq

rfkill blocks Bluetooth

rfkill unblock bluetooth

File Manager & Tools

sudo pacman -S \
    thunar thunar-volman gvfs tumbler ffmpegthumbnailer \
    zathura zathura-pdf-mupdf imv polkit-gnome wf-recorder

Theme & Wayland

sudo pacman -S qt5-wayland qt6-wayland gtk3 gtk4 nwg-look brightnessctl
yay -S catppuccin-gtk-theme-mocha catppuccin-cursors-mocha

GPU Verification

NVIDIA RTX 5090 Status

# GPU info, driver version, VRAM, temperature
nvidia-smi
# Verify DRM modesetting (required for Wayland/Hyprland)
cat /sys/module/nvidia_drm/parameters/modeset
# Must show: Y
# Verify NVIDIA kernel modules loaded
lsmod | grep nvidia
# Check for GPU errors in dmesg
dmesg | grep -iE 'nvidia|drm' | tail -20

NVIDIA Persistence Daemon

Keeps the GPU initialized between workloads (prevents cold-start delays):

sudo systemctl enable --now nvidia-persistenced.service
# Verify
systemctl is-active nvidia-persistenced.service

Display: 3.2K Tandem OLED

The P16g has a 16" 3200x2000 Tandem OLED display. At native resolution, text is tiny without scaling.

Hyprland Monitor Configuration

In ~/.config/hypr/hyprland.conf (or the stowed equivalent):

# Check current monitor config
hyprctl monitors
Hyprland monitor config for 3.2K OLED
# Scale 1.5x for readable text at 3200x2000
monitor = eDP-1, 3200x2000@60, 0x0, 1.5

# For external displays (adjust as needed)
# monitor = DP-1, 2560x1440@144, 3200x0, 1

HiDPI Cursor and Font Scaling

# Environment variables for HiDPI (in env-gpu.conf or hyprland.conf)
env = XCURSOR_SIZE,32
env = GDK_SCALE,1.5
env = QT_AUTO_SCREEN_SCALE_FACTOR,1

Verify Display

# Resolution and refresh rate
hyprctl monitors | grep -E 'Monitor|resolution|scale'
# Verify Wayland session
echo $XDG_SESSION_TYPE
# Must show: wayland

Hyprland Validation

# Verify Hyprland is running
pgrep -a Hyprland
# List workspaces
hyprctl workspaces
# Verify key components
pgrep -a waybar
pgrep -a mako
# Test notifications
notify-send "P16g Test" "Desktop environment operational"
# Test screenshot pipeline
grim -g "$(slurp)" /tmp/test-screenshot.png && ls -lh /tmp/test-screenshot.png
# Test clipboard
echo "clipboard test" | wl-copy && wl-paste

Power Management (ThinkPad)

sudo pacman -S tlp tlp-rdw
sudo systemctl enable --now tlp

Phase 6 Checklist

Check Status

NVIDIA driver loaded (nvidia-smi)

[ ]

DRM modesetting enabled (cat /sys/module/nvidia_drm/parameters/modeset)

[ ]

NVIDIA persistence daemon running

[ ]

PipeWire running (wpctl status)

[ ]

sof-firmware installed (onboard speakers work)

[ ]

Audio output verified (pw-play)

[ ]

Bluetooth service active

[ ]

At least one BT device paired and connected

[ ]

Hyprland running with correct monitor scaling

[ ]

Wayland session confirmed (echo $XDG_SESSION_TYPE)

[ ]

Waybar and Mako running

[ ]

Notifications working (notify-send)

[ ]

Screenshots working (grim + slurp)

[ ]

Clipboard working (wl-copy + wl-paste)

[ ]

pavucontrol accessible

[ ]

Theme applied (Catppuccin Mocha)

[ ]

TLP running (tlp-stat -b)

[ ]