]> git.sur5r.net Git - i3/i3/blobdiff - i3-input/main.c
include match.h in all.h
[i3/i3] / i3-input / main.c
index a3bc9de366a875c19baab7be503fd3b88d2513f8..f5229c08a3c1c2371b55e8ae896a69ad6edf2b83 100644 (file)
@@ -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);