'SDL2: How to properly toggle fullscreen?

I have problems deactivating fullscreen mode with my program. Entering fullscreen happens correctly, but trying to go back to windowed mode doesn't work, the only effect is that the cursor gets shown again.

Here's the MCVE/SSCCE that reproduces the issue for me:

void ToggleFullscreen(SDL_Window* Window) {
    Uint32 FullscreenFlag = SDL_WINDOW_FULLSCREEN;
    bool IsFullscreen = SDL_GetWindowFlags(Window) & FullscreenFlag;
    SDL_SetWindowFullscreen(Window, IsFullscreen ? 0 : FullscreenFlag);
    SDL_ShowCursor(IsFullscreen);
}

int main() {
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* Window = SDL_CreateWindow("",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);

    bool Exit = false;
    for (SDL_Event Event; !Exit;) {
        SDL_WaitEvent(&Event);
        if (Event.type == SDL_KEYDOWN) {
            switch (Event.key.keysym.sym) {
                case SDLK_f: ToggleFullscreen(Window); break;
                case SDLK_q: Exit = true; break;
            }
        }
    }
    SDL_DestroyWindow(Window);
    SDL_Quit();
}

SDL_SetWindowFullscreen returns 0, as if the operation was successful. What am I doing wrong? (I'm using SDL 2.0.3 on OS X 10.10.3.)



Solution 1:[1]

It looks like a known issue. Hopefully the SDL developers will fix it. I found the following bug report.

https://github.com/libsdl-org/SDL/issues/1428

Solution 2:[2]

Even now there still appears to be a problem with SDL_SetWindowFullscreen. I tried to add fullscreen functionality to my video player with this function. However, it would randomly crash when transitioning between fullscreen and windowed mode.

I found a temporary work around that appears to be working correctly for now.

SDL_DisplayMode dm;

if (SDL_GetDesktopDisplayMode(0, &dm))
{
    printf("Error getting desktop display mode\n");
    return -1;
}

if (SDL_PollEvent(&event))
{
    switch (event.type)
    {
        case SDL_KEYUP:
            switch (event.key.keysym.sym)
            {
                case SDLK_f:
                    SDL_RestoreWindow(screen); //Incase it's maximized...
                    SDL_SetWindowSize(screen, dm.w, dm.h + 10);
                    SDL_SetWindowPosition(screen, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
            }
            break;
    }
}

It's basically "fake" fullscreen. It resizes the window so the client area covers the whole screen and the minimize, maximize, exit buttons are off screen.

Hope this helps.

Solution 3:[3]

I know this may be 5 years after date, but I was facing the same problem, and I found your code way more complex then need be. So I just wanted to add for however comes here:

//somewhere outside the loop
bool isFullScreen = true;

void toggleFullScreen(SDL_Window* window, bool currentState)
{
    isFullScreen = !currentState;

    SDL_SetWindowFullscreen(window, !currentState);
    SDL_ShowCursor(currentState);
}

just place the isFullscreen at the currenState and you have a good toggle with a keypress event.

Solution 4:[4]

This works fine for me in SDL2(pressing f toggles it on/off and q quits):

  SDL_Window* window = SDL_CreateWindow("Fullscreen demo", 0, 0, 640, 480, 0);
  SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

  SDL_Event event;
  bool fullScreen = false;
  SDL_bool running = SDL_TRUE;

  while (running) {
    while (SDL_PollEvent(&event)) {
      switch (event.type) {
      case SDL_QUIT:
        running = SDL_FALSE;
        break;
      case SDL_KEYDOWN:
        if(event.key.keysym.scancode == SDL_SCANCODE_F){
          fullScreen = !fullScreen;
          if(fullScreen){
            SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
          }
          else{
            SDL_SetWindowFullscreen(window, 0);
          }
        }
        if(event.key.keysym.scancode == SDL_SCANCODE_Q){
          running = SDL_FALSE;
        }
        break;
      default: break;
      }
    }
    
    // drawing stuff here...
    
    // swap and display buffer
    SDL_RenderPresent(renderer);
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 genpfault
Solution 2
Solution 3 Lyingdutchman
Solution 4 Walter Schreppers