void handle_event(struct input_event *ev) { if (ev->type == EV_KEY) { if (test_mode) { if (ev->value == VA_PRESS) { if (reg_key_from_keycode(ev->code, ®_key)) printf("%s (%u)\n", reg_key.name, reg_key.keycode); else if (mod_key_from_keycode(ev->code, &mod_key)) printf("%s (%u)\n", mod_key.name, mod_key.keycode); else printf("? (%u)\n", ev->code); if (ev->code == KEY_ESC) running = false; } return; } if (!care_for[ev->code]) return; if (ev->value == VA_PRESS || ev->value == VA_REPEAT || ev->value == VA_RELEASE) { /* search for the hotkey */ hotkey_t *hk = NULL; if (ev->value == VA_RELEASE) { hk = find_hotkey(modmask | RELEASE_MASK, ev->code, current_mode); } else { hk = find_hotkey(modmask, ev->code, current_mode); } if (hk != NULL) { /* change mode if the hotkey specifies a new mode */ if (hk->next_mode != NULL) { current_mode = hk->next_mode; } /* run the hotkey's command */ char *cmd[] = {SHELL, "-c", hk->command, NULL}; if (spawnv(cmd[0], cmd) == -1) warn("failed to execute command: %s\n", hk->command); } else if (ev->value == VA_PRESS && mod_key_from_keycode(ev->code, &mod_key)) { modmask |= mod_key.modval; } } /* remove released modifiers from the current modmask */ if (ev->value == VA_RELEASE) { if (mod_key_from_keycode(ev->code, &mod_key)) modmask &= ~mod_key.modval; } } }
void key_button_event(xcb_generic_event_t *evt, uint8_t event_type) { xcb_keysym_t keysym = XCB_NO_SYMBOL; xcb_button_t button = XCB_NONE; bool replay_event = false; uint16_t modfield = 0; uint16_t lockfield = num_lock | caps_lock | scroll_lock; parse_event(evt, event_type, &keysym, &button, &modfield); modfield &= ~lockfield & MOD_STATE_FIELD; if (keysym != XCB_NO_SYMBOL || button != XCB_NONE) { hotkey_t *hk = find_hotkey(keysym, button, modfield, event_type, &replay_event); if (hk != NULL) { run(hk->command, hk->sync); if (status_fifo != NULL) put_status(COMMAND_PREFIX, hk->command); } } switch (event_type) { case XCB_BUTTON_PRESS: case XCB_BUTTON_RELEASE: if (replay_event) xcb_allow_events(dpy, XCB_ALLOW_REPLAY_POINTER, XCB_CURRENT_TIME); else xcb_allow_events(dpy, XCB_ALLOW_SYNC_POINTER, XCB_CURRENT_TIME); break; case XCB_KEY_PRESS: case XCB_KEY_RELEASE: if (replay_event) xcb_allow_events(dpy, XCB_ALLOW_REPLAY_KEYBOARD, XCB_CURRENT_TIME); else xcb_allow_events(dpy, XCB_ALLOW_SYNC_KEYBOARD, XCB_CURRENT_TIME); break; } xcb_flush(dpy); }
hotkey_t *find_hotkey(xcb_keysym_t keysym, xcb_button_t button, uint16_t modfield, uint8_t event_type, bool *replay_event) { int num_active = 0; int num_locked = 0; hotkey_t *result = NULL; for (hotkey_t *hk = hotkeys_head; hk != NULL; hk = hk->next) { chain_t *c = hk->chain; if ((chained && c->state == c->head) || (locked && c->state != c->tail)) continue; if (match_chord(c->state, event_type, keysym, button, modfield)) { if (status_fifo != NULL && num_active == 0) { if (!chained) { snprintf(progress, sizeof(progress), "%s", c->state->repr); } else { strncat(progress, ";", sizeof(progress) - strlen(progress) - 1); strncat(progress, c->state->repr, sizeof(progress) - strlen(progress) - 1); } put_status(HOTKEY_PREFIX, progress); } if (replay_event != NULL && c->state->replay_event) *replay_event = true; if (c->state->lock_chain) { num_locked += 1; if (timeout > 0) alarm(0); } if (c->state == c->tail) { if (hk->cycle != NULL) { unsigned char delay = hk->cycle->delay; hk->cycle->delay = (delay == 0 ? hk->cycle->period - 1 : delay - 1); if (delay == 0) result = hk; continue; } if (chained && !locked) abort_chain(); return hk; } else { c->state = c->state->next; num_active++; grab_chord(c->state); } } else if (chained) { if (!locked && c->state->event_type == event_type) c->state = c->head; else num_active++; } } if (result != NULL) return result; if (num_locked > 0) { locked = true; } if (!chained) { if (num_active > 0) { chained = true; put_status(BEGIN_CHAIN_PREFIX, "Begin chain"); grab_chord(abort_chord); } } else if (num_active == 0 || match_chord(abort_chord, event_type, keysym, button, modfield)) { abort_chain(); return find_hotkey(keysym, button, modfield, event_type, replay_event); } if (chained && !locked && timeout > 0) alarm(timeout); PRINTF("num active %i\n", num_active); return NULL; }