]> git.sur5r.net Git - i3/i3/blobdiff - i3-config-wizard/main.c
add libi3/ipc_connect, use it in i3-config-wizard, i3-input, i3bar
[i3/i3] / i3-config-wizard / main.c
index d3a26721d20329c427b8994d02ba6548474dea29..d3f9bcbf439c923bad01f17032a68df0d7bc23e8 100644 (file)
 while (0)
 
 #include "xcb.h"
-#include "ipc.h"
+#include "libi3.h"
 
 enum { STEP_WELCOME, STEP_GENERATE } current_step = STEP_WELCOME;
-enum { MOD_ALT, MOD_SUPER } modifier = MOD_SUPER;
+enum { MOD_Mod1, MOD_Mod4 } modifier = MOD_Mod4;
 
 static char *config_path;
 static xcb_connection_t *conn;
+static xcb_get_modifier_mapping_reply_t *modmap_reply;
 static uint32_t font_id;
 static uint32_t font_bold_id;
 static char *socket_path;
@@ -129,42 +130,6 @@ static char *resolve_tilde(const char *path) {
     return result;
 }
 
-/*
- * Try to get the socket path from X11 and return NULL if it doesn’t work.
- * As i3-msg is a short-running tool, we don’t bother with cleaning up the
- * connection and leave it up to the operating system on exit.
- *
- */
-static char *socket_path_from_x11() {
-    xcb_connection_t *conn;
-    int screen;
-    if ((conn = xcb_connect(NULL, &screen)) == NULL ||
-        xcb_connection_has_error(conn))
-        return NULL;
-    xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screen);
-    xcb_window_t root = root_screen->root;
-
-    xcb_intern_atom_cookie_t atom_cookie;
-    xcb_intern_atom_reply_t *atom_reply;
-
-    atom_cookie = xcb_intern_atom(conn, 0, strlen("I3_SOCKET_PATH"), "I3_SOCKET_PATH");
-    atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
-    if (atom_reply == NULL)
-        return NULL;
-
-    xcb_get_property_cookie_t prop_cookie;
-    xcb_get_property_reply_t *prop_reply;
-    prop_cookie = xcb_get_property_unchecked(conn, false, root, atom_reply->atom,
-                                             XCB_GET_PROPERTY_TYPE_ANY, 0, PATH_MAX);
-    prop_reply = xcb_get_property_reply(conn, prop_cookie, NULL);
-    if (prop_reply == NULL || xcb_get_property_value_length(prop_reply) == 0)
-        return NULL;
-    if (asprintf(&socket_path, "%.*s", xcb_get_property_value_length(prop_reply),
-                 (char*)xcb_get_property_value(prop_reply)) == -1)
-        return NULL;
-    return socket_path;
-}
-
 /*
  * Handles expose events, that is, draws the window contents.
  *
@@ -208,13 +173,13 @@ static int handle_expose() {
         txt(85, 10, "to abort");
 
         /* the not-selected modifier */
-        if (modifier == MOD_SUPER)
+        if (modifier == MOD_Mod4)
             txt(31, 5, "<Alt>");
         else txt(31, 4, "<Win>");
 
         /* the selected modifier */
         xcb_change_gc_single(conn, pixmap_gc, XCB_GC_FONT, font_bold_id);
-        if (modifier == MOD_SUPER)
+        if (modifier == MOD_Mod4)
             txt(31, 4, "<Win>");
         else txt(31, 5, "<Alt>");
 
@@ -271,16 +236,62 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
     if (sym == XK_Escape)
         exit(0);
 
-    if (sym == XK_Alt_L)
-        modifier = MOD_ALT;
+    /* Check if this is Mod1 or Mod4. The modmap contains Shift, Lock, Control,
+     * Mod1, Mod2, Mod3, Mod4, Mod5 (in that order) */
+    xcb_keycode_t *modmap = xcb_get_modifier_mapping_keycodes(modmap_reply);
+    /* Mod1? */
+    int mask = 3;
+    for (int i = 0; i < modmap_reply->keycodes_per_modifier; i++) {
+        xcb_keycode_t code = modmap[(mask * modmap_reply->keycodes_per_modifier) + i];
+        if (code == XCB_NONE)
+            continue;
+        printf("Modifier keycode for Mod1: 0x%02x\n", code);
+        if (code == event->detail) {
+            modifier = MOD_Mod1;
+            printf("This is Mod1!\n");
+        }
+    }
 
-    if (sym == XK_Super_L)
-        modifier = MOD_SUPER;
+    /* Mod4? */
+    mask = 6;
+    for (int i = 0; i < modmap_reply->keycodes_per_modifier; i++) {
+        xcb_keycode_t code = modmap[(mask * modmap_reply->keycodes_per_modifier) + i];
+        if (code == XCB_NONE)
+            continue;
+        printf("Modifier keycode for Mod4: 0x%02x\n", code);
+        if (code == event->detail) {
+            modifier = MOD_Mod4;
+            printf("This is Mod4!\n");
+        }
+    }
 
     handle_expose();
     return 1;
 }
 
+/*
+ * Handle button presses to make clicking on "<win>" and "<alt>" work
+ *
+ */
+static void handle_button_press(xcb_button_press_event_t* event) {
+    if (current_step != STEP_GENERATE)
+        return;
+
+    if (event->event_x >= 32 && event->event_x <= 68 &&
+        event->event_y >= 45 && event->event_y <= 54) {
+        modifier = MOD_Mod4;
+        handle_expose();
+    }
+
+    if (event->event_x >= 32 && event->event_x <= 68 &&
+        event->event_y >= 56 && event->event_y <= 70) {
+        modifier = MOD_Mod1;
+        handle_expose();
+    }
+
+    return;
+}
+
 /*
  * Creates the config file and tells i3 to reload.
  *
@@ -333,7 +344,7 @@ static void finish() {
 
         /* Set the modifier the user chose */
         if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) {
-            if (modifier == MOD_ALT)
+            if (modifier == MOD_Mod1)
                 fputs("set $mod Mod1\n", ks_config);
             else fputs("set $mod Mod4\n", ks_config);
             continue;
@@ -359,7 +370,7 @@ static void finish() {
     fclose(ks_config);
 
     /* tell i3 to reload the config file */
-    int sockfd = connect_ipc(socket_path);
+    int sockfd = ipc_connect(socket_path);
     ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload");
     close(sockfd);
 
@@ -436,6 +447,9 @@ int main(int argc, char *argv[]) {
         xcb_connection_has_error(conn))
         errx(1, "Cannot open display\n");
 
+    xcb_get_modifier_mapping_cookie_t modmap_cookie;
+    modmap_cookie = xcb_get_modifier_mapping(conn);
+
     /* Place requests for the atoms we need as soon as possible */
     #define xmacro(atom) \
         xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
@@ -445,6 +459,11 @@ int main(int argc, char *argv[]) {
     xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screens);
     root = root_screen->root;
 
+    if (!(modmap_reply = xcb_get_modifier_mapping_reply(conn, modmap_cookie, NULL)))
+        errx(EXIT_FAILURE, "Could not get modifier mapping\n");
+
+    /* XXX: we should refactor xcb_get_numlock_mask so that it uses the
+     * modifier mapping we already have */
     xcb_get_numlock_mask(conn);
 
     symbols = xcb_key_symbols_alloc(conn);
@@ -534,6 +553,10 @@ int main(int argc, char *argv[]) {
 
             /* TODO: handle mappingnotify */
 
+            case XCB_BUTTON_PRESS:
+                handle_button_press((xcb_button_press_event_t*)event);
+                break;
+
             case XCB_EXPOSE:
                 handle_expose();
                 break;