Forum bépo

Forum des utilisateurs du bépo

Vous n'êtes pas identifié(e).

#1 31/1/2016 11:49:13

bobo38
Membres
Inscription : 10/4/2013
Messages : 146

[bricolage] modif comportement clavier pour starcraft 2 sous linux

Intro, pourquoi ? diverses ressources sur les raccourcis clavier de starcraft 2

Je joue à Starcraft II (SC II)  à mes heures perdues. Je suis tombé sur pas mal de ressources sur l'optimisation de raccourcis clavier il y a quelques mois. En tant que bépoète, ça m'a pas mal intéressé. Il est possible dans SCII de régler les raccourcis clavier de façon assez souple. Tout ce que j'ai collecté est là :
https://wiki.archlinux.org/index.php/St … s_settings

Des gens ont planché sur des raccourcis clavier ergonomiques pour SCII (https://wiki.archlinux.org/index.php/St … reliminary). La démarche du projet TheCore est hyper intéressante : il s'agit de mettre toutes les touches sous une seule main en minimisant les mouvements à faire (ça vous dit quelque chose ?). Dans leur approche, ils contournent les rangées décalées en penchant les claviers ! J'ai un peu essayé mais c'est tout de même le bordel. Il existe des projets plus conventionnels sans clavier penché.

J'ai adapté/amélioré TheCore lite. L'idée de cette approche est d'avoir :
– les actions sous les doigts forts (index/majeur), avec des places standards
– une touche « intelligente » pour faire l'action la + commune : la touche « espace » sous le pousse
– les groupes et vues utilisant les mêmes touches (annulaire, auriculaire) mais en exploitant les modifieurs de façon astucieuse
– de permettre le « rapid fire » facilement (c'est commun à tous ces arrangements de hotkeys)

Qu'est-ce que le « rapid fire » ?

Il s'agit d'enchainer les actions en gardant une touche appuyée. La touche est utilisée à la fois pour déclencher l'action, et déclencher un clic à l'emplacement de la souris (une fois dans le contexte « action »). En gardant la touche enfoncée on enchaîne alors des cycles action->sélection, ce qui permet de faire pas mal d'actions rapidement.
http://www.teamliquid.net/forum/sc2-str … tkey-trick

On distingue 2 types de « rapid fire » :
– simple touche, possible par défaut sous Linux, il est possible de diminuer le délai avant activation de l'autorepeat, et d'augmenter le nombre de répétitions avec cette commande

xset r rate <delai (ms> <nb_réptitions_par_secondes>

– double touche, impossible avec la gestion du clavier de X.

Le rapid « double touche » est assez énorme. Par exemple on a ça : https://youtu.be/pIbo94IWeu8. Ça a été découvert avec certains claviers sous Windows qui ont un comportement étrange : en maintenant 2 touches enfoncées (pour l'exemple « J » et « K ») on peut obtenir cette série :

jkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjkjk

Dans mon cas j'obtiens :

jkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk

Du coup je ne pas l'utiliser.

Mes essais

J'ai fait des essais avec mon window manager pour intercepter une saisie clavier et la remplacer par 2 caractères. Hier j'ai bossé sur un début de script à base de xev et de xprop. Le soucis de ces approches c'est que ça viole les conditions d'utilisation de Blizzard : toute utilisation de logiciel tiers est considéré comme de la triche, pour prévenir l'utilisation de macro ou autre. Est autoriser tout ce que les pilotes de clavier/souris permettent de faire.

Du coup je me suis mis en quête de trouver là où ça se passe dans X… et de voir si le comportement du pilote peut être modifié.

Avec xev, je me suis rendu compte qu'il a des évènements de KeyPress KeyRelease. Mon idée serait de permettre d'avoir un autorepeat ayant ce comportement :
– quand une touche est maintenue pressée, l'ajouter à un motif à répéter
– sortir la touche du motif à répéter avec relachement de la touche

Il serait facile de définir l'ordre du motif (pour le jeu il ne faudrait pas faire n'importe quoi non plus wink). Celà autoriserait théoriquement l'enchaînement d'autant touches que l'on souhaite. Et ce serait fait au niveau du pilote.

Là où je bloque

Je suis plutôt une bille en C, je n'ai jamais vraiment fait ça et le projet xorg est un sacré sac de nœuds. Pour le moment je fais tout au feeling en téléchargeant les sources ou regardant les headers de bibliothèque à grand coup de grep. J'ai essayé de remonter en analysant le code de la commande "xset" où on trouve une fonction "xkbset_autorepeat"

#ifdef XKB
static void 
xkbset_repeatrate(Display *dpy, int delay, int interval)
{
    XkbDescPtr xkb = XkbAllocKeyboard();

    if (!xkb)
    return;
    XkbGetControls(dpy, XkbRepeatKeysMask, xkb);
    xkb->ctrls->repeat_delay = delay;
    xkb->ctrls->repeat_interval = interval;
    XkbSetControls(dpy, XkbRepeatKeysMask, xkb);
    XkbFreeKeyboard(xkb, 0, True);
}
#endif
$ grep -i modified xset.c
/* Modified by Stephen so keyboard rate is set using XKB extensions */

Les fonctions ont l'air d'être déclarées dans /usr/include/X11/XKBlib.h En remontant le code, si j'ai bien compris, j'ai essentiellement vu comment XKB stockait des paramètres, et les rendait accessibles. J'ai tenté d'autres pistes infructueuses aussi. Ceci-dit je me suis focalisé sur XkbGetControls et XkbSetControls, il faudrait que je retente en remontant par XkbFreeKeyboard.


Dans tous les cas, je me disais que les hackers de clavier de la communauté BÉPO pourraient être intéressés par ces trucs de SCII et ma tentative. Et pourraient peut-être même me filer un coup de main. On va voir dans les commentaires si ça intéresse certains d'entre vous.

Édition: maintenant on voit tout le code de la fonction "xkbset_autorepeat"
Édition bis: correction des fautes de Français…

Dernière modification par bobo38 (31/1/2016 16:17:57)


pour la frappe à l'aveugle, l'idéal c'est de poser ça sur son bureau : l'aide mémoire BÉPO (à plier en 3)

Hors ligne

#2 31/1/2016 15:21:17

Fork Bomb
Admin
Inscription : 12/8/2009
Messages : 204

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

Salut !
Tu devrais aussi copier ça sur ta page du Wiki, si t’en as une.
Ça te ferait une visibilité supplémentaire.


Message tapé en Bépo avec un TypeMatrix 2030 USB smile
They see me trollin', they hatin'

Hors ligne

#3 31/1/2016 15:56:27

bobo38
Membres
Inscription : 10/4/2013
Messages : 146

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

Tu parles de wiki BÉPO ou Archlinux ?

À propos, je viens de trouver où ça se passe : dans le xorg-server pardi ! On trouve cette fonction dans les sources xorg-server-1.18.0/xkb/xkbAccessX.c ; les commentaires ne laissent pas de doute… Par contre ça a l'air codé dans une optique où on ne considère qu'une seule touche à se répéter.

/************************************************************************/
/*									*/
/* AccessXFilterPressEvent						*/
/*									*/
/* Filter events before they get any further if SlowKeys is turned on.	*/
/* In addition, this routine handles the ever so popular magic key	*/
/* acts for turning various accessibility features on/off.		*/
/*									*/
/* Returns TRUE if this routine has discarded the event.		*/
/* Returns FALSE if the event needs further processing.			*/
/*									*/
/************************************************************************/
Bool
AccessXFilterPressEvent(DeviceEvent *event, DeviceIntPtr keybd)
{
    XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
    XkbControlsPtr ctrls = xkbi->desc->ctrls;
    Bool ignoreKeyEvent = FALSE;
    KeyCode key = event->detail.key;
    KeySym *sym = XkbKeySymsPtr(xkbi->desc, key);

    if (ctrls->enabled_ctrls & XkbAccessXKeysMask) {
        /* check for magic sequences */
        if ((sym[0] == XK_Shift_R) || (sym[0] == XK_Shift_L)) {
            xkbi->slowKeyEnableKey = key;
            if (XkbAX_NeedFeedback(ctrls, XkbAX_SlowWarnFBMask)) {
                xkbi->krgTimerActive = _KRG_WARN_TIMER;
                xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 4000,
                                          AccessXKRGExpire, (void *) keybd);
            }
            else {
                xkbi->krgTimerActive = _KRG_TIMER;
                xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 8000,
                                          AccessXKRGExpire, (void *) keybd);
            }
            if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) {
                CARD32 now = GetTimeInMillis();

                if ((now - xkbi->lastShiftEventTime) > 15000)
                    xkbi->shiftKeyCount = 1;
                else
                    xkbi->shiftKeyCount++;
                xkbi->lastShiftEventTime = now;
            }
        }
        else {
            if (xkbi->krgTimerActive) {
                xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL);
                xkbi->krgTimerActive = _OFF_TIMER;
            }
        }
    }

    /* Don't transmit the KeyPress if SlowKeys is turned on;
     * The wakeup handler will synthesize one for us if the user
     * has held the key long enough.
     */
    if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
        xkbAccessXNotify ev;

        /* If key was already pressed, ignore subsequent press events
         * from the server's autorepeat
         */
        if (xkbi->slowKey == key)
            return TRUE;
        ev.detail = XkbAXN_SKPress;
        ev.keycode = key;
        ev.slowKeysDelay = ctrls->slow_keys_delay;
        ev.debounceDelay = ctrls->debounce_delay;
        XkbSendAccessXNotify(keybd, &ev);
        if (XkbAX_NeedFeedback(ctrls, XkbAX_SKPressFBMask))
            XkbDDXAccessXBeep(keybd, _BEEP_SLOW_PRESS, XkbSlowKeysMask);
        xkbi->slowKey = key;
        xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer,
                                       0, ctrls->slow_keys_delay,
                                       AccessXSlowKeyExpire, (void *) keybd);
        ignoreKeyEvent = TRUE;
    }

    /* Don't transmit the KeyPress if BounceKeys is turned on
     * and the user pressed the same key within a given time period
     * from the last release.
     */
    else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) &&
             (key == xkbi->inactiveKey)) {
        if (XkbAX_NeedFeedback(ctrls, XkbAX_BKRejectFBMask))
            XkbDDXAccessXBeep(keybd, _BEEP_BOUNCE_REJECT, XkbBounceKeysMask);
        ignoreKeyEvent = TRUE;
    }

    /* Start repeating if necessary.  Stop autorepeating if the user
     * presses a non-modifier key that doesn't autorepeat.
     */
    if (XkbDDXUsesSoftRepeat(keybd)) {
        if ((keybd->kbdfeed->ctrl.autoRepeat) &&
            ((ctrls->enabled_ctrls & (XkbSlowKeysMask | XkbRepeatKeysMask)) ==
             XkbRepeatKeysMask)) {
            if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats, key)) {
                if (xkbDebugFlags & 0x10)
                    DebugF("Starting software autorepeat...\n");
                if (xkbi->repeatKey == key)
                    ignoreKeyEvent = TRUE;
                else {
                    xkbi->repeatKey = key;
                    xkbi->repeatKeyTimer = TimerSet(xkbi->repeatKeyTimer,
                                                    0, ctrls->repeat_delay,
                                                    AccessXRepeatKeyExpire,
                                                    (void *) keybd);
                }
            }
        }
    }

    /* Check for two keys being pressed at the same time.  This section
     * essentially says the following:
     *
     *  If StickyKeys is on, and a modifier is currently being held down,
     *  and one of the following is true:  the current key is not a modifier
     *  or the currentKey is a modifier, but not the only modifier being
     *  held down, turn StickyKeys off if the TwoKeys off ctrl is set.
     */
    if ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
        (xkbi->state.base_mods != 0) &&
        (XkbAX_NeedOption(ctrls, XkbAX_TwoKeysMask))) {
        xkbControlsNotify cn;

        cn.keycode = key;
        cn.eventType = KeyPress;
        cn.requestMajor = 0;
        cn.requestMinor = 0;
        AccessXStickyKeysTurnOff(keybd, &cn);
    }

    if (!ignoreKeyEvent)
        XkbProcessKeyboardEvent(event, keybd);
    return ignoreKeyEvent;
}    

