aboutsummaryrefslogtreecommitdiff
path: root/libX11/modules/im/ximcp
diff options
context:
space:
mode:
Diffstat (limited to 'libX11/modules/im/ximcp')
-rw-r--r--libX11/modules/im/ximcp/imLcFlt.c52
1 files changed, 42 insertions, 10 deletions
diff --git a/libX11/modules/im/ximcp/imLcFlt.c b/libX11/modules/im/ximcp/imLcFlt.c
index 06aa9980a..a7060903a 100644
--- a/libX11/modules/im/ximcp/imLcFlt.c
+++ b/libX11/modules/im/ximcp/imLcFlt.c
@@ -43,18 +43,17 @@ _XimLocalFilter(Display *d, Window w, XEvent *ev, XPointer client_data)
Xic ic = (Xic)client_data;
KeySym keysym;
static char buf[256];
+ static unsigned prevcode = 0, prevstate = 0;
+ unsigned currstate;
DefTree *b = ic->private.local.base.tree;
DTIndex t;
- Bool braille = False;
+ Bool braille = False, anymodifier = False;
if(ev->xkey.keycode == 0)
return (False);
XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &keysym, NULL);
- if(IsModifierKey(keysym))
- return (False);
-
if(keysym >= XK_braille_dot_1 && keysym <= XK_braille_dot_8) {
if(ev->type == KeyPress) {
ic->private.local.brl_pressed |=
@@ -78,38 +77,71 @@ _XimLocalFilter(Display *d, Window w, XEvent *ev, XPointer client_data)
}
}
- if( (ev->type != KeyPress)
- || (((Xim)ic->core.im)->private.local.top == 0 ) )
+ if(((Xim)ic->core.im)->private.local.top == 0 )
goto emit_braille;
+ currstate = ev->xkey.state;
+ if(ev->type == KeyPress) {
+ prevcode = ev->xkey.keycode;
+ prevstate = currstate;
+
+ if(IsModifierKey(keysym))
+ return(False);
+ prevcode = 0;
+ } else {
+ if(prevcode != ev->xkey.keycode)
+ return False;
+
+ /* For lookup, we use the state at the time when the key was pressed, */
+ /* because this state was not affected by the modifier that is mapped */
+ /* to the key. */
+ ev->xkey.state = prevstate;
+ XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &keysym, NULL);
+ }
+
for(t = ic->private.local.context; t; t = b[t].next) {
+ if(IsModifierKey(b[t].keysym))
+ anymodifier = True;
if(((ev->xkey.state & b[t].modifier_mask) == b[t].modifier) &&
(keysym == b[t].keysym))
break;
}
+ /* Restore the state */
+ ev->xkey.state = currstate;
+
if(t) { /* Matched */
if(b[t].succession) { /* Intermediate */
ic->private.local.context = b[t].succession;
- return(True);
+ return (ev->type == KeyPress);
} else { /* Terminate (reached to leaf) */
ic->private.local.composed = t;
ic->private.local.brl_committed = 0;
/* return back to client KeyPressEvent keycode == 0 */
ev->xkey.keycode = 0;
+ ev->xkey.type = KeyPress;
XPutBackEvent(d, ev);
+ if(prevcode){
+ /* For modifier key releases, restore the event, as we do not */
+ /* filter it. */
+ ev->xkey.type = KeyRelease;
+ ev->xkey.keycode = prevcode;
+ }
/* initialize internal state for next key sequence */
ic->private.local.context = ((Xim)ic->core.im)->private.local.top;
- return(True);
+ return (ev->type == KeyPress);
}
} else { /* Unmatched */
- if(ic->private.local.context == ((Xim)ic->core.im)->private.local.top) {
+ /* Unmatched modifier key releases abort matching only in the case that */
+ /* there was any modifier that would have matched */
+ if((ic->private.local.context == ((Xim)ic->core.im)->private.local.top) ||
+ (ev->type == KeyRelease && !anymodifier)) {
goto emit_braille;
}
/* Error (Sequence Unmatch occured) */
/* initialize internal state for next key sequence */
ic->private.local.context = ((Xim)ic->core.im)->private.local.top;
- return(True);
+ return (ev->type == KeyPress);
}
emit_braille: