PDA

View Full Version : Greedy XGrabKeyboard



belnac
05-18-2010, 11:37 AM
Hi there,

How do I passively capture keyboard input from a terminal program without locking out the system?

As it stands, my small test program (shown below) locks out all running programs of keyboard input and I've tried a number of variations to try and solve this:
- tried issuing XAllowEvents after KeyPress and KeyRelease, passing AsyncKeyboard, SyncKeyboard and ReplayKeyboard.
- tried using GrabKey with AnyKey, AnyModifier on DefaultRootWindow but that triggers an error (x_grabkey BadAccess (attempt to access private resource denied ...))

Any comments/suggestions would be greatly appreciated!



int main(int argc, char **argv)
{
Display *dpy;
int quit = 0;

if((dpy = XOpenDisplay(NULL)) == NULL) {
perror(argv[0]);
exit(1);
}

XGrabKeyboard(dpy, DefaultRootWindow(dpy),
False, GrabModeAsync, GrabModeAsync, CurrentTime);

while(!quit) {
XEvent ev;

XNextEvent(dpy, &ev);

switch (ev.type) {
case KeyPress:
char *s;
unsigned int kc;

kc = ((XKeyPressedEvent*)&ev)->keycode;
s = XKeysymToString(XKeycodeToKeysym(dpy, kc, 0));

if(s) printf("KEY: %s\n", s);
if(!strcmp(s, "q")) quit=~0;
}
}

XUngrabKeyboard(dpy, CurrentTime);

if (XCloseDisplay(dpy)) {
perror(argv[0]);
exit(1);
}

return 0;
}

MK27
05-18-2010, 11:52 AM
Hi there,

How do I passively capture keyboard input from a terminal program without locking out the system?

For one thing, don't use Xlib to do it. Is this a program you are writing? If so, use libtermcap or ncurses. If not, hmm, google "keylogger".

belnac
05-18-2010, 12:10 PM
For one thing, don't use Xlib to do it. Is this a program you are writing? If so, use libtermcap or ncurses. If not, hmm, google "keylogger".

Thanks for your reply. First off, this isn't a keylogger at all :D

This is a program I'm writing as an introduction to Linux programming (my background is in Win32.) Its aim is to:
- run as a daemon (already done)
- capture keyboard input
- produce a sound (from a headerless uncompressed sound file) once a key is pressed via ALSA (already done)

This is why I thought of interfacing directly with X11 for keyboard capture. Was that a wrong design call?

MK27
05-18-2010, 01:00 PM
This is why I thought of interfacing directly with X11 for keyboard capture. Was that a wrong design call?

Just to clarify, a daemon is not a terminal app, just like a terminal app is not a GUI.

So if it is a daemon, this is not a bad idea. I use Xlib in a daemon to flash the keyboard LEDS in different patterns as alerts -- but I've never tried to capture all keyboard input. Unfortunately, as far as I've noticed nobody else around here uses Xlib at all, so you may not get advice on that but you may get some other ideas. You could probably do this from kernel space too, but kernel programming is even more of a b**ch to research than Xlib :p

I would look into event handling (with X) instead of this grab keyboard thing, obviously it's very assertive, you want a more passive approach. However, I'm going to guess that events from one window do not propagate to the root.

Mostly I'd advise you to sign up on an appropriate mailing list and ask there:

X.Org Wiki - XorgMailingLists (http://www.x.org/wiki/XorgMailingLists)

if anyone can help, it will be those folks.