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;
}