garya@stan.com (Gary Aitken) (11/15/88)
Having just wasted (?) a lot of time chasing down the source for lost
button press events, I thought the following might save people some trouble.
There are several race conditions caused by the client/server model which
essentially require that button press/release events always be selected
together. Consider the following:
Client Server
----------------------------- ---------------------------
Select input on ButtonPress
User presses button
Dispatch press to user
Receive button press
Grab pointer selecting input on
ButtonRelease & other stuff
(e.g. ButtonMotion)
Process Grab
User releases button
Dispatch release to user.
User presses button again.
*** Discarded, pointer still grabbed and
ButtonPress not selected.
Receive button release.
Ungrab pointer
Process Ungrab
User releases button
Dispatch release to user.
Receive 2nd release, but no
matching press.
The above scenerio has lots of variations. The grab is not necessary,
but illustrates a common paradigm. The important lesson is that, if an
application is interested in ButtonPress/ButtonRelease pairs, it should
always select for both of them, to prevent the server from discarding
events due to timing problems. The events will be delivered in order,
but the client should probably check for extraneous ones anyway.
In the above example, the initial input selection should be for both
ButtonPress and ButtonRelease.rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (11/20/88)
Client Server
----------------------------- ---------------------------
Select input on ButtonPress
User presses button
Dispatch press to user
Receive button press
Grab pointer selecting input on
ButtonRelease & other stuff
(e.g. ButtonMotion)
Process Grab
User releases button
Dispatch release to user.
User presses button again.
*** Discarded, pointer still grabbed and
ButtonPress not selected.
Receive button release.
Ungrab pointer
Process Ungrab
User releases button
Dispatch release to user.
Receive 2nd release, but no
matching press.
The grab is not necessary, but illustrates a common paradigm.
The grab is necessary to get the kind of error you describe. Otherwise,
the button press would have caused a grab, the event mask would not have
changed, and the grab would have been release automatically when the button
was released. Alternatively, your bug is that you aren't using synchronous
event processing during the grab; if you had, then you would have been in a
position to release the grab before the subsequent button press was processed.