Use X Input Methods for keyboard handling. - sam - An updated version of the sa… | |
git clone git://vernunftzentrum.de/sam.git | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit 5d68a20e2050958499f4a6a706403d0e89a3e434 | |
parent 64ca870b0f576d609030cee84808d195d57b5009 | |
Author: Rob King <[email protected]> | |
Date: Fri, 19 May 2017 22:21:30 -0500 | |
Use X Input Methods for keyboard handling. | |
Diffstat: | |
doc/sam.1 | 6 ++++++ | |
libXg/gwin.c | 27 ++++++++++++++++++--------- | |
libXg/xtbinit.c | 44 ++++++++----------------------- | |
3 files changed, 35 insertions(+), 42 deletions(-) | |
--- | |
diff --git a/doc/sam.1 b/doc/sam.1 | |
@@ -1118,6 +1118,12 @@ Stores output of shell commands executed by | |
.Xr samrc 5 | |
.Sh BUGS | |
.Pp | |
+The character composition as described in | |
+.Xs "Composed Text Input" | |
+may be overridden or limited by the user's specified input method. | |
+This is not necessarily a bug, | |
+but rather a concession to the user's implied preferences. | |
+.Pp | |
The only human language in which colors may be specified is English. | |
.Pp | |
The only human language in which output is generated is English. | |
diff --git a/libXg/gwin.c b/libXg/gwin.c | |
@@ -106,6 +106,8 @@ WidgetClass gwinWidgetClass = (WidgetClass) &gwinClassRec; | |
static XModifierKeymap *modmap; | |
static int keypermod; | |
+extern XIC xic; | |
+extern XIM xim; | |
static void | |
Realize(Widget w, XtValueMask *valueMask, XSetWindowAttributes *attrs) | |
@@ -119,6 +121,13 @@ Realize(Widget w, XtValueMask *valueMask, XSetWindowAttrib… | |
keypermod = modmap->max_keypermod; | |
Resize(w); | |
+ | |
+ xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, | |
+ XNClientWindow, XtWindow(w), XNFocusWindow, XtWindow(w), N… | |
+ if (!xic){ | |
+ fprintf(stderr, "could not create input context\n"); | |
+ exit(EXIT_FAILURE); | |
+ } | |
} | |
static void | |
@@ -239,6 +248,7 @@ freebindings(void) | |
static void | |
Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
{ | |
+ extern XIC xic; | |
static unsigned char compose[5]; | |
static int composing = -2; | |
int kind = Kraw; | |
@@ -247,7 +257,8 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
KeySym k, mk; | |
Charfunc f; | |
Modifiers md; | |
- char buf[100] = {0}; | |
+ Status s; | |
+ wchar_t buf[32] = {0}; | |
c = 0; | |
len = 0; | |
@@ -255,8 +266,8 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
/* Translate the keycode into a key symbol. */ | |
if(e->xany.type != KeyPress) | |
return; | |
- XkbTranslateKeyCode(xkb, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k); | |
- XkbTranslateKeySym(e->xany.display, &k, e->xkey.state, buf, sizeof(buf) - … | |
+ | |
+ len = XwcLookupString(xic, &e->xkey, buf, 32, &k, &s); | |
/* Check to see if it's a specially-handled key first. */ | |
for (Keymapping *m = keymappings; m; m = m->next){ | |
@@ -288,14 +299,12 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
} | |
} | |
- /* | |
- * The following song and dance is so we can have our chosen | |
+ /* The following song and dance is so we can have our chosen | |
* modifier key behave like a compose key, i.e, press and release | |
* and then type the compose sequence, like Plan 9. We have | |
* to find out which key is the compose key first though. | |
*/ | |
- if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose | |
- && composing == -2 && modmap) { | |
+ if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose && composing == -2 &… | |
minmod = (((GwinWidget)w)->gwin.compose+2)*keypermod; | |
for (c = minmod; c < minmod+keypermod; c++) { | |
XtTranslateKeycode(e->xany.display, | |
@@ -318,7 +327,7 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
/* If we got a lone modifier key, no key, or a key outside of the | |
* representable range, ignore it. | |
*/ | |
- if (IsModifierKey(k) || k == NoSymbol || k > 0xff00) | |
+ if (IsModifierKey(k) || k == NoSymbol || k > 0xff00 || len <= 0) | |
return; | |
/* Check to see if we are in a composition sequence */ | |
@@ -363,7 +372,7 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) | |
f = ((GwinWidget)w)->gwin.gotchar; | |
if(f) | |
- (*f)(c, kind, Tcurrent, 0, 0, NULL); | |
+ (*f)(c? c : buf[0], kind, Tcurrent, 0, 0, NULL); | |
} | |
typedef struct Chordmapping Chordmapping; | |
diff --git a/libXg/xtbinit.c b/libXg/xtbinit.c | |
@@ -39,7 +39,8 @@ | |
#endif | |
/* libg globals */ | |
-XkbDescPtr xkb; | |
+XIM xim; | |
+XIC xic; | |
Bitmap screen; | |
XftFont *font; | |
XftColor fontcolor; | |
@@ -211,38 +212,15 @@ xtbinit(Errfunc f, char *class, int *pargc, char **argv, … | |
atexit(freebindings); | |
atexit(freechords); | |
- int xkbmajor = XkbMajorVersion; | |
- int xkbminor = XkbMinorVersion; | |
- int xkbop = 0; | |
- int xkbevent = 0; | |
- int xkberr = 0; | |
- if (!XkbQueryExtension(_dpy, &xkbop, &xkbevent, &xkberr, &xkbmajor, &xkbmi… | |
- fprintf(stderr, "could not initialize X Keyboard Extension\n"); | |
- exit(EXIT_FAILURE); | |
- } | |
- | |
- int ndevs = 0; | |
- XDeviceInfo *devs = XListInputDevices(_dpy, &ndevs); | |
- if (!devs){ | |
- fprintf(stderr, "could not get input devices\n"); | |
- exit(EXIT_FAILURE); | |
- } | |
- | |
- int keyid = XkbUseCoreKbd; | |
- for (int i = 0; i < ndevs && keyid == XkbUseCoreKbd; i++){ | |
- if (devs[i].use == IsXKeyboard) | |
- keyid = devs[i].id; | |
- } | |
- | |
- xkb = XkbGetKeyboard(_dpy, XkbAllComponentsMask, keyid); | |
- if (xkb == NULL || xkb->geom == NULL || XkbGetControls(_dpy, XkbAllControl… | |
- fprintf(stderr, "could not initialize keyboard\n"); | |
- exit(EXIT_FAILURE); | |
- } | |
- | |
- if (XkbGetUpdatedMap(_dpy, XkbKeyTypesMask | XkbKeySymsMask | XkbModifierM… | |
- fprintf(stderr, "could not get updated keymap\n"); | |
- exit(EXIT_FAILURE); | |
+ if ((xim = XOpenIM(_dpy, NULL, NULL, NULL)) == NULL) { | |
+ XSetLocaleModifiers("@im=local"); | |
+ if ((xim = XOpenIM(_dpy, NULL, NULL, NULL)) == NULL) { | |
+ XSetLocaleModifiers("@im="); | |
+ if ((xim = XOpenIM(_dpy, NULL, NULL, NULL)) == NULL) { | |
+ fprintf(stderr, "could not open input method\n"); | |
+ exit(EXIT_FAILURE); | |
+ } | |
+ } | |
} | |
font = XftFontOpenName(_dpy, DefaultScreen(_dpy), fontspec[0] ? fontspec :… |