#!/bin/bash # Niri-specific customizations. Sourced by customizations.sh after the generic # helpers when PROFILE=mainline-niri. # Available env: $TARGET, $USERNAME, $PROFILE, $PROFILE_DIR, all install.conf vars. _niri_write_kdl() { local TARGET="$1" local cfg="$TARGET/etc/skel/.config/niri" install -d -m 0755 "$cfg" cat > "$cfg/config.kdl" <<'EOF' // niri config — generated by void-installer (mainline-niri profile). input { keyboard { xkb { layout "ch" variant "fr" } } touchpad { tap natural-scroll dwt } mouse { accel-speed 0.0 } } layout { gaps 12 center-focused-column "never" preset-column-widths { proportion 0.33333 proportion 0.5 proportion 0.66667 } default-column-width { proportion 0.5; } focus-ring { width 2 active-color "#fabd2f" inactive-color "#3c3836" } border { off; } } prefer-no-csd spawn-at-startup "swaybg" "-i" "/usr/share/backgrounds/void-installer/pxfuel.jpg" spawn-at-startup "mako" spawn-at-startup "/usr/libexec/polkit-gnome-authentication-agent-1" spawn-at-startup "sh" "-c" "command -v gnome-keyring-daemon >/dev/null 2>&1 && gnome-keyring-daemon --start --components=secrets,pkcs11 >/dev/null 2>&1; true" spawn-at-startup "sh" "-c" "i=0; while [ \$i -lt 30 ] && ! dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:org.bluez >/dev/null 2>&1; do sleep 1; i=\$((i+1)); done; exec noctalia-shell" cursor { xcursor-theme "Bibata-Modern-Ice" xcursor-size 24 } binds { Mod+T { spawn "alacritty"; } Mod+D { spawn "sh" "-c" "quickshell msg -c noctalia-shell launcher toggle"; } Mod+Q { close-window; } Mod+Shift+E { quit; } Print { screenshot; } Mod+H { focus-column-left; } Mod+L { focus-column-right; } Mod+J { focus-window-down; } Mod+K { focus-window-up; } Mod+Shift+H { move-column-left; } Mod+Shift+L { move-column-right; } Mod+1 { focus-workspace 1; } Mod+2 { focus-workspace 2; } Mod+3 { focus-workspace 3; } Mod+4 { focus-workspace 4; } Mod+Shift+1 { move-column-to-workspace 1; } Mod+Shift+2 { move-column-to-workspace 2; } XF86AudioRaiseVolume { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "5%+"; } XF86AudioLowerVolume { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "5%-"; } XF86AudioMute { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; } XF86MonBrightnessUp { spawn "brightnessctl" "set" "+5%"; } XF86MonBrightnessDown { spawn "brightnessctl" "set" "5%-"; } } EOF # Mirror into the actual user home. install -d -m 0755 "$TARGET/home/$USERNAME/.config/niri" cp "$cfg/config.kdl" "$TARGET/home/$USERNAME/.config/niri/config.kdl" run_chroot "chown -R $USERNAME:$USERNAME /home/$USERNAME/.config/niri" || true log "niri KDL config installed" } _niri_write_env() { local TARGET="$1" cat > "$TARGET/etc/profile.d/wayland.sh" <<'EOF' # Wayland defaults installed by void-installer (mainline-niri profile). export QT_QPA_PLATFORM="wayland;xcb" export GDK_BACKEND=wayland,x11 export MOZ_ENABLE_WAYLAND=1 export _JAVA_AWT_WM_NONREPARENTING=1 export XDG_CURRENT_DESKTOP=niri export XDG_SESSION_TYPE=wayland export GTK_USE_PORTAL=1 export ELECTRON_OZONE_PLATFORM_HINT=auto EOF chmod 0644 "$TARGET/etc/profile.d/wayland.sh" log "wayland environment installed at /etc/profile.d/wayland.sh" # Expose nix .desktop files and icons (installed via first-boot-nix) cat > "$TARGET/etc/profile.d/nix-xdg.sh" <<'NIXEOF' # Add nix profile share directory so launchers and icon themes pick up nix apps. if [[ -d "${HOME:-}/.nix-profile/share" ]]; then case ":${XDG_DATA_DIRS:-}:" in *":$HOME/.nix-profile/share:"*) ;; *) export XDG_DATA_DIRS="$HOME/.nix-profile/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" ;; esac fi NIXEOF chmod 0644 "$TARGET/etc/profile.d/nix-xdg.sh" # /etc/environment: baseline XDG_DATA_DIRS loaded by pam_env for ALL session # types (TTY login, greetd). The nix profile share path must be absolute here # because pam_env does not expand $HOME when the key uses = (not DEFAULT=). # The installed user's home is /home/$USERNAME, so we hardcode it. cat > "$TARGET/etc/environment" < "$TARGET/etc/dconf/db/local.d/01-dark-theme" <<'EOF' [org/gnome/desktop/interface] color-scheme='prefer-dark' gtk-theme='Gruvbox-Dark' icon-theme='Gruvbox-Plus-Dark' cursor-theme='Bibata-Modern-Ice' cursor-size=24 EOF echo 'user-db:user system-db:local' > "$TARGET/etc/dconf/profile/user" run_chroot "dconf update 2>/dev/null || true" log "dconf dark theme profile installed" } _niri_write_session_wrapper() { local TARGET="$1" # Create /usr/local/bin/niri-session: sources /etc/profile before exec'ing # niri --session so that all /etc/profile.d/* scripts (nix paths, # XDG_DATA_DIRS with ~/.nix-profile/share, wayland env, etc.) are in effect # for the compositor and every app it spawns. install -d -m 0755 "$TARGET/usr/local/bin" cat > "$TARGET/usr/local/bin/niri-session" <<'EOF' #!/bin/bash # niri-session — wrapper started by greetd/tuigreet. # Sources /etc/profile so that all /etc/profile.d/* scripts run # (nix paths, wayland env, XDG_DATA_DIRS with ~/.nix-profile/share, etc.) # before handing off to the compositor. [ -f /etc/profile ] && . /etc/profile exec niri --session "$@" EOF chmod 0755 "$TARGET/usr/local/bin/niri-session" log "niri-session wrapper installed at /usr/local/bin/niri-session" } _niri_setup_greetd() { local TARGET="$1" install -d -m 0755 "$TARGET/etc/greetd" cat > "$TARGET/etc/greetd/config.toml" < "$TARGET/etc/xbps.d/10-noctalia.conf" <<'EOF' repository=https://universalrepo.r1xelelo.workers.dev/void EOF # If quickshell is somehow installed it conflicts with noctalia-qs. run_chroot "xbps-remove -y quickshell 2>/dev/null || true" # Sync the new repo and install. Prefix with the proxy mirror configured # by the installer environment so noctalia-shell deps still resolve fast. if ! run_chroot "xbps-install -Sy"; then log "WARN: noctalia repo sync failed; skipping noctalia-shell install" return 0 fi if run_chroot "xbps-install -y noctalia-shell"; then log "noctalia-shell installed from third-party repo" else log "WARN: noctalia-shell install failed (repo may be down); shell omitted" fi } _niri_write_portal_config() { local TARGET="$1" # Tell xdg-desktop-portal to route all portals through the GTK backend when # running under niri. Without this the dispatcher has no match for # XDG_CURRENT_DESKTOP=niri and file-picker / open-with calls fail silently. install -d -m 0755 "$TARGET/etc/xdg/xdg-desktop-portal" cat > "$TARGET/etc/xdg/xdg-desktop-portal/niri-portals.conf" <<'EOF' [preferred] default=gtk org.freedesktop.impl.portal.FileChooser=gtk org.freedesktop.impl.portal.AppChooser=gtk org.freedesktop.impl.portal.OpenURI=gtk org.freedesktop.impl.portal.Print=gtk org.freedesktop.impl.portal.Screenshot=gtk org.freedesktop.impl.portal.Inhibit=gtk org.freedesktop.impl.portal.Notification=gtk org.freedesktop.impl.portal.Settings=gtk EOF log "niri portal config installed (gtk backend for all portals)" } _niri_write_sound_udev_rules() { local TARGET="$1" # PCM/control nodes are created root:root on some kernels before the audio # group is provisioned. This persistent rule ensures correct ownership. install -d -m 0755 "$TARGET/etc/udev/rules.d" cat > "$TARGET/etc/udev/rules.d/70-sound-perms.rules" <<'EOF' # Allow the audio group to access ALSA PCM and control devices. SUBSYSTEM=="sound", GROUP="audio", MODE="0660" EOF log "sound udev rules installed" } _niri_write_noctalia_defaults() { local TARGET="$1" # Write a baseline noctalia settings.json into skel so every new user # (including the installed user) gets the correct wallpaper directory, # dark mode, and Gruvbox colour scheme out of the box. local skel_noc="$TARGET/etc/skel/.config/noctalia" install -d -m 0755 "$skel_noc" cat > "$skel_noc/settings.json" < "$TARGET/etc/xdg/mimeapps.list" <<'EOF' [Default Applications] text/html=google-chrome.desktop x-scheme-handler/http=google-chrome.desktop x-scheme-handler/https=google-chrome.desktop x-scheme-handler/about=google-chrome.desktop x-scheme-handler/unknown=google-chrome.desktop application/pdf=google-chrome.desktop application/xhtml+xml=google-chrome.desktop application/xml=google-chrome.desktop EOF # Also set in user skel so ~/.config/mimeapps.list is populated on first login install -d -m 0755 "$TARGET/etc/skel/.config" cp "$TARGET/etc/xdg/mimeapps.list" "$TARGET/etc/skel/.config/mimeapps.list" # Mirror into installed user home install -d -m 0755 "$TARGET/home/$USERNAME/.config" cp "$TARGET/etc/xdg/mimeapps.list" "$TARGET/home/$USERNAME/.config/mimeapps.list" run_chroot "chown $USERNAME:$USERNAME /home/$USERNAME/.config/mimeapps.list" || true log "google-chrome set as default browser (mimeapps.list)" } _niri_write_kdl "$TARGET" _niri_write_env "$TARGET" _niri_write_session_wrapper "$TARGET" _niri_write_portal_config "$TARGET" _niri_write_sound_udev_rules "$TARGET" _niri_setup_greetd "$TARGET" _niri_install_noctalia "$TARGET" _niri_write_noctalia_defaults "$TARGET" _niri_set_default_browser "$TARGET"