¿Cómo puedo obtener el estado del teclado en Linux?

5 minutos de lectura

avatar de usuario
Xiè Jìléi

Quiero verificar si el usuario presionó el Cambio tecla cuando se inicia el programa. (Eso significa, presione hacia abajo el Cambio key antes de que se inicie el programa) Es un programa de consola simple, nada relacionado con X.

Esto puede ser similar al Win32 GetKeyboardState() función.

Quiero saber si puedo hacer esto y cómo, pero no los pros y los contras de acceder directamente a la terminal.

  • ¿Qué idioma estás usando?

    – Delan Azabani

    6 de septiembre de 2010 a las 8:13

avatar de usuario
Eres Graciosa

Creo que habría una manera de hacer esto. La cosa es que tendrías que leer directamente desde el dispositivo de teclado. No recibiría información de la terminal. Tengo el mismo problema. Tengo un programa que se ejecuta (en segundo plano) y quiero saber si el usuario mantiene presionada la tecla shift.

Creo que esto es posible y un lugar para comenzar podría ser /dev/input/by-path/*-kbd.

Este archivo proporciona información cada vez que se presiona una tecla o repite si se mantiene presionada, por lo que podría valer la pena echarle un vistazo. (Prueba gato /dev/input/by-path/*-kbd)

Si logras resolver esto, me encantaría saber cómo lo hiciste.

EDITAR: he encontrado la solución

He descubierto cómo hacer esto. Mi programa es el siguiente:

#include <stdlib.h>
#include <stdio.h>

#include <linux/input.h>

void usage ( int argc, char *argv[] )
{
    printf("Usage:\n\t%s key\n\nvalid keys are:\n\tlshift\t- Left Shift key\n" , argv[0]);

    exit(EXIT_FAILURE);
}

int main ( int argc, char *argv[], char *env[] )
{
    if ( argc != 2 )    usage(argc, argv);

    int key;

    if ( strcmp(argv[1], "lshift") == 0 )       key = KEY_LEFTSHIFT;
    else if ( strcmp(argv[1], "rshift") == 0 )  key = KEY_RIGHTSHIFT;
    else if ( strcmp(argv[1], "lalt") == 0 )    key = KEY_LEFTALT;
    else if ( strcmp(argv[1], "ralt") == 0 )    key = KEY_RIGHTALT;
    else if ( strcmp(argv[1], "lctrl") == 0 )   key = KEY_LEFTCTRL;
    else if ( strcmp(argv[1], "rctrl") == 0 )   key = KEY_RIGHTCTRL;


    FILE *kbd = fopen("/dev/input/by-path/platform-i8042-serio-0-event-kbd", "r");

    char key_map[KEY_MAX/8 + 1];    //  Create a byte array the size of the number of keys

    memset(key_map, 0, sizeof(key_map));    //  Initate the array to zero's
    ioctl(fileno(kbd), EVIOCGKEY(sizeof(key_map)), key_map);    //  Fill the keymap with the current keyboard state

    int keyb = key_map[key/8];  //  The key we want (and the seven others arround it)
    int mask = 1 << (key % 8);  //  Put a one in the same column as out key state will be in;

    return !(keyb & mask);  //  Returns true if pressed otherwise false

}

Falta el mensaje de información (soy demasiado perezoso). Pero esencialmente, el primer argumento se compara con una lista de claves y se usa el identificador de clave apropiado. Devuelve verdadero si se presiona la tecla y falso en caso contrario.

Tenga en cuenta

Deberá cambiar el nombre del dispositivo de teclado. No conozco una forma de encontrar el dispositivo de teclado predeterminado. (si sabes me encantaría escuchar 😉 )

Esto funciona muy bien: lo uso para iniciar el inicio automático de Xorg si mantengo presionada la tecla Mayús.

  • Este programa necesita privilegios de root, de lo contrario fallará en mi máquina. Esto se debe a los permisos para el archivo del dispositivo de teclado (por cierto, es lo mismo platform-i8042-serio-0-event-kbd aquí, entonces, ¿quizás al menos todas las PC lo tengan?). Mediante la ejecución sudo xxd /dev/input/by-path/platform-i8042-serio-0-event-kbd Vi que el archivo “crece” por otro sizeof(keymap) cada vez que cambia el estado del teclado.

    – Tomasz Gandor

    23 de julio de 2014 a las 5:20

  • @Youarefunny, esto es increíble. ¡Deberías hacer un paquete con eso!

    – Julien__

    9 oct 2019 a las 20:33

avatar de usuario
MaxLZ

AFAIK, esto no se puede hacer sin Xlib (también conocido como X) sin permisos de nivel raíz. Usar XQueryKeymap() hará lo que quieras. sin embargo, señaló que X no se puede usar. Independientemente, también se requerirá la apertura de la conexión de la pantalla.

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <stdbool.h>
#include <stdio.h>

int main()
{
    Display* dpy = XOpenDisplay(NULL);
    char keys_return[32];
    XQueryKeymap( dpy, keys_return );
    KeyCode kc2 = XKeysymToKeycode( dpy, XK_Shift_L );
    bool bShiftPressed = !!( keys_return[ kc2>>3 ] & ( 1<<(kc2&7) ) );
    printf("Shift is %spressed\n", bShiftPressed ? "" : "not ");
    XCloseDisplay(dpy);
}

He encontrado una forma muy sencilla a través de gtk/gdk.

int main ( int argc, char *argv[], char *env[] )
{
    gtk_init(&argc, &argv);

    GdkModifierType button_state;
    gdk_window_get_pointer(NULL, NULL, NULL, &button_state);
    if(button_state & GDK_CONTROL_MASK) {
        printf("ctrl key is pressed");
    }
}

no puedes

los Cambio La clave no se considera una clave de carácter, por lo que incluso si accede directamente a la terminal, no podrá detectar esta clave.

Tal vez no deberías tener que hacerlo. Imagine, por ejemplo, que está utilizando un teclado de EE. UU. en el que se puede acceder a los números en la fila superior sin modificadores, y también está comprobando el Cambio llave. Las personas con otro diseño de teclado pueden tener que usar Cambio modificadores para acceder a los números. Si su programa reacciona a esto Cambio presione, entonces su programa es básicamente inutilizable. Lo mismo se aplica a otras teclas modificadoras: es posible que detecte algunas de ellas solo después de presionar una tecla de carácter normal. O peor aún, es posible que necesiten usar el Cambio tecla para usar ‘enter’ para ejecutar su programa.

También lo que Cambio clave que desea monitorear? ¿el de la máquina local o el del usuario? recuerde que SSH existe y se usa comúnmente para acceder a un pseudoterminal de forma remota.

Si es root y quiere monitorear el Cambio clave en la máquina local, puede leer los dispositivos evdev para eventos sobre el Cambio llave. Pero esto solo es posible debido a la repetición automática de teclas, por lo que no detectará una Cambio tecla que se presiona justo antes de ejecutar su programa, pero solo unos segundos antes.

Por supuesto, no puede hacer eso en la máquina remota, eso sería una falla de seguridad.

Y de todos modos, ¿por qué querrías hacer eso? ¿No sería una aplicación X lo correcto en su caso?

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad