Window doesn't show with Wayland driver

I’ve just started trying to write a new game with SDL 2.0.16 on Arch Linux. My desktop is Wayland so I tried running an early test with SDL_VIDEODRIVER=wayland. It doesn’t report any errors, but the window never appears. I think I may be doing something wrong, because I arbitrarily picked a game from Arch that depends on sdl2 - rocksndiamonds - and that does run correctly with SDL_VIDEODRIVER=wayland (after I installed libdecor to get window decorations).

I distilled my code down to a simple example that demonstrates the problem, see below. Can anyone see what’s wrong? When I run it with the driver variable set to wayland it prints events as if the window is opening:

exposed, size changed, resized, size changed, shown;

but there is no window. If I run it without the variable, the window does get shown, and it receives a different series of events:

shown, moved, exposed, focus gained, take focus.

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

int main(int argc, char **argv)
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Window *win = SDL_CreateWindow("Test",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 
        800, 600,
        SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_SHOWN);
    SDL_Event event;
    SDL_bool quit = SDL_FALSE;
    while (!quit)
    {
        if (!SDL_WaitEventTimeout(&event, 16))
        {
            SDL_UpdateWindowSurface(win);
            continue;
        }
        switch (event.type)
        {
            case SDL_QUIT:
                printf("Quit event\n");
                quit = SDL_TRUE;
                break;
            case SDL_WINDOWEVENT:
                switch (event.window.event)
                {
                    case SDL_WINDOWEVENT_CLOSE:
                        printf("Window close event\n");
                        quit = SDL_TRUE;
                        break;
                    case SDL_WINDOWEVENT_EXPOSED:
                        printf("Window exposed event\n");
                        SDL_UpdateWindowSurface(win);
                        break;
                    case SDL_WINDOWEVENT_RESIZED:
                        printf("Window resized to %d x %d\n",
                            event.window.data1,
                            event.window.data2);
                        case SDL_WINDOWEVENT_SIZE_CHANGED:
                            printf("Window size changed\n");
                            break;
                        break;
                    case SDL_WINDOWEVENT_SHOWN:
                        printf("Window shown event\n");
                        SDL_UpdateWindowSurface(win);
                        break;
                    default:
                       printf("Window event type %x\n",
                            (int) event.window.event);
                }
                if (!quit)
                {
                    int x, y, w, h;
                    SDL_GetWindowPosition(win, &x, &y);
                    SDL_GetWindowSize(win, &w, &h);
                    printf("Window position (%d, %d); size %d x %d\n",
                        x, y, w, h);
                }
                break;
            default:
                printf("Event type %x\n", event.type);
        }
    }
    return 0;
}

You need to actually render something for the window to appear with the Wayland backend.

Something like:

    SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, 0);
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);

EDIT: I see you’re trying to use SDL_UpdateWindowSurface(). You have to call SDL_GetWindowSurface(), otherwise SDL_UpdateWindowSurface() will fail because a window surface was never allocated.

Thanks. Good to know it’s something trivial.

I’m actually intending to use a renderer. Does that mean I don’t need to create a surface, and SDL_RenderPresent is equivalent to SDL_UpdateWindowSurface?

Yes, if you’re using the renderer you don’t need (or want) a surface.