Ignore auto repeat in X11 applications - keyboard

If you press and hold a key in X11 while AutoRepeat is enabled, you continuously receive KeyPress and KeyRelease events. I know that AutoRepeat can be disabled using the function XAutoRepeatOff(), but this changes the setting for the whole X server. Is there a way to either disable AutoRepeat for a single application or to ignore repeated keystrokes?
What I'm looking for is a single KeyPress event when a key is pressed and a single KeyRelease event when a key is released, without interfering with the X server's AutoRepeat setting.
Here's a minimal example to get you going (mostly from the Beginner Xlib Tutorial):
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
Display *dis;
Window win;
XEvent report;
int main ()
{
dis = XOpenDisplay (NULL);
// XAutoRepeatOn(dis);
win = XCreateSimpleWindow (dis, RootWindow (dis, 0), 1, 1, 500, 500,
0, BlackPixel (dis, 0), BlackPixel (dis, 0));
XSelectInput (dis, win, KeyPressMask | KeyReleaseMask);
XMapWindow (dis, win);
XFlush (dis);
while (1)
{
XNextEvent (dis, &report);
switch (report.type)
{
case KeyPress:
fprintf (stdout, "key #%ld was pressed.\n",
(long) XLookupKeysym (&report.xkey, 0));
break;
case KeyRelease:
fprintf (stdout, "key #%ld was released.\n",
(long) XLookupKeysym (&report.xkey, 0));
break;
}
}
return (0);
}

When you receive a key release and the next event is a key press of the same key combination, then it's auto-repeat and the key wasn't acutally released. You can use code like this to peek next event
if (event->type == KeyRelease && XEventsQueued(disp, QueuedAfterReading))
{
XEvent nev;
XPeekEvent(disp, &nev);
if (nev.type == KeyPress && nev.xkey.time == event->xkey.time &&
nev.xkey.keycode == event->xkey.keycode)
{
/* Key wasn’t actually released */
}
}

You can use the XkbSetDetectableAutorepeat function to tell the X server to only send KeyRelease events when the user actually releases the key - when you don't want autorepeat events, then you discard any KeyPress without matching KeyRelease.

For your reference, here's a working minimal example that deletes auto-repeated KeyPress events. Thank you, kralyk!
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
Display *dis;
Window win;
XEvent report;
int main ()
{
dis = XOpenDisplay (NULL);
// XAutoRepeatOn(dis);
win = XCreateSimpleWindow (dis, RootWindow (dis, 0), 1, 1, 500, 500,
0, BlackPixel (dis, 0), BlackPixel (dis, 0));
XSelectInput (dis, win, KeyPressMask | KeyReleaseMask);
XMapWindow (dis, win);
XFlush (dis);
while (1)
{
XNextEvent (dis, &report);
switch (report.type)
{
case KeyPress:
fprintf (stdout, "key #%ld was pressed.\n",
(long) XLookupKeysym (&report.xkey, 0));
break;
case KeyRelease:
{
unsigned short is_retriggered = 0;
if (XEventsQueued(dis, QueuedAfterReading))
{
XEvent nev;
XPeekEvent(dis, &nev);
if (nev.type == KeyPress && nev.xkey.time == report.xkey.time &&
nev.xkey.keycode == report.xkey.keycode)
{
fprintf (stdout, "key #%ld was retriggered.\n",
(long) XLookupKeysym (&nev.xkey, 0));
// delete retriggered KeyPress event
XNextEvent (dis, &report);
is_retriggered = 1;
}
}
if (!is_retriggered)
fprintf (stdout, "key #%ld was released.\n",
(long) XLookupKeysym (&report.xkey, 0));
}
break;
}
}
return (0);
}

You could set a timer when a key is pressed or released and ignore KeyPress and KeyRelease events that occur within the repetition interval.

