From 5efb0a5e19b75137b7294b27f4e7878aeb8f0927 Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Mon, 12 Dec 2011 12:23:04 +0100
Subject: libxtrans libX11 libxcb xserver mesa git update 12 dec 2011

---
 libX11/modules/im/ximcp/imLcFlt.c | 52 +++++++++++++++++++++++++++++++--------
 1 file changed, 42 insertions(+), 10 deletions(-)

(limited to 'libX11/modules')

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:
-- 
cgit v1.2.3