I’ve been exploring this issue. I found out a way to reproduce it easily and a workaround.
The issue
So reading the different comments here and there and with my personal experience, we see that some icons show a white square (for example network manager applet for sys-net, or bluetooth applet for sys-audio) but some icons appear correctly (like sdwdate-gui for Whonix or VLC).
Let’s check the source code for the working applets:
sdwdate-gui: sdwdate-gui/usr/lib/python3/dist-packages/sdwdate_gui/sdwdate_gui.py at master · Kicksecure/sdwdate-gui · GitHub
VLC: vlc/modules/gui/qt/dialogs/systray/systray.cpp at master · videolan/vlc · GitHub
Both are using Qt’s QSystemTrayIcon class. And nm-applet used for network manager is GTK3. So we can assume from here that GTK is buggy but not Qt.
Tests
To test it better, let’s create a simple system tray icon in python.
GTK3 / AppIndicator3:
#!/usr/bin/python3
import os, gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk as gtk, AppIndicator3 as appindicator
def main():
indicator = appindicator.Indicator.new("customtray", "actor", appindicator.IndicatorCategory.APPLICATION_STATUS)
indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
indicator.set_menu(menu())
gtk.main()
def menu():
menu = gtk.Menu()
exittray = gtk.MenuItem('Exit Tray')
exittray.connect('activate', quit)
menu.append(exittray)
menu.show_all()
return menu
def quit(_):
gtk.main_quit()
if __name__ == "__main__":
main()
GTK3 / pystray:
import pystray
from PIL import Image
image = Image.open("icon.png")
def after_click(icon, query):
if str(query) == "Exit":
icon.stop()
icon = pystray.Icon(
'testname', image, 'Test Name',
menu=pystray.Menu(
pystray.MenuItem("Exit", after_click)
)
)
icon.run()
If you run these two scripts in an appVM, it will display the buggy white square. The rest is working (Left-click on it shows the menu with a border of the appVM’s color).
Qt5:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
app = QApplication([])
app.setQuitOnLastWindowClosed(False)
# Create the icon
icon = QIcon("icon.png")
# Create the tray
tray = QSystemTrayIcon()
tray.setIcon(icon)
tray.setVisible(True)
# Create the menu
menu = QMenu()
action = QAction("A menu item")
menu.addAction(action)
# Add a Quit option to the menu.
quit = QAction("Quit")
quit.triggered.connect(app.quit)
menu.addAction(quit)
# Add the menu to the tray
tray.setContextMenu(menu)
app.exec_()
Now this script displays the icon correctly.
Summary
So to sum up, the issue occurs with GTK3 icons. We still need to investigate why, but we know that using Qt icons work as expected.
Another thing will be to try using KDE instead of XFCE in a template, maybe it will at least fix network and audio widgets.