diff options
author | Andreas Wettstein <wettstein509@solnet.ch> | 2011-11-08 20:18:09 +0000 |
---|---|---|
committer | Ulrich Sibiller <uli42@gmx.de> | 2016-10-19 21:40:25 +0200 |
commit | 4ef27790b18d697aaa4b5cd38d9f896eaeffd469 (patch) | |
tree | 97006a76e90f97bf27afee48b05aa92d3a738742 /nx-X11 | |
parent | b8b885daf7b6b368c8ad7a31dfc89b44f993d21b (diff) | |
download | nx-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>
Diffstat (limited to 'nx-X11')
-rw-r--r-- | nx-X11/lib/X11/imLcFlt.c | 52 |
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: |