skip to Main Content

Having some app, made with x11 libs, tested for ubuntu.
It takes simple keyboard inputs and outputs corresponding value.
It works fine if application window (ubuntu terminal) is currently open

linux-kbhit.h

#define     ESC     "33"
#define     UP      "33[A"
#define     DOWN    "33[B"
#define     LEFT    "33[D"
#define     RIGHT   "33[C"
#define     A   "a"

void term_setup(void (*sighandler)(int));
void term_restore();
bool kbhit();
bool keydown(const char* key);

linux-kbhit.c

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

#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <termios.h>
#include <sys/ioctl.h>

static struct termios oldtio;
static struct termios curtio;

void term_setup(void (*sighandler)(int)){
    struct sigaction sa;

    /* Save stdin terminal attributes */
    tcgetattr(0, &oldtio);

    if(sighandler){
    /* Make sure we exit cleanly */
        memset(&sa, 0, sizeof(struct sigaction));
        sa.sa_handler = sighandler;
        sigaction(SIGINT, &sa, NULL);
        sigaction(SIGQUIT, &sa, NULL);
        sigaction(SIGTERM, &sa, NULL);
    }

    /* This is needed to be able to tcsetattr() after a hangup (Ctrl-C)
     * see tcsetattr() on POSIX
     */
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = SIG_IGN;
    sigaction(SIGTTOU, &sa, NULL);

    /* Set non-canonical no-echo for stdin */
    tcgetattr(0, &curtio);
    curtio.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(0, TCSANOW, &curtio);
}

void term_restore(){
    /* restore terminal attributes */
    tcsetattr(0, TCSANOW, &oldtio);
}

static char get[4]= {0};
bool kbhit(){
    struct pollfd pfds[1];
    int ret;
    memset(get, 0, sizeof(char) * 4);

    /* See if there is data available */
    pfds[0].fd = 0;
    pfds[0].events = POLLIN;
    ret = poll(pfds, 1, 0);

    /* Consume data */
    if (ret > 0) {
        read(0, get, 3);
        return strlen(get) > 0;
    }
    return false;
}

bool keydown(const char* key){
    return !strcmp(get, key);
}

it works perfect for keyboard inputs for active application, but application purpose is to get all OS key inputs and interpret it for further use

main.c

#include "linux-kbhit.h"
#include "stdio.h"
#include <signal.h>

static sig_atomic_t end = 0;
static void sighandler(int signo)
{
    end = 1;
    printf("good beye!n");
}

int main()
{
    term_setup(sighandler);

    while (!end) {
        if (kbhit()) {
            if (keydown(ESC))
                printf("This is "ESC" button!n");
            if (keydown(UP))
                printf("This is "UP" button!n");
            if (keydown(DOWN))
                printf("This is "DOWN" button!n");
            if (keydown(LEFT))
                printf("This is "LEFT" button!n");
            if (keydown(RIGHT))
                printf("This is "RIGHT" button!n");
            if (keydown(A))
                printf("This is "A" button!n");
        }
    }

    term_restore();

    return 0;
}

I need to get keys from any app within OS (Ubuntu)
How can should I amend the code?

2

Answers


  1. I need to make analog of QuickTextPaste for Ubuntu
    You can make settings:
    if press control + T you get pop up menu, each bullet sends paste of needed command and you can use it
    https://www.softwareok.com/?seite=Microsoft/QuickTextPaste/Screenshot-2

    Login or Signup to reply.
  2. Well, if your application is built using XWindow libraries, you will not be able to control all inputs when you start XWindow connection to the server, as the XWindow keyboard events don’t enter the application through the normal tty input. If the application has the keyboard focus, it doesn’t matter what key you press (ctrl-d, ctrl-c or ctrl-]) to generate EOF, SIGINT or SIGQUIT. As those keys are encoded through the keyboard event manager (through the server tcp/unix socket) and never through the standard input file descriptor.

    BTW, you have some misconceptions in your treatment of the tty termios driver. You say

    This is needed to be able to tcsetattr() after a hangup (Ctrl-C)

    a hangup is what happens when the modem deasserts the DSR modem line and results in a SIGHUP signal (it is generated by the tty driver when the user signals a terminal end of file, and is sent to all processes in the process group controlling the terminal) but you have set the terminal settings to raw mode, and then, no control character processing is made in the tty driver, so the caracters are passed to the process without handling/generating SIGINT, SIGHUP or SIGQUIT (this last, generated normally by Ctrl-], and producing a core dump of the process, if enabled) This (the hangup) is generated by Ctrl-D, and not by Ctrl-C (which normally generates SIGINT, instead) But as I say, if you move to raw mode, no character processing is done in the tty driver and you get the characters raw.

    • Ctrl-C produces ASCII ETX (end of text) character without interrupting the program with SIGINT.
    • Ctrl-D produces ASCII EOT (end of transmission) character without signalling no more data to the tty driver. As of this, no SIGHUP will be delivered to the process group.
    • Ctrl-] produces ASCII GS (group separator) character without signalling SIGQUIT to the process (and no core dump)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search