libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
10.14k stars 1.85k forks source link

[SDL2] [Wayland] Some programs fail to go fullscreen after starting in windowed mode. #11289

Closed vanfanel closed 1 month ago

vanfanel commented 1 month ago

Hi there,

In some WLRoots-based Wayland compositors like Labwc (https://github.com/labwc/labwc), programs that create a non-fullscreen window and then call SDL_SetWindowFullscreen() fail to go fullscreen.

According to the WLRoots/Labwc people, geometry of wl_surface committed by the client (libSDL2) is windowed, even though the geometry of xdg_surface is fullscreen. What happens then is that the Wayland compositor is sending back the geometry of wl_surface to the client, so the client keeps drawing in the windowed geometry.

This is a very simple example by @tokyo4j that replicates the issue in Labwc:

#include <SDL2/SDL.h>
#include <assert.h>

int main(int argc, char *args[]) {
    setenv("SDL_VIDEODRIVER", "wayland", 1);
    assert(SDL_Init(SDL_INIT_VIDEO) == 0);
    SDL_Window *window =
        SDL_CreateWindow("hello_sdl2", SDL_WINDOWPOS_UNDEFINED,
                         SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
    assert(window);
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
    assert(renderer);
    SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);
    SDL_Delay(1000);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

I have seen that the Labwc devs are trying to work around this, but I think this is an SDL2 issue, for the aforementioned reasons. Comes from: https://github.com/labwc/labwc/issues/1812

@Kontrabant could you take a look at this one, please? I believe the wl_surface should be updated to be fullscreen too when SDL_SetWindowFullscreen() is called.

Kontrabant commented 1 month ago

What version of SDL2 is being used here? The current release doesn't call the xdg_surface_set_window_geometry function at all if viewports are supported (or libdecor is in use, but that's libdecor calling it, not SDL).

Kontrabant commented 1 month ago

The log in that thread looks like a buffer with the old size is being committed after the resize, probably from an old frame in flight, which has been a long-standing problem. The call to set the geometry was an early hack to work around this, but current versions of SDL 2 and 3 avoid this completely by unconditionally creating a viewport for the window, so the buffer size is decoupled from the window size.

e: Ah, the SDL2 commit for this change was never cherry-picked to stable.

Kontrabant commented 1 month ago

The fix has been cherry-picked the fix to stable, since it fixes an actual window behavior bug when running via labwc. That should take care of it.

vanfanel commented 3 weeks ago

@Kontrabant I was finally able to test that this is indeed not a bug anymore, thanks for all the work you do on SDL2 Wayland support!

Kontrabant commented 3 weeks ago

Welcome!