KDE换平铺WM niri:解决屏幕共享和剪贴板问题
前言
最近 KDE 总是吃满我的核显,感觉不太好。看了看平铺 WM,试用了一段时间的 hyprland 和 niri,最终选择了 niri。
相较于 hyprland ,niri 没有那么好的生态,但是无限延伸的 Workspace 让我的上手成本非常低,不需要去纠结怎么调整窗口的位置和大小。
不过一起看,相较于 KDE 这种完整的 DE,niri 还是比较的简单。选择需要谨慎。下面是一些可能遇到的问题,以及对应的可能的解法。
屏幕共享
关于屏幕共享,安装 xdg-desktop-portal-gnome ,然后打补丁。
git clone https://github.com/YaLTeR/niri.git
cd niri
wget https://github.com/YaLTeR/niri/pull/1791.patch
git apply 1791.patch
cargo build --release
我这里没做 cherry pick。产物在 130MB 左右,正常。
如果不想要 gnome 门户带来的鹦鹉螺,可以强制卸载:
sudo pacman -Rdd nautilus
运行 X11 程序
niri 自身不处理 X11,但是集成了对 xwayland-satellite 的支持。安装好了。
paru -S xwayland-satellite
X11 Wayland 剪切板同步
niri 不会同步 x11 和 Wayland 的剪贴板内容,因此在使用如 QQ、微信等 X11 程序的时候会导致无法复制剪贴板,这时候我们就需要一个脚本来手动进行同步。
#!/bin/bash
# 颜色定义
COLOR_RESET="\033[0m"
COLOR_GREEN="\033[32m"
COLOR_BLUE="\033[34m"
COLOR_YELLOW="\033[33m"
COLOR_CYAN="\033[36m"
# 日志函数
log() {
local timestamp=$(date '+%H:%M:%S')
echo -e "${COLOR_CYAN}[$timestamp]${COLOR_RESET} $1"
}
log_sync() {
local direction=$1
local type=$2
local format=$3
case "$direction" in
"x11->wl")
echo -e "${COLOR_CYAN}[$(date '+%H:%M:%S')]${COLOR_RESET} ${COLOR_GREEN}${COLOR_RESET} X11 → Wayland | ${COLOR_YELLOW}${type}${COLOR_RESET}${format}"
;;
"wl->x11")
echo -e "${COLOR_CYAN}[$(date '+%H:%M:%S')]${COLOR_RESET} ${COLOR_BLUE}${COLOR_RESET} Wayland → X11 | ${COLOR_YELLOW}${type}${COLOR_RESET}${format}"
;;
esac
}
# 检查依赖
check_dependencies() {
local missing_deps=()
for cmd in xclip wl-paste wl-copy sha256sum; do
if ! command -v "$cmd" &>/dev/null; then
missing_deps+=("$cmd")
fi
done
if [[ ${#missing_deps[@]} -gt 0 ]]; then
echo "错误:缺少以下依赖命令:${missing_deps[*]}" >&2
echo "请安装相应的软件包后重试" >&2
exit 1
fi
}
# 防抖变量
last_text=""
last_x11_img_hash="" # 上次从 X11 同步到 Wayland 的图片哈希
last_wl_img_hash="" # 上次从 Wayland 同步到 X11 的图片哈希
# 剪切板同步主循环
clipboard_sync() {
while true; do
img_synced=false # 标记本轮是否已同步图片
# -------- 图片同步:X11 → Wayland --------
x11_targets=$(xclip -selection clipboard -t TARGETS -o 2>/dev/null || true)
x11_img_type=""
if echo "$x11_targets" | grep -q "image/png"; then
x11_img_type="image/png"
elif echo "$x11_targets" | grep -q "image/jpeg"; then
x11_img_type="image/jpeg"
elif echo "$x11_targets" | grep -q "image/gif"; then
x11_img_type="image/gif"
fi
if [[ -n "$x11_img_type" ]]; then
if [[ $(xclip -selection clipboard -t "$x11_img_type" -o 2>/dev/null | wc -c) -gt 0 ]]; then
x11_img_hash=$(xclip -selection clipboard -t "$x11_img_type" -o 2>/dev/null | sha256sum | awk '{print $1}')
if [[ -n "$x11_img_hash" && "$x11_img_hash" != "$last_x11_img_hash" ]]; then
# 直接将图片数据传输到 Wayland 剪切板
xclip -selection clipboard -t "$x11_img_type" -o 2>/dev/null | wl-copy -t "$x11_img_type"
last_x11_img_hash="$x11_img_hash"
last_wl_img_hash="$x11_img_hash"
img_synced=true
log_sync "x11->wl" "图片" " ($x11_img_type)"
# 清空 X11 剪切板,让 Wayland 成为唯一数据源
xclip -selection clipboard -i /dev/null
fi
fi
fi
# -------- 图片同步:Wayland → X11 --------
# 只在本轮未同步图片时才检查 Wayland → X11
if [[ "$img_synced" == false ]]; then
wl_types=$(wl-paste --list-types 2>/dev/null || true)
wl_img_type=""
if echo "$wl_types" | grep -q "image/png"; then
wl_img_type="image/png"
elif echo "$wl_types" | grep -q "image/jpeg"; then
wl_img_type="image/jpeg"
elif echo "$wl_types" | grep -q "image/gif"; then
wl_img_type="image/gif"
fi
if [[ -n "$wl_img_type" ]]; then
# 使用管道直接传输二进制数据,计算哈希来防抖
wl_img_hash=$(wl-paste -t "$wl_img_type" 2>/dev/null | tee >(sha256sum | awk '{print $1}' > /tmp/wl_hash_$$) | cat > /dev/null; cat /tmp/wl_hash_$$ 2>/dev/null; rm -f /tmp/wl_hash_$$ 2>/dev/null)
# 如果 Wayland 的图片与上次同步的不同,则同步到 X11
if [[ -n "$wl_img_hash" && "$wl_img_hash" != "$last_wl_img_hash" ]]; then
wl-paste -t "$wl_img_type" 2>/dev/null | xclip -selection clipboard -t "$wl_img_type" -i
last_wl_img_hash="$wl_img_hash"
last_x11_img_hash="$wl_img_hash"
img_synced=true # 标记已同步图片,跳过本轮文本同步
log_sync "wl->x11" "图片" " ($wl_img_type)"
fi
fi
fi
# -------- 文本同步 --------
# 只在未同步图片时才进行文本同步
if [[ "$img_synced" == false ]]; then
current_text=$(wl-paste --type text/plain 2>/dev/null || true)
# 只在 X11 剪切板包含文本时才读取,避免读取二进制数据导致警告
x11_text=""
if [[ -z "$x11_img_type" ]]; then
x11_text=$(xclip -selection clipboard -o 2>/dev/null || true)
fi
if [[ -n "$x11_text" && "$x11_text" != "$last_text" && "$x11_text" != "$current_text" ]]; then
echo -n "$x11_text" | wl-copy --type text/plain
last_text="$x11_text"
# 显示文本预览(最多 50 个字符),换行符替换为 ↵
local preview="${x11_text:0:50}"
preview="${preview//$'\n'/↵}"
preview="${preview//$'\r'/}"
preview="${preview//$'\t'/⇥}"
[[ ${#x11_text} -gt 50 ]] && preview="${preview}..."
log_sync "x11->wl" "文本" " \"$preview\""
fi
if [[ -n "$current_text" && "$current_text" != "$last_text" && "$x11_text" != "$current_text" ]]; then
echo "$current_text" | xclip -selection clipboard -t UTF8_STRING -i
last_text="$current_text"
# 显示文本预览(最多 50 个字符),换行符替换为 ↵
local preview="${current_text:0:50}"
preview="${preview//$'\n'/↵}"
preview="${preview//$'\r'/}"
preview="${preview//$'\t'/⇥}"
[[ ${#current_text} -gt 50 ]] && preview="${preview}..."
log_sync "wl->x11" "文本" " \"$preview\""
fi
fi
sleep 0.5
done
}
# 设置退出时清理
trap 'exit' INT TERM EXIT
# 依赖检查
check_dependencies
log "剪切板同步服务已启动"
log "监控 Wayland ↔ X11 剪切板同步..."
# 启动同步服务
clipboard_sync
本脚本优化自 busyo 的脚本一起看博客,感谢他的付出。
托盘不见了
如果你和我一样是从 KDE 转到 niri 的,那极有可能是 kde6 抢占了托盘。kill 掉就好了。不过 Electron 应用无法重新注册托盘图标,也就是说 QQ 啥的托盘不会再回来了。
pkill -f kded6本文转载自互联网,如有侵权,联系删除
发布评论

