When i can access to SDL_Rendrerer after maximizing window?

I try to redraw window only when is need, but when window is resize in a hop (for example maximize), SDL_Renderer is not usable in new size some time after action.

Here is my simple example code:

#include <SDL2/SDL.h>

bool redraw = true;

void draw(SDL_Renderer* renderer, SDL_Rect& rect)
{
    SDL_SetRenderDrawColor(renderer, 0, 0, 50, 0xFF);
    SDL_RenderClear(renderer);

    SDL_SetRenderDrawColor(renderer, 90, 90, 90, 0xFF);
    SDL_RenderDrawLine(renderer, 0, 0, rect.w, rect.h);

    SDL_RenderPresent(renderer);
    redraw = false;
}

SDL_Rect resize(const SDL_Event& event)
{
    int win_w = (int) event.window.data1;
    int win_h = (int) event.window.data2;

    SDL_Rect rect = {0, 0, win_w, win_h};
    redraw = true;
    return rect;
}

int main(int argc, char** argv)
{
    SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindow("Maximize test",
                              SDL_WINDOWPOS_CENTERED,
                              SDL_WINDOWPOS_CENTERED,
                              800, 450, 0);
    SDL_SetWindowResizable(window, SDL_TRUE);

    SDL_Renderer* renderer = SDL_CreateRenderer(
            window, -1,
            SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    bool running = true;
    SDL_Event event;
    SDL_Rect rect = {0, 0, 800, 450};

    while (running) {
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    running = false;
                    break;
                case SDL_WINDOWEVENT:
                    switch (event.window.event) {
                        case SDL_WINDOWEVENT_RESIZED:
                            rect = resize(event);
                            break;
                    }
                    break;
            }

            if (redraw) {
                draw(renderer, rect);
            }
        }
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);

    return 0;
}

At first, I try to get new renderer size SDL_GetRendererOutputSize in same result like getting size from event.

When I try to resize window with typical mouse motion actions, it works fine. But maximize or window manager resizing to one screen side does not work.

I try to use different event like SDL_WINDOWEVENT_SIZE_CHANGED, but with same result.

And yes, normally, I checks all SDL calls, with SDL_RenderDrawLine but without any errors.

Are you not getting the size changed / resized event at all? Or is it not happening until the resize is finished?

What happens if you create the window with the resizable flag set, instead of setting it after the window is created?

I’m not sure about your first questions, here is what happen to me:

  • windows was created, i see the line from one corner to another
  • then I click on maximize icon in window manager
  • SDL_WINDOWEVENT_RESIZED happened, then resize function was called
  • because redraw variable is set draw function was called
  • renderer was cleared right - i see maximized window with dark blue background
  • line has right way, but it was rendered only in old original area, not in all window

When i set SDL_WINDOW_RESIZABLE flag, it behaves the same way.

When i create my own event which set redraw flag, and this event set that flag, it works. It looks like i can’t use full renderer until another event happened.

I think it’s because you’re only drawing one frame. Typically, applications will be constantly drawing frames.

Using your code, but moving the draw() call out of the event polling loop and into the main loop and then getting rid of the redraw check, it works fine.

What’s weird is that the actual, correct new window size is sent in the event, but it’s like it takes SDL a frame to update the clip rect or something. This is probably a bug.

edit: if for some reason you really really need to only redraw when absolutely necessary (not really when using modern GPUs to draw 2D stuff, but :man_shrugging:) then you can just add a second draw() call after the first one. For now.