Add VPN support to network widget with shield-check icon display

- Enumerate VPN profiles from NetworkManager (vpn and wireguard types)
- Detect active VPN connections and display shield-check icon in bar widget
- Check both primary connection and VPN profile list for active VPNs
- Properly set connected state for all connection types
- Register shield-check glyph for VPN indicator
This commit is contained in:
Mathew-D
2026-05-09 12:46:21 -04:00
parent 839257fe2d
commit 87e22607a6
3 changed files with 26 additions and 5 deletions
+24 -5
View File
@@ -99,6 +99,9 @@ namespace {
} // namespace
const char* NetworkService::glyphForState(const NetworkState& state) noexcept {
if (state.vpnActive) {
return "shield-check";
}
if (state.kind == NetworkConnectivity::Wired) {
return state.connected ? "ethernet" : "ethernet-off";
}
@@ -924,6 +927,27 @@ NetworkState NetworkService::readState() {
next.wirelessEnabled = getPropertyOr<bool>(*m_nm, k_nmInterface, "WirelessEnabled", false);
next.scanning = m_scanning;
next.vpnActive = false;
// Check primary connection: detect VPN type and connection state
if (m_activeConnection != nullptr) {
const auto type =
getPropertyOr<std::string>(*m_activeConnection, k_nmActiveConnectionInterface, "Type", std::string{});
next.vpnActive = (type == "vpn" || type == "wireguard");
const auto state = getPropertyOr<std::uint32_t>(*m_activeConnection, k_nmActiveConnectionInterface, "State", 0U);
next.connected = state == k_nmActiveConnectionStateActivated;
}
// Also check if any VPN profile is active (in case it's not the primary connection)
if (!next.vpnActive) {
for (const auto& vpn : m_vpnConnections) {
if (vpn.active) {
next.vpnActive = true;
next.connected = true;
break;
}
}
}
if (m_activeDevice == nullptr) {
return next;
@@ -936,11 +960,6 @@ NetworkState NetworkService::readState() {
getPropertyOr<sdbus::ObjectPath>(*m_activeDevice, k_nmDeviceInterface, "Ip4Config", sdbus::ObjectPath{});
next.ipv4 = firstIpv4FromConfig(m_bus.connection(), ip4ConfigPath);
if (m_activeConnection != nullptr) {
const auto state = getPropertyOr<std::uint32_t>(*m_activeConnection, k_nmActiveConnectionInterface, "State", 0U);
next.connected = state == k_nmActiveConnectionStateActivated;
}
if (deviceType == k_nmDeviceTypeWifi) {
next.kind = NetworkConnectivity::Wireless;
if (m_activeAp != nullptr) {
+1
View File
@@ -45,6 +45,7 @@ struct NetworkState {
bool connected = false;
bool wirelessEnabled = false;
bool scanning = false;
bool vpnActive = false; // true if a VPN is the active connection
std::string ssid; // Wi-Fi only
std::string ipv4; // dotted-quad of first address; empty if none
std::string interfaceName; // e.g. "wlan0", "eth0"
+1
View File
@@ -191,6 +191,7 @@ const std::unordered_map<std::string, char32_t> kIcons = {
{"ethernet-off", 0xECCD},
{"ethernet-exclamation", 0xECCE},
{"ethernet-question", 0xECCF},
{"shield-check", 0xEB22},
// Bluetooth devices
{"bluetooth", 0xEA37},