Correct way to swap from window to fullscreen

In my game, I’m supporting swapping between windowed, fullscreen, and “fullscreen window”. In code, this looks something like this:

switch( desiredWindowType )
{
    case WindowType_Window:
        SDL_SetWindowFullscreen(m_sdlWindow, 0);
        SDL_SetWindowSize(m_sdlWindow, m_windowWidth, m_windowHeight);
        break;
    case WindowType_Fullscreen:
        SDL_SetWindowFullscreen(m_sdlWindow, SDL_WINDOW_FULLSCREEN);
        SDL_SetWindowDisplayMode(m_sdlWindow, &m_fullscreenDisplayMode);
        break;
    case WindowType_FullscreenWindow:
        SDL_SetWindowFullscreen(m_sdlWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
        {
            SDL_DisplayMode desktopMode;
            if ( SDL_GetDesktopDisplayMode(0, &desktopMode) == 0 )
                SDL_SetWindowDisplayMode(m_sdlWindow, &desktopMode);
        }
        break;
}

The gotcha I’ve been running into is that sometimes I’ll get an apparently-spurious SDL_WINDOWEVENT_RESIZED event after the mode change, reporting the resolution we had before the window resolution change. Which my code then dutifully obeys, and switches the resolution back.

Does the code above look correct to folks? (apart from the missing error testing, which I’ve removed here for conciseness)

The documentation doesn’t really specify whether I should be changing resolution/size before or after changing the fullscreen state of a window, so maybe I should be doing things in the opposite order; set size/display mode first, then fullscreen status afterward?

EDIT: For clarity; I’m currently testing under SDL 2.0.8, on Ubuntu, but I have seen the same or similar behaviour under SDL versions 2.0.4, 2.0.5, and 2.0.7, on both Windows and Linux. (I don’t have enough OSX testers to really definitively state whether it’s happening there, too. I’m assuming it’s a mistake on my side, rather than something in SDL)

Following up on this…

First issue: I was calling into this code from my handler for the SDL_WINDOWEVENT_RESIZED events. And this code seems to generate two of those (presumably one for changing to fullscreen, and one for changing the displaymode).

First resized event was referring to the old resolution, second to the new one. But if I responded to the first by changing the resolution back to the old resolution, it didn’t seem to bother to deliver the second one. (Perhaps the resizing events are flushed when you change the window size? Not sure.)

I’m still having some troubles, regardless, mostly in changing between different fullscreen resolutions.

One really easy case to reproduce in Linux is starting in one fullscreen resolution and switching to a larger one; it seems like the ‘window’ isn’t being resized to match the new fullscreen resolution; you can see through the right/bottom sides of the screen to the background, where game image should be visible. Seems as if the window dimensions are set and static from when the window is created. That might just be a Linux thing, though; haven’t yet verified that on other platforms.

Not sure if this will help with the issues of switching between fullscreen modes you’re seeing, but a couple ideas:

I think these two lines are ordered backwards - this will first enter closest fullscreen mode to the current width/height of the window, and then do another mode change to m_fullscreenDisplayMode.

Pretty sure the part in braces is redundant; SDL_SetWindowFullscreen(m_sdlWindow, SDL_WINDOW_FULLSCREEN_DESKTOP); should be all you need.

Thanks for that! That would totally explain why I was getting the two resize events.

I’ve been toying with all this some more, and think I’ve worked out all the issues other than the “window doesn’t seem to resize in fullscreen” one, which seems to only happen on Linux, so I’m suspecting is a Linux-only SDL bug, which I’ll look into sometime soon. (I’ve captured using RenderDoc and validated that I’m drawing into the correct VBOs and that they’re of the correct dimensions; some of the rendered image just isn’t making it to the screen). I’ll look into that perhaps tomorrow and update with what I find.

It’s interesting that on Windows, I get a very different set of resolutions than on Linux, on the same hardware. And some of the shared resolutions behave differently.

For example, my 1920x1200 screen (16:10 aspect ratio) supports a 1600x1200 resolution (4:3 aspect ratio). If I set it that resolution for the game on Linux SDL, it works as you’d expect, with the image pillar-boxed into the middle of the screen. If I set it on Windows, it works, but the image is displayed over on the far left edge of the screen, with a big black area on the right. I’m assuming that all that sort of thing is controlled by the video driver, and isn’t something I have control over myself.