# Hyprland + DMS Migration Plan **Goal:** Migrate from GNOME to Hyprland on Fedora 43, paired with DankMaterialShell (DMS), while keeping GNOME and Sway installable as fallbacks. **Architecture:** Use Fedora's standard COPR-based install path for Hyprland (solopasha) and DMS (avengemedia). Run on the AMD iGPU (no proprietary NVIDIA driver needed). Store all user config under `~/.config/` and track it in `~/dotfiles` (Forgejo). Adopt DMS's batteries-included shell so the bar/notifications/lock/launcher work out of the box, and use `mylinuxforwork/hyprland-starter` as a reference for a minimal, readable starter `hyprland.conf`. **Tech stack:** Hyprland, Quickshell, DankMaterialShell, kitty, foot (backup), fuzzel, pipewire, hyprlock, hyprpaper, grim/slurp, wl-clipboard, cliphist, xdg-desktop-portal-hyprland, GDM. **Shell pick:** DMS (over Noctalia). First-party Fedora COPR, `dms setup` generates sensible keybinds/autostart, replaces waybar+swaylock+swayidle+mako+fuzzel+polkit in one package. Revisit Noctalia later. **Hardware note:** Machine has AMD Vega iGPU (primary) + NVIDIA RTX 3060 (discrete, unused for display). All steps assume AMD-path. Do **not** install `akmod-nvidia` as part of this plan. --- ## Phase 0 — Preparation ### Task 0.1: Bootstrap project docs and dotfiles **Files:** - Create: `~/systems-admin/docs/window-manager/progress.md` (done — append as we go) - Create: `~/systems-admin/docs/window-manager/cheatsheet.md` (done — update as bindings change) - Verify: `~/dotfiles/` exists and is the Forgejo clone - [ ] **Step 1:** Confirm dotfiles repo exists at `~/.dotfiles` (GNU Stow layout). ```bash ls -ld ~/.dotfiles && git -C ~/.dotfiles remote -v ``` Expected: `origin` at `git@forgejo.swansoncloud.com:jared/dotfiles.git`. - [ ] **Step 2:** Record starting state in progress log. ```bash { echo "## $(date -I) — Starting state" echo echo "- Fedora: $(cat /etc/fedora-release)" echo "- Kernel: $(uname -r)" echo "- Session: $XDG_SESSION_TYPE / $XDG_CURRENT_DESKTOP" echo "- Installed sessions: $(ls /usr/share/wayland-sessions/ | tr '\n' ' ')" echo "- GPU: $(lspci | grep -E 'VGA|3D' | sed 's/^/ /')" echo } >> ~/systems-admin/docs/window-manager/progress.md ``` - [ ] **Step 3:** Commit current `idea.md` and new docs to a git repo so decisions are preserved. ```bash cd ~/systems-admin git init -q 2>/dev/null || true git add docs/window-manager/ git commit -m "docs(wm): initial idea, plan, progress log" ``` --- ### Task 0.2: Enable COPRs and RPM Fusion (free only) **Why:** Hyprland and DMS are not in Fedora's default repos yet. RPM Fusion free gives us codecs + a few utilities; we are **not** enabling the nonfree NVIDIA path. - [ ] **Step 1:** Enable RPM Fusion free (safe even if already enabled). ```bash sudo dnf install -y \ https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm ``` - [ ] **Step 2:** Enable the solopasha Hyprland COPR. ```bash sudo dnf copr enable -y solopasha/hyprland ``` - [ ] **Step 3:** Enable the DMS COPR. ```bash sudo dnf copr enable -y avengemedia/dms ``` - [ ] **Step 4:** Refresh metadata. ```bash sudo dnf -y makecache ``` - [ ] **Step 5:** Verify both COPRs are listed. ```bash sudo dnf copr list | grep -E 'solopasha|avengemedia' ``` Expected: both visible and enabled. - [ ] **Step 6:** Append to progress log. ```bash echo "- $(date -Is): Enabled COPRs solopasha/hyprland, avengemedia/dms" \ >> ~/systems-admin/docs/window-manager/progress.md ``` --- ## Phase 1 — Install Hyprland and essentials ### Task 1.1: Install Hyprland core + session utilities **Files:** none yet — package install only. - [ ] **Step 1:** Install the core set in one transaction. ```bash sudo dnf install -y \ hyprland hyprland-contrib hyprpaper hyprlock hypridle \ xdg-desktop-portal-hyprland xdg-desktop-portal-gtk \ kitty foot fuzzel \ grim slurp hyprshot \ wl-clipboard cliphist \ pipewire pipewire-pulseaudio wireplumber \ brightnessctl playerctl network-manager-applet \ qt6-qtwayland qt5-qtwayland \ lxpolkit ``` - [ ] **Step 2:** Verify Hyprland runs and shows version. ```bash hyprctl version ``` Expected: version string, no errors. - [ ] **Step 3:** Confirm Hyprland's session file is present so GDM will offer it. ```bash ls /usr/share/wayland-sessions/hyprland.desktop ``` Expected: file exists. If missing, reinstall `hyprland` and check again before continuing. - [ ] **Step 4:** Log the installed Hyprland version. ```bash echo "- $(date -Is): Installed hyprland $(hyprctl version | head -n1)" \ >> ~/systems-admin/docs/window-manager/progress.md ``` --- ### Task 1.2: Install DankMaterialShell - [ ] **Step 1:** Install DMS plus commonly-needed optional deps. ```bash sudo dnf install -y dms cava matugen ``` - [ ] **Step 2:** Confirm `dms` binary is on PATH. ```bash command -v dms && dms --version ``` Expected: path printed, version string. - [ ] **Step 3:** Log DMS install. ```bash echo "- $(date -Is): Installed DMS $(dms --version 2>/dev/null | head -n1)" \ >> ~/systems-admin/docs/window-manager/progress.md ``` --- ## Phase 2 — Minimal config Approach: write one small `hyprland.conf` we can read top-to-bottom, not a mega-config. DMS provides bar/launcher/lock/notifications/polkit, so our `hyprland.conf` just handles: monitors, input, keybinds, and launching DMS. ### Task 2.1: Create the base Hyprland config **Files:** - Create: `~/.config/hypr/hyprland.conf` - [ ] **Step 1:** Ensure the directory exists. ```bash mkdir -p ~/.config/hypr ``` - [ ] **Step 2:** Write the config. ```bash cat > ~/.config/hypr/hyprland.conf <<'EOF' # ----- Monitors ----- # Use Hyprland's auto-detect. Override later with specific resolution/refresh. monitor = , preferred, auto, 1 # ----- Autostart ----- exec-once = lxpolkit exec-once = /usr/libexec/xdg-desktop-portal-hyprland exec-once = wl-paste --watch cliphist store exec-once = dms run # ----- Environment ----- env = XCURSOR_SIZE,24 env = QT_QPA_PLATFORMTHEME,qt6ct env = MOZ_ENABLE_WAYLAND,1 # ----- Input ----- input { kb_layout = us follow_mouse = 1 touchpad { natural_scroll = true tap-to-click = true } sensitivity = 0 } # ----- Look ----- general { gaps_in = 4 gaps_out = 8 border_size = 2 layout = dwindle } decoration { rounding = 8 blur { enabled = true size = 4 passes = 2 } } animations { enabled = true } dwindle { pseudotile = true preserve_split = true } # ----- Keybindings ----- $mod = SUPER # Launch bind = $mod, Return, exec, kitty bind = $mod, D, exec, fuzzel # fallback launcher; DMS spotlight works too bind = $mod, E, exec, kitty -e yazi # file manager in terminal # Window control bind = $mod, Q, killactive, bind = $mod SHIFT, Q, exit, bind = $mod, F, fullscreen, bind = $mod, V, togglefloating, bind = $mod, P, pseudo, bind = $mod, J, togglesplit, # Focus (arrows + hjkl both work) bind = $mod, left, movefocus, l bind = $mod, right, movefocus, r bind = $mod, up, movefocus, u bind = $mod, down, movefocus, d bind = $mod, h, movefocus, l bind = $mod, l, movefocus, r bind = $mod, k, movefocus, u bind = $mod, j, movefocus, d # Move window bind = $mod SHIFT, left, movewindow, l bind = $mod SHIFT, right, movewindow, r bind = $mod SHIFT, up, movewindow, u bind = $mod SHIFT, down, movewindow, d # Workspaces bind = $mod, 1, workspace, 1 bind = $mod, 2, workspace, 2 bind = $mod, 3, workspace, 3 bind = $mod, 4, workspace, 4 bind = $mod, 5, workspace, 5 bind = $mod, 6, workspace, 6 bind = $mod, 7, workspace, 7 bind = $mod, 8, workspace, 8 bind = $mod, 9, workspace, 9 bind = $mod, 0, workspace, 10 bind = $mod SHIFT, 1, movetoworkspace, 1 bind = $mod SHIFT, 2, movetoworkspace, 2 bind = $mod SHIFT, 3, movetoworkspace, 3 bind = $mod SHIFT, 4, movetoworkspace, 4 bind = $mod SHIFT, 5, movetoworkspace, 5 bind = $mod SHIFT, 6, movetoworkspace, 6 bind = $mod SHIFT, 7, movetoworkspace, 7 bind = $mod SHIFT, 8, movetoworkspace, 8 bind = $mod SHIFT, 9, movetoworkspace, 9 bind = $mod SHIFT, 0, movetoworkspace, 10 # Scroll through workspaces bind = $mod, mouse_down, workspace, e+1 bind = $mod, mouse_up, workspace, e-1 # Scratchpad bind = $mod, S, togglespecialworkspace, magic bind = $mod SHIFT, S, movetoworkspace, special:magic # Mouse drag bindm = $mod, mouse:272, movewindow bindm = $mod, mouse:273, resizewindow # Screenshots (saved to ~/Pictures/Screenshots/) bind = , Print, exec, hyprshot -m output bind = SHIFT, Print, exec, hyprshot -m region bind = CTRL, Print, exec, hyprshot -m window # Media + brightness bindel = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ bindel = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- bindl = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle bindl = , XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle bindel = , XF86MonBrightnessUp, exec, brightnessctl s 10%+ bindel = , XF86MonBrightnessDown, exec, brightnessctl s 10%- bindl = , XF86AudioPlay, exec, playerctl play-pause bindl = , XF86AudioNext, exec, playerctl next bindl = , XF86AudioPrev, exec, playerctl previous EOF ``` - [ ] **Step 3:** Sanity-check the config parses. ```bash hyprland --verify-config -c ~/.config/hypr/hyprland.conf 2>&1 | tail -20 || \ echo "(Older Hyprland versions may not have --verify-config; safe to skip)" ``` Expected: no fatal errors. Warnings are OK. --- ### Task 2.2: Run DMS's setup to generate its own baseline **Why:** `dms setup` writes its autostart/keybind snippets in a way DMS expects. Our `hyprland.conf` already launches `dms run`, so setup here is just to generate any DMS-side state files (theme, shell config). - [ ] **Step 1:** Run setup (answer prompts; accept defaults). ```bash dms setup ``` Expected: walks through theme picker, writes config to `~/.config/DankMaterialShell/` or `~/.config/quickshell/dms/`. - [ ] **Step 2:** Verify DMS config directory exists. ```bash ls ~/.config/DankMaterialShell/ 2>/dev/null || ls ~/.config/quickshell/ 2>/dev/null ``` Expected: at least one directory present. - [ ] **Step 3:** Log. ```bash echo "- $(date -Is): Ran 'dms setup'; baseline shell config written" \ >> ~/systems-admin/docs/window-manager/progress.md ``` --- ### Task 2.3: Pick a wallpaper and wire hyprpaper **Files:** - Create: `~/.config/hypr/hyprpaper.conf` - [ ] **Step 1:** Pick any image and note its absolute path. Example: ```bash mkdir -p ~/Pictures/wallpapers # copy or download a wallpaper into ~/Pictures/wallpapers/default.jpg ls ~/Pictures/wallpapers/ ``` - [ ] **Step 2:** Write hyprpaper config. ```bash cat > ~/.config/hypr/hyprpaper.conf <` and adjust.