How to properly resize and redraw after window resize event

I am trying to redraw on window resize event but when resizing, the window starts twitching and the inside of the window starts corrupting:

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

int main()
{
int width=600, height=480;
SDL_Window* window = SDL_CreateWindow("hello",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,width,height,SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);
SDL_Surface* surface = SDL_GetWindowSurface(window);
SDL_Surface* image = SDL_LoadBMP("bitmap3.bmp");
SDL_BlitSurface(image,NULL,surface,NULL);
SDL_UpdateWindowSurface(window);
bool quit=false;
SDL_Event e;
while(quit!=true)
{
    while(SDL_PollEvent(&e)!=0)
    {
        switch(e.type)
        {
            case SDL_QUIT:
            {
                quit=true;
                break;
            }
            case SDL_WINDOWEVENT:
            {
                if(e.window.event==SDL_WINDOWEVENT_EXPOSED)
                {
                    SDL_GetWindowSize(window,&width,&height);
                    printf("Resizing window to: %d x %d\n",width,height);
                    SDL_SetWindowSize(window,width,height);
                    SDL_FreeSurface(surface);
                    surface = SDL_GetWindowSurface(window);
                    SDL_BlitSurface(image,NULL,surface,NULL);
                    SDL_UpdateWindowSurface(window);
                }
                break;
            }
        }
    }
}
SDL_FreeSurface(surface);
SDL_DestroyWindow(window);
return EXIT_SUCCESS;
}

First of all, don’t free the window surface or try to create a new one for it. After resize, just call SDL_GetWindowSurface() again.

To respond to the window being resized, just handle the SDL_WINDOWEVENT_RESIZED event, and maybe also SDL_WINDOWEVENT_SIZE_CHANGED:

bool resized = false;

...

case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
    resized = true;
    break;

....

if(resized) {
    resized = false;
    SDL_GetWindowSize(window, &width, &height);
    surface = SDL_GetWindowSurface(window);
    SDL_BlitSurface(image, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
}

Note that it isn’t doing the actual resize handling in the event code, so that if multiple resize events happen in one frame we don’t waste time doing a bunch of extra work.

1 Like

Thanks! It works for preventing the window twitching but the image inside is still getting corrupted inside. I couldn’t find anything specifically regarding this in the wiki.

Here is the video:
https://imgur.com/a/03QgYjS

It’s because I forgot to clear the window surface :man_facepalming:, so it has the previous contents but all messed up because the size has changed.

if(resized) {
    resized = false;
    SDL_GetWindowSurface(window, &width, &height);
    surface = SDL_GetWindowSurface(window);
    uint32_t black = SDL_MapRGBA(surface->format, 0, 0, 0, 255);
    SDL_FillRect(surface, NULL, black);        // clear the screen
    SDL_BlitSurface(image, NULL, surface, NULL);
    SDL_UpdateWindowSurface(window);
}

Also, on further reflection, it might be a good idea to initially set resized to true instead, so that it will always get drawn the first frame.

1 Like

Thanks! It works like a charm! How did you figure it out?
I couldn’t find anything regarding this in the wiki.
So the correct way to handle resize would be:

  1. Get the window surface again
  2. Clear the screen or set it to the initial surface colour
  3. Redraw the contents onto the new surface
    Am I missing something else?

Also, should I also check for window events like SDL_WINDOWEVENT_EXPOSED along with SDL_WINDOWEVENT_RESIZED and SDL_WINDOWEVENT_SIZE_CHANGED when the window size is changed?

Once I saw it in action it was pretty obvious; I’ve run into issues doing my own software blitting before where I was calculating the offset of a line wrong and got similar results. And it stands to reason that if you have junk on the screen in the parts where you aren’t drawing then you need to clear those parts.

You don’t need to check for SDL_WINDOWEVENT_EXPOSED as part of the resize logic. It’s unrelated to resizing, however it wouldn’t be a bad idea to handle as many window events as appropriate for your app. If I wasn’t posting from my phone I’d dig up the link on the wiki that has all the window events.

1 Like

Thank you for helping and Thanks for the tip!

1 Like