[sugar] Touchpad improvements and activities using pointer (mouse) motion....
Jim Gettys
jg at laptop.org
Wed Sep 3 14:36:21 EDT 2008
Richard Smith has fixed some bad performance problems in the embedded
controller, that talks to the touch pad, now in the latest firmware in
joyride and the 8.2 stream.
The consequences are that the touch pad is reporting many real mouse
motion events, as you move your finger on the touch pad. These were
previously getting dropped on the floor in 8.1 and before, and causing
many of our touch pad behavior problems.
This improved behavior, strangely, can pose performance problems for
incorrectly written activities that ask for mouse motion events; paint
programs are a classic example. If you can't keep up with the rate at
which pointer (mouse) motion events are delivered, and you get more
events, your application can fall further and further behind, causing
bad "laggy" behavior. Having improved our touchpad, we're now exposing
some of these issues due to the increased number of events.
In days of yore on slower machines this was a common problem, so the
window system has provisions for it. Many current developers on fast
machines do not see this often on current fast desktops/laptops, so it
many have forgotten about the solutions.
X has what is called mouse motion compression; in the GTK toolkit, it is
invoked by:
The gtk.gdk.POINTER_MOTION_HINT_MASK is a special mask which is used to
reduce the number of gtk.gdk.MOTION_NOTIFY events received. Normally a
gtk.gdk.MOTION_NOTIFY event is received each time the mouse moves.
However, if the application spends a lot of time processing the event
(updating the display, for example), it can easily lag behind the
position of the mouse. When using the gtk.gdk.POINTER_MOTION_HINT_MASK
the server will only send a single gtk.gdk.MOTION_NOTIFY event (which is
marked as a hint) until the application asks for more, by calling the
gtk.gdk.Window.get_pointer() method.
You can find the full description in
http://www.pygtk.org/docs/pygtk/class-gdkevent.html
Techniques for handling the issue:
1) by far the best approach, when possible, is to make your pointer
(mouse) handler very light, then do recomputation and drawing in an idle
handler
2) The get_pointer technique using the above POINTER_MOTION_HINT_MASK,
to poll at the rate your application can keep up. But best is to drop
the result from get_pointer() on the floor and forget that it's
overloaded in the X protocol and just pretend that you called
GiveMeAnotherEvent
3) Another technique, rather than doing get_pointer, is to peek in the
event queue to see if the next event is also a pointer motion event, and
use the later event if it is still a pointer motion event, using
gdk_event_peek.
My thanks to Owen Taylor for refreshing my cache and telling me the GTK
idioms.
Note that X also has a facility to record the full stream of mouse
motion coordinates as well, if you want the precise timestamped path the
pointer followed between events. The XGetMotionEvents call can be used
to get that path, at whatever hardware resolution the hardware was able
to provide. Note that the X server/driver may have compressed some
sequential motion events together to begin with.
- Jim
--
Jim Gettys <jg at laptop.org>
One Laptop Per Child
More information about the Sugar
mailing list