// Taken from https://github.com/mackstann/tinywm #include #include #include #define MODMASK Mod1Mask #define MAX(a, b) ((a) > (b) ? (a) : (b)) static Window root; static Display* dpy; static XWindowAttributes attr; static XButtonEvent start; void grab_input(Window* root) { XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("1")), MODMASK, *root, True, GrabModeAsync, GrabModeAsync); XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("Q")), MODMASK, *root, True, GrabModeAsync, GrabModeAsync); XGrabButton(dpy, 1, MODMASK, *root, True, ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None); XGrabButton(dpy, 3, MODMASK, *root, True, ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None); } void handle_event_keypress(XEvent *e) { if (e->xkey.subwindow != None) { KeySym keysym = XkbKeycodeToKeysym(dpy, e->xkey.keycode, 0, 0); if (keysym == XK_q) { XKillClient(dpy, e->xkey.subwindow); } else if (keysym == XK_1) { XRaiseWindow(dpy, e->xkey.subwindow); } } } void handle_event_buttonpress(XEvent *e) { if (e->xkey.subwindow != None) { XGetWindowAttributes(dpy, e->xbutton.subwindow, &attr); start = e->xbutton; } } void handle_event_motionnotify(XEvent *e) { if (start.subwindow != None) { int xdiff = e->xbutton.x_root - start.x_root; int ydiff = e->xbutton.y_root - start.y_root; XMoveResizeWindow(dpy, start.subwindow, attr.x + (start.button==1 ? xdiff : 0), attr.y + (start.button==1 ? ydiff : 0), MAX(1, attr.width + (start.button==3 ? xdiff : 0)), MAX(1, attr.height + (start.button==3 ? ydiff : 0))); } } void handle_event_buttonrelease(XEvent *e) { start.subwindow = None; } void handle_event_mappingnotify(XEvent *e) { XMappingEvent *ev = &e->xmapping; if (ev->request == MappingKeyboard || ev->request == MappingModifier) { XRefreshKeyboardMapping(ev); grab_input(&root); } } static void (*event_handlers[LASTEvent])(XEvent *e) = { [KeyPress] = handle_event_keypress, [ButtonPress] = handle_event_buttonpress, [ButtonRelease] = handle_event_buttonrelease, [MotionNotify] = handle_event_motionnotify, // Below are events that are not 100% needed but without them some programs may break! // TODO: MapRequest, ConfigureRequest [MappingNotify] = handle_event_mappingnotify }; int main() { if(!(dpy = XOpenDisplay(0x0))) return 1; XEvent ev; root = DefaultRootWindow(dpy); grab_input(&root); start.subwindow = None; for (;;) { XNextEvent(dpy, &ev); if (event_handlers[ev.type]) event_handlers[ev.type](&ev); } return 0; }