elkowar / eww

ElKowars wacky widgets
https://elkowar.github.io/eww
MIT License
9.36k stars 382 forks source link

[FEATURE] Tray Support #111

Closed undefinedDarkness closed 7 months ago

undefinedDarkness commented 3 years ago

Description of the requested feature

Give a clear and concise description of the feature you are proposing, including examples for when it would be useful. A widget for the system tray allowing eww to be used for a bar more easily.

Proposed configuration syntax

If the feature you are requesting would add or change something to the Eww configuration, please provide an example for how the feature could be used.

<tray />

Additional context

Add any other context or screenshots about the feature request here.

undefinedDarkness commented 3 years ago

Stalonetray might work in the mean time

undefinedDarkness commented 3 years ago

Ive done some thonking... The easiest way to implement this would be to use stalonetray & xembed it?

elkowar commented 3 years ago

oooooooooooooph that sounds super hacky,.... but if it works well i'm not completely ruling it out. a proper implementation of a systray may be cool - but also effort :(

snakedye commented 3 years ago

Waybar doesn't seem to rely on any X11 or Wayland fuckery.

thyeun commented 3 years ago

Possible to using autostart.sh (as a user of Qtile), to show the systray, by a key press?

legendofmiracles commented 3 years ago

There's this standalone systray, https://github.com/sargon/trayer-srg, that can be used as a temporary solution for a sys tray. The location of where it displays is easily configurable with flags

thyeun commented 3 years ago

ArcoLinux-2021-05-18-1621337906_screenshot_1366x768

