Discussion:
Checking for a keypress on Linux ?????
(too old to reply)
Koen
2003-09-11 12:03:59 UTC
Permalink
Hi,

could anyone please tell me how one can check (using C or C++ code)
whether a key was pressed on the keyboard? This is for use with
console based applications that don't have fancy UI, but do need
polling for (or callback on) a keypress on the keyboard. I'm not
talking about getting a character from the input queue, since that
won't work until you press enter...
In the Windows world, this is *very* simple using kbhit() from
conio.h, but I didn't find anything in Linux and of course I must be
able to do it on Linux too!

Koen
Lew Pitcher
2003-09-11 13:07:23 UTC
Permalink
Post by Koen
Hi,
could anyone please tell me how one can check (using C or C++ code)
whether a key was pressed on the keyboard? This is for use with
console based applications that don't have fancy UI, but do need
polling for (or callback on) a keypress on the keyboard.
Typically, if your application is designed to require knowledge of "keypress",
then the application is not designed correctly for Linux.

However, "keypress" knowledge is available through the use of tty-device ioctl()
calls and/or the use of the ncurses API.
Post by Koen
I'm not
talking about getting a character from the input queue, since that
won't work until you press enter...
In the Windows world, this is *very* simple using kbhit()
Two points:
1) Windows was not designed to be a multi-user operating system, and
consequently provides 'features' that can only be used properly on
a single-user OS.
2) Stop thinking about developing Linux programs in the Windows model.
Start thinking about developing Linux programs in the Unix model.
I realize that you'll have to relearn a number of things, but if
you /don't/ learn how to develop under the Unix model, your programs
will be overly complex, easily breakable, and will ultimately either
break the Unix standards or be so convoluted as to be unmaintainable.
Post by Koen
from
conio.h, but I didn't find anything in Linux and of course I must be
able to do it on Linux too!
Koen
--
Lew Pitcher
IT Consultant, Enterprise Technology Solutions
Toronto Dominion Bank Financial Group

(Opinions expressed are my own, not my employers')
Koen
2003-09-12 08:25:07 UTC
Permalink
Post by Lew Pitcher
Typically, if your application is designed to require knowledge of "keypress",
then the application is not designed correctly for Linux.
Now, listen. I'm really fed up with this kind of arrogant comments by
all-knowing Linux guys (I know there are others too, so I won't
generalize).

What you're saying is that an application that uses keypresses to let
a user play a melody on his keyboard (to give an example) is not
something that should be done on Linux. Well, I really hope you can
live with that, but it's 2003, and I can't, OK?

And by the way: this is what someone else posted as a reply to my
post:
"The equivalent to conio.h in unixy systems is the curses library - in
particular the ncurses implementation is popular on linux (this is
what
programs like the bash shell use). You want getch() in no-delay
mode."

So the bash shell is "not designed correctly for Linux" then (your
quote)?
I'm really fed up with this kind of arrogancy, sorry (even if there
might be truth in some of your remarks, I'm not a black-and-white type
of guy).
Post by Lew Pitcher
However, "keypress" knowledge is available through the use of
tty-device ioctl()
Post by Lew Pitcher
calls and/or the use of the ncurses API.
Right. So there was a need after all? Well, well.
Post by Lew Pitcher
1) Windows was not designed to be a multi-user operating system, and
consequently provides 'features' that can only be used properly on
a single-user OS.
Now I'm not following you any longer: a few lines above you say that
it IS possible using the mentioned calls and/or ncurses API...
Post by Lew Pitcher
2) Stop thinking about developing Linux programs in the Windows model.
Start thinking about developing Linux programs in the Unix model.
I realize that you'll have to relearn a number of things, but if
you /don't/ learn how to develop under the Unix model, your
programs
Post by Lew Pitcher
will be overly complex, easily breakable, and will ultimately either
break the Unix standards or be so convoluted as to be
unmaintainable.

OK. Granted in general, but not for the keypress issue.

Really, I can take lots of advice, and I generally like it if people
tell me things to be careful with (that's why I visit newsgroups,
apart from helping out others), but your reply is plain arrogance.
I'm glad I know some other Linux developers that seem to behave
different from you, so I won't generalize this.

Anyway, have a nice life. And thanks anyway for the pointers.

