moonlight-qt/app/gui/StreamSegue.qml
Cameron Gutman 37d92dee16 Revert "Fix hiding the main UI window while streaming on Qt 6.7"
The original issue on Qt 6.7 was caused by conflicts with the window state set in main.qml
which was addressed by afbc49e39a.

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 ebe270bec5.
2024-04-14 14:08:53 -05:00

215 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
}
}