Use X Input Methods for keyboard handling. - sam - An updated version of the sam text editor.
(HTM) git clone git://vernunftzentrum.de/sam.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) LICENSE
---
(DIR) commit 5d68a20e2050958499f4a6a706403d0e89a3e434
(DIR) parent 64ca870b0f576d609030cee84808d195d57b5009
(HTM) Author: Rob King <jking@deadpixi.com>
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(-)
---
(DIR) 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.
(DIR) 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, XSetWindowAttributes *attrs)
keypermod = modmap->max_keypermod;
Resize(w);
+
+ xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+ XNClientWindow, XtWindow(w), XNFocusWindow, XtWindow(w), NULL);
+ 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) - 1, &len);
+
+ 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 && modmap) {
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;
(DIR) 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, char **fallbacks)
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, &xkbminor)){
- 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, XkbAllControlsMask, xkb)){
- fprintf(stderr, "could not initialize keyboard\n");
- exit(EXIT_FAILURE);
- }
-
- if (XkbGetUpdatedMap(_dpy, XkbKeyTypesMask | XkbKeySymsMask | XkbModifierMapMask, xkb) != Success){
- 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 : getenv("FONT") ? getenv("FONT") : "monospace");