Question about ignoring mouse events

[Sorry if I’m posting this a second time. The first try got bounced
because I wasn’t suscribed so I’m trying again.]

Hi all!!

This is probably a newbie question, so you can answer it with links
and/or pointers do the manuals. I couldn’t find anything mainly
because my english is not very good, so I don’t know exactly what to
google for.

I’m writing a small SDL program to display the Mandelbrot Set. I’m
implementing a zoom function. The idea is to mark a rectangle with
the mouse and zooming to that area. I catch the MOUSEBUTTONDOWN and
MOUSEBUTTONUP and set the rectangle’s corners to the points marked.
Then I redraw the screen.

So far so good.

The problem is that when I press the mouse’s button it doesn’t
generate one event but many. So when the program finishes
redrawing, it starts to zoom in again… and again…

I tried using
SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE)

and using
SDL_SetEventFilter(ignore_mouse_button_down)

as I found here
http://www.devolution.com/pipermail/sdl/2004-July/063671.html

but I still have the same problem.

So my questions are: ?How do I do this? and ?Am I designing wrong this
zoom function?–
Rom?n

Rom?n Gorojovsky <rgorojovsky gmail.com> writes:

The problem is that when I press the mouse’s button it doesn’t
generate one event but many. So when the program finishes
redrawing, it starts to zoom in again… and again…

I tried using
SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE)

and using
SDL_SetEventFilter(ignore_mouse_button_down)

as I found here
http://www.devolution.com/pipermail/sdl/2004-July/063671.html

but I still have the same problem.

So my questions are: ?How do I do this? and ?Am I designing wrong this
zoom function?

My idea: create a boolean var (use char for example): lets call it mouse_down.

At the beginning of the program set

mousedown=0;

When you get a mousebutton down event, set it to 1. If you get a mousebutton
down event and mousedown==1: ignore it. As soon as you get a mousebutton up
event, set mousedown=0.

Just my 0,02?

Please tell me if it helped.

Wolfgang

No, sorry, it didn’t help. It’s the same logic I’m using with
SDL_SetEventFilter(), and it didn’t work with that either:

main(){

/* initialize SDL and draw the
/* first mandelbrot set */

while (1) {
	SDL_PollEvent(&event);
    	switch (event.type) {
	    	/* SDL_QUIT Handling*/
		case SDL_MOUSEBUTTONDOWN:
			SDL_SetEventFilter(ignore_mouse_button_down);
			/* get begining of area */
			break;

		case SDL_MOUSEBUTTONUP:
			/* zoom in */
			SDL_SetEventFilter(NULL);
			break;
	}
}

return 0

}

Maybe I shouldn’t be using PollEvent() but I couldn’t find any useful
replacement (I allready tried WaitEvent() ).

Any ideas?? I’ll keep trying to find a solution, and I’ll write if I
can find it.On 11/15/05, Wolfgang Keller <mail.wolfgang.keller at web.de> wrote:

Rom?n Gorojovsky <rgorojovsky gmail.com> writes:

The problem is that when I press the mouse’s button it doesn’t
generate one event but many. So when the program finishes
redrawing, it starts to zoom in again… and again…

I tried using
SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE)

and using
SDL_SetEventFilter(ignore_mouse_button_down)

as I found here
http://www.devolution.com/pipermail/sdl/2004-July/063671.html

but I still have the same problem.

So my questions are: ?How do I do this? and ?Am I designing wrong this
zoom function?

My idea: create a boolean var (use char for example): lets call it mouse_down.

At the beginning of the program set

mousedown=0;

When you get a mousebutton down event, set it to 1. If you get a mousebutton
down event and mousedown==1: ignore it. As soon as you get a mousebutton up
event, set mousedown=0.

Just my 0,02?

Please tell me if it helped.

Wolfgang


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


Rom?n

Oh, I forgot: this is SDL 1.2.8 and the system is Linux, Ubuntu 5.10On 11/16/05, Rom?n Gorojovsky <@Roman_Gorojovsky> wrote:

