Skip to content

Commit 133632d

Browse files
committed
fix(tray): vastly improve rendering performance
1 parent 0616633 commit 133632d

File tree

5 files changed

+650
-291
lines changed

5 files changed

+650
-291
lines changed

src/modules/tray.rs

-291
This file was deleted.

src/modules/tray/diff.rs

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
use system_tray::message::menu::{MenuItem as MenuItemInfo, ToggleState};
2+
3+
/// Diff change type and associated info.
4+
#[derive(Debug, Clone)]
5+
pub enum Diff {
6+
Add(MenuItemInfo),
7+
Update(i32, MenuItemDiff),
8+
Remove(i32),
9+
}
10+
11+
/// Diff info to be applied to an existing menu item as an update.
12+
#[derive(Debug, Clone)]
13+
pub struct MenuItemDiff {
14+
/// Text of the item,
15+
pub label: Option<String>,
16+
/// Whether the item can be activated or not.
17+
pub enabled: Option<bool>,
18+
/// True if the item is visible in the menu.
19+
pub visible: Option<bool>,
20+
/// Icon name of the item, following the freedesktop.org icon spec.
21+
// pub icon_name: Option<Option<String>>,
22+
/// Describe the current state of a "togglable" item. Can be one of:
23+
/// - Some(true): on
24+
/// - Some(false): off
25+
/// - None: indeterminate
26+
pub toggle_state: Option<ToggleState>,
27+
/// A submenu for this item, typically this would ve revealed to the user by hovering the current item
28+
pub submenu: Vec<Diff>,
29+
}
30+
31+
impl MenuItemDiff {
32+
fn new(old: &MenuItemInfo, new: &MenuItemInfo) -> Self {
33+
macro_rules! diff {
34+
($field:ident) => {
35+
if old.$field == new.$field {
36+
None
37+
} else {
38+
Some(new.$field)
39+
}
40+
};
41+
42+
(&$field:ident) => {
43+
if &old.$field == &new.$field {
44+
None
45+
} else {
46+
Some(new.$field.clone())
47+
}
48+
};
49+
}
50+
51+
Self {
52+
label: diff!(&label),
53+
enabled: diff!(enabled),
54+
visible: diff!(visible),
55+
// icon_name: diff!(&icon_name),
56+
toggle_state: diff!(toggle_state),
57+
submenu: get_diffs(&old.submenu, &new.submenu),
58+
}
59+
}
60+
61+
/// Whether this diff contains any changes
62+
fn has_diff(&self) -> bool {
63+
self.label.is_some()
64+
|| self.enabled.is_some()
65+
|| self.visible.is_some()
66+
// || self.icon_name.is_some()
67+
|| self.toggle_state.is_some()
68+
|| !self.submenu.is_empty()
69+
}
70+
}
71+
72+
/// Gets a diff set between old and new state.
73+
pub fn get_diffs(old: &[MenuItemInfo], new: &[MenuItemInfo]) -> Vec<Diff> {
74+
let mut diffs = vec![];
75+
76+
for new_item in new {
77+
let old_item = old.iter().find(|&item| item.id == new_item.id);
78+
79+
let diff = match old_item {
80+
Some(old_item) => {
81+
let item_diff = MenuItemDiff::new(old_item, new_item);
82+
if item_diff.has_diff() {
83+
Some(Diff::Update(old_item.id, item_diff))
84+
} else {
85+
None
86+
}
87+
}
88+
None => Some(Diff::Add(new_item.clone())),
89+
};
90+
91+
if let Some(diff) = diff {
92+
diffs.push(diff);
93+
}
94+
}
95+
96+
for old_item in old {
97+
let new_item = new.iter().find(|&item| item.id == old_item.id);
98+
if new_item.is_none() {
99+
diffs.push(Diff::Remove(old_item.id));
100+
}
101+
}
102+
103+
diffs
104+
}

0 commit comments

Comments
 (0)