Initial Ubuntu 24.04 Niri installer
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
.cache/
|
||||||
|
.build/
|
||||||
|
*.log
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 wuyang
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
# Niri Beyond Glass
|
||||||
|
|
||||||
|
面向 **Ubuntu 24.04 LTS** 的可移植 Niri 桌面配置。一条命令安装 Niri
|
||||||
|
26.04、Xwayland 支持和一套克制的半透明桌面组件,同时保留原有 GNOME 与
|
||||||
|
GDM,可在登录界面随时切换会话。
|
||||||
|
|
||||||
|
## 效果与范围
|
||||||
|
|
||||||
|
- Niri 滚动平铺、窗口圆角、阴影、流畅动画
|
||||||
|
- 支持 Niri 26.04 的背景模糊、`xray` 和轻微噪点效果
|
||||||
|
- Waybar 顶栏,时间位于最右侧区域,图标风格统一
|
||||||
|
- Fuzzel 启动器、Mako 通知、Swaylock 锁屏和自动息屏
|
||||||
|
- 中文快捷键说明
|
||||||
|
- 浏览器、视频播放器、Steam 保持完全不透明
|
||||||
|
- 自动备份已有配置,可卸载恢复
|
||||||
|
|
||||||
|
本项目**不包含**动态壁纸、DMS、登录界面或 GRUB 主题,也不重新分发
|
||||||
|
Wallpaper Engine 创意工坊图片。默认使用 Ubuntu 自带静态壁纸;安装时可指定
|
||||||
|
自己的图片。
|
||||||
|
|
||||||
|
## 一键安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://git.k1412.top/wuyang/niri-beyond-glass/raw/branch/main/install.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
首次安装需要编译 Niri,耗时取决于 CPU 和网络。脚本会调用 `sudo` 安装依赖,
|
||||||
|
但必须以普通用户运行。完成后注销,在 GDM 左下角的会话菜单选择 **Niri**。
|
||||||
|
|
||||||
|
使用自己的静态壁纸:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://git.k1412.top/wuyang/niri-beyond-glass/raw/branch/main/install.sh \
|
||||||
|
-o /tmp/install-niri.sh
|
||||||
|
bash /tmp/install-niri.sh --wallpaper "$HOME/Pictures/wallpaper.jpg"
|
||||||
|
```
|
||||||
|
|
||||||
|
只更新配置,不编译和安装软件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash /tmp/install-niri.sh --config-only
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常用快捷键
|
||||||
|
|
||||||
|
| 快捷键 | 功能 |
|
||||||
|
|---|---|
|
||||||
|
| `Super + Enter` | 终端 |
|
||||||
|
| `Super + D` | 应用启动器 |
|
||||||
|
| `Super + B` | 默认浏览器 |
|
||||||
|
| `Super + E` | 文件管理器 |
|
||||||
|
| `Super + O` | 总览 |
|
||||||
|
| `Super + Q` | 关闭窗口 |
|
||||||
|
| `Super + V` | 切换浮动 |
|
||||||
|
| `Super + L` | 锁屏 |
|
||||||
|
| `Super + Shift + /` | 中文快捷键总览 |
|
||||||
|
| `Super + PageUp/PageDown` | 切换工作区 |
|
||||||
|
| `Super + Shift + E` | 退出 Niri |
|
||||||
|
|
||||||
|
`Super` 就是键盘上的 Windows 徽标键或 Mac 键盘上的 Command 键。
|
||||||
|
|
||||||
|
## 安全设计
|
||||||
|
|
||||||
|
- 仅支持 Ubuntu 24.04,检测到其他版本会停止
|
||||||
|
- 不替换显示管理器,不修改 GDM,不移除 GNOME
|
||||||
|
- 安装前备份 `niri`、`waybar`、`fuzzel`、`mako`、`swaylock`
|
||||||
|
- Niri 和 Xwayland Satellite 固定到明确版本
|
||||||
|
- Rust 工具链隔离在 `~/.local/share/niri-beyond-glass`
|
||||||
|
- 配置安装后使用 `niri validate` 校验
|
||||||
|
|
||||||
|
备份位于:
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/.local/state/niri-beyond-glass/backups/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 卸载
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://git.k1412.top/wuyang/niri-beyond-glass/raw/branch/main/uninstall.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
卸载器恢复最近一次配置备份,并保留已安装的系统软件和 Niri 二进制,避免破坏
|
||||||
|
其他会话。若要删除系统依赖,请按实际用途手动处理,不建议执行盲目的
|
||||||
|
`apt autoremove`。
|
||||||
|
|
||||||
|
## 已知限制
|
||||||
|
|
||||||
|
- Niri 26.04 比 Ubuntu 24.04 更新,因此脚本采用源码编译,而不是跨版本安装
|
||||||
|
PPA 二进制包。
|
||||||
|
- Ubuntu 24.04 自带的 `libdisplay-info` 版本不足时,脚本会在
|
||||||
|
`/usr/local` 编译安装 0.3.0。
|
||||||
|
- 这是一套 Niri 配置,不复刻 DMS 的控制中心、登录页和动态壁纸。
|
||||||
|
- NVIDIA 用户应先确保 Ubuntu 官方驱动在 GNOME Wayland 下工作正常。
|
||||||
|
|
||||||
|
## 上游项目
|
||||||
|
|
||||||
|
- [Niri](https://github.com/niri-wm/niri)
|
||||||
|
- [Xwayland Satellite](https://github.com/Supreeeme/xwayland-satellite)
|
||||||
|
- [Waybar](https://github.com/Alexays/Waybar)
|
||||||
|
- [Fuzzel](https://codeberg.org/dnkl/fuzzel)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)。Niri、Xwayland Satellite 及各依赖遵循其各自许可证。
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
[main]
|
||||||
|
font=Noto Sans CJK SC:size=13
|
||||||
|
terminal=alacritty
|
||||||
|
prompt="搜索 "
|
||||||
|
icon-theme=Yaru
|
||||||
|
icons-enabled=yes
|
||||||
|
width=46
|
||||||
|
lines=10
|
||||||
|
horizontal-pad=20
|
||||||
|
vertical-pad=14
|
||||||
|
inner-pad=8
|
||||||
|
image-size-ratio=0.45
|
||||||
|
layer=overlay
|
||||||
|
|
||||||
|
[colors]
|
||||||
|
background=181a1de8
|
||||||
|
text=f0eee8ff
|
||||||
|
match=d4c5a5ff
|
||||||
|
selection=3b3e44ff
|
||||||
|
selection-text=ffffffff
|
||||||
|
selection-match=e7d8b8ff
|
||||||
|
border=ffffff20
|
||||||
|
|
||||||
|
[border]
|
||||||
|
width=1
|
||||||
|
radius=10
|
||||||
|
|
||||||
|
[dmenu]
|
||||||
|
exit-immediately-if-empty=yes
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
font=Noto Sans CJK SC 12
|
||||||
|
background-color=#181a1de8
|
||||||
|
text-color=#f0eee8
|
||||||
|
border-color=#ffffff20
|
||||||
|
progress-color=over #d4c5a5
|
||||||
|
border-size=1
|
||||||
|
border-radius=8
|
||||||
|
padding=14
|
||||||
|
margin=12
|
||||||
|
width=360
|
||||||
|
height=120
|
||||||
|
max-visible=5
|
||||||
|
default-timeout=5000
|
||||||
|
icons=1
|
||||||
|
layer=overlay
|
||||||
|
anchor=top-right
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
// Niri Beyond Glass
|
||||||
|
// Portable profile for Ubuntu 24.04 and Niri 26.04.
|
||||||
|
|
||||||
|
input {
|
||||||
|
keyboard {
|
||||||
|
numlock
|
||||||
|
}
|
||||||
|
|
||||||
|
touchpad {
|
||||||
|
tap
|
||||||
|
natural-scroll
|
||||||
|
dwt
|
||||||
|
}
|
||||||
|
|
||||||
|
mouse {
|
||||||
|
accel-profile "flat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
environment {
|
||||||
|
"XDG_CURRENT_DESKTOP" "niri"
|
||||||
|
"XDG_SESSION_DESKTOP" "niri"
|
||||||
|
"QT_QPA_PLATFORM" "wayland;xcb"
|
||||||
|
"NIXOS_OZONE_WL" "1"
|
||||||
|
"_JAVA_AWT_WM_NONREPARENTING" "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
spawn-at-startup "xwayland-satellite"
|
||||||
|
spawn-at-startup "sh" "-lc" "$HOME/.local/bin/niri-beyond-wallpaper"
|
||||||
|
spawn-at-startup "waybar"
|
||||||
|
spawn-at-startup "mako"
|
||||||
|
spawn-at-startup "/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1"
|
||||||
|
spawn-at-startup "swayidle" "-w" "timeout" "600" "swaylock -f" "timeout" "660" "niri msg action power-off-monitors" "resume" "niri msg action power-on-monitors" "before-sleep" "swaylock -f"
|
||||||
|
|
||||||
|
hotkey-overlay {
|
||||||
|
skip-at-startup
|
||||||
|
}
|
||||||
|
|
||||||
|
prefer-no-csd
|
||||||
|
screenshot-path "~/Pictures/Screenshots/niri-%Y-%m-%d-%H-%M-%S.png"
|
||||||
|
|
||||||
|
cursor {
|
||||||
|
xcursor-theme "Yaru"
|
||||||
|
xcursor-size 24
|
||||||
|
}
|
||||||
|
|
||||||
|
layer-rule {
|
||||||
|
match namespace="swaybg"
|
||||||
|
place-within-backdrop true
|
||||||
|
}
|
||||||
|
|
||||||
|
layer-rule {
|
||||||
|
match namespace="waybar"
|
||||||
|
geometry-corner-radius 10
|
||||||
|
background-effect {
|
||||||
|
blur true
|
||||||
|
xray true
|
||||||
|
noise 0.018
|
||||||
|
saturation 0.94
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animations {
|
||||||
|
slowdown 0.85
|
||||||
|
}
|
||||||
|
|
||||||
|
layout {
|
||||||
|
gaps 8
|
||||||
|
center-focused-column "never"
|
||||||
|
background-color "#15171a"
|
||||||
|
|
||||||
|
preset-column-widths {
|
||||||
|
proportion 0.33333
|
||||||
|
proportion 0.5
|
||||||
|
proportion 0.66667
|
||||||
|
}
|
||||||
|
|
||||||
|
default-column-width {
|
||||||
|
proportion 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
focus-ring {
|
||||||
|
width 2
|
||||||
|
active-color "#d4c5a5"
|
||||||
|
inactive-color "#4d5056"
|
||||||
|
urgent-color "#dc7a78"
|
||||||
|
}
|
||||||
|
|
||||||
|
border {
|
||||||
|
off
|
||||||
|
}
|
||||||
|
|
||||||
|
shadow {
|
||||||
|
on
|
||||||
|
softness 30
|
||||||
|
spread -5
|
||||||
|
offset x=0 y=8
|
||||||
|
color "#00000070"
|
||||||
|
}
|
||||||
|
|
||||||
|
tab-indicator {
|
||||||
|
active-color "#d4c5a5"
|
||||||
|
inactive-color "#4d5056"
|
||||||
|
urgent-color "#dc7a78"
|
||||||
|
}
|
||||||
|
|
||||||
|
insert-hint {
|
||||||
|
color "#d4c5a580"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window-rule {
|
||||||
|
match app-id=".*"
|
||||||
|
geometry-corner-radius 12
|
||||||
|
clip-to-geometry true
|
||||||
|
tiled-state true
|
||||||
|
draw-border-with-background false
|
||||||
|
}
|
||||||
|
|
||||||
|
window-rule {
|
||||||
|
match app-id=r#"(?i)^alacritty$"#
|
||||||
|
opacity 0.88
|
||||||
|
default-column-width {
|
||||||
|
proportion 0.5
|
||||||
|
}
|
||||||
|
background-effect {
|
||||||
|
blur true
|
||||||
|
xray true
|
||||||
|
noise 0.025
|
||||||
|
saturation 0.95
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window-rule {
|
||||||
|
match app-id=r#"(?i)^(firefox|org\.mozilla\.firefox|google-chrome|chromium|brave-browser|zen-browser)$"#
|
||||||
|
opacity 1.0
|
||||||
|
default-column-width {
|
||||||
|
proportion 0.62
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window-rule {
|
||||||
|
match app-id=r#"(?i)^(mpv|vlc|io\.github\.celluloid_player\.Celluloid|org\.gnome\.Totem|steam)$"#
|
||||||
|
opacity 1.0
|
||||||
|
default-column-width {
|
||||||
|
proportion 0.70
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window-rule {
|
||||||
|
match app-id=r#"^org\.gnome\.(Calculator|Settings|Loupe)$"#
|
||||||
|
open-floating true
|
||||||
|
default-column-width {
|
||||||
|
proportion 0.36
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binds {
|
||||||
|
Mod+Return hotkey-overlay-title="打开终端" { spawn "alacritty"; }
|
||||||
|
Mod+D hotkey-overlay-title="应用启动器" { spawn "fuzzel"; }
|
||||||
|
Mod+B hotkey-overlay-title="打开默认浏览器" { spawn "sh" "-lc" "xdg-open https://www.google.com"; }
|
||||||
|
Mod+E hotkey-overlay-title="文件管理器" { spawn "nautilus"; }
|
||||||
|
Mod+L hotkey-overlay-title="锁定屏幕" { spawn "swaylock" "-f"; }
|
||||||
|
Mod+Shift+Slash hotkey-overlay-title="显示快捷键说明" { show-hotkey-overlay; }
|
||||||
|
|
||||||
|
Mod+Q hotkey-overlay-title="关闭窗口" { close-window; }
|
||||||
|
Mod+O repeat=false hotkey-overlay-title="总览" { toggle-overview; }
|
||||||
|
Mod+F hotkey-overlay-title="最大化当前列" { maximize-column; }
|
||||||
|
Mod+Shift+F hotkey-overlay-title="窗口全屏" { fullscreen-window; }
|
||||||
|
Mod+V hotkey-overlay-title="切换浮动窗口" { toggle-window-floating; }
|
||||||
|
Mod+W hotkey-overlay-title="切换标签页模式" { toggle-column-tabbed-display; }
|
||||||
|
|
||||||
|
Mod+Left hotkey-overlay-title="焦点向左" { focus-column-left; }
|
||||||
|
Mod+Down hotkey-overlay-title="焦点向下" { focus-window-down; }
|
||||||
|
Mod+Up hotkey-overlay-title="焦点向上" { focus-window-up; }
|
||||||
|
Mod+Right hotkey-overlay-title="焦点向右" { focus-column-right; }
|
||||||
|
Mod+H { focus-column-left; }
|
||||||
|
Mod+J { focus-window-down; }
|
||||||
|
Mod+K { focus-window-up; }
|
||||||
|
Mod+Semicolon { focus-column-right; }
|
||||||
|
|
||||||
|
Mod+Shift+Left hotkey-overlay-title="窗口向左移动" { move-column-left; }
|
||||||
|
Mod+Shift+Down hotkey-overlay-title="窗口向下移动" { move-window-down; }
|
||||||
|
Mod+Shift+Up hotkey-overlay-title="窗口向上移动" { move-window-up; }
|
||||||
|
Mod+Shift+Right hotkey-overlay-title="窗口向右移动" { move-column-right; }
|
||||||
|
|
||||||
|
Mod+Page_Down hotkey-overlay-title="下一个工作区" { focus-workspace-down; }
|
||||||
|
Mod+Page_Up hotkey-overlay-title="上一个工作区" { focus-workspace-up; }
|
||||||
|
Mod+Shift+Page_Down hotkey-overlay-title="窗口移到下一个工作区" { move-column-to-workspace-down; }
|
||||||
|
Mod+Shift+Page_Up hotkey-overlay-title="窗口移到上一个工作区" { move-column-to-workspace-up; }
|
||||||
|
|
||||||
|
Mod+1 { focus-workspace 1; }
|
||||||
|
Mod+2 { focus-workspace 2; }
|
||||||
|
Mod+3 { focus-workspace 3; }
|
||||||
|
Mod+4 { focus-workspace 4; }
|
||||||
|
Mod+5 { focus-workspace 5; }
|
||||||
|
Mod+Shift+1 { move-column-to-workspace 1; }
|
||||||
|
Mod+Shift+2 { move-column-to-workspace 2; }
|
||||||
|
Mod+Shift+3 { move-column-to-workspace 3; }
|
||||||
|
Mod+Shift+4 { move-column-to-workspace 4; }
|
||||||
|
Mod+Shift+5 { move-column-to-workspace 5; }
|
||||||
|
|
||||||
|
Mod+R hotkey-overlay-title="切换列宽" { switch-preset-column-width; }
|
||||||
|
Mod+Shift+R hotkey-overlay-title="切换窗口高度" { switch-preset-window-height; }
|
||||||
|
Mod+Minus { set-column-width "-10%"; }
|
||||||
|
Mod+Equal { set-column-width "+10%"; }
|
||||||
|
|
||||||
|
Print hotkey-overlay-title="截图" { screenshot; }
|
||||||
|
Ctrl+Print hotkey-overlay-title="截取屏幕" { screenshot-screen; }
|
||||||
|
Alt+Print hotkey-overlay-title="截取窗口" { screenshot-window; }
|
||||||
|
|
||||||
|
XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.05+"; }
|
||||||
|
XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.05-"; }
|
||||||
|
XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; }
|
||||||
|
XF86AudioPlay allow-when-locked=true { spawn "playerctl" "play-pause"; }
|
||||||
|
XF86AudioNext allow-when-locked=true { spawn "playerctl" "next"; }
|
||||||
|
XF86AudioPrev allow-when-locked=true { spawn "playerctl" "previous"; }
|
||||||
|
XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "set" "+5%"; }
|
||||||
|
XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "set" "5%-"; }
|
||||||
|
|
||||||
|
Mod+Shift+E hotkey-overlay-title="退出 Niri" { quit; }
|
||||||
|
Mod+Shift+P hotkey-overlay-title="关闭显示器" { power-off-monitors; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
daemonize
|
||||||
|
show-failed-attempts
|
||||||
|
ignore-empty-password
|
||||||
|
font=Noto Sans CJK SC
|
||||||
|
font-size=24
|
||||||
|
indicator-radius=82
|
||||||
|
indicator-thickness=8
|
||||||
|
inside-color=181a1dcc
|
||||||
|
inside-clear-color=d4c5a5cc
|
||||||
|
inside-ver-color=5d83aacc
|
||||||
|
inside-wrong-color=dc7a78cc
|
||||||
|
ring-color=ffffff30
|
||||||
|
ring-clear-color=d4c5a5ff
|
||||||
|
ring-ver-color=7aa2c8ff
|
||||||
|
ring-wrong-color=dc7a78ff
|
||||||
|
key-hl-color=d4c5a5ff
|
||||||
|
text-color=f0eee8ff
|
||||||
|
text-clear-color=181a1dff
|
||||||
|
text-ver-color=f0eee8ff
|
||||||
|
text-wrong-color=f0eee8ff
|
||||||
|
separator-color=00000000
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"layer": "top",
|
||||||
|
"position": "top",
|
||||||
|
"height": 36,
|
||||||
|
"spacing": 6,
|
||||||
|
"margin-top": 6,
|
||||||
|
"margin-left": 8,
|
||||||
|
"margin-right": 8,
|
||||||
|
"modules-left": ["custom/launcher"],
|
||||||
|
"modules-center": [],
|
||||||
|
"modules-right": ["tray", "network", "pulseaudio", "battery", "clock", "custom/lock", "custom/power"],
|
||||||
|
"custom/launcher": {
|
||||||
|
"format": " \uf141 ",
|
||||||
|
"tooltip": false,
|
||||||
|
"on-click": "fuzzel"
|
||||||
|
},
|
||||||
|
"tray": {
|
||||||
|
"icon-size": 17,
|
||||||
|
"spacing": 8
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"format-wifi": "\uf1eb {signalStrength}%",
|
||||||
|
"format-ethernet": "\uf1e6",
|
||||||
|
"format-disconnected": "\uf071",
|
||||||
|
"tooltip-format": "{ifname}: {ipaddr}/{cidr}"
|
||||||
|
},
|
||||||
|
"pulseaudio": {
|
||||||
|
"format": "{icon} {volume}%",
|
||||||
|
"format-muted": "\uf026",
|
||||||
|
"format-icons": ["\uf026", "\uf027", "\uf028"],
|
||||||
|
"on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
|
||||||
|
"tooltip": false
|
||||||
|
},
|
||||||
|
"battery": {
|
||||||
|
"states": {"warning": 30, "critical": 15},
|
||||||
|
"format": "{icon} {capacity}%",
|
||||||
|
"format-charging": "\uf0e7 {capacity}%",
|
||||||
|
"format-icons": ["\uf244", "\uf243", "\uf242", "\uf241", "\uf240"],
|
||||||
|
"tooltip": false
|
||||||
|
},
|
||||||
|
"clock": {
|
||||||
|
"interval": 1,
|
||||||
|
"format": "{:%m月%d日 %H:%M}",
|
||||||
|
"tooltip-format": "<tt>{calendar}</tt>"
|
||||||
|
},
|
||||||
|
"custom/lock": {
|
||||||
|
"format": "\uf023",
|
||||||
|
"tooltip": false,
|
||||||
|
"on-click": "swaylock -f"
|
||||||
|
},
|
||||||
|
"custom/power": {
|
||||||
|
"format": "\uf011",
|
||||||
|
"tooltip": false,
|
||||||
|
"on-click": "wlogout"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
@define-color panel rgba(24, 26, 29, 0.76);
|
||||||
|
@define-color text #f0eee8;
|
||||||
|
@define-color muted #a8abb2;
|
||||||
|
@define-color accent #d4c5a5;
|
||||||
|
@define-color red #dc7a78;
|
||||||
|
|
||||||
|
* {
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
min-height: 0;
|
||||||
|
font-family: "Noto Sans CJK SC", "Noto Sans", "FontAwesome";
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
window#waybar {
|
||||||
|
background: @panel;
|
||||||
|
color: @text;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.10);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-launcher,
|
||||||
|
#tray,
|
||||||
|
#network,
|
||||||
|
#pulseaudio,
|
||||||
|
#battery,
|
||||||
|
#clock,
|
||||||
|
#custom-lock,
|
||||||
|
#custom-power {
|
||||||
|
padding: 0 10px;
|
||||||
|
color: @text;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-launcher {
|
||||||
|
color: @accent;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#network.disconnected,
|
||||||
|
#battery.critical {
|
||||||
|
color: @red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-lock,
|
||||||
|
#custom-power {
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-power {
|
||||||
|
color: @red;
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip {
|
||||||
|
background: #202226;
|
||||||
|
color: @text;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
Executable
+323
@@ -0,0 +1,323 @@
|
|||||||
|
#!/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.0(Ubuntu 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
|
||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
state="${XDG_CONFIG_HOME:-$HOME/.config}/niri-beyond-glass/wallpaper"
|
||||||
|
wallpaper=""
|
||||||
|
|
||||||
|
if [[ -s "$state" ]]; then
|
||||||
|
IFS= read -r wallpaper < "$state"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$wallpaper" && -f "$wallpaper" ]]; then
|
||||||
|
exec swaybg -m fill -i "$wallpaper"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec swaybg -c '#15171a'
|
||||||
Executable
+29
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||||
|
state_home="${XDG_STATE_HOME:-$HOME/.local/state}"
|
||||||
|
backup_root="$state_home/niri-beyond-glass/backups"
|
||||||
|
latest=""
|
||||||
|
|
||||||
|
if [[ -d "$backup_root" ]]; then
|
||||||
|
latest="$(find "$backup_root" -mindepth 1 -maxdepth 1 -type d -printf '%p\n' | sort | tail -n 1)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf \
|
||||||
|
"$config_home/niri" \
|
||||||
|
"$config_home/waybar" \
|
||||||
|
"$config_home/fuzzel" \
|
||||||
|
"$config_home/mako" \
|
||||||
|
"$config_home/swaylock" \
|
||||||
|
"$config_home/niri-beyond-glass"
|
||||||
|
rm -f "$HOME/.local/bin/niri-beyond-wallpaper"
|
||||||
|
|
||||||
|
if [[ -n "$latest" && -d "$latest/config" ]]; then
|
||||||
|
cp -a "$latest/config/." "$config_home/"
|
||||||
|
printf '已恢复备份:%s\n' "$latest"
|
||||||
|
else
|
||||||
|
printf '配置已移除;没有找到可恢复的备份。\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'Niri 和系统软件包被保留。GNOME/GDM 未修改。\n'
|
||||||
Reference in New Issue
Block a user