Closed rieje closed 3 years ago
Hi, and thanks again for reporting!
As you noted, the menu not being flat with wayland/appindicator is a workaround for a bug with dynamically sized menus that I currently don't see any other way to mitigate on udiskie side, other than possibly switching to another KSNI implementation. It should be fixed upstream (but I'm not sure whether in sway, wayland, waybar, or appindicator).
Regarding the second issue, this seems to be an upstream bug as well. I checked that setting the indicator's status to APP_INDICATOR_STATUS_PASSIVE
has no effect in sway (even though this should hide the icon according to the docs).
I considered the following potential workaround: let udiskie destroy and create the icon entirely rather than just update its status. However, the AppIndicator3 API
sadly doesn't seem to expose any method to actually get rid of the icon (appindicator is just ridiculously broken.....). So one would have to hope that nobody else holds a reference to the indicator object and that it is hidden after the python object is freed. Consider the following minimal example:
import sys
import signal
import weakref
from gi import require_version
require_version('GLib', '2.0')
require_version('Gtk', '3.0')
require_version('AppIndicator3', '0.1')
from gi.repository import GLib
from gi.repository import Gtk
from gi.repository import AppIndicator3
ACTIVE = AppIndicator3.IndicatorStatus.ACTIVE
PASSIVE = AppIndicator3.IndicatorStatus.PASSIVE
def create_icon():
indicator = AppIndicator3.Indicator.new(
'myappindicator',
'ICON-NOT-FOUND',
AppIndicator3.IndicatorCategory.OTHER)
menu = Gtk.Menu()
item_quit = Gtk.MenuItem()
item_quit.set_label('Quit')
item_quit.connect('activate', Gtk.main_quit)
menu.append(item_quit)
menu.show_all()
indicator.set_menu(menu)
return indicator
class NormalModeIcon:
def __init__(self):
self.icon = create_icon()
def is_active(self):
return self.icon.get_status() == ACTIVE
def show(self):
self.icon.set_status(ACTIVE)
def hide(self):
self.icon.set_status(PASSIVE)
class WorkaroundIcon:
def __init__(self):
self.icon = None
def is_active(self):
return self.icon is not None
def show(self):
self.icon = create_icon()
self.icon.set_status(ACTIVE)
# get notified when the `Indicator` object is finalized:
self.w = weakref.ref(self.icon, print)
def hide(self):
self.icon = None
def toggle_icon(icon):
if icon.is_active():
print("hide")
icon.hide()
else:
print("show")
icon.show()
return True
def main(mode='normal'):
if mode == 'normal':
icon = NormalModeIcon()
else:
icon = WorkaroundIcon()
GLib.timeout_add(1000, toggle_icon, icon)
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
if __name__ == '__main__':
main(*sys.argv[1:])
Call it like this for the normal mode:
python appindicator.py normal
or like this to try the workaround:
python appindicator.py workaround
For me, both work in X, neither works in sway.
Note that the weakref shows that the python Indicator proxy is in fact destroyed, but the system icon stays visible nevertheless.
Now, we could of course go further in the workaround and create the icon each time in their own subprocess and stop the process to hide it (and that might actually work, maybe?), but that's obviously ridiculous :)
I have forwarded the issue to waybar, see https://github.com/Alexays/Waybar/issues/1150, but I wouldn't count on this being addressed anytime soon, as they might be overwhelmed by issues.
Best, Thomas
Should be fixed as of waybar v0.9.8.
On X11, I run udiskie
udiskie --no-automount --smart-tray &
and with rules that work as expected--ignored devices such as internal drives are ignored. There is no tray icon until an external drive is plugged in.On Wayland, the same command will always show the tray icon on Waybar (even with
--appindicator
option and withlibappindicator-gtk3
installed)--even when there are only ignored drives. In addition, despite having a setting the menu asflat
, it show a menu "Managed devices
" containing both ignored (like my internal drives) and unignored drives. I prefer a flat menu for convenience via less clicks and visibility. I think this workaround is whyManaged devices
parent menu exists despite setting menu to be flat, but I'm also not sure if that might also be what is preventing smart tray from being hidden when there are no unignored devices.I know you found AppIndicator to be broken, so it might be the culprit.