From 4788031f5f56872e7138c52602a24ae3b6ee55c2 Mon Sep 17 00:00:00 2001 From: Reinout Meliesie Date: Sun, 30 Jun 2024 18:25:24 +0200 Subject: [PATCH 1/4] fix: revert inclusion of networkmanager module --- docs/modules/Networkmanager.md | 74 ----------------- src/clients/mod.rs | 16 ---- src/clients/networkmanager.rs | 148 --------------------------------- src/config/mod.rs | 6 -- src/modules/mod.rs | 2 - src/modules/networkmanager.rs | 87 ------------------- 6 files changed, 333 deletions(-) delete mode 100644 docs/modules/Networkmanager.md delete mode 100644 src/clients/networkmanager.rs delete mode 100644 src/modules/networkmanager.rs diff --git a/docs/modules/Networkmanager.md b/docs/modules/Networkmanager.md deleted file mode 100644 index ec3a8fd..0000000 --- a/docs/modules/Networkmanager.md +++ /dev/null @@ -1,74 +0,0 @@ -Displays the current network connection state of NetworkManager. -Supports wired ethernet, wifi, cellular data and VPN connections among others. - -> [!NOTE] -> This module uses NetworkManager's so-called primary connection, and therefore inherits its limitation of only being able to display the "top-level" connection. -> For example, if we have a VPN connection over a wifi connection it will only display the former, until it is disconnected, at which point it will display the latter. -> A solution to this is currently in the works. - -## Configuration - -> Type: `networkmanager` - -| Name | Type | Default | Description | -|-------------|-----------|---------|-------------------------| -| `icon_size` | `integer` | `24` | Size to render icon at. | - -
- JSON - - ```json - { - "end": [ - { - "type": "networkmanager", - "icon_size": 32 - } - ] - } - ``` -
- -
- TOML - - ```toml - [[end]] - type = "networkmanager" - icon_size = 32 - ``` -
- -
- YAML - - ```yaml - end: - - type: "networkmanager" - icon_size: 32 - ``` -
- -
- Corn - - ```corn - { - end = [ - { - type = "networkmanager" - icon_size = 32 - } - ] - } - ``` -
- -## Styling - -| Selector | Description | -|------------------------|----------------------------------| -| `.networkmanager` | NetworkManager widget container. | -| `.networkmanger .icon` | NetworkManager widget icon. | - -For more information on styling, please see the [styling guide](styling-guide). diff --git a/src/clients/mod.rs b/src/clients/mod.rs index d286bdb..b44f0df 100644 --- a/src/clients/mod.rs +++ b/src/clients/mod.rs @@ -12,8 +12,6 @@ pub mod compositor; pub mod lua; #[cfg(feature = "music")] pub mod music; -#[cfg(feature = "networkmanager")] -pub mod networkmanager; #[cfg(feature = "notifications")] pub mod swaync; #[cfg(feature = "tray")] @@ -37,8 +35,6 @@ pub struct Clients { lua: Option>, #[cfg(feature = "music")] music: std::collections::HashMap>, - #[cfg(feature = "networkmanager")] - networkmanager: Option>, #[cfg(feature = "notifications")] notifications: Option>, #[cfg(feature = "tray")] @@ -100,18 +96,6 @@ impl Clients { .clone() } - #[cfg(feature = "networkmanager")] - pub fn networkmanager(&mut self) -> ClientResult { - match &self.networkmanager { - Some(client) => Ok(client.clone()), - None => { - let client = networkmanager::create_client()?; - self.networkmanager = Some(client.clone()); - Ok(client) - } - } - } - #[cfg(feature = "notifications")] pub fn notifications(&mut self) -> ClientResult { let client = match &self.notifications { diff --git a/src/clients/networkmanager.rs b/src/clients/networkmanager.rs deleted file mode 100644 index a1b760f..0000000 --- a/src/clients/networkmanager.rs +++ /dev/null @@ -1,148 +0,0 @@ -use std::sync::Arc; - -use color_eyre::Result; -use futures_signals::signal::{Mutable, MutableSignalCloned}; -use tracing::error; -use zbus::{ - blocking::{fdo::PropertiesProxy, Connection}, - names::InterfaceName, - zvariant::{Error as ZVariantError, ObjectPath, Str}, - Error as ZBusError, -}; - -use crate::{register_fallible_client, spawn_blocking}; - -static DBUS_BUS: &str = "org.freedesktop.NetworkManager"; -static DBUS_PATH: &str = "/org/freedesktop/NetworkManager"; -static DBUS_INTERFACE: &str = "org.freedesktop.NetworkManager"; - -#[derive(Debug)] -pub struct Client { - client_state: Mutable, - interface_name: InterfaceName<'static>, - props_proxy: PropertiesProxy<'static>, -} - -#[derive(Clone, Debug)] -pub enum ClientState { - WiredConnected, - WifiConnected, - CellularConnected, - VpnConnected, - WifiDisconnected, - Offline, - Unknown, -} - -impl Client { - fn new() -> Result { - let client_state = Mutable::new(ClientState::Unknown); - let dbus_connection = Connection::system()?; - let props_proxy = PropertiesProxy::builder(&dbus_connection) - .destination(DBUS_BUS)? - .path(DBUS_PATH)? - .build()?; - let interface_name = InterfaceName::from_static_str(DBUS_INTERFACE)?; - - Ok(Self { - client_state, - interface_name, - props_proxy, - }) - } - - fn run(&self) -> Result<()> { - let props = self.props_proxy.get_all(self.interface_name.clone())?; - let mut primary_connection = props["PrimaryConnection"] - .downcast_ref::() - .ok_or(ZBusError::Variant(ZVariantError::IncorrectType))? - .to_string(); - let mut primary_connection_type = props["PrimaryConnectionType"] - .downcast_ref::() - .ok_or(ZBusError::Variant(ZVariantError::IncorrectType))? - .to_string(); - let mut wireless_enabled = *props["WirelessEnabled"] - .downcast_ref::() - .ok_or(ZBusError::Variant(ZVariantError::IncorrectType))?; - self.client_state.set(determine_state( - &primary_connection, - &primary_connection_type, - wireless_enabled, - )); - - let changed_props_stream = self.props_proxy.receive_properties_changed()?; - for signal in changed_props_stream { - let args = signal.args()?; - if args.interface_name != self.interface_name { - continue; - } - let changed_props = args.changed_properties; - if let Some(new_primary_connection) = changed_props.get("PrimaryConnection") { - let new_primary_connection = new_primary_connection - .downcast_ref::() - .ok_or(ZBusError::Variant(ZVariantError::IncorrectType))?; - primary_connection = new_primary_connection.to_string(); - } - if let Some(new_primary_connection_type) = changed_props.get("PrimaryConnectionType") { - let new_primary_connection_type = new_primary_connection_type - .downcast_ref::() - .ok_or(ZBusError::Variant(ZVariantError::IncorrectType))?; - primary_connection_type = new_primary_connection_type.to_string(); - } - if let Some(new_wireless_enabled) = changed_props.get("WirelessEnabled") { - let new_wireless_enabled = new_wireless_enabled - .downcast_ref::() - .ok_or(ZBusError::Variant(ZVariantError::IncorrectType))?; - wireless_enabled = *new_wireless_enabled; - } - self.client_state.set(determine_state( - &primary_connection, - &primary_connection_type, - wireless_enabled, - )); - } - - Ok(()) - } - - pub fn subscribe(&self) -> MutableSignalCloned { - self.client_state.signal_cloned() - } -} - -pub fn create_client() -> Result> { - let client = Arc::new(Client::new()?); - { - let client = client.clone(); - spawn_blocking(move || { - if let Err(error) = client.run() { - error!("{}", error); - }; - }); - } - Ok(client) -} - -fn determine_state( - primary_connection: &str, - primary_connection_type: &str, - wireless_enabled: bool, -) -> ClientState { - if primary_connection == "/" { - if wireless_enabled { - ClientState::WifiDisconnected - } else { - ClientState::Offline - } - } else { - match primary_connection_type { - "802-3-ethernet" | "adsl" | "pppoe" => ClientState::WiredConnected, - "802-11-olpc-mesh" | "802-11-wireless" | "wifi-p2p" => ClientState::WifiConnected, - "cdma" | "gsm" | "wimax" => ClientState::CellularConnected, - "vpn" | "wireguard" => ClientState::VpnConnected, - _ => ClientState::Unknown, - } - } -} - -register_fallible_client!(Client, networkmanager); diff --git a/src/config/mod.rs b/src/config/mod.rs index 12b7164..e277bac 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -16,8 +16,6 @@ use crate::modules::label::LabelModule; use crate::modules::launcher::LauncherModule; #[cfg(feature = "music")] use crate::modules::music::MusicModule; -#[cfg(feature = "networkmanager")] -use crate::modules::networkmanager::NetworkManagerModule; #[cfg(feature = "notifications")] use crate::modules::notifications::NotificationsModule; use crate::modules::script::ScriptModule; @@ -62,8 +60,6 @@ pub enum ModuleConfig { Launcher(Box), #[cfg(feature = "music")] Music(Box), - #[cfg(feature = "networkmanager")] - NetworkManager(Box), #[cfg(feature = "notifications")] Notifications(Box), Script(Box), @@ -107,8 +103,6 @@ impl ModuleConfig { Self::Launcher(module) => create!(module), #[cfg(feature = "music")] Self::Music(module) => create!(module), - #[cfg(feature = "networkmanager")] - Self::NetworkManager(module) => create!(module), #[cfg(feature = "notifications")] Self::Notifications(module) => create!(module), Self::Script(module) => create!(module), diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 98e272d..2a15252 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -36,8 +36,6 @@ pub mod label; pub mod launcher; #[cfg(feature = "music")] pub mod music; -#[cfg(feature = "networkmanager")] -pub mod networkmanager; #[cfg(feature = "notifications")] pub mod notifications; pub mod script; diff --git a/src/modules/networkmanager.rs b/src/modules/networkmanager.rs deleted file mode 100644 index 972fccb..0000000 --- a/src/modules/networkmanager.rs +++ /dev/null @@ -1,87 +0,0 @@ -use color_eyre::Result; -use futures_lite::StreamExt; -use futures_signals::signal::SignalExt; -use gtk::prelude::ContainerExt; -use gtk::{Box, Image, Orientation}; -use serde::Deserialize; -use tokio::sync::mpsc::Receiver; - -use crate::clients::networkmanager::{Client, ClientState}; -use crate::config::CommonConfig; -use crate::gtk_helpers::IronbarGtkExt; -use crate::image::ImageProvider; -use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext}; -use crate::{glib_recv, module_impl, send_async, spawn}; - -#[derive(Debug, Deserialize, Clone)] -pub struct NetworkManagerModule { - #[serde(default = "default_icon_size")] - icon_size: i32, - - #[serde(flatten)] - pub common: Option, -} - -const fn default_icon_size() -> i32 { - 24 -} - -impl Module for NetworkManagerModule { - type SendMessage = ClientState; - type ReceiveMessage = (); - - fn spawn_controller( - &self, - _: &ModuleInfo, - context: &WidgetContext, - _: Receiver<()>, - ) -> Result<()> { - let client = context.try_client::()?; - let mut client_signal = client.subscribe().to_stream(); - let widget_transmitter = context.tx.clone(); - - spawn(async move { - while let Some(state) = client_signal.next().await { - send_async!(widget_transmitter, ModuleUpdateEvent::Update(state)); - } - }); - - Ok(()) - } - - fn into_widget( - self, - context: WidgetContext, - info: &ModuleInfo, - ) -> Result> { - let container = Box::new(Orientation::Horizontal, 0); - let icon = Image::new(); - icon.add_class("icon"); - container.add(&icon); - - let icon_theme = info.icon_theme.clone(); - - let initial_icon_name = "content-loading-symbolic"; - ImageProvider::parse(initial_icon_name, &icon_theme, false, self.icon_size) - .map(|provider| provider.load_into_image(icon.clone())); - - let widget_receiver = context.subscribe(); - glib_recv!(widget_receiver, state => { - let icon_name = match state { - ClientState::WiredConnected => "network-wired-symbolic", - ClientState::WifiConnected => "network-wireless-symbolic", - ClientState::CellularConnected => "network-cellular-symbolic", - ClientState::VpnConnected => "network-vpn-symbolic", - ClientState::WifiDisconnected => "network-wireless-acquiring-symbolic", - ClientState::Offline => "network-wireless-disabled-symbolic", - ClientState::Unknown => "dialog-question-symbolic", - }; - ImageProvider::parse(icon_name, &icon_theme, false, self.icon_size) - .map(|provider| provider.load_into_image(icon.clone())); - }); - - Ok(ModuleParts::new(container, None)) - } - - module_impl!("networkmanager"); -} From 33c69241b797837afd851c73f25855abaa0f6dfe Mon Sep 17 00:00:00 2001 From: Reinout Meliesie Date: Sun, 30 Jun 2024 18:28:50 +0200 Subject: [PATCH 2/4] fix: revert inclusion of networkmanager module, part 2 --- Cargo.lock | 44 -------------------------------------------- Cargo.toml | 10 ++-------- 2 files changed, 2 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf81ffb..0db173a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -740,12 +740,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "dlib" version = "0.5.2" @@ -1012,22 +1006,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "futures-signals" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b175f2f6600dd81d92d20cf10872b03ea9df6b2513ca7f672341260dacb1ab2" -dependencies = [ - "discard", - "futures-channel", - "futures-core", - "futures-util", - "gensym", - "log", - "pin-project", - "serde", -] - [[package]] name = "futures-sink" version = "0.3.30" @@ -1126,18 +1104,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "gensym" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "913dce4c5f06c2ea40fc178c06f777ac89fc6b1383e90c254fafb1abe4ba3c82" -dependencies = [ - "proc-macro2", - "quote 1.0.35", - "syn 2.0.48", - "uuid", -] - [[package]] name = "getrandom" version = "0.2.9" @@ -1648,7 +1614,6 @@ dependencies = [ "ctrlc", "dirs", "futures-lite 2.3.0", - "futures-signals", "futures-util", "glib", "gtk", @@ -3600,15 +3565,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "uuid" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" -dependencies = [ - "getrandom", -] - [[package]] name = "valuable" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index a29150b..6be1241 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ default = [ "ipc", "launcher", "music+all", - "networkmanager", "notifications", "sys_info", "tray", @@ -62,8 +61,6 @@ music = ["regex"] "music+mpris" = ["music", "mpris"] "music+mpd" = ["music", "mpd-utils"] -networkmanager = ["futures-lite", "futures-signals", "zbus"] - notifications = ["zbus"] sys_info = ["sysinfo", "regex"] @@ -139,9 +136,6 @@ chrono = { version = "0.4.38", optional = true, default-features = false, featur mpd-utils = { version = "0.2.1", optional = true } mpris = { version = "2.0.1", optional = true } -# networkmanager -futures-signals = { version = "0.3.33", optional = true } - # sys_info sysinfo = { version = "0.29.11", optional = true } @@ -160,11 +154,11 @@ hyprland = { version = "0.4.0-alpha.2", features = ["silent"], optional = true } futures-util = { version = "0.3.30", optional = true } # shared -futures-lite = { version = "2.3.0", optional = true } # networkmanager, upower, workspaces +futures-lite = { version = "2.3.0", optional = true } # workspaces, upower regex = { version = "1.10.5", default-features = false, features = [ "std", ], optional = true } # music, sys_info -zbus = { version = "3.15.2", default-features = false, features = ["tokio"], optional = true } # networkmanager, notifications, upower +zbus = { version = "3.15.2", default-features = false, features = ["tokio"], optional = true } # notifications, upower # schema schemars = { version = "0.8.21", optional = true } From 081678464afd3bc8c280af1ed9496fe293ccd974 Mon Sep 17 00:00:00 2001 From: Reinout Meliesie Date: Mon, 5 Aug 2024 14:27:10 +0200 Subject: [PATCH 3/4] refactor: partially re-add text label support to volume module --- src/modules/volume.rs | 113 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 97 insertions(+), 16 deletions(-) diff --git a/src/modules/volume.rs b/src/modules/volume.rs index 54c536e..3c454ad 100644 --- a/src/modules/volume.rs +++ b/src/modules/volume.rs @@ -1,3 +1,12 @@ +use std::collections::HashMap; + +use glib::Propagation; +use gtk::pango::EllipsizeMode; +use gtk::prelude::*; +use gtk::{Button, CellRendererText, ComboBoxText, Image, Label, Orientation, Scale, ToggleButton}; +use serde::Deserialize; +use tokio::sync::mpsc; + use crate::clients::volume::{self, Event}; use crate::config::CommonConfig; use crate::gtk_helpers::IronbarGtkExt; @@ -6,20 +15,17 @@ use crate::modules::{ Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext, }; use crate::{glib_recv, lock, module_impl, send_async, spawn, try_send}; -use glib::Propagation; -use gtk::pango::EllipsizeMode; -use gtk::prelude::*; -use gtk::{ - Box as GtkBox, Button, CellRendererText, ComboBoxText, Image, Label, Orientation, Scale, - ToggleButton, -}; -use serde::Deserialize; -use std::collections::HashMap; -use tokio::sync::mpsc; #[derive(Debug, Clone, Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct VolumeModule { + /// The format string to use for the widget button label. + /// For available tokens, see [below](#formatting-tokens). + /// + /// **Default**: `{icon} {percentage}%` + #[serde(default = "default_format")] + format: String, + /// Maximum value to allow volume sliders to reach. /// Pulse supports values > 100 but this may result in distortion. /// @@ -27,6 +33,12 @@ pub struct VolumeModule { #[serde(default = "default_max_volume")] max_volume: f64, + /// Volume state icons. + /// + /// See [icons](#icons). + #[serde(default)] + icons: Icons, + #[serde(default = "default_icon_size")] icon_size: i32, @@ -35,10 +47,79 @@ pub struct VolumeModule { pub common: Option, } +fn default_format() -> String { + String::from("{icon} {percentage}%") +} + +#[derive(Debug, Clone, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +pub struct Icons { + /// Icon to show for high volume levels. + /// + /// **Default**: `󰕾` + #[serde(default = "default_icon_volume_high")] + volume_high: String, + + /// Icon to show for medium volume levels. + /// + /// **Default**: `󰖀` + #[serde(default = "default_icon_volume_medium")] + volume_medium: String, + + /// Icon to show for low volume levels. + /// + /// **Default**: `󰕿` + #[serde(default = "default_icon_volume_low")] + volume_low: String, + + /// Icon to show for muted outputs. + /// + /// **Default**: `󰝟` + #[serde(default = "default_icon_muted")] + muted: String, +} + +impl Icons { + fn volume_icon(&self, volume_percent: f64) -> &str { + match volume_percent as u32 { + 0..=33 => &self.volume_low, + 34..=66 => &self.volume_medium, + 67.. => &self.volume_high, + } + } +} + +impl Default for Icons { + fn default() -> Self { + Self { + volume_high: default_icon_volume_high(), + volume_medium: default_icon_volume_medium(), + volume_low: default_icon_volume_low(), + muted: default_icon_muted(), + } + } +} + const fn default_max_volume() -> f64 { 100.0 } +fn default_icon_volume_high() -> String { + String::from("󰕾") +} + +fn default_icon_volume_medium() -> String { + String::from("󰖀") +} + +fn default_icon_volume_low() -> String { + String::from("󰕿") +} + +fn default_icon_muted() -> String { + String::from("󰝟") +} + const fn default_icon_size() -> i32 { 24 } @@ -182,16 +263,16 @@ impl Module