Qt: Refactor and remove multiple sources of truth for render-to-main

This commit is contained in:
Stenzek 2025-07-18 16:14:29 +10:00
parent 0f2ef98747
commit 6b969a0b94
No known key found for this signature in database
5 changed files with 105 additions and 90 deletions

View File

@ -25,6 +25,9 @@ public:
explicit DisplayWidget(QWidget* parent); explicit DisplayWidget(QWidget* parent);
~DisplayWidget(); ~DisplayWidget();
ALWAYS_INLINE const char* windowPositionKey() const { return m_window_position_key; }
ALWAYS_INLINE void setWindowPositionKey(const char* key) { m_window_position_key = key; }
QPaintEngine* paintEngine() const override; QPaintEngine* paintEngine() const override;
int scaledWindowWidth() const; int scaledWindowWidth() const;
@ -67,6 +70,8 @@ private:
u32 m_last_window_width = 0; u32 m_last_window_width = 0;
u32 m_last_window_height = 0; u32 m_last_window_height = 0;
float m_last_window_scale = 1.0f; float m_last_window_scale = 1.0f;
const char* m_window_position_key = nullptr;
}; };
class DisplayContainer final : public QStackedWidget class DisplayContainer final : public QStackedWidget

View File

@ -251,13 +251,13 @@ bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr
#endif #endif
std::optional<WindowInfo> MainWindow::acquireRenderWindow(RenderAPI render_api, bool fullscreen, std::optional<WindowInfo> MainWindow::acquireRenderWindow(RenderAPI render_api, bool fullscreen,
bool exclusive_fullscreen, bool render_to_main, bool exclusive_fullscreen, bool surfaceless, Error* error)
bool surfaceless, bool use_main_window_pos, Error* error)
{ {
DEV_LOG("acquireRenderWindow() fullscreen={} exclusive_fullscreen={}, render_to_main={} surfaceless={} " const bool render_to_main =
"use_main_window_pos={}", QtHost::CanRenderToMainWindow() && !fullscreen && (s_system_locked.load(std::memory_order_relaxed) == 0);
fullscreen ? "true" : "false", exclusive_fullscreen ? "true" : "false", render_to_main ? "true" : "false",
surfaceless ? "true" : "false", use_main_window_pos ? "true" : "false"); DEV_LOG("acquireRenderWindow() fullscreen={} exclusive_fullscreen={}, render_to_main={}, surfaceless={} ", fullscreen,
exclusive_fullscreen, render_to_main, surfaceless);
QWidget* container = QWidget* container =
m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget); m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget);
@ -279,6 +279,9 @@ std::optional<WindowInfo> MainWindow::acquireRenderWindow(RenderAPI render_api,
DEV_LOG("Toggling to {} without recreating surface", (fullscreen ? "fullscreen" : "windowed")); DEV_LOG("Toggling to {} without recreating surface", (fullscreen ? "fullscreen" : "windowed"));
m_exclusive_fullscreen_requested = exclusive_fullscreen; m_exclusive_fullscreen_requested = exclusive_fullscreen;
// ensure it's resizable when changing size, we'll fix it up later in updateWindowState()
QtUtils::SetWindowResizeable(container, true);
// since we don't destroy the display widget, we need to save it here // since we don't destroy the display widget, we need to save it here
if (!is_fullscreen && !is_rendering_to_main) if (!is_fullscreen && !is_rendering_to_main)
saveDisplayWindowGeometryToConfig(); saveDisplayWindowGeometryToConfig();
@ -290,10 +293,7 @@ std::optional<WindowInfo> MainWindow::acquireRenderWindow(RenderAPI render_api,
else else
{ {
container->showNormal(); container->showNormal();
if (use_main_window_pos) restoreDisplayWindowGeometryFromConfig();
container->setGeometry(geometry());
else
restoreDisplayWindowGeometryFromConfig();
} }
updateDisplayWidgetCursor(); updateDisplayWidgetCursor();
@ -309,7 +309,7 @@ std::optional<WindowInfo> MainWindow::acquireRenderWindow(RenderAPI render_api,
std::optional<WindowInfo> wi; std::optional<WindowInfo> wi;
if (!surfaceless) if (!surfaceless)
{ {
createDisplayWidget(fullscreen, render_to_main, use_main_window_pos); createDisplayWidget(fullscreen, render_to_main);
wi = m_display_widget->getWindowInfo(render_api, error); wi = m_display_widget->getWindowInfo(render_api, error);
if (!wi.has_value()) if (!wi.has_value())
@ -343,7 +343,7 @@ bool MainWindow::hasDisplayWidget() const
return m_display_widget != nullptr; return m_display_widget != nullptr;
} }
void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool use_main_window_pos) void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main)
{ {
// If we're rendering to main and were hidden (e.g. coming back from fullscreen), // If we're rendering to main and were hidden (e.g. coming back from fullscreen),
// make sure we're visible before trying to add ourselves. Otherwise Wayland breaks. // make sure we're visible before trying to add ourselves. Otherwise Wayland breaks.
@ -384,10 +384,7 @@ void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool
} }
else if (!render_to_main) else if (!render_to_main)
{ {
if (use_main_window_pos) restoreDisplayWindowGeometryFromConfig();
container->setGeometry(geometry());
else
restoreDisplayWindowGeometryFromConfig();
container->showNormal(); container->showNormal();
if (s_disable_window_rounded_corners) if (s_disable_window_rounded_corners)
@ -441,7 +438,7 @@ void MainWindow::releaseRenderWindow()
// Now we can safely destroy the display window. // Now we can safely destroy the display window.
destroyDisplayWidget(true); destroyDisplayWidget(true);
updateWindowTitle(); updateWindowTitle();
updateWindowState(false); updateWindowState();
} }
void MainWindow::destroyDisplayWidget(bool show_game_list) void MainWindow::destroyDisplayWidget(bool show_game_list)
@ -809,7 +806,7 @@ void MainWindow::recreate()
{ {
g_emu_thread->setSurfaceless(false); g_emu_thread->setSurfaceless(false);
if (was_fullscreen) if (was_fullscreen)
g_emu_thread->setFullscreen(true, true); g_emu_thread->setFullscreen(true);
g_main_window->updateEmulationActions(false, s_system_valid, s_achievements_hardcore_mode); g_main_window->updateEmulationActions(false, s_system_valid, s_achievements_hardcore_mode);
g_main_window->onFullscreenUIStartedOrStopped(s_fullscreen_ui_started); g_main_window->onFullscreenUIStartedOrStopped(s_fullscreen_ui_started);
} }
@ -2035,22 +2032,20 @@ void MainWindow::updateWindowTitle()
g_log_window->updateWindowTitle(); g_log_window->updateWindowTitle();
} }
void MainWindow::updateWindowState(bool force_visible) void MainWindow::updateWindowState()
{ {
// Skip all of this when we're closing, since we don't want to make ourselves visible and cancel it. // Skip all of this when we're closing, since we don't want to make ourselves visible and cancel it.
if (m_is_closing) if (m_is_closing)
return; return;
const bool hide_window = shouldHideMainWindow(); const bool visible = !shouldHideMainWindow();
const bool disable_resize = (Host::GetBoolSettingValue("Main", "DisableWindowResize", false) && wantsDisplayWidget()); const bool resizeable = (!Host::GetBoolSettingValue("Main", "DisableWindowResize", false) || !wantsDisplayWidget() ||
isRenderingFullscreen());
// Need to test both valid and display widget because of startup (vm invalid while window is created).
const bool visible = force_visible || !hide_window;
if (isVisible() != visible) if (isVisible() != visible)
setVisible(visible); setVisible(visible);
// No point changing realizability if we're not visible. // No point changing realizability if we're not visible.
const bool resizeable = force_visible || !disable_resize;
if (visible) if (visible)
QtUtils::SetWindowResizeable(this, resizeable); QtUtils::SetWindowResizeable(this, resizeable);
@ -2108,12 +2103,12 @@ bool MainWindow::shouldHideMouseCursor() const
bool MainWindow::shouldHideMainWindow() const bool MainWindow::shouldHideMainWindow() const
{ {
// CanRenderToMain check is for temporary unfullscreens. // CanRenderToMain check is for temporary unfullscreens.
return !isRenderingToMain() && wantsDisplayWidget() && return (!isRenderingToMain() && wantsDisplayWidget() &&
((Host::GetBoolSettingValue("Main", "RenderToSeparateWindow", false) && ((Host::GetBoolSettingValue("Main", "RenderToSeparateWindow", false) &&
Host::GetBoolSettingValue("Main", "HideMainWindowWhenRunning", false)) || Host::GetBoolSettingValue("Main", "HideMainWindowWhenRunning", false)) ||
(QtHost::CanRenderToMainWindow() && (QtHost::CanRenderToMainWindow() &&
(isRenderingFullscreen() || s_system_locked.load(std::memory_order_relaxed))) || (isRenderingFullscreen() || s_system_locked.load(std::memory_order_relaxed))))) ||
QtHost::InNoGUIMode()); QtHost::InNoGUIMode();
} }
void MainWindow::switchToGameListView() void MainWindow::switchToGameListView()
@ -2434,7 +2429,7 @@ void MainWindow::saveStateToConfig()
if (!isVisible() || ((windowState() & Qt::WindowFullScreen) != Qt::WindowNoState)) if (!isVisible() || ((windowState() & Qt::WindowFullScreen) != Qt::WindowNoState))
return; return;
bool changed = QtUtils::SaveWindowGeometry("MainWindow", this, false); bool changed = false;
const QByteArray state(saveState()); const QByteArray state(saveState());
const QByteArray state_b64(state.toBase64()); const QByteArray state_b64(state.toBase64());
@ -2445,14 +2440,14 @@ void MainWindow::saveStateToConfig()
changed = true; changed = true;
} }
changed |= QtUtils::SaveWindowGeometry("MainWindow", this, false);
if (changed) if (changed)
Host::CommitBaseSettingChanges(); Host::CommitBaseSettingChanges();
} }
void MainWindow::restoreStateFromConfig() void MainWindow::restoreStateFromConfig()
{ {
QtUtils::RestoreWindowGeometry("MainWindow", this);
{ {
const std::string state_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowState"); const std::string state_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowState");
const QByteArray state = QByteArray::fromBase64(QByteArray::fromStdString(state_b64)); const QByteArray state = QByteArray::fromBase64(QByteArray::fromStdString(state_b64));
@ -2473,6 +2468,8 @@ void MainWindow::restoreStateFromConfig()
m_ui.actionViewStatusBar->setChecked(!m_ui.statusBar->isHidden()); m_ui.actionViewStatusBar->setChecked(!m_ui.statusBar->isHidden());
} }
} }
QtUtils::RestoreWindowGeometry("MainWindow", this);
} }
void MainWindow::saveDisplayWindowGeometryToConfig() void MainWindow::saveDisplayWindowGeometryToConfig()
@ -2484,13 +2481,29 @@ void MainWindow::saveDisplayWindowGeometryToConfig()
return; return;
} }
QtUtils::SaveWindowGeometry("DisplayWindow", container); const char* key = m_display_widget->windowPositionKey();
if (key)
QtUtils::SaveWindowGeometry(key, container);
} }
void MainWindow::restoreDisplayWindowGeometryFromConfig() void MainWindow::restoreDisplayWindowGeometryFromConfig()
{ {
QWidget* const container = getDisplayContainer(); QWidget* const container = getDisplayContainer();
if (!QtUtils::RestoreWindowGeometry("DisplayWindow", container)) DebugAssert(m_display_widget);
// just sync it with the main window if we're not using nogui modem, config will be stale
if (QtHost::CanRenderToMainWindow())
{
container->setGeometry(geometry());
return;
}
// we don't want the temporary windowed window to be positioned on a different monitor, so use the main window
// coordinates... unless you're on wayland, too fucking bad, broken by design.
const bool use_main_window_pos = QtHost::UseMainWindowGeometryForDisplayWindow();
m_display_widget->setWindowPositionKey(use_main_window_pos ? "MainWindow" : "DisplayWindow");
if (!QtUtils::RestoreWindowGeometry(m_display_widget->windowPositionKey(), container))
{ {
// default size // default size
container->resize(640, 480); container->resize(640, 480);
@ -2641,7 +2654,7 @@ void MainWindow::changeEvent(QEvent* event)
static_cast<QWindowStateChangeEvent*>(event)->oldState() & Qt::WindowMinimized) static_cast<QWindowStateChangeEvent*>(event)->oldState() & Qt::WindowMinimized)
{ {
// TODO: This should check the render-to-main option. // TODO: This should check the render-to-main option.
if (m_display_widget) if (isRenderingToMain())
g_emu_thread->redrawDisplayWindow(); g_emu_thread->redrawDisplayWindow();
} }
@ -2785,6 +2798,10 @@ bool MainWindow::requestShutdown(bool allow_confirm, bool allow_save_to_state, b
lock.cancelResume(); lock.cancelResume();
} }
// If we're running in batch mode, don't show the main window after shutting down.
if (QtHost::InBatchMode())
m_is_closing = true;
// Now we can actually shut down the VM. // Now we can actually shut down the VM.
g_emu_thread->shutdownSystem(save_state, check_memcard_busy); g_emu_thread->shutdownSystem(save_state, check_memcard_busy);
return true; return true;
@ -2824,6 +2841,13 @@ void MainWindow::checkForSettingChanges()
} }
} }
// don't change state if temporary unfullscreened
if (m_display_widget && !QtHost::IsSystemLocked() && !isRenderingFullscreen())
{
if (QtHost::CanRenderToMainWindow() != isRenderingToMain())
g_emu_thread->updateDisplayWindow();
}
LogWindow::updateSettings(); LogWindow::updateSettings();
updateWindowState(); updateWindowState();
} }
@ -2986,7 +3010,7 @@ void MainWindow::onToolsCoverDownloaderTriggered()
// This can be invoked via big picture, so exit fullscreen. // This can be invoked via big picture, so exit fullscreen.
if (isRenderingFullscreen()) if (isRenderingFullscreen())
{ {
g_emu_thread->setFullscreen(false, true); g_emu_thread->setFullscreen(false);
// wait for the fullscreen request to actually go through, otherwise the downloader appears behind the main window. // wait for the fullscreen request to actually go through, otherwise the downloader appears behind the main window.
QtUtils::ProcessEventsWithSleep(QEventLoop::ExcludeUserInputEvents, [this]() { return isRenderingFullscreen(); }); QtUtils::ProcessEventsWithSleep(QEventLoop::ExcludeUserInputEvents, [this]() { return isRenderingFullscreen(); });
@ -3181,14 +3205,10 @@ MainWindow::SystemLock MainWindow::pauseAndLockSystem()
// However, we do not want to switch back to render-to-main, the window might have generated this event. // However, we do not want to switch back to render-to-main, the window might have generated this event.
if (was_fullscreen) if (was_fullscreen)
{ {
g_emu_thread->setFullscreen(false, false); g_emu_thread->setFullscreen(false);
// Container could change... thanks Wayland. // Container could change... thanks Wayland.
QtUtils::ProcessEventsWithSleep(QEventLoop::ExcludeUserInputEvents, [this]() { QtUtils::ProcessEventsWithSleep(QEventLoop::ExcludeUserInputEvents, [this]() { return isRenderingFullscreen(); });
QWidget* container;
return (s_system_valid &&
(g_emu_thread->isFullscreen() || !(container = getDisplayContainer()) || container->isFullScreen()));
});
} }
if (!was_paused) if (!was_paused)
@ -3228,7 +3248,7 @@ MainWindow::SystemLock::~SystemLock()
DebugAssert(s_system_locked.load(std::memory_order_relaxed) > 0); DebugAssert(s_system_locked.load(std::memory_order_relaxed) > 0);
s_system_locked.fetch_sub(1, std::memory_order_release); s_system_locked.fetch_sub(1, std::memory_order_release);
if (m_was_fullscreen) if (m_was_fullscreen)
g_emu_thread->setFullscreen(true, true); g_emu_thread->setFullscreen(true);
if (!m_was_paused) if (!m_was_paused)
g_emu_thread->setSystemPaused(false); g_emu_thread->setSystemPaused(false);
} }