another approach. it works for me.
char keyz[1024] = {0};
bool physical;
XEvent event, nev;
while (!quit) {
XNextEvent(display, &event);
...
switch(event.type) {
case KeyPress:
physical = (keyz[event.xkey.keycode] == 0);
keyz[event.xkey.keycode] = 1;
keyboard(event.xkey.window, true, event.xkey.keycode, physical);
break;
case KeyRelease:
physical = true;
if (XPending(display)) {
XPeekEvent(display, &nev);
if (nev.type == KeyPress && nev.xkey.time == event.xkey.time
&& nev.xkey.keycode == event.xkey.keycode) physical = false;
}
if (physical) keyz[event.xkey.keycode] = 0;
keyboard(event.xkey.window, false, event.xkey.keycode, physical);
break;
...
}

Here's the solution I came up with.
XEvent event;
while(1)
{
XNextEvent(display, &event);
switch(event.type)
{
// Other cases
case ...:
...
break;
...
// On KeyRelease
case KeyRelease:
{
char keys[32];
XQueryKeymap(display, keys);
if(!(keys[event.xkey.keycode>>3] & (0x1 << (event.xkey.keycode % 8))))
{
// Stuff to do on KeyRelease
...
}
}
break;
// On KeyPress
case KeyPress:
// Stuff to do on KeyPress
...
break;
default:
...
}
}
So, everytime I get a KeyRelease event, I use XQueryKeymap which will copy to keys the bits of pressed keys (8 different keys by char).
For the ones who are not used to work with bitwise operatos and shift operator, here's a simple explanation:
keys[event.xkey.keycode>>3] search for index event.xkey.keycode / 8 using "right shift operator" (that allows for "integer division" by 2, 4, 8, 16 and so on, without type cast to float or double and back to integer).
0x1 << (event.xkey.keycode % 8) does the oposite. It multiplies the value of 0x1 (== 1) by 2 raised to (event.xkey.keycode % 8)
The & bitwise operator between keys[event.xkey.keycode>>3] and 0x1 << (event.xkey.keycode % 8) will compare if the only bit set in the right side operand is set to 1 inside this array index. If so, the key is being pressed.
Finally you just enclose it in (), with a ! right before and if the result becomes true, you're not pressing that key anymore.
One final Note: To use this method, you need to keep feeding the XServer with events. If not, XQueryKeymap will freze until it does (better use with threads).

Related

How to use use XNextEvent, XPeekEvent and XPutBackEvent

I am trying to develop a little Linux application to perform measurements directly on the screen i.e. to measure distances and angles in images, documents etc.
To this end I was inspired by How to listen for mouse events in Linux?
and thought I could use XNextEvent or XPeekEvent and possibly XPutBackEvent.
This program responds nicely to mouse events but since it uses XNextEvent the bucket stops there and the event is not sent to the target window and the mouse becomes useless and if I use XPutBackEvent the same event comes back again.
To fix this I replaced XNextEvent with XPeekEvent, which is supposed to send the event up the ladder. This didn't help but made things worse sending an endless stream of the same event, filtering
out equal events didn't help either.
Thanks in advance for any tip to solve this problem.
The problem is basically that the events do not disappear and I don't know how to get rid of them in order to be able to use the mouse. The code below is copied from
How to listen for mouse events in Linux? and somewhat modified.
#include <stdio.h>
#include <X11/Xlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
char *key_name[] = {
"first",
"second (or middle)",
"third",
"fourth", // :D
"fivth" // :|
};
int main(int argc, char **argv)
{
Display *display;
XEvent xevent,oldevent;
Window window;
long unsigned int buttontime=0;
if( (display = XOpenDisplay(NULL)) == NULL )
return -1;
window = DefaultRootWindow(display);
XAllowEvents(display, AsyncBoth, CurrentTime);
XGrabPointer(display,
window,
1,
//PointerMotionMask |
ButtonPressMask | ButtonReleaseMask ,
GrabModeAsync,
GrabModeAsync,
None,
None,
CurrentTime);
while(1)
{
XNextEvent(display, &xevent);
//XPeekEvent(display, &xevent);
switch (xevent.type) {
/*case MotionNotify:
printf("Mouse move : [%d, %d]\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
break;*/
case ButtonPress:
//if ((buttontime <= xevent.xbutton.time))
{
printf("Button pressed : %s\n", key_name[xevent.xbutton.button - 1]);
printf("timevent %lu\n",xevent.xbutton.time);
printf("timeold %lu\n",buttontime);
buttontime = xevent.xbutton.time;
buttontime++;
}
break;
case ButtonRelease:
printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]);
break;
}
// XPutBackEvent(display, &xevent);
sleep(1);
}
return 0;
}

