[comp.windows.x] XUpdateMouse

dcmartin@INGRES.BERKELEY.EDU.UUCP (02/23/87)

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?

Thanks.

dcm

don@BRILLIG.UMD.EDU.UUCP (02/24/87)

There's no fundemental reason it can't handle more than 2 shift
modifiers at once, except for the fact that the .uwmrc yacc grammar
only allows for up to two. Find the label "keyexpr:" in "uwm/gram.y",
and make it look like the following: (adding the last two cases)

keyexpr:        /* empty */
                        { $$ = 0; }
        |       kmask
                        { $$ = $1; }
        |       kmask '|' kmask
                        { $$ = $1 | $3; }
        |       kmask '|' kmask '|' kmask
                        { $$ = $1 | $3 | $5; }
        |       kmask '|' kmask '|' kmask '|' kmask
                        { $$ = $1 | $3 | $5 | $7; }
        ;

I suppose you could make it a recursive definition, so you could
specify as many kmasks as you wanted. Would that be any more or less
efficient? 

Now you should be able to "or" together up to four shift modifiers to
specify an event for uwm to look for. i.e. this would not work before
but will now:

f.menu=	c|m|s	::	left	: "Ctrl-Meta-Shift-Mouse-Left Menu"

I would like to be able to make a function key assert some combination
of shift keys (all at the same time, on one function key), but there
does not seem to be any simple way to do that. If I could do that,
then I'd bind function keys to ungainly shift combinations, and use
them to modify mouse clicks. Each function key would correspond to a
class of window manager (or whatever) commands.

	-Don

P.S.: While you're waiting for it to recompile, you can sing this:

	Double Bucky
	(Sung to the tune of "Rubber Duckie")	

	Double bucky, you're the one!
	You make my keyboard lots of fun
	  Double bucky, an additional bit or two:
	(Vo-vo-de-o!)
	Control and Meta side by side,
	Augmented ASCII, nine bits wide!
	  Double bucky, a half a thousand glyphs,
		   plus a few!
	    Oh,
	    I sure wish that I
	    Had a couple of
  	        bits more!
	    Perhaps a
	    Set of pedals to
	    Make the number of
	        Bits four:
	    Double double bucky!
	Double bucky, left and right
	OR'd together, outta sight!
	    Double bucky, I'd like a whole word of
	    Double bucky, I'm happy I heard of
	    Double bucky, I'd like a whole
	        word of you!

	(C) 1978 by Guy L. Steele, Jr.

	(For those of you who are interested, the term "bucky bits"
	comes from Niklaus Wirth, known as "bucky" to friends, who
	suggested that an extra bit be added to terminal codes on 36
	bit machines for use by screen editors.)

glennw@hercules.UUCP (02/26/87)

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 <X/mit-copyright.h>

/* $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

glennw@hercules.UUCP (02/26/87)

   Recently I heard a presentation from a workstation supplier on its
plan to support X.  They plan to provide an optimized Xlib that uses
shared memory instead of IPC when talking locally to their own server.
Having just suggested a user extension to Xlib, I am concerned that any
re-architecture of the Xlib/server interface like this must permit user
extensions to the Xlib to be used in conjunction with the re-architected
interface.  Otherwise, people should be warned to avoid any non-standard,
non-Xlib interface to the protocol.
-- 
Glenn Widener