Koen
Thomas Richter
2003-09-12 10:01:36 UTC
Permalink
Hi,
Post by Lew Pitcher
Post by Lew Pitcher
Typically, if your application is designed to require knowledge of
"keypress",
Post by Lew Pitcher
then the application is not designed correctly for Linux.
Now, listen. I'm really fed up with this kind of arrogant comments by
all-knowing Linux guys (I know there are others too, so I won't
generalize).
While I agree with you that this kind of answer is agorrant and
unsuitable, I have to agree that you need to state your problem
clearer. "Keypress" has several abstractions, and dependent on what
*exactly* you want to do, some of them might be more apropriate than
others.
Post by Lew Pitcher
What you're saying is that an application that uses keypresses to let
a user play a melody on his keyboard (to give an example) is not
something that should be done on Linux.
It should be done on Linux, but it should be done in a different
way than "conio.h" and doing that from the shell. A keypress for a console
applications has other semantics than a keypress for a graphical end
user application. Your users won't be happy if they would have to hold
the shell window open and active to play a melody. They would be happy
if there would be a graphical keyboard on the screen that, when activated
by the window manager (say, KDE) plays a melody when the keys are pressed.

In this case, the X11 system (or its various helper libraries) seem to
be much more suitable to solve your problem than to go for the console.
Post by Lew Pitcher
And by the way: this is what someone else posted as a reply to my
"The equivalent to conio.h in unixy systems is the curses library - in
particular the ncurses implementation is popular on linux (this is
what
programs like the bash shell use). You want getch() in no-delay
mode."
So the bash shell is "not designed correctly for Linux" then (your
quote)?
"The bash shell is not designed correctly to play a melody." Yes, I'll
sign that. (-;
Post by Lew Pitcher
I'm really fed up with this kind of arrogancy, sorry (even if there
might be truth in some of your remarks, I'm not a black-and-white type
of guy).
Me, too. (-;

But then, it's better to give backgrounds about the problem you want
to solve than to state the problem "I want a keypress". There is no
single solution that is suitable for all problems, as there is no
concept of "a keypress". There is a concept of "getting a single
character unbuffered from an input stream", which has one concrete
realisation in the console connected to the keyboard, and "get an
X11 keypress event", which is suitable for graphical applications.
Post by Lew Pitcher
Now I'm not following you any longer: a few lines above you say that
it IS possible using the mentioned calls and/or ncurses API...
Yes, but that's maybe not want you want/need.
Post by Lew Pitcher
OK. Granted in general, but not for the keypress issue.
Yes, especially for this issue, I afraid. (-;
Post by Lew Pitcher
Really, I can take lots of advice, and I generally like it if people
tell me things to be careful with (that's why I visit newsgroups,
apart from helping out others), but your reply is plain arrogance.
Yup, no question. /-:

So long,
Thomas
Koen
2003-09-12 22:18:05 UTC
Permalink
Post by Thomas Richter
It should be done on Linux, but it should be done in a different
way than "conio.h" and doing that from the shell. A keypress for a console
applications has other semantics than a keypress for a graphical end
user application. Your users won't be happy if they would have to hold
the shell window open and active to play a melody. They would be happy
if there would be a graphical keyboard on the screen that, when activated
by the window manager (say, KDE) plays a melody when the keys are pressed.
In this case, the X11 system (or its various helper libraries) seem to
be much more suitable to solve your problem than to go for the console.
Just very short:
- I don't want to play a melody on my keyboard at all, it was just an
example of showing what one COULD do with a kbhit-like function
- I never concluded from the mentioned posts that the bash shell is or is
not designed to play a melody
- it seems like there were a lot of people that did exactly get what I was
meaning
- never mind spending more time on this: I got what I wanted and you
probably have much more important things to do than following this thread
I'll try to be clearer next time.
Koen
unknown
2003-09-26 01:14:29 UTC
Permalink
Post by Lew Pitcher
Post by Koen
Hi,
could anyone please tell me how one can check (using C or C++ code)
whether a key was pressed on the keyboard? This is for use with
console based applications that don't have fancy UI, but do need
polling for (or callback on) a keypress on the keyboard.
Typically, if your application is designed to require knowledge of "keypress",
then the application is not designed correctly for Linux.
However, "keypress" knowledge is available through the use of tty-device ioctl()
calls and/or the use of the ncurses API.
Post by Koen
I'm not
talking about getting a character from the input queue, since that
won't work until you press enter...
In the Windows world, this is *very* simple using kbhit()
1) Windows was not designed to be a multi-user operating system, and
consequently provides 'features' that can only be used properly on
a single-user OS.
2) Stop thinking about developing Linux programs in the Windows model.
Start thinking about developing Linux programs in the Unix model.
I realize that you'll have to relearn a number of things, but if
you /don't/ learn how to develop under the Unix model, your programs
will be overly complex, easily breakable, and will ultimately either
break the Unix standards or be so convoluted as to be unmaintainable.
I've read this a couple times and it's not insulting at all!
Lew says how to use ncurses to achieve it and offers a
perspective adjustment that should be thought about.

When I'm eating an orange I don't try to slice it like an apple.
But then some people do don't they.
:)
-Walt

Thanks Lew!


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----

