Qt: Fix fullscreening in Wayland

This commit is contained in:
Connor McLaughlin 2022-04-15 18:45:41 +10:00 committed by refractionpcsx2
parent 06beadba74
commit 7194542029
4 changed files with 25 additions and 21 deletions

View File

@ -24,6 +24,7 @@
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include <QtGui/QKeyEvent> #include <QtGui/QKeyEvent>
#include <QtGui/QResizeEvent>
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <QtGui/QWindowStateChangeEvent> #include <QtGui/QWindowStateChangeEvent>
@ -208,7 +209,12 @@ bool DisplayWidget::event(QEvent* event)
{ {
QWidget::event(event); QWidget::event(event);
emit windowResizedEvent(scaledWindowWidth(), scaledWindowHeight(), devicePixelRatioFromScreen()); const qreal dpr = devicePixelRatioFromScreen();
const QSize size = static_cast<QResizeEvent*>(event)->size();
const int width = static_cast<int>(std::ceil(static_cast<qreal>(size.width()) * devicePixelRatioFromScreen()));
const int height = static_cast<int>(std::ceil(static_cast<qreal>(size.height()) * devicePixelRatioFromScreen()));
emit windowResizedEvent(width, height, dpr);
return true; return true;
} }
@ -262,7 +268,7 @@ bool DisplayContainer::IsNeeded(bool fullscreen, bool render_to_main)
#if defined(_WIN32) || defined(__APPLE__) #if defined(_WIN32) || defined(__APPLE__)
return false; return false;
#else #else
if (fullscreen || render_to_main) if (!fullscreen && render_to_main)
return false; return false;
// We only need this on Wayland because of client-side decorations... // We only need this on Wayland because of client-side decorations...

View File

@ -603,9 +603,6 @@ void EmuThread::updateDisplay()
pxFailRel("Failed to recreate context after updating"); pxFailRel("Failed to recreate context after updating");
return; return;
} }
// this is always a new widget, so reconnect it
connectDisplaySignals(widget);
} }
HostDisplay* EmuThread::acquireHostDisplay(HostDisplay::RenderAPI api) HostDisplay* EmuThread::acquireHostDisplay(HostDisplay::RenderAPI api)

View File

@ -47,6 +47,7 @@ public:
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main). /// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
HostDisplay* acquireHostDisplay(HostDisplay::RenderAPI api); HostDisplay* acquireHostDisplay(HostDisplay::RenderAPI api);
void connectDisplaySignals(DisplayWidget* widget);
void releaseHostDisplay(); void releaseHostDisplay();
void updateDisplay(); void updateDisplay();
@ -127,7 +128,6 @@ private:
static constexpr u32 BACKGROUND_CONTROLLER_POLLING_INTERVAL = static constexpr u32 BACKGROUND_CONTROLLER_POLLING_INTERVAL =
100; /// Interval at which the controllers are polled when the system is not active. 100; /// Interval at which the controllers are polled when the system is not active.
void connectDisplaySignals(DisplayWidget* widget);
void destroyVM(); void destroyVM();
void executeVM(); void executeVM();
void checkForSettingChanges(); void checkForSettingChanges();

View File

@ -1140,8 +1140,6 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
container->showFullScreen(); container->showFullScreen();
else else
container->showNormal(); container->showNormal();
// updateMouseMode(System::IsPaused());
} }
else if (!render_to_main) else if (!render_to_main)
{ {
@ -1150,7 +1148,7 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
} }
else else
{ {
m_ui.mainContainer->insertWidget(1, m_display_widget); m_ui.mainContainer->insertWidget(1, container);
switchToEmulationView(); switchToEmulationView();
} }
@ -1165,6 +1163,8 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
return nullptr; return nullptr;
} }
g_emu_thread->connectDisplaySignals(m_display_widget);
if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""), EmuConfig.GetEffectiveVsyncMode(), if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""), EmuConfig.GetEffectiveVsyncMode(),
Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false), Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false))) Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false), Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false)))
{ {
@ -1183,34 +1183,35 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main) DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
{ {
HostDisplay* host_display = Host::GetHostDisplay(); HostDisplay* host_display = Host::GetHostDisplay();
const bool is_fullscreen = m_display_widget->isFullScreen(); QWidget* container = m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget);
const bool is_rendering_to_main = (!is_fullscreen && m_display_widget->parent()); const bool is_fullscreen = container->isFullScreen();
const bool is_rendering_to_main = (!is_fullscreen && 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) if (fullscreen == is_fullscreen && is_rendering_to_main == render_to_main)
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.
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) if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen && has_container == needs_container && !needs_container)
{ {
qDebug() << "Toggling to" << (fullscreen ? "fullscreen" : "windowed") << "without recreating surface"; Console.WriteLn("Toggling to %s without recreating surface", (fullscreen ? "fullscreen" : "windowed"));
if (host_display->IsFullscreen()) if (host_display->IsFullscreen())
host_display->SetFullscreen(false, 0, 0, 0.0f); host_display->SetFullscreen(false, 0, 0, 0.0f);
if (fullscreen) if (fullscreen)
{ {
m_display_widget->showFullScreen(); container->showFullScreen();
} }
else else
{ {
restoreDisplayWindowGeometryFromConfig(); restoreDisplayWindowGeometryFromConfig();
m_display_widget->showNormal(); container->showNormal();
} }
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
// updateMouseMode(System::IsPaused());
return m_display_widget; return m_display_widget;
} }
@ -1218,7 +1219,6 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
destroyDisplayWidget(); destroyDisplayWidget();
QWidget* container;
if (DisplayContainer::IsNeeded(fullscreen, render_to_main)) if (DisplayContainer::IsNeeded(fullscreen, render_to_main))
{ {
m_display_container = new DisplayContainer(); m_display_container = new DisplayContainer();
@ -1241,8 +1241,6 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
container->showFullScreen(); container->showFullScreen();
else else
container->showNormal(); container->showNormal();
// updateMouseMode(System::IsPaused());
} }
else if (!render_to_main) else if (!render_to_main)
{ {
@ -1251,7 +1249,7 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
} }
else else
{ {
m_ui.mainContainer->insertWidget(1, m_display_widget); m_ui.mainContainer->insertWidget(1, container);
switchToEmulationView(); switchToEmulationView();
} }
@ -1266,6 +1264,8 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main)
return nullptr; return nullptr;
} }
g_emu_thread->connectDisplaySignals(m_display_widget);
if (!host_display->ChangeRenderWindow(wi.value())) if (!host_display->ChangeRenderWindow(wi.value()))
pxFailRel("Failed to recreate surface on new widget."); pxFailRel("Failed to recreate surface on new widget.");
@ -1344,7 +1344,8 @@ void MainWindow::destroyDisplayWidget()
if (!m_display_widget) if (!m_display_widget)
return; return;
if (m_display_container || (!m_display_widget->parent() && !m_display_widget->isFullScreen())) const QWidget* container = m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget);
if (!container->parent() && !container->isFullScreen())
saveDisplayWindowGeometryToConfig(); saveDisplayWindowGeometryToConfig();
if (m_display_container) if (m_display_container)