Search code examples
clinuxcygwin

How to capture event "down" "up" for a keystroke or a mouse button in C


I found numerous examples that use either X11 or linux/input.h unfortunately I am on Cygwin where linux/input.h does not exist.

I would like a simple example that I can use to detect events such as:

  • Key down
  • Key up

Or

  • Mouse button down
  • Mouse button up

I would like to find a solution that can work on Cygwin/Linux and as optionally on Windows/OSX.

Is it possible?

So far I've found 1 solution that is using X11:

#include <stdio.h>
#include <X11/Xlib.h>

char *key_name[] = {
    "first",
    "second (or middle)",
    "third",
    "fourth",  // :D
    "fivth"    // :|
};

int main(int argc, char **argv)
{
    Display *display;
    XEvent xevent;
    Window window;

    if( (display = XOpenDisplay(NULL)) == NULL )
        return -1;

    window = DefaultRootWindow(display);
    XAllowEvents(display, AsyncBoth, CurrentTime);

    XGrabPointer(display, 
                 window,
                 1, 
                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask , 
                 GrabModeAsync,
                 GrabModeAsync, 
                 None,
                 None,
                 CurrentTime);

    while(1) {
        XNextEvent(display, &xevent);
        switch (xevent.type) {
            case ButtonPress:
                printf("Button pressed  : %s\n", key_name[xevent.xbutton.button - 1]);
                break;
            case ButtonRelease:
                printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]);
                break;
        }
    }

    return 0;
}

Building with

gcc foo.c -lX11

Unfortunately the Xserver has to be launched startxwin& and the mouse pointer has to be inside a X server window. So this is not a good solution.

Another approach was to use ncurses but It seems states key-down, key-up are not possible.

The example below does not work on cygwin because conio.h is not POSIX:

#include <stdio.h>
#include <conio.h>
char ch;
void main(){
    while(1){
        if(kbhit()){ //kbhit is 1 if a key has been pressed
            ch=getch();
            printf("pressed key was: %c", ch);
        }
    }
}

conio.h is a C header file used mostly by MS-DOS compilers to provide console input/output.[1] It is not part of the C standard library or ISO C, nor is it defined by POSIX.


Solution

  • You seem to want to make a cross-platform program. I doubt you'll be able to resolve this problem with Linux-only libraries. What I suggest is to:

    1. Ditch X in favor of Qt or GTK.
    2. Make a module that listens to key events using facilities from Windows.h, compiled only if user is on Windows. Sooner or later you'll need to do that anyway for other stuff as your project grows.