j***@onevista.com
2003-09-11 13:28:52 UTC
Permalink
Post by Koen
Hi,
could anyone please tell me how one can check (using C or C++ code)
whether a key was pressed on the keyboard? This is for use with
console based applications that don't have fancy UI, but do need
polling for (or callback on) a keypress on the keyboard. I'm not
talking about getting a character from the input queue, since that
won't work until you press enter...
In the Windows world, this is *very* simple using kbhit() from
conio.h, but I didn't find anything in Linux and of course I must be
able to do it on Linux too!
Here's some C code:

#include <termios.h>
#include <unistd.h>

struct termios argin, argout;
unsigned char ch = 0;

kbhit()
{
tcgetattr(0,&argin);
argout = argin;
argout.c_lflag &= ~(ICANON);
argout.c_iflag &= ~(ICRNL);
argout.c_oflag &= ~(OPOST);
argout.c_cc[VMIN] = 1;
argout.c_cc[VTIME] = 0;
tcsetattr(0,TCSADRAIN,&argout);
read(0, &ch, 1);
tcsetattr(0,TCSADRAIN,&argin);
}
Koen
2003-09-12 08:29:32 UTC
Permalink
Post by j***@onevista.com
#include <termios.h>
#include <unistd.h>
struct termios argin, argout;
unsigned char ch = 0;
kbhit()
{
tcgetattr(0,&argin);
argout = argin;
argout.c_lflag &= ~(ICANON);
argout.c_iflag &= ~(ICRNL);
argout.c_oflag &= ~(OPOST);
argout.c_cc[VMIN] = 1;
argout.c_cc[VTIME] = 0;
tcsetattr(0,TCSADRAIN,&argout);
read(0, &ch, 1);
tcsetattr(0,TCSADRAIN,&argin);
}
Thanks! I'll try that!
Koen
Ivar Nilsson
2003-09-12 09:29:22 UTC
Permalink
Post by Koen
Hi,
could anyone please tell me how one can check (using C or C++ code)
whether a key was pressed on the keyboard? This is for use with
console based applications that don't have fancy UI, but do need
polling for (or callback on) a keypress on the keyboard. I'm not
talking about getting a character from the input queue, since that
won't work until you press enter...
In the Windows world, this is *very* simple using kbhit() from
conio.h, but I didn't find anything in Linux and of course I must be
able to do it on Linux too!
Here is some code I've used from the net, auther unkown and #include
whatever it needs. It works for me so I don't think more about it...

int kbhit(void)
{
struct timeval tv; fd_set
read_fd; /* Do not wait at all, not even a microsecond */
tv.tv_sec=0;
tv.tv_usec=0; /* Must be done first to initialize read_fd */
FD_ZERO(&read_fd); /* Makes select() ask if input is ready: *
0 is the file descriptor for stdin */
FD_SET(0,&read_fd); /* The first parameter is the number of the *
largest file descriptor to check + 1. */
if(select(1, &read_fd, NULL, /*No writes*/ NULL, /*No exceptions*/
&tv) == -1)
return 0; /* An error occured */

/* read_fd now holds a bit map of files that are *
readable. We test the entry for the standard *
input (file 0). */
if(FD_ISSET(0,&read_fd)) /* Character pending on stdin */
return 1; /* no characters were pending */
return 0;
}


/Ivar
Sam Abu-Nassar
2003-09-23 00:35:20 UTC
Permalink
Post by Koen
Hi,
could anyone please tell me how one can check (using C or C++ code)
whether a key was pressed on the keyboard? This is for use with
console based applications that don't have fancy UI, but do need
polling for (or callback on) a keypress on the keyboard. I'm not
talking about getting a character from the input queue, since that
won't work until you press enter...
In the Windows world, this is *very* simple using kbhit() from
conio.h, but I didn't find anything in Linux and of course I must be
able to do it on Linux too!
Koen
The Curses library was the easiest way I could find to implement
kbhit() in Linux. Although I use a custom library, which gives me
code compatibility in Linux, Windows console, & DOS, the relevant code
below should work for you. The technique is to use getch() in
non-blocking mode to get the next character from the input queue. If
no character (ERR) is returned, then no character is pending. Note,
this code has been used successfully in RedHat 7.x, 8.x, & 9.0.


int My_kbhit( void )
{
char ch;


// Initialize console
initscr();

// Disable buffering to provide input immediately to app
cbreak();

// Put getch into non-blocking mode
nodelay(
stdscr,
TRUE
);

// getch will not echo characters
noecho();

// Get character
ch = getch();

// Restore getch into blocking mode
nodelay(
stdscr,
FALSE
);

// Restore getch echo of characters
noecho();

if (ch == ERR)
{
// Restore console
endwin();

return 0;
}

// Put character back into input queue
ungetch(
ch
);

// Restore console
endwin();

return 1;
}
Loading...