mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-06-18 14:40:56 +00:00
Move heavy SystemProperties loads to an opt-in model
This avoids heavyweight operations when we're not actually running config checks.
This commit is contained in:
@@ -98,13 +98,82 @@ SystemProperties::SystemProperties()
|
|||||||
hasDiscordIntegration = false;
|
hasDiscordIntegration = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unmappedGamepads = SdlInputHandler::getUnmappedGamepads();
|
|
||||||
|
|
||||||
// These will be queried asynchronously to avoid blocking the UI
|
// These will be queried asynchronously to avoid blocking the UI
|
||||||
hasHardwareAcceleration = true;
|
hasHardwareAcceleration = true;
|
||||||
rendererAlwaysFullScreen = false;
|
rendererAlwaysFullScreen = false;
|
||||||
supportsHdr = true;
|
supportsHdr = true;
|
||||||
maximumResolution = QSize(0, 0);
|
maximumResolution = QSize(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemProperties::~SystemProperties()
|
||||||
|
{
|
||||||
|
waitForAsyncLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemProperties::updateDecoderProperties(bool hasHardwareAcceleration, bool rendererAlwaysFullScreen, QSize maximumResolution, bool supportsHdr)
|
||||||
|
{
|
||||||
|
SDL_assert(testWindow);
|
||||||
|
|
||||||
|
if (hasHardwareAcceleration != this->hasHardwareAcceleration) {
|
||||||
|
this->hasHardwareAcceleration = hasHardwareAcceleration;
|
||||||
|
emit hasHardwareAccelerationChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rendererAlwaysFullScreen != this->rendererAlwaysFullScreen) {
|
||||||
|
this->rendererAlwaysFullScreen = rendererAlwaysFullScreen;
|
||||||
|
emit rendererAlwaysFullScreenChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maximumResolution != this->maximumResolution) {
|
||||||
|
this->maximumResolution = maximumResolution;
|
||||||
|
emit maximumResolutionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportsHdr != this->supportsHdr) {
|
||||||
|
this->supportsHdr = supportsHdr;
|
||||||
|
emit supportsHdrChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DestroyWindow(testWindow);
|
||||||
|
testWindow = nullptr;
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect SystemProperties::getNativeResolution(int displayIndex)
|
||||||
|
{
|
||||||
|
// Returns default constructed QRect if out of bounds
|
||||||
|
Q_ASSERT(!monitorNativeResolutions.isEmpty());
|
||||||
|
return monitorNativeResolutions.value(displayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect SystemProperties::getSafeAreaResolution(int displayIndex)
|
||||||
|
{
|
||||||
|
// Returns default constructed QRect if out of bounds
|
||||||
|
Q_ASSERT(!monitorSafeAreaResolutions.isEmpty());
|
||||||
|
return monitorSafeAreaResolutions.value(displayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SystemProperties::getRefreshRate(int displayIndex)
|
||||||
|
{
|
||||||
|
// Returns 0 if out of bounds
|
||||||
|
Q_ASSERT(!monitorRefreshRates.isEmpty());
|
||||||
|
return monitorRefreshRates.value(displayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemProperties::startAsyncLoad()
|
||||||
|
{
|
||||||
|
if (systemPropertyQueryThread) {
|
||||||
|
// Already started/completed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This isn't actually asynchronous (due to the need to synchronize with
|
||||||
|
// SdlGamepadKeyNavigation), but we don't query it in the constructor
|
||||||
|
// because it's expensive.
|
||||||
|
unmappedGamepads = SdlInputHandler::getUnmappedGamepads();
|
||||||
|
if (!unmappedGamepads.isEmpty()) {
|
||||||
|
emit unmappedGamepadsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
// We initialize the video subsystem and test window on the main thread
|
// We initialize the video subsystem and test window on the main thread
|
||||||
// because some platforms (macOS) do not support window creation on
|
// because some platforms (macOS) do not support window creation on
|
||||||
@@ -140,62 +209,11 @@ SystemProperties::SystemProperties()
|
|||||||
systemPropertyQueryThread->start();
|
systemPropertyQueryThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemProperties::~SystemProperties()
|
void SystemProperties::waitForAsyncLoad()
|
||||||
{
|
{
|
||||||
|
if (systemPropertyQueryThread) {
|
||||||
systemPropertyQueryThread->wait();
|
systemPropertyQueryThread->wait();
|
||||||
}
|
|
||||||
|
|
||||||
void SystemProperties::updateDecoderProperties(bool hasHardwareAcceleration, bool rendererAlwaysFullScreen, QSize maximumResolution, bool supportsHdr)
|
|
||||||
{
|
|
||||||
SDL_assert(testWindow);
|
|
||||||
|
|
||||||
if (hasHardwareAcceleration != this->hasHardwareAcceleration) {
|
|
||||||
this->hasHardwareAcceleration = hasHardwareAcceleration;
|
|
||||||
emit hasHardwareAccelerationChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rendererAlwaysFullScreen != this->rendererAlwaysFullScreen) {
|
|
||||||
this->rendererAlwaysFullScreen = rendererAlwaysFullScreen;
|
|
||||||
emit rendererAlwaysFullScreenChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maximumResolution != this->maximumResolution) {
|
|
||||||
this->maximumResolution = maximumResolution;
|
|
||||||
emit maximumResolutionChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportsHdr != this->supportsHdr) {
|
|
||||||
this->supportsHdr = supportsHdr;
|
|
||||||
emit supportsHdrChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_DestroyWindow(testWindow);
|
|
||||||
testWindow = nullptr;
|
|
||||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect SystemProperties::getNativeResolution(int displayIndex)
|
|
||||||
{
|
|
||||||
// Returns default constructed QRect if out of bounds
|
|
||||||
systemPropertyQueryThread->wait();
|
|
||||||
Q_ASSERT(!monitorNativeResolutions.isEmpty());
|
|
||||||
return monitorNativeResolutions.value(displayIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect SystemProperties::getSafeAreaResolution(int displayIndex)
|
|
||||||
{
|
|
||||||
// Returns default constructed QRect if out of bounds
|
|
||||||
systemPropertyQueryThread->wait();
|
|
||||||
Q_ASSERT(!monitorSafeAreaResolutions.isEmpty());
|
|
||||||
return monitorSafeAreaResolutions.value(displayIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SystemProperties::getRefreshRate(int displayIndex)
|
|
||||||
{
|
|
||||||
// Returns 0 if out of bounds
|
|
||||||
systemPropertyQueryThread->wait();
|
|
||||||
Q_ASSERT(!monitorRefreshRates.isEmpty());
|
|
||||||
return monitorRefreshRates.value(displayIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemProperties::refreshDisplays()
|
void SystemProperties::refreshDisplays()
|
||||||
|
|||||||
@@ -26,18 +26,22 @@ public:
|
|||||||
Q_PROPERTY(bool usesMaterial3Theme MEMBER usesMaterial3Theme CONSTANT)
|
Q_PROPERTY(bool usesMaterial3Theme MEMBER usesMaterial3Theme CONSTANT)
|
||||||
Q_PROPERTY(QString versionString MEMBER versionString CONSTANT)
|
Q_PROPERTY(QString versionString MEMBER versionString CONSTANT)
|
||||||
|
|
||||||
// Properties queried asynchronously
|
// Properties queried asynchronously (startAsyncLoad() must be called!)
|
||||||
Q_PROPERTY(bool hasHardwareAcceleration MEMBER hasHardwareAcceleration NOTIFY hasHardwareAccelerationChanged)
|
Q_PROPERTY(bool hasHardwareAcceleration MEMBER hasHardwareAcceleration NOTIFY hasHardwareAccelerationChanged)
|
||||||
Q_PROPERTY(bool rendererAlwaysFullScreen MEMBER rendererAlwaysFullScreen NOTIFY rendererAlwaysFullScreenChanged)
|
Q_PROPERTY(bool rendererAlwaysFullScreen MEMBER rendererAlwaysFullScreen NOTIFY rendererAlwaysFullScreenChanged)
|
||||||
Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged)
|
Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged)
|
||||||
Q_PROPERTY(QSize maximumResolution MEMBER maximumResolution NOTIFY maximumResolutionChanged)
|
Q_PROPERTY(QSize maximumResolution MEMBER maximumResolution NOTIFY maximumResolutionChanged)
|
||||||
Q_PROPERTY(bool supportsHdr MEMBER supportsHdr NOTIFY supportsHdrChanged)
|
Q_PROPERTY(bool supportsHdr MEMBER supportsHdr NOTIFY supportsHdrChanged)
|
||||||
|
|
||||||
Q_INVOKABLE void refreshDisplays();
|
// Either startAsyncLoad()+waitForAsyncLoad() or refreshDisplays() must be invoked first
|
||||||
Q_INVOKABLE QRect getNativeResolution(int displayIndex);
|
Q_INVOKABLE QRect getNativeResolution(int displayIndex);
|
||||||
Q_INVOKABLE QRect getSafeAreaResolution(int displayIndex);
|
Q_INVOKABLE QRect getSafeAreaResolution(int displayIndex);
|
||||||
Q_INVOKABLE int getRefreshRate(int displayIndex);
|
Q_INVOKABLE int getRefreshRate(int displayIndex);
|
||||||
|
|
||||||
|
Q_INVOKABLE void startAsyncLoad();
|
||||||
|
Q_INVOKABLE void waitForAsyncLoad();
|
||||||
|
Q_INVOKABLE void refreshDisplays();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void unmappedGamepadsChanged();
|
void unmappedGamepadsChanged();
|
||||||
void hasHardwareAccelerationChanged();
|
void hasHardwareAccelerationChanged();
|
||||||
@@ -49,8 +53,8 @@ private slots:
|
|||||||
void updateDecoderProperties(bool hasHardwareAcceleration, bool rendererAlwaysFullScreen, QSize maximumResolution, bool supportsHdr);
|
void updateDecoderProperties(bool hasHardwareAcceleration, bool rendererAlwaysFullScreen, QSize maximumResolution, bool supportsHdr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QThread* systemPropertyQueryThread;
|
QThread* systemPropertyQueryThread = nullptr;
|
||||||
SDL_Window* testWindow;
|
SDL_Window* testWindow = nullptr;
|
||||||
|
|
||||||
// Properties set by the constructor
|
// Properties set by the constructor
|
||||||
bool isRunningWayland;
|
bool isRunningWayland;
|
||||||
@@ -60,15 +64,15 @@ private:
|
|||||||
bool hasDesktopEnvironment;
|
bool hasDesktopEnvironment;
|
||||||
bool hasBrowser;
|
bool hasBrowser;
|
||||||
bool hasDiscordIntegration;
|
bool hasDiscordIntegration;
|
||||||
QString unmappedGamepads;
|
|
||||||
QString versionString;
|
QString versionString;
|
||||||
bool usesMaterial3Theme;
|
bool usesMaterial3Theme;
|
||||||
|
|
||||||
// Properties set by updateDecoderProperties()
|
// Properties only set if startAsyncLoad() is called
|
||||||
bool hasHardwareAcceleration;
|
bool hasHardwareAcceleration;
|
||||||
bool rendererAlwaysFullScreen;
|
bool rendererAlwaysFullScreen;
|
||||||
QSize maximumResolution;
|
QSize maximumResolution;
|
||||||
bool supportsHdr;
|
bool supportsHdr;
|
||||||
|
QString unmappedGamepads;
|
||||||
|
|
||||||
// Properties set by refreshDisplays()
|
// Properties set by refreshDisplays()
|
||||||
QList<QRect> monitorNativeResolutions;
|
QList<QRect> monitorNativeResolutions;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import QtQuick.Window 2.2
|
|||||||
|
|
||||||
import SdlGamepadKeyNavigation 1.0
|
import SdlGamepadKeyNavigation 1.0
|
||||||
import Session 1.0
|
import Session 1.0
|
||||||
|
import SystemProperties 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property Session session
|
property Session session
|
||||||
@@ -120,6 +121,10 @@ Item {
|
|||||||
session.sessionFinished.connect(sessionFinished)
|
session.sessionFinished.connect(sessionFinished)
|
||||||
session.readyForDeletion.connect(sessionReadyForDeletion)
|
session.readyForDeletion.connect(sessionReadyForDeletion)
|
||||||
|
|
||||||
|
// Ensure the SystemProperties async thread is finished,
|
||||||
|
// since it may currently be using the SDL video subsystem
|
||||||
|
SystemProperties.waitForAsyncLoad()
|
||||||
|
|
||||||
// Kick off the stream
|
// Kick off the stream
|
||||||
spinnerTimer.start()
|
spinnerTimer.start()
|
||||||
streamLoader.active = true
|
streamLoader.active = true
|
||||||
|
|||||||
+10
-6
@@ -56,13 +56,10 @@ ApplicationWindow {
|
|||||||
wow64Dialog.open()
|
wow64Dialog.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SystemProperties.unmappedGamepads) {
|
// Hardware acceleration and unmapped gamepads are checked asynchronously
|
||||||
unmappedGamepadDialog.unmappedGamepads = SystemProperties.unmappedGamepads
|
|
||||||
unmappedGamepadDialog.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hardware acceleration is checked asynchronously
|
|
||||||
SystemProperties.hasHardwareAccelerationChanged.connect(hasHardwareAccelerationChanged)
|
SystemProperties.hasHardwareAccelerationChanged.connect(hasHardwareAccelerationChanged)
|
||||||
|
SystemProperties.unmappedGamepadsChanged.connect(hasUnmappedGamepadsChanged)
|
||||||
|
SystemProperties.startAsyncLoad()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +74,13 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasUnmappedGamepadsChanged() {
|
||||||
|
if (SystemProperties.unmappedGamepads) {
|
||||||
|
unmappedGamepadDialog.unmappedGamepads = SystemProperties.unmappedGamepads
|
||||||
|
unmappedGamepadDialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// It would be better to use TextMetrics here, but it always lays out
|
// It would be better to use TextMetrics here, but it always lays out
|
||||||
// the text slightly more compactly than real Text does in ToolTip,
|
// the text slightly more compactly than real Text does in ToolTip,
|
||||||
// causing unexpected line breaks to be inserted
|
// causing unexpected line breaks to be inserted
|
||||||
|
|||||||
Reference in New Issue
Block a user