From bfb575cf40990fde1d0baec442c3603c07e2dd45 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 25 Feb 2021 12:51:43 +1000 Subject: [PATCH] Qt: Improve handling of exclusive fullscreen loss Exclusive fullscreen will be re-requested automatically when the window regains focus. --- src/duckstation-qt/mainwindow.cpp | 12 +++++++++-- src/duckstation-qt/qtdisplaywidget.cpp | 16 +++++++++++++++ src/duckstation-qt/qtdisplaywidget.h | 1 + src/duckstation-qt/qthostinterface.cpp | 23 ++++++++++++++++++---- src/duckstation-qt/qthostinterface.h | 2 ++ src/frontend-common/d3d11_host_display.cpp | 11 ++++++++--- 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 69cd0a9de..49299e4f7 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -178,6 +178,9 @@ QtDisplayWidget* MainWindow::updateDisplay(QThread* worker_thread, bool fullscre if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen) { qDebug() << "Toggling to" << (fullscreen ? "fullscreen" : "windowed") << "without recreating surface"; + if (m_host_display && m_host_display->IsFullscreen()) + m_host_display->SetFullscreen(false, 0, 0, 0.0f); + if (fullscreen) { m_display_widget->showFullScreen(); @@ -253,10 +256,15 @@ void MainWindow::setDisplayFullscreen(const std::string& fullscreen_mode) if (CommonHostInterface::ParseFullscreenMode(fullscreen_mode, &width, &height, &refresh_rate)) { result = m_host_display->SetFullscreen(true, width, height, refresh_rate); - if (!result) + if (result) { m_host_interface->AddOSDMessage( - m_host_interface->TranslateStdString("OSDMessage", "Failed to acquire exclusive fullscreen."), 20.0f); + m_host_interface->TranslateStdString("OSDMessage", "Acquired exclusive fullscreen."), 10.0f); + } + else + { + m_host_interface->AddOSDMessage( + m_host_interface->TranslateStdString("OSDMessage", "Failed to acquire exclusive fullscreen."), 10.0f); } } } diff --git a/src/duckstation-qt/qtdisplaywidget.cpp b/src/duckstation-qt/qtdisplaywidget.cpp index 9470a090a..c02a39172 100644 --- a/src/duckstation-qt/qtdisplaywidget.cpp +++ b/src/duckstation-qt/qtdisplaywidget.cpp @@ -202,6 +202,22 @@ bool QtDisplayWidget::event(QEvent* event) return true; } + case QEvent::FocusIn: + { + QWidget::event(event); + emit windowFocusEvent(); + return true; + } + + case QEvent::ActivationChange: + { + QWidget::event(event); + if (isActiveWindow()) + emit windowFocusEvent(); + + return true; + } + default: return QWidget::event(event); } diff --git a/src/duckstation-qt/qtdisplaywidget.h b/src/duckstation-qt/qtdisplaywidget.h index 49e79f699..9056c803b 100644 --- a/src/duckstation-qt/qtdisplaywidget.h +++ b/src/duckstation-qt/qtdisplaywidget.h @@ -23,6 +23,7 @@ public: void setRelativeMode(bool enabled); Q_SIGNALS: + void windowFocusEvent(); void windowResizedEvent(int width, int height); void windowRestoredEvent(); void windowClosedEvent(); diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index 36dff0cdd..892794073 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -415,6 +415,7 @@ void QtHostInterface::onDisplayWindowMouseButtonEvent(int button, bool pressed) void QtHostInterface::onHostDisplayWindowResized(int width, int height) { + Log_WarningPrintf("resize %dx%d", width, height); // this can be null if it was destroyed and the main thread is late catching up if (!m_display) return; @@ -427,11 +428,11 @@ void QtHostInterface::onHostDisplayWindowResized(int width, int height) { if (m_is_exclusive_fullscreen && !m_display->IsFullscreen()) { - // we lost exclusive fullscreen - AddOSDMessage(TranslateStdString("OSDMessage", "Lost exclusive fullscreen."), 20.0f); + // we lost exclusive fullscreen, switch to borderless + AddOSDMessage(TranslateStdString("OSDMessage", "Lost exclusive fullscreen."), 10.0f); m_is_exclusive_fullscreen = false; m_is_fullscreen = false; - updateDisplayState(); + m_lost_exclusive_fullscreen = true; } // force redraw if we're paused @@ -440,6 +441,18 @@ void QtHostInterface::onHostDisplayWindowResized(int width, int height) } } +void QtHostInterface::onHostDisplayWindowFocused() +{ + if (!m_display || !m_lost_exclusive_fullscreen) + return; + + // try to restore exclusive fullscreen + m_lost_exclusive_fullscreen = false; + m_is_exclusive_fullscreen = true; + m_is_fullscreen = true; + updateDisplayState(); +} + void QtHostInterface::redrawDisplayWindow() { if (!isOnWorkerThread()) @@ -526,6 +539,7 @@ void QtHostInterface::connectDisplaySignals(QtDisplayWidget* widget) { widget->disconnect(this); + connect(widget, &QtDisplayWidget::windowFocusEvent, this, &QtHostInterface::onHostDisplayWindowFocused); connect(widget, &QtDisplayWidget::windowResizedEvent, this, &QtHostInterface::onHostDisplayWindowResized); connect(widget, &QtDisplayWidget::windowRestoredEvent, this, &QtHostInterface::redrawDisplayWindow); connect(widget, &QtDisplayWidget::windowClosedEvent, this, &QtHostInterface::powerOffSystem, @@ -543,7 +557,8 @@ void QtHostInterface::updateDisplayState() // this expects the context to get moved back to us afterwards m_display->DoneRenderContextCurrent(); - QtDisplayWidget* display_widget = updateDisplayRequested(m_worker_thread, m_is_fullscreen, m_is_rendering_to_main); + QtDisplayWidget* display_widget = + updateDisplayRequested(m_worker_thread, m_is_fullscreen, m_is_rendering_to_main && !m_is_fullscreen); if (!display_widget || !m_display->MakeRenderContextCurrent()) Panic("Failed to make device context current after updating"); diff --git a/src/duckstation-qt/qthostinterface.h b/src/duckstation-qt/qthostinterface.h index 9ff94b720..5d3b9705a 100644 --- a/src/duckstation-qt/qthostinterface.h +++ b/src/duckstation-qt/qthostinterface.h @@ -180,6 +180,7 @@ public Q_SLOTS: private Q_SLOTS: void doStopThread(); void onHostDisplayWindowResized(int width, int height); + void onHostDisplayWindowFocused(); void doBackgroundControllerPoll(); void doSaveSettings(); @@ -276,4 +277,5 @@ private: bool m_is_rendering_to_main = false; bool m_is_fullscreen = false; bool m_is_exclusive_fullscreen = false; + bool m_lost_exclusive_fullscreen = false; }; diff --git a/src/frontend-common/d3d11_host_display.cpp b/src/frontend-common/d3d11_host_display.cpp index ee057faf3..ad1e6821a 100644 --- a/src/frontend-common/d3d11_host_display.cpp +++ b/src/frontend-common/d3d11_host_display.cpp @@ -436,9 +436,14 @@ bool D3D11HostDisplay::CreateSwapChain(const DXGI_MODE_DESC* fullscreen_mode) } } - hr = m_dxgi_factory->MakeWindowAssociation(swap_chain_desc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES); - if (FAILED(hr)) - Log_WarningPrintf("MakeWindowAssociation() to disable ALT+ENTER failed"); + ComPtr dxgi_factory; + hr = m_swap_chain->GetParent(IID_PPV_ARGS(dxgi_factory.GetAddressOf())); + if (SUCCEEDED(hr)) + { + hr = dxgi_factory->MakeWindowAssociation(swap_chain_desc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES); + if (FAILED(hr)) + Log_WarningPrintf("MakeWindowAssociation() to disable ALT+ENTER failed"); + } return CreateSwapChainRTV(); }