3

I'm searching how to test if a key is pressed. The test shouldn't block the program. I can use a little library if it is not too heavy, but unfortunately ncurses is too much of a dependency to bring in.

indiv
  • 17,306
  • 6
  • 61
  • 82
Lucas S.
  • 312
  • 3
  • 15
  • this is off-topic because you are asking us for code/tutorial – Irrational Person Jan 15 '15 at 16:43
  • _" I can't use ncurse."_ Why? Anyway, you could have a look at their sources, to get a grip how they're actually doing it. – πάντα ῥεῖ Jan 15 '15 at 16:48
  • @πάνταῥεῖ Probably because it is too heavy? From the question: "I can used little lib if they are not too heavy" – Borgleader Jan 15 '15 at 16:51
  • 2
    This is not off topic. This type of question is exactly what most people use this site for. (I can't imagine it's not a duplicate, though...) – indiv Jan 15 '15 at 16:56
  • Relevant http://stackoverflow.com/questions/27824573/boostasio-read-from-dev-input-event0/27827955#27827955 (the example is with mouse, but Linux Kernel unifies input devices so keyboard would be about the same) – sehe Jan 15 '15 at 17:03
  • 6
    This question is not off-topic. As-is, it's currently just a lazily asked question that doesn't meet the guidelines for a good question. – Rapptz Jan 15 '15 at 17:04

2 Answers2

4

I found a solution :

int khbit() const
{
    struct timeval tv;
    fd_set fds;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    return FD_ISSET(STDIN_FILENO, &fds);
}

void nonblock(int state) const
{
    struct termios ttystate;
    tcgetattr(STDIN_FILENO, &ttystate);

    if ( state == 1)
    {
        ttystate.c_lflag &= (~ICANON & ~ECHO); //Not display character
        ttystate.c_cc[VMIN] = 1;
    }
    else if (state == 0)
    {
        ttystate.c_lflag |= ICANON;
    }
    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}

bool keyState(int key) const //Use ASCII table
{
    bool pressed;
    int i = khbit(); //Alow to read from terminal
    if (i != 0)
    {
        char c = fgetc(stdin);
        if (c == (char) key)
        {
            pressed = true;
        }
        else
        {
            pressed = false;
        }
    }

    return pressed;
}

int main()
{
    nonblock(1);
    int i = 0;
    while (!i)
    {
        if (cmd.keyState(32)) //32 in ASCII table correspond to Space Bar
        {
            i = 1;
        }
    }
    nonblock(0);

    return 0;
}

It works well. Thanks for helping me. I hope it will help someone :)

Lucas S.
  • 312
  • 3
  • 15
  • 2
    It does the job for who's not root, thanks! Just don't forget to `usleep()` a bit should you be actively waiting for a key to be pressed (which is not my case, so I didn't have to), and don't forget to restore the echo state after use: `ttystate.c_lflag |= ICANON | ECHO;` in `nonblock()`. – Shlublu Sep 14 '17 at 14:54
  • Awesome! Thank you very much. Shiublu is right about re-enabling the echo. I want to add, that you need these includes #include #include #include #include – Algoman Mar 10 '19 at 00:15
  • I would also add that the functions can't be const because they modify the environment (g++ 5.4 fails on it). And I prefer this modified keystate function, which just tells you WHICH key was pressed instead of testing IF a SPECIFIC key was pressed: bool keystate(int& key) { if(khbit() == 0) return false; key = fgetc(stdin); return true; } – Algoman Mar 10 '19 at 00:29
0

I don't know what exactly you are looking for.

  • I recently did a Proof-of-Concept reading from "raw" input device nodes here: boost::asio read from /dev/input/event0. The example is with mouse, but Linux Kernel unifies input devices so keyboard would be about the same.

    All you need here is UNIX permissions to open/read the device files (you could create them out-of-/etc-tree if that's more convenient for your deployment style).

    The sample shows full asynchronous processing of events

  • I have used bindings to XTest (libxtst) (actually to send keystrokes); I imagine that this may contain the features you need

  • Then there is XInput which (as far as I can tell) constitute the XOrg way to abstract the "raw" input device streams I described in the first option

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633