Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
410 views
in Technique[技术] by (71.8m points)

c - How can I get the keyboard state in Linux?

I want to check if the user pressed down the Shift key when the program starts. (That means, press down the Shift key before the program is started) It's a simple console program, nothing related to X.

This maybe similar to the Win32 GetKeyboardState() function.

I want to know whether I can do this and how, but not any pros and cons with accessing the terminal directly.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think there would be a way to do this. The thing is that you would have to read directly from the keyboard device. You would not be getting input from the terminal. I have the same problem. I have a program that runs (in the background) and I want to know if the user is holding down the shift key.

I believe this is possible and a place to start might be /dev/input/by-path/*-kbd.

This file does give input every time a key is pressed or reptadly if it is held down so it might be worth a look. (Try cat /dev/input/by-path/*-kbd)

If you do figure this out I would love to hear how you did it.

EDIT: I have found the solution

I have figured out how do do this. My program is as follows:

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

#include <linux/input.h>

void usage ( int argc, char *argv[] )
{
    printf("Usage:
%s key

valid keys are:
lshift- Left Shift key
" , 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

}

The info message is lacking (I'm too lazy). But essentially the first argument is compared to a list of keys and the appropriate key identifier is used. It returns true if the key is pressed and false if not.

Please Note

You will need to change the name of they keyboard device. I do not know of a way to find the default keyboard device. (if you know I would love to hear ;) )

This works beautifully: I use it to start the autostart of Xorg if I hold down the shift key.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...