X11 XGrabPointer, how do I clear all the events before I release the mouse?

I am able to grab the mouse, but my problem is that the mouse events that happen while the mouse is grabbed are just queued, and happen after I release the mouse.
this is the code I have until now:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
XEvent e;
Display* dispaly = XOpenDisplay(NULL);
Window window = XDefaultRootWindow(dispaly);
unsigned int count = 0;
XGrabPointer(dispaly, window, true, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, None, CurrentTime);
while(count < 500000) {
if (XPending(dispaly))
XNextEvent(dispaly, &e);
count++;
printf("%d\n", count);
}
XFlush(dispaly);
XCloseDisplay(dispaly);
scanf("%d", &count);
printf("end\n");
return 0;
}
as you can see, I tried consuming the all the events in numerous ways, like with XPending and XNextEvent, with XFlush, and also with XSync.
No matter what function I tried, all the mouse events I do while the mouse is grabbed just happen after I close the display.
can someone help?
Create window:
#include <stdio.h>
#include <unistd.h>
#include <X11/X.h>
#include <X11/Xlib.h>
int main()
{
Display* disp = XOpenDisplay(NULL);
Window root = XDefaultRootWindow(disp);
int scr = XDefaultScreen(disp);
GC context = XDefaultGC(disp, scr);
ulong fg = BlackPixel(disp, scr); // fg color
ulong bg = WhitePixel(disp, scr); // bg color
int depth = 1;
Window win = XCreateSimpleWindow(disp, root, 0, 0, 50, 50, depth, fg, bg);
long events =
ExposureMask |
ButtonPressMask |
ButtonReleaseMask |
PointerMotionMask;
XSelectInput(disp, win, events);
XMapWindow(disp, win);
XFlush(disp);
unsigned int masks = PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
XGrabPointer(
disp, win, true, masks, GrabModeSync, GrabModeAsync, None, None, CurrentTime
);
Catch pointer events:
XEvent event;
do {
XNextEvent(disp, &event);
switch (event.type) {
case ButtonPress :
printf("pressed %i\n", event.xbutton.button);
break;
case ButtonRelease :
printf("released %i\n", event.xbutton.button);
break;
case MotionNotify :
printf("move x %i y %i\n", event.xmotion.x, event.xmotion.y);
break;
default : break;
}
usleep(1000);
} while (true);
XCloseDisplay(disp);
return 0;
}
Or if you need to capture all events inside the root window, you may use XQueryPointer instead of XNextEvent:
...
Window root_ret;
Window child_ret;
int x_rel, y_rel;
int x_win, y_win;
unsigned int mask;
do {
XQueryPointer(
disp, root,
&root_ret, &child_ret,
&x_rel, &y_rel, &x_win, &y_win,
&mask);
printf("%d %d\n", x_rel, y_rel);
usleep(1000);
) while (true);
...
Information above would be a good start point to yours researches.
If you log out these two lines of code, you can also get mouse events.
unsigned int masks = PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
XGrabPointer(disp, win, 1, masks, GrabModeSync, GrabModeAsync, None, None, CurrentTime);

getch not working without initscr

