2

I'm learning to create my first window following LazyFoo's tutorial, everything compile and run, but the surface is not updating when SDL_UpdateWindowSurface() is called, like the image below:

The surface was supposed to be white

As you can see, the last thing that appearing it's my background. I already test this program on my other laptop, and everything works fine, and i use the same system, both updated.

My code:

#include <SDL2/SDL.h>

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

int main(){
    SDL_Window* window = NULL;
    SDL_Surface* screenSurface = NULL;
    if(SDL_Init(SDL_INIT_VIDEO) < 0){
        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
    }else{
        window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
        if(window == NULL){
            printf("Window could not be created SDL_Error: %s\n", SDL_GetError() );
        }
        else{
            screenSurface = SDL_GetWindowSurface(window);
            if(screenSurface == NULL){
                printf("Surface could not be loaded SDL_Error: %s\n", SDL_GetError());
            }else{
                SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 255, 255, 255));
                SDL_UpdateWindowSurface(window);
                SDL_Delay(3000);
            }
        }
    }
}

A Strange thing: If i add SDL_Delay(1000) before SDL_UpdateWindowSurface(), after 1 second i could see the surface filled with white, but this not seems the correct solution since the program work perfectly on my laptop.

Edit 1:

Just realize one thing, my desktop enviroment where i am developing this program, is using as window manager the awesomewm. My laptop is using gnome as DE. I just installed gnome on my desktop and voilá, the program works as expected. Now I'm just curious why this happens. Screenshot of the same program running on Gnome:

Working as expected(Surface filled with white)

Edit 2:

As keltar mentioned, the SDL was updating the surface before my window manager load them. The solution is to handle window event EXPOSED that is when the window loaded by the window manager.

SDL_Event event;

while(SDL_WaitEvent(&event))){
    switch(event.type){
        case SDL_WINDOWEVENT:
            switch(event.window.event){
                case SDL_WINDOWEVENT_EXPOSED:
                    SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 255, 255, 255));
                    SDL_UpdateWindowSurface(window);
                    SDL_Delay(3000);
                    SDL_Quit();
                    break;
            }
    }
}
Yuri Santos
  • 179
  • 7
  • 2
    Tutorial is wrong, you can't draw once and expect result to stay forever (or any time at all). This is true for every graphical program, but GUI toolkits usually redraws when needed. Game oriented toolkits provide much finer control; most common approach is to redraw unconditionally once in a while (e.g. each vsync interval), or, if image is known to be mostly static and CPU/GPU usage is your concern - redraw when window system asks you to with appropriate [event](https://wiki.libsdl.org/SDL_WindowEvent) – keltar Nov 15 '17 at 03:20
  • @keltar so basically, all i have to do is redraw when theses events occurs? – Yuri Santos Nov 15 '17 at 19:13
  • 2
    Redraw on EXPOSED event, I think. Window manager can show your window a bit later => you've drawn while it wasn't visible, now its visibility changed (either was hidden or overshadowed by other window) - here goes exposed event, redraw. Overshadow your window by other program, switch to yours again - now region that wasn't visible needs to be redrawn. With compositing window managers (e.g. gnome3's clutter) things are different, but by no means clearer - they theoretically can show older image if you don't redraw (e.g. for smoother window movement), but I don't think they're required to. – keltar Nov 16 '17 at 06:04
  • @keltar got it! thanks for the explanation. Now i understand what was happening. – Yuri Santos Nov 16 '17 at 23:16
  • I was having the same issue with KDE/KWin. The catch is that by default, SDL tries to bypass compositor, which makes SDL_UpdateWindow non effective. But when you add a hint `SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,·"0");` just before `SDL_Init()`, the compositor stays and the UpdateWindow worked. I still don't know why you don't need to wait for the EXPOSED event with compositor on. – JonnyRobbie May 26 '20 at 15:25
  • The answer to this question might be this: https://stackoverflow.com/questions/40113594/sdl-pollevent-seems-to-prevent-window-surface-from-updating/40122002#40122002 -> i.e. the surface is invalidated on some events from window manager, such as EXPOSED – Dalibor Filus Mar 10 '21 at 18:26

0 Answers0