mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-01 23:35:55 +00:00
The original issue on Qt 6.7 was caused by conflicts with the window state set in main.qml which was addressed by afbc49e39aeae9fb1cb3dd2362d2dc04e76941ce. The remaining issue with Qt 6.7 clobbering window state and position when hiding a window looks like a legitimate Qt bug. This reverts commit ebe270bec5820b956f4c511fd31097a0c1d1a7c3.
216 lines
6.8 KiB
QML
216 lines
6.8 KiB
QML
import QtQuick 2.0
|
|
import QtQuick.Controls 2.2
|
|
import QtQuick.Window 2.2
|
|
|
|
import SdlGamepadKeyNavigation 1.0
|
|
import Session 1.0
|
|
|
|
Item {
|
|
property Session session
|
|
property string appName
|
|
property string stageText : isResume ? qsTr("Resuming %1...").arg(appName) :
|
|
qsTr("Starting %1...").arg(appName)
|
|
property bool isResume : false
|
|
property bool quitAfter : false
|
|
|
|
function stageStarting(stage)
|
|
{
|
|
// Update the spinner text
|
|
stageText = qsTr("Starting %1...").arg(stage)
|
|
}
|
|
|
|
function stageFailed(stage, errorCode, failingPorts)
|
|
{
|
|
// Display the error dialog after Session::exec() returns
|
|
streamSegueErrorDialog.text = qsTr("Starting %1 failed: Error %2").arg(stage).arg(errorCode)
|
|
|
|
if (failingPorts) {
|
|
streamSegueErrorDialog.text += "\n\n" + qsTr("Check your firewall and port forwarding rules for port(s): %1").arg(failingPorts)
|
|
}
|
|
}
|
|
|
|
function connectionStarted()
|
|
{
|
|
// Hide the UI contents so the user doesn't
|
|
// see them briefly when we pop off the StackView
|
|
stageSpinner.visible = false
|
|
stageLabel.visible = false
|
|
hintText.visible = false
|
|
|
|
// Hide the window now that streaming has begun
|
|
window.visible = false
|
|
}
|
|
|
|
function displayLaunchError(text)
|
|
{
|
|
// Display the error dialog after Session::exec() returns
|
|
streamSegueErrorDialog.text = text
|
|
console.error(text)
|
|
}
|
|
|
|
function displayLaunchWarning(text)
|
|
{
|
|
// This toast appears for 3 seconds, just shorter than how long
|
|
// Session will wait for it to be displayed. This gives it time
|
|
// to transition to invisible before continuing.
|
|
var toast = Qt.createQmlObject('import QtQuick.Controls 2.2; ToolTip {}', parent, '')
|
|
toast.text = text
|
|
toast.timeout = 3000
|
|
toast.visible = true
|
|
console.warn(text)
|
|
}
|
|
|
|
function quitStarting()
|
|
{
|
|
// Avoid the push transition animation
|
|
var component = Qt.createComponent("QuitSegue.qml")
|
|
stackView.replace(stackView.currentItem, component.createObject(stackView, {"appName": appName}), StackView.Immediate)
|
|
|
|
// Show the Qt window again to show quit segue
|
|
window.visible = true
|
|
}
|
|
|
|
function sessionFinished(portTestResult)
|
|
{
|
|
if (portTestResult !== 0 && portTestResult !== -1 && streamSegueErrorDialog.text) {
|
|
streamSegueErrorDialog.text += "\n\n" + qsTr("This PC's Internet connection is blocking Moonlight. Streaming over the Internet may not work while connected to this network.")
|
|
}
|
|
|
|
// Enable GUI gamepad usage now
|
|
SdlGamepadKeyNavigation.enable()
|
|
|
|
if (quitAfter) {
|
|
if (streamSegueErrorDialog.text) {
|
|
// Quit when the error dialog is acknowledged
|
|
streamSegueErrorDialog.quitAfter = quitAfter
|
|
streamSegueErrorDialog.open()
|
|
}
|
|
else {
|
|
// Quit immediately
|
|
Qt.quit()
|
|
}
|
|
} else {
|
|
// Exit this view
|
|
stackView.pop()
|
|
|
|
// Show the Qt window again after streaming
|
|
window.visible = true
|
|
|
|
// Display any launch errors. We do this after
|
|
// the Qt UI is visible again to prevent losing
|
|
// focus on the dialog which would impact gamepad
|
|
// users.
|
|
if (streamSegueErrorDialog.text) {
|
|
streamSegueErrorDialog.quitAfter = quitAfter
|
|
streamSegueErrorDialog.open()
|
|
}
|
|
}
|
|
}
|
|
|
|
function sessionReadyForDeletion()
|
|
{
|
|
// Garbage collect the Session object since it's pretty heavyweight
|
|
// and keeps other libraries (like SDL_TTF) around until it is deleted.
|
|
session = null
|
|
gc()
|
|
}
|
|
|
|
StackView.onDeactivating: {
|
|
// Show the toolbar again when popped off the stack
|
|
toolBar.visible = true
|
|
|
|
// Enable GUI gamepad usage now
|
|
SdlGamepadKeyNavigation.enable()
|
|
}
|
|
|
|
StackView.onActivated: {
|
|
// Hide the toolbar before we start loading
|
|
toolBar.visible = false
|
|
|
|
// Hook up our signals
|
|
session.stageStarting.connect(stageStarting)
|
|
session.stageFailed.connect(stageFailed)
|
|
session.connectionStarted.connect(connectionStarted)
|
|
session.displayLaunchError.connect(displayLaunchError)
|
|
session.displayLaunchWarning.connect(displayLaunchWarning)
|
|
session.quitStarting.connect(quitStarting)
|
|
session.sessionFinished.connect(sessionFinished)
|
|
session.readyForDeletion.connect(sessionReadyForDeletion)
|
|
|
|
// Kick off the stream
|
|
spinnerTimer.start()
|
|
streamLoader.active = true
|
|
}
|
|
|
|
Timer {
|
|
id: spinnerTimer
|
|
|
|
// Display the spinner appearance a bit to allow us to reach
|
|
// the code in Session.exec() that pumps the event loop.
|
|
// If we display it immediately, it will briefly hang in the
|
|
// middle of the animation on Windows, which looks very
|
|
// obviously broken.
|
|
interval: 100
|
|
onTriggered: stageSpinner.running = true
|
|
}
|
|
|
|
Loader {
|
|
id: streamLoader
|
|
active: false
|
|
asynchronous: true
|
|
|
|
onLoaded: {
|
|
// Set the hint text. We do this here rather than
|
|
// in the hintText control itself to synchronize
|
|
// with Session.exec() which requires no concurrent
|
|
// gamepad usage.
|
|
hintText.text = qsTr("Tip:") + " " + qsTr("Press %1 to disconnect your session").arg(SdlGamepadKeyNavigation.getConnectedGamepads() > 0 ?
|
|
qsTr("Start+Select+L1+R1") : qsTr("Ctrl+Alt+Shift+Q"))
|
|
|
|
// Stop GUI gamepad usage now
|
|
SdlGamepadKeyNavigation.disable()
|
|
|
|
// Garbage collect QML stuff before we start streaming,
|
|
// since we'll probably be streaming for a while and we
|
|
// won't be able to GC during the stream.
|
|
gc()
|
|
|
|
// Run the streaming session to completion
|
|
session.exec(Window.window)
|
|
}
|
|
|
|
sourceComponent: Item {}
|
|
}
|
|
|
|
Row {
|
|
anchors.centerIn: parent
|
|
spacing: 5
|
|
|
|
BusyIndicator {
|
|
id: stageSpinner
|
|
running: false
|
|
}
|
|
|
|
Label {
|
|
id: stageLabel
|
|
height: stageSpinner.height
|
|
text: stageText
|
|
font.pointSize: 20
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
wrapMode: Text.Wrap
|
|
}
|
|
}
|
|
|
|
Label {
|
|
id: hintText
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: 50
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
font.pointSize: 18
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
wrapMode: Text.Wrap
|
|
}
|
|
}
|