Le passage sur les stickykeys à la fin a l'air bizarre. Et j'ai déjà réussi à planter 2 émulateurs de terminal en jouant avec la touche « Ctrl » en maintenant un autre touche enfoncée.


pour la frappe à l'aveugle, l'idéal c'est de poser ça sur son bureau : l'aide mémoire BÉPO (à plier en 3)

Hors ligne

#4 31/1/2016 16:05:25

bobo38
Membres
Inscription : 10/4/2013
Messages : 146

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

Le comportement du bousin est documenté ici : http://www.x.org/releases/current/doc/k … d_Controls

On retrouve des infos sur les SlowKeys, BounceKeys et les StickyKeys…


pour la frappe à l'aveugle, l'idéal c'est de poser ça sur son bureau : l'aide mémoire BÉPO (à plier en 3)

Hors ligne

#5 31/1/2016 17:30:55

Fork Bomb
Admin
Inscription : 12/8/2009
Messages : 204

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

bobo38 a écrit :

Tu parles de wiki BÉPO ou Archlinux ?

Du wiki Bépo, mais si tu veux mettre sur le wiki d’Arch rien ne t’en empêche.
À propos, Xorg finira par sauter au profit de Wayland.
Penses-y pour une future mise à jour. smile


Message tapé en Bépo avec un TypeMatrix 2030 USB smile
They see me trollin', they hatin'

