SDL2:如何正确切换全屏?

SDL2: How to properly toggle fullscreen?

我在使用我的程序停用全屏模式时遇到问题。进入全屏正确,但尝试返回窗口模式不起作用,唯一的影响是光标再次显示。

这是为我重现问题的MCVE/SSCCE:

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_SetWindowFullscreenreturns0,好像操作成功了。我究竟做错了什么? (我在 OS X 10.10.3 上使用 SDL 2.0.3。)

这看起来像是一个已知问题。希望 SDL 开发人员会修复它。我发现了以下错误报告。

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

即使现在 SDL_SetWindowFullscreen 似乎仍然存在问题。我尝试使用此功能向我的视频播放器添加全屏功能。但是,在全屏和 windowed 模式之间转换时它会随机崩溃。

我找到了一个临时解决方法,目前看来可以正常工作。

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;
    }
}

基本上是 "fake" 全屏。它调整 window 的大小,使客户区覆盖整个屏幕,最小化、最大化、退出按钮不在屏幕上。

希望对您有所帮助。

我知道这可能是 5 年后的事了,但我遇到了同样的问题,我发现你的代码比需要的更复杂。所以我只是想补充一下然而来到这里:

//somewhere outside the loop
bool isFullScreen = true;

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

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

只需将 isFullscreen 置于 currenState,您就可以很好地切换按键事件。

这对我来说在 SDL2 中工作正常(按 f 切换它 on/off 和 q 退出):

  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);
  }