355 lines
8.3 KiB
Markdown
355 lines
8.3 KiB
Markdown
# 锁屏信号问题快速修复指南
|
||
|
||
## 问题症状
|
||
|
||
✗ 程序显示"已成功连接到目标系统的服务"
|
||
✗ 但锁屏时 `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. ✅ 多重连接策略(提高兼容性)
|
||
|
||
大多数情况下,这些修复应该能解决问题。如果还有问题,使用提供的调试工具找出系统实际使用的信号机制。 |