#include #include #include #include #include #include #include #include #include static Atom atom_wm_protocols; static Atom atom_wm_delete; static Atom atom_wm_state; static Atom atom_wm_fullscreen; static Display *dpy; static Window win; static GC gc; static XIM im; static XIC ic; static void set_fullscreen() { XEvent e = { 0 }; e.type = ClientMessage; e.xclient.window = win; e.xclient.message_type = atom_wm_state; e.xclient.format = 32; e.xclient.data.l[0] = 1; e.xclient.data.l[1] = atom_wm_fullscreen; e.xclient.data.l[2] = 0; XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureNotifyMask, &e); } static int preedit_start_cb(XIC ic, XPointer client_data, XPointer p) { printf("start preedit\n"); return -1; } static int preedit_stop_cb(XIC ic, XPointer client_data, XPointer p) { printf("stop preedit\n"); return 0; } static int preedit_draw_cb(XIC ic, XPointer client_data, XIMPreeditDrawCallbackStruct *s) { printf("draw preedit %d'%s'\n", s->text->length, s->text->string.multi_byte); return 0; } int main(int argc, char ** argv) { bool quit = false; setlocale(LC_ALL, ""); XSetLocaleModifiers("@im=xmim"); char *nl = nl_langinfo(CODESET); printf("codeset %s\n", nl); dpy = XOpenDisplay(NULL); assert(dpy); int scr = DefaultScreen(dpy); atom_wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", True); atom_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", True); atom_wm_state = XInternAtom(dpy, "_NET_WM_STATE", True); atom_wm_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", True); win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 0, 0, 400, 400, 0, WhitePixel(dpy, scr), WhitePixel(dpy, scr)); im = XOpenIM(dpy, NULL, NULL, NULL); assert(im); XIMStyles *xim_styles = NULL; if (XGetIMValues(im, XNQueryInputStyle, &xim_styles, NULL) == 0) { printf("styles: (%u)\n", xim_styles->count_styles); for (int i = 0; i < xim_styles->count_styles; i++) { const XIMStyle style = xim_styles->supported_styles[i]; printf(" style %lu\n", style); } } XIMCallback preedit_start = { NULL, (XIMProc) preedit_start_cb }; XIMCallback preedit_stop = { NULL, (XIMProc) preedit_stop_cb }; XIMCallback preedit_draw = { NULL, (XIMProc) preedit_draw_cb }; XVaNestedList preedit_list = XVaCreateNestedList(0, XNPreeditStartCallback, &preedit_start, XNPreeditDoneCallback, &preedit_stop, XNPreeditDrawCallback, &preedit_draw, NULL); ic = XCreateIC(im, XNInputStyle, XIMPreeditCallbacks | XIMStatusNothing, XNClientWindow, win, XNFocusWindow, win, XNPreeditAttributes, preedit_list, NULL); assert(ic); XGCValues gc_values; gc = XCreateGC(dpy, win, 0, &gc_values); unsigned long im_event_mask; XGetICValues(ic, XNFilterEvents, &im_event_mask, NULL); printf("im event mask 0x%lx\n", im_event_mask); im_event_mask |= KeyPressMask | KeyReleaseMask | ButtonPressMask | FocusChangeMask | ClientMessage; XSelectInput(dpy, win, im_event_mask); XSetWMProtocols(dpy, win, &atom_wm_delete, 1); set_fullscreen(); XMapWindow(dpy, win); while (!quit) { XEvent e; XNextEvent(dpy, &e); if (XFilterEvent(&e, None)) { continue; } switch (e.type) { case KeyPress: { printf("key press\n"); KeySym keysym; Status status; int buflength; static int bufsize = 16; static char *buf; if (buf == NULL) { buf = malloc(bufsize + 1); assert(buf); } buflength = Xutf8LookupString(ic, &e.xkey, buf, bufsize, &keysym, &status); if (status == XBufferOverflow) { bufsize = buflength; buf = realloc(buf, bufsize + 1); assert(buf); buflength = Xutf8LookupString(ic, &e.xkey, buf, bufsize, &keysym, &status); } switch(status) { case XLookupKeySym: printf("keysim(0x%lx)\n", keysym); break; case XLookupBoth: printf("keysim(0x%lx)+", keysym); // Fallthrough case XLookupChars: buf[buflength] = '\0'; printf("string(%d'%s')\n", buflength, buf); break; case XLookupNone: printf("none\n"); break; default: printf("weirdo\n"); break; } } break; case KeyRelease: printf("key release\n"); break; case ButtonPress: printf("button press\n"); break; case FocusIn: printf("focus in\n"); XSetICFocus(ic); break; case FocusOut: printf("focus out\n"); XUnsetICFocus(ic); break; case ClientMessage: printf("client message\n"); if (e.xclient.message_type == atom_wm_protocols) { if (e.xclient.data.l[0] == atom_wm_delete) { quit = true; } } break; default: printf("unknown event\n"); break; } } XFreeGC(dpy, gc); XDestroyIC(ic); XCloseIM(im); XDestroyWindow(dpy, win); XFlush(dpy); XCloseDisplay(dpy); return EXIT_SUCCESS; }