Skip to main content
GameDev.net gamedev.net
🔒 Locked

SDL window resize glitch

Started by Servant of the Lord Dec 11, 2006 at 12:48 PM 4 replies 17.9k views
Original Post
Servant of the Lord
Servant of the Lord
I've made a SDL window resizable, but when I resize it, it doesn't update. I grab the edge of the window and stretch it, and it stretches, but the surface in the center isn't refreshed until I let go of the window's edge. This creates an ugly blur when resizing. Here's two pictures to illustrate what I mean. While dragging: While dragging the edge of the window... And after I let go: After letting go of the edge... It seems to me that SDL stops my application while it is being resized! I don't mind my application pausing, but I don't want that ugly smear to appear at every resize. Is there a SDL event that I can use to tell me while a window is being resized, and not just after? Currently I just have this in my event loop:
        case SDL_VIDEORESIZE: //Screen resized
        {
            SCREEN_WIDTH = WinEvent.resize.w;
            SCREEN_HEIGHT = WinEvent.resize.h;
            
            Screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE|SDL_RESIZABLE);
            if(Screen == NULL) return -1;
        }
What can I do to remedy this?
KaptainKomunist
KaptainKomunist
Instead of creating a new screen surface, why don't you just call SDL_UpdateRect(0,0,0,0);

edit: Oh, and SDL probably doesn't support dynamic resizing. SDL won't get that message until the mouse sends a mouse_up message.
rip-off
rip-off


SDL has the ability to filter incoming events. SDL's event queue will be running even when your app isnt.

If you write a event filter that takes some action instead of just filtering events you can be notified of events *before* they even arrive at the event queue.

Read up on SDL_SetEventFilter();

But remember that you are potentially running multi-threaded code and that you should use mutual exclusion or whatever to prevent any mishaps from occuring

( but on my computer (Windows) the event filter appears to run in the same thread as main() )

A quick test I threw together updated the screen while you moved the mouse resizing the window. However, just holding mouse down at the side of the window ready to resize paused the program.



Enjoy [smile]
Servant of the Lord
Servant of the Lord
Quote:
Original post by KaptainKomunist
Instead of creating a new screen surface, why don't you just call SDL_UpdateRect(0,0,0,0);


That doesn't work. It would only update my old sized window, while the frame of my window will be the new size. I'm not creating a new surface, but updating my old surface to match the new size.

Quote:
edit: Oh, and SDL probably doesn't support dynamic resizing. SDL won't get that message until the mouse sends a mouse_up message.

Dang, well that causes problems for me. Thanks for pointing that out.

@rip-off: I don't get how I'd use that. Could you explain it? There is a lack of examples for me to peruse.
And are you saying that on non-window operating systems it would create new threads? I would prefer sticking with the blurred window and keeping it crossplatform-able if you'd think it would cause problems.
rip-off
rip-off
Quote:

There is a lack of examples for me to peruse.


Thats because Im abusing SDL [smile]

The purpose of the event filter is to control the types of events that are added to the event queue. Im using the fact that this function is run while the rest of the program is halted to allow the program to continue drawing. Hence why I called it a horrible hack.

Quote:

And are you saying that on non-window operating systems it would create new threads?

Other operating systems can have threaded events. Im not overly familiar with them. But if the filter is run by another thread then this *could* cause problems. But we have a simple way around that, disable the filter.

Heres the "technique":

From what I can tell, SDL seems to pause the main thread ( under Win32 anyway ) during resizing. Since rendering can only be done in the main thread, this prevents redrawing.

However, from what I can see on windows the event filter runs in the main thread. Its not very hard to enable if you have drawing code seperated from other code.

Here is a quick example:

#include "SDL.h"int x,y;int vx,vy;void draw(){    SDL_Surface * screen = SDL_GetVideoSurface();    SDL_FillRect(screen,NULL,0);    SDL_Rect rect = {x,y,20,20};    x += vx;    y += vy;    if( x > screen->w - 20 || x < 0 )    {        x = x<0? 0 : screen->w - 20;        vx = -vx;    }    if( y > screen->h - 20 || y < 0 )    {        y = y<0 ? 0 : screen->h - 20;        vy = -vy;    }    SDL_FillRect(screen,▭,0xfffffff);    SDL_Flip(screen);    SDL_Delay(10);}int eventFilter( const SDL_Event *e ){    if( e->type == SDL_VIDEORESIZE )    {        SDL_SetVideoMode(e->resize.w,e->resize.h,0,SDL_ANYFORMAT | SDL_RESIZABLE);        draw();    }    return 1; // return 1 so all events are added to queue}int main( int , char ** ){    SDL_Init( SDL_INIT_VIDEO );    #ifdef WIN32    SDL_SetEventFilter( &eventFilter );    #endif    SDL_SetVideoMode(800,600,0,SDL_ANYFORMAT | SDL_RESIZABLE);    x = y = 0;    vx = vy = 1;    bool running = true;    while(running)    {        SDL_Event e;        while(SDL_PollEvent(&e) )        {            if( e.type == SDL_QUIT )            {                running = false;            }        }        draw();    }    SDL_Quit();    return 0;}


If you are not sure that this will work under linux etc you can simply wrap the SDL_SetEventFilter in a #ifdef WIN32 block as shown. If the majority of the users will be windows only it may be worth the extra effort of having 1 "platform specific" feature.
Servant of the Lord
Servant of the Lord
Many thanks! I saw an example on the libSDL mailing list but hadn't understood it. It's the pointer to the function that threw me. Resizes perfectly now, thanks.

(Added the Window OS if-defines and if-not-defines as well)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.