Cant make it work (not show-up anything) :( , will try again later on, might be something that not include correctly

undefinedDarkness commented 3 years ago

I saw taffybar do something like what we want, it's in haskell tho and uses a package so I can't make head or tail of the code

hiukky commented 3 years ago

It would be an excellent resource! +1

Animeshz commented 3 years ago

Not entirely sure but tint2 panel's systray integration (systraybar.c) can be looked for inspiration.

SystematicError commented 2 years ago

Hey just bumping this thread as I have some questions:

  1. Is this on the roadmap or will this require a lot of fiddling to get something stable?
  2. Is any hacky workaround like the suggested xembed possible for a user to do? and how?
OlfillasOdikno commented 2 years ago

Hey, I have written a simple POC that dumps the title and icon of tray items as JSON, since I don't write rust often and it was hacked together, the code quality is quite bad. But I hope that it can kick-start development. I may implement it myself at some point in the future, if nobody else is willing to, but I need to properly learn Rust before. For reference: GitHub repo

oknozor commented 2 years ago

Hello, I made a prototype using literal to show a system tray. The code can be found here : https://github.com/oknozor/eww-tray

screenshot-2022-04-19T13:47:54+0200

What works ?

What does not work (yet) ?

Should this be directly integrated in eww ?

At first I tried to integrate this into the eww codebase but it felt very hacky:

Once https://github.com/elkowar/eww/pull/350 is merged it would be better to use the for widget instead literal. This way eww-tray would only needs to return some json representing the tray menus.

But I am still wondering if it would be worth it to implement all the DBus logic in eww, printing some json to stdout and using deflisten to get the system tray icons and menus seems sufficient.

What's your take on this @elkowar ?

thyeun commented 2 years ago

@oknozor will try it on my current eww-bar and thanks alot.

elkowar commented 2 years ago

Damn, I haven't been watching this thread all that actively, yall are doing some crazy cool stuff! I do think it's desirable to have support for a full on systray, including menus and everything as a builtin part in eww.

Ill be looking through the code you've all been working on, and see how well that might fit into ewws structure.

There's a few sides to exposing the systray widget wise: the simplest way would be to just have a systray widget, which shows all the icons and has some basic configurability for how it looks. This would be a viable mvp, but,.. Honestly somewhat boring.

What I'd love to do would be to provide as much flexibility in how the systray is shown as possible. This could mean basic things like customizing the positioning, layout, conditionally rendering only some icons, etc, but could also go further into possibly exposing the menus in fancier ways, depending on how feasible that is.

I'll try to actually look into this more closely soon, and I'll be giving updates!

elkowar commented 2 years ago

@oknozor so looking at your code,... how much of that do you reckon could realistically be abstracted into it's own, self-contained library crate that might be just directly used by eww (and others, possibly) to get the systray infomation? I'll still need to do more reading on how the systray spec/api actually works, of course

oknozor commented 2 years ago

As the spec mention, their are three processes involved, communicating via DBus :

The prototype I made receives updates from those Dbus services via a tokio channel, this is the part responsible for updating the UI : https://github.com/oknozor/eww-tray/blob/116ef9bb9454daf4a73a954e85b1a28441543670/src/tray.rs#L81

It's realy simple actually, just a hashmap containing the system tray data.

To warp this in a crate you'd need to expose a way to start the ui reveicer and another function start the three Dbus related tasks. Message would be wrapped in a struct representing the tray state (icon + menu) as described here.

It would somehow look like this :

let (tx, rx) = channel();

// Spawn all the Dbus boring stuff
tokio::spawn(async {start_status_notifier(tx)}); 

// Receive Tray updates
while le Some(message) = rx.recv().await {
  // Do some stuff with the UI.
}

This would be quite simple to pull off actually, I will try to do this and keep you updated.

oknozor commented 2 years ago

Of course this would heavily rely on tokio, I am not sure how independent from the async runtime it could be. I'll go for the simplest API possible and try to refine it later if needed.

oknozor commented 2 years ago

@elkowar quick update, I have been working on the library this morning, here is an working example of the public API :

#[tokio::main]
pub async fn main() -> anyhow::Result<()> {
    let mut stream = SystemTray::new().await;

    while let Some(message) = stream.next().await {
        match message {
            Message::Update { address, icon } => {
                println!("{:?} -> {:?}", address, icon);
            }
            Message::Remove { address } => {
                println!("{:?}", address);
            }
        }
    }

    Ok(())
}

Also I managed to make it runtime agnostic, all you need is some StreamExt trait in scope. I still need to get rid of anyhow in the crate and parse more of the Dbus messages (icon and menus).

andornaut commented 2 years ago

@oknozor Just curious: how are you planning on supporting menus?

oknozor commented 2 years ago

@andornaut I am looking into this right now, I am not sure yet.

As far as I understand existing implementation just send the Dbus address of the menu and the ui is responsible for making the call to dbus to get the menu widget (wrapped in libdbusmenu-qt or libdbusmenu-gtk3).

It's super convenient for gtk/qt app but it might be better to re-expose the menu in our own wrapper so the systray lib does not depend on gtk in our case. That said it's still early to make a decision, I still need to get deeper in libdmenu. I suspect implementing the menu widget from the raw dbus data will be a ton of boiler plate, that would explain why qt and qtk have a dedicated lib for this.

Honestly I need to dig deeper before taking any decision.

Also advice are more than welcome, I have no experience with all those UI shenanigans :laughing:

oknozor commented 2 years ago

Made some progress with the menus, It still super tricky to implement this using yuck without the for loops but I am getting there.

I still need to write some doc and clean everything up before publishing a crate but it shall soon be usable. The system tray implementation is now only lacking the ability to activate the menu items.

screenshot_20220423_191848

andornaut commented 2 years ago

Made some progress with the menus, It still super tricky to implement this using yuck without the for loops but I am getting there.

For-loops have been merged in #350

This is super exciting. Thanks, @oknozor !

oknozor commented 2 years ago

Everything is now functional !

There is still room for improvement but it works. I did not implement this in eww but I created a gtk frontend so it will be easy to port to eww now.

image

PR coming soon.

oknozor commented 2 years ago

So I have been trying to port this to eww but I have to admit I am lost.

I lack the gtk knowledge and I am really not sure how to properly handle the global system tray state in eww, pass the mscp sender to the widget, bind the styling properties to the menu child widget etc.

If someone is willing to try including this in eww, or at least provide some guidance (@elkowar :pray: ), the systray crate is now available here : https://crates.io/crates/stray.

There is also a crappy gtk example on the repo : https://github.com/oknozor/stray/blob/main/gtk-tray/src/main.rs

elkowar commented 2 years ago

I'll definitely look into this soon, thanks a ton already for all the work you put into this!

Looking into a bit more spec stuff, there seem to be two specs for systray stuff: the StatusNotifierItem thing as well as an older(?) systemtray spec. Looking through other systray apps it appears that most of those focus on the older spec - did you find this to work for most/all apps, or is that where the missing icons etc are coming from? (some apps only exposing stuff via the older spec)

oknozor commented 2 years ago

The older spec is the Xembed protocol.

For now the crate I made focus on the StatusNotifierItem spec only and I am not sure it's worth implementing xembed yet.

I didn't found any app that use Xembed only. There was nm-applet but I just found out there is a --indicator flag to launch it using the StatusNotifierItem spec.

I guess we should focus on the current specification and maybe later implement some kind of proxy if people wants it. Sway recommend the following :

There are two standards for status icons: XEmbed and StatusNotifierItem (SNI). XEmbed is legacy and unimplemented in Sway. SNI is supported by swaybar. If your app uses XEmbed, the status icon won't show up. You should ask them to upgrade to SNI.

mateodd25 commented 1 year ago

Any progress on this front? I really wish I could have a tray.

developomp commented 1 year ago

Any progress on this front? I really wish I could have a tray.

It is currently very experimental, but you can try #448

Henry-Hiles commented 1 year ago

The older spec is the Xembed protocol.

For now the crate I made focus on the StatusNotifierItem spec only and I am not sure it's worth implementing xembed yet.

I didn't found any app that use Xembed only. There was nm-applet but I just found out there is a --indicator flag to launch it using the StatusNotifierItem spec.

I guess we should focus on the current specification and maybe later implement some kind of proxy if people wants it. Sway recommend the following :

There are two standards for status icons: XEmbed and StatusNotifierItem (SNI). XEmbed is legacy and unimplemented in Sway. SNI is supported by swaybar. If your app uses XEmbed, the status icon won't show up. You should ask them to upgrade to SNI.

I believe that wine uses xembed only. On waybar I am able to work around this by running xembedsniproxy in the background, not sure if that would work for eww as well. Looking forward to making an eww bar as soon as systray is merged :)

mortymacs commented 1 year ago

+1 No news about this issue?

Prayag2 commented 10 months ago

Any updates?

MrDiver commented 9 months ago

743