mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
services: network&wifi only send notification toasts if the adapter has changed state externally
This commit is contained in:
+33
-21
@@ -527,13 +527,14 @@ void Application::initServices() {
|
||||
try {
|
||||
m_networkService = std::make_unique<NetworkService>(*m_systemBus);
|
||||
m_prevWirelessEnabledForEvents = m_networkService->state().wirelessEnabled;
|
||||
m_networkService->setChangeCallback([this, shouldRefreshControlCenter](const NetworkState& state) {
|
||||
onNetworkStateChangedForEvents(state);
|
||||
m_bar.refresh();
|
||||
if (shouldRefreshControlCenter()) {
|
||||
m_panelManager.refresh();
|
||||
}
|
||||
});
|
||||
m_networkService->setChangeCallback(
|
||||
[this, shouldRefreshControlCenter](const NetworkState& state, NetworkChangeOrigin origin) {
|
||||
onNetworkStateChangedForEvents(state, origin);
|
||||
m_bar.refresh();
|
||||
if (shouldRefreshControlCenter()) {
|
||||
m_panelManager.refresh();
|
||||
}
|
||||
});
|
||||
kLog.info("network service active");
|
||||
} catch (const std::exception& e) {
|
||||
kLog.warn("network service disabled: {}", e.what());
|
||||
@@ -558,10 +559,11 @@ void Application::initServices() {
|
||||
m_panelManager.refresh();
|
||||
}
|
||||
};
|
||||
m_bluetoothService->setStateCallback([this, refreshBluetoothUi](const BluetoothState& state) {
|
||||
onBluetoothStateChangedForEvents(state);
|
||||
refreshBluetoothUi();
|
||||
});
|
||||
m_bluetoothService->setStateCallback(
|
||||
[this, refreshBluetoothUi](const BluetoothState& state, BluetoothStateChangeOrigin origin) {
|
||||
onBluetoothStateChangedForEvents(state, origin);
|
||||
refreshBluetoothUi();
|
||||
});
|
||||
m_bluetoothService->setDevicesCallback(
|
||||
[refreshBluetoothUi](const std::vector<BluetoothDeviceInfo>& /*devices*/) { refreshBluetoothUi(); });
|
||||
kLog.info("bluetooth service active");
|
||||
@@ -1172,40 +1174,50 @@ void Application::onUpowerStateChangedForHooks() {
|
||||
m_prevUpowerForHooks = next;
|
||||
}
|
||||
|
||||
void Application::onNetworkStateChangedForEvents(const NetworkState& state) {
|
||||
void Application::onNetworkStateChangedForEvents(const NetworkState& state, NetworkChangeOrigin origin) {
|
||||
if (!m_prevWirelessEnabledForEvents.has_value()) {
|
||||
m_prevWirelessEnabledForEvents = state.wirelessEnabled;
|
||||
return;
|
||||
}
|
||||
const bool prev = *m_prevWirelessEnabledForEvents;
|
||||
if (prev != state.wirelessEnabled) {
|
||||
if (origin != NetworkChangeOrigin::Noctalia) {
|
||||
if (state.wirelessEnabled) {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.network"),
|
||||
i18n::tr("notifications.internal.wifi-enabled"), "");
|
||||
} else {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.network"),
|
||||
i18n::tr("notifications.internal.wifi-disabled"), "");
|
||||
}
|
||||
}
|
||||
if (state.wirelessEnabled) {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.network"),
|
||||
i18n::tr("notifications.internal.wifi-enabled"), "");
|
||||
m_hookManager.fire(HookKind::WifiEnabled);
|
||||
} else {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.network"),
|
||||
i18n::tr("notifications.internal.wifi-disabled"), "");
|
||||
m_hookManager.fire(HookKind::WifiDisabled);
|
||||
}
|
||||
}
|
||||
m_prevWirelessEnabledForEvents = state.wirelessEnabled;
|
||||
}
|
||||
|
||||
void Application::onBluetoothStateChangedForEvents(const BluetoothState& state) {
|
||||
void Application::onBluetoothStateChangedForEvents(const BluetoothState& state, BluetoothStateChangeOrigin origin) {
|
||||
if (!m_prevBluetoothPoweredForEvents.has_value()) {
|
||||
m_prevBluetoothPoweredForEvents = state.powered;
|
||||
return;
|
||||
}
|
||||
const bool prev = *m_prevBluetoothPoweredForEvents;
|
||||
if (prev != state.powered) {
|
||||
if (origin != BluetoothStateChangeOrigin::Noctalia) {
|
||||
if (state.powered) {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.bluetooth"),
|
||||
i18n::tr("notifications.internal.bluetooth-enabled"), "");
|
||||
} else {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.bluetooth"),
|
||||
i18n::tr("notifications.internal.bluetooth-disabled"), "");
|
||||
}
|
||||
}
|
||||
if (state.powered) {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.bluetooth"),
|
||||
i18n::tr("notifications.internal.bluetooth-enabled"), "");
|
||||
m_hookManager.fire(HookKind::BluetoothEnabled);
|
||||
} else {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.bluetooth"),
|
||||
i18n::tr("notifications.internal.bluetooth-disabled"), "");
|
||||
m_hookManager.fire(HookKind::BluetoothDisabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,8 +109,8 @@ private:
|
||||
bool runIdleCommand(const std::string& command);
|
||||
void onIconThemeChanged();
|
||||
void onUpowerStateChangedForHooks();
|
||||
void onNetworkStateChangedForEvents(const NetworkState& state);
|
||||
void onBluetoothStateChangedForEvents(const BluetoothState& state);
|
||||
void onNetworkStateChangedForEvents(const NetworkState& state, NetworkChangeOrigin origin);
|
||||
void onBluetoothStateChangedForEvents(const BluetoothState& state, BluetoothStateChangeOrigin origin);
|
||||
[[nodiscard]] std::vector<PollSource*> currentPollSources();
|
||||
[[nodiscard]] std::vector<PollSource*> buildPollSources();
|
||||
|
||||
|
||||
@@ -326,12 +326,15 @@ struct BluetoothService::Impl {
|
||||
BluetoothState next = self.m_state;
|
||||
readAdapterProps(changed, next);
|
||||
next.adapterPresent = true;
|
||||
if (next.powered != self.m_state.powered) {
|
||||
const bool poweredChanged = next.powered != self.m_state.powered;
|
||||
BluetoothStateChangeOrigin origin = BluetoothStateChangeOrigin::External;
|
||||
if (poweredChanged) {
|
||||
kLog.debug("adapter Powered -> {}", next.powered);
|
||||
origin = self.consumePoweredChangeOrigin(next.powered);
|
||||
}
|
||||
if (next != self.m_state) {
|
||||
self.m_state = std::move(next);
|
||||
self.emitState();
|
||||
self.emitState(origin);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -442,12 +445,16 @@ void BluetoothService::refresh() {
|
||||
try {
|
||||
ManagedObjects objects;
|
||||
m_impl->root->callMethod("GetManagedObjects").onInterface(k_objectManagerInterface).storeResultsTo(objects);
|
||||
const BluetoothState previous = m_state;
|
||||
m_devices.clear();
|
||||
m_state = BluetoothState{};
|
||||
m_impl->adapterPath.clear();
|
||||
m_impl->adapter.reset();
|
||||
m_impl->seedFromManagedObjects(objects);
|
||||
emitState();
|
||||
const BluetoothStateChangeOrigin origin = previous.powered != m_state.powered
|
||||
? consumePoweredChangeOrigin(m_state.powered)
|
||||
: BluetoothStateChangeOrigin::External;
|
||||
emitState(origin);
|
||||
emitDevices();
|
||||
} catch (const sdbus::Error& e) {
|
||||
kLog.debug("GetManagedObjects failed: {}", e.what());
|
||||
@@ -458,6 +465,9 @@ void BluetoothService::setPowered(bool enabled) {
|
||||
if (m_impl->adapter == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (enabled != m_state.powered) {
|
||||
m_pendingLocalPowered = enabled;
|
||||
}
|
||||
try {
|
||||
if (!enabled && m_state.discovering) {
|
||||
try {
|
||||
@@ -467,6 +477,9 @@ void BluetoothService::setPowered(bool enabled) {
|
||||
}
|
||||
m_impl->adapter->setProperty("Powered").onInterface(k_adapterInterface).toValue(enabled);
|
||||
} catch (const sdbus::Error& e) {
|
||||
if (m_pendingLocalPowered == enabled) {
|
||||
m_pendingLocalPowered.reset();
|
||||
}
|
||||
kLog.warn("setPowered failed: {}", e.what());
|
||||
}
|
||||
}
|
||||
@@ -618,9 +631,18 @@ BluetoothDeviceInfo* BluetoothService::findDevice(const std::string& path) {
|
||||
return it == m_devices.end() ? nullptr : &*it;
|
||||
}
|
||||
|
||||
void BluetoothService::emitState() {
|
||||
BluetoothStateChangeOrigin BluetoothService::consumePoweredChangeOrigin(bool powered) {
|
||||
if (!m_pendingLocalPowered.has_value()) {
|
||||
return BluetoothStateChangeOrigin::External;
|
||||
}
|
||||
const bool matchesLocalRequest = *m_pendingLocalPowered == powered;
|
||||
m_pendingLocalPowered.reset();
|
||||
return matchesLocalRequest ? BluetoothStateChangeOrigin::Noctalia : BluetoothStateChangeOrigin::External;
|
||||
}
|
||||
|
||||
void BluetoothService::emitState(BluetoothStateChangeOrigin origin) {
|
||||
if (m_stateCallback) {
|
||||
m_stateCallback(m_state);
|
||||
m_stateCallback(m_state, origin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -57,9 +58,14 @@ struct BluetoothState {
|
||||
bool operator==(const BluetoothState&) const = default;
|
||||
};
|
||||
|
||||
enum class BluetoothStateChangeOrigin : std::uint8_t {
|
||||
External,
|
||||
Noctalia,
|
||||
};
|
||||
|
||||
class BluetoothService {
|
||||
public:
|
||||
using StateCallback = std::function<void(const BluetoothState&)>;
|
||||
using StateCallback = std::function<void(const BluetoothState&, BluetoothStateChangeOrigin)>;
|
||||
using DevicesCallback = std::function<void(const std::vector<BluetoothDeviceInfo>&)>;
|
||||
|
||||
explicit BluetoothService(SystemBus& bus);
|
||||
@@ -93,13 +99,15 @@ private:
|
||||
friend struct Impl;
|
||||
|
||||
BluetoothDeviceInfo* findDevice(const std::string& path);
|
||||
void emitState();
|
||||
[[nodiscard]] BluetoothStateChangeOrigin consumePoweredChangeOrigin(bool powered);
|
||||
void emitState(BluetoothStateChangeOrigin origin = BluetoothStateChangeOrigin::External);
|
||||
void emitDevices();
|
||||
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
|
||||
BluetoothState m_state;
|
||||
std::vector<BluetoothDeviceInfo> m_devices;
|
||||
std::optional<bool> m_pendingLocalPowered;
|
||||
StateCallback m_stateCallback;
|
||||
DevicesCallback m_devicesCallback;
|
||||
};
|
||||
|
||||
@@ -204,9 +204,12 @@ void NetworkService::refresh() {
|
||||
const bool apsChanged = previousAps != m_accessPoints;
|
||||
const bool savedChanged = previousSaved != m_savedSsids;
|
||||
const bool stateChanged = next != m_state;
|
||||
const bool wirelessEnabledChanged = next.wirelessEnabled != m_state.wirelessEnabled;
|
||||
const NetworkChangeOrigin origin =
|
||||
wirelessEnabledChanged ? consumeWirelessEnabledChangeOrigin(next.wirelessEnabled) : NetworkChangeOrigin::External;
|
||||
m_state = std::move(next);
|
||||
if ((stateChanged || apsChanged || savedChanged) && m_changeCallback) {
|
||||
m_changeCallback(m_state);
|
||||
m_changeCallback(m_state, origin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,9 +302,15 @@ bool NetworkService::activateAccessPoint(const AccessPointInfo& ap) {
|
||||
}
|
||||
|
||||
void NetworkService::setWirelessEnabled(bool enabled) {
|
||||
if (enabled != m_state.wirelessEnabled) {
|
||||
m_pendingLocalWirelessEnabled = enabled;
|
||||
}
|
||||
try {
|
||||
m_nm->setProperty("WirelessEnabled").onInterface(k_nmInterface).toValue(enabled);
|
||||
} catch (const sdbus::Error& e) {
|
||||
if (m_pendingLocalWirelessEnabled == enabled) {
|
||||
m_pendingLocalWirelessEnabled.reset();
|
||||
}
|
||||
kLog.warn("WirelessEnabled write failed: {}", e.what());
|
||||
}
|
||||
}
|
||||
@@ -727,12 +736,24 @@ NetworkState NetworkService::readState() {
|
||||
return next;
|
||||
}
|
||||
|
||||
NetworkChangeOrigin NetworkService::consumeWirelessEnabledChangeOrigin(bool enabled) {
|
||||
if (!m_pendingLocalWirelessEnabled.has_value()) {
|
||||
return NetworkChangeOrigin::External;
|
||||
}
|
||||
const bool matchesLocalRequest = *m_pendingLocalWirelessEnabled == enabled;
|
||||
m_pendingLocalWirelessEnabled.reset();
|
||||
return matchesLocalRequest ? NetworkChangeOrigin::Noctalia : NetworkChangeOrigin::External;
|
||||
}
|
||||
|
||||
void NetworkService::emitChangedIfNeeded(NetworkState next) {
|
||||
if (next == m_state) {
|
||||
return;
|
||||
}
|
||||
const bool wirelessEnabledChanged = next.wirelessEnabled != m_state.wirelessEnabled;
|
||||
const NetworkChangeOrigin origin =
|
||||
wirelessEnabledChanged ? consumeWirelessEnabledChangeOrigin(next.wirelessEnabled) : NetworkChangeOrigin::External;
|
||||
m_state = std::move(next);
|
||||
if (m_changeCallback) {
|
||||
m_changeCallback(m_state);
|
||||
m_changeCallback(m_state, origin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -44,9 +45,14 @@ struct NetworkState {
|
||||
bool operator==(const NetworkState&) const = default;
|
||||
};
|
||||
|
||||
enum class NetworkChangeOrigin : std::uint8_t {
|
||||
External,
|
||||
Noctalia,
|
||||
};
|
||||
|
||||
class NetworkService {
|
||||
public:
|
||||
using ChangeCallback = std::function<void(const NetworkState&)>;
|
||||
using ChangeCallback = std::function<void(const NetworkState&, NetworkChangeOrigin)>;
|
||||
|
||||
explicit NetworkService(SystemBus& bus);
|
||||
~NetworkService();
|
||||
@@ -93,6 +99,7 @@ private:
|
||||
void rebindActiveAccessPoint(const std::string& apPath);
|
||||
void ensureWifiDeviceSubscribed(const std::string& devicePath);
|
||||
[[nodiscard]] NetworkState readState();
|
||||
[[nodiscard]] NetworkChangeOrigin consumeWirelessEnabledChangeOrigin(bool enabled);
|
||||
void emitChangedIfNeeded(NetworkState next);
|
||||
|
||||
SystemBus& m_bus;
|
||||
@@ -109,5 +116,6 @@ private:
|
||||
std::vector<std::string> m_savedSsids;
|
||||
bool m_scanning = false;
|
||||
std::int64_t m_scanBaselineLastScan = 0;
|
||||
std::optional<bool> m_pendingLocalWirelessEnabled;
|
||||
ChangeCallback m_changeCallback;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user