eww icon indicating copy to clipboard operation
eww copied to clipboard

[FEATURE] Tray Support

Open undefinedDarkness opened this issue 3 years ago • 33 comments

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 avatar Feb 09 '21 13:02 undefinedDarkness

Stalonetray might work in the mean time

undefinedDarkness avatar Feb 09 '21 13:02 undefinedDarkness

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

undefinedDarkness avatar Mar 31 '21 02:03 undefinedDarkness

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 :(

elkowar avatar Apr 03 '21 22:04 elkowar

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

snakedye avatar May 12 '21 13:05 snakedye

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

thyeun avatar May 15 '21 15:05 thyeun

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

legendofmiracles avatar May 18 '21 10:05 legendofmiracles

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

thyeun avatar May 18 '21 11:05 thyeun

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

undefinedDarkness avatar May 18 '21 14:05 undefinedDarkness

It would be an excellent resource! +1

hiukky avatar May 22 '21 00:05 hiukky

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

Animeshz avatar Sep 13 '21 08:09 Animeshz

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?

SystematicError avatar Dec 30 '21 17:12 SystematicError

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

OlfillasOdikno avatar Jan 29 '22 05:01 OlfillasOdikno

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 ?

  • icons are displayed
  • icons gets removed when their tray app closes
  • icons update correctly (chat notification etc)

What does not work (yet) ?

  • no menu
  • icons does not show up for some apps (bluez, transmission ... )

Should this be directly integrated in eww ?

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

  • the system tray needs a global state and currently builtin variable are only obtained via polling sysinfo
  • there is currently no way to render a widget dynamically from a json array

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 ?

oknozor avatar Apr 19 '22 12:04 oknozor

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

thyeun avatar Apr 19 '22 12:04 thyeun

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 avatar Apr 19 '22 14:04 elkowar

@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

elkowar avatar Apr 19 '22 19:04 elkowar

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 avatar Apr 19 '22 21:04 oknozor

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 avatar Apr 19 '22 22:04 oknozor

@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).

oknozor avatar Apr 20 '22 08:04 oknozor

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

andornaut avatar Apr 21 '22 13:04 andornaut

@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 avatar Apr 21 '22 14:04 oknozor

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

oknozor avatar Apr 23 '22 17:04 oknozor

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 !

andornaut avatar Apr 23 '22 17:04 andornaut

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 avatar Apr 26 '22 22:04 oknozor

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

oknozor avatar Apr 27 '22 10:04 oknozor

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)

elkowar avatar Apr 27 '22 14:04 elkowar

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.

oknozor avatar Apr 28 '22 06:04 oknozor

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

mateodd25 avatar Dec 16 '22 17:12 mateodd25

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

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

developomp avatar Dec 17 '22 04:12 developomp

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 :)

Henry-Hiles avatar Jan 27 '23 19:01 Henry-Hiles