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