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:
parent
8128b6cf89
commit
180e75cb9a
4 changed files with 61 additions and 24 deletions
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue