Skip to content

Commit bd83ea9

Browse files
Fix tray menu focus and icon loading on Linux
Replace QApplication::setActiveWindow with menu->activateWindow() to give the menu X11 focus before popup() and clarify the comment. Include QPixmap and change icon resolution logic: when the icon string refers to an existing file, load a QPixmap and add it to a QIcon immediately (avoiding QIcon's lazy loading that leaves availableSizes() empty and can produce a blank tray icon with Qt6 SNI). Fall back to QIcon::fromTheme() when the file doesn't exist. Keep guarding against setting null icons.
1 parent b9434ce commit bd83ea9

1 file changed

Lines changed: 18 additions & 5 deletions

File tree

src/tray_linux.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <QGuiApplication>
2020
#include <QIcon>
2121
#include <QMenu>
22+
#include <QPixmap>
2223
#include <QScreen>
2324
#include <QSystemTrayIcon>
2425
#include <QTimer>
@@ -266,17 +267,16 @@ extern "C" {
266267
// event-loop iteration via QTimer::singleShot(0). Deferring allows any
267268
// platform pointer grab from the tray click to be released before the menu
268269
// establishes its own grab.
269-
// QApplication::setActiveWindow gives the menu window X11 focus so that the
270-
// subsequent XGrabPointer inside popup() succeeds, enabling click-outside
271-
// dismissal on Xorg.
270+
// activateWindow() gives the menu window X11 focus so that the subsequent
271+
// XGrabPointer inside popup() succeeds, enabling click-outside dismissal on Xorg.
272272
QObject::connect(g_tray_icon, &QSystemTrayIcon::activated, [](QSystemTrayIcon::ActivationReason reason) {
273273
if (reason == QSystemTrayIcon::Trigger) {
274274
const QPoint pos = calculateMenuPosition();
275275
QTimer::singleShot(0, g_tray_icon, [pos]() {
276276
if (g_tray_icon != nullptr) {
277277
QMenu *menu = g_tray_icon->contextMenu();
278278
if (menu != nullptr && !menu->isVisible()) {
279-
QApplication::setActiveWindow(menu);
279+
menu->activateWindow();
280280
menu->popup(pos);
281281
}
282282
}
@@ -337,7 +337,20 @@ extern "C" {
337337
}
338338

339339
const QString icon_str = QString::fromUtf8(tray->icon);
340-
const QIcon icon = QFileInfo(icon_str).exists() ? QIcon(icon_str) : QIcon::fromTheme(icon_str);
340+
QIcon icon;
341+
const QFileInfo icon_fi(icon_str);
342+
if (icon_fi.exists()) {
343+
// Explicitly load via QPixmap so that the icon engine has pixmap data and
344+
// availableSizes() is populated immediately. QIcon(filename) lazy-loads the
345+
// pixmap, which leaves availableSizes() empty; Qt6's SNI tray backend then
346+
// sees no sizes and sends no icon data, causing the tray icon to be blank.
347+
const QPixmap pixmap(icon_fi.absoluteFilePath());
348+
if (!pixmap.isNull()) {
349+
icon.addPixmap(pixmap);
350+
}
351+
} else {
352+
icon = QIcon::fromTheme(icon_str);
353+
}
341354
// Only update the icon when the resolved icon is valid. Setting a null icon
342355
// clears the tray icon and triggers "No Icon set" warnings (Qt6 is stricter
343356
// about QIcon::fromTheme when the name is not found in the active theme).

0 commit comments

Comments
 (0)