View File

@ -138,8 +138,7 @@ private Q_SLOTS:
void onStatusMessage(const QString& message); void onStatusMessage(const QString& message);
std::optional<WindowInfo> acquireRenderWindow(RenderAPI render_api, bool fullscreen, bool exclusive_fullscreen, std::optional<WindowInfo> acquireRenderWindow(RenderAPI render_api, bool fullscreen, bool exclusive_fullscreen,
bool render_to_main, bool surfaceless, bool use_main_window_pos, bool surfaceless, Error* error);
Error* error);
void displayResizeRequested(qint32 width, qint32 height); void displayResizeRequested(qint32 width, qint32 height);
void releaseRenderWindow(); void releaseRenderWindow();
void focusDisplayWidget(); void focusDisplayWidget();
@ -250,7 +249,7 @@ private:
void updateShortcutActions(bool starting); void updateShortcutActions(bool starting);
void updateStatusBarWidgetVisibility(); void updateStatusBarWidgetVisibility();
void updateWindowTitle(); void updateWindowTitle();
void updateWindowState(bool force_visible = false); void updateWindowState();
void setProgressBar(int current, int total); void setProgressBar(int current, int total);
void clearProgressBar(); void clearProgressBar();
@ -269,7 +268,7 @@ private:
void saveDisplayWindowGeometryToConfig(); void saveDisplayWindowGeometryToConfig();
void restoreDisplayWindowGeometryFromConfig(); void restoreDisplayWindowGeometryFromConfig();
bool wantsDisplayWidget() const; bool wantsDisplayWidget() const;
void createDisplayWidget(bool fullscreen, bool render_to_main, bool use_main_window_pos); void createDisplayWidget(bool fullscreen, bool render_to_main);
void destroyDisplayWidget(bool show_game_list); void destroyDisplayWidget(bool show_game_list);
void updateDisplayWidgetCursor(); void updateDisplayWidgetCursor();
void updateDisplayRelatedActions(bool has_surface, bool fullscreen); void updateDisplayRelatedActions(bool has_surface, bool fullscreen);

