1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-04-19 19:34:24 +02:00

feat(networkmanager): add more info to wifi tooltip

I was aiming to make it more customizable, but there is currently no
support for custom tooltip formatting with module dependent variables.
This commit is contained in:
Rodrigo Batista de Moraes 2024-07-13 23:38:22 -03:00
parent 5c19032e8b
commit f74f550db9
3 changed files with 58 additions and 6 deletions

View file

@ -1,3 +1,5 @@
use std::collections::HashMap;
use color_eyre::Result; use color_eyre::Result;
use zbus::dbus_proxy; use zbus::dbus_proxy;
use zbus::zvariant::{ObjectPath, OwnedValue, Str}; use zbus::zvariant::{ObjectPath, OwnedValue, Str};
@ -67,6 +69,12 @@ trait DeviceDbus {
#[dbus_proxy(property)] #[dbus_proxy(property)]
fn state(&self) -> Result<DeviceState>; fn state(&self) -> Result<DeviceState>;
#[dbus_proxy(property)]
fn interface(&self) -> Result<Str>;
#[dbus_proxy(property)]
fn ip4_config(&self) -> Result<ObjectPath>;
} }
#[dbus_proxy( #[dbus_proxy(
@ -89,6 +97,19 @@ trait AccessPointDbus {
#[dbus_proxy(property)] #[dbus_proxy(property)]
fn strength(&self) -> Result<u8>; fn strength(&self) -> Result<u8>;
#[dbus_proxy(property)]
fn hw_address(&self) -> Result<Str>;
}
// based on code generated by `zbus-xmlgen system org.freedesktop.NetworkManager /org/freedesktop/NetworkManager/AccessPoint/1`
#[dbus_proxy(
default_service = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.IP4Config"
)]
trait Ip4ConfigDbus {
#[dbus_proxy(property)]
fn address_data(&self) -> Result<Vec<HashMap<String, OwnedValue>>>;
} }
#[derive(Clone, Debug, OwnedValue, PartialEq)] #[derive(Clone, Debug, OwnedValue, PartialEq)]

View file

@ -1,8 +1,8 @@
use color_eyre::Result; use color_eyre::{Report, Result};
use crate::clients::networkmanager::dbus::{ use crate::clients::networkmanager::dbus::{
AccessPointDbusProxyBlocking, ActiveConnectionDbusProxyBlocking, DeviceDbusProxyBlocking, AccessPointDbusProxyBlocking, ActiveConnectionDbusProxyBlocking, DeviceDbusProxyBlocking,
DeviceState, DeviceType, DeviceWirelessDbusProxyBlocking, DeviceState, DeviceType, DeviceWirelessDbusProxyBlocking, Ip4ConfigDbusProxyBlocking,
}; };
use crate::clients::networkmanager::PathMap; use crate::clients::networkmanager::PathMap;
@ -33,9 +33,16 @@ pub enum WifiState {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct WifiConnectedState { pub struct WifiConnectedState {
/// The SSID of the access point.
pub ssid: String, pub ssid: String,
/// The MAC address of the access point.
pub bssid: String,
/// Strength in percentage, from 0 to 100. /// Strength in percentage, from 0 to 100.
pub strength: u8, pub strength: u8,
/// The IPv4 address.
pub ip4_address: String,
/// The IPv4 prefix, in bits (also known as the subnet mask length).
pub ip4_prefix: u32,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -103,24 +110,47 @@ pub(super) fn determine_wifi_state(
.build()?; .build()?;
let primary_access_point_path = wireless_device.active_access_point()?; let primary_access_point_path = wireless_device.active_access_point()?;
if primary_access_point_path.as_str() != "/" { if primary_access_point_path.as_str() != "/" {
connected = Some( connected = Some((
device,
AccessPointDbusProxyBlocking::builder(dbus_connection) AccessPointDbusProxyBlocking::builder(dbus_connection)
.path(primary_access_point_path)? .path(primary_access_point_path)?
.build()?, .build()?,
); ));
break; break;
} }
} }
} }
} }
if let Some(access_point) = connected { if let Some((device, access_point)) = connected {
let ssid = access_point let ssid = access_point
.ssid() .ssid()
.map(|x| String::from_utf8_lossy(&x).to_string()) .map(|x| String::from_utf8_lossy(&x).to_string())
.unwrap_or_else(|_| "unkown".into()); .unwrap_or_else(|_| "unkown".into());
let bssid = access_point.hw_address()?.to_string();
let ip4config = Ip4ConfigDbusProxyBlocking::builder(dbus_connection)
.path(device.ip4_config()?.clone())?
.build()?;
let address_data = ip4config.address_data()?;
// pick the first address. not sure if there are cases when there are more than one address
// (at least for wifi).
let address = &address_data
.iter()
.next()
.ok_or_else(|| Report::msg("No address in IP4Config"))?;
let ip4_address = address
.get("address")
.ok_or_else(|| Report::msg("IP address data object must have a address"))?;
let ip4_prefix = address
.get("prefix")
.ok_or_else(|| Report::msg("IP address data object must have a prefix"))?;
Ok(WifiState::Connected(WifiConnectedState { Ok(WifiState::Connected(WifiConnectedState {
ssid, ssid,
bssid,
ip4_address: String::try_from(ip4_address.to_owned()).unwrap_or_default(),
ip4_prefix: u32::try_from(ip4_prefix.to_owned()).unwrap_or_default(),
strength: access_point.strength().unwrap_or(0), strength: access_point.strength().unwrap_or(0),
})) }))
} else if enabled { } else if enabled {

View file

@ -112,7 +112,8 @@ impl Module<GtkBox> for NetworkManagerModule {
match &state.wifi { match &state.wifi {
WifiState::Connected(state) => { WifiState::Connected(state) => {
wifi_icon.set_tooltip_text(Some(&state.ssid)); let tooltip = format!("{}\n{}/{}", state.ssid, state.ip4_address, state.ip4_prefix);
wifi_icon.set_tooltip_text(Some(&tooltip));
}, },
_ => { _ => {
wifi_icon.set_tooltip_text(None); wifi_icon.set_tooltip_text(None);