Hors ligne

#6 31/1/2016 21:03:52

bobo38
Membres
Inscription : 10/4/2013
Messages : 146

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

Je vais déjà essayer de faire fonctionner le bousin wink J'ai un peu de mal à appréhender ce bout de code… Je ne suis pas sûr de l'intérêt que peut avoir mes explications sur les raccourcis clavier optimisés de Starcraft II pour les bépoètes… Ceci-dit il y a des similitudes dans l'étude de l'optimisation du périphérique de saisie clavier (c'est pour ça que j'ai un peu développé).

Qu'entends-tu par « Ça te ferait une visibilité supplémentaire ? »


pour la frappe à l'aveugle, l'idéal c'est de poser ça sur son bureau : l'aide mémoire BÉPO (à plier en 3)

Hors ligne

#7 31/1/2016 21:33:39

Fork Bomb
Admin
Inscription : 12/8/2009
Messages : 204

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

bobo38 a écrit :

Qu'entends-tu par « Ça te ferait une visibilité supplémentaire ? »

Nous avons trois canaux de communication :
1/ Le forum
2/ Le wiki
3/ Le canal IRC

Ces canaux différents attirent des publics différent. Ce qui sera présent sur le wiki ne sera pas lu par quelqu’un ne lisant que le forum (ou n’allant que sur le chan).
Du coup, mieux vaut multiplier les endroits ou ton didacticiel peut être lu.


