diff --git a/src/impl/networkmanager/devicemanagerrealize.cpp b/src/impl/networkmanager/devicemanagerrealize.cpp index d9a34eeae..3ad7b6b3e 100644 --- a/src/impl/networkmanager/devicemanagerrealize.cpp +++ b/src/impl/networkmanager/devicemanagerrealize.cpp @@ -10,6 +10,7 @@ #include "configsetting.h" #include "ipmanager.h" #include "nmnetworkmanager.h" +#include "sessionstatetracker.h" #include #include @@ -846,12 +847,14 @@ void WirelessDeviceManagerRealize::connectNetwork(const AccessPoints *accessPoin wsSetting->setInitialized(keyMgmt != NetworkManager::WirelessSecuritySetting::KeyMgmt::WpaNone && keyMgmt != NetworkManager::WirelessSecuritySetting::KeyMgmt::Unknown); NMVariantMapMap settingMap = currentConnection->settings()->toMap(); qCDebug(DNC) << "securit changed..." << settingMap; - if (currentConnection->isUnsaved()) { - currentConnection->updateUnsaved(settingMap); - } else { - currentConnection->update(settingMap); - QDBusPendingReply<> reply = currentConnection->save(); - reply.waitForFinished(); + if (SessionStateTracker::instance()->isSessionActive()) { + if (currentConnection->isUnsaved()) { + currentConnection->updateUnsaved(settingMap); + } else { + currentConnection->update(settingMap); + QDBusPendingReply<> reply = currentConnection->save(); + reply.waitForFinished(); + } } } QVariantMap options; @@ -1009,14 +1012,16 @@ void WirelessDeviceManagerRealize::onActiveConnectionChanged() if (activeAp && conn) { conn->settings()->setTimestamp(QDateTime::currentDateTime()); if (state == NetworkManager::ActiveConnection::Activated && conn->isUnsaved()) { - const NetworkManager::Setting::SettingType settingType[] = { NetworkManager::Setting::Security8021x, NetworkManager::Setting::WirelessSecurity }; - for (auto type : settingType) { - NetworkManager::Setting::Ptr setting = conn->settings()->setting(type); - if (setting) { - conn->secrets(setting->name()); + if (SessionStateTracker::instance()->isSessionActive()) { + const NetworkManager::Setting::SettingType settingType[] = { NetworkManager::Setting::Security8021x, NetworkManager::Setting::WirelessSecurity }; + for (auto type : settingType) { + NetworkManager::Setting::Ptr setting = conn->settings()->setting(type); + if (setting) { + conn->secrets(setting->name()); + } } + conn->save(); } - conn->save(); connect(conn.data(), &NetworkManager::Connection::unsavedChanged, this, [this] { Q_EMIT activeConnectionChanged(); }); diff --git a/src/impl/networkmanager/networkmanagerprocesser.cpp b/src/impl/networkmanager/networkmanagerprocesser.cpp index a8b1d0f6c..a0911faa3 100644 --- a/src/impl/networkmanager/networkmanagerprocesser.cpp +++ b/src/impl/networkmanager/networkmanagerprocesser.cpp @@ -7,6 +7,7 @@ #include "hotspotcontrollernm.h" #include "networkdevicebase.h" #include "networkmanagerprocesser.h" +#include "sessionstatetracker.h" #include "proxycontrollernm.h" #include "vpncontrollernm.h" #include "networkdetails.h" @@ -80,6 +81,13 @@ void NetworkManagerProcesser::initConnections() connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionsChanged, this, &NetworkManagerProcesser::onUpdateNetworkDetail); // 当网络状态发生变化时,也刷新Detail connect(NetworkManager::notifier(), &NetworkManager::Notifier::statusChanged, this, &NetworkManagerProcesser::onUpdateNetworkDetail); + // 会话从后台切回前台时,本地用户主动刷新网络状态 + connect(SessionStateTracker::instance(), &SessionStateTracker::sessionResumed, this, [this] { + if (SessionStateTracker::instance()->isLocalUser()) { + qCDebug(DNC) << "session resumed, refreshing network state"; + onUpdateNetworkDetail(); + } + }); } void NetworkManagerProcesser::onDevicesChanged(const QList &devices) diff --git a/src/impl/networkmanager/sessionstatetracker.h b/src/impl/networkmanager/sessionstatetracker.h new file mode 100644 index 000000000..fdad83839 --- /dev/null +++ b/src/impl/networkmanager/sessionstatetracker.h @@ -0,0 +1,136 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef SESSIONSTATETRACKER_H +#define SESSIONSTATETRACKER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SessionStateTracker : public QObject { + Q_OBJECT +public: + static SessionStateTracker *instance() { + static SessionStateTracker *s_instance = new SessionStateTracker(); + return s_instance; + } + + bool isSessionActive() const { + return m_userActive; + } + + bool isLocalUser() const { + return m_isLocal; + } + +private: + SessionStateTracker() + : QObject(nullptr) + , m_userActive(true) + , m_isLocal(false) + { + // Step 1: 异步获取 User.Display(session 路径) + QDBusMessage msg = QDBusMessage::createMethodCall( + "org.freedesktop.login1", + "/org/freedesktop/login1/user/self", + "org.freedesktop.DBus.Properties", + "Get" + ); + msg << "org.freedesktop.login1.User" << "Display"; + QDBusConnection::systemBus().callWithCallback(msg, this, SLOT(onDisplayReady(QDBusVariant))); + } + + ~SessionStateTracker() = default; + SessionStateTracker(const SessionStateTracker &) = delete; + SessionStateTracker &operator=(const SessionStateTracker &) = delete; + +private slots: + void onDisplayReady(const QDBusVariant &display) { + const QDBusArgument arg = display.variant().value(); + QString id; + QDBusObjectPath path; + arg.beginStructure(); + arg >> id >> path; + arg.endStructure(); + + if (path.path().isEmpty()) { + qWarning() << "[SessionStateTracker] Display empty, keep default active"; + return; + } + + // Step 2: 检查 Remote 属性 + QDBusMessage remoteMsg = QDBusMessage::createMethodCall( + "org.freedesktop.login1", + path.path(), + "org.freedesktop.DBus.Properties", + "Get" + ); + remoteMsg << "org.freedesktop.login1.Session" << "Remote"; + QDBusPendingReply remoteReply = QDBusConnection::systemBus().asyncCall(remoteMsg); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(remoteReply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [path, this](QDBusPendingCallWatcher *self) { + QDBusPendingReply reply = *self; + bool remote = !reply.isError() && reply.value().variant().toBool(); + if (!remote) { + m_isLocal = true; + // Step 3: 监听 Active 变化 + QDBusConnection::systemBus().connect( + "org.freedesktop.login1", + path.path(), + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + this, + SLOT(onSessionPropertiesChanged(QString, QVariantMap, QStringList)) + ); + // 同时读一次初始 Active 状态 + QDBusMessage activeMsg = QDBusMessage::createMethodCall( + "org.freedesktop.login1", + path.path(), + "org.freedesktop.DBus.Properties", + "Get" + ); + activeMsg << "org.freedesktop.login1.Session" << "Active"; + QDBusPendingReply activeReply = QDBusConnection::systemBus().asyncCall(activeMsg); + QDBusPendingCallWatcher *activeWatcher = new QDBusPendingCallWatcher(activeReply, this); + connect(activeWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *sw) { + QDBusPendingReply sr = *sw; + if (!sr.isError()) { + m_userActive = sr.value().variant().toBool(); + } + sw->deleteLater(); + }); + } + self->deleteLater(); + }); + } + + void onSessionPropertiesChanged(const QString &interface, const QVariantMap &properties, const QStringList &) { + if (interface == "org.freedesktop.login1.Session" && properties.contains("Active")) { + m_userActive = properties.value("Active").toBool(); + if (m_userActive) { + qWarning() << "[SessionStateTracker] session resumed"; + Q_EMIT sessionResumed(); + } else { + qWarning() << "[SessionStateTracker] session left"; + } + } + } + +signals: + void sessionResumed(); + +private: + bool m_userActive; + bool m_isLocal; +}; + +#endif // SESSIONSTATETRACKER_H \ No newline at end of file diff --git a/src/impl/serviceinter/deviceinterrealize.cpp b/src/impl/serviceinter/deviceinterrealize.cpp index b1d9c1296..83d4f6f46 100644 --- a/src/impl/serviceinter/deviceinterrealize.cpp +++ b/src/impl/serviceinter/deviceinterrealize.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -7,6 +7,7 @@ #include "wireddevice.h" #include "wirelessdevice.h" #include "accesspointsproxyinter.h" +#include "../networkmanager/sessionstatetracker.h" #include @@ -366,14 +367,16 @@ void DeviceInterRealize::onActiveConnectionChanged() connect(activeConnection.data(), &NetworkManager::ActiveConnection::stateChanged, this, [ activeConnection, this ](NetworkManager::ActiveConnection::State state) { if (state == NetworkManager::ActiveConnection::State::Activated) { NetworkManager::Connection::Ptr conn = activeConnection->connection(); - const NetworkManager::Setting::SettingType settingType[] = { NetworkManager::Setting::Security8021x, NetworkManager::Setting::WirelessSecurity }; - for (auto type : settingType) { - NetworkManager::Setting::Ptr setting = conn->settings()->setting(type); - if (setting) { - conn->secrets(setting->name()); + if (SessionStateTracker::instance()->isSessionActive()) { + const NetworkManager::Setting::SettingType settingType[] = { NetworkManager::Setting::Security8021x, NetworkManager::Setting::WirelessSecurity }; + for (auto type : settingType) { + NetworkManager::Setting::Ptr setting = conn->settings()->setting(type); + if (setting) { + conn->secrets(setting->name()); + } } + conn->save(); } - conn->save(); connect(conn.data(), &NetworkManager::Connection::unsavedChanged, this, [this] { Q_EMIT activeConnectionChanged(); });