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.
This commit is contained in:
Ian Douglas Scott 2024-03-27 13:33:37 -07:00 committed by GitHub
parent 8128b6cf89
commit 180e75cb9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 61 additions and 24 deletions

View file

@ -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<icon::Handle>,
_item_proxy: StatusNotifierItemProxy<'static>,
menu_proxy: DBusMenuProxy<'static>,
}
#[derive(Clone, Debug, zvariant::Value)]
pub struct Icon {
width: i32,
height: i32,
bytes: Vec<u8>,
}
impl StatusNotifierItem {
pub async fn new(connection: &zbus::Connection, name: String) -> zbus::Result<Self> {
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<Result<Layout, String>> {
let menu_proxy = self.menu_proxy.clone();
@ -81,6 +107,10 @@ trait StatusNotifierItem {
#[dbus_proxy(property)]
fn icon_name(&self) -> zbus::Result<String>;
// https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/Icons
#[dbus_proxy(property)]
fn icon_pixmap(&self) -> zbus::Result<Vec<Icon>>;
#[dbus_proxy(property)]
fn menu(&self) -> zbus::Result<zvariant::OwnedObjectPath>;
}