8.3 KiB
锁屏信号问题快速修复指南
问题症状
✗ 程序显示"已成功连接到目标系统的服务"
✗ 但锁屏时 onSessionLocked() 没有被调用
✗ Ubuntu 和 Deepin 系统都有此问题
快速解决方案
🚀 一键验证修复
已经重新编译,直接运行验证脚本:
./verify_fix.sh
这个脚本会:
- 检查编译状态
- 显示系统环境信息
- 检测可用的 DBus 服务
- 启动程序并提示如何测试
📋 核心修复内容
修复 1: 动态获取会话路径
问题: 原代码使用固定路径 /org/freedesktop/login1/session/auto,在大多数系统上不工作
修复: 新增方法动态获取实际会话路径
QString getCurrentSessionPath() {
// 从环境变量 XDG_SESSION_ID 获取
// 或通过 DBus 调用 GetSessionByPID 获取
}
修复 2: 广播式信号监听
问题: 只监听特定路径的信号
修复: 添加空路径监听(监听所有会话)
// 监听所有 session 的 Lock/Unlock 信号
QDBusConnection::systemBus().connect(
"org.freedesktop.login1",
"", // 空路径 = 监听所有对象
"org.freedesktop.login1.Session",
"Lock",
this,
SLOT(onSessionLocked())
);
修复 3: 增强调试信息
问题: 无法判断问题出在哪个环节
修复:
- 继承
QDBusContext获取信号详情 - 在关键点添加详细日志
- 显示信号的来源路径和接口
验证修复是否生效
预期的启动日志
=================================================
Initializing ScreenLockDetector...
=================================================
--- Connecting to Login Manager (systemd-logind) ---
Session path from XDG_SESSION_ID: /org/freedesktop/login1/session/c1
Current session path: /org/freedesktop/login1/session/c1
Login Manager interface is valid for session: ...
Session Lock signal connected: true ← ✓ 应该是 true
Session Unlock signal connected: true ← ✓ 应该是 true
=================================================
ScreenLockDetector initialized successfully
Login Manager connected: true ← ✓ 至少一个为 true
=================================================
预期的锁屏日志
当你按 Super+L 或 Ctrl+Alt+L 锁屏后:
##################################################
## LOCK SIGNAL RECEIVED
## Screen is now LOCKED
## DBus Message Details:
## Service: :1.43
## Path: /org/freedesktop/login1/session/c1
## Interface: org.freedesktop.login1.Session
## Member: Lock
##################################################
如果还是不工作
🔍 调试步骤
步骤 1: 检查实际发送的信号
运行监听脚本:
./test_lock_signals.sh
按提示锁屏/解锁,观察哪些信号被发出。
步骤 2: 手动测试 DBus
在一个终端运行:
dbus-monitor --system "type='signal',interface='org.freedesktop.login1.Session'"
在另一个终端锁屏:
# GNOME/Ubuntu
gnome-screensaver-command -l
# 或通用方法
loginctl lock-session
# Deepin
dde-lock
观察是否有 Lock 信号出现。
步骤 3: 检查会话状态
# 查看会话 ID
echo $XDG_SESSION_ID
# 查看会话详情
loginctl show-session $XDG_SESSION_ID
# 列出所有会话
loginctl list-sessions
确保你的会话是活动的,类型是 x11 或 wayland。
步骤 4: 检查权限
# 当前用户的组
groups
# 测试是否能访问 systemd-logind
dbus-send --system --print-reply \
--dest=org.freedesktop.login1 \
/org/freedesktop/login1 \
org.freedesktop.DBus.Introspectable.Introspect
🔧 特定系统的额外步骤
Ubuntu / GNOME 系统
如果 systemd-logind 不工作,检查 GNOME ScreenSaver:
# 检查服务是否存在
dbus-send --session --print-reply \
--dest=org.gnome.ScreenSaver \
/org/gnome/ScreenSaver \
org.freedesktop.DBus.Introspectable.Introspect
# 监听 GNOME 信号
dbus-monitor --session "interface='org.gnome.ScreenSaver'"
# 锁屏
gnome-screensaver-command -l
Deepin 系统
运行 Deepin 专用调试脚本:
./debug_deepin_dbus.sh
这会显示所有可用的 Deepin 锁屏服务,然后实时监听信号。
常见的 Deepin 服务名:
com.deepin.dde.lockFrontorg.deepin.dde.lockFrontcom.deepin.ScreenSaver
Wayland 会话
Wayland 可能有不同的行为:
# 检查会话类型
echo $XDG_SESSION_TYPE
# 如果是 wayland,可能需要使用不同的方法
# 某些 Wayland 合成器使用自己的锁屏协议
常见问题解答
Q: 为什么连接显示成功但收不到信号?
A: 可能原因:
- 路径不对: 连接到了错误的会话路径
- 时机问题: 信号在连接之前就发送了
- 权限问题: 没有权限监听 system bus 信号
- 桌面环境: 使用了非标准的锁屏机制
解决: 使用 test_lock_signals.sh 查看实际信号
Q: 在虚拟机中测试有问题吗?
A: 可能会有。确保:
- ✓ 使用完整的桌面环境(不是最小化安装)
- ✓ 通过图形界面登录(不是 SSH)
- ✓ 虚拟机有足够的资源
- ✓ 安装了 Guest Additions / Tools
Q: 日志显示 "connected: true" 但还是没反应?
A: 这说明连接成功了,但信号可能:
- 使用了不同的信号名(如
LockedvsLock) - 从不同的路径发出
- 带有额外的参数
运行 dbus-monitor 直接查看:
# 监听所有 session bus 信号
dbus-monitor --session "type='signal'" | grep -i lock
# 监听所有 system bus 信号
dbus-monitor --system "type='signal'" | grep -i lock
Q: Deepin 系统上完全不工作?
A: Deepin 不同版本的接口差异很大:
-
找到正确的服务名:
dbus-send --session --print-reply \ --dest=org.freedesktop.DBus \ /org/freedesktop/DBus \ org.freedesktop.DBus.ListNames | grep -i deepin -
查看服务接口:
dbus-send --session --print-reply \ --dest=com.deepin.dde.lockFront \ /com/deepin/dde/lockFront \ org.freedesktop.DBus.Introspectable.Introspect -
修改
screenlockdetector.cpp中connectToDeepinDDE()的服务列表
技术细节
为什么需要空路径监听?
DBus 信号连接时指定路径会限制只接收该对象的信号。使用空路径 "" 表示监听该接口的所有对象的信号。
// 只监听特定会话
connect("service", "/path/to/session1", "interface", "signal", ...)
// 监听所有会话(推荐)
connect("service", "", "interface", "signal", ...)
QDBusContext 的作用
继承 QDBusContext 后,在 slot 函数中可以调用 message() 获取触发信号的详细信息:
QDBusMessage msg = QDBusContext::message();
qDebug() << "Signal from:" << msg.service() << msg.path();
这对调试非常有用。
systemd-logind Session 接口
标准接口应该有这些信号:
Lock- 会话锁定Unlock- 会话解锁PauseDevice- 设备暂停ResumeDevice- 设备恢复
和这些属性:
LockedHint- 布尔值,指示会话是否锁定Active- 会话是否活动Type- 会话类型(x11, wayland, tty 等)
获取帮助
如果以上方法都不行,请提供以下信息:
-
系统信息:
cat /etc/os-release echo "Desktop: $XDG_CURRENT_DESKTOP" echo "Session: $XDG_SESSION_TYPE" -
会话信息:
loginctl show-session $XDG_SESSION_ID -
程序输出: 运行
./run.sh的完整输出 -
信号监听结果: 运行
./test_lock_signals.sh的输出 -
手动测试结果:
dbus-monitor --system "type='signal'" | grep -i lock # 然后锁屏,记录输出
相关文档
- 📖 详细修复说明:
LOCK_SIGNAL_FIX.md - 🔧 Deepin 支持:
DEEPIN_SUPPORT.md - 🏗️ 架构文档:
ARCHITECTURE.md - 📝 项目概览:
PROJECT_OVERVIEW.md
总结
核心修复点:
- ✅ 动态获取会话路径(不硬编码 "auto")
- ✅ 空路径监听(接收所有会话信号)
- ✅ 详细调试日志(便于诊断)
- ✅ 多重连接策略(提高兼容性)
大多数情况下,这些修复应该能解决问题。如果还有问题,使用提供的调试工具找出系统实际使用的信号机制。