ScreenLockDetector/QUICKFIX_LOCK_SIGNALS.md

355 lines
8.3 KiB
Markdown
Raw Normal View History

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