Hi!

I've recently postest on this list about mapping keyboard events to 
mousebuttons.

I've found a small program that does this (it's so small that I've attached 
the source, hope that 3kb aren't a problem)

To summarize, the program uses 

  XGrabButton(disp,
              button,
              AnyModifier,
              DefaultRootWindow(disp),
              False,
              ButtonPressMask | ButtonReleaseMask,
              GrabModeAsync,
              GrabModeAsync,
              None,
              None);

to grab the button(s) and then uses 

XNextEvent(disp, &event); 

in an endless loop to wait for the grabbed mousebutton events.

For simple things, this works fine, but as soon as you push the grabbed 
mousebutton, hold it and push a second mousebutton, XNextEvent gets the 
second event and everything goes wrong (program crashes, the crash is easily 
fixed by a if/continue statement, but the event is lost of course).

So my questions:

- Why does XNextEvent get an event it shouldn't when a grabbed button is 
pressed?
- How do you prevent XNextEvent from getting the event or how do you forwared 
those events to the X server?

Thanks a lot,

Roland

-- 
Wethern's Law:
        Assumption is the mother of all screw-ups.
/*
 * mousemap: remapping of mouse events
 *
 * MOUSEMAP is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
 * Version 2 (June 1991). See the "COPYING" file distributed with this
 * software for more info.
 *
 * Copyright (c) 2001 by Michael Schroeder <[EMAIL PROTECTED]>

 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>


#define PROG		"mousemap"
#define VERSION		"v0.2"

#define PRESS		True
#define RELEASE		False

#define MAXBUTTON	2
#define MINIMUM		6	/* minimum count of buttons */

#define KEYLEFT		"Left"
#define KEYRIGHT	"Right"

//#define DBG	1

#ifdef DBG
# define DBGMSG(x...)	fprintf(stderr, ##x)
#else
# define DBGMSG(x...) 
#endif


static char *symbol[MAXBUTTON] = {KEYLEFT, KEYRIGHT};

/*
 * generate key event
 */
static void fakeKey(Display *disp, char *key, Bool press)
{
  unsigned int keycode;

  keycode = XKeysymToKeycode(disp, XStringToKeysym(key));
  
  XTestFakeKeyEvent(disp, keycode, press, CurrentTime);
}


static void grabButton(Display *disp, int button)
{
  XGrabButton(disp,
	      button,
	      AnyModifier,
	      DefaultRootWindow(disp),
	      False,
	      ButtonPressMask | ButtonReleaseMask,
	      GrabModeAsync,
	      GrabModeAsync,
	      None,
	      None);
}


int main(int argc, char *argv[])
{
  int buttons, index, i;
  unsigned char buf[80], map[16];
  Display *disp;
  XEvent event;
  				/* create new process */
  if (fork())
    exit(0);		/*  parent exits immediatly */

  setsid();		/* child is a daemon and runs in a new session */

  if(!(disp = XOpenDisplay(NULL))) {
    fprintf(stderr, "%s: unable to open display\n", PROG);
    exit(1);
  }

  buttons = XGetPointerMapping(disp, map, sizeof(map));	/* get button count */

  if (buttons < MINIMUM) {
    fprintf(stderr, "%s: mapping is not required %d\n", PROG, buttons);
    XCloseDisplay(disp);
    exit(0);
  }

  for (i = 0; i < MAXBUTTON && i < argc; i++)
    if (argv[i+1])			/* are there user defined symbols? */
      symbol[i] = argv[i+1];

  if (argc > MAXBUTTON && argv[i+1]) {	/* new mapping table? */

    sprintf(buf, "xmodmap -e \"pointer = %s\"", argv[i+1]);

    if (system(buf)) {				 /* success ? */
      XCloseDisplay(disp);
      exit(1);
    }

    XGetPointerMapping(disp, map, sizeof(map));		/* get new map */
  }

  XAllowEvents(disp, AsyncBoth, CurrentTime);	/* release queued events */
  XAllowEvents(disp, SyncBoth, CurrentTime);

  for (i = MINIMUM; i <= buttons; i++) 
    grabButton(disp, i);			/* claim mouse buttons */

  XSelectInput(disp, XDefaultRootWindow(disp), PointerMotionMask);

  fprintf(stderr, "%s %s installed - mapping table:", PROG, VERSION);
  for (i = 0; i < buttons; i++) {
    if (map[i] >= MINIMUM)
      fprintf(stderr, " %d=%s", map[i], symbol[map[i]-MINIMUM]);
    else
      fprintf(stderr, " %d", map[i]);
  }
  fprintf(stderr, "\n");

  for (;;) {	/* loop forever */

    XNextEvent(disp, &event);		/* block until button pressed */

    DBGMSG("%s: button event: %d\n", PROG, event.xbutton.button);

    index = event.xbutton.button - MINIMUM;	/* 0 = left, 1 = right */

    switch (event.type) {

      case ButtonPress:
	DBGMSG("button pressed: %d\n", event.xbutton.button);
	fakeKey(disp, symbol[index], PRESS);
	break;
	
      case ButtonRelease:
	DBGMSG("button released: %d\n", event.xbutton.button);
	fakeKey(disp, symbol[index], RELEASE);
	break;
    }
  }

/* never reached */

  return 0;
}




Reply via email to