X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=i3-input%2Fmain.c;h=f5229c08a3c1c2371b55e8ae896a69ad6edf2b83;hb=42bed06b9a59d574b1e183b07ccf069f80f01eee;hp=a3bc9de366a875c19baab7be503fd3b88d2513f8;hpb=acb07b95c00d090042eba6888b6f062261d15234;p=i3%2Fi3 diff --git a/i3-input/main.c b/i3-input/main.c index a3bc9de3..f5229c08 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -37,6 +37,7 @@ static int sockfd; static xcb_key_symbols_t *symbols; static int modeswitchmask; +static int numlockmask; static bool modeswitch_active = false; static xcb_window_t win; static xcb_pixmap_t pixmap; @@ -56,7 +57,7 @@ static int limit; * */ static uint8_t *concat_strings(char **glyphs, int max) { - uint8_t *output = calloc(max, 4); + uint8_t *output = calloc(max+1, 4); uint8_t *walk = output; for (int c = 0; c < max; c++) { printf("at %c\n", glyphs[c][0]); @@ -119,6 +120,9 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_release_event_t *event) { printf("releasing %d, state raw = %d\n", event->detail, event->state); + /* fix state */ + event->state &= ~numlockmask; + xcb_keysym_t sym = xcb_key_press_lookup_keysym(symbols, event, event->state); if (sym == XK_Mode_switch) { printf("Mode switch disabled\n"); @@ -163,6 +167,11 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press if (modeswitch_active) event->state |= modeswitchmask; + /* Apparantly, after activating numlock once, the numlock modifier + * stays turned on (use xev(1) to verify). So, to resolve useful + * keysyms, we remove the numlock flag from the event state */ + event->state &= ~numlockmask; + xcb_keysym_t sym = xcb_key_press_lookup_keysym(symbols, event, event->state); if (sym == XK_Mode_switch) { printf("Mode switch enabled\n"); @@ -290,7 +299,8 @@ int main(int argc, char *argv[]) { xcb_event_set_key_release_handler(&evenths, handle_key_release, NULL); xcb_event_set_expose_handler(&evenths, handle_expose, NULL); - modeswitchmask = get_mode_switch_mask(conn); + modeswitchmask = get_mod_mask(conn, XK_Mode_switch); + numlockmask = get_mod_mask(conn, XK_Num_Lock); symbols = xcb_key_symbols_alloc(conn); uint32_t font_id = get_font_id(conn, pattern, &font_height); @@ -306,11 +316,33 @@ int main(int argc, char *argv[]) { xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, font_height + 8); xcb_create_gc(conn, pixmap_gc, pixmap, 0, 0); + /* Set input focus (we have override_redirect=1, so the wm will not do + * this for us) */ + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME); + /* Create graphics context */ xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FONT, font_id); /* Grab the keyboard to get all input */ - xcb_grab_keyboard(conn, false, win, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + xcb_flush(conn); + + /* Try (repeatedly, if necessary) to grab the keyboard. We might not + * get the keyboard at the first attempt because of the keybinding + * still being active when started via a wm’s keybinding. */ + xcb_grab_keyboard_cookie_t cookie; + xcb_grab_keyboard_reply_t *reply = NULL; + + int count = 0; + while ((reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) && (count++ < 500)) { + cookie = xcb_grab_keyboard(conn, false, win, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + reply = xcb_grab_keyboard_reply(conn, cookie, NULL); + usleep(1000); + } + + if (reply->status != XCB_GRAB_STATUS_SUCCESS) { + fprintf(stderr, "Could not grab keyboard, status = %d\n", reply->status); + exit(-1); + } xcb_flush(conn);