libsdl-org / SDL

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

SDL_CreateWindow() silently fails with Wayland/Phosh/Phoc on ARM64/PinePhone with SDL2 sdl2-2.0.16-r4 #5596

Closed ell1e closed 8 months ago

ell1e commented 2 years ago

Running the following mini program with SDL_VIDEODRIVER=wayland ./sdltest.bin will not create a visible window for me even though SDL_CreateWindow reports success:

// sdltest.c:
#include <stdio.h>
#include <SDL2/SDL.h>

int main(int argc, const char **argv) {
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        printf("sdl init failed\n");
        return 1;
    }
    SDL_Window *window = SDL_CreateWindow(
        "Cursor Down Test", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED, 400, 400,
        SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
    if (!window) {
        printf("sdl createwindow failed\n");
        return 1;
    }
    SDL_Surface *winsrf = SDL_GetWindowSurface(window);
    if (!winsrf) {
        printf("getting window surface failed\n");
        return 1;
    }
    printf("window created, starting event loop\n");
    SDL_Event event;
    while (1) {
        if (!SDL_PollEvent(&event)) {
            SDL_UpdateWindowSurface(window);
            continue;
        }
        int quit = 0;
        switch(event.type) {
        case SDL_WINDOWEVENT: {
            if (event.window.event == SDL_WINDOWEVENT_CLOSE)
                quit = 1;
            break;
        }
        case SDL_QUIT: {
            quit = 1;
            break;
        }
        case SDL_KEYDOWN: {
            if (event.key.keysym.sym == SDLK_DOWN)
                printf("cursor down pressed\n");
            else
                printf("other key pressed\n");
            break;
        }
        }
        if (quit) break;
        SDL_UpdateWindowSurface(window);
    }
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

Build it like this: gcc ./sdltest.c -o ./sdltest.bin -lSDL2. If I run it with the X11 backend, it works. The "window created, starting event loop\n" is printed in any case, just with Wayland there is no actual window of any kind to interact with. I wanted to write a reproducer for actually a different Wayland backend bug, so this sadly is currently stopping me from doing that :open_mouth: my apologies if the code is in some way obviously wrong, but I wouldn't know how so.

SDL2 Version: SDL2 sdl2-2.0.16-r4 (as packaged by Alpine Linux)

Wayland compositor: Phoc 0.10.0, Phosh 0.15.0

Hardware: PinePhone 3GB RAM variant/ARM64/Allwinner

Linux distribution: postmarketOS (based on Alpine Linux)

Edit: oops, window event close handling had a bug. however, seems like that was irrelevant in practice

slouken commented 2 years ago

We've made lots of changes to Wayland support in the last few releases. Can you please try the 2.0.22 release and see if that works any better?

slouken commented 8 months ago

SDL 2.0 is now in maintenance mode, and all inactive issues are being closed. If this issue is impacting you, please feel free to reopen it with additional information.

ell1e commented 4 months ago

For what it's worth, this is still broken wit....

Not broken, see see update.

ell1e commented 4 months ago

Here is a minimal code example to reproduce this with KDE Plasma: (Update: this code lacks SDL_GetWindowSurface() that's why it doesn't work, so the mistake was on my end)

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

int main(int argc, const char **argv) {
    SDL_Window *window = NULL;
    if (SDL_Init(SDL_INIT_VIDEO) < 0) return 1;
    window = SDL_CreateWindow("Test",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        200, 200, SDL_WINDOW_SHOWN);
    if (window == NULL) return 1;

    int hadsurfaceupdate = 0;
    printf("Window should now be visible.\n");
    while (1) {
        SDL_Event e;
        while (SDL_PollEvent(&e) != 0) {
            if (e.type == SDL_MOUSEMOTION) {
                printf("Mouse at: %d, %d\n",
                    (int)e.motion.x, (int)e.motion.y);
            } else if (e.type == SDL_WINDOWEVENT) {
                if (e.window.event == SDL_WINDOWEVENT_ENTER) {
                    printf("Mouse enters window.\n");
                } else if (e.window.event == SDL_WINDOWEVENT_LEAVE) {
                    printf("Mouse leaves window.\n");
                }
            }
        }

        SDL_UpdateWindowSurface(window);
        if (!hadsurfaceupdate) {
            printf("First surface update done.\n");
            hadsurfaceupdate = 1;
        }
    }
    return 0;
}

Edit: updated with info that this isn't a bug

ell1e commented 4 months ago

My apologies, as was helpfully pointed out I needed to use SDL_GetWindowSurface in above newer example (which as you can see I didn't) and that's why the window never showed up. If you either use SDL_GetWindowSurface or SDL_RenderPresent at any point then it works with the latest SDL2.

Therefore it works and I was just me being confused/silly. I hope whoever ends up here with the same problem via search engines finds this helpful in the future!