1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2026-01-11 05:26:43 +01:00

Compare commits

..

48 commits

Author SHA1 Message Date
54e91facd3
Remove unused parts of pulseaudio module 2025-08-20 20:51:36 +02:00
d1f433c990
refactor(networkmanager): remove now unused state.rs 2025-08-20 19:56:39 +02:00
f4369b20d3
refactor(networkmanager): implement clippy::pedantic suggestions 2025-08-20 18:49:20 +02:00
92a1b3455d
Merge branch 'master' into develop
# Conflicts:
#	Cargo.toml
2025-08-20 18:04:33 +02:00
c7e002ee6c
Merge pull request #1107 from JakeStanger/dependabot/cargo/serde_json-1.0.142
build(deps): bump serde_json from 1.0.141 to 1.0.142
2025-08-06 09:49:47 +01:00
a2e72bcdde
Merge pull request #1106 from JakeStanger/dependabot/cargo/wayland-protocols-wlr-0.3.9
build(deps): bump wayland-protocols-wlr from 0.3.8 to 0.3.9
2025-08-06 09:49:36 +01:00
ef26554434
Merge pull request #1093 from slowsage/wmclass-async
fix(launcher): improve app ID handling: fallback for desktop entries.…
2025-08-05 15:10:07 +01:00
dependabot[bot]
ca77a991f7
build(deps): bump serde_json from 1.0.141 to 1.0.142
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.141 to 1.0.142.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.141...v1.0.142)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-version: 1.0.142
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-05 08:12:55 +00:00
dependabot[bot]
279ef938d1
build(deps): bump wayland-protocols-wlr from 0.3.8 to 0.3.9
Bumps [wayland-protocols-wlr](https://github.com/smithay/wayland-rs) from 0.3.8 to 0.3.9.
- [Release notes](https://github.com/smithay/wayland-rs/releases)
- [Changelog](https://github.com/Smithay/wayland-rs/blob/master/historical_changelog.md)
- [Commits](https://github.com/smithay/wayland-rs/commits)

---
updated-dependencies:
- dependency-name: wayland-protocols-wlr
  dependency-version: 0.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-05 08:12:51 +00:00
24ef1b700a
Merge pull request #1105 from JakeStanger/dependabot/cargo/clap-4.5.42
build(deps): bump clap from 4.5.41 to 4.5.42
2025-08-05 09:10:45 +01:00
b7557bc78b
Merge pull request #1104 from JakeStanger/dependabot/cargo/tokio-1.47.1
build(deps): bump tokio from 1.46.1 to 1.47.1
2025-08-05 09:10:18 +01:00
037de421cd
Merge pull request #1103 from JakeStanger/dependabot/cargo/notify-8.2.0
build(deps): bump notify from 8.1.0 to 8.2.0
2025-08-05 09:09:59 +01:00
dependabot[bot]
4041e080d0
build(deps): bump clap from 4.5.41 to 4.5.42
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.41 to 4.5.42.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.41...clap_complete-v4.5.42)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.42
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-04 18:51:20 +00:00
dependabot[bot]
491e055aa1
build(deps): bump tokio from 1.46.1 to 1.47.1
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.46.1 to 1.47.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.46.1...tokio-1.47.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.47.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-04 18:35:36 +00:00
dependabot[bot]
304b1d3e17
build(deps): bump notify from 8.1.0 to 8.2.0
Bumps [notify](https://github.com/notify-rs/notify) from 8.1.0 to 8.2.0.
- [Release notes](https://github.com/notify-rs/notify/releases)
- [Changelog](https://github.com/notify-rs/notify/blob/main/CHANGELOG.md)
- [Commits](https://github.com/notify-rs/notify/compare/notify-8.1.0...notify-8.2.0)

---
updated-dependencies:
- dependency-name: notify
  dependency-version: 8.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-04 18:13:45 +00:00
slowsage
0159c0155e fix: app_id StartupWMClass resolution in launcher 2025-08-03 16:22:06 -04:00
dea571506f
Merge pull request #1101 from JakeStanger/update_flake_lock_action
Update flake.lock
2025-08-01 08:42:25 +01:00
github-actions[bot]
bd5745f2ef flake.lock: Update
Flake lock file updates:

• Updated input 'naersk':
    'github:nix-community/naersk/38bc60bbc157ae266d4a0c96671c6c742ee17a5f?narHash=sha256-cyAAMal0aPrlb1NgzMxZqeN1mAJ2pJseDhm2m6Um8T0%3D' (2025-04-29)
  → 'github:nix-community/naersk/0e72363d0938b0208d6c646d10649164c43f4d64?narHash=sha256-uldUBFkZe/E7qbvxa3mH1ItrWZyT6w1dBKJQF/3ZSsc%3D' (2025-07-16)
• Added input 'naersk/fenix':
    'github:nix-community/fenix/bf0d6f70f4c9a9cf8845f992105652173f4b617f?narHash=sha256-z6QEu4ZFuHiqdOPbYss4/Q8B0BFhacR8ts6jO/F/aOU%3D' (2025-07-14)
• Added input 'naersk/fenix/nixpkgs':
    follows 'naersk/nixpkgs'
• Added input 'naersk/fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/591e3b7624be97e4443ea7b5542c191311aa141d?narHash=sha256-EJcdxw3aXfP8Ex1Nm3s0awyH9egQvB2Gu%2BQEnJn2Sfg%3D' (2025-07-13)
• Updated input 'naersk/nixpkgs':
    'github:NixOS/nixpkgs/b95255df2360a45ddbb03817a68869d5cb01bf96?narHash=sha256-IJWIzZSkBsDzS7iS/iwSwur%2BxFkWqeLYC4kdf8ObtOM%3D' (2025-06-30)
  → 'github:NixOS/nixpkgs/be9e214982e20b8310878ac2baa063a961c1bdf6?narHash=sha256-HM791ZQtXV93xtCY%2BZxG1REzhQenSQO020cu6rHtAPk%3D' (2025-07-09)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/30e2e2857ba47844aa71991daa6ed1fc678bcbb7?narHash=sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM%3D' (2025-06-27)
  → 'github:nixos/nixpkgs/dc9637876d0dcc8c9e5e22986b857632effeb727?narHash=sha256-cKgvtz6fKuK1Xr5LQW/zOUiAC0oSQoA9nOISB0pJZqM%3D' (2025-07-28)
2025-08-01 00:20:13 +00:00
106e23e311
Merge pull request #1096 from JakeStanger/dependabot/cargo/serde_json-1.0.141
build(deps): bump serde_json from 1.0.140 to 1.0.141
2025-07-21 16:52:44 +01:00
546e75c43c
Merge pull request #1099 from JakeStanger/dependabot/cargo/zbus-5.9.0
build(deps): bump zbus from 5.8.0 to 5.9.0
2025-07-21 16:47:56 +01:00
50ab48500f
Merge pull request #1097 from JakeStanger/dependabot/cargo/mlua-0.11.1
build(deps): bump mlua from 0.11.0 to 0.11.1
2025-07-21 16:45:11 +01:00
798a71cc13
Merge pull request #1098 from JakeStanger/dependabot/cargo/sysinfo-0.36.1
build(deps): bump sysinfo from 0.36.0 to 0.36.1
2025-07-21 16:44:59 +01:00
dependabot[bot]
dca0e07ce2
build(deps): bump serde_json from 1.0.140 to 1.0.141
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.140 to 1.0.141.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.140...v1.0.141)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-version: 1.0.141
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 15:42:30 +00:00
dependabot[bot]
8c9673eb1f
build(deps): bump zbus from 5.8.0 to 5.9.0
Bumps [zbus](https://github.com/dbus2/zbus) from 5.8.0 to 5.9.0.
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zbus-5.8.0...zbus-5.9.0)

---
updated-dependencies:
- dependency-name: zbus
  dependency-version: 5.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 15:35:25 +00:00
a92e6684a0
Merge pull request #1095 from JakeStanger/dependabot/cargo/rustix-1.0.8
build(deps): bump rustix from 1.0.7 to 1.0.8
2025-07-21 16:35:18 +01:00
dependabot[bot]
eadc7a7bab
build(deps): bump sysinfo from 0.36.0 to 0.36.1
Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.36.0 to 0.36.1.
- [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/GuillaumeGomez/sysinfo/compare/v0.36.0...v0.36.1)

---
updated-dependencies:
- dependency-name: sysinfo
  dependency-version: 0.36.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 15:32:44 +00:00
dependabot[bot]
c3c3dab11b
build(deps): bump mlua from 0.11.0 to 0.11.1
Bumps [mlua](https://github.com/mlua-rs/mlua) from 0.11.0 to 0.11.1.
- [Release notes](https://github.com/mlua-rs/mlua/releases)
- [Changelog](https://github.com/mlua-rs/mlua/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mlua-rs/mlua/compare/v0.11.0...v0.11.1)

---
updated-dependencies:
- dependency-name: mlua
  dependency-version: 0.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 15:29:37 +00:00
dependabot[bot]
dd9a0c2065
build(deps): bump rustix from 1.0.7 to 1.0.8
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 1.0.7 to 1.0.8.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGES.md)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v1.0.7...v1.0.8)

---
updated-dependencies:
- dependency-name: rustix
  dependency-version: 1.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 15:25:58 +00:00
Alan
5520562a18
feat: support glob patterns for keyboard layout icons (#949)
* Simplistic globbing for matching keyboard layout icons

Update the logic for determining the display text for the current keyboard layout.
Instead of a direct map lookup, iterate through the layout map to support wildcard matching.

Patterns ending with `*` will match any language string starting with the characters before the `*`. This allows grouping similar layouts (e.g., `English`, `English (Colemak-DH ISO)`) under a single pattern like `English*`.

* Use `IndexMap` instead of `HashMap` for keyboard layout icons map

This enables users to choose which globs to prioritize via ordering in the config

* Enable feature `serde` for `indexmap`

* Document wildcard matching for keyboard layouts

* Enable `indexmap2` feature flag for `schemars`

* Add missing period

* use string slices

* Fix formatting
2025-07-20 22:19:58 +01:00
233f7f1ee2
Merge pull request #1094 from JakeStanger/fix/launcher-regression
fix: regression caused by #1089
2025-07-20 16:26:33 +01:00
feccc29fd1
fix: regression caused by #1089
This resolves an issue caused by a previous fix which broke launching applications with the `launcher` and `menu` modules
2025-07-20 16:21:31 +01:00
ccb57c8458
Merge pull request #1092 from slowsage/app_id_lowercase
fix(desktop_file): case-insensitive app_id -> desktop_file find
2025-07-19 09:33:56 +01:00
slowsage
ff185d0de9 fix(desktop_file): case-insensitive app_id -> desktop_file find 2025-07-19 04:01:51 -04:00
34da5edfe0
docs(sysinfo): add info on querying values
Resolves #1090
2025-07-15 22:45:49 +01:00
622ca3cc4f
Merge pull request #1089 from JakeStanger/fix/gtk-launch-zombie
fix: opening programs via `launcher` and `menu` leaving zombie processes
2025-07-14 21:45:40 +01:00
40adfaf810
fix: opening programs via launcher and menu leaving zombie processes
Fixes #1020
2025-07-14 21:42:11 +01:00
749b9f0433
Merge pull request #1067 from JakeStanger/fix/ipc-limit
fix(ipc): message size limited to 1024 bytes
2025-07-14 21:10:31 +01:00
c4f5485d53
fix(ipc): message size limited to 1024 bytes
Fixes #1065
2025-07-14 21:06:57 +01:00
a67e722dee
Merge pull request #1088 from JakeStanger/chores
Chores
2025-07-14 20:09:20 +01:00
f1a8b42cfa
chore: clippy/fmt 2025-07-14 19:55:46 +01:00
3a3888a2d6
chore: update deps 2025-07-14 19:55:25 +01:00
b68e4b4af9
chore(deps): update system-tray 2025-07-14 19:34:04 +01:00
f1dc35e873
Merge pull request #1086 from JakeStanger/dependabot/cargo/clap-4.5.41
build(deps): bump clap from 4.5.40 to 4.5.41
2025-07-14 19:32:25 +01:00
dc8af7ada8
Merge pull request #1085 from JakeStanger/dependabot/cargo/sysinfo-0.36.0
build(deps): bump sysinfo from 0.35.2 to 0.36.0
2025-07-14 19:30:48 +01:00
613495ce0b
Merge pull request #1084 from JakeStanger/dependabot/cargo/zbus-5.8.0
build(deps): bump zbus from 5.7.1 to 5.8.0
2025-07-14 19:28:25 +01:00
dependabot[bot]
98e9af68d9
build(deps): bump clap from 4.5.40 to 4.5.41
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.40 to 4.5.41.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.40...clap_complete-v4.5.41)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.41
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-14 18:24:12 +00:00
dependabot[bot]
1fbe655480
build(deps): bump sysinfo from 0.35.2 to 0.36.0
Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.35.2 to 0.36.0.
- [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/GuillaumeGomez/sysinfo/compare/v0.35.2...v0.36.0)

---
updated-dependencies:
- dependency-name: sysinfo
  dependency-version: 0.36.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-14 17:46:09 +00:00
dependabot[bot]
93a797be3f
build(deps): bump zbus from 5.7.1 to 5.8.0
Bumps [zbus](https://github.com/dbus2/zbus) from 5.7.1 to 5.8.0.
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zbus-5.7.1...zbus-5.8.0)

---
updated-dependencies:
- dependency-name: zbus
  dependency-version: 5.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-14 17:15:47 +00:00
8 changed files with 346 additions and 298 deletions

76
Cargo.lock generated
View file

@ -736,12 +736,6 @@ dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "discard"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "displaydoc"
version = "0.2.5"
@ -1018,22 +1012,6 @@ dependencies = [
"syn 2.0.99",
]
[[package]]
name = "futures-signals"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70abe9c40a0dccd69bf7c59ba58714ebeb6c15a88143a10c6be7130e895f1696"
dependencies = [
"discard",
"futures-channel",
"futures-core",
"futures-util",
"gensym",
"log",
"pin-project",
"serde",
]
[[package]]
name = "futures-sink"
version = "0.3.31"
@ -1145,18 +1123,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.39",
"syn 2.0.99",
"uuid",
]
[[package]]
name = "getrandom"
version = "0.2.15"
@ -1845,7 +1811,6 @@ dependencies = [
"dirs",
"evdev-rs",
"futures-lite",
"futures-signals",
"glib",
"gtk",
"gtk-layer-shell",
@ -1869,6 +1834,7 @@ dependencies = [
"sysinfo",
"system-tray",
"tokio",
"tokio-stream",
"tracing",
"tracing-appender",
"tracing-error",
@ -2541,26 +2507,6 @@ dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote 1.0.39",
"syn 2.0.99",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@ -3557,6 +3503,17 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-stream"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.13"
@ -3865,15 +3822,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587"
dependencies = [
"getrandom 0.3.1",
]
[[package]]
name = "valuable"
version = "0.1.1"

View file

@ -84,7 +84,7 @@ music = ["dep:regex"]
"music+mpris" = ["music", "mpris"]
"music+mpd" = ["music", "mpd-utils"]
network_manager = ["futures-lite", "futures-signals", "zbus"]
network_manager = ["futures-lite", "tokio-stream", "zbus"]
notifications = ["zbus"]
@ -171,7 +171,7 @@ regex = { version = "1.11.1", default-features = false, features = [
], optional = true }
# network_manager
futures-signals = { version = "0.3.34", optional = true }
tokio-stream = { version = "0.1.17", optional = true }
# sys_info
sysinfo = { version = "0.36.1", optional = true }

View file

@ -190,7 +190,7 @@ impl Clients {
if let Some(client) = &self.network_manager {
Ok(client.clone())
} else {
let client = await_sync(async move { networkmanager::create_client().await })?;
let client = networkmanager::create_client()?;
self.network_manager = Some(client.clone());
Ok(client)
}

View file

@ -1,171 +0,0 @@
use std::sync::Arc;
use crate::{register_fallible_client, spawn};
use color_eyre::Result;
use futures_signals::signal::{Mutable, MutableSignalCloned};
use tracing::error;
use zbus::export::ordered_stream::OrderedStreamExt;
use zbus::fdo::PropertiesProxy;
use zbus::{
Connection,
names::InterfaceName,
proxy,
zvariant::{ObjectPath, Str},
};
const DBUS_BUS: &str = "org.freedesktop.NetworkManager";
const DBUS_PATH: &str = "/org/freedesktop/NetworkManager";
const DBUS_INTERFACE: &str = "org.freedesktop.NetworkManager";
#[derive(Debug)]
pub struct Client {
client_state: Mutable<ClientState>,
interface_name: InterfaceName<'static>,
dbus_connection: Connection,
props_proxy: PropertiesProxy<'static>,
}
#[derive(Clone, Debug)]
pub enum ClientState {
WiredConnected,
WifiConnected,
CellularConnected,
VpnConnected,
WifiDisconnected,
Offline,
Unknown,
}
#[proxy(
default_service = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager",
default_path = "/org/freedesktop/NetworkManager"
)]
trait NetworkManagerDbus {
#[zbus(property)]
fn active_connections(&self) -> Result<Vec<ObjectPath>>;
#[zbus(property)]
fn devices(&self) -> Result<Vec<ObjectPath>>;
#[zbus(property)]
fn networking_enabled(&self) -> Result<bool>;
#[zbus(property)]
fn primary_connection(&self) -> Result<ObjectPath>;
#[zbus(property)]
fn primary_connection_type(&self) -> Result<Str>;
#[zbus(property)]
fn wireless_enabled(&self) -> Result<bool>;
}
impl Client {
async fn new() -> Result<Self> {
let client_state = Mutable::new(ClientState::Unknown);
let dbus_connection = Connection::system().await?;
let interface_name = InterfaceName::from_static_str(DBUS_INTERFACE)?;
let props_proxy = PropertiesProxy::builder(&dbus_connection)
.destination(DBUS_BUS)?
.path(DBUS_PATH)?
.build()
.await?;
Ok(Self {
client_state,
interface_name,
dbus_connection,
props_proxy,
})
}
async fn run(&self) -> Result<()> {
let proxy = NetworkManagerDbusProxy::new(&self.dbus_connection).await?;
let mut primary_connection = proxy.primary_connection().await?;
let mut primary_connection_type = proxy.primary_connection_type().await?;
let mut wireless_enabled = proxy.wireless_enabled().await?;
self.client_state.set(determine_state(
&primary_connection,
&primary_connection_type,
wireless_enabled,
));
let mut stream = self.props_proxy.receive_properties_changed().await?;
while let Some(change) = stream.next().await {
let args = change.args()?;
if args.interface_name != self.interface_name {
continue;
}
let changed_props = args.changed_properties;
let mut relevant_prop_changed = false;
if changed_props.contains_key("PrimaryConnection") {
primary_connection = proxy.primary_connection().await?;
relevant_prop_changed = true;
}
if changed_props.contains_key("PrimaryConnectionType") {
primary_connection_type = proxy.primary_connection_type().await?;
relevant_prop_changed = true;
}
if changed_props.contains_key("WirelessEnabled") {
wireless_enabled = proxy.wireless_enabled().await?;
relevant_prop_changed = true;
}
if relevant_prop_changed {
self.client_state.set(determine_state(
&primary_connection,
&primary_connection_type,
wireless_enabled,
));
}
}
Ok(())
}
pub fn subscribe(&self) -> MutableSignalCloned<ClientState> {
self.client_state.signal_cloned()
}
}
pub async fn create_client() -> Result<Arc<Client>> {
let client = Arc::new(Client::new().await?);
{
let client = client.clone();
spawn(async move {
if let Err(error) = client.run().await {
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, network_manager);

View file

@ -0,0 +1,84 @@
use color_eyre::Result;
use zbus::proxy;
use zbus::zvariant::{ObjectPath, OwnedValue, Str};
#[proxy(
default_service = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager",
default_path = "/org/freedesktop/NetworkManager"
)]
pub(super) trait Dbus {
#[zbus(property)]
fn all_devices(&self) -> Result<Vec<ObjectPath<'_>>>;
}
#[proxy(
default_service = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.Device"
)]
pub(super) trait DeviceDbus {
#[zbus(property)]
fn device_type(&self) -> Result<DeviceType>;
#[zbus(property)]
fn interface(&self) -> Result<Str<'_>>;
#[zbus(property)]
fn state(&self) -> Result<DeviceState>;
}
// For reference: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/e1a7d5ac062f4f23ce3a6b33c62e856056161ad8/src/libnm-core-public/nm-dbus-interface.h#L212-L253
#[derive(Clone, Debug, Eq, Hash, OwnedValue, PartialEq)]
#[repr(u32)]
pub enum DeviceType {
Unknown = 0,
Ethernet = 1,
Wifi = 2,
Bluetooth = 5,
OlpcMesh = 6,
Wimax = 7,
Modem = 8,
Infiniband = 9,
Bond = 10,
Vlan = 11,
Adsl = 12,
Bridge = 13,
Team = 15,
Tun = 16,
IpTunnel = 17,
Macvlan = 18,
Vxlan = 19,
Veth = 20,
Macsec = 21,
Dummy = 22,
Ppp = 23,
OvsInterface = 24,
OvsPort = 25,
OvsBridge = 26,
Wpan = 27,
Lowpan = 28,
Wireguard = 29,
WifiP2p = 30,
Vrf = 31,
Loopback = 32,
Hsr = 33,
}
// For reference: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/e1a7d5ac062f4f23ce3a6b33c62e856056161ad8/src/libnm-core-public/nm-dbus-interface.h#L501-L538
#[derive(Clone, Debug, OwnedValue, PartialEq)]
#[repr(u32)]
pub enum DeviceState {
Unknown = 0,
Unmanaged = 10,
Unavailable = 20,
Disconnected = 30,
Prepare = 40,
Config = 50,
NeedAuth = 60,
IpConfig = 70,
IpCheck = 80,
Secondaries = 90,
Activated = 100,
Deactivating = 110,
Failed = 120,
}

View file

@ -0,0 +1,13 @@
use crate::clients::networkmanager::dbus::{DeviceState, DeviceType};
#[derive(Debug, Clone)]
pub enum Event {
DeviceAdded {
interface: String,
},
DeviceStateChanged {
interface: String,
r#type: DeviceType,
state: DeviceState,
},
}

View file

@ -0,0 +1,118 @@
use color_eyre::Result;
use color_eyre::eyre::Ok;
use futures_lite::StreamExt;
use std::collections::HashSet;
use std::sync::Arc;
use tokio::sync::broadcast;
use zbus::Connection;
use zbus::zvariant::{ObjectPath, Str};
use crate::clients::ClientResult;
use crate::clients::networkmanager::dbus::{DbusProxy, DeviceDbusProxy};
use crate::clients::networkmanager::event::Event;
use crate::{register_fallible_client, spawn};
pub mod dbus;
pub mod event;
#[derive(Debug)]
pub struct Client {
tx: broadcast::Sender<Event>,
}
impl Client {
fn new() -> Result<Client> {
let (tx, _) = broadcast::channel(64);
Ok(Client { tx })
}
fn run(&self) -> Result<()> {
let tx = self.tx.clone();
spawn(async move {
let dbus_connection = Connection::system().await?;
let root = DbusProxy::new(&dbus_connection).await?;
let mut devices = HashSet::new();
let mut devices_changes = root.receive_all_devices_changed().await;
while let Some(devices_change) = devices_changes.next().await {
// The new list of devices from dbus, not to be confused with the added devices below
let new_devices = HashSet::from_iter(devices_change.get().await?);
let added_devices = new_devices.difference(&devices);
for added_device in added_devices {
spawn(watch_device(added_device.to_owned(), tx.clone()));
}
let _removed_devices = devices.difference(&new_devices);
// TODO: Cook up some way to notify closures for removed devices to exit
devices = new_devices;
}
Ok(())
});
Ok(())
}
pub fn subscribe(&self) -> broadcast::Receiver<Event> {
self.tx.subscribe()
}
}
pub fn create_client() -> ClientResult<Client> {
let client = Arc::new(Client::new()?);
client.run()?;
Ok(client)
}
async fn watch_device(device_path: ObjectPath<'_>, tx: broadcast::Sender<Event>) -> Result<()> {
let dbus_connection = Connection::system().await?;
let device = DeviceDbusProxy::new(&dbus_connection, device_path.to_owned()).await?;
let interface = device.interface().await?;
tx.send(Event::DeviceAdded {
interface: interface.to_string(),
})?;
spawn(watch_device_state(
device_path.to_owned(),
interface.to_owned(),
tx.clone(),
));
Ok(())
}
async fn watch_device_state(
device_path: ObjectPath<'_>,
interface: Str<'_>,
tx: broadcast::Sender<Event>,
) -> Result<()> {
let dbus_connection = Connection::system().await?;
let device = DeviceDbusProxy::new(&dbus_connection, &device_path).await?;
let r#type = device.device_type().await?;
// Send an event communicating the initial state
let state = device.state().await?;
tx.send(Event::DeviceStateChanged {
interface: interface.to_string(),
r#type: r#type.clone(),
state,
})?;
let mut state_changes = device.receive_state_changed().await;
while let Some(state_change) = state_changes.next().await {
let state = state_change.get().await?;
tx.send(Event::DeviceStateChanged {
interface: interface.to_string(),
r#type: r#type.clone(),
state,
})?;
}
Ok(())
}
register_fallible_client!(Client, network_manager);

View file

@ -1,16 +1,18 @@
use crate::channels::{AsyncSenderExt, BroadcastReceiverExt};
use crate::clients::networkmanager::{Client, ClientState};
use crate::clients::networkmanager::Client;
use crate::clients::networkmanager::dbus::{DeviceState, DeviceType};
use crate::clients::networkmanager::event::Event;
use crate::config::CommonConfig;
use crate::gtk_helpers::IronbarGtkExt;
use crate::image::Provider;
use crate::modules::{Module, ModuleInfo, ModuleParts, WidgetContext};
use crate::{module_impl, spawn};
use color_eyre::Result;
use futures_lite::StreamExt;
use futures_signals::signal::SignalExt;
use gtk::prelude::ContainerExt;
use gtk::{Box as GtkBox, Image};
use color_eyre::{Result, eyre::Ok};
use glib::spawn_future_local;
use gtk::prelude::{ContainerExt, WidgetExt};
use gtk::{Image, Orientation};
use serde::Deserialize;
use tokio::sync::mpsc::Receiver;
use std::collections::HashMap;
use tokio::sync::{broadcast, mpsc};
#[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
@ -26,26 +28,29 @@ const fn default_icon_size() -> i32 {
24
}
impl Module<GtkBox> for NetworkManagerModule {
type SendMessage = ClientState;
impl Module<gtk::Box> for NetworkManagerModule {
type SendMessage = Event;
type ReceiveMessage = ();
module_impl!("network_manager");
fn spawn_controller(
&self,
_: &ModuleInfo,
context: &WidgetContext<ClientState, ()>,
_: Receiver<()>,
_info: &ModuleInfo,
context: &WidgetContext<Event, ()>,
_rx: mpsc::Receiver<()>,
) -> Result<()> {
let client = context.try_client::<Client>()?;
let mut client_signal = client.subscribe().to_stream();
let tx = context.tx.clone();
// Should we be using context.tx with ModuleUpdateEvent::Update instead?
let tx = context.update_tx.clone();
// Must be done here synchronously to avoid race condition
let mut client_rx = client.subscribe();
spawn(async move {
while let Some(state) = client_signal.next().await {
tx.send_update(state).await;
while let Result::Ok(event) = client_rx.recv().await {
tx.send(event)?;
}
Ok(())
});
Ok(())
@ -53,50 +58,101 @@ impl Module<GtkBox> for NetworkManagerModule {
fn into_widget(
self,
context: WidgetContext<ClientState, ()>,
info: &ModuleInfo,
) -> Result<ModuleParts<GtkBox>> {
const INITIAL_ICON_NAME: &str = "content-loading-symbolic";
context: WidgetContext<Event, ()>,
_info: &ModuleInfo,
) -> Result<ModuleParts<gtk::Box>> {
let container = gtk::Box::new(Orientation::Horizontal, 0);
let container = GtkBox::new(info.bar_position.orientation(), 0);
let icon = Image::new();
icon.add_class("icon");
container.add(&icon);
let image_provider = context.ironbar.image_provider();
glib::spawn_future_local({
let image_provider = image_provider.clone();
let icon = icon.clone();
async move {
image_provider
.load_into_image_silent(INITIAL_ICON_NAME, self.icon_size, false, &icon)
.await;
}
});
context.subscribe().recv_glib_async((), move |(), state| {
let image_provider = image_provider.clone();
let icon = icon.clone();
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",
};
async move {
image_provider
.load_into_image_silent(icon_name, self.icon_size, false, &icon)
.await;
}
});
// Must be done here synchronously to avoid race condition
let rx = context.subscribe();
// We cannot use recv_glib_async here because the lifetimes don't work out
spawn_future_local(handle_update_events(
rx,
container.clone(),
self.icon_size,
context.ironbar.image_provider(),
));
Ok(ModuleParts::new(container, None))
}
}
async fn handle_update_events(
mut rx: broadcast::Receiver<Event>,
container: gtk::Box,
icon_size: i32,
image_provider: Provider,
) {
let mut icons = HashMap::<String, Image>::new();
while let Result::Ok(event) = rx.recv().await {
match event {
Event::DeviceAdded { interface, .. } => {
let icon = Image::new();
icon.add_class("icon");
container.add(&icon);
icons.insert(interface, icon);
}
Event::DeviceStateChanged {
interface,
r#type,
state,
} => {
let icon = icons
.get(&interface)
.expect("the icon for the interface to be present");
// TODO: Make this configurable at runtime
let icon_name = get_icon_for_device_state(&r#type, &state);
match icon_name {
Some(icon_name) => {
image_provider
.load_into_image_silent(icon_name, icon_size, false, icon)
.await;
icon.show();
}
None => {
icon.hide();
}
}
}
};
}
}
fn get_icon_for_device_state(r#type: &DeviceType, state: &DeviceState) -> Option<&'static str> {
match r#type {
DeviceType::Ethernet => match state {
DeviceState::Unavailable
| DeviceState::Disconnected
| DeviceState::Prepare
| DeviceState::Config
| DeviceState::NeedAuth
| DeviceState::IpConfig
| DeviceState::IpCheck
| DeviceState::Secondaries
| DeviceState::Deactivating
| DeviceState::Failed => Some("icon:network-wired-disconnected-symbolic"),
DeviceState::Activated => Some("icon:network-wired-symbolic"),
_ => None,
},
DeviceType::Wifi => match state {
DeviceState::Unavailable => Some("icon:network-wireless-hardware-disabled-symbolic"),
DeviceState::Disconnected
| DeviceState::Prepare
| DeviceState::Config
| DeviceState::NeedAuth
| DeviceState::IpConfig
| DeviceState::IpCheck
| DeviceState::Secondaries
| DeviceState::Deactivating
| DeviceState::Failed => Some("icon:network-wireless-offline-symbolic"),
DeviceState::Activated => Some("icon:network-wireless-connected-symbolic"),
_ => None,
},
DeviceType::Tun | DeviceType::Wireguard => match state {
DeviceState::Activated => Some("icon:network-vpn-symbolic"),
_ => None,
},
_ => None,
}
}