Ignore auto repeat in X11 applications

autorepeat, keyboard, x11

Solution

When you receive a key release and the next event is a key press of the same key combination, then it's auto-repeat and the key wasn't acutally released. You can use code like this to peek next event

if (event->type == KeyRelease && XEventsQueued(disp, QueuedAfterReading))
{
  XEvent nev;
  XPeekEvent(disp, &nev);
    
  if (nev.type == KeyPress && nev.xkey.time == event->xkey.time &&
      nev.xkey.keycode == event->xkey.keycode)
  {
    /* Key wasn’t actually released */
  }
}

Problem

If you press and hold a key in X11 while AutoRepeat is enabled, you continuously receive KeyPress and KeyRelease events. I know that AutoRepeat can be disabled using the function XAutoRepeatOff(), but this changes the setting for the whole X server. Is there a way to either disable AutoRepeat for a single application or to ignore repeated keystrokes? What I'm looking for is a single KeyPress event when a key is pressed and a single KeyRelease event when a key is released, without interfering with the X server's AutoRepeat setting. Here's a minimal example to get you going (mostly from the Beginner Xlib Tutorial): ``` #include <stdio.h> #include <stdlib.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xos.h> #include <X11/Xatom.h> #include <X11/keysym.h> Display *dis; Window win; XEvent report; int main () { dis = XOpenDisplay (NULL); // XAutoRepeatOn(dis); win = XCreateSimpleWindow (dis, RootWindow (dis, 0), 1, 1, 500, 500, 0, BlackPixel (dis, 0), BlackPixel (dis, 0)); XSelectInput (dis, win, KeyPressMask | KeyReleaseMask); XMapWindow (dis, win); XFlush (dis); while (1) { XNextEvent (dis, &report); switch (report.type) { case KeyPress: fprintf (stdout, "key #%ld was pressed.\n", (long) XLookupKeysym (&report.xkey, 0)); break; case KeyRelease: fprintf (stdout, "key #%ld was released.\n", (long) XLookupKeysym (&report.xkey, 0)); break; } } return (0); } ```

Original source