/* copyright Constantin Fürst 2021, licensed under GPLv3, a copy is provided in LICENSE */ /* non-major portions of the code were taken from DWM (https://dwm.suckless.org) */ /* inspired and named after keym by Chris Willcocks (https://github.com/cwkx/keym) */ #include #include #include #include #include #include "config.h" #include "typedefs.h" keym_state state; void eventhandler(XEvent *e) { uint32_t arg; KeySym keysym; XKeyEvent *ev; ev = &e->xkey; keysym = XKeycodeToKeysym(state.display, (KeyCode)ev->keycode, 0); for (uint32_t i = 0; i < LENGTH(keys); i++) { if ( keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) && keys[i].func ) { arg = keys[i].arg; switch (ev->type) { case KeyRelease: arg |= KEY_RELEASE_MASK; break; case KeyPress: default: break; } keys[i].func(&arg); } } } void grabkeys() { KeyCode code; XUngrabKey(state.display, AnyKey, AnyModifier, state.window); for (uint32_t i = 0; i < LENGTH(keys); i++) { if ((code = XKeysymToKeycode(state.display, keys[i].keysym))) { XGrabKey(state.display, code, keys[i].mod, state.window, True, GrabModeAsync, GrabModeAsync); } } } int setup() { state.speed = 1; state.quit = False; if (!(state.display = XOpenDisplay(NULL))) { fprintf(stderr, "[x] error opening display\n"); return 1; } state.window = XDefaultRootWindow(state.display); state.screen = DefaultScreen(state.display); XSelectInput(state.display, state.window, ExposureMask | KeyPressMask); XMapWindow(state.display, state.window); state.x11_fd = ConnectionNumber(state.display);; grabkeys(); return 0; } void cleanup() { XUngrabKey(state.display, AnyKey, AnyModifier, state.window); FD_CLR(state.x11_fd, &state.in_fds); XUnmapWindow(state.display,state.window); XCloseDisplay(state.display); } void set_x_update(uint32_t tv_usec) { FD_ZERO(&state.in_fds); FD_SET(state.x11_fd, &state.in_fds); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = tv_usec; select(state.x11_fd + 1, &state.in_fds, NULL, NULL, &tv); } void move_pointer_by_state() { XWarpPointer(state.display, None, None, 0, 0, 0, 0, state.x, state.y); } int main() { XEvent ev; if (setup() != 0) return -1; XSync(state.display, False); while (!state.quit) { while (XPending(state.display)) XNextEvent(state.display, &ev); set_x_update(speeds[state.speed]); eventhandler(&ev); move_pointer_by_state(); } cleanup(); return 1; }