Cambiar el estado de los leds del teclado, desde una sesión X, sin acceso de root

10

Estoy tratando de forzar el bloqueo del led. xsetno funciona para mí, así que estoy tratando de usarlo setleds.

En una consola gráfica, este comando devuelve:

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

En una terminal virtual, funciona, sin embargo, el efecto es local en esa terminal virtual. Por lo que entiendo, corriendo

> setleds -L +caps < /dev/tty1

desde una terminal virtual (mi servidor X está sentado en tty1) debería funcionar. Sin embargo, esto requiere acceso de root.

¿Hay alguna forma de enviar un comando a la consola subyacente a un servidor X, ya sea desde dicho servidor x o desde otro VT, sin root?

Editar: a partir de una sugerencia de Mark Plotnik, y en base al código encontrado aquí , escribí y compilé lo siguiente:

#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;
}

Por lo que Gilles escribió sobre xset, no esperaba que funcionara, pero lo hace ... en cierto sentido: establece el led, pero también establece el estado del bloqueo de mayúsculas. No entiendo completamente todo el código anterior, por lo que es posible que haya cometido un error tonto. Aparentemente, la línea XChangeKeyboardControl...no cambia el comportamiento del programa, y XkbLockModifierses lo que establece el led y el estado del bloqueo de mayúsculas.

T. Verron
fuente
Puede hacer algo como xdotool key Caps_Lockdesde un cliente X autorizado, aunque esto realmente activará el bloqueo de mayúsculas.
Mark Plotnick
@MarkPlotnick El objetivo es no activar CapsLock. ¿Hay alguna manera de desactivar CapsLock sin tocar el led?
T. Verron
Miré la xtermfuente y utiliza una llamada a XChangeKeyboardControl () para configurar o deshabilitar los LED sin afectar el estado de bloqueo de mayúsculas, etc. Entonces, si puede compilar el código C, ese es un enfoque.
Mark Plotnick
@ MarkPlotnick ¿Afecta xterma los leds? Parece una buena idea, editaré la pregunta con mis resultados.
T. Verron
Pude xtermencender el LED ScrollLock enviando la secuencia de escape ESC [3 q, según el archivo ctlseqs.txtque viene con la fuente, pero no pude hacer que los LED Num o CapsLock se iluminaran con los parámetros 1 y 2. Tal vez necesito haz la configuración XKB mencionada en la respuesta. xtermllamadas XChangeKeyboardControlen xtermShowLEDy xtermClearLEDs, pero no llama XkbLockModifiersa ningún lado.
Mark Plotnick

Respuestas:

7

En principio, deberías poder hacerlo con el venerable xsetcomando.

xset led named 'Caps Lock'

o xset led 4para configurar el LED número 4, si su sistema no reconoce los LED por su nombre.

Sin embargo, esto no parece funcionar de manera confiable. En mi máquina, solo puedo configurar Scroll Lock de esta manera, y no soy el único . Esto parece ser una cuestión de configuración de XKB .

La siguiente solución a nivel de usuario debería funcionar (en su mayor parte):

  1. Extraiga su configuración actual de xkb:

    xkbcomp $DISPLAY myconf.xkb
    
  2. Edite el archivo myconf.xkb, reemplazando !allowExplicitcon allowExpliciten los bloques relevantes:

    indicator "Caps Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= Lock;
    };
    indicator "Num Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= NumLock;
    };
    
  3. Cargue el nuevo archivo

    xkbcomp myconf.xkb $DISPLAY
    

Ahora, encender y apagar los leds xsetdebería funcionar. Según el informe de error, no podrá apagar los leds cuando se supone que están encendidos (por ejemplo, si CapsLock está habilitado).

Gilles 'SO- deja de ser malvado'
fuente
¡Gracias! Lo había intentado xsetantes, y de hecho no funciona. Sin embargo, no había visto este informe de error. De todos modos, "Estado: Wontfix resuelto" no es realmente alentador ... La solución allowExplicitprobablemente funcionaría para mí (no necesito apagar el led), pero cambiarlo aún requiere root.
T. Verron
@ T.Verron No necesita ser root para cambiar la configuración de XKB. Puedes llamar xkbcompen cualquier momento. No estoy lo suficientemente familiarizado con XKB para decirle exactamente lo que necesita cambiar (establecer un aspecto específico en lugar de un mapa predefinido completo con XKB es un poco difícil ), pero unix.stackexchange.com/questions/166844/mapping -key-bindings / ... debería tener algunos punteros.
Gilles 'SO- deja de ser malvado'
Oh, buen punto. Bueno, como primer intento, intenté:, xkbcomp $DISPLAY output.xkbluego reemplacé !allowExplicitpor allowExpliciten la indicator "Caps Lock"sección, luego volví a cargar el archivo xkbcomp output.xkb. Hay muchas advertencias y xset no funciona mejor después. Leeré más sobre xkb.
T. Verron
1
Esto me funcionó un poco. Después de importar el archivo modificado, recibí algunos mensajes de error y pude encender los LED, pero otras cosas se estropearon, y no sobrevivió al reinicio. Así que hice un editado /usr/share/X11/xkb/compat/ledcapsy ... / lednum y esto lo hizo permanente.
jtgd
0

Utilizando sed

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

Después de cerrar sesión y volver a iniciarla, el Caps LockLED ahora se puede controlar sin ningún rootprivilegio utilizando los comandos:

$ xset led named 'Caps Lock'
$ xset -led named 'Caps Lock'
Serge Stroobandt
fuente
Pero esto requiere root.
T. Verron
@ T.Verron Solo una vez para cambiar un archivo de configuración sudoy nunca más. Para comprender por qué esto podría ser tan importante para ciertos usuarios, consulte esta vimaplicación .
Serge Stroobandt el
Siendo quien hizo la pregunta hace 3 años, definitivamente entiendo por qué puede ser importante para algunos usuarios (en mi caso, fue evitar el estúpido retraso que tienen los teclados de Apple al activar el bloqueo de mayúsculas, después de reasignar el bloqueo de mayúsculas para controlar). Pero en aquel entonces, necesitaba específicamente una solución sin ningún acceso de root, porque era para una computadora de trabajo. La respuesta aceptada implica unos pocos pasos más, pero funciona sin sudo.
T. Verron
@ T.Verron lo entiendo. Los sistemas compartidos son otro caso en el que esto no funcionaría. No obstante, me gustó la franqueza del último comentarista sobre la respuesta aceptada e hice una sedsola frase.
Serge Stroobandt
0

Una combinación del enfoque sin raíz de @Gilles con la idea de la automatización completa de @Serge_Stroobandt.

Para habilitar el control de los LED de bloqueo de mayúsculas , bloqueo numérico y bloqueo de mayúsculas :

#!/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

Para encender y apagar un 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
fuente