Qt: Improve handling of exclusive fullscreen loss

Exclusive fullscreen will be re-requested automatically when the window
regains focus.
This commit is contained in:
Connor McLaughlin 2021-02-25 12:51:43 +10:00
parent defea38a60
commit bfb575cf40
6 changed files with 56 additions and 9 deletions

View File

@ -178,6 +178,9 @@ QtDisplayWidget* MainWindow::updateDisplay(QThread* worker_thread, bool fullscre
if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen) if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen)
{ {
qDebug() << "Toggling to" << (fullscreen ? "fullscreen" : "windowed") << "without recreating surface"; 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) if (fullscreen)
{ {
m_display_widget->showFullScreen(); 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)) if (CommonHostInterface::ParseFullscreenMode(fullscreen_mode, &width, &height, &refresh_rate))
{ {
result = m_host_display->SetFullscreen(true, 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->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);
} }
} }
} }

View File

@ -202,6 +202,22 @@ bool QtDisplayWidget::event(QEvent* event)
return true; 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: default:
return QWidget::event(event); return QWidget::event(event);
} }

View File

@ -23,6 +23,7 @@ public:
void setRelativeMode(bool enabled); void setRelativeMode(bool enabled);
Q_SIGNALS: Q_SIGNALS:
void windowFocusEvent();
void windowResizedEvent(int width, int height); void windowResizedEvent(int width, int height);
void windowRestoredEvent(); void windowRestoredEvent();
void windowClosedEvent(); void windowClosedEvent();

View File

@ -415,6 +415,7 @@ void QtHostInterface::onDisplayWindowMouseButtonEvent(int button, bool pressed)
void QtHostInterface::onHostDisplayWindowResized(int width, int height) 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 // this can be null if it was destroyed and the main thread is late catching up
if (!m_display) if (!m_display)
return; return;
@ -427,11 +428,11 @@ void QtHostInterface::onHostDisplayWindowResized(int width, int height)
{ {
if (m_is_exclusive_fullscreen && !m_display->IsFullscreen()) if (m_is_exclusive_fullscreen && !m_display->IsFullscreen())
{ {
// we lost exclusive fullscreen // we lost exclusive fullscreen, switch to borderless
AddOSDMessage(TranslateStdString("OSDMessage", "Lost exclusive fullscreen."), 20.0f); AddOSDMessage(TranslateStdString("OSDMessage", "Lost exclusive fullscreen."), 10.0f);
m_is_exclusive_fullscreen = false; m_is_exclusive_fullscreen = false;
m_is_fullscreen = false; m_is_fullscreen = false;
updateDisplayState(); m_lost_exclusive_fullscreen = true;
} }
// force redraw if we're paused // 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() void QtHostInterface::redrawDisplayWindow()
{ {
if (!isOnWorkerThread()) if (!isOnWorkerThread())
@ -526,6 +539,7 @@ void QtHostInterface::connectDisplaySignals(QtDisplayWidget* widget)
{ {
widget->disconnect(this); widget->disconnect(this);
connect(widget, &QtDisplayWidget::windowFocusEvent, this, &QtHostInterface::onHostDisplayWindowFocused);
connect(widget, &QtDisplayWidget::windowResizedEvent, this, &QtHostInterface::onHostDisplayWindowResized); connect(widget, &QtDisplayWidget::windowResizedEvent, this, &QtHostInterface::onHostDisplayWindowResized);
connect(widget, &QtDisplayWidget::windowRestoredEvent, this, &QtHostInterface::redrawDisplayWindow); connect(widget, &QtDisplayWidget::windowRestoredEvent, this, &QtHostInterface::redrawDisplayWindow);
connect(widget, &QtDisplayWidget::windowClosedEvent, this, &QtHostInterface::powerOffSystem, 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 // this expects the context to get moved back to us afterwards
m_display->DoneRenderContextCurrent(); 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()) if (!display_widget || !m_display->MakeRenderContextCurrent())
Panic("Failed to make device context current after updating"); Panic("Failed to make device context current after updating");

View File

@ -180,6 +180,7 @@ public Q_SLOTS:
private Q_SLOTS: private Q_SLOTS:
void doStopThread(); void doStopThread();
void onHostDisplayWindowResized(int width, int height); void onHostDisplayWindowResized(int width, int height);
void onHostDisplayWindowFocused();
void doBackgroundControllerPoll(); void doBackgroundControllerPoll();
void doSaveSettings(); void doSaveSettings();
@ -276,4 +277,5 @@ private:
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_exclusive_fullscreen = false; bool m_is_exclusive_fullscreen = false;
bool m_lost_exclusive_fullscreen = false;
}; };

View File

@ -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); ComPtr<IDXGIFactory> dxgi_factory;
if (FAILED(hr)) hr = m_swap_chain->GetParent(IID_PPV_ARGS(dxgi_factory.GetAddressOf()));
Log_WarningPrintf("MakeWindowAssociation() to disable ALT+ENTER failed"); 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(); return CreateSwapChainRTV();
} }