mirror of
https://github.com/LizardByte/tray.git
synced 2026-10-23 03:27:02 +09:00
fix(linux): fall back when display is inaccessible (#189)
This commit is contained in:
1 parent
e479042a0e
commit
c1f2a8ab56
3 files changed
+115
-6
No files matched your search
+47
-6
@@ -4,6 +4,8 @@
|
||||
*/
|
||||
// standard includes
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
// qt includes
|
||||
#include <QByteArray>
|
||||
@@ -16,6 +18,7 @@
|
||||
// local includes
|
||||
#include "QtTrayMenu.h"
|
||||
#include "tray.h"
|
||||
#include "tray_qt.h"
|
||||
|
||||
namespace tray_qt {
|
||||
/**
|
||||
@@ -91,16 +94,54 @@ namespace tray_qt {
|
||||
current_state.trayMenu->configureAppMetadata(current_state.appName, current_state.appDisplayName, current_state.desktopName);
|
||||
}
|
||||
|
||||
std::string select_platform_plugins(
|
||||
const std::string_view requested_platform,
|
||||
const std::string_view session_type,
|
||||
const std::string_view wayland_display,
|
||||
const std::string_view x11_display
|
||||
) {
|
||||
if (!requested_platform.empty()) {
|
||||
return std::string {requested_platform};
|
||||
}
|
||||
|
||||
std::string platforms;
|
||||
const auto append_platform = [&platforms](const std::string_view platform) {
|
||||
if (!platforms.empty()) {
|
||||
platforms.push_back(';');
|
||||
}
|
||||
platforms.append(platform);
|
||||
};
|
||||
const bool prefer_x11 = session_type == "x11" || session_type == "X11";
|
||||
|
||||
if (prefer_x11 && !x11_display.empty()) {
|
||||
append_platform("xcb");
|
||||
}
|
||||
if (!wayland_display.empty()) {
|
||||
append_platform("wayland");
|
||||
}
|
||||
if (!prefer_x11 && !x11_display.empty()) {
|
||||
append_platform("xcb");
|
||||
}
|
||||
append_platform("minimal");
|
||||
return platforms;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure Linux headless fallback for Qt.
|
||||
* @brief Configure Linux Qt platform candidates with a headless fallback.
|
||||
*/
|
||||
void configure_platform() {
|
||||
#if defined(__linux__)
|
||||
// Check if a (wayland_)display is set or fallback to minimal QPA platform
|
||||
if (qgetenv("WAYLAND_DISPLAY").isEmpty() && qgetenv("DISPLAY").isEmpty()) {
|
||||
// Force fallback to QT platform minimal if no (WAYLAND_)DISPLAY was found
|
||||
qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("minimal"));
|
||||
qWarning("QtTrayMenu: no reachable WAYLAND_DISPLAY or DISPLAY endpoint, forcing QT_QPA_PLATFORM=minimal");
|
||||
const auto requested_platform = qgetenv("QT_QPA_PLATFORM");
|
||||
const auto platforms = select_platform_plugins(
|
||||
requested_platform.toStdString(),
|
||||
qgetenv("XDG_SESSION_TYPE").toStdString(),
|
||||
qgetenv("WAYLAND_DISPLAY").toStdString(),
|
||||
qgetenv("DISPLAY").toStdString()
|
||||
);
|
||||
if (requested_platform.isEmpty()) {
|
||||
const auto qt_platforms = QByteArray::fromStdString(platforms);
|
||||
qputenv("QT_QPA_PLATFORM", qt_platforms);
|
||||
qDebug() << "QtTrayMenu: configured platform fallback chain:" << qt_platforms;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @file src/tray_qt.h
|
||||
* @brief Internal helpers for the Qt system tray implementation.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// standard includes
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace tray_qt {
|
||||
/**
|
||||
* @brief Select the ordered Qt platform plugin candidates for Linux.
|
||||
*
|
||||
* An explicit platform selection is preserved. Otherwise, available desktop
|
||||
* environment hints determine whether Wayland or X11 is tried first, and the
|
||||
* headless minimal plugin is retained as the final fallback.
|
||||
*
|
||||
* @param requested_platform Explicit QT_QPA_PLATFORM value.
|
||||
* @param session_type XDG session type, such as `wayland` or `x11`.
|
||||
* @param wayland_display WAYLAND_DISPLAY value.
|
||||
* @param x11_display DISPLAY value.
|
||||
* @return Semicolon-separated Qt platform plugin candidates.
|
||||
*/
|
||||
std::string select_platform_plugins(
|
||||
std::string_view requested_platform,
|
||||
std::string_view session_type,
|
||||
std::string_view wayland_display,
|
||||
std::string_view x11_display
|
||||
);
|
||||
} // namespace tray_qt
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
// local includes
|
||||
#include "src/tray.h"
|
||||
#include "src/tray_qt.h"
|
||||
|
||||
// standard includes
|
||||
#include <array>
|
||||
@@ -50,6 +51,42 @@ namespace {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(TrayQtPlatformTest, PreservesExplicitPlatformSelection) {
|
||||
EXPECT_EQ(
|
||||
tray_qt::select_platform_plugins("offscreen", "wayland", "wayland-0", ":0"),
|
||||
"offscreen"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(TrayQtPlatformTest, UsesMinimalPlatformWithoutDesktopEnvironment) {
|
||||
EXPECT_EQ(
|
||||
tray_qt::select_platform_plugins({}, {}, {}, {}),
|
||||
"minimal"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(TrayQtPlatformTest, AddsMinimalFallbackForSingleDisplayProtocol) {
|
||||
EXPECT_EQ(
|
||||
tray_qt::select_platform_plugins({}, "wayland", "wayland-0", {}),
|
||||
"wayland;minimal"
|
||||
);
|
||||
EXPECT_EQ(
|
||||
tray_qt::select_platform_plugins({}, "x11", {}, ":0"),
|
||||
"xcb;minimal"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(TrayQtPlatformTest, PrefersSessionProtocolBeforeHeadlessFallback) {
|
||||
EXPECT_EQ(
|
||||
tray_qt::select_platform_plugins({}, "wayland", "wayland-0", ":0"),
|
||||
"wayland;xcb;minimal"
|
||||
);
|
||||
EXPECT_EQ(
|
||||
tray_qt::select_platform_plugins({}, "X11", "wayland-0", ":0"),
|
||||
"xcb;wayland;minimal"
|
||||
);
|
||||
}
|
||||
|
||||
class TrayQtCoverageTest: public BaseTest {
|
||||
private:
|
||||
bool trayRunning_ {false};
|
||||
|
||||
Reference in new issue
Block a user