Reducing input latency when working with X
Asked Answered
D

1

24

I've been reading a few articles about input latency lately:

https://danluu.com/term-latency/

https://pavelfatin.com/typing-with-pleasure/

And I've been trying to improve the user experience of my small text editor. I was using SDL to pool input and create the window, but decided to remove it and do my own X implementation. Application startup has improved, but input latency not so much. Is there any specific technique that can be done to improve how my application picks up mouse and keyboard data from X? Or should I just give up and force Wayland?

I've considered running my XNextEvent() loop on a separate thread, but is that really the only solution for this?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <GL/glx.h>
#include <GL/glext.h>
#include <GL/glu.h>

Display *dpy;
Window root, win;
GLint att[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None};
XVisualInfo *vi;
Colormap cmap;
XSetWindowAttributes swa;
XWindowAttributes wa;
XEvent xev;
Mask mask;

float TimeCounter, LastFrameTimeCounter, DT, prevTime = 0.0, FPS;
struct timeval tv, tv0;
int Frame = 1, FramesPerFPS;

void CreateWindow() {
  if ((dpy = XOpenDisplay(NULL)) == NULL) {
    printf("\n\tcannot connect to x server\n\n");
    exit(0);
  }

  root = DefaultRootWindow(dpy);

  if ((vi = glXChooseVisual(dpy, 0, att)) == NULL) {
    printf("\n\tno matching visual\n\n");
    exit(0);
  }

  if ((cmap = XCreateColormap(dpy, root, vi->visual, AllocNone)) == 0) {
    printf("\n\tcannot create colormap\n\n");
    exit(0);
  }

  swa.event_mask = KeyPressMask;
  swa.colormap = cmap;
  win = XCreateWindow(dpy, root, 0, 0, 1024, 768, 0, vi->depth, InputOutput,
                      vi->visual, CWColormap | CWEventMask, &swa);
  XStoreName(dpy, win, "ed");
  XMapWindow(dpy, win);
}

void Close() {
  XDestroyWindow(dpy, win);
  XCloseDisplay(dpy);
  exit(0);
}

int main(int argc, char *argv[]) {
  CreateWindow();

  while (true) {
    mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;
    while (XCheckWindowEvent(dpy, win, mask, &xev) ||
           XCheckTypedWindowEvent(dpy, win, ClientMessage, &xev)) {
      char *key_string =
          XKeysymToString(XkbKeycodeToKeysym(dpy, xev.xkey.keycode, 0, 0));

      if (strncmp(key_string, "Escape", 5) == 0) {
        Close();
      }
    }
  }
}
Dream answered 27/4, 2018 at 15:16 Comment(2)
A surprisingly counter-intuitive way to reduce latency is to actually process input as LATE as possible within your render loop. We can't see how your input code interacts with your rendering code, so it's hard to tell whether that would help you or not, though...Arrowhead
try to use select(). linuxquestions.org/questions/linux-software-2/…Weighting
S
1

You can also directly listen the evdev input driver, but then you have to deliver the event to the window by your own implementation.

XNextEvent() in turn converts all the mathematical conversions (from raw events to window based), calculates window in focus and many other things.

I feel XNextEvent() is the only option if you go for simplicity and easy implementation.

Symer answered 29/11, 2018 at 7:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.