You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
2.8 KiB
121 lines
2.8 KiB
/* 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 <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdint.h>
|
|
#include <inttypes.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#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;
|
|
}
|