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