No, sorry, it didn’t help. It’s the same logic I’m using with
SDL_SetEventFilter(), and it didn’t work with that either:

main(){

/* initialize SDL and draw the
/* first mandelbrot set */

    while (1) {
            SDL_PollEvent(&event);
            switch (event.type) {
                    /* SDL_QUIT Handling*/
                    case SDL_MOUSEBUTTONDOWN:
                            SDL_SetEventFilter(ignore_mouse_button_down);
                            /* get begining of area */
                            break;

                    case SDL_MOUSEBUTTONUP:
                            /* zoom in */
                            SDL_SetEventFilter(NULL);
                            break;
            }
    }

    return 0

}

Maybe I shouldn’t be using PollEvent() but I couldn’t find any useful
replacement (I allready tried WaitEvent() ).

Any ideas?? I’ll keep trying to find a solution, and I’ll write if I
can find it.

On 11/15/05, Wolfgang Keller <mail.wolfgang.keller at web.de> wrote:

Rom?n Gorojovsky <rgorojovsky gmail.com> writes:

The problem is that when I press the mouse’s button it doesn’t
generate one event but many. So when the program finishes
redrawing, it starts to zoom in again… and again…

I tried using
SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE)

and using
SDL_SetEventFilter(ignore_mouse_button_down)

as I found here
http://www.devolution.com/pipermail/sdl/2004-July/063671.html

but I still have the same problem.

So my questions are: ?How do I do this? and ?Am I designing wrong this
zoom function?

My idea: create a boolean var (use char for example): lets call it mouse_down.

At the beginning of the program set

mousedown=0;

When you get a mousebutton down event, set it to 1. If you get a mousebutton
down event and mousedown==1: ignore it. As soon as you get a mousebutton up
event, set mousedown=0.

Just my 0,02?

Please tell me if it helped.

Wolfgang


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


Rom?n


Rom?n

