Qt: Rework display widget swapping

This commit is contained in:
Connor McLaughlin 2022-05-06 21:03:16 +10:00 committed by refractionpcsx2
parent 233195b020
commit 98b537575f
8 changed files with 188 additions and 83 deletions

View File

@ -17,6 +17,7 @@
#include "DisplayWidget.h" #include "DisplayWidget.h"
#include "EmuThread.h" #include "EmuThread.h"
#include "MainWindow.h"
#include "QtHost.h" #include "QtHost.h"
#include "pcsx2/GS/GSIntrin.h" // _BitScanForward #include "pcsx2/GS/GSIntrin.h" // _BitScanForward
@ -242,7 +243,13 @@ bool DisplayWidget::event(QEvent* event)
case QEvent::Close: case QEvent::Close:
{ {
emit windowClosedEvent(); if (!g_main_window->requestShutdown())
{
// abort the window close
event->ignore();
return true;
}
QWidget::event(event); QWidget::event(event);
return true; return true;
} }
@ -317,18 +324,19 @@ DisplayWidget* DisplayContainer::removeDisplayWidget()
bool DisplayContainer::event(QEvent* event) bool DisplayContainer::event(QEvent* event)
{ {
if (event->type() == QEvent::Close && !g_main_window->requestShutdown())
{
// abort the window close
event->ignore();
return true;
}
const bool res = QStackedWidget::event(event); const bool res = QStackedWidget::event(event);
if (!m_display_widget) if (!m_display_widget)
return res; return res;
switch (event->type()) switch (event->type())
{ {
case QEvent::Close:
{
emit m_display_widget->windowClosedEvent();
}
break;
case QEvent::WindowStateChange: case QEvent::WindowStateChange:
{ {
if (static_cast<QWindowStateChangeEvent*>(event)->oldState() & Qt::WindowMinimized) if (static_cast<QWindowStateChangeEvent*>(event)->oldState() & Qt::WindowMinimized)

View File

@ -42,7 +42,6 @@ Q_SIGNALS:
void windowFocusEvent(); void windowFocusEvent();
void windowResizedEvent(int width, int height, float scale); void windowResizedEvent(int width, int height, float scale);
void windowRestoredEvent(); void windowRestoredEvent();
void windowClosedEvent();
void windowKeyEvent(int key_code, bool pressed); void windowKeyEvent(int key_code, bool pressed);
void windowMouseMoveEvent(int x, int y); void windowMouseMoveEvent(int x, int y);
void windowMouseButtonEvent(int button, bool pressed); void windowMouseButtonEvent(int button, bool pressed);

View File

@ -108,6 +108,7 @@ void EmuThread::startVM(std::shared_ptr<VMBootParameters> boot_params)
// create the display, this may take a while... // create the display, this may take a while...
m_is_fullscreen = boot_params->fullscreen.value_or(QtHost::GetBaseBoolSettingValue("UI", "StartFullscreen", false)); m_is_fullscreen = boot_params->fullscreen.value_or(QtHost::GetBaseBoolSettingValue("UI", "StartFullscreen", false));
m_is_rendering_to_main = QtHost::GetBaseBoolSettingValue("UI", "RenderToMainWindow", true); m_is_rendering_to_main = QtHost::GetBaseBoolSettingValue("UI", "RenderToMainWindow", true);
m_is_surfaceless = false;
if (!VMManager::Initialize(*boot_params)) if (!VMManager::Initialize(*boot_params))
return; return;
@ -134,6 +135,10 @@ void EmuThread::setVMPaused(bool paused)
return; return;
} }
// if we were surfaceless (view->game list, system->unpause), get our display widget back
if (m_is_surfaceless)
setSurfaceless(false);
VMManager::SetPaused(paused); VMManager::SetPaused(paused);
} }
@ -346,6 +351,23 @@ void EmuThread::setFullscreen(bool fullscreen)
GetMTGS().WaitGS(); GetMTGS().WaitGS();
} }
void EmuThread::setSurfaceless(bool surfaceless)
{
if (!isOnEmuThread())
{
QMetaObject::invokeMethod(this, "setSurfaceless", Qt::QueuedConnection, Q_ARG(bool, surfaceless));
return;
}
if (!VMManager::HasValidVM() || m_is_surfaceless == surfaceless)
return;
// This will call back to us on the MTGS thread.
m_is_surfaceless = surfaceless;
GetMTGS().UpdateDisplayWindow();
GetMTGS().WaitGS();
}
void EmuThread::applySettings() void EmuThread::applySettings()
{ {
if (!isOnEmuThread()) if (!isOnEmuThread())
@ -545,7 +567,6 @@ void EmuThread::connectDisplaySignals(DisplayWidget* widget)
connect(widget, &DisplayWidget::windowFocusEvent, this, &EmuThread::onDisplayWindowFocused); connect(widget, &DisplayWidget::windowFocusEvent, this, &EmuThread::onDisplayWindowFocused);
connect(widget, &DisplayWidget::windowResizedEvent, this, &EmuThread::onDisplayWindowResized); connect(widget, &DisplayWidget::windowResizedEvent, this, &EmuThread::onDisplayWindowResized);
// connect(widget, &DisplayWidget::windowRestoredEvent, this, &EmuThread::redrawDisplayWindow); // connect(widget, &DisplayWidget::windowRestoredEvent, this, &EmuThread::redrawDisplayWindow);
connect(widget, &DisplayWidget::windowClosedEvent, []() { g_main_window->requestShutdown(); });
connect(widget, &DisplayWidget::windowKeyEvent, this, &EmuThread::onDisplayWindowKeyEvent); connect(widget, &DisplayWidget::windowKeyEvent, this, &EmuThread::onDisplayWindowKeyEvent);
connect(widget, &DisplayWidget::windowMouseMoveEvent, this, &EmuThread::onDisplayWindowMouseMoveEvent); connect(widget, &DisplayWidget::windowMouseMoveEvent, this, &EmuThread::onDisplayWindowMouseMoveEvent);
connect(widget, &DisplayWidget::windowMouseButtonEvent, this, &EmuThread::onDisplayWindowMouseButtonEvent); connect(widget, &DisplayWidget::windowMouseButtonEvent, this, &EmuThread::onDisplayWindowMouseButtonEvent);
@ -590,8 +611,8 @@ void EmuThread::updateDisplay()
display->DoneRenderContextCurrent(); display->DoneRenderContextCurrent();
// but we should get it back after this call // but we should get it back after this call
DisplayWidget* widget = onUpdateDisplayRequested(m_is_fullscreen, !m_is_fullscreen && m_is_rendering_to_main); onUpdateDisplayRequested(m_is_fullscreen, !m_is_fullscreen && m_is_rendering_to_main, m_is_surfaceless);
if (!widget || !display->MakeRenderContextCurrent()) if (!display->MakeRenderContextCurrent())
{ {
pxFailRel("Failed to recreate context after updating"); pxFailRel("Failed to recreate context after updating");
return; return;
@ -851,9 +872,11 @@ void Host::RunOnCPUThread(std::function<void()> function, bool block /* = false
Q_ARG(const std::function<void()>&, std::move(function))); Q_ARG(const std::function<void()>&, std::move(function)));
} }
ScopedVMPause::ScopedVMPause(bool was_paused) ScopedVMPause::ScopedVMPause(bool was_paused, bool was_fullscreen)
: m_was_paused(was_paused) : m_was_paused(was_paused), m_was_fullscreen(was_fullscreen)
{ {
if (was_fullscreen)
g_emu_thread->setFullscreen(false);
if (!m_was_paused) if (!m_was_paused)
g_emu_thread->setVMPaused(true); g_emu_thread->setVMPaused(true);
} }
@ -862,6 +885,8 @@ ScopedVMPause::~ScopedVMPause()
{ {
if (!m_was_paused) if (!m_was_paused)
g_emu_thread->setVMPaused(false); g_emu_thread->setVMPaused(false);
if (m_was_fullscreen)
g_emu_thread->setFullscreen(true);
} }
alignas(16) static SysMtgsThread s_mtgs_thread; alignas(16) static SysMtgsThread s_mtgs_thread;

View File

@ -66,6 +66,7 @@ public Q_SLOTS:
void saveStateToSlot(qint32 slot); void saveStateToSlot(qint32 slot);
void toggleFullscreen(); void toggleFullscreen();
void setFullscreen(bool fullscreen); void setFullscreen(bool fullscreen);
void setSurfaceless(bool surfaceless);
void applySettings(); void applySettings();
void reloadGameSettings(); void reloadGameSettings();
void toggleSoftwareRendering(); void toggleSoftwareRendering();
@ -81,7 +82,7 @@ public Q_SLOTS:
Q_SIGNALS: Q_SIGNALS:
DisplayWidget* onCreateDisplayRequested(bool fullscreen, bool render_to_main); DisplayWidget* onCreateDisplayRequested(bool fullscreen, bool render_to_main);
DisplayWidget* onUpdateDisplayRequested(bool fullscreen, bool render_to_main); DisplayWidget* onUpdateDisplayRequested(bool fullscreen, bool render_to_main, bool surfaceless);
void onResizeDisplayRequested(qint32 width, qint32 height); void onResizeDisplayRequested(qint32 width, qint32 height);
void onDestroyDisplayRequested(); void onDestroyDisplayRequested();
@ -157,6 +158,7 @@ private:
bool m_verbose_status = false; bool m_verbose_status = false;
bool m_is_rendering_to_main = false; bool m_is_rendering_to_main = false;
bool m_is_fullscreen = false; bool m_is_fullscreen = false;
bool m_is_surfaceless = false;
float m_last_speed = 0.0f; float m_last_speed = 0.0f;
float m_last_game_fps = 0.0f; float m_last_game_fps = 0.0f;
@ -171,11 +173,15 @@ private:
class ScopedVMPause class ScopedVMPause
{ {
public: public:
ScopedVMPause(bool was_paused); ScopedVMPause(bool was_paused, bool was_fullscreen);
~ScopedVMPause(); ~ScopedVMPause();
__fi bool WasPaused() const { return m_was_paused; }
__fi bool WasFullscreen() const { return m_was_fullscreen; }
private: private:
bool m_was_paused; bool m_was_paused;
bool m_was_fullscreen;
}; };
extern EmuThread* g_emu_thread; extern EmuThread* g_emu_thread;

View File

@ -104,11 +104,10 @@ void MainWindow::setupAdditionalUi()
m_ui.actionViewStatusBar->setChecked(status_bar_visible); m_ui.actionViewStatusBar->setChecked(status_bar_visible);
m_ui.statusBar->setVisible(status_bar_visible); m_ui.statusBar->setVisible(status_bar_visible);
m_game_list_widget = new GameListWidget(m_ui.mainContainer); m_game_list_widget = new GameListWidget(this);
m_game_list_widget->initialize(); m_game_list_widget->initialize();
m_ui.mainContainer->insertWidget(0, m_game_list_widget);
m_ui.mainContainer->setCurrentIndex(0);
m_ui.actionGridViewShowTitles->setChecked(m_game_list_widget->getShowGridCoverTitles()); m_ui.actionGridViewShowTitles->setChecked(m_game_list_widget->getShowGridCoverTitles());
setCentralWidget(m_game_list_widget);
m_status_progress_widget = new QProgressBar(m_ui.statusBar); m_status_progress_widget = new QProgressBar(m_ui.statusBar);
m_status_progress_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); m_status_progress_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
@ -578,6 +577,9 @@ void MainWindow::updateEmulationActions(bool starting, bool running)
m_ui.actionViewGameProperties->setEnabled(running); m_ui.actionViewGameProperties->setEnabled(running);
m_game_list_widget->setDisabled(starting && !running); m_game_list_widget->setDisabled(starting && !running);
if (!starting && !running)
m_ui.actionPause->setChecked(false);
} }
void MainWindow::updateStatusBarWidgetVisibility() void MainWindow::updateStatusBarWidgetVisibility()
@ -603,26 +605,28 @@ void MainWindow::updateStatusBarWidgetVisibility()
void MainWindow::updateWindowTitle() void MainWindow::updateWindowTitle()
{ {
QString title;
if (!m_vm_valid || m_current_game_name.isEmpty())
{
#if defined(_DEBUG) #if defined(_DEBUG)
title = QStringLiteral("PCSX2 [Debug] %1").arg(GIT_REV); QString main_title(QStringLiteral("PCSX2 [Debug] %1").arg(GIT_REV));
QString display_title(QStringLiteral("%1 [Debug]").arg(m_current_game_name));
#else #else
title = QStringLiteral("PCSX2 %1").arg(GIT_REV); QString main_title(QStringLiteral("PCSX2 %1").arg(GIT_REV));
QString display_title(m_current_game_name);
#endif #endif
}
else
{
#if defined(_DEBUG)
title = QStringLiteral("%1 [Debug]").arg(m_current_game_name);
#else
title = m_current_game_name;
#endif
}
if (windowTitle() != title) if (!m_vm_valid || m_current_game_name.isEmpty())
setWindowTitle(title); display_title = main_title;
else if (isRenderingToMain())
main_title = display_title;
if (windowTitle() != main_title)
setWindowTitle(main_title);
if (m_display_widget && !isRenderingToMain())
{
QWidget* container = m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget);
if (container->windowTitle() != display_title)
container->setWindowTitle(display_title);
}
} }
void MainWindow::setProgressBar(int current, int total) void MainWindow::setProgressBar(int current, int total)
@ -648,37 +652,63 @@ void MainWindow::clearProgressBar()
bool MainWindow::isShowingGameList() const bool MainWindow::isShowingGameList() const
{ {
return m_ui.mainContainer->currentIndex() == 0; return (centralWidget() == m_game_list_widget);
}
bool MainWindow::isRenderingFullscreen() const
{
HostDisplay* display = Host::GetHostDisplay();
if (!display || !m_display_widget)
return false;
return (m_display_widget->parent() != this && (m_display_widget->isFullScreen() || display->IsFullscreen()));
}
bool MainWindow::isRenderingToMain() const
{
return (m_display_widget && m_display_widget->parent() == this);
} }
void MainWindow::switchToGameListView() void MainWindow::switchToGameListView()
{ {
if ((m_display_widget && !m_display_widget->parent()) || m_ui.mainContainer->currentIndex() == 0) if (centralWidget() == m_game_list_widget)
{
m_game_list_widget->setFocus();
return; return;
}
if (m_vm_valid) if (m_vm_valid)
{ {
m_was_focused_on_container_switch = m_vm_paused; m_was_paused_on_surface_loss = m_vm_paused;
if (!m_vm_paused) if (!m_vm_paused)
g_emu_thread->setVMPaused(true); g_emu_thread->setVMPaused(true);
// switch to surfaceless. we have to wait until the display widget is gone before we swap over.
g_emu_thread->setSurfaceless(true);
while (m_display_widget)
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
} }
m_ui.mainContainer->setCurrentIndex(0); pxAssertMsg(!centralWidget(), "Should not have a central widget at game list switch time");
takeCentralWidget();
setCentralWidget(m_game_list_widget);
m_game_list_widget->setVisible(true);
m_game_list_widget->setFocus(); m_game_list_widget->setFocus();
} }
void MainWindow::switchToEmulationView() void MainWindow::switchToEmulationView()
{ {
if (!m_display_widget || !m_display_widget->parent() || m_ui.mainContainer->currentIndex() == 1) if (!m_vm_valid || (m_display_widget && centralWidget() == m_display_widget))
return; return;
if (m_vm_valid) // we're no longer surfaceless! this will call back to UpdateDisplay(), which will swap the widget out.
{ g_emu_thread->setSurfaceless(false);
m_ui.mainContainer->setCurrentIndex(1);
if (m_vm_paused && !m_was_focused_on_container_switch)
g_emu_thread->setVMPaused(false);
}
// resume if we weren't paused at switch time
if (m_vm_paused && !m_was_paused_on_surface_loss)
g_emu_thread->setVMPaused(false);
if (m_display_widget)
m_display_widget->setFocus(); m_display_widget->setFocus();
} }
@ -710,8 +740,8 @@ bool MainWindow::requestShutdown(bool allow_confirm /* = true */, bool allow_sav
// only confirm on UI thread because we need to display a msgbox // only confirm on UI thread because we need to display a msgbox
if (allow_confirm && !GSDumpReplayer::IsReplayingDump() && QtHost::GetBaseBoolSettingValue("UI", "ConfirmShutdown", true)) if (allow_confirm && !GSDumpReplayer::IsReplayingDump() && QtHost::GetBaseBoolSettingValue("UI", "ConfirmShutdown", true))
{ {
ScopedVMPause pauser(m_vm_paused); ScopedVMPause pauser(m_vm_paused, isRenderingFullscreen());
if (QMessageBox::question(g_main_window, tr("Confirm Shutdown"), if (QMessageBox::question(m_display_widget, tr("Confirm Shutdown"),
tr("Are you sure you want to shut down the virtual machine?\n\nAll unsaved progress will be lost.")) != QMessageBox::Yes) tr("Are you sure you want to shut down the virtual machine?\n\nAll unsaved progress will be lost.")) != QMessageBox::Yes)
{ {
return false; return false;
@ -882,7 +912,7 @@ void MainWindow::onStartBIOSActionTriggered()
void MainWindow::onChangeDiscFromFileActionTriggered() void MainWindow::onChangeDiscFromFileActionTriggered()
{ {
ScopedVMPause pauser(m_vm_paused); ScopedVMPause pauser(m_vm_paused, isRenderingFullscreen());
QString filename = QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr); QString filename = QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr);
if (filename.isEmpty()) if (filename.isEmpty())
@ -1114,6 +1144,8 @@ void MainWindow::closeEvent(QCloseEvent* event)
DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main) DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
{ {
DevCon.WriteLn("createDisplay(%u, %u)", static_cast<u32>(fullscreen), static_cast<u32>(render_to_main));
HostDisplay* host_display = Host::GetHostDisplay(); HostDisplay* host_display = Host::GetHostDisplay();
if (!host_display) if (!host_display)
return nullptr; return nullptr;
@ -1131,12 +1163,15 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
} }
else else
{ {
m_display_widget = new DisplayWidget((!fullscreen && render_to_main) ? m_ui.mainContainer : nullptr); m_display_widget = new DisplayWidget((!fullscreen && render_to_main) ? this : nullptr);
container = m_display_widget; container = m_display_widget;
} }
if (fullscreen || !render_to_main)
{
container->setWindowTitle(windowTitle()); container->setWindowTitle(windowTitle());
container->setWindowIcon(windowIcon()); container->setWindowIcon(windowIcon());
}
if (fullscreen) if (fullscreen)
{ {
@ -1152,8 +1187,9 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
} }
else else
{ {
m_ui.mainContainer->insertWidget(1, container); m_game_list_widget->setVisible(false);
switchToEmulationView(); takeCentralWidget();
setCentralWidget(m_display_widget);
} }
// we need the surface visible.. this might be able to be replaced with something else // we need the surface visible.. this might be able to be replaced with something else
@ -1180,26 +1216,32 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
if (is_exclusive_fullscreen) if (is_exclusive_fullscreen)
setDisplayFullscreen(fullscreen_mode); setDisplayFullscreen(fullscreen_mode);
updateWindowTitle();
m_display_widget->setFocus();
host_display->DoneRenderContextCurrent(); host_display->DoneRenderContextCurrent();
return m_display_widget; return m_display_widget;
} }
DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main) DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main, bool surfaceless)
{ {
DevCon.WriteLn("updateDisplay(%u, %u, %u)", static_cast<u32>(fullscreen), static_cast<u32>(render_to_main), static_cast<u32>(surfaceless));
HostDisplay* host_display = Host::GetHostDisplay(); HostDisplay* host_display = Host::GetHostDisplay();
QWidget* container = m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget); QWidget* container = m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget);
const bool is_fullscreen = container->isFullScreen(); const bool is_fullscreen = (container && container->isFullScreen());
const bool is_rendering_to_main = (!is_fullscreen && container->parent()); const bool is_rendering_to_main = (!is_fullscreen && container && container->parent());
const std::string fullscreen_mode(QtHost::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", "")); const std::string fullscreen_mode(QtHost::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && host_display->SupportsFullscreen()); const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && host_display->SupportsFullscreen());
if (fullscreen == is_fullscreen && is_rendering_to_main == render_to_main) const bool changing_surfaceless = (!m_display_widget != surfaceless);
if (fullscreen == is_fullscreen && is_rendering_to_main == render_to_main && !changing_surfaceless)
return m_display_widget; return m_display_widget;
// Skip recreating the surface if we're just transitioning between fullscreen and windowed with render-to-main off. // Skip recreating the surface if we're just transitioning between fullscreen and windowed with render-to-main off.
// .. except on Wayland, where everything tends to break if you don't recreate. // .. except on Wayland, where everything tends to break if you don't recreate.
const bool has_container = (m_display_container != nullptr); const bool has_container = (m_display_container != nullptr);
const bool needs_container = DisplayContainer::IsNeeded(fullscreen, render_to_main); const bool needs_container = DisplayContainer::IsNeeded(fullscreen, render_to_main);
if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen && has_container == needs_container && !needs_container) if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen && has_container == needs_container && !needs_container && !changing_surfaceless)
{ {
Console.WriteLn("Toggling to %s without recreating surface", (fullscreen ? "fullscreen" : "windowed")); Console.WriteLn("Toggling to %s without recreating surface", (fullscreen ? "fullscreen" : "windowed"));
if (host_display->IsFullscreen()) if (host_display->IsFullscreen())
@ -1223,6 +1265,10 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
destroyDisplayWidget(); destroyDisplayWidget();
// if we're going to surfaceless, we're done here
if (surfaceless)
return nullptr;
if (DisplayContainer::IsNeeded(fullscreen, render_to_main)) if (DisplayContainer::IsNeeded(fullscreen, render_to_main))
{ {
m_display_container = new DisplayContainer(); m_display_container = new DisplayContainer();
@ -1232,13 +1278,23 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
} }
else else
{ {
m_display_widget = new DisplayWidget((!fullscreen && render_to_main) ? m_ui.mainContainer : nullptr); m_display_widget = new DisplayWidget((!fullscreen && render_to_main) ? this : nullptr);
container = m_display_widget; container = m_display_widget;
} }
if (fullscreen || !render_to_main)
{
container->setWindowTitle(windowTitle()); container->setWindowTitle(windowTitle());
container->setWindowIcon(windowIcon()); container->setWindowIcon(windowIcon());
// make sure the game list widget is still visible
if (centralWidget() != m_game_list_widget && !fullscreen)
{
setCentralWidget(m_game_list_widget);
m_game_list_widget->setVisible(true);
}
}
if (fullscreen) if (fullscreen)
{ {
if (!is_exclusive_fullscreen) if (!is_exclusive_fullscreen)
@ -1253,8 +1309,10 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
} }
else else
{ {
m_ui.mainContainer->insertWidget(1, container); m_game_list_widget->setVisible(false);
switchToEmulationView(); takeCentralWidget();
setCentralWidget(m_display_widget);
m_display_widget->setFocus();
} }
// we need the surface visible.. this might be able to be replaced with something else // we need the surface visible.. this might be able to be replaced with something else
@ -1276,6 +1334,7 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
if (is_exclusive_fullscreen) if (is_exclusive_fullscreen)
setDisplayFullscreen(fullscreen_mode); setDisplayFullscreen(fullscreen_mode);
updateWindowTitle();
m_display_widget->setFocus(); m_display_widget->setFocus();
QSignalBlocker blocker(m_ui.actionFullscreen); QSignalBlocker blocker(m_ui.actionFullscreen);
@ -1308,11 +1367,20 @@ void MainWindow::displayResizeRequested(qint32 width, qint32 height)
void MainWindow::destroyDisplay() void MainWindow::destroyDisplay()
{ {
destroyDisplayWidget(); destroyDisplayWidget();
// switch back to game list view, we're not going back to display, so we can't use switchToGameListView().
if (centralWidget() != m_game_list_widget)
{
takeCentralWidget();
setCentralWidget(m_game_list_widget);
m_game_list_widget->setVisible(true);
m_game_list_widget->setFocus();
}
} }
void MainWindow::focusDisplayWidget() void MainWindow::focusDisplayWidget()
{ {
if (m_ui.mainContainer->currentIndex() != 1) if (!m_display_widget || centralWidget() != m_display_widget)
return; return;
m_display_widget->setFocus(); m_display_widget->setFocus();
@ -1355,18 +1423,20 @@ void MainWindow::destroyDisplayWidget()
if (m_display_container) if (m_display_container)
m_display_container->removeDisplayWidget(); m_display_container->removeDisplayWidget();
if (m_display_widget->parent()) if (m_display_widget == centralWidget())
takeCentralWidget();
if (m_display_widget)
{ {
m_ui.mainContainer->removeWidget(m_display_widget); m_display_widget->deleteLater();
m_ui.mainContainer->setCurrentIndex(0); m_display_widget = nullptr;
m_game_list_widget->setFocus();
} }
delete m_display_widget; if (m_display_container)
m_display_widget = nullptr; {
m_display_container->deleteLater();
delete m_display_container;
m_display_container = nullptr; m_display_container = nullptr;
}
} }
void MainWindow::setDisplayFullscreen(const std::string& fullscreen_mode) void MainWindow::setDisplayFullscreen(const std::string& fullscreen_mode)

View File

@ -62,7 +62,7 @@ public Q_SLOTS:
private Q_SLOTS: private Q_SLOTS:
DisplayWidget* createDisplay(bool fullscreen, bool render_to_main); DisplayWidget* createDisplay(bool fullscreen, bool render_to_main);
DisplayWidget* updateDisplay(bool fullscreen, bool render_to_main); DisplayWidget* updateDisplay(bool fullscreen, bool render_to_main, bool surfaceless);
void displayResizeRequested(qint32 width, qint32 height); void displayResizeRequested(qint32 width, qint32 height);
void destroyDisplay(); void destroyDisplay();
void focusDisplayWidget(); void focusDisplayWidget();
@ -134,6 +134,8 @@ private:
void clearProgressBar(); void clearProgressBar();
bool isShowingGameList() const; bool isShowingGameList() const;
bool isRenderingFullscreen() const;
bool isRenderingToMain() const;
void switchToGameListView(); void switchToGameListView();
void switchToEmulationView(); void switchToEmulationView();
@ -181,7 +183,7 @@ private:
bool m_vm_valid = false; bool m_vm_valid = false;
bool m_vm_paused = false; bool m_vm_paused = false;
bool m_save_states_invalidated = false; bool m_save_states_invalidated = false;
bool m_was_focused_on_container_switch = false; bool m_was_paused_on_surface_loss = false;
QString m_last_fps_status; QString m_last_fps_status;
}; };

View File

@ -20,13 +20,6 @@
<iconset resource="resources/resources.qrc"> <iconset resource="resources/resources.qrc">
<normaloff>:/icons/AppIcon.png</normaloff>:/icons/AppIcon.png</iconset> <normaloff>:/icons/AppIcon.png</normaloff>:/icons/AppIcon.png</iconset>
</property> </property>
<widget class="QStackedWidget" name="mainContainer">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page"/>
<widget class="QWidget" name="page_2"/>
</widget>
<widget class="QMenuBar" name="menuBar"> <widget class="QMenuBar" name="menuBar">
<property name="geometry"> <property name="geometry">
<rect> <rect>

View File

@ -117,6 +117,7 @@ void GSinitConfig()
void GSshutdown() void GSshutdown()
{ {
#ifndef PCSX2_CORE
if (g_gs_renderer) if (g_gs_renderer)
{ {
g_gs_renderer->Destroy(); g_gs_renderer->Destroy();
@ -129,6 +130,7 @@ void GSshutdown()
} }
Host::ReleaseHostDisplay(); Host::ReleaseHostDisplay();
#endif
#ifdef _WIN32 #ifdef _WIN32
if (SUCCEEDED(s_hr)) if (SUCCEEDED(s_hr))