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.
-
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
-
2This 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
-
6This 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 Answers
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 :)

- 312
- 3
- 15
-
2It 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 – Algoman Mar 10 '19 at 00:15#include #include -
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
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 needThen 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