while (1) {
SDL_PollEvent(&event);
switch (event.type) {

You need to check the return value from SDL_PollEvent!

What is happening is you are getting a legitimate mousebuttondown event,
and then the next call to SDL_PollEvent() is reporting that there aren’t
any more events, but you are ignoring this and looking at the data from
the previous event, which is still in the “event” object from the
previous call.

It’s best to do “while (SDL_PollEvent(&event))”, handle all queued
events, and then do whatever else you want the program to do, then
repeat it again next frame.

–ryan.

Yes, thank you, that almost worked.

But if you do “while (SDL_PollEvent(&event))” the loop won’t even
start, because usually at that point you don’t have any event. So I
did

while (1) {
if (SDL_PollEvent(&event))
{/everything/}
}

and that did work. Thanks a lot. I’ll be back!!!On 11/16/05, Ryan C. Gordon wrote:

 while (1) {
         SDL_PollEvent(&event);
         switch (event.type) {

You need to check the return value from SDL_PollEvent!

What is happening is you are getting a legitimate mousebuttondown event,
and then the next call to SDL_PollEvent() is reporting that there aren’t
any more events, but you are ignoring this and looking at the data from
the previous event, which is still in the “event” object from the
previous call.

It’s best to do “while (SDL_PollEvent(&event))”, handle all queued
events, and then do whatever else you want the program to do, then
repeat it again next frame.

–ryan.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


Rom?n

Uhm, well, that’s the idea; if there are no events, this loop should
not run. Conversely, the loop should spin as long as there are
events, in order to empty the queue before exiting.

Note that the latter (emptying the event queue before you move on) is
very important! If you don’t do it that way, you’ll get this horrible
"rubber band" delay effect as soon as your rendering loop cannot spin
at least once per input event. (Which it most likely cannot, unless
the user has a low frame rate mouse and/or you’re doing OpenGL
rendering without retrace sync.)

So, what I’m saying is, this event decoding loop should be an inner
loop, inside the main/rendering loop. That way, it simply does
nothing if there are no events.

(Well, there are cases where you actually want the event loop to be
the outer loop, or logically equivalent, but then you generally want
to use SDL_WaitEvent instead, and either way, this rarely applies to
games, where there is usually stuff going on even when there are no
input events.)

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Wednesday 16 November 2005 14.26, Rom?n Gorojovsky wrote:

Yes, thank you, that almost worked.

But if you do “while (SDL_PollEvent(&event))” the loop won’t even
start, because usually at that point you don’t have any event.

Yes, thank you, that almost worked.

But if you do “while (SDL_PollEvent(&event))” the loop won’t even
start, because usually at that point you don’t have any event.

Uhm, well, that’s the idea; if there are no events, this loop should
not run. Conversely, the loop should spin as long as there are
events, in order to empty the queue before exiting.

So, what I’m saying is, this event decoding loop should be an inner
loop, inside the main/rendering loop. That way, it simply does
nothing if there are no events.

ok, but is there an important difference between the following?

while (1)
{
if (SDL_PollEvent(&event))
{
/* process events */
case SDL_QUIT:
exit(0);
}
}

vs

while (1)
{
while (SDL_PollEvent(&event))
{
/* process events */
}
}

Should I handle the SDL_QUIT case differently?

Note that the latter (emptying the event queue before you move on) is
very important! If you don’t do it that way, you’ll get this horrible
"rubber band" delay effect as soon as your rendering loop cannot spin
at least once per input event. (Which it most likely cannot, unless
the user has a low frame rate mouse and/or you’re doing OpenGL
rendering without retrace sync.)

humm I’m not sure if I’m following you. I don’t have a rendering
loop. I render, then I check events, and then if I have to render
again I do it. The rendering loop only checks the SDL_QUIT event.

(Well, there are cases where you actually want the event loop to be
the outer loop, or logically equivalent, but then you generally want
to use SDL_WaitEvent instead, and either way, this rarely applies to
games, where there is usually stuff going on even when there are no
input events.)

Yes, I think I would have used Wait in that case.On 11/16/05, David Olofson wrote:

On Wednesday 16 November 2005 14.26, Rom?n Gorojovsky wrote:

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


Rom?n

ok, but is there an important difference between the following?

while (1)
{
if (SDL_PollEvent(&event))
{
/* process events */
case SDL_QUIT:
exit(0);
}
}

vs

while (1)
{
while (SDL_PollEvent(&event))
{
/* process events */
}
}

Yes, in the first case, you only handle ONE event per loop.
(“Loop” here being the outer “while(1)” loop).

Move the mouse for a few seconds and the queue quickly become backed up
with mouse motion events that you haven’t gotten around to handling.

In the latter case, you suck the queue dry whenever you get the chance,
keeping your program up-to-speed with what the user and OS might be doing
(wiggling the mouse, hitting a bunch of keys, firing timers, etc.)

Should I handle the SDL_QUIT case differently?

Well, really what >I< do is:

done = 0; /* FALSE */

do
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
done = 1; /* TRUE /
else if (event.type …) /
keypress, mouse motion, timers, etc. */

}

/* Do my once-a-loop stuff (e.g., draw enemies, move enemies, etc.) */

/* SDL_Delay() can be useful here; see numerous mailinglist threads... */

}
while (!done);

/* Clean up… free memory, etc. etc. */

SDL_Quit();

You can have events also cause “done” to become 1 (TRUE), such as
the user hitting [Escape] at the main menu, or pressing [Alt]+[F4],
or pulling down a menu in your super-duper SDL-based GUI and selecting
"Exit" and then clicking “Yes” to “But I’m such a cool game! Are you SURE?”.

:slight_smile:

-bill!On Wed, Nov 16, 2005 at 03:10:31PM -0300, Rom?n Gorojovsky wrote:

[…]

ok, but is there an important difference between the following?

Well, if you insert (unconditional) rendering code…

while (1)
{
if (SDL_PollEvent(&event))
{
/* process events */
case SDL_QUIT:
exit(0);
}

…here…

}

vs

while (1)
{
while (SDL_PollEvent(&event))
{
/* process events */
}

…and here…

}

…there is a big difference in the chances of keeping up with the
input event stream. The first version will helplessly lag behind and
add an increasing delay, if it cannot render fast enough to generate
one frame per input event.

However, if you make sure not to repaint the screen, or get stuck
waiting for the retrace (ie SDL_Flip()) every loop, you may still be
fine.

Should I handle the SDL_QUIT case differently?

Doesn’t really matter; it’s just another event, basically. In fact,
you can chose to ignore it, pop up a “Sure?” dialog or something and
keep running if the user cancels the operation. SDL_QUIT just means
the user klicked the X button, or whatever one does on the OS we’re
on.

Note that the latter (emptying the event queue before you move on)
is very important! If you don’t do it that way, you’ll get this
horrible “rubber band” delay effect as soon as your rendering loop
cannot spin at least once per input event. (Which it most likely
cannot, unless the user has a low frame rate mouse and/or you’re
doing OpenGL rendering without retrace sync.)

humm I’m not sure if I’m following you. I don’t have a rendering
loop. I render, then I check events, and then if I have to render
again I do it.

Well, that sounds pretty much like an event driven application then
(as in, it’s not spinning full speed rendering frames at all times) -
but this alone does not mean you completely avoid the problem! All it
takes is responding to mouse moves or other events that may arrive at
high frequencies and you may fall in the “one event per frame” trap.

The rendering loop only checks the SDL_QUIT event.

That is, rendering may take long enough that there is reason to check
SDL_QUIT while doing it…? That makes it even more important to
process all pending events whenever you have a chance to handle them
properly.

If it takes more than a second or so to render a frame, you should
probably decouple the rest of the visual feedback from this
rendering, so the application doesn’t appear to be completely frozen
while rendering.

The best way to deal with this sort of stuff is usually to do the
rendering completely asynchronously in the background, with automatic
abort/restart if the user changes parameters while rendering. Serious
image processing applications have to do this to be realistically
usable on very large images, and IMHO, something like this should be
done whenever possible, as soon as delays in interactive work start
crossing this magic one second stress limit.

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Wednesday 16 November 2005 19.10, Rom?n Gorojovsky wrote:

aaaah. Now I see the difference. It didn’t hurt me because, since my
program isn’t a game, I can react slower, i. e. I draw the mandelbrot
set, wait for zoom in/out and redraw, so I don’t have moving objects
or anythig else. And I don’t react to mouse movements.

But clearly the while (1) { while (SDL_Poll) } } version is better,
more realiable and flexible. Thanks for the good advice!!On 11/16/05, Bill Kendrick wrote:

On Wed, Nov 16, 2005 at 03:10:31PM -0300, Rom?n Gorojovsky wrote:

ok, but is there an important difference between the following?

while (1)
{
if (SDL_PollEvent(&event))
{
/* process events */
case SDL_QUIT:
exit(0);
}
}

vs

while (1)
{
while (SDL_PollEvent(&event))
{
/* process events */
}
}

Yes, in the first case, you only handle ONE event per loop.
(“Loop” here being the outer “while(1)” loop).

Move the mouse for a few seconds and the queue quickly become backed up
with mouse motion events that you haven’t gotten around to handling.

In the latter case, you suck the queue dry whenever you get the chance,
keeping your program up-to-speed with what the user and OS might be doing
(wiggling the mouse, hitting a bunch of keys, firing timers, etc.)

Should I handle the SDL_QUIT case differently?

Well, really what >I< do is:

done = 0; /* FALSE */

do
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
done = 1; /* TRUE /
else if (event.type …) /
keypress, mouse motion, timers, etc. */

}

/* Do my once-a-loop stuff (e.g., draw enemies, move enemies, etc.) */

/* SDL_Delay() can be useful here; see numerous mailinglist threads... */

}
while (!done);

/* Clean up… free memory, etc. etc. */

SDL_Quit();

You can have events also cause “done” to become 1 (TRUE), such as
the user hitting [Escape] at the main menu, or pressing [Alt]+[F4],
or pulling down a menu in your super-duper SDL-based GUI and selecting
"Exit" and then clicking “Yes” to “But I’m such a cool game! Are you SURE?”.

:slight_smile:

-bill!


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


Rom?n