515 lines
15 KiB
Markdown
515 lines
15 KiB
Markdown
# 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 <<EOF
|
|
preload = $HOME/Pictures/wallpapers/default.jpg
|
|
wallpaper = ,$HOME/Pictures/wallpapers/default.jpg
|
|
EOF
|
|
```
|
|
|
|
- [ ] **Step 3:** Add hyprpaper to autostart. Edit `~/.config/hypr/hyprland.conf`, in the `# ----- Autostart -----` block, append:
|
|
|
|
```
|
|
exec-once = hyprpaper
|
|
```
|
|
|
|
**Note:** If DMS manages your wallpaper (it often does via matugen theming), skip this task and let DMS handle it. Revisit later if DMS's wallpaper tool isn't working for you.
|
|
|
|
---
|
|
|
|
## Phase 3 — Dotfiles symlinks
|
|
|
|
### Task 3.1: Add a `hypr` stow package
|
|
|
|
**Files:**
|
|
- Create: `~/.dotfiles/hypr/.config/hypr/hyprland.conf` (moved from `~/.config/hypr/hyprland.conf`)
|
|
- Symlink: `~/.config/hypr/hyprland.conf` → `~/.dotfiles/hypr/.config/hypr/hyprland.conf` (created by `stow`)
|
|
|
|
- [ ] **Step 1:** Confirm `stow` is installed.
|
|
|
|
```bash
|
|
command -v stow || sudo dnf install -y stow
|
|
```
|
|
|
|
- [ ] **Step 2:** Move the config into a new `hypr` stow package.
|
|
|
|
```bash
|
|
mkdir -p ~/.dotfiles/hypr/.config
|
|
mv ~/.config/hypr ~/.dotfiles/hypr/.config/hypr
|
|
```
|
|
|
|
- [ ] **Step 3:** Stow it to recreate the symlink.
|
|
|
|
```bash
|
|
cd ~/.dotfiles
|
|
stow --target="$HOME" hypr
|
|
```
|
|
|
|
- [ ] **Step 4:** Verify the symlink resolves.
|
|
|
|
```bash
|
|
ls -l ~/.config/hypr/hyprland.conf
|
|
readlink -f ~/.config/hypr/hyprland.conf
|
|
```
|
|
Expected: points into `~/.dotfiles/hypr/.config/hypr/hyprland.conf`.
|
|
|
|
- [ ] **Step 5:** Commit (only the new `hypr` package — leave existing uncommitted changes in `kitty/`, `nvim/`, etc. alone).
|
|
|
|
```bash
|
|
cd ~/.dotfiles
|
|
git add hypr
|
|
git commit -m "hypr: add baseline Hyprland + DMS config"
|
|
git push
|
|
```
|
|
|
|
- [ ] **Step 6:** (Optional) Add a `dms` stow package once you've confirmed what file `dms setup` wrote and that it's stable. Don't move it yet if DMS rewrites its config on upgrades.
|
|
|
|
---
|
|
|
|
## Phase 4 — First login and smoke test
|
|
|
|
### Task 4.1: Log out and pick Hyprland from GDM
|
|
|
|
- [ ] **Step 1:** Save any open work. Log out of GNOME.
|
|
|
|
- [ ] **Step 2:** At GDM, click the gear/session picker and choose **Hyprland**.
|
|
|
|
- [ ] **Step 3:** Log in. Expected:
|
|
- Blank desktop briefly, then DMS bar appears at top.
|
|
- `SUPER+Return` opens kitty.
|
|
- `SUPER+D` opens fuzzel launcher.
|
|
- `SUPER+1..9` switches workspaces.
|
|
|
|
- [ ] **Step 4:** If things break: switch to TTY (`Ctrl+Alt+F3`), log in, and inspect:
|
|
|
|
```bash
|
|
journalctl --user -b -u graphical-session.target -n 100
|
|
cat ~/.cache/hyprland/hyprland.log | tail -100
|
|
```
|
|
Log out via `loginctl terminate-user $USER` if stuck, then pick **GNOME** or **Sway** from GDM as fallback.
|
|
|
|
---
|
|
|
|
### Task 4.2: Smoke-test checklist
|
|
|
|
Run through each and tick off:
|
|
|
|
- [ ] `SUPER+Return` launches kitty
|
|
- [ ] `SUPER+D` launches fuzzel; typing + Enter launches the app
|
|
- [ ] Bar shows time, battery/system info
|
|
- [ ] `SUPER+Q` closes the focused window
|
|
- [ ] `SUPER+2` switches to workspace 2; opening a new app there puts it on 2
|
|
- [ ] `SUPER+SHIFT+3` moves the current window to workspace 3
|
|
- [ ] Volume keys work; a notification appears on change
|
|
- [ ] `Print` takes a screenshot (check `~/Pictures/Screenshots/`)
|
|
- [ ] `wl-copy hello && wl-paste` round-trips clipboard
|
|
- [ ] DMS notification appears when running `notify-send "hi" "it works"`
|
|
- [ ] Browser (Firefox) opens on Wayland (`echo $WAYLAND_DISPLAY` inside the browser's about:support shows Wayland)
|
|
- [ ] Lock screen works: run `hyprlock` — can unlock with password
|
|
|
|
- [ ] **Step 1:** Log results.
|
|
|
|
```bash
|
|
$EDITOR ~/systems-admin/docs/window-manager/progress.md
|
|
# Append a dated "First login" section with ✓/✗ per item.
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 5 — Knobs to turn later (not in this plan)
|
|
|
|
These are intentionally deferred. Write them in `progress.md` as "future" items as you encounter them:
|
|
|
|
- Monitor resolution/scaling overrides (`monitor = HDMI-A-1, 2560x1440@144, 0x0, 1`)
|
|
- Keyboard layout tweaks (caps→esc, etc.)
|
|
- Per-app window rules (`windowrule = float, class:^(pavucontrol)$`)
|
|
- Matugen wallpaper theming wired to DMS
|
|
- Gaming / `prime-run` for NVIDIA dGPU usage
|
|
- Replace `fuzzel` keybind with DMS spotlight if you prefer it
|
|
- Move to `foot` as default terminal if kitty feels heavy
|
|
|
|
---
|
|
|
|
## Self-review check
|
|
|
|
- **Spec coverage:** idea.md asked for Hyprland + shell (DMS or Noctalia) + stability. Plan installs Hyprland, picks DMS with reasoning, keeps Sway/GNOME as fallbacks. ✓
|
|
- **GPU path:** Plan explicitly avoids proprietary NVIDIA driver based on detected hardware (AMD iGPU primary). ✓
|
|
- **Backup goal:** Configs live in `~/.config/` and are migrated into `~/dotfiles` (Forgejo) in Phase 3. ✓
|
|
- **Learning goal:** Minimal hand-authored `hyprland.conf` the user can read top-to-bottom; cheat sheet provided separately. ✓
|
|
- **Known gaps to verify at install time:** exact COPR package names (solopasha occasionally renames), whether `hyprshot`/`hypridle`/`hyprpolkitagent` are split packages or bundled in `hyprland-contrib`. If `dnf install` complains about a missing name, `dnf search <name>` and adjust.
|