Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!im4u!ut-sally!seismo!lll-lcc!ames!ucbcad!ucbvax!decvax!tektronix!teklds!hercules!glennw From: glennw@hercules.UUCP Newsgroups: comp.windows.x Subject: Re: XUpdateMouse() Message-ID: <1786@hercules.TEK.COM> Date: Thu, 26-Feb-87 10:29:12 EST Article-I.D.: hercules.1786 Posted: Thu Feb 26 10:29:12 1987 Date-Received: Sun, 1-Mar-87 08:15:11 EST References: <8702231839.AA02342@ingres.Berkeley.EDU> Organization: Tektronix Inc., Beaverton, Or. Lines: 116 Summary: the secrets of XUpdateMouse revealed (and improved) Fcc:x In article <8702231839.AA02342@ingres.Berkeley.EDU>, dcmartin@INGRES.BERKELEY.EDU (David C. Martin) writes: > The manual says that XUpdateMouse() "eliminates any mouse moved events at the > head of the queue..." > > Does this mean that all mouse moved events are flushed from the queue, with > the exception of the last, or are all mouse moved events flushed? XUpdateMouse only flushes the contiguous block of MouseMoved events at the head of the queue, that is, flushing ceases when the first non-mouse event is encountered. In the little project I am doing now, I have found this to be less than optimal. For one thing, there is no good way to be sure that the pointer is not in another window overlapping yours, because there is no way to find out if any mouse events actually occured. For another, there is no reason to leave any Mouse events lying around in the queue once the mouse has been queried. Also, I have found it useful to have the one routine missing from the set, XUpdateMouseButtons. So I have written a new Mouse polling routine, XUpdatePointer (V11-style name), which adds a return argument to XQueryMouseButtons giving the number of events removed from the queue, and deletes all MouseMoved and Button events throughout the queue. The calling routine uses the last mouse state if no events are found. This routine significantly improves performance when mouse buttons and keys are intermixed in the queue. The source is enclosed. A correct XUpdateMouse or XUpdateMouseButtons is a simple reduction from this routine. I hit one minor mystery which I coded around, not having time to figure it out. Apparently, either GetReq() or _XReply allows new events to enter the queue, so I had to move the XPending call after these calls to get an accurate count of the events removed from the queue. One annoying problem with getting buttons with QueryButton is that it is easy to miss a fast button press. I am thinking about a further hack on this routine which would return the state of each button event, if any instead of polling the pointer, guaranteeing accurate capture of the button presses and additionally reducing the IPC overhead a bit. ----------- #include /* $Header: XUpdatePointer.c,v 1.1 87/02/23 06:31:02 glennw Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ #include "XlibInternal.h" extern _QEvent *_qfree; /* Like XQueryButtons, but also reads pending events and flushes any * MouseMoved, ButtonPressed, or ButtonRelease events anywhere in the queue. * It returns the number of events flushed in the removed argument. * A good way to track the mouse is to use a MouseMoved or Button event * as a "hint", by calling this routine to get up to date coordinates. */ Status XUpdatePointer (w, x, y, subw, state, removed) Window w; Window *subw; int *x, *y; short *state; int *removed; { register Display *dpy; register XReq *req; register _QEvent *qelt, *qprev; _QEvent qdummy; XRep rep; int quelen; GetReq(X_QueryMouse, w); if (!_XReply(dpy, &rep)) return(0); quelen = XPending(); /* read all events in socket's kernel buffer, flush output */ /* note - apparently GetReq or XReply allows more events to get in, so XPending is moved after them to get a correct queue length */ qprev = &qdummy; /* temporary stash for next ptr while at head */ qelt = dpy->head; while (qelt) { if ((qelt->event.type & (MouseMoved | ButtonPressed | ButtonReleased)) != 0) { qprev->next = qelt->next; /* stash next ptr or splice cur out */ qelt->next = _qfree; /* and into free list */ _qfree = qelt; qelt = qprev->next; /* move to next item */ dpy->qlen--; } else { if (qprev == &qdummy) /* first non-Mouse event; reset head */ { dpy->head = qelt; } qprev = qelt; qelt = qelt->next; /* skip over non-Mouse events */ } } if(qprev == &qdummy) /* found no non-Mouse event; queue is empty */ dpy->head = dpy->tail = NULL; else dpy->tail = qprev; /* in case we removed events from end of queue */ *x = rep.param.s[2]; *y = rep.param.s[3]; *subw = rep.param.l[0]; *state = rep.params4; *removed = quelen - dpy->qlen; return (1); } -- Glenn Widener