Use icon.visible to show or hide the tray icon on all systems

On Linux, pystray's icon.stop() currently doesn't work well with the
AppIndicator backend.

So, instead of destroying the icon when the user restores from tray
(only to later re-create it when the user minimizes to tray again), we
have the option to control the icon's visibility instead! Luckily, that
works on Windows too!

Note that for this change to work properly on Linux, we need to switch
to the master version of pystray, because we need this specific fix:

https://github.com/moses-palmer/pystray/commit/5943ed4e19be48224cf39b70444de8ffe22c23ce

After pystray releases a version newer than 0.19.4, we can switch back.

Co-authored-by: DevilXD <bartosz.peszek@gmail.com>
This commit is contained in:
guihkxandDevilXD authored and DevilXD committed 2023-06-11 16:58:18 +02:00
1 parent 7a07e1a9e4
commit f8c0dba1ee
2 files changed
+26 -25

No files matched your search

+24 -24
View File
@@ -1048,11 +1048,9 @@ class TrayIcon:
self._button.grid(column=0, row=0, sticky="ne")
def __del__(self) -> None:
self.stop()
self.icon_image.close()
def is_tray(self) -> bool:
return self.icon is not None
def get_title(self, drop: TimedDrop | None) -> str:
if drop is None:
return self.TITLE
@@ -1064,23 +1062,22 @@ class TrayIcon:
f"{drop.progress:.1%} ({campaign.claimed_drops}/{campaign.total_drops})"
)
def start(self):
if self.icon is None:
loop = asyncio.get_running_loop()
drop = self._manager.progress._drop
def _start(self):
loop = asyncio.get_running_loop()
drop = self._manager.progress._drop
# we need this because tray icon lives in a separate thread
def bridge(func):
return lambda: loop.call_soon_threadsafe(func)
# we need this because tray icon lives in a separate thread
def bridge(func):
return lambda: loop.call_soon_threadsafe(func)
menu = pystray.Menu(
pystray.MenuItem(_("gui", "tray", "show"), bridge(self.restore), default=True),
pystray.Menu.SEPARATOR,
pystray.MenuItem(_("gui", "tray", "quit"), bridge(self.quit)),
)
self.icon = pystray.Icon("twitch_miner", self.icon_image, self.get_title(drop), menu)
# self.icon.run_detached()
loop.run_in_executor(None, self.icon.run)
menu = pystray.Menu(
pystray.MenuItem(_("gui", "tray", "show"), bridge(self.restore), default=True),
pystray.Menu.SEPARATOR,
pystray.MenuItem(_("gui", "tray", "quit"), bridge(self.quit)),
)
self.icon = pystray.Icon("twitch_miner", self.icon_image, self.get_title(drop), menu)
# self.icon.run_detached()
loop.run_in_executor(None, self.icon.run)
def stop(self):
if self.icon is not None:
@@ -1091,13 +1088,16 @@ class TrayIcon:
self._manager.close()
def minimize(self):
if not self.is_tray():
self.start()
self._manager._root.withdraw()
if self.icon is None:
self._start()
else:
self.icon.visible = True
self._manager._root.withdraw()
def restore(self):
if self.is_tray():
self.stop()
if self.icon is not None:
# self.stop()
self.icon.visible = False
self._manager._root.deiconify()
def notify(
@@ -1107,7 +1107,7 @@ class TrayIcon:
if not self._manager._twitch.settings.tray_notifications:
return None
if self.icon is not None:
icon = self.icon
icon = self.icon # nonlocal scope bind
async def notifier():
icon.notify(message, title)