commit 42380f62ebebefc94eb986343d6d91b1b6106ed5
Author:     Max Schillinger <[email protected]>
AuthorDate: Sun Jun 13 22:27:57 2021 +0200
Commit:     Hiltjo Posthuma <[email protected]>
CommitDate: Sun Jun 13 22:33:03 2021 +0200

    allow neutralizing a key modifier by applying the same modifier again
    
    svkbd allows you to create keys for symbols of the second (=shift) layer by 
defining them with a modifier included, like:
    
        { "|", "|", XK_backslash, 1, XK_Shift_L },
    
    This key creates a pipe symbol by sending shift + backslash. But 
unfortunately, this way you can't emit get the original symbol (backslash) 
anymore. So you still need a separate key for typing a backslash, wasting 
precious space on the screen.
    
    The appended patch fixes this by allowing to neutralize the shift by 
tapping this key with shift. It works both by tapping first shift, then the 
pipe key on the on-screen keyboard, or by clicking the pipe key with the middle 
mouse button (assuming XK_Shift_L is set as the button 2 mod).
    
    This way you can create a "flipped" backslash/pipe key:
    
        { "|", "\\", XK_backslash, 1, XK_Shift_L },
    
    This patch works equally for AltGr symbols in a `de`-based layout. For 
example:
    
        { "~", "+", XK_plus, 1, XK_ISO_Level3_Shift },
    
    (In the German QWERTZ layout, you enter "~" with AltGr-"+".)
    
    Best regards,
    Max
    
    Signed-off-by: Maarten van Gompel <[email protected]>

diff --git a/svkbd.c b/svkbd.c
index f9b951d..61778c6 100644
--- a/svkbd.c
+++ b/svkbd.c
@@ -198,16 +198,19 @@ buttonpress(XEvent *e)
        if (!(k = findkey(ev->x, ev->y)))
                return;
 
-       if (k->modifier) {
-               mod = k->modifier;
-       } else {
-               for (i = 0; i < LENGTH(buttonmods); i++) {
-                       if (ev->button == buttonmods[i].button) {
-                               mod = buttonmods[i].mod;
-                               break;
-                       }
+       for (i = 0; i < LENGTH(buttonmods); i++) {
+               if (ev->button == buttonmods[i].button) {
+                       mod = buttonmods[i].mod;
+                       break;
                }
        }
+
+       if (k->modifier) {
+               if (mod == k->modifier)
+                       mod = 0;
+               else
+                       mod = k->modifier;
+       }
        press(k, mod);
 }
 
@@ -231,7 +234,9 @@ buttonrelease(XEvent *e)
        if (ev->x < 0 || ev->y < 0) {
                unpress(NULL, mod);
        } else if ((k = findkey(ev->x, ev->y))) {
-               if (k->modifier)
+               if (k->modifier == mod)
+                       unpress(k, 0);
+               else if (k->modifier)
                        unpress(k, k->modifier);
                else
                        unpress(k, mod);
@@ -564,6 +569,7 @@ void
 unpress(Key *k, KeySym buttonmod)
 {
        int i;
+       Bool neutralizebuttonmod = False;
 
        if (k != NULL) {
                switch(k->keysym) {
@@ -589,10 +595,13 @@ unpress(Key *k, KeySym buttonmod)
                /* simulate the press event, as we postponed it earlier in 
press() */
                for (i = 0; i < numkeys; i++) {
                        if (keys[i].pressed && IsModifierKey(keys[i].keysym)) {
-                               simulate_keypress(keys[i].keysym);
+                               if (keys[i].keysym == buttonmod)
+                                       neutralizebuttonmod = True;
+                               else
+                                       simulate_keypress(keys[i].keysym);
                        }
                }
-               if (buttonmod) {
+               if (buttonmod && !neutralizebuttonmod) {
                        simulate_keypress(buttonmod);
                }
                simulate_keypress(k->keysym);
@@ -615,14 +624,15 @@ unpress(Key *k, KeySym buttonmod)
                }
        }
 
-       if (buttonmod) {
+       if (buttonmod && !neutralizebuttonmod) {
                simulate_keyrelease(buttonmod);
        }
 
        if ((k == NULL) || (!IsModifierKey(k->keysym))) {
                for (i = 0; i < numkeys; i++) {
                        if (keys[i].pressed && IsModifierKey(keys[i].keysym)) {
-                               simulate_keyrelease(keys[i].keysym);
+                               if (!(keys[i].keysym == buttonmod && 
neutralizebuttonmod))
+                                       simulate_keyrelease(keys[i].keysym);
                                keys[i].pressed = 0;
                                drawkey(&keys[i]);
                        }

Reply via email to