fix(linux): migrate to qt tray#104
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #104 +/- ##
==========================================
- Coverage 73.06% 63.75% -9.32%
==========================================
Files 4 4
Lines 427 858 +431
Branches 83 313 +230
==========================================
+ Hits 312 547 +235
- Misses 72 208 +136
- Partials 43 103 +60
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Sentry.
|
8341803 to
aff9e33
Compare
998ffb0 to
c06fa40
Compare
Screenshot ComparisonPR #104 screenshots vs Matrix:
|
| Image | Baseline | PR |
|---|---|---|
tray_icon_initial.png |
||
tray_menu_checkbox_checked.png |
![]() |
|
tray_menu_checkbox_unchecked.png |
![]() |
|
tray_menu_shown.png |
![]() |
|
tray_notification_displayed.png |
![]() |
Matrix: Linux-libayatana-appindicator3-dev
| Image | Baseline | PR |
|---|---|---|
tray_icon_initial.png |
||
tray_menu_checkbox_checked.png |
![]() |
|
tray_menu_checkbox_unchecked.png |
![]() |
|
tray_menu_shown.png |
![]() |
|
tray_notification_displayed.png |
![]() |
Matrix: Linux-qt5
Matrix: Linux-qt6
Matrix: Windows
| Image | Baseline | PR |
|---|---|---|
tray_icon_initial.png |
||
tray_menu_checkbox_checked.png |
![]() |
![]() |
tray_menu_checkbox_unchecked.png |
![]() |
![]() |
tray_menu_shown.png |
![]() |
![]() |
tray_notification_displayed.png |
![]() |
![]() |
Matrix: macOS
| Image | Baseline | PR |
|---|---|---|
tray_icon_initial.png |
||
tray_menu_checkbox_checked.png |
![]() |
![]() |
tray_menu_checkbox_unchecked.png |
![]() |
![]() |
tray_menu_shown.png |
![]() |
![]() |
tray_notification_displayed.png |
![]() |
![]() |
0ce906a to
66665fb
Compare
be38d26 to
246b2e1
Compare
Add support for simulating notification clicks and routing D-Bus notification actions to callbacks. - Export tray_simulate_notification_click() in tray.h and provide platform implementations: no-op stubs for macOS and Windows, and a working simulator for Linux. - Introduce TrayNotificationHandler (src/tray_notification_handler.h) to handle org.freedesktop.Notifications ActionInvoked signals and invoke the stored callback when the "default" action is triggered. - Integrate the handler into the Linux tray: create/connect a single handler per QApplication, store callback and notification ID before calling Notify, set up a fallback that connects QSystemTrayIcon::messageClicked when D-Bus is unavailable, and clean up/disconnect the handler on app destroy. - Also connect QSystemTrayIcon::activated to popup the context menu on left/middle clicks (fixes missing menu on left-click). - Add unit tests verifying left-click menu popup and that notification callbacks fire when simulated (tests call tray_simulate_notification_click()). These changes ensure notification clicks are handled consistently for D-Bus-dispatched notifications and add a test hook for exercising the click behavior.
Expose tray_set_log_callback in the public API and implement it on Linux to forward Qt diagnostic messages to a user-provided callback (NULL restores default behavior). Add a Qt message handler and global callback state, and route qInstallMessageHandler accordingly; provide no-op stubs on macOS and Windows since Qt logging is not used there. Improve context-menu positioning by calculating a sensible popup point from the tray icon geometry (falling back to cursor position) and use it when showing menus. Defer D-Bus ActionInvoked connection via QTimer::singleShot to avoid QSocketNotifier warnings when the tray runs in a std::thread, and add a few related include adjustments and minor activation handling cleanup.
Detect Wayland sessions and improve context-menu placement by prioritizing tray icon geometry, then using QCursor on Xorg, and falling back to a screen-geometry heuristic on Wayland (inferring panel edge from full vs available geometry). Defer showing the menu with QTimer::singleShot(0) and call QApplication::setActiveWindow before popup() so pointer grabs and XGrabPointer behavior work reliably; avoid showing the menu if it's already visible. Also avoid clearing the tray icon by only setting it when the resolved QIcon is valid, preventing spurious "No Icon set" warnings.
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.
Delete legacy CMake find modules for AppIndicator and LibNotify
Add SVG tray icon support and make Linux tray handling more robust: - CMake: include icons/*.svg, link Qt Svg (Qt5/Qt6), and copy icon.svg to build dir. - Add new icons/icon.svg asset. - src/tray_linux.cpp: improve Wayland detection, calculate menu position with preferred position, derive screen anchor, retry popup logic, robust icon resolution (file, pixmap, themed), set application/desktop names, and fallback standard icon. - tests/unit/test_tray.cpp: ensure test icons are copied into the test binary directory, add TestTrayIconSvgFile unit test. These changes fix issues with blank tray icons (Qt/SNI) and unreliable menu placement on Wayland, and add SVG icon support across platforms.
Add a matrix dimension for Qt version and run builds for both Qt5 and Qt6 on Ubuntu. The build job name now includes the Qt version, and qt_version is set per matrix entry. Linux dependency installation is made conditional on QT_VERSION (installing Qt5 or Qt6 packages accordingly) and QT_VERSION is exported into the job environment. Split CMake configure and ninja build into separate steps, make test environment/platformtheme conditional, and append Qt version to artifact names and codecov flags. Update README to document Qt5 and Qt6 package installation commands for supported distros.
Replace QCoreApplication::applicationDisplayName and setApplicationDisplayName with QGuiApplication equivalents in src/tray_linux.cpp. This ensures the GUI-specific API is used when initializing the tray's display name (from tooltip or default), avoiding misuse of QCoreApplication for GUI-only display name operations.
Make CMakeLists usable as a subproject: detect top-level build (TRAY_IS_TOP_LEVEL) and gate BUILD_DOCS/BUILD_TESTS/BUILD_EXAMPLE on it. Don't override parent CMAKE_MODULE_PATH; append module path relative to current source dir. Centralize icon paths into TRAY_ICON_* variables, add tray_copy_default_icons() to copy icons at post-build, and install icons/headers. Use target_include_directories and expose compile definitions publicly for the library. Adjust Qt/Qt-version caching and other target properties. Update tests/CMakeLists.txt to use CMAKE_CURRENT_SOURCE_DIR paths, reference the googletest directory relatively, force shared CRT on Windows earlier, link the test target against tray::tray, add icon copying for the test binary, and register the test with add_test.
Add a new API tray_set_app_info to provide application metadata (name, display name, desktop file) used by the Linux/Qt backend and add no-op stubs for macOS and Windows. Improve Qt integration on Linux: add run_on_qt_thread helper, make g_exit_pending atomic, ensure all Qt GUI and teardown operations run on the Qt thread, and handle external event loops safely. Update notification/D-Bus handling and move tray updates, menu popup and simulated notification clicks onto the Qt thread to avoid cross-thread warnings. Also remove the QUIET flag from find_package(Qt6) in CMake and add necessary includes (atomic, utility, QThread).
Only perform install steps when the project is top-level by wrapping install commands in if(TRAY_IS_TOP_LEVEL). Also normalize to lowercase install() and remove the duplicated target name (was INSTALL(TARGETS tray tray ...)). This prevents unintended installs when the project is used as a subdirectory while preserving header and icon installations.
Add detection for reachable Wayland/X11 endpoints and fall back to the minimal QPA if none are present. Introduce QDir include and helper functions has_wayland_display_endpoint(), has_x11_display_endpoint(), and should_force_headless_qpa_fallback() to check WAYLAND_DISPLAY and DISPLAY (including XDG_RUNTIME_DIR sockets and /tmp/.X11-unix/X<n> sockets, as well as remote/TCP displays). If QT_QPA_PLATFORM is unset and no local display endpoints are found, set QT_QPA_PLATFORM=minimal before creating QApplication and emit a log via g_log_cb. This prevents trying to use GUI QPAs when no local display is reachable.
Add automatic discovery of a Wayland display socket when WAYLAND_DISPLAY is not set. Introduce discover_wayland_display_name() to scan XDG_RUNTIME_DIR for wayland-* entries (preferring wayland-0) and try_autodiscover_wayland_display() to export the found name via qputenv. Call the autodiscovery at tray initialization and emit a log message on success. Also include QStringList header required for the new code.
246b2e1 to
ff76d0e
Compare
Add the missing standard library header to src/tray_windows.c to ensure declarations for libc functions used in the file are available and to prevent implicit-declaration warnings or build errors.
|





































Description
Migrate to qt5/6 for Linux tray.
Screenshot
Issues Fixed or Closed
Roadmap Issues
Type of Change
Checklist
AI Usage