#include "screenlockdetector.h" #ifdef Q_OS_MAC #include "screenlockdetector_mac.h" #endif #ifdef Q_OS_LINUX #include #include #include #include #endif ScreenLockDetector::ScreenLockDetector(QObject *parent) : QObject(parent) , m_isLocked(false) #ifdef Q_OS_LINUX , m_gnomeInterface(nullptr) , m_loginInterface(nullptr) , m_deepinInterface(nullptr) , m_gnomeConnected(false) , m_loginConnected(false) , m_deepinConnected(false) #endif #ifdef Q_OS_MAC , m_macDetector(nullptr) #endif { } ScreenLockDetector::~ScreenLockDetector() { #ifdef Q_OS_LINUX if (m_gnomeInterface) { delete m_gnomeInterface; m_gnomeInterface = nullptr; } if (m_loginInterface) { delete m_loginInterface; m_loginInterface = nullptr; } if (m_deepinInterface) { delete m_deepinInterface; m_deepinInterface = nullptr; } #endif #ifdef Q_OS_MAC if (m_macDetector) { delete m_macDetector; m_macDetector = nullptr; } #endif } bool ScreenLockDetector::isScreenLocked() const { return m_isLocked; } bool ScreenLockDetector::initialize() { #ifdef Q_OS_MAC qDebug() << "================================================="; qDebug() << "Initializing ScreenLockDetector for macOS..."; qDebug() << "================================================="; // 创建 macOS 特定的检测器 m_macDetector = new ScreenLockDetectorMac(this); // 连接信号 connect(m_macDetector, &ScreenLockDetectorMac::screenLocked, this, &ScreenLockDetector::screenLocked); connect(m_macDetector, &ScreenLockDetectorMac::screenUnlocked, this, &ScreenLockDetector::screenUnlocked); connect(m_macDetector, &ScreenLockDetectorMac::lockStateChanged, this, [this](bool locked) { m_isLocked = locked; emit lockStateChanged(locked); }); bool success = m_macDetector->initialize(); if (success) { qDebug() << "================================================="; qDebug() << "ScreenLockDetector initialized successfully on macOS"; qDebug() << "================================================="; } else { qWarning() << "Failed to initialize ScreenLockDetector on macOS"; } return success; #elif defined(Q_OS_LINUX) qDebug() << "================================================="; qDebug() << "Initializing ScreenLockDetector for Linux..."; qDebug() << "================================================="; // 尝试连接到不同的DBus接口 bool deepinOk = connectToDeepinDDE(); bool gnomeOk = connectToGnomeScreenSaver(); bool loginOk = connectToUkuiManager(); if (!deepinOk && !gnomeOk && !loginOk) { qWarning() << "Failed to connect to any screen lock detection service"; qWarning() << "Make sure you are running on a supported Linux desktop environment"; return false; } // 查询当前锁屏状态 queryCurrentLockState(); qDebug() << "================================================="; qDebug() << "ScreenLockDetector initialized successfully on Linux"; qDebug() << "Deepin DDE connected:" << m_deepinConnected; qDebug() << "GNOME ScreenSaver connected:" << m_gnomeConnected; qDebug() << "Login Manager connected:" << m_loginConnected; qDebug() << "================================================="; return true; #else qWarning() << "ScreenLockDetector: Unsupported platform"; return false; #endif } void ScreenLockDetector::setLockState(bool locked) { if (m_isLocked != locked) { m_isLocked = locked; qDebug() << "##################################################"; qDebug() << "## Screen lock state changed:" << (locked ? "LOCKED" : "UNLOCKED"); qDebug() << "##################################################"; emit lockStateChanged(locked); if (locked) { emit screenLocked(); } else { emit screenUnlocked(); } } } #ifdef Q_OS_LINUX bool ScreenLockDetector::connectToGnomeScreenSaver() { qDebug() << "\n--- Connecting to GNOME ScreenSaver ---"; // 连接到GNOME屏幕保护程序的DBus接口 m_gnomeInterface = new QDBusInterface( "org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", QDBusConnection::sessionBus(), this ); if (!m_gnomeInterface->isValid()) { qDebug() << "GNOME ScreenSaver interface not available:" << m_gnomeInterface->lastError().message(); delete m_gnomeInterface; m_gnomeInterface = nullptr; return false; } qDebug() << "GNOME ScreenSaver interface is valid"; // 连接ActiveChanged信号 bool connected = QDBusConnection::sessionBus().connect( "org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "ActiveChanged", this, SLOT(onScreenSaverActiveChanged(bool)) ); qDebug() << "GNOME ActiveChanged signal connected:" << connected; if (!connected) { qWarning() << "Failed to connect to GNOME ScreenSaver ActiveChanged signal"; delete m_gnomeInterface; m_gnomeInterface = nullptr; return false; } m_gnomeConnected = true; qDebug() << "Successfully connected to GNOME ScreenSaver"; return true; } bool ScreenLockDetector::connectToUkuiManager() { qDebug() << "\n--- Connecting to ukui ScreenSaver ---"; QString sessionPath = "/"; m_loginInterface = new QDBusInterface( "org.ukui.ScreenSaver", sessionPath, "org.ukui.ScreenSaver", QDBusConnection::sessionBus(), this ); if (m_loginInterface->isValid()) { qDebug() << "ukui ScreenSaver interface is valid for session:" << sessionPath; // 连接Lock和Unlock信号到特定会话 bool lockConnected = QDBusConnection::sessionBus().connect( "org.ukui.ScreenSaver", sessionPath, "org.ukui.ScreenSaver", "lock", this, SLOT(onSessionLocked()) ); bool unlockConnected = QDBusConnection::sessionBus().connect( "org.ukui.ScreenSaver", sessionPath, "org.ukui.ScreenSaver", "unlock", this, SLOT(onSessionUnlocked()) ); qDebug() << "Session Lock signal connected:" << lockConnected; qDebug() << "Session Unlock signal connected:" << unlockConnected; if (lockConnected || unlockConnected) { m_loginConnected = true; qDebug() << "Successfully connected to Login Manager via session path"; return true; } } qWarning() << "Failed to connect to Login Manager signals"; delete m_loginInterface; m_loginInterface = nullptr; return false; } QString ScreenLockDetector::getCurrentSessionPath() { // 尝试从环境变量获取 QString xdgSessionId = qgetenv("XDG_SESSION_ID"); if (!xdgSessionId.isEmpty()) { QString path = QString("/org/freedesktop/login1/session/%1").arg(xdgSessionId); qDebug() << "Session path from XDG_SESSION_ID:" << path; return path; } // 尝试通过DBus调用获取当前会话 QDBusInterface managerIface( "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus() ); if (managerIface.isValid()) { // 获取当前用户的会话列表 QDBusReply reply = managerIface.call("GetSessionByPID", (quint32)QCoreApplication::applicationPid()); if (reply.isValid()) { QString path = reply.value().path(); qDebug() << "Session path from GetSessionByPID:" << path; return path; } else { qDebug() << "GetSessionByPID failed:" << reply.error().message(); } } return QString(); } bool ScreenLockDetector::connectToDeepinDDE() { qDebug() << "\n--- Connecting to Deepin DDE ---"; // 可能的服务配置列表 struct DeepinService { QString service; QString path; QString interface; QString lockSignal; QString unlockSignal; }; QList services = { // Deepin 20/23 主要接口 {"com.deepin.dde.lockFront", "/com/deepin/dde/lockFront", "com.deepin.dde.lockFront", "Visible", "Visible"}, // 备用接口 {"com.deepin.daemon.ScreenSaver", "/com/deepin/daemon/ScreenSaver", "com.deepin.daemon.ScreenSaver", "ActiveChanged", "ActiveChanged"}, }; for (const auto& svc : services) { qDebug() << "Trying Deepin service:" << svc.service; m_deepinInterface = new QDBusInterface( svc.service, svc.path, svc.interface, QDBusConnection::sessionBus(), this ); if (!m_deepinInterface->isValid()) { qDebug() << " Interface not available:" << m_deepinInterface->lastError().message(); delete m_deepinInterface; m_deepinInterface = nullptr; continue; } qDebug() << " Interface is valid, connecting signals..."; // 尝试连接锁屏信号 bool visibleConnected = QDBusConnection::sessionBus().connect( svc.service, svc.path, svc.interface, svc.lockSignal, this, SLOT(onLockFrontVisible(bool)) ); qDebug() << " Visible signal (" << svc.lockSignal << ") connected:" << visibleConnected; if (visibleConnected) { m_deepinConnected = true; qDebug() << "Successfully connected to Deepin DDE via" << svc.service; qDebug() << "Listening for signals:" << svc.lockSignal; return true; } qWarning() << " Failed to connect signals for" << svc.service; delete m_deepinInterface; m_deepinInterface = nullptr; } qWarning() << "Failed to connect to any Deepin DDE lock service"; return false; } void ScreenLockDetector::queryCurrentLockState() { qDebug() << "\n--- Querying current lock state ---"; // 尝试从Deepin DDE查询当前状态 if (m_deepinInterface && m_deepinInterface->isValid()) { qDebug() << "Querying Deepin DDE lock state..."; QStringList possibleMethods = {"GetLocked", "IsLocked", "GetActive", "GetSessionLocked"}; for (const QString& method : possibleMethods) { QDBusReply reply = m_deepinInterface->call(method); if (reply.isValid()) { bool locked = reply.value(); qDebug() << " Method" << method << "returned:" << (locked ? "LOCKED" : "UNLOCKED"); setLockState(locked); return; } } qDebug() << " No query method worked, waiting for signals"; } // 尝试从GNOME屏幕保护程序查询当前状态 if (m_gnomeInterface && m_gnomeInterface->isValid()) { qDebug() << "Querying GNOME ScreenSaver state..."; QDBusReply reply = m_gnomeInterface->call("GetActive"); if (reply.isValid()) { bool active = reply.value(); qDebug() << " Current GNOME ScreenSaver state:" << (active ? "ACTIVE/LOCKED" : "INACTIVE/UNLOCKED"); setLockState(active); return; } } // 尝试从登录管理器查询锁定状态 if (m_loginInterface && m_loginInterface->isValid()) { qDebug() << "Querying Login Manager lock state..."; // 尝试读取 LockedHint 属性 QDBusMessage msg = QDBusMessage::createMethodCall( "org.freedesktop.login1", m_loginInterface->path(), "org.freedesktop.DBus.Properties", "Get" ); msg << "org.freedesktop.login1.Session" << "LockedHint"; QDBusReply reply = QDBusConnection::systemBus().call(msg); if (reply.isValid()) { bool locked = reply.value().toBool(); qDebug() << " LockedHint property:" << (locked ? "LOCKED" : "UNLOCKED"); setLockState(locked); return; } else { qDebug() << " Could not read LockedHint:" << reply.error().message(); } } qDebug() << "Could not query initial lock state, will detect on next lock/unlock event"; } void ScreenLockDetector::onScreenSaverActiveChanged(bool active) { qDebug() << "##################################################"; qDebug() << "## GNOME ScreenSaver ActiveChanged signal received"; qDebug() << "## New state:" << (active ? "ACTIVE (LOCKED)" : "INACTIVE (UNLOCKED)"); qDebug() << "##################################################"; setLockState(active); } void ScreenLockDetector::onLockFrontVisible(bool visible) { qDebug() << "##################################################"; qDebug() << "## DEEPIN LockFront Visible signal received"; qDebug() << "## New state:" << (visible ? "ACTIVE (LOCKED)" : "INACTIVE (UNLOCKED)"); qDebug() << "##################################################"; setLockState(visible); } void ScreenLockDetector::onSessionLocked() { qDebug() << "##################################################"; qDebug() << "## LOCK SIGNAL RECEIVED"; qDebug() << "## Screen is now LOCKED"; qDebug() << "## Sender:" << sender(); // 获取信号发送者的详细信息 QDBusMessage msg = QDBusContext::message(); if (msg.type() != QDBusMessage::InvalidMessage) { qDebug() << "## DBus Message Details:"; qDebug() << "## Service:" << msg.service(); qDebug() << "## Path:" << msg.path(); qDebug() << "## Interface:" << msg.interface(); qDebug() << "## Member:" << msg.member(); } qDebug() << "##################################################"; setLockState(true); } void ScreenLockDetector::onSessionUnlocked() { qDebug() << "##################################################"; qDebug() << "## UNLOCK SIGNAL RECEIVED"; qDebug() << "## Screen is now UNLOCKED"; qDebug() << "## Sender:" << sender(); // 获取信号发送者的详细信息 QDBusMessage msg = QDBusContext::message(); if (msg.type() != QDBusMessage::InvalidMessage) { qDebug() << "## DBus Message Details:"; qDebug() << "## Service:" << msg.service(); qDebug() << "## Path:" << msg.path(); qDebug() << "## Interface:" << msg.interface(); qDebug() << "## Member:" << msg.member(); } qDebug() << "##################################################"; setLockState(false); } #endif // Q_OS_LINUX