#include <iostream>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <pthread.h>
#include <X11/keysym.h>
#include <unistd.h>
const int fps = 30;
void render(long int monoSpan) {
static int renderCount = 0;
std::cout << "render " << renderCount++ << " - " << monoSpan / 1000000.0f << std::endl;
}
int main() {
auto displayName = getenv("DISPLAY");
auto display = XOpenDisplay(displayName);
auto defaultScreen = DefaultScreen(display);
auto windowRoot = RootWindow(display, defaultScreen);
auto visualInfo = DefaultVisual(display, defaultScreen);
auto depth = DefaultDepth(display, defaultScreen);
auto maskEvents = ExposureMask | KeyPressMask;
XSetWindowAttributes attrs;
attrs.event_mask = maskEvents;
attrs.background_pixel = XWhitePixel(display, defaultScreen);
auto window = XCreateWindow(display, windowRoot, 100, 100, 320, 240, 0, depth, InputOutput, visualInfo,
CWBackPixel | CWEventMask, &attrs);
XMapWindow(display, window);
const long int oneFrameMonoLimit = 1000000000 / fps;
timespec lastRenderTime;
clock_gettime(CLOCK_MONOTONIC, &lastRenderTime);
render(0);
for (;;) {
XEvent event;
XNextEvent(display, &event); // block the thread
// process the event
L_PROCESS_EVENT:
switch (event.type) {
case Expose:
//
break;
case KeyPress:
auto keySys = XkbKeycodeToKeysym(display, event.xkey.keycode, 0, event.xkey.state & ShiftMask ? 1 : 0);
switch (keySys) {
case XK_Escape:
goto L_EXIT;
case XK_space:
// render();
break;
}
break;
}
//
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
auto timeSpan = (now.tv_sec - lastRenderTime.tv_sec) * 1000000000 + now.tv_nsec - lastRenderTime.tv_nsec;
if (timeSpan > oneFrameMonoLimit) {
render(timeSpan);
lastRenderTime = now;
} else {
if (XCheckMaskEvent(display, maskEvents, &event)) {
goto L_PROCESS_EVENT;
} else {
for (int c = 0;; ++c) {
if (XCheckMaskEvent(display, maskEvents, &event)) {
goto L_PROCESS_EVENT;
} else {
clock_gettime(CLOCK_MONOTONIC, &now);
timeSpan = (now.tv_sec - lastRenderTime.tv_sec) * 1000000000 + now.tv_nsec -
lastRenderTime.tv_nsec;
if (timeSpan > oneFrameMonoLimit) {
render(timeSpan);
std::cout << c << std::endl;
lastRenderTime = now;
break;
}
// pthread_yield();
usleep(1000);
}
}
}
}
}
L_EXIT:
return 0;
}