x: fix XIM handling - st - Personal fork of st
 (HTM) git clone git://git.drkhsh.at/st.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 26cdfebf31f024e331429e482b1ee342708888e3
 (DIR) parent cd785755f2e3e3305c7d2556a04423a40bce060a
 (HTM) Author: Quentin Rameau <quinq@fifth.space>
       Date:   Sun,  2 Feb 2020 21:47:19 +0100
       
       x: fix XIM handling
       
       Do not try to set specific IM method, let the user specify it with
       XMODIFIERS.
       
       If the requested method is not available or opening fails, fallback to
       the default input handler and register a handler on the new IM server
       availability signal.
       
       Do the same when the input server is closed and (re)started.
       
       Diffstat:
         M x.c                                 |      68 ++++++++++++++++++++-----------
       
       1 file changed, 44 insertions(+), 24 deletions(-)
       ---
 (DIR) diff --git a/x.c b/x.c
       @@ -146,9 +146,10 @@ static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
        static void xdrawglyph(Glyph, int, int);
        static void xclear(int, int, int, int);
        static int xgeommasktogravity(int);
       -static void ximopen(Display *);
       +static int ximopen(Display *);
        static void ximinstantiate(Display *, XPointer, XPointer);
        static void ximdestroy(XIM, XPointer, XPointer);
       +static int xicdestroy(XIC, XPointer, XPointer);
        static void xinit(int, int);
        static void cresize(int, int);
        static void xresize(int, int);
       @@ -1025,48 +1026,61 @@ xunloadfonts(void)
                xunloadfont(&dc.ibfont);
        }
        
       -void
       +int
        ximopen(Display *dpy)
        {
       -        XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy };
       +        XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy };
       +        XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy };
        
       -        if ((xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
       -                XSetLocaleModifiers("@im=local");
       -                if ((xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
       -                        XSetLocaleModifiers("@im=");
       -                        if ((xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL)
       -                                die("XOpenIM failed. Could not open input device.\n");
       -                }
       -        }
       -        if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &destroy, NULL) != NULL)
       -                die("XSetIMValues failed. Could not set input method value.\n");
       -        xw.xic = XCreateIC(xw.ime.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
       -                           XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL);
       -        if (xw.xic == NULL)
       -                die("XCreateIC failed. Could not obtain input method.\n");
       +        xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL);
       +        if (xw.ime.xim == NULL)
       +                return 0;
       +
       +        if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL))
       +                fprintf(stderr, "XSetIMValues: "
       +                                "Could not set XNDestroyCallback.\n");
        
                xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot,
                                                      NULL);
       +
       +        if (xw.ime.xic == NULL) {
       +                xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle,
       +                                       XIMPreeditNothing | XIMStatusNothing,
       +                                       XNClientWindow, xw.win,
       +                                       XNFocusWindow, xw.win,
       +                                       XNDestroyCallback, &icdestroy,
       +                                       NULL);
       +        }
       +        if (xw.ime.xic == NULL)
       +                fprintf(stderr, "XCreateIC: Could not create input context.\n");
       +
       +        return 1;
        }
        
        void
        ximinstantiate(Display *dpy, XPointer client, XPointer call)
        {
       -        ximopen(dpy);
       -        XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
       -                                        ximinstantiate, NULL);
       +        if (ximopen(dpy))
       +                XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
       +                                                 ximinstantiate, NULL);
        }
        
        void
        ximdestroy(XIM xim, XPointer client, XPointer call)
        {
                xw.ime.xim = NULL;
       -        xw.ime.xic = NULL;
                XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
       -                                        ximinstantiate, NULL);
       +                                       ximinstantiate, NULL);
                XFree(xw.ime.spotlist);
        }
        
       +int
       +xicdestroy(XIC xim, XPointer client, XPointer call)
       +{
       +        xw.ime.xic = NULL;
       +        return 1;
       +}
       +
        void
        xinit(int cols, int rows)
        {
       @@ -1132,7 +1146,10 @@ xinit(int cols, int rows)
                xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
        
                /* input methods */
       -        ximopen(xw.dpy);
       +        if (!ximopen(xw.dpy)) {
       +                XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
       +                                               ximinstantiate, NULL);
       +        }
        
                /* white cursor, black outline */
                cursor = XCreateFontCursor(xw.dpy, mouseshape);
       @@ -1765,7 +1782,10 @@ kpress(XEvent *ev)
                if (IS_SET(MODE_KBDLOCK))
                        return;
        
       -        len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
       +        if (xw.ime.xic)
       +                len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
       +        else
       +                len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
                /* 1. shortcuts */
                for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
                        if (ksym == bp->keysym && match(bp->mod, e->state)) {