niri Waybar集成教程:工作区状态与系统信息显示配置
引言
你是否还在为Wayland环境下工作区状态无法实时同步而烦恼?是否希望将系统监控与窗口管理器状态无缝融合?本文将带你通过10分钟配置,实现niri compositor与Waybar的深度集成,打造兼顾美观与实用的桌面状态监控中心。
读完本文你将获得:
- 实时工作区状态显示(含活动窗口数量、聚焦状态)
- 低资源占用的事件驱动更新机制
- 系统资源监控与工作区状态的一体化展示
- 自适应明暗主题的UI设计方案
前置准备
环境要求
| 组件 | 最低版本 | 安装方式 |
|---|---|---|
| niri | ≥0.1.9 | cargo install --git https://gitcode.com/GitHub_Trending/ni/niri |
| Waybar | ≥0.9.20 | 各发行版官方仓库或源码编译 |
| jq | ≥1.6 | 系统包管理器安装 |
| socat | ≥1.7.4 | 系统包管理器安装 |
架构概览
工作区状态模块配置
1. 基础数据采集脚本
创建~/.config/waybar/scripts/niri-workspaces.py:
#!/usr/bin/env python3
import json
import os
import subprocess
import sys
from typing import Dict, List
def get_workspaces() -> List[Dict]:
result = subprocess.run(
["niri", "msg", "--json", "workspaces"],
capture_output=True,
text=True
)
return json.loads(result.stdout)["Ok"]["Workspaces"]
def format_workspace(ws: Dict) -> str:
icon = "●" if ws["is_focused"] else "○"
return f"<span color='{ws['color']}'>{icon}</span>"
def main():
workspaces = get_workspaces()
output = {
"text": " ".join(format_workspace(ws) for ws in workspaces),
"class": "workspaces",
"tooltip": "\n".join(f"Workspace {ws['index']}: {ws['window_count']} windows" for ws in workspaces)
}
print(json.dumps(output))
if __name__ == "__main__":
main()
赋予执行权限:
chmod +x ~/.config/waybar/scripts/niri-workspaces.py
2. Waybar模块配置
在~/.config/waybar/config中添加:
{
"modules-left": ["custom/workspaces"],
"custom/workspaces": {
"exec": "~/.config/waybar/scripts/niri-workspaces.py",
"interval": 1,
"return-type": "json",
"format": " {} ",
"on-click": "niri msg action focus-workspace {button}",
"tooltip": true
}
}
3. 事件驱动优化
创建~/.config/waybar/scripts/niri-event-listener.sh:
#!/bin/bash
socat - UNIX-CONNECT:"$NIRI_SOCKET" <<EOF
"Subscribe"
{"EventStream": {}}
EOF | while read -r event; do
if echo "$event" | jq -e '.Ok.Event.WorkspaceChanged' > /dev/null; then
pkill -RTMIN+8 waybar
fi
done
修改Waybar模块为信号触发模式:
"custom/workspaces": {
"exec": "~/.config/waybar/scripts/niri-workspaces.py",
"signal": 8,
"return-type": "json"
}
在~/.config/systemd/user/waybar.service中添加事件监听器:
[Service]
ExecStartPre=/bin/sh -c '~/.config/waybar/scripts/niri-event-listener.sh &'
ExecStart=/usr/bin/waybar
系统信息集成
1. 混合模块配置
扩展Waybar配置,添加系统监控模块:
{
"modules-right": ["custom/ipc-cpu", "custom/ipc-memory", "battery", "clock"],
"custom/ipc-cpu": {
"exec": "~/.config/waybar/scripts/niri-system-info.py cpu",
"interval": 2,
"return-type": "json"
},
"custom/ipc-memory": {
"exec": "~/.config/waybar/scripts/niri-system-info.py memory",
"interval": 5,
"return-type": "json"
}
}
2. 系统信息采集脚本
创建~/.config/waybar/scripts/niri-system-info.py:
#!/usr/bin/env python3
import json
import sys
import psutil
def get_cpu_usage():
return {
"text": f"CPU {psutil.cpu_percent()}%",
"class": "cpu",
"percentage": psutil.cpu_percent()
}
def get_memory_usage():
mem = psutil.virtual_memory()
return {
"text": f"MEM {mem.percent}%",
"class": "memory",
"percentage": mem.percent
}
if __name__ == "__main__":
if len(sys.argv) != 2:
print(json.dumps({"error": "Missing argument"}))
sys.exit(1)
if sys.argv[1] == "cpu":
data = get_cpu_usage()
elif sys.argv[1] == "memory":
data = get_memory_usage()
else:
data = {"error": "Invalid argument"}
print(json.dumps(data))
样式美化
1. 基础样式定义
在~/.config/waybar/style.css中添加:
/* 工作区模块基础样式 */
#custom-workspaces {
background: rgba(30, 30, 46, 0.8);
padding: 0 10px;
border-radius: 8px;
margin: 4px 0;
}
/* 工作区状态指示 */
#custom-workspaces span {
font-size: 12px;
padding: 0 2px;
}
/* 系统信息模块 */
#custom-ipc-cpu, #custom-ipc-memory {
padding: 0 8px;
margin: 0 4px;
}
/* 资源占用警告样式 */
#custom-ipc-cpu.percentage-high,
#custom-ipc-memory.percentage-high {
color: #f38ba8;
}
2. 动态样式适配
修改系统信息脚本,添加动态样式类:
def get_cpu_usage():
usage = psutil.cpu_percent()
return {
"text": f"CPU {usage}%",
"class": "cpu" + (" percentage-high" if usage > 80 else ""),
"percentage": usage
}
高级配置
1. 多显示器工作区同步
添加多显示器支持到工作区脚本:
def get_workspaces():
result = subprocess.run(
["niri", "msg", "--json", "outputs"],
capture_output=True,
text=True
)
outputs = json.loads(result.stdout)["Ok"]["Outputs"]
workspace_data = []
for output in outputs:
ws_result = subprocess.run(
["niri", "msg", "--json", f"workspaces --output {output['name']}"],
capture_output=True,
text=True
)
workspace_data.extend(json.loads(ws_result.stdout)["Ok"]["Workspaces"])
return workspace_data
2. 窗口标题显示优化
添加窗口标题模块到Waybar配置:
"custom/window-title": {
"exec": "~/.config/waybar/scripts/niri-window-title.py",
"signal": 9,
"return-type": "json"
}
窗口标题脚本:
#!/usr/bin/env python3
import json
import subprocess
def get_focused_window():
result = subprocess.run(
["niri", "msg", "--json", "focused-window"],
capture_output=True,
text=True
)
return json.loads(result.stdout)["Ok"]["FocusedWindow"]
if __name__ == "__main__":
window = get_focused_window() or {"title": "", "app_id": ""}
text = window["title"] or window["app_id"]
print(json.dumps({"text": text[:50] + "..." if len(text) > 50 else text}))
故障排除
常见问题解决
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 工作区状态不更新 | 事件监听器未运行 | systemctl --user restart waybar |
| JSON解析错误 | niri版本不匹配 | niri --version 确认≥0.1.9 |
| Waybar崩溃 | 脚本权限不足 | chmod +x 所有Python脚本 |
| 高CPU占用 | 轮询间隔过短 | 改用事件驱动模式 |
调试工具
# 监控niri事件流
niri msg --json event-stream | jq .
# 检查Waybar日志
waybar -l debug 2> ~/.waybar.log
# 验证IPC连接
socat STDIO "$NIRI_SOCKET"
总结与展望
通过本教程,我们构建了一个基于niri IPC事件流的高效工作区监控系统,实现了:
- 微秒级响应的工作区状态更新
- 模块化的系统资源监控设计
- 自适应主题的UI展示方案
未来可能的扩展方向:
- 集成窗口预览缩略图
- 添加工作区切换动画效果
- 实现基于机器学习的窗口自动分类
建议收藏本文,并关注项目GitCode仓库获取最新更新。如有疑问,欢迎在项目issue区提交反馈。
附录:完整配置文件
Waybar配置文件
{
"height": 32,
"modules-left": ["custom/workspaces", "custom/window-title"],
"modules-right": ["custom/ipc-cpu", "custom/ipc-memory", "battery", "clock"],
"custom/workspaces": {
"exec": "~/.config/waybar/scripts/niri-workspaces.py",
"signal": 8,
"return-type": "json",
"format": " {} "
},
"custom/window-title": {
"exec": "~/.config/waybar/scripts/niri-window-title.py",
"signal": 9,
"return-type": "json",
"max-length": 60
},
"custom/ipc-cpu": {
"exec": "~/.config/waybar/scripts/niri-system-info.py cpu",
"interval": 2,
"return-type": "json"
},
"custom/ipc-memory": {
"exec": "~/.config/waybar/scripts/niri-system-info.py memory",
"interval": 5,
"return-type": "json"
}
}
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



