st

fork of suckless's simple terminal
Index Commits Files Refs README LICENSE
commit 26cdfebf31f024e331429e482b1ee342708888e3
parent cd785755f2e3e3305c7d2556a04423a40bce060a
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:
Mx.c | 68++++++++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 44 insertions(+), 24 deletions(-)
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)) {