Mouse problems

I just ran into some problems with the SDL mouse routines. Here is why:
I’m currently hacking together a breakout clone, so I need the relative
mouse movements (this one is easy). Furthermore, I don’t want the mouse
cursor to leave the window, so I tried that old trick that worked so
well for Xlib games: warp the mouse to the center of the window whenever
it leaves some predefined rectangle inside the window. This only worked
if you didn’t rely on X events but polled the mouse, but as far as I
know, this is the only way to effectively “grab” the mouse under X.

So far, so good. But it doesn’t work under SDL. It seems that neither
X nor SDL respond quickly enough to mouse warps. When warping while
moving the mouse, I usually get two or three motion events reporting the
old mouse positions, before finally receiving the new mouse
coordinates. Using SDL_GetMouseState doesn’t help either (I thought it
was something like XQueryPointer, but it tourned out to simply return an
internal mouse state).

I took a look at SDL’s source – it seems to rely on X events for
everything concerning mouse movements. Wouldn’t it be nicer to base
motion events on calls to XQueryPointer? That should solve all my
problems and wouldn’t even break old applications…

Another curiosity is demonstrated by the following program:

      SDL_WarpMouse (oldmousex, oldmousey);
      do {
        SDL_GetMouseState (&mousex, &mousey);
      } while (mousex==oldmousex && mousey==oldmousey);

This loop turned out to run forever – not quite what I expected it to
do. But once again, using XQueryPointer should solve this problem.

Cheers
Daniel

I just ran into some problems with the SDL mouse routines. Here is why:
I’m currently hacking together a breakout clone, so I need the relative
mouse movements (this one is easy). Furthermore, I don’t want the mouse
cursor to leave the window, so I tried that old trick that worked so
well for Xlib games: warp the mouse to the center of the window whenever
it leaves some predefined rectangle inside the window. This only worked
if you didn’t rely on X events but polled the mouse, but as far as I
know, this is the only way to effectively “grab” the mouse under X.

This works well for SDL doom. Try downloading the source from:
http://www.devolution.com/~slouken/SDL/download.html

Another curiosity is demonstrated by the following program:

      SDL_WarpMouse (oldmousex, oldmousey);
      do {
        SDL_GetMouseState (&mousex, &mousey);
      } while (mousex==oldmousex && mousey==oldmousey);

Yup. You need to drive the event loop with SDL_PumpEvents().
I thought very seriously about adding a call to SDL_PumpEvents() to the
event state polling functions, but many programs get the state at high
frequency, expecting them to be very fast functions, and they only need
event state updated once per frame.

I’m open to suggestions. :slight_smile:

-Sam Lantinga				(slouken at devolution.com)

Lead Programmer, Loki Entertainment Software–
“Any sufficiently advanced bug is indistinguishable from a feature”
– Rich Kulawiec

Yup. You need to drive the event loop with SDL_PumpEvents().
I thought very seriously about adding a call to SDL_PumpEvents() to the
event state polling functions, but many programs get the state at high
frequency, expecting them to be very fast functions, and they only need
event state updated once per frame.

I’m open to suggestions. :slight_smile:

Maybe add a boolean parameter that determines whethere the function
advances the queue or not? Or just two different functions.

Stuart Anderson

Sam Lantinga wrote:

Another curiosity is demonstrated by the following program:

      SDL_WarpMouse (oldmousex, oldmousey);
      do {
        SDL_GetMouseState (&mousex, &mousey);
      } while (mousex==oldmousex && mousey==oldmousey);

Yup. You need to drive the event loop with SDL_PumpEvents().
I thought very seriously about adding a call to SDL_PumpEvents() to the
event state polling functions, but many programs get the state at high
frequency, expecting them to be very fast functions, and they only need
event state updated once per frame.

Well, you’re absolutely right: GetMouseState should execute fast. But
programs that need to “get the state at high frequency” are probably
also interested in the current mouse state. I took a look at the SDL
source and it seems that GetMouseState return simply an internal mouse
state that is updated whenever SDL_PumptEvents() or the like is called.
As it stands, SDL_GetMouseState() could be easily replaced by a few
lines of code in the game engine: You simply poll the event queue once
per frame and store the mouse state in some global variables. But there
is no way to get the current mouse position quickly and without having
having to rely on X events.

Imho buffering mouse events, as X does, is highly inappropriate for
games. I just don’t care about the exact path along which the mouse was
moved, if the framerate of my game isn’t high enough to let me draw all
those intermediate mouse cursors. It also seems like the X event queue
is really slow. You might try running SDLdoom on a “slow” computer
(like my P100). It works nicely – as long as you don’t touch the
mouse! Whenever you do this, the game slows down to a crawl. I know,
a P100 isn’t really “state-of-the-art”, but moving the mouse shouldn’t
have that much impact on the game speed, should it?

I don’t want to quibble over minor things, but SDL_GetMouseState() isn’t
as “Direct” as you (or, well, at least `I’) would expect it to be. This
is the only thing about SDL that irks me; I don’t really care about
internationalized error messages (although introducing
SDL_SomethingErr() functions seems to be a good idea). But fast and
direct access to the mouse cursor is important for many games.

Just my point of view…

Daniel

But there is no way to get the current mouse position quickly and
without having having to rely on X events.

Unfortunately, you’re stuck with this when using X.
SDL is going to support one or more fullscreen APIs under Linux which
shouldn’t suffer from the same problem. It’s work in progress.

Imho buffering mouse events, as X does, is highly inappropriate for
games. I just don’t care about the exact path along which the mouse was
moved, if the framerate of my game isn’t high enough to let me draw all
those intermediate mouse cursors. It also seems like the X event queue
is really slow. You might try running SDLdoom on a “slow” computer
(like my P100). It works nicely – as long as you don’t touch the
mouse! Whenever you do this, the game slows down to a crawl. I know,
a P100 isn’t really “state-of-the-art”, but moving the mouse shouldn’t
have that much impact on the game speed, should it?

No, it shouldn’t. Were I to have time, I would check it out, but unfortunately
I’m swamped with life right now. :slight_smile:

I don’t want to quibble over minor things, but SDL_GetMouseState() isn’t
as “Direct” as you (or, well, at least `I’) would expect it to be. This
is the only thing about SDL that irks me; I don’t really care about
internationalized error messages (although introducing
SDL_SomethingErr() functions seems to be a good idea). But fast and
direct access to the mouse cursor is important for many games.

Very good points.

The next development version of SDL will involve some internal restructuring,
making it more modular and allowing you to get even closer to the hardware
than you are now.

-Sam Lantinga				(slouken at devolution.com)

Lead Programmer, Loki Entertainment Software–
“Any sufficiently advanced bug is indistinguishable from a feature”
– Rich Kulawiec

Sam Lantinga wrote:

But there is no way to get the current mouse position quickly and
without having having to rely on X events.

Unfortunately, you’re stuck with this when using X.

You can always use XQueryPointer(). That’s what I would favor for
SDL_GetMouseState().

–Daniel