Message tapé en Bépo avec un TypeMatrix 2030 USB smile
They see me trollin', they hatin'

Hors ligne

#8 31/1/2016 23:46:47

bobo38
Membres
Inscription : 10/4/2013
Messages : 146

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

OK merci pour les explications

Bon j'ai fait des essais de compilation en commentant tout ce qui avait rapport avec les StickyKeys BounceKeys SlowKeys histoire d'y voir plus clair. J'ai pu avoir un X fonctionnel et un comportement d'autorepeat identique. Ça donne ça pour xkb/xkbAccessX.c

/************************************************************************/
/*									*/
/* AccessXFilterPressEvent						*/
/*									*/
/* Filter events before they get any further if SlowKeys is turned on.	*/
/* In addition, this routine handles the ever so popular magic key	*/
/* acts for turning various accessibility features on/off.		*/
/*									*/
/* Returns TRUE if this routine has discarded the event.		*/
/* Returns FALSE if the event needs further processing.			*/
/*									*/
/************************************************************************/
Bool
AccessXFilterPressEvent(DeviceEvent *event, DeviceIntPtr keybd)
{
    XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
    XkbControlsPtr ctrls = xkbi->desc->ctrls;
    Bool ignoreKeyEvent = FALSE;
    KeyCode key = event->detail.key;
    KeySym *sym = XkbKeySymsPtr(xkbi->desc, key);

    if (ctrls->enabled_ctrls & XkbAccessXKeysMask) {
        /* check for magic sequences */
        if ((sym[0] == XK_Shift_R) || (sym[0] == XK_Shift_L)) {
            xkbi->slowKeyEnableKey = key;
            if (XkbAX_NeedFeedback(ctrls, XkbAX_SlowWarnFBMask)) {
                xkbi->krgTimerActive = _KRG_WARN_TIMER;
                xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 4000,
                                          AccessXKRGExpire, (void *) keybd);
            }
            else {
                xkbi->krgTimerActive = _KRG_TIMER;
                xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 8000,
                                          AccessXKRGExpire, (void *) keybd);
            }
            if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) {
                CARD32 now = GetTimeInMillis();

                if ((now - xkbi->lastShiftEventTime) > 15000)
                    xkbi->shiftKeyCount = 1;
                else
                    xkbi->shiftKeyCount++;
                xkbi->lastShiftEventTime = now;
            }
        }
        else {
            if (xkbi->krgTimerActive) {
                xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL);
                xkbi->krgTimerActive = _OFF_TIMER;
            }
        }
    }
