If it's not required, then some kind of a round-trip ping is needed. The
NoOperation request is a one-way trip only, and is not sufficient.
Currently, I am abusing the InternAtom request for this, to know when the
server processed all requests that preceded it. This is how I arrived at
this conundrum.
I am intentionally using a sub-optimal environment, where the client and the
server are across a network that includes a wireless AP. This is to make
suboptimal drawing algorithms be more visible.
I can process MotionNotify events as fast as they come in, generating a pile
of X and RENDER requests as a result. But with a couple of hops across the
network, it's surprising how many X and RENDER requests can fill up in the
intermediate network buffers, before the server goes through them; which
(especially RENDER composition) create a lot of work for the server. My
display was noticably lagging behind the pointer, as much as 2-3 seconds,
even though my client was doing nothing, waiting to receive the next event.
I fixed this by sending an InternAtom just before flushing out all my work,
and then waiting for the response to the InternAtom, which arrives only
after the server dealt with my preceding requests. Once the InternAtom
response was received, with anything that came before it getting held in
/my/ queue, the existing logic that I already had in place dealt with all
the queued up MotionNotify events, only processing the last one. No more
apparent visual lag.
This trick will only work as long as the server processes all requests
serially. If someone gets the bright idea to optimize responses out of
sequence, where possible, this will defeat this workaround. The server seems
to already be capable of throwing me MotionNotify events while it's chewing
away at the request backlog.