您必须这样做:
if (XFilterEvent(&ev, win)) continue;
在您的事件循环中。这将运行输入法机制,没有它,您将获得原始X事件。例如,当您按一个重音符号后跟一个字母键,并且不进行调用时
XFilterEvent,您将像往常一样获得两个KeyPress事件。但是,如果您拨打电话,您将获得
三个 事件。有两个原始事件,需要为其
XFilterEvent(&ev,win)返回
True。然后,通过输入法合成了一个事件,针对该事件
XFilterEvent(&ev,win)返回
False。这是第三个事件,其中包含重音字符。
如果您既想要原始事件,又想要通过输入法合成的原始事件,则当然可以使用自己做原始事件处理
continue。
请注意
buf[count] = 0;,为了
buf正确打印(或显式使用长度),您将需要
Xutf8LookupString不对输出进行null终止。
最后,如评论中所述,对于X11的最新版本,您将需要指定对的修改,
XSetLocaleModifiers例如
XSetLocaleModifiers("@im=none"),否则将不会生成额外的事件。这是代码的更正版本:
#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; 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; } screen_num = DefaultScreen(dpy); background = BlackPixel(dpy, screen_num); border = WhitePixel(dpy, screen_num); width = 400; height = 200; win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0,0, width, height, 2, border, background); XSelectInput(dpy, win, ButtonPressMask|StructureNotifyMask|KeyPressMask|KeyReleaseMask); XMapWindow(dpy, win); im = XOpenIM(dpy, NULL, NULL, NULL); if (im == NULL) { fputs("Could not open input methodn", stdout); return 2; } failed_arg = XGetIMValues(im, XNQueryInputStyle, &styles, NULL); if (failed_arg != NULL) { fputs("XIM Can't get stylesn", stdout); return 3; } int i; for (i = 0; i < styles->count_styles; i++) { printf("style %dn", (int)styles->supported_styles[i]); } ic = XCreateIC(im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, NULL); if (ic == NULL) { printf("Could not open ICn"); return 4; } XSetICFocus(ic); 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: %dn", count); if (status==XBufferOverflow) printf("BufferOverflown"); if (count) printf("buffer: %.*sn", count, buf); if (status == XLookupKeySym || status == XLookupBoth) { printf("status: %dn", status); } printf("pressed KEY: %dn", (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: %.*sn", count, buf); printf("released KEY: %dn", (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); }}


