Browse Source

Fix inconsistent window mode transitions.

- Fix unwanted window reposition to (0, 0) during
windowed-to-fullscreen-to-windowed mode transition.

- Fix unwanted display resolution change during
fullscreen-to-windowed mode transition on DX9 and DX11.
Eugene Kozlov 5 years ago
parent
commit
d1ad98d067

+ 21 - 2
Source/Urho3D/Graphics/Direct3D11/D3D11Graphics.cpp

@@ -1978,6 +1978,10 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen,
 {
 {
     if (!externalWindow_)
     if (!externalWindow_)
     {
     {
+        // Keep current window position because it may change in intermediate callbacks
+        const IntVector2 oldPosition = position_;
+        bool reposition = false;
+        bool resizePostponed = false;
         if (!newWidth || !newHeight)
         if (!newWidth || !newHeight)
         {
         {
             SDL_MaximizeWindow(window_);
             SDL_MaximizeWindow(window_);
@@ -1988,13 +1992,18 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen,
             SDL_Rect display_rect;
             SDL_Rect display_rect;
             SDL_GetDisplayBounds(monitor, &display_rect);
             SDL_GetDisplayBounds(monitor, &display_rect);
 
 
-            if (newFullscreen || (newBorderless && newWidth >= display_rect.w && newHeight >= display_rect.h))
+            reposition = newFullscreen || (newBorderless && newWidth >= display_rect.w && newHeight >= display_rect.h);
+            if (reposition)
             {
             {
                 // Reposition the window on the specified monitor if it's supposed to cover the entire monitor
                 // Reposition the window on the specified monitor if it's supposed to cover the entire monitor
                 SDL_SetWindowPosition(window_, display_rect.x, display_rect.y);
                 SDL_SetWindowPosition(window_, display_rect.x, display_rect.y);
             }
             }
 
 
-            SDL_SetWindowSize(window_, newWidth, newHeight);
+            // Postpone window resize if exiting fullscreen to avoid redundant resolution change
+            if (!newFullscreen && screenParams_.fullscreen_)
+                resizePostponed = true;
+            else
+                SDL_SetWindowSize(window_, newWidth, newHeight);
         }
         }
 
 
         // Turn off window fullscreen mode so it gets repositioned to the correct monitor
         // Turn off window fullscreen mode so it gets repositioned to the correct monitor
@@ -2004,6 +2013,16 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen,
         SDL_SetWindowFullscreen(window_, newFullscreen ? SDL_WINDOW_FULLSCREEN : 0);
         SDL_SetWindowFullscreen(window_, newFullscreen ? SDL_WINDOW_FULLSCREEN : 0);
         SDL_SetWindowBordered(window_, newBorderless ? SDL_FALSE : SDL_TRUE);
         SDL_SetWindowBordered(window_, newBorderless ? SDL_FALSE : SDL_TRUE);
         if (!newFullscreen) SDL_ShowWindow(window_);
         if (!newFullscreen) SDL_ShowWindow(window_);
+
+        // Resize now if was postponed
+        if (resizePostponed)
+            SDL_SetWindowSize(window_, newWidth, newHeight);
+
+        // Ensure that window keeps its position
+        if (!reposition)
+            SDL_SetWindowPosition(window_, oldPosition.x_, oldPosition.y_);
+        else
+            position_ = oldPosition;
     }
     }
     else
     else
     {
     {

+ 21 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -2256,6 +2256,10 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen,
 {
 {
     if (!externalWindow_)
     if (!externalWindow_)
     {
     {
+        // Keep current window position because it may change in intermediate callbacks
+        const IntVector2 oldPosition = position_;
+        bool reposition = false;
+        bool resizePostponed = false;
         if (!newWidth || !newHeight)
         if (!newWidth || !newHeight)
         {
         {
             SDL_MaximizeWindow(window_);
             SDL_MaximizeWindow(window_);
@@ -2265,13 +2269,18 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen,
             SDL_Rect display_rect;
             SDL_Rect display_rect;
             SDL_GetDisplayBounds(monitor, &display_rect);
             SDL_GetDisplayBounds(monitor, &display_rect);
 
 
-            if (newFullscreen || (newBorderless && newWidth >= display_rect.w && newHeight >= display_rect.h))
+            reposition = newFullscreen || (newBorderless && newWidth >= display_rect.w && newHeight >= display_rect.h);
+            if (reposition)
             {
             {
                 // Reposition the window on the specified monitor if it's supposed to cover the entire monitor
                 // Reposition the window on the specified monitor if it's supposed to cover the entire monitor
                 SDL_SetWindowPosition(window_, display_rect.x, display_rect.y);
                 SDL_SetWindowPosition(window_, display_rect.x, display_rect.y);
             }
             }
 
 
-            SDL_SetWindowSize(window_, newWidth, newHeight);
+            // Postpone window resize if exiting fullscreen to avoid redundant resolution change
+            if (!newFullscreen && screenParams_.fullscreen_)
+                resizePostponed = true;
+            else
+                SDL_SetWindowSize(window_, newWidth, newHeight);
         }
         }
 
 
         // Hack fix: on SDL 2.0.4 a fullscreen->windowed transition results in a maximized window when the D3D device is reset, so hide before
         // Hack fix: on SDL 2.0.4 a fullscreen->windowed transition results in a maximized window when the D3D device is reset, so hide before
@@ -2279,6 +2288,16 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen,
         SDL_SetWindowFullscreen(window_, newFullscreen ? SDL_WINDOW_FULLSCREEN : 0);
         SDL_SetWindowFullscreen(window_, newFullscreen ? SDL_WINDOW_FULLSCREEN : 0);
         SDL_SetWindowBordered(window_, newBorderless ? SDL_FALSE : SDL_TRUE);
         SDL_SetWindowBordered(window_, newBorderless ? SDL_FALSE : SDL_TRUE);
         if (!newFullscreen) SDL_ShowWindow(window_);
         if (!newFullscreen) SDL_ShowWindow(window_);
+
+        // Resize now if was postponed
+        if (resizePostponed)
+            SDL_SetWindowSize(window_, newWidth, newHeight);
+
+        // Ensure that window keeps its position
+        if (!reposition)
+            SDL_SetWindowPosition(window_, oldPosition.x_, oldPosition.y_);
+        else
+            position_ = oldPosition;
     }
     }
     else
     else
     {
     {

+ 5 - 2
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -274,6 +274,9 @@ bool Graphics::SetScreenMode(int width, int height, const ScreenModeParams& para
         return true;
         return true;
     }
     }
 
 
+    // Track if the window was repositioned and don't update window position in this case
+    bool reposition = false;
+
     // With an external window, only the size can change after initial setup, so do not recreate context
     // With an external window, only the size can change after initial setup, so do not recreate context
     if (!externalWindow_ || !impl_->context_)
     if (!externalWindow_ || !impl_->context_)
     {
     {
@@ -325,7 +328,7 @@ bool Graphics::SetScreenMode(int width, int height, const ScreenModeParams& para
 
 
         SDL_Rect display_rect;
         SDL_Rect display_rect;
         SDL_GetDisplayBounds(newParams.monitor_, &display_rect);
         SDL_GetDisplayBounds(newParams.monitor_, &display_rect);
-        const bool reposition = newParams.fullscreen_ || (newParams.borderless_ && width >= display_rect.w && height >= display_rect.h);
+        reposition = newParams.fullscreen_ || (newParams.borderless_ && width >= display_rect.w && height >= display_rect.h);
 
 
         const int x = reposition ? display_rect.x : position_.x_;
         const int x = reposition ? display_rect.x : position_.x_;
         const int y = reposition ? display_rect.y : position_.y_;
         const int y = reposition ? display_rect.y : position_.y_;
@@ -405,7 +408,7 @@ bool Graphics::SetScreenMode(int width, int height, const ScreenModeParams& para
     screenParams_ = newParams;
     screenParams_ = newParams;
 
 
     SDL_GL_GetDrawableSize(window_, &width_, &height_);
     SDL_GL_GetDrawableSize(window_, &width_, &height_);
-    if (!screenParams_.fullscreen_)
+    if (!reposition)
         SDL_GetWindowPosition(window_, &position_.x_, &position_.y_);
         SDL_GetWindowPosition(window_, &position_.x_, &position_.y_);
 
 
     int logicalWidth, logicalHeight;
     int logicalWidth, logicalHeight;