Increase Qt requirement to 5.12 and remove pre-5.12 workarounds

This commit is contained in:
Cameron Gutman
2025-10-11 11:03:33 -05:00
parent 4189903233
commit 2b3e0803de
7 changed files with 17 additions and 65 deletions
+2 -2
View File
@@ -54,7 +54,7 @@ Hosting for Moonlight's Debian and L4T package repositories is graciously provid
* [create-dmg](https://github.com/sindresorhus/create-dmg) (only if building DMGs for use on non-development Macs) * [create-dmg](https://github.com/sindresorhus/create-dmg) (only if building DMGs for use on non-development Macs)
### Linux/Unix Build Requirements ### Linux/Unix Build Requirements
* Qt 6 is recommended, but Qt 5.9 or later is also supported (replace `qmake6` with `qmake` when using Qt 5). * Qt 6 is recommended, but Qt 5.12 or later is also supported (replace `qmake6` with `qmake` when using Qt 5).
* GCC or Clang * GCC or Clang
* FFmpeg 4.0 or later * FFmpeg 4.0 or later
* Install the required packages: * Install the required packages:
@@ -75,7 +75,7 @@ Hosting for Moonlight's Debian and L4T package repositories is graciously provid
### Build Setup Steps ### Build Setup Steps
1. Install the latest Qt SDK (and optionally, the Qt Creator IDE) from https://www.qt.io/download 1. Install the latest Qt SDK (and optionally, the Qt Creator IDE) from https://www.qt.io/download
* You can install Qt via Homebrew on macOS, but you will need to use `brew install qt --with-debug` to be able to create debug builds of Moonlight. * You can install Qt via Homebrew on macOS, but you will need to use `brew install qt --with-debug` to be able to create debug builds of Moonlight.
* You may also use your Linux distro's package manager for the Qt SDK as long as the packages are Qt 5.9 or later. * You may also use your Linux distro's package manager for the Qt SDK as long as the packages are Qt 5.12 or later.
* This step is not required for building on Steam Link, because the Steam Link SDK includes Qt 5.14. * This step is not required for building on Steam Link, because the Steam Link SDK includes Qt 5.14.
2. Run `git submodule update --init --recursive` from within `moonlight-qt/` 2. Run `git submodule update --init --recursive` from within `moonlight-qt/`
3. Open the project in Qt Creator or build from qmake on the command line. 3. Open the project in Qt Creator or build from qmake on the command line.
+2 -8
View File
@@ -9,8 +9,7 @@
#include <QThread> #include <QThread>
#include <QThreadPool> #include <QThreadPool>
#include <QCoreApplication> #include <QCoreApplication>
#include <QRandomGenerator>
#include <random>
#define SER_HOSTS "hosts" #define SER_HOSTS "hosts"
#define SER_HOSTS_BACKUP "hostsbackup" #define SER_HOSTS_BACKUP "hostsbackup"
@@ -966,14 +965,9 @@ void ComputerManager::addNewHost(NvAddress address, bool mdns, NvAddress mdnsIpv
QThreadPool::globalInstance()->start(addTask); QThreadPool::globalInstance()->start(addTask);
} }
// TODO: Use QRandomGenerator when we drop Qt 5.9 support
QString ComputerManager::generatePinString() QString ComputerManager::generatePinString()
{ {
std::uniform_int_distribution<int> dist(0, 9999); return QString::asprintf("%04u", QRandomGenerator::system()->bounded(10000));
std::random_device rd;
std::mt19937 engine(rd());
return QString::asprintf("%04u", dist(engine));
} }
#include "computermanager.moc" #include "computermanager.moc"
+4 -8
View File
@@ -38,7 +38,7 @@ CenteredGridView {
activated = true activated = true
// Highlight the first item if a gamepad is connected // Highlight the first item if a gamepad is connected
if (currentIndex == -1 && SdlGamepadKeyNavigation.getConnectedGamepads() > 0) { if (currentIndex === -1 && SdlGamepadKeyNavigation.getConnectedGamepads() > 0) {
currentIndex = 0 currentIndex = 0
} }
@@ -94,9 +94,9 @@ CenteredGridView {
// the image size checks if this is not an app collector game. We know the officially // the image size checks if this is not an app collector game. We know the officially
// supported games all have box art, so this check is not required. // supported games all have box art, so this check is not required.
if (!model.isAppCollectorGame && if (!model.isAppCollectorGame &&
((sourceSize.width == 130 && sourceSize.height == 180) || // GFE 2.0 placeholder image ((sourceSize.width === 130 && sourceSize.height === 180) || // GFE 2.0 placeholder image
(sourceSize.width == 628 && sourceSize.height == 888) || // GFE 3.0 placeholder image (sourceSize.width === 628 && sourceSize.height === 888) || // GFE 3.0 placeholder image
(sourceSize.width == 200 && sourceSize.height == 266))) // Our no_app_image.png (sourceSize.width === 200 && sourceSize.height === 266))) // Our no_app_image.png
{ {
isPlaceholder = true isPlaceholder = true
} }
@@ -299,18 +299,15 @@ CenteredGridView {
sourceComponent: NavigableMenu { sourceComponent: NavigableMenu {
id: appContextMenu id: appContextMenu
NavigableMenuItem { NavigableMenuItem {
parentMenu: appContextMenu
text: model.running ? qsTr("Resume Game") : qsTr("Launch Game") text: model.running ? qsTr("Resume Game") : qsTr("Launch Game")
onTriggered: launchOrResumeSelectedApp(true) onTriggered: launchOrResumeSelectedApp(true)
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: appContextMenu
text: qsTr("Quit Game") text: qsTr("Quit Game")
onTriggered: doQuitGame() onTriggered: doQuitGame()
visible: model.running visible: model.running
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: appContextMenu
checkable: true checkable: true
checked: model.directLaunch checked: model.directLaunch
text: qsTr("Direct Launch") text: qsTr("Direct Launch")
@@ -323,7 +320,6 @@ CenteredGridView {
ToolTip.visible: hovered ToolTip.visible: hovered
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: appContextMenu
checkable: true checkable: true
checked: model.hidden checked: model.hidden
text: qsTr("Hide Game") text: qsTr("Hide Game")
-18
View File
@@ -2,10 +2,6 @@ import QtQuick 2.9
import QtQuick.Controls 2.2 import QtQuick.Controls 2.2
GridView { GridView {
// Detect Qt 5.11 or earlier using presence of synchronousDrag.
// Prior to 5.12, the leftMargin and rightMargin values did not work.
property bool hasBrokenMargins: this.synchronousDrag === undefined
property int minMargin: 10 property int minMargin: 10
property real availableWidth: (parent.width - 2 * minMargin) property real availableWidth: (parent.width - 2 * minMargin)
property int itemsPerRow: availableWidth / cellWidth property int itemsPerRow: availableWidth / cellWidth
@@ -15,11 +11,6 @@ GridView {
function updateMargins() { function updateMargins() {
leftMargin = horizontalMargin leftMargin = horizontalMargin
rightMargin = horizontalMargin rightMargin = horizontalMargin
if (hasBrokenMargins) {
anchors.leftMargin = leftMargin
anchors.rightMargin = rightMargin
}
} }
onHorizontalMarginChanged: { onHorizontalMarginChanged: {
@@ -27,15 +18,6 @@ GridView {
} }
Component.onCompleted: { Component.onCompleted: {
if (hasBrokenMargins) {
// This will cause an anchor conflict with the parent StackView
// which breaks animation, but otherwise the grid will not be
// centered in the window.
anchors.fill = parent
anchors.topMargin = topMargin
anchors.bottomMargin = bottomMargin
}
updateMargins() updateMargins()
} }
+2 -6
View File
@@ -2,10 +2,6 @@ import QtQuick 2.0
import QtQuick.Controls 2.2 import QtQuick.Controls 2.2
MenuItem { MenuItem {
// Qt 5.10 has a menu property, but we need to support 5.9
// so we must make our own.
property Menu parentMenu
// Ensure focus can't be given to an invisible item // Ensure focus can't be given to an invisible item
enabled: visible enabled: visible
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
@@ -15,7 +11,7 @@ MenuItem {
// We must close the context menu first or // We must close the context menu first or
// it can steal focus from any dialogs that // it can steal focus from any dialogs that
// onTriggered may spawn. // onTriggered may spawn.
parentMenu.close() menu.close()
} }
Keys.onReturnPressed: { Keys.onReturnPressed: {
@@ -27,6 +23,6 @@ MenuItem {
} }
Keys.onEscapePressed: { Keys.onEscapePressed: {
parentMenu.close() menu.close()
} }
} }
+1 -7
View File
@@ -35,7 +35,7 @@ CenteredGridView {
ComputerManager.computerAddCompleted.connect(addComplete) ComputerManager.computerAddCompleted.connect(addComplete)
// Highlight the first item if a gamepad is connected // Highlight the first item if a gamepad is connected
if (currentIndex == -1 && SdlGamepadKeyNavigation.getConnectedGamepads() > 0) { if (currentIndex === -1 && SdlGamepadKeyNavigation.getConnectedGamepads() > 0) {
currentIndex = 0 currentIndex = 0
} }
} }
@@ -169,7 +169,6 @@ CenteredGridView {
enabled: false enabled: false
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("View All Apps") text: qsTr("View All Apps")
onTriggered: { onTriggered: {
var component = Qt.createComponent("AppView.qml") var component = Qt.createComponent("AppView.qml")
@@ -179,13 +178,11 @@ CenteredGridView {
visible: model.online && model.paired visible: model.online && model.paired
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Wake PC") text: qsTr("Wake PC")
onTriggered: computerModel.wakeComputer(index) onTriggered: computerModel.wakeComputer(index)
visible: !model.online && model.wakeable visible: !model.online && model.wakeable
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Test Network") text: qsTr("Test Network")
onTriggered: { onTriggered: {
computerModel.testConnectionForComputer(index) computerModel.testConnectionForComputer(index)
@@ -194,7 +191,6 @@ CenteredGridView {
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Rename PC") text: qsTr("Rename PC")
onTriggered: { onTriggered: {
renamePcDialog.pcIndex = index renamePcDialog.pcIndex = index
@@ -203,7 +199,6 @@ CenteredGridView {
} }
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Delete PC") text: qsTr("Delete PC")
onTriggered: { onTriggered: {
deletePcDialog.pcIndex = index deletePcDialog.pcIndex = index
@@ -212,7 +207,6 @@ CenteredGridView {
} }
} }
NavigableMenuItem { NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("View Details") text: qsTr("View Details")
onTriggered: { onTriggered: {
showPcDetailsDialog.pcDetails = model.details showPcDetailsDialog.pcDetails = model.details
+6 -16
View File
@@ -205,20 +205,10 @@ ApplicationWindow {
SdlGamepadKeyNavigation.notifyWindowFocus(visible && active) SdlGamepadKeyNavigation.notifyWindowFocus(visible && active)
} }
// Workaround for lack of instanceof in Qt 5.9.
//
// Based on https://stackoverflow.com/questions/13923794/how-to-do-a-is-a-typeof-or-instanceof-in-qml
function qmltypeof(obj, className) { // QtObject, string -> bool
// className plus "(" is the class instance without modification
// className plus "_QML" is the class instance with user-defined properties
var str = obj.toString();
return str.startsWith(className + "(") || str.startsWith(className + "_QML");
}
function navigateTo(url, objectType) function navigateTo(url, objectType)
{ {
var existingItem = stackView.find(function(item, index) { var existingItem = stackView.find(function(item, index) {
return qmltypeof(item, objectType) return item instanceof objectType
}) })
if (existingItem !== null) { if (existingItem !== null) {
@@ -285,7 +275,7 @@ ApplicationWindow {
Label { Label {
id: versionLabel id: versionLabel
visible: qmltypeof(stackView.currentItem, "SettingsView") visible: stackView.currentItem instanceof SettingsView
text: qsTr("Version %1").arg(SystemProperties.versionString) text: qsTr("Version %1").arg(SystemProperties.versionString)
font.pointSize: 12 font.pointSize: 12
horizontalAlignment: Qt.AlignRight horizontalAlignment: Qt.AlignRight
@@ -295,7 +285,7 @@ ApplicationWindow {
NavigableToolButton { NavigableToolButton {
id: discordButton id: discordButton
visible: SystemProperties.hasBrowser && visible: SystemProperties.hasBrowser &&
qmltypeof(stackView.currentItem, "SettingsView") stackView.currentItem instanceof SettingsView
iconSource: "qrc:/res/discord.svg" iconSource: "qrc:/res/discord.svg"
@@ -314,7 +304,7 @@ ApplicationWindow {
NavigableToolButton { NavigableToolButton {
id: addPcButton id: addPcButton
visible: qmltypeof(stackView.currentItem, "PcView") visible: stackView.currentItem instanceof PcView
iconSource: "qrc:/res/ic_add_to_queue_white_48px.svg" iconSource: "qrc:/res/ic_add_to_queue_white_48px.svg"
@@ -412,7 +402,7 @@ ApplicationWindow {
iconSource: "qrc:/res/ic_videogame_asset_white_48px.svg" iconSource: "qrc:/res/ic_videogame_asset_white_48px.svg"
onClicked: navigateTo("qrc:/gui/GamepadMapper.qml", "GamepadMapper") onClicked: navigateTo("qrc:/gui/GamepadMapper.qml", GamepadMapper)
Keys.onDownPressed: { Keys.onDownPressed: {
stackView.currentItem.forceActiveFocus(Qt.TabFocus) stackView.currentItem.forceActiveFocus(Qt.TabFocus)
@@ -424,7 +414,7 @@ ApplicationWindow {
iconSource: "qrc:/res/settings.svg" iconSource: "qrc:/res/settings.svg"
onClicked: navigateTo("qrc:/gui/SettingsView.qml", "SettingsView") onClicked: navigateTo("qrc:/gui/SettingsView.qml", SettingsView)
Keys.onDownPressed: { Keys.onDownPressed: {
stackView.currentItem.forceActiveFocus(Qt.TabFocus) stackView.currentItem.forceActiveFocus(Qt.TabFocus)