[Xcb] [RFC] xcb/util-keysyms input handling patch

Michael Stapelberg michael+xcb at stapelberg.de
Tue Oct 23 03:47:45 PDT 2012


Hi,

It’s been a week without any news. Does nobody feel up to reviewing this
code and answering my questions? :-)

Michael Stapelberg <michael+xcb at stapelberg.de> writes:

> Hi Peter,
>
> Michael Stapelberg <michael+xcb at stapelberg.de> writes:
>> solve. In case I can confirm that, I’ll happily help with
>> testing/implementing.
> So I wrote some test code which you can find attached. It’s really
> horrible code and I apologize, but it gets the job done. Compile it with
> gcc -o xlib-ih xlib-ih.c -lX11 -lXi
>
> The program opens a window and then grabs the keyboard forever (so you
> might want to run it via SSH on another computer or keep at vt handy for
> killing it). For every XI_KeyPress event, it translates the keycode to a
> keysym and prints the name of that keysym.
>
> I have the following questions about it:
>
> 1. Is using the function XkbTranslateKeyCode appropriate for this? It
>    feels slightly kludgy to use XkbBuildCoreState, but I could not
>    figure out what the correct shift level is for calling
>    XkbKeycodeToKeysym (it does NOT map 1:1 to the KeyPress’s
>    mods.effective in all cases).
>
> 2. Is getting the core keyboard via XKB correct?
>
> 3. To port this code over to XCB, we’d need to implement XInput >= 2.0
>    plus maybe more of XKB (haven’t checked) plus all the code which Xlib
>    provides (especially XkbTranslateKeyCode and dependencies), right?
>
> 4. Assuming that 3 is true, would it be acceptable to implement the bare
>    minimum of XI/XKB to get this working? I’m not interested in
>    implementing full XKB, full Xinput or a full port of additional
>    functions. I just want to correctly get Keysyms for key presses./*
>  * vim:ts=4:sw=4:expandtab
>  */
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> #include <stdbool.h>
> #include <stdint.h>
> #include <err.h>
>
> #include <X11/Xlib.h>
> #include <X11/XKBlib.h>
> #include <X11/extensions/XI.h>
> #include <X11/extensions/XInput2.h>
> #include <X11/extensions/XKB.h>
>
>
> int xi_opcode;
>
> int
> xinput_version(Display  *display)
> {
>     XExtensionVersion   *version;
>     static int vers = -1;
>
>     if (vers != -1)
>         return vers;
>
>     version = XGetExtensionVersion(display, INAME);
>
>     if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
>     vers = version->major_version;
>     XFree(version);
>     }
>
>     /* Announce our supported version so the server treats us correctly. */
>     if (vers >= XI_2_Major)
>     {
>         int maj = 2,
>             min = 2;
>
>         XIQueryVersion(display, &maj, &min);
>     }
>
>     return vers;
> }
>
> static Window create_win(Display *dpy)
> {
>     Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200,
>     200, 0, 0, WhitePixel(dpy, 0));
>     Window subwindow = XCreateSimpleWindow(dpy, win, 50, 50, 50, 50, 0, 0,
>     BlackPixel(dpy, 0));
>
>     XMapWindow(dpy, subwindow);
>     XSelectInput(dpy, win, ExposureMask);
>     return win;
> }
>
> int main() {
>     int event, error;
>
>     Display *display = XOpenDisplay(NULL);
>     if (!display)
>         errx(1, "cannot connect to X11");
>     printf("dpy = %p\n", display);
>
>     if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error))
>         errx(1, "X Input extension not available.\n");
>
>     if (!xinput_version(display))
>         errx(1, "xinput not available\n");
>
>     Window win = create_win(display);
>
>     XMapWindow(display, win);
>
>
>     XSync(display, False);
>
>     usleep(100 * 1000);
>
>     int rc;
>     XIEventMask mask;
>
>     /* Select for motion events */
>     mask.deviceid = XIAllDevices;
>     mask.mask_len = 2;
>     mask.mask = calloc(2, sizeof(char));
>     XISetMask(mask.mask, XI_KeyPress);
>
>     if ((rc = XIGrabDevice(display, 3,  win, CurrentTime, None, GrabModeAsync,
>                            GrabModeAsync, False, &mask)) != GrabSuccess)
>     {
>         fprintf(stderr, "Grab failed with %d\n", rc);
>         return;
>     }
>     free(mask.mask);
>     printf("grabbed\n");
>
>     XEvent *ev = malloc(65535);
>     while (1) {
>         printf("next event\n");
>         XGenericEventCookie *cookie = (XGenericEventCookie*)&ev->xcookie;
>         XNextEvent(display, (XEvent*)ev);
>
>         if (XGetEventData(display, cookie) &&
>             cookie->type == GenericEvent &&
>             cookie->extension == xi_opcode)
>         {
>             XIDeviceEvent *event = cookie->data;
>             if (event->evtype != XI_KeyPress)
>                 continue;
>
>             KeySym ksym;
>             int mods_rtrn;
>             XkbDescPtr desc = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);
>
>             XkbTranslateKeyCode(desc, event->detail, XkbBuildCoreState(event->mods.effective, event->group.effective), &mods_rtrn, &ksym);
>             printf("keysym = %s\n", XKeysymToString(ksym));
>
>         }
>     }
> }
>
>
> -- 
> Best regards,
> Michael

-- 
Best regards,
Michael


More information about the Xcb mailing list