//
//    /* Don't transmit the KeyPress if SlowKeys is turned on;
//     * The wakeup handler will synthesize one for us if the user
//     * has held the key long enough.
//     */
//    if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
//        xkbAccessXNotify ev;
//
//        /* If key was already pressed, ignore subsequent press events
//         * from the server's autorepeat
//         */
//        if (xkbi->slowKey == key)
//            return TRUE;
//        ev.detail = XkbAXN_SKPress;
//        ev.keycode = key;
//        ev.slowKeysDelay = ctrls->slow_keys_delay;
//        ev.debounceDelay = ctrls->debounce_delay;
//        XkbSendAccessXNotify(keybd, &ev);
//        if (XkbAX_NeedFeedback(ctrls, XkbAX_SKPressFBMask))
//            XkbDDXAccessXBeep(keybd, _BEEP_SLOW_PRESS, XkbSlowKeysMask);
//        xkbi->slowKey = key;
//        xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer,
//                                       0, ctrls->slow_keys_delay,
//                                       AccessXSlowKeyExpire, (void *) keybd);
//        ignoreKeyEvent = TRUE;
//    }
//
//    /* Don't transmit the KeyPress if BounceKeys is turned on
//     * and the user pressed the same key within a given time period
//     * from the last release.
//     */
//    else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) &&
//             (key == xkbi->inactiveKey)) {
//        if (XkbAX_NeedFeedback(ctrls, XkbAX_BKRejectFBMask))
//            XkbDDXAccessXBeep(keybd, _BEEP_BOUNCE_REJECT, XkbBounceKeysMask);
//        ignoreKeyEvent = TRUE;
//    }
//

    /* Start repeating if necessary.  Stop autorepeating if the user
     * presses a non-modifier key that doesn't autorepeat.
     */
    if (XkbDDXUsesSoftRepeat(keybd)) {
        if ((keybd->kbdfeed->ctrl.autoRepeat) &&
            ((ctrls->enabled_ctrls & (XkbSlowKeysMask | XkbRepeatKeysMask)) ==
             XkbRepeatKeysMask)) {
            if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats, key)) {
                if (xkbDebugFlags & 0x10)
                    DebugF("Starting software autorepeat...\n");
                if (xkbi->repeatKey == key)
                    ignoreKeyEvent = TRUE;
                else {
                    xkbi->repeatKey = key;
                    xkbi->repeatKeyTimer = TimerSet(xkbi->repeatKeyTimer,
                                                    0, ctrls->repeat_delay,
                                                    AccessXRepeatKeyExpire,
                                                    (void *) keybd);
                }
            }
        }
    }

