通过X11显示器获取UTF-8输入

我一直在尝试和阅读Internet上的大量资源,试图找到一种从X显示器获取UTF-8键盘(组合)输入的方法。但是我无法使其工作。

我已经尝试过此链接中的示例代码(例如11-4),但没有成功。

我还写了一个简单的示例(如下),试图使其工作。我的简单测试用例是打印一个“é”,这是通过先键入“ a”然后再键入e来实现的。

怎么了?

谢谢,

这是我的示例:

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

}

}

回答:

您必须这样做:

            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;

/* 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);

}

}

以上是 通过X11显示器获取UTF-8输入 的全部内容, 来源链接: utcz.com/qa/409797.html

回到顶部