View File

@ -568,27 +568,11 @@ void Host::LoadSettings(const SettingsInterface& si, std::unique_lock<std::mutex
{ {
} }
void EmuThread::checkForSettingsChanges(const Settings& old_settings)
{
if (g_main_window)
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
// don't mess with fullscreen while locked
if (!QtHost::IsSystemLocked())
{
const bool render_to_main = QtHost::CanRenderToMainWindow();
if (m_is_rendering_to_main != render_to_main && !m_is_fullscreen)
{
m_is_rendering_to_main = render_to_main;
if (g_gpu_device)
GPUThread::UpdateDisplayWindow(m_is_fullscreen);
}
}
}
void Host::CheckForSettingsChanges(const Settings& old_settings) void Host::CheckForSettingsChanges(const Settings& old_settings)
{ {
g_emu_thread->checkForSettingsChanges(old_settings); // NOTE: emu thread, push to UI thread
if (g_main_window)
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
} }
void EmuThread::setDefaultSettings(bool system /* = true */, bool controller /* = true */) void EmuThread::setDefaultSettings(bool system /* = true */, bool controller /* = true */)
@ -649,6 +633,12 @@ bool QtHost::CanRenderToMainWindow()
return !Host::GetBoolSettingValue("Main", "RenderToSeparateWindow", false) && !InNoGUIMode(); return !Host::GetBoolSettingValue("Main", "RenderToSeparateWindow", false) && !InNoGUIMode();
} }
bool QtHost::UseMainWindowGeometryForDisplayWindow()
{
// nogui _or_ main window mode, since we want to use it for temporary unfullscreens
return !Host::GetBoolSettingValue("Main", "RenderToSeparateWindow", false) || InNoGUIMode();
}
void Host::RequestResizeHostDisplay(s32 new_window_width, s32 new_window_height) void Host::RequestResizeHostDisplay(s32 new_window_width, s32 new_window_height)
{ {
if (g_emu_thread->isFullscreen()) if (g_emu_thread->isFullscreen())
@ -729,7 +719,6 @@ void EmuThread::startFullscreenUI()
// we want settings loaded so we choose the correct renderer // we want settings loaded so we choose the correct renderer
// this also sorts out input sources. // this also sorts out input sources.
System::LoadSettings(false); System::LoadSettings(false);
m_is_rendering_to_main = QtHost::CanRenderToMainWindow();
// borrow the game start fullscreen flag // borrow the game start fullscreen flag
const bool start_fullscreen = const bool start_fullscreen =
@ -799,8 +788,6 @@ void EmuThread::bootSystem(std::shared_ptr<SystemBootParameters> params)
if (System::IsValidOrInitializing()) if (System::IsValidOrInitializing())
return; return;
m_is_rendering_to_main = QtHost::CanRenderToMainWindow();
Error error; Error error;
if (!System::BootSystem(std::move(*params), &error)) if (!System::BootSystem(std::move(*params), &error))
{ {
@ -913,15 +900,14 @@ void EmuThread::toggleFullscreen()
return; return;
} }
setFullscreen(!m_is_fullscreen, true); setFullscreen(!m_is_fullscreen);
} }
void EmuThread::setFullscreen(bool fullscreen, bool allow_render_to_main) void EmuThread::setFullscreen(bool fullscreen)
{ {
if (!isCurrentThread()) if (!isCurrentThread())
{ {
QMetaObject::invokeMethod(this, "setFullscreen", Qt::QueuedConnection, Q_ARG(bool, fullscreen), QMetaObject::invokeMethod(this, "setFullscreen", Qt::QueuedConnection, Q_ARG(bool, fullscreen));
Q_ARG(bool, allow_render_to_main));
return; return;
} }
@ -929,7 +915,6 @@ void EmuThread::setFullscreen(bool fullscreen, bool allow_render_to_main)
return; return;
m_is_fullscreen = fullscreen; m_is_fullscreen = fullscreen;
m_is_rendering_to_main = allow_render_to_main && QtHost::CanRenderToMainWindow();
GPUThread::UpdateDisplayWindow(fullscreen); GPUThread::UpdateDisplayWindow(fullscreen);
} }
@ -944,7 +929,7 @@ void Host::SetFullscreen(bool enabled)
if (QtHost::IsSystemLocked()) if (QtHost::IsSystemLocked())
return; return;
g_emu_thread->setFullscreen(enabled, true); g_emu_thread->setFullscreen(enabled);
} }
void EmuThread::setSurfaceless(bool surfaceless) void EmuThread::setSurfaceless(bool surfaceless)
@ -962,6 +947,17 @@ void EmuThread::setSurfaceless(bool surfaceless)
GPUThread::UpdateDisplayWindow(false); GPUThread::UpdateDisplayWindow(false);
} }
void EmuThread::updateDisplayWindow()
{
if (!isCurrentThread())
{
QMetaObject::invokeMethod(this, &EmuThread::updateDisplayWindow, Qt::QueuedConnection);
return;
}
GPUThread::UpdateDisplayWindow(m_is_fullscreen);
}
void EmuThread::requestDisplaySize(float scale) void EmuThread::requestDisplaySize(float scale)
{ {
if (!isCurrentThread()) if (!isCurrentThread())
@ -983,12 +979,8 @@ std::optional<WindowInfo> EmuThread::acquireRenderWindow(RenderAPI render_api, b
m_is_fullscreen = fullscreen; m_is_fullscreen = fullscreen;
const bool window_fullscreen = m_is_fullscreen && !exclusive_fullscreen; return emit onAcquireRenderWindowRequested(render_api, m_is_fullscreen, exclusive_fullscreen, m_is_surfaceless,
const bool render_to_main = !fullscreen && m_is_rendering_to_main; error);
const bool use_main_window_pos = QtHost::CanRenderToMainWindow();
return emit onAcquireRenderWindowRequested(render_api, window_fullscreen, exclusive_fullscreen, render_to_main,
m_is_surfaceless, use_main_window_pos, error);
} }
void EmuThread::releaseRenderWindow() void EmuThread::releaseRenderWindow()

View File

@ -32,8 +32,8 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector>
#include <variant> #include <variant>
#include <vector>
class QActionGroup; class QActionGroup;
class QEventLoop; class QEventLoop;
@ -97,7 +97,6 @@ public:
ALWAYS_INLINE QEventLoop* getEventLoop() const { return m_event_loop; } ALWAYS_INLINE QEventLoop* getEventLoop() const { return m_event_loop; }
ALWAYS_INLINE bool isFullscreen() const { return m_is_fullscreen; } ALWAYS_INLINE bool isFullscreen() const { return m_is_fullscreen; }
ALWAYS_INLINE bool isRenderingToMain() const { return m_is_rendering_to_main; }
ALWAYS_INLINE bool isSurfaceless() const { return m_is_surfaceless; } ALWAYS_INLINE bool isSurfaceless() const { return m_is_surfaceless; }
ALWAYS_INLINE InputDeviceListModel* getInputDeviceListModel() const { return m_input_device_list_model.get(); } ALWAYS_INLINE InputDeviceListModel* getInputDeviceListModel() const { return m_input_device_list_model.get(); }
@ -111,8 +110,6 @@ public:
void stopBackgroundControllerPollTimer(); void stopBackgroundControllerPollTimer();
void wakeThread(); void wakeThread();
void checkForSettingsChanges(const Settings& old_settings);
void bootOrLoadState(std::string path); void bootOrLoadState(std::string path);
void updatePerformanceCounters(const GPUBackend* gpu_backend); void updatePerformanceCounters(const GPUBackend* gpu_backend);
@ -146,8 +143,7 @@ Q_SIGNALS:
void gameListRefreshed(); void gameListRefreshed();
void gameListRowsChanged(const QList<int>& rows_changed); void gameListRowsChanged(const QList<int>& rows_changed);
std::optional<WindowInfo> onAcquireRenderWindowRequested(RenderAPI render_api, bool fullscreen, std::optional<WindowInfo> onAcquireRenderWindowRequested(RenderAPI render_api, bool fullscreen,
bool exclusive_fullscreen, bool render_to_main, bool exclusive_fullscreen, bool surfaceless, Error* error);
bool surfaceless, bool use_main_window_pos, Error* error);
void onResizeRenderWindowRequested(qint32 width, qint32 height); void onResizeRenderWindowRequested(qint32 width, qint32 height);
void onReleaseRenderWindowRequested(); void onReleaseRenderWindowRequested();
void focusDisplayWidgetRequested(); void focusDisplayWidgetRequested();
@ -210,8 +206,9 @@ public Q_SLOTS:
void saveScreenshot(); void saveScreenshot();
void redrawDisplayWindow(); void redrawDisplayWindow();
void toggleFullscreen(); void toggleFullscreen();
void setFullscreen(bool fullscreen, bool allow_render_to_main); void setFullscreen(bool fullscreen);
void setSurfaceless(bool surfaceless); void setSurfaceless(bool surfaceless);
void updateDisplayWindow();
void requestDisplaySize(float scale); void requestDisplaySize(float scale);
void applyCheat(const QString& name); void applyCheat(const QString& name);
void reloadPostProcessingShaders(); void reloadPostProcessingShaders();
@ -253,7 +250,6 @@ private:
std::unique_ptr<InputDeviceListModel> m_input_device_list_model; std::unique_ptr<InputDeviceListModel> m_input_device_list_model;
bool m_shutdown_flag = false; bool m_shutdown_flag = false;
bool m_is_rendering_to_main = false;
bool m_is_fullscreen = false; bool m_is_fullscreen = false;
bool m_is_fullscreen_ui_started = false; bool m_is_fullscreen_ui_started = false;
bool m_gpu_thread_run_idle = false; bool m_gpu_thread_run_idle = false;
@ -364,6 +360,9 @@ bool IsRunningOnWayland();
/// Returns true if rendering to the main window should be allowed. /// Returns true if rendering to the main window should be allowed.
bool CanRenderToMainWindow(); bool CanRenderToMainWindow();
/// Returns true if the separate-window display widget should use the main window coordinates.
bool UseMainWindowGeometryForDisplayWindow();
/// Default language for the platform. /// Default language for the platform.
const char* GetDefaultLanguage(); const char* GetDefaultLanguage();