Skip to content

Commit e107d45

Browse files
authored
feat: make Client::items optional behind feature flag (#18)
Flag is enabled by default
1 parent 6899ae0 commit e107d45

File tree

5 files changed

+96
-42
lines changed

5 files changed

+96
-42
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ categories = ["gui"]
99
keywords = ["statusnotifieritem", "dbusmenu", "tokio", "tray"]
1010

1111
[features]
12-
default = []
12+
default = ["data"]
13+
data = []
1314
dbusmenu-gtk3 = ["dep:gtk", "dep:dbusmenu-gtk3-sys"]
1415

1516
[dependencies]
@@ -19,6 +20,7 @@ serde = { version = "1", features = ["derive"] }
1920
tokio = { version = "1", features = ["rt", "sync", "macros", "time"] }
2021
thiserror = "2.0"
2122
futures-lite = "2.6"
23+
cfg-if = "1.0.0"
2224

2325
gtk = { version = "0.18.1", optional = true }
2426
dbusmenu-gtk3-sys = { version = "0.1.0", optional = true }

src/client.rs

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::data::TrayItemMap;
12
use crate::dbus::dbus_menu_proxy::{DBusMenuProxy, PropertiesUpdate};
23
use crate::dbus::notifier_item_proxy::StatusNotifierItemProxy;
34
use crate::dbus::notifier_watcher_proxy::StatusNotifierWatcherProxy;
@@ -9,8 +10,6 @@ use crate::menu::{MenuDiff, TrayMenu};
910
use crate::names;
1011
use dbus::DBusProps;
1112
use futures_lite::StreamExt;
12-
use std::collections::HashMap;
13-
use std::sync::{Arc, Mutex};
1413
use std::time::{Duration, SystemTime, UNIX_EPOCH};
1514
use tokio::spawn;
1615
use tokio::sync::broadcast;
@@ -76,8 +75,6 @@ pub enum ActivateRequest {
7675
Secondary { address: String, x: i32, y: i32 },
7776
}
7877

79-
type State = HashMap<String, (StatusNotifierItem, Option<TrayMenu>)>;
80-
8178
const PROPERTIES_INTERFACE: &str = "org.kde.StatusNotifierItem";
8279

8380
/// Client for watching the tray.
@@ -87,7 +84,8 @@ pub struct Client {
8784
_rx: broadcast::Receiver<Event>,
8885
connection: Connection,
8986

90-
items: Arc<Mutex<State>>,
87+
#[cfg(feature = "data")]
88+
items: TrayItemMap,
9189
}
9290

9391
impl Client {
@@ -153,8 +151,7 @@ impl Client {
153151
watcher_proxy
154152
.register_status_notifier_host(&wellknown)
155153
.await?;
156-
157-
let items = Arc::new(Mutex::new(HashMap::new()));
154+
let items = TrayItemMap::new();
158155

159156
// handle new items
160157
{
@@ -229,11 +226,8 @@ impl Client {
229226
while let Some(thing) = stream.next().await {
230227
let body = thing.args()?;
231228
if body.name == names::WATCHER_BUS {
232-
let mut items = items.lock().expect("mutex lock should succeed");
233-
let keys = items.keys().cloned().collect::<Vec<_>>();
234-
for address in keys {
235-
items.remove(&address);
236-
tx.send(Event::Remove(address))?;
229+
for dest in items.clear_items() {
230+
tx.send(Event::Remove(dest))?;
237231
}
238232
}
239233
}
@@ -248,6 +242,7 @@ impl Client {
248242
connection,
249243
tx,
250244
_rx: rx,
245+
#[cfg(feature = "data")]
251246
items,
252247
})
253248
}
@@ -258,7 +253,7 @@ impl Client {
258253
address: &str,
259254
connection: Connection,
260255
tx: broadcast::Sender<Event>,
261-
items: Arc<Mutex<State>>,
256+
items: TrayItemMap,
262257
) -> crate::error::Result<()> {
263258
let (destination, path) = parse_address(address);
264259

@@ -270,10 +265,7 @@ impl Client {
270265

271266
let properties = Self::get_item_properties(destination, &path, &properties_proxy).await?;
272267

273-
items
274-
.lock()
275-
.expect("mutex lock should succeed")
276-
.insert(destination.into(), (properties.clone(), None));
268+
items.new_item(destination.into(), &properties);
277269

278270
tx.send(Event::Add(
279271
destination.to_string(),
@@ -292,8 +284,8 @@ impl Client {
292284
&path,
293285
&connection,
294286
properties_proxy,
295-
items,
296287
tx,
288+
items,
297289
)
298290
.await?;
299291

@@ -350,8 +342,8 @@ impl Client {
350342
path: &str,
351343
connection: &Connection,
352344
properties_proxy: PropertiesProxy<'_>,
353-
items: Arc<Mutex<State>>,
354345
tx: broadcast::Sender<Event>,
346+
items: TrayItemMap,
355347
) -> crate::error::Result<()> {
356348
let notifier_item_proxy = StatusNotifierItemProxy::builder(connection)
357349
.destination(destination)?
@@ -395,7 +387,8 @@ impl Client {
395387
error!("{error:?}");
396388
}
397389

398-
items.lock().expect("mutex lock should succeed").remove(&destination.to_string());
390+
391+
items.remove_item(destination);
399392

400393
tx.send(Event::Remove(destination.to_string()))?;
401394
break Ok(());
@@ -469,7 +462,7 @@ impl Client {
469462
menu_path: &str,
470463
connection: &Connection,
471464
tx: broadcast::Sender<Event>,
472-
items: Arc<Mutex<State>>,
465+
items: TrayItemMap,
473466
) -> crate::error::Result<()> {
474467
let dbus_menu_proxy = DBusMenuProxy::builder(connection)
475468
.destination(destination.as_str())?
@@ -480,15 +473,7 @@ impl Client {
480473
let menu = dbus_menu_proxy.get_layout(0, 10, &[]).await?;
481474
let menu = TrayMenu::try_from(menu)?;
482475

483-
if let Some((_, menu_cache)) = items
484-
.lock()
485-
.expect("mutex lock should succeed")
486-
.get_mut(&destination)
487-
{
488-
menu_cache.replace(menu.clone());
489-
} else {
490-
error!("could not find item in state");
491-
}
476+
items.update_menu(&destination, &menu);
492477

493478
tx.send(Event::Update(
494479
destination.to_string(),
@@ -522,15 +507,7 @@ impl Client {
522507

523508
let menu = TrayMenu::try_from(menu)?;
524509

525-
if let Some((_, menu_cache)) = items
526-
.lock()
527-
.expect("mutex lock should succeed")
528-
.get_mut(&destination)
529-
{
530-
menu_cache.replace(menu.clone());
531-
} else {
532-
error!("could not find item in state");
533-
}
510+
items.update_menu(&destination, &menu);
534511

535512
debug!("sending new menu for '{destination}'");
536513
trace!("new menu for '{destination}': {menu:?}");
@@ -592,9 +569,10 @@ impl Client {
592569
}
593570

594571
/// Gets all current items, including their menus if present.
572+
#[cfg(feature = "data")]
595573
#[must_use]
596-
pub fn items(&self) -> Arc<Mutex<State>> {
597-
self.items.clone()
574+
pub fn items(&self) -> std::sync::Arc<std::sync::Mutex<crate::data::BaseMap>> {
575+
self.items.get_map()
598576
}
599577

600578
/// One should call this method with id=0 when opening the root menu.

src/data.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use crate::{item::StatusNotifierItem, menu::TrayMenu};
2+
use std::sync::{Arc, Mutex};
3+
4+
#[cfg(feature = "data")]
5+
pub type BaseMap = std::collections::HashMap<String, (StatusNotifierItem, Option<TrayMenu>)>;
6+
7+
#[cfg(not(feature = "data"))]
8+
type BaseMap = std::collections::HashSet<String>;
9+
10+
#[derive(Debug, Clone)]
11+
pub(crate) struct TrayItemMap {
12+
inner: Arc<Mutex<BaseMap>>,
13+
}
14+
15+
impl TrayItemMap {
16+
pub(crate) fn new() -> Self {
17+
Self {
18+
inner: Arc::new(Mutex::new(Default::default())),
19+
}
20+
}
21+
22+
#[cfg(feature = "data")]
23+
pub(crate) fn get_map(&self) -> Arc<Mutex<BaseMap>> {
24+
self.inner.clone()
25+
}
26+
27+
pub(crate) fn new_item(&self, dest: String, item: &StatusNotifierItem) {
28+
let mut lock = self.inner.lock().expect("mutex lock should succeed");
29+
cfg_if::cfg_if! {
30+
if #[cfg(feature = "data")] {
31+
lock.insert(dest, (item.clone(), None));
32+
}else {
33+
let _ = item;
34+
lock.insert(dest);
35+
}
36+
}
37+
}
38+
39+
pub(crate) fn remove_item(&self, dest: &str) {
40+
self.inner
41+
.lock()
42+
.expect("mutex lock should succeed")
43+
.remove(dest);
44+
}
45+
46+
pub(crate) fn clear_items(&self) -> Vec<String> {
47+
let mut lock = self.inner.lock().expect("mutex lock should succeed");
48+
cfg_if::cfg_if! {
49+
if #[cfg(feature = "data")] {
50+
lock.drain().map(|(k, _)| k).collect()
51+
}else {
52+
lock.drain().collect()
53+
}
54+
}
55+
}
56+
57+
pub(crate) fn update_menu(&self, dest: &str, menu: &TrayMenu) {
58+
cfg_if::cfg_if! {
59+
if #[cfg(feature = "data")] {
60+
if let Some((_, menu_cache)) = self.inner.lock().unwrap().get_mut(dest) {
61+
menu_cache.replace(menu.clone());
62+
} else {
63+
tracing::error!("could not find item in state");
64+
}
65+
}else {
66+
let _ = menu;
67+
let _ = dest;
68+
}
69+
}
70+
}
71+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
/// ```
2626
mod dbus;
2727

28+
pub mod data;
29+
2830
/// Client for listening to item and menu events,
2931
/// and associated types.
3032
pub mod client;

0 commit comments

Comments
 (0)