feat: add system tray (StatusNotifierWatcher / SNI)
Some checks failed
release / build (push) Failing after 3s
Some checks failed
release / build (push) Failing after 3s
Implements org.kde.StatusNotifierWatcher as a D-Bus service so apps like Nextcloud can register their tray icons. Icons are rendered from SNI ARGB pixmaps (falling back to icon-name theme lookup), click calls Activate(0,0), and NameOwnerChanged cleans up ghost icons when an app exits. Styling follows the Bread Design System (4px tertiary radius, xs/sm spacing, opacity transitions). Also fixes a latent infinite-loop risk in osd.rs (.flatten → .map_while) and syncs the notifications server version string to CARGO_PKG_VERSION.
This commit is contained in:
parent
a036737823
commit
44a8d95887
8 changed files with 277 additions and 7 deletions
30
src/main.rs
30
src/main.rs
|
|
@ -34,6 +34,8 @@ pub struct App {
|
|||
wifi_img: gtk4::Image,
|
||||
// Pre-loaded textures indexed by constant pointer values.
|
||||
wifi_textures: std::collections::HashMap<usize, gtk4::gdk::Texture>,
|
||||
tray_box: gtk4::Box,
|
||||
tray_items: std::collections::HashMap<String, gtk4::Button>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -42,6 +44,7 @@ pub enum AppInput {
|
|||
ActiveWorkspace(WorkspaceId),
|
||||
ClockTick,
|
||||
StatsUpdate(bar::stats::Stats),
|
||||
TrayUpdate(bar::tray::TrayUpdate),
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
|
|
@ -153,6 +156,8 @@ impl SimpleComponent for App {
|
|||
wifi_lbl: wifi_lbl.clone(),
|
||||
wifi_img: wifi_img.clone(),
|
||||
wifi_textures,
|
||||
tray_box: gtk4::Box::new(gtk4::Orientation::Horizontal, 4),
|
||||
tray_items: std::collections::HashMap::new(),
|
||||
};
|
||||
let widgets = view_output!();
|
||||
model.workspace_box = widgets.workspace_box.clone();
|
||||
|
|
@ -179,12 +184,15 @@ impl SimpleComponent for App {
|
|||
wifi_pair.append(&wifi_img);
|
||||
wifi_pair.append(&wifi_lbl);
|
||||
stats_box.append(&wifi_pair);
|
||||
model.tray_box.add_css_class("tray-box");
|
||||
stats_box.append(&model.tray_box);
|
||||
widgets.center_box.set_end_widget(Some(&stats_box));
|
||||
|
||||
theme::apply();
|
||||
bar::workspaces::spawn_watcher(sender.clone());
|
||||
bar::clock::spawn_ticker(sender.clone());
|
||||
bar::stats::spawn_poller(sender);
|
||||
bar::stats::spawn_poller(sender.clone());
|
||||
bar::tray::spawn_watcher(sender.clone());
|
||||
notifications::spawn();
|
||||
osd::spawn();
|
||||
|
||||
|
|
@ -228,6 +236,26 @@ impl SimpleComponent for App {
|
|||
self.wifi_img.set_paintable(Some(tex));
|
||||
}
|
||||
}
|
||||
AppInput::TrayUpdate(bar::tray::TrayUpdate::Add { id, icon, title }) => {
|
||||
if self.tray_items.contains_key(&id) {
|
||||
return;
|
||||
}
|
||||
let btn = gtk4::Button::new();
|
||||
btn.add_css_class("tray-btn");
|
||||
btn.set_child(Some(&bar::tray::make_tray_image(icon.as_ref())));
|
||||
if !title.is_empty() {
|
||||
btn.set_tooltip_text(Some(&title));
|
||||
}
|
||||
let id_click = id.clone();
|
||||
btn.connect_clicked(move |_| bar::tray::spawn_activate(id_click.clone()));
|
||||
self.tray_box.append(&btn);
|
||||
self.tray_items.insert(id, btn);
|
||||
}
|
||||
AppInput::TrayUpdate(bar::tray::TrayUpdate::Remove { id }) => {
|
||||
if let Some(btn) = self.tray_items.remove(&id) {
|
||||
self.tray_box.remove(&btn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue