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