Skip to content

SDL3: OpenGL Borderless Window Becomes Exclusive Fullscreen on SDL_GL_SwapWindow (Windows 11) #12791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vittorioromeo opened this issue Apr 10, 2025 · 4 comments

Comments

@vittorioromeo
Copy link
Contributor

vittorioromeo commented Apr 10, 2025

Creating a borderless OpenGL window (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS) at the native display resolution on Windows 11 results in the window unexpectedly switching to an exclusive fullscreen mode upon the first call to SDL_GL_SwapWindow. This behavior is not desired; the expectation is a standard borderless fullscreen windowed mode.

  • OS: Windows 11 24H2
  • GPU: NVIDIA RTX 4090
  • Graphics Driver Version: 32.0.15.7247

MCVE:

#include <SDL3/SDL.h>

int main()
{
    SDL_InitSubSystem(SDL_INIT_VIDEO);

    SDL_WindowFlags flags = {};
    flags |= SDL_WINDOW_OPENGL;
    flags |= SDL_WINDOW_RESIZABLE;
    flags |= SDL_WINDOW_BORDERLESS;

    SDL_Window *w = SDL_CreateWindow("", 3440, 1440, flags); // use fullscreen resolution here
    SDL_GLContext wCtx = SDL_GL_CreateContext(w);

    while (true) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) { }

        SDL_GL_SwapWindow(w); // commenting this line solves the issue
    }
}

Expected Behavior:

The application should display a borderless window that perfectly fills the native screen resolution (e.g., 3440x1440). This window should behave like standard borderless fullscreen windowed mode:

  • It covers the entire screen, including the taskbar area.
  • Alt-tabbing works smoothly without display mode changes.
  • System overlays (like volume controls) appear correctly.
  • No screen flickering associated with a display mode switch occurs.

Actual Behavior:

Upon the first call to SDL_GL_SwapWindow, the window enters an exclusive fullscreen-like mode:

  • There is a brief screen flicker or blanking, suggesting a display mode change or swapchain takeover.
  • Alt-tabbing becomes sluggish.
  • Overlays do not render over the application.

Additional Context & Workarounds Tried:

  • The trigger seems to be specifically the SDL_GL_SwapWindow call. Before this call, the window exists but doesn't exhibit exclusive behavior.
  • Creating the window with slightly smaller dimensions (e.g., mode.w, mode.h - 1) avoids the exclusive fullscreen switch, but results in the Windows taskbar being rendered on top of the application window, which is also undesirable.
  • Creating a standard windowed window first and then calling SDL_SetWindowFullscreen(window, true) also results in the same undesirable exclusive fullscreen behavior.
  • Disabling "Fullscreen Optimizations" in the Windows compatibility settings for the executable does not prevent this behavior.
  • Setting different VSync modes via SDL_GL_SetSwapInterval(0/1/-1) does not prevent this behavior.
@slouken
Copy link
Collaborator

slouken commented Apr 10, 2025

This is intentional OpenGL driver behavior to increase performance and not something SDL can affect.

@slouken slouken closed this as not planned Won't fix, can't repro, duplicate, stale Apr 10, 2025
@vittorioromeo
Copy link
Contributor Author

vittorioromeo commented Apr 10, 2025

This is intentional OpenGL driver behavior to increase performance and not something SDL can affect.

@slouken: I honestly think that closing this issue without any chance of discussion is very premature and not in the best interests of your users. Creating a fullscreen borderless window is an extremely common requirement for modern games and applications.

Furthermore, this is definitely an SDL quirk, as I was able to achieve my goals easily with SFML, on the exact same machine and environment (in fact, I just reproduced it).

@vittorioromeo
Copy link
Contributor Author

@slouken: This is the relevant code in my SFML fork that seems to make borderless fullscreen work flawlessly:

SetWindowLongPtr(m_handle, GWL_STYLE, WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
SetWindowLongPtr(m_handle, GWL_EXSTYLE, WS_EX_APPWINDOW);

SetWindowPos(m_handle, HWND_TOP, left, top, width, height, SWP_FRAMECHANGED | SWP_NOOWNERZORDER | SWP_SHOWWINDOW);

Could this issue please be reopened?

@vittorioromeo
Copy link
Contributor Author

Here's a MCVE that fixes the issue on SDL3 as well:

#include <SDL3/SDL.h>
#include <windows.h>

int main()
{
    SDL_InitSubSystem(SDL_INIT_VIDEO);

    SDL_WindowFlags flags = {};
    flags |= SDL_WINDOW_OPENGL;
    flags |= SDL_WINDOW_RESIZABLE;
    flags |= SDL_WINDOW_BORDERLESS;

    SDL_Window *w = SDL_CreateWindow("title", 3440, 1440, flags);

    SDL_PropertiesID props = SDL_GetWindowProperties(w);

    void *hwnd = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
    SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
    SetWindowLongPtr(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
    SetWindowPos(hwnd, HWND_TOP, 0, 0, 3440, 1440, SWP_FRAMECHANGED | SWP_NOOWNERZORDER | SWP_SHOWWINDOW);

    SDL_GLContext wCtx = SDL_GL_CreateContext(w);

    while (true) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
        }

        SDL_GL_SwapWindow(w);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants