aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Wettstein <wettstein509@solnet.ch>2011-11-08 20:18:09 +0000
committerUlrich Sibiller <uli42@gmx.de>2016-10-19 21:40:25 +0200
commit4ef27790b18d697aaa4b5cd38d9f896eaeffd469 (patch)
tree97006a76e90f97bf27afee48b05aa92d3a738742
parentb8b885daf7b6b368c8ad7a31dfc89b44f993d21b (diff)
downloadnx-libs-4ef27790b18d697aaa4b5cd38d9f896eaeffd469.tar.gz
nx-libs-4ef27790b18d697aaa4b5cd38d9f896eaeffd469.tar.bz2
nx-libs-4ef27790b18d697aaa4b5cd38d9f896eaeffd469.zip
XIM: Allow modifier releases in compose sequences (#26705)
Currently, only non-modifier keys (actually, keysyms) can be part of a compose sequence, and they are matched against the defined compose sequences at the time the key is pressed. The patch allows to use modifier keys an well, but matches them on key release, and only if no other key has been pressed after the modifier. Releasing a non-matched modifier during an ongoing compose sequence only aborts the sequence if any modifier release would have matched. In particular, if no compose sequences with modifiers are specified, the compose mechanism works exactly as without this patch. Even if modifiers are part of a compose sequence, they are not filtered. This is because modifiers affect the keyboard state no matter what we do here and, therefore, filtering them only could confuse clients. The purpose is this extension to the compose mechanism is to allow to make better use of keys in convenient reach for touch typing. Signed-off-by: Andreas Wettstein <wettstein509@solnet.ch> Signed-off-by: James Cloos <cloos@jhcloos.com> Backported-to-NX-by: Ulrich Sibiller <uli42@gmx.de>
-rw-r--r--nx-X11/lib/X11/imLcFlt.c52
1 files changed, 42 insertions, 10 deletions
diff --git a/nx-X11/lib/X11/imLcFlt.c b/nx-X11/lib/X11/imLcFlt.c
index e4ab3815c..50f4c252a 100644
--- a/nx-X11/lib/X11/imLcFlt.c
+++ b/nx-X11/lib/X11/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: