From a5e30c799a2a5f551abdb1e2f81cb47938f2ba0e Mon Sep 17 00:00:00 2001 From: JiDe Zhang Date: Tue, 2 Jun 2026 19:21:02 +0800 Subject: [PATCH] refactor(ddm): switch treeland IPC to Qt Remote Objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the greeter IPC bridge with Qt Remote Objects endpoints. Use DDMRemote and TreelandRemote as cross-process call contracts. 将 greeter IPC 桥接改为 Qt Remote Objects 端点。 使用 DDMRemote 和 TreelandRemote 作为跨进程调用契约。 Log: 切换 Treeland 与 DDM 的 IPC 到 Qt Remote Objects Influence: 规范远程对象和 socket 命名,影响 DDM 与 Treeland 的登录/切换通信。 --- src/CMakeLists.txt | 7 + src/greeter/ddmremote.rep | 23 + src/greeter/greeterproxy.cpp | 465 ++++++------------ src/greeter/greeterproxy.h | 102 ++-- src/modules/ddm/CMakeLists.txt | 19 +- src/modules/ddm/ddminterfacev1.cpp | 134 ----- src/modules/ddm/ddmremoteobjectv1.cpp | 177 +++++++ .../{ddminterfacev1.h => ddmremoteobjectv1.h} | 21 +- src/modules/ddm/treelandremote.rep | 9 + .../foreigntoplevelhandlev1.h | 2 +- src/modules/resource/treelandremotesource.cpp | 22 +- src/modules/resource/treelandremotesource.h | 6 +- src/plugins/lockscreen/qml/UserInput.qml | 5 +- src/seat/helper.cpp | 58 +-- src/seat/helper.h | 15 +- 15 files changed, 449 insertions(+), 616 deletions(-) create mode 100644 src/greeter/ddmremote.rep delete mode 100644 src/modules/ddm/ddminterfacev1.cpp create mode 100644 src/modules/ddm/ddmremoteobjectv1.cpp rename src/modules/ddm/{ddminterfacev1.h => ddmremoteobjectv1.h} (53%) create mode 100644 src/modules/ddm/treelandremote.rep diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 82a991581..d98661c74 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -148,6 +148,7 @@ qt_add_qml_module(libtreeland effects/tsgradiusimagenode.h $<$>,$>:core/lockscreen.h> $<$>,$>:core/lockscreen.cpp> + $<$>:greeter/ddmremote.rep> $<$>:greeter/greeterproxy.cpp> $<$>:greeter/greeterproxy.h> $<$>:greeter/sessionmodel.cpp> @@ -266,6 +267,12 @@ qt_add_qml_module(libtreeland ${PROJECT_BINARY_DIR}/qt/qml/Treeland ) +if (NOT DISABLE_DDM) + qt_add_repc_replicas(libtreeland + ${CMAKE_CURRENT_SOURCE_DIR}/greeter/ddmremote.rep + ) +endif() + qt_add_repc_sources(libtreeland modules/resource/treelandwindowtree.rep ) diff --git a/src/greeter/ddmremote.rep b/src/greeter/ddmremote.rep new file mode 100644 index 000000000..4c7e10300 --- /dev/null +++ b/src/greeter/ddmremote.rep @@ -0,0 +1,23 @@ +// Copyright (C) 2026 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +class DDMRemote { + PROP(QString hostName SOURCEONLYSETTER) + PROP(bool canPowerOff=false SOURCEONLYSETTER) + PROP(bool canReboot=false SOURCEONLYSETTER) + PROP(bool canSuspend=false SOURCEONLYSETTER) + PROP(bool canHibernate=false SOURCEONLYSETTER) + PROP(bool canHybridSleep=false SOURCEONLYSETTER) + SIGNAL(loginFailed(QString user)) + SIGNAL(informationMessage(QString message)) + SIGNAL(userSessionAdded(QString user, int sessionId)) + SIGNAL(userSessionRemoved(QString user, int sessionId)) + SLOT(bool connectGreeter()) + SLOT(bool login(QString user, QString password, int sessionType, QString sessionFile)) + SLOT(bool logout(int id)) + SLOT(bool powerOff()) + SLOT(bool reboot()) + SLOT(bool suspend()) + SLOT(bool hibernate()) + SLOT(bool hybridSleep()) +}; diff --git a/src/greeter/greeterproxy.cpp b/src/greeter/greeterproxy.cpp index 44915c9d2..104ced69f 100644 --- a/src/greeter/greeterproxy.cpp +++ b/src/greeter/greeterproxy.cpp @@ -12,20 +12,16 @@ #include "core/lockscreen.h" // DDM -#include -#include -#include -#include +#include // Qt #include #include -#include -#include -#include #include #include -#include +#include +#include +#include #include // Waylib @@ -33,11 +29,14 @@ // System #include -#include #include using namespace DDM; +namespace { +constexpr auto ddmRemoteSocketName = "org.deepin.dde.ddm.qro"; +} + ///////////////////// // Local Functions // ///////////////////// @@ -95,30 +94,9 @@ GreeterProxy::GreeterProxy(QObject *parent) // connect signals connect(m_socket, &QLocalSocket::connected, this, &GreeterProxy::connected); connect(m_socket, &QLocalSocket::disconnected, this, &GreeterProxy::disconnected); - connect(m_socket, &QLocalSocket::readyRead, this, &GreeterProxy::readyRead); connect(m_socket, &QLocalSocket::errorOccurred, this, &GreeterProxy::error); - auto conn = QDBusConnection::systemBus(); - conn.connect(Logind::serviceName(), - Logind::managerPath(), - Logind::managerIfaceName(), - "SessionNew", - this, - SLOT(onSessionNew(QString, QDBusObjectPath))); - conn.connect(Logind::serviceName(), - Logind::managerPath(), - Logind::managerIfaceName(), - "SessionRemoved", - this, - SLOT(onSessionRemoved(QString, QDBusObjectPath))); - conn.connect("org.deepin.DisplayManager", - "/org/deepin/DisplayManager", - "org.deepin.DisplayManager", - "AuthInfoChanged", - this, - SLOT(updateAuthSocket())); - - updateAuthSocket(); + connectToDDM(); } GreeterProxy::~GreeterProxy() { } @@ -159,33 +137,49 @@ void GreeterProxy::setLock(bool isLocked) void GreeterProxy::powerOff() { - SocketWriter(m_socket) << quint32(GreeterMessages::PowerOff); + if (isConnected()) + watchRemoteCall("powerOff", m_remoteReplica->powerOff()); } void GreeterProxy::reboot() { - SocketWriter(m_socket) << quint32(GreeterMessages::Reboot); + if (isConnected()) + watchRemoteCall("reboot", m_remoteReplica->reboot()); } void GreeterProxy::suspend() { - SocketWriter(m_socket) << quint32(GreeterMessages::Suspend); + if (isConnected()) + watchRemoteCall("suspend", m_remoteReplica->suspend()); } void GreeterProxy::hibernate() { - SocketWriter(m_socket) << quint32(GreeterMessages::Hibernate); + if (isConnected()) + watchRemoteCall("hibernate", m_remoteReplica->hibernate()); } void GreeterProxy::hybridSleep() { - SocketWriter(m_socket) << quint32(GreeterMessages::HybridSleep); + if (isConnected()) + watchRemoteCall("hybridSleep", m_remoteReplica->hybridSleep()); } void GreeterProxy::login(const QString &user, const QString &password, const int sessionIndex) { - if (!m_socket->isValid()) { - qCDebug(treelandGreeter) << "Socket is not valid. Local password check."; + auto userInfo = userModel()->getUser(user); + if (!isConnected() || !userInfo) { + qCDebug(treelandGreeter) << "Socket is not valid or user not found. Local password check."; + if (localValidation(user, password)) { + setLock(false); + } else { + Q_EMIT failedAttemptsChanged(++m_failedAttempts); + } + return; + } + + if (userInfo->loggedIn()) { + qCInfo(treelandGreeter) << "Unlocking user" << user; if (localValidation(user, password)) { setLock(false); } else { @@ -202,34 +196,20 @@ void GreeterProxy::login(const QString &user, const QString &password, const int static_cast(sessionModel()->data(index, SessionModel::TypeRole).toInt()); QString name = sessionModel()->data(index, SessionModel::FileRole).toString(); qCInfo(treelandGreeter) << "Logging user" << user << "in with" << type << "session" << name; - DDM::Session session(type, name); - SocketWriter(m_socket) << quint32(GreeterMessages::Login) << user << password << session; + watchRemoteCall("login", m_remoteReplica->login(user, password, type, name)); } -void GreeterProxy::unlock(const QString &user, const QString &password) +void GreeterProxy::logout() { - if (!m_socket->isValid()) { - qCDebug(treelandGreeter) << "Socket is not valid. Local password check."; - if (localValidation(user, password)) { - setLock(false); - } else { - Q_EMIT failedAttemptsChanged(++m_failedAttempts); - } + auto session = Helper::instance()->sessionManager()->activeSession().lock(); + if (!session) { + qCWarning(treelandGreeter) << "Trying to logout when no user session active."; return; } - auto userInfo = userModel()->get(user); - if (userInfo.isValid()) { - qCInfo(treelandGreeter) << "Unlocking user" << user; - SocketWriter(m_socket) << quint32(GreeterMessages::Unlock) << user << password; - } -} - -void GreeterProxy::logout() -{ - auto session = Helper::instance()->sessionManager()->activeSession().lock(); qCInfo(treelandGreeter) << "Logging user" << session->username() << "out with session id" << session->id(); - SocketWriter(m_socket) << quint32(GreeterMessages::Logout) << session->id(); + if (isConnected()) + watchRemoteCall("logout", m_remoteReplica->logout(session->id())); } void GreeterProxy::lock() @@ -241,91 +221,43 @@ void GreeterProxy::lock() return; } qCInfo(treelandGreeter) << "Locking user" << session->username() << "with session id" << session->id(); - SocketWriter(m_socket) << quint32(GreeterMessages::Lock) << session->id(); + setLock(true); } -////////////////////////////// -// Logind session listeners // -////////////////////////////// +//////////////////////////// +// DDM session listeners // +//////////////////////////// -void GreeterProxy::onSessionNew(const QString &id, [[maybe_unused]] const QDBusObjectPath &path) +void GreeterProxy::addUserSession(const QString &user, int sessionId) { - QByteArray sessionBa = id.toLocal8Bit(); - const char *session = sessionBa.constData(); - char *username = nullptr; - char *service = nullptr; - auto guard = qScopeGuard([&]() { - if (username) - free(username); - if (service) - free(service); - }); - if (sd_session_get_username(session, &username) < 0) { - qCWarning(treelandGreeter) << "sd_session_get_username() failed for session id:" << id; - return; - } - if (sd_session_get_service(session, &service) < 0) { - qCWarning(treelandGreeter) << "sd_session_get_service() failed for session id:" << id; + qCInfo(treelandGreeter) << "User session added: id=" << sessionId << ", user=" << user; + auto userPtr = userModel()->getUser(user); + if (!userPtr) { + qCWarning(treelandGreeter) << "User" << user << "logged in but not found"; return; } - if (strcmp(service, "ddm") == 0) { - QString user = QString::fromLocal8Bit(username); - qCInfo(treelandGreeter) << "New session added: id=" << id << ", user=" << user; - userModel()->updateUserLoginState(user, true); - // userLoggedIn signal is connected with Helper::updateActiveUserSession - Q_EMIT userModel()->userLoggedIn(user, id.toInt()); - - // Connect to Lock/Unlock signals - auto conn = QDBusConnection::systemBus(); - conn.connect(Logind::serviceName(), - path.path(), - Logind::sessionIfaceName(), - "Lock", - this, - SLOT(onSessionLock())); - conn.connect(Logind::serviceName(), - path.path(), - Logind::sessionIfaceName(), - "Unlock", - this, - SLOT(onSessionUnlock())); - - if (userModel()->currentUserName() == user) - setLock(false); - if (!m_hasActiveSession) { - m_hasActiveSession = true; - Q_EMIT hasActiveSessionChanged(true); - } + userModel()->updateUserLoginState(user, true); + Q_EMIT userModel()->userLoggedIn(user, sessionId); + + if (userModel()->currentUserName() == user) + setLock(false); + if (!m_hasActiveSession) { + m_hasActiveSession = true; + Q_EMIT hasActiveSessionChanged(true); } } -void GreeterProxy::onSessionRemoved(const QString &id, [[maybe_unused]] const QDBusObjectPath &path) +void GreeterProxy::removeUserSession(const QString &user, int sessionId) { - // Disconnect from Lock/Unlock signals, if any - auto conn = QDBusConnection::systemBus(); - conn.disconnect(Logind::serviceName(), - path.path(), - Logind::sessionIfaceName(), - "Lock", - this, - SLOT(onSessionLock())); - conn.disconnect(Logind::serviceName(), - path.path(), - Logind::sessionIfaceName(), - "Unlock", - this, - SLOT(onSessionUnlock())); - - auto session = Helper::instance()->sessionManager()->sessionForId(id.toInt()); + qCInfo(treelandGreeter) << "User session removed: id=" << sessionId << ", user=" << user; + auto session = Helper::instance()->sessionManager()->sessionForId(sessionId); if (session) { - QString username = session->username(); - qCInfo(treelandGreeter) << "Session removed: id=" << id << ", user=" << username; if (Helper::instance()->sessionManager()->activeSession().lock() == session) setLock(true); - userModel()->updateUserLoginState(username, false); Helper::instance()->sessionManager()->removeSession(session); } + userModel()->updateUserLoginState(user, false); if (m_hasActiveSession && Helper::instance()->sessionManager()->sessions().isEmpty()) { m_hasActiveSession = false; @@ -333,230 +265,123 @@ void GreeterProxy::onSessionRemoved(const QString &id, [[maybe_unused]] const QD } } -void GreeterProxy::onSessionLock() +/////////////////////// +// DDM Communication // +/////////////////////// + +QString GreeterProxy::hostName() const +{ + return m_remoteReplica ? m_remoteReplica->hostName() : QString(); +} + +bool GreeterProxy::canPowerOff() const { - const QString path = message().path(); - QThreadPool::globalInstance()->start([this, path] { - OrgFreedesktopLogin1SessionInterface session("org.freedesktop.login1", - path, - QDBusConnection::systemBus()); - int id = session.id().toInt(); - qCInfo(treelandGreeter) << "Lock signal received for session id:" << id; - auto activeSession = Helper::instance()->sessionManager()->activeSession().lock(); - if (!activeSession) - qCWarning(treelandGreeter) - << "Lock signal received for non-exist session id:" << id << ", ignore."; - else if (activeSession->id() != id) - qCWarning(treelandGreeter) - << "Lock signal received for non-active session id:" << id << ", ignore."; - else - QMetaObject::invokeMethod(this, [this] { - setLock(true); - }); - }); + return m_remoteReplica && m_remoteReplica->canPowerOff(); } -void GreeterProxy::onSessionUnlock() +bool GreeterProxy::canReboot() const { - const QString path = message().path(); - QThreadPool::globalInstance()->start([this, path] { - OrgFreedesktopLogin1SessionInterface session("org.freedesktop.login1", - path, - QDBusConnection::systemBus()); - int id = session.id().toInt(); - const QString username = session.name(); - qCInfo(treelandGreeter) << "Unlock signal received for session id:" << id; - auto activeSession = Helper::instance()->sessionManager()->activeSession().lock(); - if (!activeSession) { - qCWarning(treelandGreeter) - << "Unlock signal received for non-exist session id:" << id << ", ignore."; - } else if (activeSession->id() != id) { - qCWarning(treelandGreeter) - << "Unlock signal received for non-active session id:" << id << ", lock it back."; - QMetaObject::invokeMethod(this, [this, id] { - SocketWriter(m_socket) << quint32(GreeterMessages::Lock) << QString::number(id); - }); - } else { - QMetaObject::invokeMethod(this, [this] { - setLock(false); - }); - } - }); + return m_remoteReplica && m_remoteReplica->canReboot(); } -/////////////////////// -// DDM Communication // -/////////////////////// +bool GreeterProxy::canSuspend() const +{ + return m_remoteReplica && m_remoteReplica->canSuspend(); +} + +bool GreeterProxy::canHibernate() const +{ + return m_remoteReplica && m_remoteReplica->canHibernate(); +} + +bool GreeterProxy::canHybridSleep() const +{ + return m_remoteReplica && m_remoteReplica->canHybridSleep(); +} bool GreeterProxy::isConnected() const { - return m_socket->state() == QLocalSocket::ConnectedState; + return m_remoteReplica && m_remoteReplica->state() == QRemoteObjectReplica::Valid; } void GreeterProxy::connected() { qCInfo(treelandGreeter) << "Connected to the ddm"; - - SocketWriter(m_socket) - << quint32(GreeterMessages::Connect) - << Helper::instance()->sessionManager()->globalSession()->socket()->fullServerName(); + Q_EMIT socketConnected(); + + resetRemote(); + m_remoteNode.reset(new QRemoteObjectNode); + m_remoteNode->addClientSideConnection(m_socket); + m_remoteReplica.reset(m_remoteNode->acquire()); + + connect(m_remoteReplica.get(), &DDMRemoteReplica::hostNameChanged, this, &GreeterProxy::hostNameChanged); + connect(m_remoteReplica.get(), &DDMRemoteReplica::canPowerOffChanged, this, &GreeterProxy::canPowerOffChanged); + connect(m_remoteReplica.get(), &DDMRemoteReplica::canRebootChanged, this, &GreeterProxy::canRebootChanged); + connect(m_remoteReplica.get(), &DDMRemoteReplica::canSuspendChanged, this, &GreeterProxy::canSuspendChanged); + connect(m_remoteReplica.get(), &DDMRemoteReplica::canHibernateChanged, this, &GreeterProxy::canHibernateChanged); + connect(m_remoteReplica.get(), &DDMRemoteReplica::canHybridSleepChanged, this, &GreeterProxy::canHybridSleepChanged); + connect(m_remoteReplica.get(), &DDMRemoteReplica::informationMessage, this, &GreeterProxy::informationMessage); + connect(m_remoteReplica.get(), &DDMRemoteReplica::loginFailed, this, &GreeterProxy::onLoginFailed); + connect(m_remoteReplica.get(), &DDMRemoteReplica::userSessionAdded, this, &GreeterProxy::addUserSession); + connect(m_remoteReplica.get(), &DDMRemoteReplica::userSessionRemoved, this, &GreeterProxy::removeUserSession); + connect(m_remoteReplica.get(), &QRemoteObjectReplica::stateChanged, this, &GreeterProxy::remoteStateChanged); } void GreeterProxy::disconnected() { qCWarning(treelandGreeter) << "Disconnected from the ddm"; - + resetRemote(); Q_EMIT socketDisconnected(); } void GreeterProxy::error() { qCCritical(treelandGreeter) << "Socket error: " << m_socket->errorString(); + if (m_socket->state() == QLocalSocket::UnconnectedState) + QTimer::singleShot(1000, this, &GreeterProxy::connectToDDM); } -void GreeterProxy::readyRead() +void GreeterProxy::connectToDDM() { - // input stream - QDataStream input(m_socket); - - while (input.device()->bytesAvailable()) { - // read message - quint32 message; - input >> message; - - switch (DaemonMessages(message)) { - case DaemonMessages::Capabilities: { - // log message - qCDebug(treelandGreeter) << "Message received from daemon: Capabilities"; - - // read capabilities - quint32 capabilities; - input >> capabilities; - - // parse capabilities - m_canPowerOff = capabilities & Capability::PowerOff; - m_canReboot = capabilities & Capability::Reboot; - m_canSuspend = capabilities & Capability::Suspend; - m_canHibernate = capabilities & Capability::Hibernate; - m_canHybridSleep = capabilities & Capability::HybridSleep; - - // Q_EMIT signals - Q_EMIT canPowerOffChanged(m_canPowerOff); - Q_EMIT canRebootChanged(m_canReboot); - Q_EMIT canSuspendChanged(m_canSuspend); - Q_EMIT canHibernateChanged(m_canHibernate); - Q_EMIT canHybridSleepChanged(m_canHybridSleep); - } break; - case DaemonMessages::HostName: { - qCDebug(treelandGreeter) << "Message received from daemon: HostName"; - - // read host name - input >> m_hostName; - - // Q_EMIT signal - Q_EMIT hostNameChanged(m_hostName); - } break; - case DaemonMessages::LoginFailed: { - QString user; - input >> user; - - qCDebug(treelandGreeter) << "Message received from daemon: LoginFailed" << user; + if (m_socket->state() != QLocalSocket::UnconnectedState) + m_socket->abort(); - Q_EMIT failedAttemptsChanged(++m_failedAttempts); - } break; - case DaemonMessages::InformationMessage: { - QString message; - input >> message; - - qCDebug(treelandGreeter) << "Information Message received from daemon: " << message; - Q_EMIT informationMessage(message); - } break; - case DaemonMessages::SwitchToGreeter: { - qCInfo(treelandGreeter) << "switch to greeter"; - lock(); - } break; - case DaemonMessages::UserActivateMessage: { - QString user; - int sessionId; - input >> user >> sessionId; - - // NOTE: maybe DDM will active dde user. - if (!userModel()->getUser(user)) { - qCInfo(treelandGreeter) << "activate user, but switch to greeter"; - lock(); - break; - } - - userModel()->setCurrentUserName(user); - - qCInfo(treelandGreeter) << "activate successfully: " << user << ", XDG_SESSION_ID: " << sessionId; - } break; - case DaemonMessages::UserLoggedIn: { - QString user; - int sessionId; - input >> user >> sessionId; - - // This will happen after a crash recovery of treeland - qCInfo(treelandGreeter) << "User " << user << " is already logged in"; - auto userPtr = userModel()->getUser(user); - if (userPtr) { - userModel()->updateUserLoginState(user, true); - Q_EMIT userModel()->userLoggedIn(user, sessionId); - QThreadPool::globalInstance()->start([this, sessionId] { - // Connect to Lock/Unlock signals - auto conn = QDBusConnection::systemBus(); - OrgFreedesktopLogin1ManagerInterface manager("org.freedesktop.login1", - Logind::managerPath(), - conn); - auto reply = manager.GetSession(QString::number(sessionId)); - reply.waitForFinished(); - if (!reply.isValid()) { - qCWarning(treelandGreeter) << "Failed to get session path for session id:" << sessionId << ", error:" << reply.error().message(); - return; - } - auto path = reply.value(); - conn.connect(Logind::serviceName(), - path.path(), - Logind::sessionIfaceName(), - "Lock", - this, - SLOT(onSessionLock())); - conn.connect(Logind::serviceName(), - path.path(), - Logind::sessionIfaceName(), - "Unlock", - this, - SLOT(onSessionUnlock())); - }); - } else { - qCWarning(treelandGreeter) << "User " << user << " logged in but not found"; - } - } break; - default: { - qCWarning(treelandGreeter) << "Unknown message received from daemon." << message; - } - } - } + m_socket->connectToServer(QString::fromLatin1(ddmRemoteSocketName)); } -void GreeterProxy::updateAuthSocket() +void GreeterProxy::onLoginFailed(const QString &user) { - QThreadPool::globalInstance()->start([this]() { - QDBusInterface manager("org.deepin.DisplayManager", - "/org/deepin/DisplayManager", - "org.deepin.DisplayManager", - QDBusConnection::systemBus()); - QDBusReply reply = manager.call("AuthInfo"); - if (!reply.isValid()) { - qCWarning(treelandGreeter) << "Failed to get auth info from display manager:" << reply.error().message(); - return; - } - const QString &socket = reply.value(); - QMetaObject::invokeMethod(this, [this, socket] { - if (m_socket->state() == QLocalSocket::ConnectedState) - m_socket->disconnectFromServer(); + qCDebug(treelandGreeter) << "Message received from daemon: LoginFailed" << user; + Q_EMIT failedAttemptsChanged(++m_failedAttempts); +} - m_socket->connectToServer(socket); - }); +void GreeterProxy::remoteStateChanged(QRemoteObjectReplica::State state, QRemoteObjectReplica::State oldState) +{ + qCInfo(treelandGreeter) << "Greeter remote state changed from" << oldState << "to" << state; + if (state != QRemoteObjectReplica::Valid) + return; + + Q_EMIT hostNameChanged(hostName()); + Q_EMIT canPowerOffChanged(canPowerOff()); + Q_EMIT canRebootChanged(canReboot()); + Q_EMIT canSuspendChanged(canSuspend()); + Q_EMIT canHibernateChanged(canHibernate()); + Q_EMIT canHybridSleepChanged(canHybridSleep()); + watchRemoteCall("connectGreeter", m_remoteReplica->connectGreeter()); +} + +void GreeterProxy::watchRemoteCall(const char *operation, const QRemoteObjectPendingCall &call) +{ + auto *watcher = new QRemoteObjectPendingCallWatcher(call, this); + connect(watcher, &QRemoteObjectPendingCallWatcher::finished, this, [operation](QRemoteObjectPendingCallWatcher *watcher) { + if (watcher->error() != QRemoteObjectPendingCall::NoError) + qCWarning(treelandGreeter) << "DDM remote call failed:" << operation << watcher->error(); + watcher->deleteLater(); }); } + +void GreeterProxy::resetRemote() +{ + m_remoteReplica.reset(); + m_remoteNode.reset(); +} diff --git a/src/greeter/greeterproxy.h b/src/greeter/greeterproxy.h index e628e0a51..1737d294d 100644 --- a/src/greeter/greeterproxy.h +++ b/src/greeter/greeterproxy.h @@ -3,18 +3,20 @@ #pragma once -#include "QDBusContext" -#include #include #include +#include +#include + +#include class QLocalSocket; +class QRemoteObjectNode; +class DDMRemoteReplica; class LockScreen; -class GreeterProxy - : public QObject - , protected QDBusContext +class GreeterProxy : public QObject { Q_OBJECT Q_DISABLE_COPY(GreeterProxy) @@ -51,37 +53,37 @@ class GreeterProxy * @brief Get the host name * @return Host name */ - inline const QString &hostName() const { return m_hostName; }; + QString hostName() const; /** * @brief Get the power off capability * @return true if can power off */ - inline bool canPowerOff() const { return m_canPowerOff; }; + bool canPowerOff() const; /** * @brief Get the reboot capability * @return true if can reboot */ - inline bool canReboot() const { return m_canReboot; }; + bool canReboot() const; /** * @brief Get the suspend capability * @return true if can suspend */ - inline bool canSuspend() const { return m_canSuspend; }; + bool canSuspend() const; /** * @brief Get the hibernate capability * @return true if can hibernate */ - inline bool canHibernate() const { return m_canHibernate; }; + bool canHibernate() const; /** * @brief Get the hybrid sleep capability * @return true if can hybrid sleep */ - inline bool canHybridSleep() const { return m_canHybridSleep; }; + bool canHybridSleep() const; /** * @brief Get the greeter's lock state @@ -136,6 +138,12 @@ class GreeterProxy */ void setShowShutdownView(bool show); + /** + * @brief Set the local lock state without sending a request to DDM. + * @param isLocked true to show lockscreen, false to hide it + */ + void setLock(bool isLocked); + //////////////////// // Public methods // //////////////////// @@ -178,9 +186,8 @@ public Q_SLOTS: /** @brief Login given user with given password for given desktop session. * This function will call DDM to perform the login. * - * Listen to org.freedesktop.login1.Manager.SessionNew signal to - * detect if new sessions successfully logged in, and listen to - * failedAttempts property to detect failed login attempts. + * Listen to user session signals from DDM to detect session changes, + * and listen to failedAttempts property to detect failed login attempts. * * @param user Username * @param password Password @@ -191,28 +198,15 @@ public Q_SLOTS: /** @brief Lock the current active session. * This function will call DDM to perform the lock. * - * Listen to org.freedesktop.login1.Session.Lock signal to detect - * if the session is successfully locked. + * Show the lockscreen locally (Treeland self-manages lock state). */ void lock(); - /** @brief Unlock given user with given password. - * This function will call DDM to perform the unlock. - * - * Listen to org.freedesktop.login1.Session.Unlock signal to - * detect if the session is successfully unlocked, and listen to - * failedAttempts property to detect failed unlock attempts. - * - * @param user Username - * @param password Password - */ - void unlock(const QString &user, const QString &password); - /** @brief Logout the current active session. * This function will call DDM to perform the logout. * - * Listen to org.freedesktop.login1.Manager.SessionRemoved signal to - * detect if the session is successfully logged out. + * Listen to userSessionRemoved from DDM to detect if the session is + * successfully logged out. */ void logout(); @@ -224,30 +218,14 @@ private Q_SLOTS: void connected(); void disconnected(); - void readyRead(); void error(); - ////////////////////////////// - // Logind session listeners // - ////////////////////////////// - - /** @brief Listener for org.freederktop.login1.Manager.SessionNew */ - void onSessionNew(const QString &id, const QDBusObjectPath &session); - - /** @brief Listener for org.freederktop.login1.Manager.SessionRemoved */ - void onSessionRemoved(const QString &id, const QDBusObjectPath &session); - - /** @brief Listener for org.freederktop.login1.Session.Lock */ - void onSessionLock(); - - /** @brief Listener for org.freederktop.login1.Session.Unlock */ - void onSessionUnlock(); - Q_SIGNALS: void informationMessage(const QString &message); void switchUser(); + void socketConnected(); void socketDisconnected(); ///////////////////////////// @@ -293,35 +271,23 @@ private Q_SLOTS: // Private methods // ///////////////////// - /** - * @brief Set the lock state - * This is the internal method to set the lock state (lockscreen - * visibility, etc.) directly without calling DDM and - * communicating with systemd-logind. - * - * @param isLocked true to set locked, false to set unlocked - */ - void setLock(bool isLocked); - - /** - * @brief Update the DDM communication socket - */ - void updateAuthSocket(); + void connectToDDM(); + void resetRemote(); + void onLoginFailed(const QString &user); + void addUserSession(const QString &user, int sessionId); + void removeUserSession(const QString &user, int sessionId); + void remoteStateChanged(QRemoteObjectReplica::State state, QRemoteObjectReplica::State oldState); + void watchRemoteCall(const char *operation, const QRemoteObjectPendingCall &call); ///////////////////// // Property values // ///////////////////// QLocalSocket *m_socket{ nullptr }; + std::unique_ptr m_remoteNode; + std::unique_ptr m_remoteReplica; LockScreen *m_lockScreen{ nullptr }; - QString m_hostName{}; - - bool m_canPowerOff { false }; - bool m_canReboot { false }; - bool m_canSuspend { false }; - bool m_canHibernate { false }; - bool m_canHybridSleep { false }; bool m_isLocked { false }; int m_failedAttempts { 0 }; diff --git a/src/modules/ddm/CMakeLists.txt b/src/modules/ddm/CMakeLists.txt index 769d803fa..6f39658c1 100644 --- a/src/modules/ddm/CMakeLists.txt +++ b/src/modules/ddm/CMakeLists.txt @@ -1,17 +1,20 @@ -find_package(TreelandProtocols REQUIRED) - -local_qtwayland_server_protocol_treeland(libtreeland - PROTOCOL ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-ddm-v1.xml - BASENAME treeland-ddm-v1 +add_library(treelandremote_qro OBJECT) +set_target_properties(treelandremote_qro PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_link_libraries(treelandremote_qro PRIVATE Qt6::RemoteObjects) +qt_add_repc_sources(treelandremote_qro + ${CMAKE_CURRENT_SOURCE_DIR}/treelandremote.rep ) +target_link_libraries(libtreeland PRIVATE treelandremote_qro) +target_include_directories(libtreeland PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +set_source_files_properties(${CMAKE_SOURCE_DIR}/src/modules/ddm/ddmremoteobjectv1.cpp PROPERTIES SKIP_AUTOMOC ON) + impl_treeland( NAME module_ddm SOURCE - ${CMAKE_SOURCE_DIR}/src/modules/ddm/ddminterfacev1.h - ${CMAKE_SOURCE_DIR}/src/modules/ddm/ddminterfacev1.cpp - ${CMAKE_BINARY_DIR}/src/modules/ddm/wayland-treeland-ddm-v1-server-protocol.c + ${CMAKE_SOURCE_DIR}/src/modules/ddm/ddmremoteobjectv1.cpp + ${CMAKE_SOURCE_DIR}/src/modules/ddm/ddmremoteobjectv1.h INCLUDE $ ) diff --git a/src/modules/ddm/ddminterfacev1.cpp b/src/modules/ddm/ddminterfacev1.cpp deleted file mode 100644 index 47ab508cd..000000000 --- a/src/modules/ddm/ddminterfacev1.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (C) 2025-2026 UnionTech Software Technology Co., Ltd. -// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -#include "ddminterfacev1.h" -#include "common/treelandlogging.h" -#include "helper.h" -#include "usermodel.h" -#include "qwayland-server-treeland-ddm-v1.h" - -#include -#include -#include - -#include - -#include - -class DDMInterfaceV1Private : public QtWaylandServer::treeland_ddm_v1 -{ -public: - explicit DDMInterfaceV1Private(DDMInterfaceV1 *_q); - wl_global *global() const; - - DDMInterfaceV1 *q = nullptr; -protected: - void destroy(Resource *resource) override; - void bind_resource(Resource *resource) override; - void switch_to_greeter(Resource *resource) override; - void switch_to_user(Resource *resource, const QString &username) override; - void activate_session(Resource *resource) override; - void deactivate_session(Resource *resource) override; - void enable_render(Resource *resource) override; - void disable_render(Resource *resource, uint32_t callback) override; -}; - -DDMInterfaceV1Private::DDMInterfaceV1Private(DDMInterfaceV1 *_q) - : QtWaylandServer::treeland_ddm_v1() - , q(_q) -{ -} - -wl_global *DDMInterfaceV1Private::global() const -{ - return m_global; -} - -void DDMInterfaceV1Private::destroy(Resource *resource) -{ - wl_resource_destroy(resource->handle); -} - -void DDMInterfaceV1Private::bind_resource(Resource *resource) -{ - Q_UNUSED(resource) -} - -void DDMInterfaceV1Private::switch_to_greeter([[maybe_unused]] Resource *resource) -{ - qCWarning(treelandCore) << "DDM protocol: switch_to_greeter"; - Helper::instance()->showLockScreen(false); -} - -void DDMInterfaceV1Private::switch_to_user([[maybe_unused]] Resource *resource, const QString &username) -{ - qCWarning(treelandCore) << "DDM protocol: switch_to_user" << username; - auto helper = Helper::instance(); - if (username == "dde") { - helper->showLockScreen(false); - } else if (username != helper->userModel()->currentUserName()) { - helper->userModel()->setCurrentUserName(username); - helper->showLockScreen(false); - } -} - -void DDMInterfaceV1Private::activate_session([[maybe_unused]] Resource *resource) -{ - qCWarning(treelandCore) << "DDM protocol: activate_session"; - Helper::instance()->activateSession(); -} - -void DDMInterfaceV1Private::deactivate_session([[maybe_unused]] Resource *resource) -{ - qCWarning(treelandCore) << "DDM protocol: deactivate_session"; - Helper::instance()->deactivateSession(); -} - -void DDMInterfaceV1Private::enable_render([[maybe_unused]] Resource *resource) -{ - qCWarning(treelandCore) << "DDM protocol: enable_render"; - Helper::instance()->enableRender(); -} - -void DDMInterfaceV1Private::disable_render(Resource *resource, uint32_t id) -{ - Helper::instance()->disableRender(); - auto callback = wl_resource_create(resource->client(), &wl_callback_interface, 1, id); - auto serial = wl_display_get_serial(wl_client_get_display(resource->client())); - wl_callback_send_done(callback, serial); - wl_resource_destroy(callback); -} - -DDMInterfaceV1::DDMInterfaceV1(QObject *parent) - : QObject(parent) - , WServerInterface() - , d(new DDMInterfaceV1Private(this)) -{ -} - -DDMInterfaceV1::~DDMInterfaceV1() = default; - -QByteArrayView DDMInterfaceV1::interfaceName() const -{ - return d->interfaceName(); -} - -bool DDMInterfaceV1::isConnected() const -{ - return !d->resourceMap().isEmpty(); -} - -void DDMInterfaceV1::create(WServer *server) -{ - d->init(server->handle()->handle(), InterfaceVersion); -} - -void DDMInterfaceV1::destroy([[maybe_unused]] WServer *server) -{ - d->globalRemove(); -} - -wl_global *DDMInterfaceV1::global() const -{ - return d->global(); -} diff --git a/src/modules/ddm/ddmremoteobjectv1.cpp b/src/modules/ddm/ddmremoteobjectv1.cpp new file mode 100644 index 000000000..c19cf83b7 --- /dev/null +++ b/src/modules/ddm/ddmremoteobjectv1.cpp @@ -0,0 +1,177 @@ +// Copyright (C) 2026 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "ddmremoteobjectv1.h" + +#include "rep_treelandremote_source.h" + +#include "common/treelandlogging.h" +#include "greeterproxy.h" +#include "helper.h" +#include "usermodel.h" + +#include +#include +#include +#include + +namespace { +constexpr auto remoteObjectName = "TreelandRemote"; +constexpr auto remoteObjectSocketName = "org.deepin.dde.treeland.qro"; +} + +class DDMRemoteObjectV1Private : public TreelandRemoteSource +{ +public: + explicit DDMRemoteObjectV1Private(DDMRemoteObjectV1 *qObject); + void startHost(); + void stopHost(); + void switchToGreeter() override; + void switchToUser(QString username) override; + void lock() override; + + DDMRemoteObjectV1 *q = nullptr; + QRemoteObjectHost *host = nullptr; + QLocalServer *server = nullptr; +}; + +DDMRemoteObjectV1Private::DDMRemoteObjectV1Private(DDMRemoteObjectV1 *qObject) + : TreelandRemoteSource() + , q(qObject) +{ + auto *greeterProxy = Helper::instance()->greeterProxy(); + QObject::connect(greeterProxy, &GreeterProxy::lockChanged, this, [this](bool isLocked) { + Q_EMIT lockStateChanged(isLocked); + }); +} + +void DDMRemoteObjectV1Private::startHost() +{ + if (host) + return; + + QLocalServer::removeServer(QString::fromLatin1(remoteObjectSocketName)); + + server = new QLocalServer(q); + server->setSocketOptions(QLocalServer::UserAccessOption); + if (!server->listen(QString::fromLatin1(remoteObjectSocketName))) { + qCCritical(treelandCore) << "Failed to listen DDM remote socket:" + << server->errorString(); + delete server; + server = nullptr; + return; + } + + host = new QRemoteObjectHost(q); + if (!host->enableRemoting(this, QString::fromLatin1(remoteObjectName))) { + qCCritical(treelandCore) << "Failed to enable DDM remote object"; + delete host; + host = nullptr; + delete server; + server = nullptr; + QLocalServer::removeServer(QString::fromLatin1(remoteObjectSocketName)); + return; + } + + QObject::connect(server, &QLocalServer::newConnection, q, [this] { + while (server && server->hasPendingConnections()) { + auto *socket = server->nextPendingConnection(); + if (!socket) + continue; + + QObject::connect(socket, &QLocalSocket::disconnected, socket, &QObject::deleteLater); + host->addHostSideConnection(socket); + } + }); + + qCInfo(treelandCore) << "DDM remote object is listening on" + << server->fullServerName(); +} + +void DDMRemoteObjectV1Private::stopHost() +{ + if (server) { + server->close(); + delete server; + server = nullptr; + QLocalServer::removeServer(QString::fromLatin1(remoteObjectSocketName)); + } + + if (!host) + return; + + delete host; + host = nullptr; + qCInfo(treelandCore) << "DDM remote object stopped"; +} + +void DDMRemoteObjectV1Private::switchToGreeter() +{ + qCInfo(treelandCore) << "DDM remote: switchToGreeter"; + Helper::instance()->showLockScreen(false); +} + +void DDMRemoteObjectV1Private::switchToUser(QString username) +{ + qCInfo(treelandCore) << "DDM remote: switchToUser" << username; + auto helper = Helper::instance(); + if (username == "dde") { + helper->showLockScreen(false); + } else if (username != helper->userModel()->currentUserName()) { + helper->userModel()->setCurrentUserName(username); + helper->showLockScreen(false); + } +} + +void DDMRemoteObjectV1Private::lock() +{ + qCInfo(treelandCore) << "DDM remote: lock"; + Helper::instance()->greeterProxy()->setLock(true); +} + +DDMRemoteObjectV1::DDMRemoteObjectV1(QObject *parent) + : QObject(parent) + , WServerInterface() + , d(new DDMRemoteObjectV1Private(this)) +{ +} + +DDMRemoteObjectV1::~DDMRemoteObjectV1() = default; + +QByteArrayView DDMRemoteObjectV1::interfaceName() const +{ + return QByteArrayView(remoteObjectName); +} + +bool DDMRemoteObjectV1::isConnected() const +{ + return d->host != nullptr; +} + +void DDMRemoteObjectV1::create(WServer *server) +{ + Q_UNUSED(server) + + auto *greeterProxy = Helper::instance()->greeterProxy(); + Q_ASSERT(greeterProxy); + + QObject::connect(greeterProxy, &GreeterProxy::socketConnected, this, [this] { + d->startHost(); + }, Qt::UniqueConnection); + QObject::connect(greeterProxy, &GreeterProxy::socketDisconnected, this, [this] { + d->stopHost(); + }, Qt::UniqueConnection); + + if (greeterProxy->isConnected()) + d->startHost(); +} + +void DDMRemoteObjectV1::destroy([[maybe_unused]] WServer *server) +{ + d->stopHost(); +} + +wl_global *DDMRemoteObjectV1::global() const +{ + return nullptr; +} diff --git a/src/modules/ddm/ddminterfacev1.h b/src/modules/ddm/ddmremoteobjectv1.h similarity index 53% rename from src/modules/ddm/ddminterfacev1.h rename to src/modules/ddm/ddmremoteobjectv1.h index 310b46f6d..0f1d454a1 100644 --- a/src/modules/ddm/ddminterfacev1.h +++ b/src/modules/ddm/ddmremoteobjectv1.h @@ -1,18 +1,27 @@ -// Copyright (C) 2025-2026 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2026 UnionTech Software Technology Co., Ltd. // SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#pragma once + #include "wserver.h" +#include + WAYLIB_SERVER_USE_NAMESPACE QW_USE_NAMESPACE -class DDMInterfaceV1Private; -class DDMInterfaceV1 : public QObject , public WServerInterface +class QLocalServer; +class QRemoteObjectHost; +class DDMRemoteObjectV1; + +class DDMRemoteObjectV1Private; + +class DDMRemoteObjectV1 : public QObject, public WServerInterface { Q_OBJECT public: - explicit DDMInterfaceV1(QObject *parent = nullptr); - ~DDMInterfaceV1() override; + explicit DDMRemoteObjectV1(QObject *parent = nullptr); + ~DDMRemoteObjectV1() override; bool isConnected() const; @@ -25,5 +34,5 @@ class DDMInterfaceV1 : public QObject , public WServerInterface wl_global *global() const override; private: - std::unique_ptr d; + std::unique_ptr d; }; diff --git a/src/modules/ddm/treelandremote.rep b/src/modules/ddm/treelandremote.rep new file mode 100644 index 000000000..db212a16a --- /dev/null +++ b/src/modules/ddm/treelandremote.rep @@ -0,0 +1,9 @@ +// Copyright (C) 2026 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +class TreelandRemote { + SLOT(void switchToGreeter()); + SLOT(void switchToUser(QString username)); + SLOT(void lock()); + SIGNAL(lockStateChanged(bool locked)); +}; diff --git a/src/modules/foreign-toplevel/foreigntoplevelhandlev1.h b/src/modules/foreign-toplevel/foreigntoplevelhandlev1.h index e6b0da20a..bfb11632f 100644 --- a/src/modules/foreign-toplevel/foreigntoplevelhandlev1.h +++ b/src/modules/foreign-toplevel/foreigntoplevelhandlev1.h @@ -12,7 +12,7 @@ #include -class SurfaceEntry; +struct SurfaceEntry; class ForeignToplevelManagerInterfaceV1; class ForeignToplevelHandleV1Private; struct wl_resource; diff --git a/src/modules/resource/treelandremotesource.cpp b/src/modules/resource/treelandremotesource.cpp index 78e112585..75ea39bfc 100644 --- a/src/modules/resource/treelandremotesource.cpp +++ b/src/modules/resource/treelandremotesource.cpp @@ -23,7 +23,7 @@ WAYLIB_SERVER_USE_NAMESPACE -TreelandRemoteSource::TreelandRemoteSource(QObject *parent) +TreelandWindowTreeSource::TreelandWindowTreeSource(QObject *parent) : WindowTreeRemoteSource(parent) { auto *host = new QRemoteObjectHost(this); @@ -36,11 +36,11 @@ TreelandRemoteSource::TreelandRemoteSource(QObject *parent) } } -TreelandRemoteSource::~TreelandRemoteSource() = default; +TreelandWindowTreeSource::~TreelandWindowTreeSource() = default; -QPointF TreelandRemoteSource::cursorPosition() const +QPointF TreelandWindowTreeSource::cursorPosition() const { - auto *self = const_cast(this); + auto *self = const_cast(this); if (!self->m_cursorTracking) { if (auto *root = Helper::instance()->rootSurfaceContainer(); root && root->cursor()) { self->m_cursorTracking = true; @@ -54,7 +54,7 @@ QPointF TreelandRemoteSource::cursorPosition() const return m_cursorPosition; } -TreelandInfo TreelandRemoteSource::getTreelandInfo() +TreelandInfo TreelandWindowTreeSource::getTreelandInfo() { TreelandInfo info; @@ -74,7 +74,7 @@ TreelandInfo TreelandRemoteSource::getTreelandInfo() return info; } -WindowInfo TreelandRemoteSource::buildWindowInfo(SurfaceWrapper *surface, +WindowInfo TreelandWindowTreeSource::buildWindowInfo(SurfaceWrapper *surface, int layer, const QString &containerName, int z) const @@ -109,7 +109,7 @@ WindowInfo TreelandRemoteSource::buildWindowInfo(SurfaceWrapper *surface, return info; } -void TreelandRemoteSource::collectSurfaceInfos(QList &infos, +void TreelandWindowTreeSource::collectSurfaceInfos(QList &infos, SurfaceWrapper *surface, int layer, const QString &containerName, @@ -124,7 +124,7 @@ void TreelandRemoteSource::collectSurfaceInfos(QList &infos, } } -void TreelandRemoteSource::collectWorkspaceModelWindows(QList &infos, +void TreelandWindowTreeSource::collectWorkspaceModelWindows(QList &infos, WorkspaceModel *workspaceModel, int layer, const QString &containerName) const @@ -141,7 +141,7 @@ void TreelandRemoteSource::collectWorkspaceModelWindows(QList &infos } } -void TreelandRemoteSource::collectCurrentWorkspaceModelWindows(QList &infos, +void TreelandWindowTreeSource::collectCurrentWorkspaceModelWindows(QList &infos, WorkspaceModel *workspaceModel, int layer, const QString &containerName) const @@ -171,7 +171,7 @@ void TreelandRemoteSource::collectCurrentWorkspaceModelWindows(QList } } -LayerInfo TreelandRemoteSource::buildLayerInfo(SurfaceContainer *container) const +LayerInfo TreelandWindowTreeSource::buildLayerInfo(SurfaceContainer *container) const { LayerInfo layerInfo; const int layer = static_cast(container->z()); @@ -211,7 +211,7 @@ LayerInfo TreelandRemoteSource::buildLayerInfo(SurfaceContainer *container) cons return layerInfo; } -void TreelandRemoteSource::updateCursor(const QPointF &newPosition) +void TreelandWindowTreeSource::updateCursor(const QPointF &newPosition) { if (newPosition != m_cursorPosition) { m_cursorPosition = newPosition; diff --git a/src/modules/resource/treelandremotesource.h b/src/modules/resource/treelandremotesource.h index 276c2c2a9..bbb761e73 100644 --- a/src/modules/resource/treelandremotesource.h +++ b/src/modules/resource/treelandremotesource.h @@ -11,13 +11,13 @@ class SurfaceWrapper; class SurfaceContainer; class WorkspaceModel; -class TreelandRemoteSource : public WindowTreeRemoteSource +class TreelandWindowTreeSource : public WindowTreeRemoteSource { Q_OBJECT public: - explicit TreelandRemoteSource(QObject *parent = nullptr); - ~TreelandRemoteSource() override; + explicit TreelandWindowTreeSource(QObject *parent = nullptr); + ~TreelandWindowTreeSource() override; QPointF cursorPosition() const override; TreelandInfo getTreelandInfo() override; diff --git a/src/plugins/lockscreen/qml/UserInput.qml b/src/plugins/lockscreen/qml/UserInput.qml index e368d4904..a4b796a85 100644 --- a/src/plugins/lockscreen/qml/UserInput.qml +++ b/src/plugins/lockscreen/qml/UserInput.qml @@ -349,10 +349,7 @@ Item { function userLogin() { let user = UserModel.get(UserModel.currentUserName) - if (user.loggedIn) - GreeterProxy.unlock(user.name, passwordField.text) - else - GreeterProxy.login(user.name, passwordField.text, SessionModel.currentIndex) + GreeterProxy.login(user.name, passwordField.text, SessionModel.currentIndex) } Connections { diff --git a/src/seat/helper.cpp b/src/seat/helper.cpp index 2fdabfbc9..3721bd9c5 100644 --- a/src/seat/helper.cpp +++ b/src/seat/helper.cpp @@ -31,7 +31,7 @@ #include "modules/capture/capture.h" #include "modules/dde-shell/ddeshellattached.h" #include "modules/dde-shell/ddeshellmanagerinterfacev1.h" -#include "modules/ddm/ddminterfacev1.h" +#include "modules/ddm/ddmremoteobjectv1.h" #include "modules/output-manager/outputmanagement.h" #include "modules/personalization/personalizationmanagerinterfacev1.h" #include "modules/screensaver/screensaverinterfacev1.h" @@ -123,8 +123,6 @@ #include #include -#include -#include #include #include #include @@ -283,16 +281,6 @@ Helper::Helper(QObject *parent) } else { qCInfo(treelandCore) << "Successfully connected to systemd-logind PrepareForSleep signal"; } - - // Also connect to SessionNew signal for logging purposes - QDBusConnection::systemBus().connect( - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "SessionNew", - this, - SLOT(onSessionNew(QString,QDBusObjectPath)) - ); } Helper::~Helper() @@ -339,7 +327,7 @@ void Helper::tryInitRemoteSource() if (m_treelandRemoteSource) return; if (m_globalConfig->debugSource()) { - m_treelandRemoteSource = new TreelandRemoteSource(this); + m_treelandRemoteSource = new TreelandWindowTreeSource(this); } } @@ -1271,7 +1259,7 @@ void Helper::init(Treeland::Treeland *treeland) m_backend = m_server->attach(); m_seatManager = new SeatsManager(m_server, this); - m_ddmInterfaceV1 = m_server->attach(); + m_ddmRemoteObjectV1 = m_server->attach(); m_outputManager = m_server->attach(); connect(m_backend, &WBackend::outputAdded, this, &Helper::onOutputAdded); @@ -2262,26 +2250,6 @@ void Helper::handleLockScreen(LockScreenInterface *lockScreen) } -void Helper::onSessionNew(const QString &sessionId, const QDBusObjectPath &sessionPath) -{ - const auto path = sessionPath.path(); - qCDebug(treelandCore) << "Session new, sessionId:" << sessionId << ", sessionPath:" << path; - QDBusConnection::systemBus().connect("org.freedesktop.login1", path, "org.freedesktop.login1.Session", "Lock", this, SLOT(onSessionLock())); - QDBusConnection::systemBus().connect("org.freedesktop.login1", path, "org.freedesktop.login1.Session", "Unlock", this, SLOT(onSessionUnlock())); -} - -void Helper::onSessionLock() -{ - showLockScreen(); -} - -void Helper::onSessionUnlock() -{ - if (m_lockScreen) { - m_lockScreen->unlock(); - } -} - void Helper::onExtSessionLock(WSessionLock *lock) { #ifdef EXT_SESSION_LOCK_V1 @@ -2587,18 +2555,10 @@ void Helper::showLockScreen(bool switchToGreeter) setWorkspaceVisible(false); setCurrentMode(CurrentMode::LockScreen); - m_lockScreen->lock(); - - // send DDM switch to greeter mode - if (switchToGreeter) { - QThreadPool::globalInstance()->start([]() { - QDBusInterface interface("org.freedesktop.DisplayManager", - "/org/freedesktop/DisplayManager/Seat0", - "org.freedesktop.DisplayManager.Seat", - QDBusConnection::systemBus()); - interface.call("SwitchToGreeter"); - }); - } + if (switchToGreeter) + m_lockScreen->lock(); + else + m_greeterProxy->setLock(true); } WSeat *Helper::seat() const @@ -2729,10 +2689,6 @@ void Helper::onPrepareForSleep(bool sleep) } } -DDMInterfaceV1 *Helper::ddmInterfaceV1() const { - return m_ddmInterfaceV1; -} - void Helper::activateSession() { if (!m_backend->isSessionActive()) m_backend->activateSession(); diff --git a/src/seat/helper.h b/src/seat/helper.h index bbaec0c4e..ea31eff09 100644 --- a/src/seat/helper.h +++ b/src/seat/helper.h @@ -29,7 +29,6 @@ class QJsonObject; -Q_MOC_INCLUDE() Q_MOC_INCLUDE() Q_MOC_INCLUDE() Q_MOC_INCLUDE() @@ -43,7 +42,6 @@ Q_MOC_INCLUDE("treelandconfig.hpp") Q_MOC_INCLUDE("treelanduserconfig.hpp") QT_BEGIN_NAMESPACE -class QDBusObjectPath; class QQuickItem; QT_END_NAMESPACE @@ -98,7 +96,7 @@ QW_USE_NAMESPACE class CaptureSourceSelector; class DDEShellManagerInterfaceV1; -class DDMInterfaceV1; +class DDMRemoteObjectV1; class ForeignToplevelManagerInterfaceV1; class FpsDisplayManager; class GreeterProxy; @@ -124,7 +122,7 @@ class SurfaceContainer; class SurfaceWrapper; class TreelandConfig; class TreelandUserConfig; -class TreelandRemoteSource; +class TreelandWindowTreeSource; class UserModel; class VirtualOutputManagerInterfaceV1; class WallpaperColorInterfaceV1; @@ -237,7 +235,7 @@ class Helper : public WSeatEventFilter inline UserModel *userModel() const { return m_userModel; }; inline SessionModel *sessionModel() const { return m_sessionModel; }; - DDMInterfaceV1 *ddmInterfaceV1() const; + inline GreeterProxy *greeterProxy() const { return m_greeterProxy; }; void activateSession(); void deactivateSession(); @@ -291,9 +289,6 @@ private Q_SLOTS: void onShowDesktop(); void deleteTaskSwitch(); void onPrepareForSleep(bool sleep); - void onSessionNew(const QString &sessionId, const QDBusObjectPath &objectPath); - void onSessionLock(); - void onSessionUnlock(); private: void onOutputAdded(WOutput *output); @@ -402,7 +397,7 @@ private Q_SLOTS: DDEShellManagerInterfaceV1 *m_ddeShellV1 = nullptr; VirtualOutputManagerInterfaceV1 *m_virtualOutputInterfaceV1 = nullptr; OutputManagerV1 *m_outputManagerV1 = nullptr; - DDMInterfaceV1 *m_ddmInterfaceV1 = nullptr; + DDMRemoteObjectV1 *m_ddmRemoteObjectV1 = nullptr; ScreensaverInterfaceV1 *m_screensaverInterfaceV1 = nullptr; TreelandWallpaperManagerInterfaceV1 *m_wallpaperManagerInterfaceV1 = nullptr; TreelandWallpaperNotifierInterfaceV1 *m_wallpaperNotifierInterfaceV1 = nullptr; @@ -440,7 +435,7 @@ private Q_SLOTS: bool m_isDDMDisplay{ false }; void tryInitRemoteSource(); - TreelandRemoteSource *m_treelandRemoteSource = nullptr; + TreelandWindowTreeSource *m_treelandRemoteSource = nullptr; struct PendingOutputConfig { qw_output_configuration_v1 *config = nullptr;