From 38396b26919d56dab02e3e06e7791ef9b748bacf Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 24 Apr 2022 16:22:17 -0500 Subject: [PATCH] Rework window management to fix issues restoring window state between windowed and full-screen --- app/streaming/session.cpp | 88 +++++-------------- app/streaming/session.h | 1 - .../video/ffmpeg-renderers/dxva2.cpp | 3 + 3 files changed, 23 insertions(+), 69 deletions(-) diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 2704ccc1..ac6cfbfc 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -449,7 +449,6 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere m_AudioMuted(false), m_DisplayOriginX(0), m_DisplayOriginY(0), - m_PendingWindowedTransition(false), m_UnexpectedTermination(true), // Failure prior to streaming is unexpected m_InputHandler(nullptr), m_MouseEmulationRefCount(0), @@ -897,12 +896,10 @@ void Session::getWindowDimensions(int& x, int& y, int& width, int& height) { int displayIndex = 0; - bool fullScreen; if (m_Window != nullptr) { displayIndex = SDL_GetWindowDisplayIndex(m_Window); SDL_assert(displayIndex >= 0); - fullScreen = (SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN); } // Create our window on the same display that Qt's UI // was being displayed on. @@ -929,38 +926,19 @@ void Session::getWindowDimensions(int& x, int& y, i, SDL_GetError()); } } - - fullScreen = m_IsFullScreen; } SDL_Rect usableBounds; - if (fullScreen && SDL_GetDisplayBounds(displayIndex, &usableBounds) == 0) { - width = usableBounds.w; - height = usableBounds.h; - } - else if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) { - width = usableBounds.w; - height = usableBounds.h; + if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) { + // Don't use more than 80% of the display to leave room for system UI + width = (int)SDL_roundf(usableBounds.w * 0.80f); + height = (int)SDL_roundf(usableBounds.h * 0.80f); - if (m_Window != nullptr) { - int top, left, bottom, right; - - if (SDL_GetWindowBordersSize(m_Window, &top, &left, &bottom, &right) == 0) { - width -= left + right; - 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; - } + // 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 { @@ -1070,7 +1048,6 @@ void Session::toggleFullscreen() SDL_SetWindowGrab(m_Window, SDL_TRUE); } - SDL_SetWindowResizable(m_Window, SDL_FALSE); SDL_SetWindowFullscreen(m_Window, m_FullScreenFlag); } else { @@ -1078,10 +1055,6 @@ void Session::toggleFullscreen() SDL_SetWindowGrab(m_Window, SDL_FALSE); 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 @@ -1378,12 +1351,19 @@ void Session::execInternal() SDL_GL_SetAttribute(SDL_GL_GREEN_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", x, y, width, height, - SDL_WINDOW_ALLOW_HIGHDPI | StreamUtils::getPlatformWindowFlags()); + windowFlags | StreamUtils::getPlatformWindowFlags()); if (!m_Window) { SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateWindow() failed with platform flags: %s", @@ -1394,7 +1374,7 @@ void Session::execInternal() y, width, height, - SDL_WINDOW_ALLOW_HIGHDPI); + windowFlags); if (!m_Window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateWindow() failed: %s", @@ -1431,22 +1411,8 @@ void Session::execInternal() } #endif - // For non-full screen windows, call getWindowDimensions() - // again after creating a window to allow it to account - // 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 { + // Enter full-screen if requested + if (m_IsFullScreen) { // Update the window display mode based on our current monitor updateOptimalWindowDisplayMode(); @@ -1616,20 +1582,6 @@ void Session::execInternal() } #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) { // Ignore window events for renderer reset if flushing SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, diff --git a/app/streaming/session.h b/app/streaming/session.h index bf5bbfc9..7ab26686 100644 --- a/app/streaming/session.h +++ b/app/streaming/session.h @@ -163,7 +163,6 @@ private: int m_DisplayOriginX; int m_DisplayOriginY; bool m_ThreadedExec; - bool m_PendingWindowedTransition; bool m_UnexpectedTermination; SdlInputHandler* m_InputHandler; int m_MouseEmulationRefCount; diff --git a/app/streaming/video/ffmpeg-renderers/dxva2.cpp b/app/streaming/video/ffmpeg-renderers/dxva2.cpp index 828e1fc8..b2d65235 100644 --- a/app/streaming/video/ffmpeg-renderers/dxva2.cpp +++ b/app/streaming/video/ffmpeg-renderers/dxva2.cpp @@ -643,6 +643,9 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync) // in a separate thread with this device. 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) { deviceFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; }