//    /* Check for two keys being pressed at the same time.  This section
//     * essentially says the following:
//     *
//     *  If StickyKeys is on, and a modifier is currently being held down,
//     *  and one of the following is true:  the current key is not a modifier
//     *  or the currentKey is a modifier, but not the only modifier being
//     *  held down, turn StickyKeys off if the TwoKeys off ctrl is set.
//     */
//    if ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
//        (xkbi->state.base_mods != 0) &&
//        (XkbAX_NeedOption(ctrls, XkbAX_TwoKeysMask))) {
//        xkbControlsNotify cn;
//
//        cn.keycode = key;
//        cn.eventType = KeyPress;
//        cn.requestMajor = 0;
//        cn.requestMinor = 0;
//        AccessXStickyKeysTurnOff(keybd, &cn);
//    }

    if (!ignoreKeyEvent)
        XkbProcessKeyboardEvent(event, keybd);
    return ignoreKeyEvent;
}                               /* AccessXFilterPressEvent */
/************************************************************************/
/*									*/
/* AccessXFilterReleaseEvent						*/
/*									*/
/* Filter events before they get any further if SlowKeys is turned on.	*/
/* In addition, this routine handles the ever so popular magic key	*/
/* acts for turning various accessibility features on/off.		*/
/*									*/
/* Returns TRUE if this routine has discarded the event.		*/
/* Returns FALSE if the event needs further processing.			*/
/*									*/
/************************************************************************/
Bool
AccessXFilterReleaseEvent(DeviceEvent *event, DeviceIntPtr keybd)
{
    XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
    XkbControlsPtr ctrls = xkbi->desc->ctrls;
    KeyCode key = event->detail.key;
    Bool ignoreKeyEvent = FALSE;

//    /* Don't transmit the KeyRelease if BounceKeys is on and
//     * this is the release of a key that was ignored due to
//     * BounceKeys.
//     */
//    if (ctrls->enabled_ctrls & XkbBounceKeysMask) {
//        if ((key != xkbi->mouseKey) && (!BitIsOn(keybd->key->down, key)))
//            ignoreKeyEvent = TRUE;
//        xkbi->inactiveKey = key;
//        xkbi->bounceKeysTimer = TimerSet(xkbi->bounceKeysTimer, 0,
//                                         ctrls->debounce_delay,
//                                         AccessXBounceKeyExpire,
//                                         (void *) keybd);
//    }

//    /* Don't transmit the KeyRelease if SlowKeys is turned on and
//     * the user didn't hold the key long enough.  We know we passed
//     * the key if the down bit was set by CoreProcessKeyboadEvent.
//     */
//    if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
//        xkbAccessXNotify ev;
//        unsigned beep_type;
//
//        ev.keycode = key;
//        ev.slowKeysDelay = ctrls->slow_keys_delay;
//        ev.debounceDelay = ctrls->debounce_delay;
//        if (BitIsOn(keybd->key->down, key) || (xkbi->mouseKey == key)) {
//            ev.detail = XkbAXN_SKRelease;
//            beep_type = _BEEP_SLOW_RELEASE;
//        }
//        else {
//            ev.detail = XkbAXN_SKReject;
//            beep_type = _BEEP_SLOW_REJECT;
//            ignoreKeyEvent = TRUE;
//        }
//        XkbSendAccessXNotify(keybd, &ev);
//        if (XkbAX_NeedFeedback(ctrls, XkbAX_SKRejectFBMask)) {
//            XkbDDXAccessXBeep(keybd, beep_type, XkbSlowKeysMask);
//        }
//        if (xkbi->slowKey == key)
//            xkbi->slowKey = 0;
//    }

    /* Stop Repeating if the user releases the key that is currently
     * repeating.
     */
    if (xkbi->repeatKey == key) {
        xkbi->repeatKey = 0;
    }

    if ((ctrls->enabled_ctrls & XkbAccessXTimeoutMask) &&
        (ctrls->ax_timeout > 0)) {
        xkbi->lastPtrEventTime = 0;
        xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0,
                                  ctrls->ax_timeout * 1000,
                                  AccessXTimeoutExpire, (void *) keybd);
        xkbi->krgTimerActive = _ALL_TIMEOUT_TIMER;
    }
    else if (xkbi->krgTimerActive != _OFF_TIMER) {
        xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL);
        xkbi->krgTimerActive = _OFF_TIMER;
    }

//    /* Keep track of how many times the Shift key has been pressed.
//     * If it has been pressed and released 5 times in a row, toggle
//     * the state of StickyKeys.
//     */
//    if ((!ignoreKeyEvent) && (xkbi->shiftKeyCount)) {
//        KeySym *pSym = XkbKeySymsPtr(xkbi->desc, key);
//
//        if ((pSym[0] != XK_Shift_L) && (pSym[0] != XK_Shift_R)) {
//            xkbi->shiftKeyCount = 0;
//        }
//        else if (xkbi->shiftKeyCount >= 5) {
//            xkbControlsNotify cn;
//
//            cn.keycode = key;
//            cn.eventType = KeyPress;
//            cn.requestMajor = 0;
//            cn.requestMinor = 0;
//            if (ctrls->enabled_ctrls & XkbStickyKeysMask)
//                AccessXStickyKeysTurnOff(keybd, &cn);
//            else
//                AccessXStickyKeysTurnOn(keybd, &cn);
//            xkbi->shiftKeyCount = 0;
//        }
//    }

    if (!ignoreKeyEvent)
        XkbProcessKeyboardEvent(event, keybd);
    return ignoreKeyEvent;

}                               /* AccessXFilterReleaseEvent */

