Check keypress in C++ on Linux

11,367

Solution 1

I find a simpler way:

#include <X11/Xlib.h>
#include <iostream>
#include "X11/keysym.h"

/**
 *
 * @param ks  like XK_Shift_L, see /usr/include/X11/keysymdef.h
 * @return
 */
bool key_is_pressed(KeySym ks) {
    Display *dpy = XOpenDisplay(":0");
    char keys_return[32];
    XQueryKeymap(dpy, keys_return);
    KeyCode kc2 = XKeysymToKeycode(dpy, ks);
    bool isPressed = !!(keys_return[kc2 >> 3] & (1 << (kc2 & 7)));
    XCloseDisplay(dpy);
    return isPressed;
}

bool ctrl_is_pressed() {
    return key_is_pressed(XK_Control_L) || key_is_pressed(XK_Control_R);
}

int main(int argc, char **argv) {
    std::cout << ctrl_is_pressed() << std::endl;
    return (0);
};

Solution 2

Try this:-

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

int main()
{
    struct termios oldSettings, newSettings;

    tcgetattr( fileno( stdin ), &oldSettings );
    newSettings = oldSettings;
    newSettings.c_lflag &= (~ICANON & ~ECHO);
    tcsetattr( fileno( stdin ), TCSANOW, &newSettings );    

    while ( 1 )
    {
        fd_set set;
        struct timeval tv;

        tv.tv_sec = 10;
        tv.tv_usec = 0;

        FD_ZERO( &set );
        FD_SET( fileno( stdin ), &set );

        int res = select( fileno( stdin )+1, &set, NULL, NULL, &tv );

        if( res > 0 )
        {
            char c;
            printf( "Input available\n" );
            read( fileno( stdin ), &c, 1 );
        }
        else if( res < 0 )
        {
            perror( "select error" );
            break;
        }
        else
        {
            printf( "Select timeout\n" );
        }
    }

    tcsetattr( fileno( stdin ), TCSANOW, &oldSettings );
    return 0;
}

From here

Share:
11,367
Admin
Author by

Admin

Updated on July 24, 2022

Comments

  • Admin
    Admin almost 2 years

    Is there an easy way to check if a key is being pressed so I can loop through that in a thread? Preferred not to use a library and definitely not ncurses. There isn't a single thing working that I have found over the internet.

  • JimR
    JimR almost 11 years
    commonly known as kbhit in windows!os/2!dos land. Keep in mind you have to get the key or this will continue to report there's a keypress available. Call getch() when this indicates a key is ready.
  • domsson
    domsson over 3 years
    Nice, but I assume this will only work if you're in an X environment (in other words, won't work on a pure tty or under Wayland, for example)?
  • gavrilikhin.d
    gavrilikhin.d almost 3 years
    What's the hell is this: !!(keys_return[kc2 >> 3] & (1 << (kc2 & 7)))? Ok, it's some bits manipulating, but where do these magic numbers come from?
  • gavrilikhin.d
    gavrilikhin.d almost 3 years
    Oh, I got it. There's a quick explanation:
  • gavrilikhin.d
    gavrilikhin.d almost 3 years
    keys_return is an array of 32*8 bits, where every bit with the number kc2 is a status of the corresponding key with keycode kc2. Our goal is to convert kc2 to somewhat of coordinates in "two-dimensional array" keys_return. To achieve that, we first need to get correct row by dividing kc2 / 8 (remember each "row" is 8 bits. kc2 >> 3 does the same as kc2 / 8. Then we get "column" kc2 % 8, which is the same as kc2 & 7. Hovewer, since it's a bit, we need to shift 1 to get it.
  • gavrilikhin.d
    gavrilikhin.d almost 3 years
    So, equivalent is keys_return[kc2 / 8] & (1 << (kc2 % 8). Almost like arr[n/8][n%8].