Files
niri-beyond-glass/install.sh
T
2026-07-27 13:39:29 +08:00

324 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -Eeuo pipefail
readonly PROJECT="niri-beyond-glass"
readonly NIRI_TAG="v26.04"
readonly XWS_TAG="v0.8.2"
readonly RUST_TOOLCHAIN="1.85.1"
readonly ARCHIVE_URL="https://git.k1412.top/wuyang/niri-beyond-glass/archive/main.tar.gz"
wallpaper=""
config_only=0
dry_run=0
rebuild=0
source_dir="${NBG_SOURCE_DIR:-}"
tmp_dir=""
usage() {
cat <<'EOF'
用法:install.sh [选项]
--wallpaper PATH 使用指定的静态壁纸
--config-only 只更新配置,不安装/编译软件
--rebuild 强制重新编译 Niri 和 Xwayland Satellite
--dry-run 显示将执行的主要步骤,不修改系统
-h, --help 显示帮助
EOF
}
log() {
printf '\033[1;36m[Niri]\033[0m %s\n' "$*"
}
die() {
printf '\033[1;31m错误:\033[0m %s\n' "$*" >&2
exit 1
}
run() {
if (( dry_run )); then
printf '+'
printf ' %q' "$@"
printf '\n'
else
"$@"
fi
}
cleanup() {
[[ -n "$tmp_dir" && -d "$tmp_dir" ]] && rm -rf "$tmp_dir"
}
trap cleanup EXIT
while (($#)); do
case "$1" in
--wallpaper)
(($# >= 2)) || die "--wallpaper 缺少路径"
wallpaper="$2"
shift 2
;;
--config-only)
config_only=1
shift
;;
--rebuild)
rebuild=1
shift
;;
--dry-run)
dry_run=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
die "未知参数:$1"
;;
esac
done
[[ ${EUID:-$(id -u)} -ne 0 ]] || die "请用普通用户运行,脚本会在需要时调用 sudo。"
[[ -z "$wallpaper" || -f "$wallpaper" ]] || die "壁纸不存在:$wallpaper"
if [[ -r /etc/os-release ]]; then
# shellcheck disable=SC1091
. /etc/os-release
else
die "无法识别操作系统。"
fi
if [[ "${ID:-}" != "ubuntu" || "${VERSION_ID:-}" != "24.04" ]]; then
die "只支持 Ubuntu 24.04;当前是 ${PRETTY_NAME:-未知系统}"
fi
case "$(uname -m)" in
x86_64|aarch64) ;;
*) die "目前只支持 x86_64 和 aarch64。" ;;
esac
fetch_source() {
if [[ -n "$source_dir" ]]; then
[[ -f "$source_dir/config/niri/config.kdl" ]] || die "NBG_SOURCE_DIR 不是有效源码目录。"
return
fi
tmp_dir="$(mktemp -d)"
log "下载配置仓库"
curl -fL --retry 3 "$ARCHIVE_URL" -o "$tmp_dir/source.tar.gz"
mkdir -p "$tmp_dir/source"
tar -xzf "$tmp_dir/source.tar.gz" -C "$tmp_dir/source" --strip-components=1
source_dir="$tmp_dir/source"
}
install_packages() {
log "安装 Ubuntu 24.04 依赖"
run sudo apt-get update
run sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y \
build-essential clang git curl ca-certificates pkg-config \
meson ninja-build cmake \
libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev \
libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev \
libseat-dev libpipewire-0.3-dev libpango1.0-dev \
libdisplay-info-dev libcairo2-dev libglib2.0-dev \
libxcb1-dev libxcb-composite0-dev libxcb-randr0-dev \
libxcb-res0-dev libxcb-xfixes0-dev libxcb-cursor-dev \
xwayland xdg-desktop-portal-gnome xdg-desktop-portal-gtk \
alacritty fuzzel waybar swaybg swaylock swayidle mako-notifier \
nautilus policykit-1-gnome pipewire-pulse wireplumber \
brightnessctl playerctl grim slurp wl-clipboard wlogout \
fonts-noto-core fonts-noto-cjk fonts-noto-color-emoji fonts-font-awesome
}
install_rust() {
export RUSTUP_HOME="${XDG_DATA_HOME:-$HOME/.local/share}/$PROJECT/rustup"
export CARGO_HOME="${XDG_DATA_HOME:-$HOME/.local/share}/$PROJECT/cargo"
export PATH="$CARGO_HOME/bin:$PATH"
if [[ ! -x "$CARGO_HOME/bin/rustup" ]]; then
log "安装隔离的 Rust $RUST_TOOLCHAIN 工具链"
if (( dry_run )); then
printf '+ curl https://sh.rustup.rs | sh -s -- -y --no-modify-path --profile minimal --default-toolchain %q\n' "$RUST_TOOLCHAIN"
return
fi
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs |
sh -s -- -y --no-modify-path --profile minimal --default-toolchain "$RUST_TOOLCHAIN"
else
run "$CARGO_HOME/bin/rustup" toolchain install "$RUST_TOOLCHAIN" --profile minimal
run "$CARGO_HOME/bin/rustup" default "$RUST_TOOLCHAIN"
fi
}
version_ge() {
[[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -n1)" == "$2" ]]
}
install_libdisplay_info() {
local installed=""
installed="$(pkg-config --modversion libdisplay-info 2>/dev/null || true)"
if [[ -n "$installed" ]] && version_ge "$installed" "0.3.0"; then
return
fi
log "编译 libdisplay-info 0.3.0Ubuntu 24.04 自带版本较旧)"
local build_root="${XDG_CACHE_HOME:-$HOME/.cache}/$PROJECT/build"
local src="$build_root/libdisplay-info"
run mkdir -p "$build_root"
if [[ ! -d "$src/.git" ]]; then
run git clone --depth 1 --branch 0.3.0 \
https://gitlab.freedesktop.org/emersion/libdisplay-info.git "$src"
fi
run meson setup "$src/build" "$src" --prefix=/usr/local --buildtype=release --wipe
run ninja -C "$src/build"
run sudo ninja -C "$src/build" install
run sudo ldconfig
}
install_niri() {
local current=""
current="$(niri --version 2>/dev/null || true)"
if (( ! rebuild )) && [[ "$current" == *"26.4"* || "$current" == *"26.04"* ]]; then
log "已安装兼容的 $current,跳过编译"
return
fi
log "编译 Niri $NIRI_TAG"
local build_root="${XDG_CACHE_HOME:-$HOME/.cache}/$PROJECT/build"
local src="$build_root/niri"
run mkdir -p "$build_root"
if [[ ! -d "$src/.git" ]]; then
run git clone --depth 1 --branch "$NIRI_TAG" https://github.com/niri-wm/niri.git "$src"
else
run git -C "$src" fetch --depth 1 origin "refs/tags/$NIRI_TAG:refs/tags/$NIRI_TAG"
run git -C "$src" checkout -f "$NIRI_TAG"
fi
run cargo build --manifest-path "$src/Cargo.toml" --release --locked
run sudo install -Dm755 "$src/target/release/niri" /usr/local/bin/niri
run sudo install -Dm755 "$src/resources/niri-session" /usr/local/bin/niri-session
run sudo install -Dm644 "$src/resources/niri.service" /usr/local/lib/systemd/user/niri.service
run sudo install -Dm644 "$src/resources/niri-shutdown.target" /usr/local/lib/systemd/user/niri-shutdown.target
run sudo install -Dm644 "$src/resources/niri.desktop" /usr/local/share/wayland-sessions/niri.desktop
run sudo install -Dm644 "$src/resources/niri-portals.conf" /usr/local/share/xdg-desktop-portal/niri-portals.conf
}
install_xwayland_satellite() {
if (( ! rebuild )) && command -v xwayland-satellite >/dev/null 2>&1; then
return
fi
log "编译 Xwayland Satellite $XWS_TAG"
local build_root="${XDG_CACHE_HOME:-$HOME/.cache}/$PROJECT/build"
local src="$build_root/xwayland-satellite"
run mkdir -p "$build_root"
if [[ ! -d "$src/.git" ]]; then
run git clone --depth 1 --branch "$XWS_TAG" \
https://github.com/Supreeeme/xwayland-satellite.git "$src"
else
run git -C "$src" fetch --depth 1 origin "refs/tags/$XWS_TAG:refs/tags/$XWS_TAG"
run git -C "$src" checkout -f "$XWS_TAG"
fi
run cargo build --manifest-path "$src/Cargo.toml" --release --locked
run sudo install -Dm755 "$src/target/release/xwayland-satellite" /usr/local/bin/xwayland-satellite
}
backup_and_install_config() {
local config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
local state_home="${XDG_STATE_HOME:-$HOME/.local/state}"
local stamp
stamp="$(date +%Y%m%d-%H%M%S)"
local backup="$state_home/$PROJECT/backups/$stamp/config"
local names=(niri waybar fuzzel mako swaylock niri-beyond-glass)
log "备份并安装用户配置"
run mkdir -p "$backup"
local name
for name in "${names[@]}"; do
if [[ -e "$config_home/$name" ]]; then
run cp -a "$config_home/$name" "$backup/$name"
fi
done
run mkdir -p \
"$config_home/niri" \
"$config_home/waybar" \
"$config_home/fuzzel" \
"$config_home/mako" \
"$config_home/swaylock" \
"$config_home/niri-beyond-glass" \
"$HOME/.local/bin" \
"$HOME/Pictures/Screenshots"
run install -m644 "$source_dir/config/niri/config.kdl" "$config_home/niri/config.kdl"
run install -m644 "$source_dir/config/waybar/config.jsonc" "$config_home/waybar/config.jsonc"
run install -m644 "$source_dir/config/waybar/style.css" "$config_home/waybar/style.css"
run install -m644 "$source_dir/config/fuzzel/fuzzel.ini" "$config_home/fuzzel/fuzzel.ini"
run install -m644 "$source_dir/config/mako/config" "$config_home/mako/config"
run install -m644 "$source_dir/config/swaylock/config" "$config_home/swaylock/config"
run install -m755 "$source_dir/scripts/niri-beyond-wallpaper" "$HOME/.local/bin/niri-beyond-wallpaper"
select_wallpaper "$config_home/niri-beyond-glass/wallpaper"
}
select_wallpaper() {
local state_file="$1"
local selected="$wallpaper"
if [[ -z "$selected" ]]; then
local candidates=(
/usr/share/backgrounds/warty-final-ubuntu.png
/usr/share/backgrounds/ubuntu-default-greyscale-wallpaper.png
)
local candidate
for candidate in "${candidates[@]}"; do
if [[ -f "$candidate" ]]; then
selected="$candidate"
break
fi
done
fi
if [[ -z "$selected" ]]; then
selected="$(find /usr/share/backgrounds -maxdepth 2 -type f \
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \) \
-print -quit 2>/dev/null || true)"
fi
if (( dry_run )); then
printf '+ write wallpaper path %q to %q\n' "$selected" "$state_file"
else
printf '%s\n' "$selected" > "$state_file"
fi
}
validate_config() {
if (( dry_run )); then
printf '+ niri validate -c %q\n' "${XDG_CONFIG_HOME:-$HOME/.config}/niri/config.kdl"
return
fi
command -v niri >/dev/null 2>&1 || die "找不到 niri,无法验证配置。"
niri validate -c "${XDG_CONFIG_HOME:-$HOME/.config}/niri/config.kdl"
}
main() {
fetch_source
if (( ! config_only )); then
install_packages
install_rust
install_libdisplay_info
install_niri
install_xwayland_satellite
fi
backup_and_install_config
validate_config
log "安装完成"
printf '\n请注销,在 GDM 会话菜单中选择“Niri”后登录。\n'
printf 'GNOME 和 GDM 均未被修改;快捷键说明:Super+Shift+/。\n'
}
main