Rework window management to fix issues restoring window state between windowed and full-screen

This commit is contained in:
Cameron Gutman 2022-04-24 16:22:17 -05:00
parent 220f50ebe4
commit 38396b2691
3 changed files with 23 additions and 69 deletions

View file

@ -449,7 +449,6 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere
m_AudioMuted(false), m_AudioMuted(false),
m_DisplayOriginX(0), m_DisplayOriginX(0),
m_DisplayOriginY(0), m_DisplayOriginY(0),
m_PendingWindowedTransition(false),
m_UnexpectedTermination(true), // Failure prior to streaming is unexpected m_UnexpectedTermination(true), // Failure prior to streaming is unexpected
m_InputHandler(nullptr), m_InputHandler(nullptr),
m_MouseEmulationRefCount(0), m_MouseEmulationRefCount(0),
@ -897,12 +896,10 @@ void Session::getWindowDimensions(int& x, int& y,
int& width, int& height) int& width, int& height)
{ {
int displayIndex = 0; int displayIndex = 0;
bool fullScreen;
if (m_Window != nullptr) { if (m_Window != nullptr) {
displayIndex = SDL_GetWindowDisplayIndex(m_Window); displayIndex = SDL_GetWindowDisplayIndex(m_Window);
SDL_assert(displayIndex >= 0); SDL_assert(displayIndex >= 0);
fullScreen = (SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN);
} }
// Create our window on the same display that Qt's UI // Create our window on the same display that Qt's UI
// was being displayed on. // was being displayed on.
@ -929,38 +926,19 @@ void Session::getWindowDimensions(int& x, int& y,
i, SDL_GetError()); i, SDL_GetError());
} }
} }
fullScreen = m_IsFullScreen;
} }
SDL_Rect usableBounds; SDL_Rect usableBounds;
if (fullScreen && SDL_GetDisplayBounds(displayIndex, &usableBounds) == 0) { if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) {
width = usableBounds.w; // Don't use more than 80% of the display to leave room for system UI
height = usableBounds.h; width = (int)SDL_roundf(usableBounds.w * 0.80f);
} height = (int)SDL_roundf(usableBounds.h * 0.80f);
else if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) {
width = usableBounds.w;
height = usableBounds.h;
if (m_Window != nullptr) { // If the stream window can fit within the usable drawing area with 1:1
int top, left, bottom, right; // scaling, do that rather than filling the screen.
if (m_StreamConfig.width < width && m_StreamConfig.height < height) {
if (SDL_GetWindowBordersSize(m_Window, &top, &left, &bottom, &right) == 0) { width = m_StreamConfig.width;
width -= left + right; height = m_StreamConfig.height;
height -= top + bottom;
}
else {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Unable to get window border size: %s",
SDL_GetError());
}
// If the stream window can fit within the usable drawing area with 1:1
// scaling, do that rather than filling the screen.
if (m_StreamConfig.width < width && m_StreamConfig.height < height) {
width = m_StreamConfig.width;
height = m_StreamConfig.height;
}
} }
} }
else { else {
@ -1070,7 +1048,6 @@ void Session::toggleFullscreen()
SDL_SetWindowGrab(m_Window, SDL_TRUE); SDL_SetWindowGrab(m_Window, SDL_TRUE);
} }
SDL_SetWindowResizable(m_Window, SDL_FALSE);
SDL_SetWindowFullscreen(m_Window, m_FullScreenFlag); SDL_SetWindowFullscreen(m_Window, m_FullScreenFlag);
} }
else { else {
@ -1078,10 +1055,6 @@ void Session::toggleFullscreen()
SDL_SetWindowGrab(m_Window, SDL_FALSE); SDL_SetWindowGrab(m_Window, SDL_FALSE);
SDL_SetWindowFullscreen(m_Window, 0); SDL_SetWindowFullscreen(m_Window, 0);
SDL_SetWindowResizable(m_Window, SDL_TRUE);
// Reposition the window when the resize is complete
m_PendingWindowedTransition = true;
} }
// Input handler might need to start/stop keyboard grab after changing modes // Input handler might need to start/stop keyboard grab after changing modes
@ -1378,12 +1351,19 @@ void Session::execInternal()
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
Uint32 windowFlags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
// If the video is larger than the entire desktop, maximize the window
if (m_StreamConfig.width > width || m_StreamConfig.height > height) {
windowFlags |= SDL_WINDOW_MAXIMIZED;
}
m_Window = SDL_CreateWindow("Moonlight", m_Window = SDL_CreateWindow("Moonlight",
x, x,
y, y,
width, width,
height, height,
SDL_WINDOW_ALLOW_HIGHDPI | StreamUtils::getPlatformWindowFlags()); windowFlags | StreamUtils::getPlatformWindowFlags());
if (!m_Window) { if (!m_Window) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"SDL_CreateWindow() failed with platform flags: %s", "SDL_CreateWindow() failed with platform flags: %s",
@ -1394,7 +1374,7 @@ void Session::execInternal()
y, y,
width, width,
height, height,
SDL_WINDOW_ALLOW_HIGHDPI); windowFlags);
if (!m_Window) { if (!m_Window) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_CreateWindow() failed: %s", "SDL_CreateWindow() failed: %s",
@ -1431,22 +1411,8 @@ void Session::execInternal()
} }
#endif #endif
// For non-full screen windows, call getWindowDimensions() // Enter full-screen if requested
// again after creating a window to allow it to account if (m_IsFullScreen) {
// for window chrome size.
if (!m_IsFullScreen) {
getWindowDimensions(x, y, width, height);
// We must set the size before the position because centering
// won't work unless it knows the final size of the window.
SDL_SetWindowSize(m_Window, width, height);
SDL_SetWindowPosition(m_Window, x, y);
// Passing SDL_WINDOW_RESIZABLE to set this during window
// creation causes our window to be full screen for some reason
SDL_SetWindowResizable(m_Window, SDL_TRUE);
}
else {
// Update the window display mode based on our current monitor // Update the window display mode based on our current monitor
updateOptimalWindowDisplayMode(); updateOptimalWindowDisplayMode();
@ -1616,20 +1582,6 @@ void Session::execInternal()
} }
#endif #endif
// Complete any repositioning that was deferred until
// the resize from full-screen to windowed had completed.
// If we try to do this immediately, the resize won't take effect
// properly on Windows.
if (m_PendingWindowedTransition) {
m_PendingWindowedTransition = false;
int x, y, width, height;
getWindowDimensions(x, y, width, height);
SDL_SetWindowSize(m_Window, width, height);
SDL_SetWindowPosition(m_Window, x, y);
}
if (m_FlushingWindowEventsRef > 0) { if (m_FlushingWindowEventsRef > 0) {
// Ignore window events for renderer reset if flushing // Ignore window events for renderer reset if flushing
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,

View file

@ -163,7 +163,6 @@ private:
int m_DisplayOriginX; int m_DisplayOriginX;
int m_DisplayOriginY; int m_DisplayOriginY;
bool m_ThreadedExec; bool m_ThreadedExec;
bool m_PendingWindowedTransition;
bool m_UnexpectedTermination; bool m_UnexpectedTermination;
SdlInputHandler* m_InputHandler; SdlInputHandler* m_InputHandler;
int m_MouseEmulationRefCount; int m_MouseEmulationRefCount;

View file

@ -643,6 +643,9 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
// in a separate thread with this device. // in a separate thread with this device.
int deviceFlags = D3DCREATE_MULTITHREADED; int deviceFlags = D3DCREATE_MULTITHREADED;
// We don't need D3D to mess with our window at all. SDL does that.
deviceFlags |= D3DCREATE_NOWINDOWCHANGES;
if (deviceCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { if (deviceCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
deviceFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; deviceFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
} }