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.