I gone through the Documentation of NCURSES. I am not getting that if I use getch without initscr then why this program is not working. Is there any other approach to get arrow keys input without clearing screen (that initscr do).
#include <ncurses.h>
#include <unistd.h>
int main()
{
int ch;
//initscr();
//raw();
//keypad(stdscr, TRUE);
//noecho();
while(1)
{
ch = getch();
switch(ch)
{
case KEY_UP:
printw("\nUp Arrow");
break;
case KEY_DOWN:
printw("\nDown Arrow");
break;
case KEY_LEFT:
printw("\nLeft Arrow");
break;
case KEY_RIGHT:
printw("\nRight Arrow");
break;
}
if(ch == KEY_UP)
break;
}
//endwin();
}
Alternatively you may use change the terminal attribute through tcsetattr in termios. If you cycle between the canonical mode (requires new line for the process to begin) and non-canonocal mode (Keypress is more than enough).
The following program works as follows - THe process waits for user input. If up arrow key is pressed, it prints 'Arrow key pressed' and exits. If something else is pressed, it waits for the user to press Enter and then prints the user inpu. Exits after the inut is printed.
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
struct termios oldt, newt;
char ch, command[20];
int oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
while(1)
{
ch = getchar();
if (ch == '\033')
{ printf("Arrow key\n"); ch=-1; break;}
else if(ch == -1) // by default the function returns -1, as it is non blocking
{
continue;
}
else
{
break;
}
}
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{
ungetc(ch,stdin);ith
putchar(ch);
scanf("%s",command);
printf("\n%s\n",command);
return 1;
}
return 0;
}
getch is the same as wgetch(stdscr). It assumes that the screen has been initialized. ncurses (any curses implementation) has to do a couple of things to make wgetch usable:
read the terminal description
initialize the terminal I/O modes
allocate a screen to draw on.
The last is because wgetch does a wrefresh on the window for which it was called, before doing a read.
You could use newterm with filter to avoid clearing the screen, and doing line-oriented input. The filter program in ncurses-examples demonstrates how to do this.
I have a solution without ncurses
You can use simple-getch like this:
t_key keys[] = {
{"[A", K_UP},
{"[B", K_DOWN},
{"[D", K_LEFT},
{"[C", K_RIGHT},
{NULL, K_UNK},
};
int key;
ch_init();
while ((key = ch_get(keys)) != K_BACK)
{
printf("%d\n", key);
}
ch_end();
keys array is a list of escape sequences which will be used, (when you type an arrow key in a terminal, it will write an escape key followed by multiples characters to define the key.)
This sequences may/will change between terminals, you should use termcap to properly set this sequences.

Cannot generate keystroke written to device kernel with input.h Linux

I am trying to generate keystrokes and write them to the kernel in Linux using the input library. I found an example form http://rico-studio.com/linux/read-and-write-to-a-keyboard-device/ and made a little test program. It should just print a bunch of t's but only does this when I strike a key (space for example) myself.
#include <linux/input.h>
#include <linux/uinput.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#define EV_PRESSED 1
#define EV_RELEASED 0
#define EV_REPEAT 2
int main() {
int fd = 0;
/*In my case event3 handles the keyboard. This can be checked typing
* cat /proc/bus/input/devices in the terminal
*/
char *device = "/dev/input/event3";
struct input_event event;
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
if( (fd = open(device, O_RDWR | O_NONBLOCK )) < 0 )
{
printf("not opened "); // Read or Write to device
return 0;
}
for(int i=0;i <500 ;i++)
{
// usleep(1000);
event.type = EV_KEY;
// Press the key down
event.value = EV_PRESSED;
event.code = KEY_T;
write(fd, &event, sizeof(struct input_event));
// usleep(1000);
// Release the key
event.value = EV_RELEASED;
event.code = KEY_T;
write(fd, &event, sizeof(struct input_event));
usleep(100000);
}
close(fd);
return 0;
}
Maybe this key-stroke flushes the memory along with the generated keystrokes for t written to the devices memory? So I am wondering what I am missing to let it generate a keystroke and write it to the kernel all by itself.
If you run xxd /dev/input3 and break apart the output, you can see that the keyboard is also sending EV_SYN, SYN_REPORT events after each key change to mark the end of a grouped set of events. To do the same:
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(fd, &event, sizeof(struct input_event));

Get UTF-8 input with X11 Display

