Last active
November 25, 2025 05:27
-
-
Save ihipop/b3daaa8fba69f3dbe4189a5e63dbb001 to your computer and use it in GitHub Desktop.
根据外接显示器/笔记本盖子的情况 开启关闭 krfb-virtualmonitor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # 监听 KDE 6 的 org.kde.Solid.PowerManagement 用户级会话信号,控制 krfb-virtualmonitor 服务 | |
| # 完全用户级,无需 root 权限,增强信号解析和错误处理 | |
| # 用于后台监听显示器插拔事件 | |
| start_monitor_listener() { | |
| gdbus monitor --session --dest org.freedesktop.PowerManagement -o /org/kde/ScreenBrightness | | |
| while IFS= read -r line; do | |
| if echo "$line" | grep --line-buffered -q -E "DisplayAdded|DisplayRemoved"; then | |
| echo "检测到显示器相关事件,重新检查 4K 状态" | |
| control_krfb_service $(check_lid_not_closed_state) | |
| fi | |
| done | |
| } | |
| start_lock_listener(){ | |
| gdbus monitor --session --dest org.freedesktop.ScreenSaver --object-path /ScreenSaver "member='ActiveChanged'"| | |
| while IFS= read -r line; do | |
| if echo "$line" | grep --line-buffered -q -E "ActiveChanged"; then | |
| echo "检测到锁屏相关事件,重新检查 4K 状态" | |
| control_krfb_service $(check_not_lock_state) | |
| fi | |
| done | |
| } | |
| check_not_lock_state(){ | |
| locked=$(gdbus call --session \ | |
| --dest org.freedesktop.ScreenSaver \ | |
| --object-path /ScreenSaver \ | |
| --method org.freedesktop.ScreenSaver.GetActive |sed -E "s/.*?(true|false).*?/\1/g") | |
| if [ "$locked" = "true" ]; then | |
| echo "false" | |
| elif [ "$locked" = "false" ]; then | |
| echo "true" | |
| else | |
| echo "unknown" | |
| fi | |
| } | |
| # 函数:根据状态控制 krfb-virtualmonitor 服务 | |
| control_krfb_service() { | |
| if has_4k_monitor; then | |
| echo "检测到 4K 显示器,禁止启动 krfb-virtualmonitor 服务" | |
| systemctl --user stop krfb-virtualmonitor.service | |
| return 0 | |
| fi | |
| local state="$1" | |
| if [ "$state" = "false" ]; then | |
| echo "停止 krfb-virtualmonitor 服务" | |
| systemctl --user stop krfb-virtualmonitor.service | |
| elif [ "$state" = "true" ]; then | |
| echo "启动 krfb-virtualmonitor 服务" | |
| systemctl --user start krfb-virtualmonitor.service | |
| else | |
| echo "错误:无法控制服务,未知状态 '$state'" | |
| fi | |
| } | |
| # 函数:检查盖子状态并返回状态 | |
| check_lid_not_closed_state() { | |
| local lid_state | |
| lid_state=$(loginctl show-session -p LidClosed | cut -d= -f2) | |
| if [ "$lid_state" = "yes" ]; then | |
| echo "false" | |
| elif [ "$lid_state" = "no" ]; then | |
| echo "true" | |
| else | |
| echo "unknown" | |
| fi | |
| } | |
| # 函数:检查是否存在物理 4K(2160 高度)的显示器 | |
| has_4k_monitor() { | |
| for modes in $(kscreen-doctor -o | grep -oP '\d+x\d+@\d+(?=\*)'); do | |
| if echo "$modes" | grep -q 'x2160'; then | |
| return 0 # 存在 4K | |
| fi | |
| done | |
| return 1 # 没有 4K | |
| } | |
| # 函数:检查是否存在物理 4K(2160 高度)的显示器 | |
| has_4k_monitor_from_drm() { | |
| for modes in /sys/class/drm/*/modes; do | |
| [ -f "$modes" ] || continue | |
| if grep -q 'x2160' "$modes"; then | |
| return 0 # 存在 4K | |
| fi | |
| done | |
| return 1 # 没有 4K | |
| } | |
| start_lid_listener() { | |
| # 监听 org.kde.Solid.PowerManagement 的用户级信号 | |
| gdbus monitor --session -d org.kde.Solid.PowerManagement -o /org/kde/Solid/PowerManagement | | |
| while IFS= read -r line; do | |
| # 检查 D-Bus 连接是否有效 | |
| if echo "$line" | grep -q "org.freedesktop.DBus.Error"; then | |
| echo "错误:D-Bus 连接失败,信号内容:'$line'" | |
| continue | |
| fi | |
| # 检查信号是否包含盖子状态相关内容 | |
| if echo "$line" | grep -q -E "lidClosed|onLidClosed|lidClosedChanged"; then | |
| # 尝试解析信号中的盖子状态 | |
| if echo "$line" | grep -q -E "lidClosed.*true|onLidClosed.*true|lidClosedChanged.*true"; then | |
| CURRENT_STATE="closed" | |
| elif echo "$line" | grep -q -E "lidClosed.*false|onLidClosed.*false|lidClosedChanged.*false"; then | |
| CURRENT_STATE="open" | |
| else | |
| # 后备:调用 loginctl 检查函数 | |
| CURRENT_STATE=$(check_lid_state) | |
| fi | |
| control_krfb_service "$CURRENT_STATE" | |
| fi | |
| done | |
| } | |
| # 初始化:启动 D-Bus 监听前执行一次 loginctl 检测 | |
| control_krfb_service $(check_lid_not_closed_state) | |
| control_krfb_service $(check_not_lock_state) | |
| # 启动后台监听 | |
| start_monitor_listener & | |
| MONITOR_LISTENER_PID=$! | |
| start_lid_listener & | |
| LID_LISTENER_PID=$! | |
| start_lock_listener & | |
| LOCK_LISTENER_PID=$! | |
| # 捕获退出信号,确保后台进程被杀掉 | |
| cleanup() { | |
| echo "脚本退出,停止后台监听..." | |
| kill $MONITOR_LISTENER_PID $LID_LISTENER_PID $LOCK_LISTENER_PID 2>/dev/null | |
| wait $MONITOR_LISTENER_PID $LID_LISTENER_PID $LOCK_LISTENER_PID 2>/dev/null | |
| } | |
| trap cleanup EXIT INT TERM | |
| wait -n $MONITOR_LISTENER_PID $LID_LISTENER_PID $LOCK_LISTENER_PID | |
| echo "有后台进程退出,脚本结束" | |
| exit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment