Modifier l'état des voyants du clavier, depuis une session X, sans accès root

10

J'essaie de forcer le verrouillage des majuscules. xsetne fonctionne pas pour moi, donc j'essaie d'utiliser setleds.

Dans une console graphique, cette commande renvoie:

> LANG=C setleds -L +caps
KDGKBLED: Inappropriate ioctl for device
Error reading current flags setting. Maybe you are not on the console?

Dans un terminal virtuel, cela fonctionne, mais l'effet est local sur ce terminal virtuel. D'après ce que je comprends, courir

> setleds -L +caps < /dev/tty1

à partir d'un terminal virtuel (mon serveur X est assis sur tty1) devrait fonctionner. Cependant, cela nécessite un accès root.

Existe-t-il un moyen d'envoyer une commande à la console sous-jacente à un serveur X, que ce soit à partir dudit serveur x ou d'un autre VT, sans root?

Edit: D'après une suggestion de Mark Plotnik, et basé sur le code trouvé ici , j'ai écrit et compilé ce qui suit:

#include <X11/Xlib.h>
#include <X11/XKBlib.h>

#define SCROLLLOCK 1
#define CAPSLOCK 2
#define NUMLOCK 16

void setLeds(int leds) {
   Display *dpy = XOpenDisplay(0);
   XKeyboardControl values;
   values.led_mode = leds & SCROLLLOCK ? LedModeOn : LedModeOff;
   values.led = 3;
   XChangeKeyboardControl(dpy, KBLedMode, &values);
   XkbLockModifiers(dpy, XkbUseCoreKbd, CAPSLOCK | NUMLOCK,
                    leds & (CAPSLOCK | NUMLOCK) );
   XFlush(dpy);
   XCloseDisplay(dpy);
}

int main() {
   setLeds(CAPSLOCK);
   return 0;
}

D'après ce que Gilles a écrit xset, je ne m'attendais pas à ce que cela fonctionne, mais ça le fait ... dans un certain sens: cela définit la LED, mais cela définit également le statut de verrouillage. Je ne comprends pas bien tout le code ci-dessus, donc j'ai peut-être fait une erreur stupide. Apparemment, la ligne XChangeKeyboardControl...ne change pas le comportement du programme, et XkbLockModifiersc'est ce qui définit le statut de la led et du capslock.

T. Verron
la source
Vous pouvez faire quelque chose comme à xdotool key Caps_Lockpartir d'un client X autorisé, bien que cela active le verrouillage des majuscules.
Mark Plotnick
@MarkPlotnick Le but n'est en effet pas d'activer CapsLock. Existe-t-il un moyen de désactiver CapsLock sans toucher au voyant?
T. Verron
J'ai regardé la xtermsource et il utilise un appel à XChangeKeyboardControl () pour définir ou désactiver les LED sans affecter l'état du verrouillage des majuscules, etc. Donc, si vous pouvez compiler du code C, c'est une approche.
Mark Plotnick
@MarkPlotnick Affecte-t-il xtermles leds? Cela semble être une bonne idée, je vais modifier la question avec mes résultats.
T. Verron
J'ai pu xtermallumer la LED ScrollLock en envoyant la séquence d'échappement ESC [3 q, selon le fichier ctlseqs.txtfourni avec la source, mais je n'ai pas pu allumer les LED Num ou CapsLock avec les paramètres 1 et 2. Peut-être que je dois faire la configuration XKB mentionnée dans la réponse. xtermappels XChangeKeyboardControlà xtermShowLEDet xtermClearLEDs, mais ne remet pas XkbLockModifiersnulle part.
Mark Plotnick

Réponses:

7

En principe, vous devriez pouvoir le faire avec la xsetcommande venerable .

xset led named 'Caps Lock'

ou xset led 4pour définir le numéro de LED 4, si votre système ne reconnaît pas les LED par leur nom.

Cependant, cela ne semble pas fonctionner de manière fiable. Sur ma machine, je ne peux que définir le verrouillage du défilement de cette façon, et je ne suis pas le seul . Cela semble être une question de configuration XKB .

La solution de contournement suivante au niveau de l'utilisateur devrait fonctionner (pour la plupart):

  1. Extrayez votre configuration xkb actuelle:

    xkbcomp $DISPLAY myconf.xkb
    
  2. Modifiez le fichier myconf.xkben le remplaçant !allowExplicitpar allowExplicitdans les blocs appropriés:

    indicator "Caps Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= Lock;
    };
    indicator "Num Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= NumLock;
    };
    
  3. Chargez le nouveau fichier

    xkbcomp myconf.xkb $DISPLAY
    

Maintenant, allumer et éteindre les leds xsetdevrait fonctionner. Selon le rapport de bogue, vous ne pourrez pas éteindre les voyants lorsqu'ils sont censés être allumés (par exemple si CapsLock est activé).

Gilles 'SO- arrête d'être méchant'
la source
Merci! J'avais essayé xsetavant, et en effet ça ne marche pas. Je n'avais cependant pas vu ce rapport de bogue. Quoi qu'il en soit, "Status: Resolved Wontfix" n'est pas vraiment encourageant ... La solution de allowExplicitcontournement fonctionnerait probablement pour moi (je n'ai pas besoin d'éteindre le voyant), mais le changer nécessite toujours root.
T. Verron
@ T.Verron Vous n'avez pas besoin d'être root pour changer la configuration XKB. Vous pouvez appeler xkbcompà tout moment. Je ne connais pas suffisamment XKB pour vous dire exactement ce que vous devez changer (définir un aspect spécifique plutôt qu'une carte complète prédéfinie avec XKB est un peu pénible ), mais unix.stackexchange.com/questions/166844/mapping -key-bindings /… devrait avoir quelques pointeurs.
Gilles 'SO- arrête d'être méchant'
Oh, bon point. Eh bien, comme première tentative, j'ai essayé xkbcomp $DISPLAY output.xkb:, puis en remplaçant !allowExplicitpar allowExplicitdans la indicator "Caps Lock"section, puis en rechargeant le fichier avec xkbcomp output.xkb. Il y a beaucoup d'avertissements et xset ne fonctionne pas mieux par la suite. Je vais en lire plus sur xkb.
T. Verron
1
Ce genre de travail a fonctionné pour moi. Après avoir importé le fichier modifié, j'ai reçu des messages d'erreur et j'ai pu allumer les LED, mais d'autres choses ont été gâchées, et il n'a pas survécu à un redémarrage. Je suis donc allé de l'avant avec un montage /usr/share/X11/xkb/compat/ledcapset ... / lednum et cela l'a rendu permanent.
jtgd
0

En utilisant sed

$ sudo sed -i 's|\!allowExplicit|allowExplicit|g' /usr/share/X11/xkb/compat/ledcaps

Après vous être déconnecté et reconnecté, la Caps LockLED peut maintenant être contrôlée sans aucun rootprivilège à l'aide des commandes:

$ xset led named 'Caps Lock'
$ xset -led named 'Caps Lock'
Serge Stroobandt
la source
Mais cela nécessite un root.
T. Verron
@ T.Verron Une seule fois pour changer un fichier de configuration avec sudopuis plus jamais. Pour comprendre pourquoi cela peut être si important pour certains utilisateurs, consultez cette vimapplication .
Serge Stroobandt
Étant celui qui a posé la question il y a 3 ans, je comprends vraiment pourquoi cela peut être important pour certains utilisateurs (dans mon cas, c'était pour contourner le stupide retard des claviers Apple lors de l'activation de capslock, après avoir remappé capslock pour contrôler). Mais à l'époque, j'avais spécifiquement besoin d'une solution sans aucun accès root, car c'était pour un ordinateur de travail. La réponse acceptée implique quelques étapes supplémentaires, mais elle fonctionne sans sudo.
T. Verron
@ T.Verron je comprends. Les systèmes partagés sont un autre cas où cela ne fonctionnerait pas. Néanmoins, j'ai aimé la simplicité du dernier intervenant sur la réponse acceptée et j'en ai fait une sedligne.
Serge Stroobandt
0

Une combinaison de l'approche sans racine de @Gilles avec l'idée d'une automatisation complète par @Serge_Stroobandt.

Pour activer le contrôle des voyants Lock Lock , Num Lock et Shift Lock :

#!/bin/bash
# Enables to control keyboard LEDs that are not available for control by default
xkbcomp $DISPLAY /tmp/my_conf.xkb
cat /tmp/my_conf.xkb | awk -e '
    BEGIN {
        change = 0
    }

    {
        if (change == 1) {
            if ($1 == "!allowExplicit;") {
                gsub("!", "", $0)
            }
            change = 0
        }
        print $0

    }

    /indicator "Caps Lock"/ {
        change = 1
    }
    /indicator "Num Lock"/ {
        change = 1
    }
    /indicator "Shift Lock"/ {
        change = 1
    }
    ' > /tmp/my_conf_modified.xkb
xkbcomp /tmp/my_conf_modified.xkb $DISPLAY

Pour allumer et éteindre une LED:

# Turns the LED on
xset led named 'Caps Lock'

# wait 1s
sleep 1

# Resets the LED to the actual state,
# so it might still be on, if Caps Lock is activated.
xset -led named 'Caps Lock'
hoijui
la source