Dans xkb/xkbPrKeyEv.c, qui ressemble à un wrapper permettant d'accéder aux fonctions ci-dessus, j'ai désactivé les conditions pour lancer directement « XkbProcessKeyboardEvent ». Après compilation, l'autorepeat est désactivé. Hypothèse validée.

void
ProcessKeyboardEvent(InternalEvent *ev, DeviceIntPtr keybd)
{

    KeyClassPtr keyc = keybd->key;
    XkbSrvInfoPtr xkbi = NULL;
    ProcessInputProc backup_proc;
    xkbDeviceInfoPtr xkb_priv = XKBDEVICEINFO(keybd);
    DeviceEvent *event = &ev->device_event;
    int is_press = (event->type == ET_KeyPress);
    int is_release = (event->type == ET_KeyRelease);

    /* We're only interested in key events. */
    if (!is_press && !is_release) {
        UNWRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc);
        keybd->public.processInputProc(ev, keybd);
        COND_WRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc,
                                     xkbUnwrapProc);
        return;
    }   

    xkbi = keyc->xkbInfo;

//    /* If AccessX filters are active, then pass it through to
//     * AccessXFilter{Press,Release}Event; else, punt to
//     * XkbProcessKeyboardEvent.
//     *
//     * If AXF[PK]E don't intercept anything (which they probably won't),
//     * they'll punt through XPKE anyway. */
//    if ((xkbi->desc->ctrls->enabled_ctrls & XkbAllFilteredEventsMask)) {
//        if (is_press)
//            AccessXFilterPressEvent(event, keybd);
//        else if (is_release)
//            AccessXFilterReleaseEvent(event, keybd);
//        return;
//    }
//    else {
//        XkbProcessKeyboardEvent(event, keybd);
//    }
    XkbProcessKeyboardEvent(event, keybd);

    return;
}

Le code semble bel et bien écrit pour ne supporter qu'une seule touche en « autorepeat ». On a xkbi (= keybd->key->xkbInfo) qui semble servir d'interface de communication entre les diverses fonctions. xkbi->repeatKey stocke le KeyCode de LA touche qui s'autorepète. Si la touche est relâchée celà passe à 0, en mettant un terme au "timer" qui fait la répétition. Je n'ai pas trop bien saisi l'effet de la saisie d'une nouvelle touche.

En l'état je ne peux pas faire de modif simple « bien sentie », je suis bien trop mauvais en C pour rajouter des variables et comprendre plus que ça le répercussions que ça aurait… sad Je me demande si ça ne serait pas possible de rajouter un tableau de KeyCode qui serait en autorepeat (rempli de 0, si aucun autorepeat ) où le premier 0 serait réécrit en Keycode. On parcourerait le tableau pour voir si le KeyCode correspondant à la touche est dedans, si non on arrête l'autorépétition.


pour la frappe à l'aveugle, l'idéal c'est de poser ça sur son bureau : l'aide mémoire BÉPO (à plier en 3)

Hors ligne

#9 4/2/2016 11:29:55

bobo38
Membres
Inscription : 10/4/2013
Messages : 146

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

Après quelques essais, je suis parvenu à mes fins !! J'arrive à reproduire le comportement voulu avec 2 touches… Il n'y a plus qu'à parvenir à un patch correct, et mettre ça sur la page « Starcraft 2 » du wiki Archlinux.

Ça me fait aussi une bonne base pour implémenter une version « grand luxe »… qui permette d'enchaîner plus de 2 touches facilement.


pour la frappe à l'aveugle, l'idéal c'est de poser ça sur son bureau : l'aide mémoire BÉPO (à plier en 3)

Hors ligne

#10 13/2/2016 09:53:20

bobo38
Membres
Inscription : 10/4/2013
Messages : 146

Re : [bricolage] modif comportement clavier pour starcraft 2 sous linux

J'ai finalement trouvé le temps de publier sur le gitlab de Framasoft :
https://git.framasoft.org/bobo/xkb_repeat/tree/master


pour la frappe à l'aveugle, l'idéal c'est de poser ça sur son bureau : l'aide mémoire BÉPO (à plier en 3)

Hors ligne

Pied de page des forums