/* * Copyright 2010 Johan Veenhuizen */ #include #include #include #include "wind.h" static void fnkey(KeySym, unsigned, Time, int); static void configurerequest(XConfigureRequestEvent *); static void maprequest(XMapRequestEvent *); static void keypress(XKeyEvent *); static void focusin(XFocusChangeEvent *); static void rooteventlistener(void *, XEvent *); static const struct eventlistener listener = { .function = rooteventlistener, .pointer = NULL, }; static struct keybind { KeySym keysym; unsigned modifiers; void (*function)(KeySym key, unsigned state, Time t, int arg); int arg; KeyCode keycode; } keymap[] = { { XK_F1, Mod1Mask, fnkey, 1 }, { XK_F2, Mod1Mask, fnkey, 2 }, { XK_F3, Mod1Mask, fnkey, 3 }, { XK_F4, Mod1Mask, fnkey, 4 }, { XK_F5, Mod1Mask, fnkey, 5 }, { XK_F6, Mod1Mask, fnkey, 6 }, { XK_F7, Mod1Mask, fnkey, 7 }, { XK_F8, Mod1Mask, fnkey, 8 }, { XK_F9, Mod1Mask, fnkey, 9 }, { XK_F10, Mod1Mask, fnkey, 10 }, { XK_F11, Mod1Mask, fnkey, 11 }, { XK_F12, Mod1Mask, fnkey, 12 }, { XK_F1, ShiftMask | Mod1Mask, fnkey, 1 }, { XK_F2, ShiftMask | Mod1Mask, fnkey, 2 }, { XK_F3, ShiftMask | Mod1Mask, fnkey, 3 }, { XK_F4, ShiftMask | Mod1Mask, fnkey, 4 }, { XK_F5, ShiftMask | Mod1Mask, fnkey, 5 }, { XK_F6, ShiftMask | Mod1Mask, fnkey, 6 }, { XK_F7, ShiftMask | Mod1Mask, fnkey, 7 }, { XK_F8, ShiftMask | Mod1Mask, fnkey, 8 }, { XK_F9, ShiftMask | Mod1Mask, fnkey, 9 }, { XK_F10, ShiftMask | Mod1Mask, fnkey, 10 }, { XK_F11, ShiftMask | Mod1Mask, fnkey, 11 }, { XK_F12, ShiftMask | Mod1Mask, fnkey, 12 }, }; static void fnkey(KeySym keysym, unsigned state, Time time, int arg) { if (state & ShiftMask) setndesk(arg); gotodesk(arg - 1); refocus(time); } static void configurerequest(XConfigureRequestEvent *e) { // First try to redirect the event. if (redirect((XEvent *)e, e->window) == 0) return; // Nobody listens to this window so we'll just // do whatever it wants us to do. // Ignore stacking requests for now. e->value_mask &= ~(CWSibling | CWStackMode); XConfigureWindow(dpy, e->window, e->value_mask, &(XWindowChanges){ .x = e->x, .y = e->y, .width = e->width, .height = e->height, .border_width = e->border_width, .sibling = e->above, .stack_mode = e->detail }); } static void maprequest(XMapRequestEvent *e) { // Already managed? if (redirect((XEvent *)e, e->window) == 0) return; // Try to manage it, otherwise just map it. if (manage(e->window) == NULL) XMapWindow(dpy, e->window); } static void keypress(XKeyEvent *e) { for (int i = 0; i < NELEM(keymap); i++) if (keymap[i].keycode == e->keycode) { keymap[i].function(keymap[i].keysym, e->state, e->time, keymap[i].arg); break; } } static void focusin(XFocusChangeEvent *e) { // Pick a new focus window whenever input focus reverts // to the root window (unless caused by our own key grab). if (e->window == root && e->mode != NotifyGrab) refocus(CurrentTime); } static void rooteventlistener(void *self, XEvent *e) { switch (e->type) { case MapRequest: maprequest(&e->xmaprequest); break; case ConfigureRequest: configurerequest(&e->xconfigurerequest); break; case KeyPress: keypress(&e->xkey); break; case FocusIn: focusin(&e->xfocus); break; case ClientMessage: ewmh_rootclientmessage(&e->xclient); break; case UnmapNotify: /* * Refer to the ICCCM section 4.1.4, "Changing Window State", * for information on the synthetic UnmapNotify event sent * by clients on window withdrawal. */ if (e->xunmap.send_event) redirect(e, e->xunmap.window); break; } } void initroot(void) { XSync(dpy, False); xerror = NULL; XSelectInput(dpy, root, FocusChangeMask | SubstructureRedirectMask | SubstructureNotifyMask); XSync(dpy, False); if (xerror != NULL) { errorf("display \"%s\" already managed", XDisplayName(displayname)); exit(1); } seteventlistener(root, &listener); for (int i = 0; i < NELEM(keymap); i++) { struct keybind *k = &keymap[i]; k->keycode = XKeysymToKeycode(dpy, k->keysym); grabkey(k->keycode, k->modifiers, root, True, GrabModeAsync, GrabModeAsync); } }