I've been trying and reading lots of resources on the internet, trying to find a way to get an UTF-8 keyboard (composed) input from a X Display. But I could not make it work.
I have tried the example code from this link (exaple 11-4), but no success.
I also have written a simple example (below) to try to make it work. My simple test case is to print an "é", which happens by typing the acute and then the e.
What is wrong?
Thanks,
Here is my example:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <X11/Xlocale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char ** argv)
{
int screen_num, width, height;
unsigned long background, border;
Window win;
XEvent ev;
Display *dpy;
XIM im;
XIC ic;
char *failed_arg;
XIMStyles *styles;
XIMStyle xim_requested_style;
/* First connect to the display server, as specified in the DISPLAY
environment variable. */
if (setlocale(LC_ALL, "") == NULL) {
return 9;
}
if (!XSupportsLocale()) {
return 10;
}
if (XSetLocaleModifiers("") == NULL) {
return 11;
}
dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "unable to connect to display");
return 7;
}
/* these are macros that pull useful data out of the display object */
/* we use these bits of info enough to want them in their own variables */
screen_num = DefaultScreen(dpy);
background = BlackPixel(dpy, screen_num);
border = WhitePixel(dpy, screen_num);
width = 400; /* start with a small window */
height = 200;
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), /* display, parent */
0,0, /* x, y: the window manager will place the window elsewhere */
width, height, /* width, height */
2, border, /* border width & colour, unless you have a window manager */
background); /* background colour */
/* tell the display server what kind of events we would like to see */
XSelectInput(dpy, win, ButtonPressMask|StructureNotifyMask|KeyPressMask|KeyReleaseMask|KeymapStateMask);
/* okay, put the window on the screen, please */
XMapWindow(dpy, win);
im = XOpenIM(dpy, NULL, NULL, NULL);
if (im == NULL) {
fputs("Could not open input method\n", stdout);
return 2;
}
failed_arg = XGetIMValues(im, XNQueryInputStyle, &styles, NULL);
if (failed_arg != NULL) {
fputs("XIM Can't get styles\n", stdout);
return 3;
}
int i;
for (i = 0; i < styles->count_styles; i++) {
printf("style %d\n", styles->supported_styles[i]);
}
ic = XCreateIC(im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, NULL);
if (ic == NULL) {
printf("Could not open IC\n");
return 4;
}
XSetICFocus(ic);
/* as each event that we asked about occurs, we respond. In this
* case we note if the window's shape changed, and exit if a button
* is pressed inside the window */
while(1) {
XNextEvent(dpy, &ev);
switch(ev.type){
case KeymapNotify:
XRefreshKeyboardMapping(&ev.xmapping);
break;
case KeyPress:
{
int count = 0;
KeySym keysym = 0;
char buf[20];
Status status = 0;
count = Xutf8LookupString(ic, (XKeyPressedEvent*)&ev, buf, 20, &keysym, &status);
printf("count: %d\n", count);
if (status==XBufferOverflow)
printf("BufferOverflow\n");
if (count)
printf("buffer: %s\n", buf);
if (status == XLookupKeySym || status == XLookupBoth) {
printf("status: %d\n", status);
}
printf("pressed KEY: %d\n", keysym);
}
break;
case KeyRelease:
{
int count = 0;
KeySym keysym = 0;
char buf[20];
Status status = 0;
count = XLookupString((XKeyEvent*)&ev, buf, 20, &keysym, NULL);
if (count)
printf("in release buffer: %s\n", buf);
printf("released KEY: %d\n", keysym);
}
break;
case ConfigureNotify:
if (width != ev.xconfigure.width
|| height != ev.xconfigure.height) {
width = ev.xconfigure.width;
height = ev.xconfigure.height;
printf("Size changed to: %d by %d", width, height);
}
break;
case ButtonPress:
XCloseDisplay(dpy);
return 0;
}
fflush(stdout);
}
}
You have to do this:
if (XFilterEvent(&ev, win))
continue;
in your event loop. This runs the input method machinery, without it you will get raw X events. For example, when you press a dead accent key followed by a letter key, and do not call XFilterEvent, you will get two KeyPress events as usual. But if you do the call, you will get three events. There are two raw events, for which XFilterEvent(&ev, win) returns True. And then there is one event synthesized by the input method, for which XFilterEvent(&ev, win) returns False. It is this third event that contains the accented character.
If you want both raw events and those synthesized by the input method, you can of course do your own raw event processing instead of continue.
Note you will need buf[count] = 0; in order to print buf correctly (or explicitly use a length), Xutf8LookupString doesn't null-terminate its output.
Finally, as mentioned in the comments, with recent versions of X11 you will need to specify a modify to XSetLocaleModifiers such as XSetLocaleModifiers("#im=none"), otherwise the extra events won't be generated.
Here is a corrected version of the code:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <X11/Xlocale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char ** argv)
{
int screen_num, width, height;
unsigned long background, border;
Window win;
XEvent ev;
Display *dpy;
XIM im;
XIC ic;
char *failed_arg;
XIMStyles *styles;
XIMStyle xim_requested_style;
/* First connect to the display server, as specified in the DISPLAY
environment variable. */
if (setlocale(LC_ALL, "") == NULL) {
return 9;
}
if (!XSupportsLocale()) {
return 10;
}
if (XSetLocaleModifiers("#im=none") == NULL) {
return 11;
}
dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "unable to connect to display");
return 7;
}
/* these are macros that pull useful data out of the display object */
/* we use these bits of info enough to want them in their own variables */
screen_num = DefaultScreen(dpy);
background = BlackPixel(dpy, screen_num);
border = WhitePixel(dpy, screen_num);
width = 400; /* start with a small window */
height = 200;
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), /* display, parent */
0,0, /* x, y: the window manager will place the window elsewhere */
width, height, /* width, height */
2, border, /* border width & colour, unless you have a window manager */
background); /* background colour */
/* tell the display server what kind of events we would like to see */
XSelectInput(dpy, win, ButtonPressMask|StructureNotifyMask|KeyPressMask|KeyReleaseMask);
/* okay, put the window on the screen, please */
XMapWindow(dpy, win);
im = XOpenIM(dpy, NULL, NULL, NULL);
if (im == NULL) {
fputs("Could not open input method\n", stdout);
return 2;
}
failed_arg = XGetIMValues(im, XNQueryInputStyle, &styles, NULL);
if (failed_arg != NULL) {
fputs("XIM Can't get styles\n", stdout);
return 3;
}
int i;
for (i = 0; i < styles->count_styles; i++) {
printf("style %d\n", (int)styles->supported_styles[i]);
}
ic = XCreateIC(im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, NULL);
if (ic == NULL) {
printf("Could not open IC\n");
return 4;
}
XSetICFocus(ic);
/* as each event that we asked about occurs, we respond. In this
* case we note if the window's shape changed, and exit if a button
* is pressed inside the window */
while(1) {
XNextEvent(dpy, &ev);
if (XFilterEvent(&ev, win))
continue;
switch(ev.type){
case MappingNotify:
XRefreshKeyboardMapping(&ev.xmapping);
break;
case KeyPress:
{
int count = 0;
KeySym keysym = 0;
char buf[20];
Status status = 0;
count = Xutf8LookupString(ic, (XKeyPressedEvent*)&ev, buf, 20, &keysym, &status);
printf("count: %d\n", count);
if (status==XBufferOverflow)
printf("BufferOverflow\n");
if (count)
printf("buffer: %.*s\n", count, buf);
if (status == XLookupKeySym || status == XLookupBoth) {
printf("status: %d\n", status);
}
printf("pressed KEY: %d\n", (int)keysym);
}
break;
case KeyRelease:
{
int count = 0;
KeySym keysym = 0;
char buf[20];
Status status = 0;
count = XLookupString((XKeyEvent*)&ev, buf, 20, &keysym, NULL);
if (count)
printf("in release buffer: %.*s\n", count, buf);
printf("released KEY: %d\n", (int)keysym);
}
break;
case ConfigureNotify:
if (width != ev.xconfigure.width
|| height != ev.xconfigure.height) {
width = ev.xconfigure.width;
height = ev.xconfigure.height;
printf("Size changed to: %d by %d", width, height);
}
break;
case ButtonPress:
XCloseDisplay(dpy);
return 0;
}
fflush(stdout);
}
}

Resources