Valentin Diard

Input management on linux in C

2021-03-29 09:20:09.965666

I article is a draft, I published it because I think this subject have a lack of documentations.

In some situation as game engine development dans GUI library, retrieving input with non-blocking solution is important. But contrary to windows, linux doesn't offer a solution to this problem directly on this API, and in some case multiple kernel version must be handled. So I'm decided to resume this subject exploration on this article.

I. Root solution

1. Reading kernel event

2. Reading input with evdev

II. Non-root

An other way, is to use graphical environment layer. Two environment are really popular on linux, Xorg and wayland, I have only tested Xorg actually.

1. Reading input with xorg library

Xorg is the most popular graphical environment, used to creating windows on numerous libraries and commonly installed by default on various distributions.

This library have as architecture a backend server who retrieved and send information to linux user api, and client process generally a window.

Warning I doesn't tested this solution on wayland graphical environment.

#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

int main(void)
{
  // Connect to the X server on default screen. "DISPLAY" environnement variable which used for that.
  Display *display = XOpenDisplay(nullptr);
  XEvent event;

  // Verify that the connection succeed
  if (display == nullptr) {
    return EXIT_FAILURE;
  }

  // Ask to Xlib to retrieve input in async mode on actual connection
  XGrabKeyboard(display, DefaultRootWindow(display), true, GrabModeAsync, GrabModeAsync, CurrentTime);

  while (true) {
      // Retrieve the next event from X server event pool
      XNextEvent(display, &event);

      if (event.type == KeyPress) {
    std::cout << "press" << event.xkey.keycode << std::endl;

        // need to quit the program with escape keyboard input
        if (event.xkey.keycode == 9) {
      break;
    }
      } else if(event.type == KeyRelease) {
    std::cout << "release" << event.xkey.keycode << std::endl;
      }
    }
  // Close the connection with the X server
  XCloseDisplay(display);

  return EXIT_SUCCESS;
}

Actually this code cause interception of all input, and break my i3 configuration, but successfully retrieved keyboard input without giving root right.

Useful link: