use serde::{Deserialize, Serialize};
use zbus::{
interface,
object_server::SignalEmitter,
zvariant::{ObjectPath, OwnedValue, Type, Value},
};
#[derive(Clone, PartialEq, Type, OwnedValue, Value, Debug, Default)]
pub struct IconPixmap {
pub width: i32,
pub height: i32,
pub data: Vec<u8>,
}
#[derive(Clone, PartialEq, Type, OwnedValue, Value, Default, Debug)]
pub struct ToolTip {
pub icon: String,
pub data: Vec<IconPixmap>,
pub title: String,
pub description: String,
}
#[derive(Clone, PartialEq, Type, OwnedValue, Value, Debug, Default, Serialize, Deserialize)]
#[zvariant(signature = "s")]
pub enum NotifierStatus {
#[default]
Active,
Passive,
NeedsAttention,
}
const MENU_PATH: ObjectPath = ObjectPath::from_static_str_unchecked("/MenuBar");
#[derive(
Clone, Copy, PartialEq, Type, OwnedValue, Value, Debug, Default, Serialize, Deserialize,
)]
#[zvariant(signature = "s")]
pub enum Category {
#[default]
ApplicationStatus,
Communications,
SystemServices,
Hardware,
}
pub trait StatusNotifierItem {
type State;
fn boot(&self) -> Self::State;
fn id(&self) -> String;
#[allow(unused)]
fn activate(&self, state: &mut Self::State, x: i32, y: i32) -> zbus::fdo::Result<()> {
Ok(())
}
fn context_menu(&self, _state: &mut Self::State, _x: i32, _y: i32) -> zbus::fdo::Result<()> {
Err(zbus::fdo::Error::NotSupported("Error".to_owned()))
}
fn scroll(
&self,
_state: &mut Self::State,
_delta: i32,
_orientation: &str,
) -> zbus::fdo::Result<()> {
Err(zbus::fdo::Error::NotSupported("Error".to_owned()))
}
fn secondary_activate(
&self,
_state: &mut Self::State,
_x: i32,
_y: i32,
) -> zbus::fdo::Result<()> {
Err(zbus::fdo::Error::NotSupported("Error".to_owned()))
}
#[allow(unused)]
fn tool_tip(&self, state: &Self::State) -> zbus::fdo::Result<ToolTip> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
#[allow(unused)]
fn icon_theme_path(&self, state: &Self::State) -> zbus::fdo::Result<String> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
#[allow(unused)]
fn icon_name(&self, state: &Self::State) -> zbus::fdo::Result<String> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
#[allow(unused)]
fn icon_pixmap(&self, state: &Self::State) -> zbus::fdo::Result<Vec<IconPixmap>> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
#[allow(unused)]
fn attention_icon_name(&self, state: &Self::State) -> zbus::fdo::Result<String> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
#[allow(unused)]
fn attention_icon_pixmap(&self, state: &Self::State) -> zbus::fdo::Result<Vec<IconPixmap>> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
#[allow(unused)]
fn overlay_icon_name(&self, state: &Self::State) -> zbus::fdo::Result<String> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
#[allow(unused)]
fn overlay_icon_pixmap(&self, state: &Self::State) -> zbus::fdo::Result<Vec<IconPixmap>> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
#[allow(unused)]
fn attention_movie_name(&self, state: &Self::State) -> zbus::fdo::Result<String> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
fn category(&self) -> Category {
Category::SystemServices
}
fn title(&self, state: &Self::State) -> zbus::fdo::Result<String>;
#[allow(unused)]
fn status(&self, state: &Self::State) -> zbus::fdo::Result<NotifierStatus> {
Ok(NotifierStatus::Active)
}
#[allow(unused)]
fn item_is_menu(&self, state: &Self::State) -> bool {
false
}
#[allow(unused)]
fn window_id(&self, state: &Self::State) -> zbus::fdo::Result<i32> {
Err(zbus::fdo::Error::NotSupported("Unimplemented".to_string()))
}
}
pub trait NotifierBootFn<State> {
fn boot(&self) -> State;
}
impl<T, State> NotifierBootFn<State> for T
where
T: Fn() -> State,
{
fn boot(&self) -> State {
self()
}
}
pub trait IdFn {
fn id(&self) -> String;
}
impl<T> IdFn for T
where
T: Fn() -> String,
{
fn id(&self) -> String {
self()
}
}
impl IdFn for &str {
fn id(&self) -> String {
self.to_string()
}
}
impl IdFn for String {
fn id(&self) -> String {
self.clone()
}
}
pub trait CategoryFn {
fn category(&self) -> Category;
}
impl<T> CategoryFn for T
where
T: Fn() -> Category,
{
fn category(&self) -> Category {
self()
}
}
impl CategoryFn for Category {
fn category(&self) -> Category {
*self
}
}
pub trait ActivateFn<State> {
fn activate(&self, state: &mut State, x: i32, y: i32) -> zbus::fdo::Result<()>;
}
impl<T, State> ActivateFn<State> for T
where
T: Fn(&mut State, i32, i32) -> zbus::fdo::Result<()>,
{
fn activate(&self, state: &mut State, x: i32, y: i32) -> zbus::fdo::Result<()> {
self(state, x, y)
}
}
pub trait ScrollFn<State> {
fn scroll(&self, state: &mut State, delta: i32, orientation: &str) -> zbus::fdo::Result<()>;
}
impl<T, State> ScrollFn<State> for T
where
T: Fn(&mut State, i32, &str) -> zbus::fdo::Result<()>,
{
fn scroll(&self, state: &mut State, delta: i32, orientation: &str) -> zbus::fdo::Result<()> {
self(state, delta, orientation)
}
}
pub trait SecondaryActivateFn<State> {
fn secondary_activate(&self, state: &mut State, x: i32, y: i32) -> zbus::fdo::Result<()>;
}
impl<T, State> SecondaryActivateFn<State> for T
where
T: Fn(&mut State, i32, i32) -> zbus::fdo::Result<()>,
{
fn secondary_activate(&self, state: &mut State, x: i32, y: i32) -> zbus::fdo::Result<()> {
self(state, x, y)
}
}
pub trait ContextMenuFn<State> {
fn context_menu(&self, state: &mut State, x: i32, y: i32) -> zbus::fdo::Result<()>;
}
impl<T, State> ContextMenuFn<State> for T
where
T: Fn(&mut State, i32, i32) -> zbus::fdo::Result<()>,
{
fn context_menu(&self, state: &mut State, x: i32, y: i32) -> zbus::fdo::Result<()> {
self(state, x, y)
}
}
pub trait TitleFn<State> {
fn title(&self, state: &State) -> zbus::fdo::Result<String>;
}
impl<State> TitleFn<State> for &str {
fn title(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.to_string())
}
}
impl<State> TitleFn<State> for String {
fn title(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.clone())
}
}
impl<State, T> TitleFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<String>,
{
fn title(&self, state: &State) -> zbus::fdo::Result<String> {
self(state)
}
}
pub trait IconThemePathNotifierFn<State> {
fn icon_theme_path(&self, state: &State) -> zbus::fdo::Result<String>;
}
impl<State> IconThemePathNotifierFn<State> for &str {
fn icon_theme_path(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.to_string())
}
}
impl<State> IconThemePathNotifierFn<State> for String {
fn icon_theme_path(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.clone())
}
}
impl<State, T> IconThemePathNotifierFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<String>,
{
fn icon_theme_path(&self, state: &State) -> zbus::fdo::Result<String> {
self(state)
}
}
pub trait IconNameFn<State> {
fn icon_name(&self, state: &State) -> zbus::fdo::Result<String>;
}
impl<State> IconNameFn<State> for &str {
fn icon_name(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.to_string())
}
}
impl<State> IconNameFn<State> for String {
fn icon_name(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.clone())
}
}
impl<State, T> IconNameFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<String>,
{
fn icon_name(&self, state: &State) -> zbus::fdo::Result<String> {
self(state)
}
}
pub trait IconPixmapFn<State> {
fn icon_pixmap(&self, state: &State) -> zbus::fdo::Result<Vec<IconPixmap>>;
}
impl<State, T> IconPixmapFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<Vec<IconPixmap>>,
{
fn icon_pixmap(&self, state: &State) -> zbus::fdo::Result<Vec<IconPixmap>> {
self(state)
}
}
pub trait AttentionIconNameFn<State> {
fn attention_icon_name(&self, state: &State) -> zbus::fdo::Result<String>;
}
impl<State> AttentionIconNameFn<State> for &str {
fn attention_icon_name(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.to_string())
}
}
impl<State> AttentionIconNameFn<State> for String {
fn attention_icon_name(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.clone())
}
}
impl<State, T> AttentionIconNameFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<String>,
{
fn attention_icon_name(&self, state: &State) -> zbus::fdo::Result<String> {
self(state)
}
}
pub trait AttentionIconPixmapFn<State> {
fn attention_icon_pixmap(&self, state: &State) -> zbus::fdo::Result<Vec<IconPixmap>>;
}
impl<State, T> AttentionIconPixmapFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<Vec<IconPixmap>>,
{
fn attention_icon_pixmap(&self, state: &State) -> zbus::fdo::Result<Vec<IconPixmap>> {
self(state)
}
}
pub trait AttentionMovieNameFn<State> {
fn attention_movie_name(&self, state: &State) -> zbus::fdo::Result<String>;
}
impl<State> AttentionMovieNameFn<State> for &str {
fn attention_movie_name(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.to_string())
}
}
impl<State> AttentionMovieNameFn<State> for String {
fn attention_movie_name(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.clone())
}
}
impl<State, T> AttentionMovieNameFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<String>,
{
fn attention_movie_name(&self, state: &State) -> zbus::fdo::Result<String> {
self(state)
}
}
pub trait OverlayIconNameFn<State> {
fn overlay_icon_name(&self, state: &State) -> zbus::fdo::Result<String>;
}
impl<State> OverlayIconNameFn<State> for &str {
fn overlay_icon_name(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.to_string())
}
}
impl<State> OverlayIconNameFn<State> for String {
fn overlay_icon_name(&self, _state: &State) -> zbus::fdo::Result<String> {
Ok(self.clone())
}
}
impl<State, T> OverlayIconNameFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<String>,
{
fn overlay_icon_name(&self, state: &State) -> zbus::fdo::Result<String> {
self(state)
}
}
pub trait OverlayIconPixmapFn<State> {
fn overlay_icon_pixmap(&self, state: &State) -> zbus::fdo::Result<Vec<IconPixmap>>;
}
impl<State, T> OverlayIconPixmapFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<Vec<IconPixmap>>,
{
fn overlay_icon_pixmap(&self, state: &State) -> zbus::fdo::Result<Vec<IconPixmap>> {
self(state)
}
}
pub trait NotifierStatusFn<State> {
fn status(&self, state: &State) -> NotifierStatus;
}
impl<State, T> NotifierStatusFn<State> for T
where
T: Fn(&State) -> NotifierStatus,
{
fn status(&self, state: &State) -> NotifierStatus {
self(state)
}
}
pub trait ItemIsMenuFn<State> {
fn item_is_menu(&self, state: &State) -> bool;
}
impl<State, T> ItemIsMenuFn<State> for T
where
T: Fn(&State) -> bool,
{
fn item_is_menu(&self, state: &State) -> bool {
self(state)
}
}
impl<State> ItemIsMenuFn<State> for bool {
fn item_is_menu(&self, _state: &State) -> bool {
*self
}
}
pub trait ToolTipFn<State> {
fn tool_tip(&self, state: &State) -> zbus::fdo::Result<ToolTip>;
}
impl<State, T> ToolTipFn<State> for T
where
T: Fn(&State) -> zbus::fdo::Result<ToolTip>,
{
fn tool_tip(&self, state: &State) -> zbus::fdo::Result<ToolTip> {
self(state)
}
}
pub trait WindowIdFn<State> {
fn window_id(&self, state: &State) -> i32;
}
impl<State> WindowIdFn<State> for i32 {
fn window_id(&self, _state: &State) -> i32 {
*self
}
}
impl<State, T> WindowIdFn<State> for T
where
T: Fn(&State) -> i32,
{
fn window_id(&self, state: &State) -> i32 {
self(state)
}
}
pub struct StatusNotifierInstance<P: StatusNotifierItem> {
pub(crate) program: P,
pub(crate) state: P::State,
}
#[interface(name = "org.kde.StatusNotifierItem")]
impl<P: StatusNotifierItem> StatusNotifierInstance<P>
where
P: Send + Sync + 'static,
P::State: 'static + Send + Sync,
{
fn activate(&mut self, x: i32, y: i32) -> zbus::fdo::Result<()> {
self.program.activate(&mut self.state, x, y)
}
fn context_menu(&mut self, x: i32, y: i32) -> zbus::fdo::Result<()> {
self.program.context_menu(&mut self.state, x, y)
}
fn scroll(&mut self, delta: i32, orientation: &str) -> zbus::fdo::Result<()> {
self.program.scroll(&mut self.state, delta, orientation)
}
fn secondary_activate(&mut self, x: i32, y: i32) -> zbus::fdo::Result<()> {
self.program.secondary_activate(&mut self.state, x, y)
}
#[zbus(signal)]
async fn new_attention_icon(ctxt: &SignalEmitter<'_>) -> zbus::Result<()>;
#[zbus(signal)]
pub async fn new_icon(ctxt: &SignalEmitter<'_>) -> zbus::Result<()>;
#[zbus(signal)]
pub async fn new_menu(ctxt: &SignalEmitter<'_>) -> zbus::Result<()>;
#[zbus(signal)]
pub async fn new_overlay_icon(ctxt: &SignalEmitter<'_>) -> zbus::Result<()>;
#[zbus(signal)]
pub async fn new_status(ctxt: &SignalEmitter<'_>, status: &str) -> zbus::Result<()>;
#[zbus(signal)]
pub async fn new_title(ctxt: &SignalEmitter<'_>) -> zbus::Result<()>;
#[zbus(signal)]
pub async fn new_tool_tip(ctxt: &SignalEmitter<'_>) -> zbus::Result<()>;
#[zbus(property)]
fn menu(&self) -> zbus::zvariant::OwnedObjectPath {
MENU_PATH.into()
}
#[zbus(property)]
fn tool_tip(&self) -> zbus::fdo::Result<ToolTip> {
self.program.tool_tip(&self.state)
}
#[zbus(property)]
fn icon_theme_path(&self) -> zbus::fdo::Result<String> {
self.program.icon_theme_path(&self.state)
}
#[zbus(property)]
fn icon_name(&self) -> zbus::fdo::Result<String> {
self.program.icon_name(&self.state)
}
#[zbus(property)]
fn icon_pixmap(&self) -> zbus::fdo::Result<Vec<IconPixmap>> {
self.program.icon_pixmap(&self.state)
}
#[zbus(property)]
fn attention_icon_name(&self) -> zbus::fdo::Result<String> {
self.program.attention_icon_name(&self.state)
}
#[zbus(property)]
fn attention_icon_pixmap(&self) -> zbus::fdo::Result<Vec<IconPixmap>> {
self.program.attention_icon_pixmap(&self.state)
}
#[zbus(property)]
fn attention_movie_name(&self) -> zbus::fdo::Result<String> {
self.program.attention_movie_name(&self.state)
}
#[zbus(property)]
fn overlay_icon_name(&self) -> zbus::fdo::Result<String> {
self.program.overlay_icon_name(&self.state)
}
#[zbus(property)]
fn overlay_icon_pixmap(&self) -> zbus::fdo::Result<Vec<IconPixmap>> {
self.program.overlay_icon_pixmap(&self.state)
}
#[zbus(property)]
fn category(&self) -> Category {
self.program.category()
}
#[zbus(property)]
fn id(&self) -> zbus::fdo::Result<String> {
Ok(self.program.id())
}
#[zbus(property)]
fn status(&self) -> zbus::fdo::Result<NotifierStatus> {
self.program.status(&self.state)
}
#[zbus(property)]
fn title(&self) -> zbus::fdo::Result<String> {
self.program.title(&self.state)
}
#[zbus(property)]
fn item_is_menu(&self) -> zbus::fdo::Result<bool> {
Ok(self.program.item_is_menu(&self.state))
}
#[zbus(property)]
fn window_id(&self) -> zbus::fdo::Result<i32> {
self.program.window_id(&self.state)
}
}