ScreenLockDetector/QUICKFIX_LOCK_SIGNALS.md

355 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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