ScreenLockDetector/QUICKFIX_LOCK_SIGNALS.md

8.3 KiB
Raw Blame History

锁屏信号问题快速修复指南

问题症状

✗ 程序显示"已成功连接到目标系统的服务"
✗ 但锁屏时 onSessionLocked() 没有被调用
✗ Ubuntu 和 Deepin 系统都有此问题

快速解决方案

🚀 一键验证修复

已经重新编译,直接运行验证脚本:

./verify_fix.sh

这个脚本会:

  1. 检查编译状态
  2. 显示系统环境信息
  3. 检测可用的 DBus 服务
  4. 启动程序并提示如何测试

📋 核心修复内容

修复 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+LCtrl+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

确保你的会话是活动的,类型是 x11wayland

步骤 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.lockFront
  • org.deepin.dde.lockFront
  • com.deepin.ScreenSaver

Wayland 会话

Wayland 可能有不同的行为:

# 检查会话类型
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 直接查看:

# 监听所有 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. 找到正确的服务名:

    dbus-send --session --print-reply \
        --dest=org.freedesktop.DBus \
        /org/freedesktop/DBus \
        org.freedesktop.DBus.ListNames | grep -i deepin
    
  2. 查看服务接口:

    dbus-send --session --print-reply \
        --dest=com.deepin.dde.lockFront \
        /com/deepin/dde/lockFront \
        org.freedesktop.DBus.Introspectable.Introspect
    
  3. 修改 screenlockdetector.cppconnectToDeepinDDE() 的服务列表

技术细节

为什么需要空路径监听?

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 等)

获取帮助

如果以上方法都不行,请提供以下信息:

  1. 系统信息:

    cat /etc/os-release
    echo "Desktop: $XDG_CURRENT_DESKTOP"
    echo "Session: $XDG_SESSION_TYPE"
    
  2. 会话信息:

    loginctl show-session $XDG_SESSION_ID
    
  3. 程序输出: 运行 ./run.sh 的完整输出

  4. 信号监听结果: 运行 ./test_lock_signals.sh 的输出

  5. 手动测试结果:

    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. 多重连接策略(提高兼容性)

大多数情况下,这些修复应该能解决问题。如果还有问题,使用提供的调试工具找出系统实际使用的信号机制。