From 180e75cb9a15e87665e08bc36b995659bf3e494b Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 27 Mar 2024 13:33:37 -0700 Subject: [PATCH] status-area: Show icons that have `icon_pixmap` but not `icon_name` (#302) This is at least one of the issue behind https://github.com/pop-os/cosmic-applets/issues/165. OBS now shows it's icon instead of an empty space. But the Mattermost flatpak doesn't show anything. (Is that Flatpak related, or does it not use `StatusNotifierItem`?) Requires https://github.com/pop-os/libcosmic/pull/368. Ideally, it should have some way to choose from multiple icons in memory of different sizes. --- Cargo.lock | 34 +++++++++---------- .../src/components/app.rs | 13 ++++--- .../src/components/status_menu.rs | 6 +++- .../src/subscriptions/status_notifier_item.rs | 32 ++++++++++++++++- 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca1e36bc..e358e3ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1146,7 +1146,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "atomicwrites", "cosmic-config-derive", @@ -1166,7 +1166,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "quote", "syn 1.0.109", @@ -1219,7 +1219,7 @@ dependencies = [ [[package]] name = "cosmic-panel-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-panel#39f5f519338734daab5c09174b7fcacbc17d5843" +source = "git+https://github.com/pop-os/cosmic-panel#c2d4b3d9a12894f22e184de93bb0c634a844577c" dependencies = [ "anyhow", "cosmic-config", @@ -1277,7 +1277,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "almost", "cosmic-config", @@ -2713,7 +2713,7 @@ dependencies = [ [[package]] name = "iced" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "iced_accessibility", "iced_core", @@ -2729,7 +2729,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "accesskit", "accesskit_unix", @@ -2738,7 +2738,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "bitflags 1.3.2", "iced_accessibility", @@ -2758,7 +2758,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "futures", "iced_core", @@ -2771,7 +2771,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "bitflags 1.3.2", "bytemuck", @@ -2795,7 +2795,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2807,7 +2807,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "iced_accessibility", "iced_core", @@ -2820,7 +2820,7 @@ dependencies = [ [[package]] name = "iced_sctk" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "enum-repr", "float-cmp", @@ -2846,7 +2846,7 @@ dependencies = [ [[package]] name = "iced_style" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "iced_core", "once_cell", @@ -2856,7 +2856,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "bytemuck", "cosmic-text", @@ -2873,7 +2873,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "bitflags 1.3.2", "bytemuck", @@ -2892,7 +2892,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "iced_renderer", "iced_runtime", @@ -3168,7 +3168,7 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#8afd6490da67704abf9480692abfe33b0780c9c9" +source = "git+https://github.com/pop-os/libcosmic#61a14a953dcb052efa6cdaf5b37c74e964896f5f" dependencies = [ "apply", "ashpd 0.7.0", diff --git a/cosmic-applet-status-area/src/components/app.rs b/cosmic-applet-status-area/src/components/app.rs index c3eb16d2..c22d99fc 100644 --- a/cosmic-applet-status-area/src/components/app.rs +++ b/cosmic-applet-status-area/src/components/app.rs @@ -174,11 +174,14 @@ impl cosmic::Application for App { fn view(&self) -> cosmic::Element<'_, Msg> { // XXX connect open event iced::widget::row(self.menus.iter().map(|(id, menu)| { - self.core - .applet - .icon_button(menu.icon_name()) - .on_press(Msg::TogglePopup(*id)) - .into() + match menu.icon_pixmap() { + Some(icon) if menu.icon_name() == "" => { + self.core.applet.icon_button_from_handle(icon.clone()) + } + _ => self.core.applet.icon_button(menu.icon_name()), + } + .on_press(Msg::TogglePopup(*id)) + .into() })) .into() } diff --git a/cosmic-applet-status-area/src/components/status_menu.rs b/cosmic-applet-status-area/src/components/status_menu.rs index c4cce8e1..3607f8eb 100644 --- a/cosmic-applet-status-area/src/components/status_menu.rs +++ b/cosmic-applet-status-area/src/components/status_menu.rs @@ -1,5 +1,5 @@ use cosmic::applet::menu_button; -use cosmic::iced; +use cosmic::{iced, widget::icon}; use crate::subscriptions::status_notifier_item::{Layout, StatusNotifierItem}; @@ -65,6 +65,10 @@ impl State { self.item.icon_name() } + pub fn icon_pixmap(&self) -> Option<&icon::Handle> { + self.item.icon_pixmap() + } + pub fn popup_view(&self) -> cosmic::Element { if let Some(layout) = self.layout.as_ref() { layout_view(layout, self.expanded) diff --git a/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs b/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs index d5c79739..6316d6ab 100644 --- a/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs +++ b/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs @@ -1,4 +1,4 @@ -use cosmic::iced; +use cosmic::{iced, widget::icon}; use futures::{FutureExt, StreamExt}; use zbus::zvariant::{self, OwnedValue}; @@ -6,10 +6,19 @@ use zbus::zvariant::{self, OwnedValue}; pub struct StatusNotifierItem { name: String, icon_name: String, + // TODO Handle icon with multiple sizes? + icon_pixmap: Option, _item_proxy: StatusNotifierItemProxy<'static>, menu_proxy: DBusMenuProxy<'static>, } +#[derive(Clone, Debug, zvariant::Value)] +pub struct Icon { + width: i32, + height: i32, + bytes: Vec, +} + impl StatusNotifierItem { pub async fn new(connection: &zbus::Connection, name: String) -> zbus::Result { let (dest, path) = if let Some(idx) = name.find('/') { @@ -25,6 +34,18 @@ impl StatusNotifierItem { .await?; let icon_name = item_proxy.icon_name().await?; + let icon_pixmap = item_proxy + .icon_pixmap() + .await? + .into_iter() + .max_by_key(|i| (i.width, i.height)) + .map(|mut i| { + // Convert ARGB to RGBA + for pixel in i.bytes.chunks_exact_mut(4) { + pixel.rotate_left(1); + } + icon::from_raster_pixels(i.width as u32, i.height as u32, i.bytes) + }); let menu_path = item_proxy.menu().await?; let menu_proxy = DBusMenuProxy::builder(connection) @@ -36,6 +57,7 @@ impl StatusNotifierItem { Ok(Self { name, icon_name, + icon_pixmap, _item_proxy: item_proxy, menu_proxy, }) @@ -49,6 +71,10 @@ impl StatusNotifierItem { &self.icon_name } + pub fn icon_pixmap(&self) -> Option<&icon::Handle> { + self.icon_pixmap.as_ref() + } + // TODO: Only fetch changed part of layout, if that's any faster pub fn layout_subscription(&self) -> iced::Subscription> { let menu_proxy = self.menu_proxy.clone(); @@ -81,6 +107,10 @@ trait StatusNotifierItem { #[dbus_proxy(property)] fn icon_name(&self) -> zbus::Result; + // https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/Icons + #[dbus_proxy(property)] + fn icon_pixmap(&self) -> zbus::Result>; + #[dbus_proxy(property)] fn menu(&self) -> zbus::Result; }