]> git.sur5r.net Git - i3/i3/commitdiff
wizard: actually write the output config
authorMichael Stapelberg <michael@stapelberg.de>
Sun, 1 May 2011 11:56:35 +0000 (13:56 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sun, 1 May 2011 11:56:35 +0000 (13:56 +0200)
i3-config-wizard/cfgparse.l
i3-config-wizard/cfgparse.y
i3-config-wizard/ipc.c [new file with mode: 0644]
i3-config-wizard/ipc.h [new file with mode: 0644]
i3-config-wizard/main.c

index d94abe2a6f917d02d9a180ff02cee7ae76e55542..772b8470d47284896b6c01e6ab2f563a16de7917 100644 (file)
@@ -78,6 +78,7 @@ Mod3                            { yylval.number = (1 << 5); return MODIFIER; }
 Mod4                            { yylval.number = (1 << 6); return MODIFIER; }
 Mod5                            { yylval.number = (1 << 7); return MODIFIER; }
 Mode_switch                     { yylval.number = (1 << 8); return MODIFIER; }
+$mod                           { yylval.number = (1 << 9); return TOKMODVAR; }
 control                         { return TOKCONTROL; }
 ctrl                            { return TOKCONTROL; }
 shift                           { return TOKSHIFT; }
index 85e57bfb76fff5cbdae74e686123aa27f4674b4b..f2e4a05466497a57471a51ad1e477c50773a786f 100644 (file)
@@ -89,6 +89,10 @@ static char *modifier_to_string(int modifiers) {
         return strdup("Mod1");
     else if (modifiers == ((1 << 3) | (1 << 0)))
         return strdup("Mod1+shift");
+    else if (modifiers == (1 << 9))
+        return strdup("$mod");
+    else if (modifiers == ((1 << 9) | (1 << 0)))
+        return strdup("$mod+shift");
     else return strdup("UNKNOWN");
 }
 
@@ -105,6 +109,7 @@ static char *modifier_to_string(int modifiers) {
 %token <number>NUMBER "<number>"
 %token <string>STR "<string>"
 %token TOKBINDCODE
+%token TOKMODVAR "$mod"
 %token MODIFIER "<modifier>"
 %token TOKCONTROL "control"
 %token TOKSHIFT "shift"
@@ -148,6 +153,7 @@ binding_modifiers:
 
 binding_modifier:
     MODIFIER        { $<number>$ = $<number>1; }
+    | TOKMODVAR     { $<number>$ = $<number>1; }
     | TOKCONTROL    { $<number>$ = (1 << 2); }
     | TOKSHIFT      { $<number>$ = (1 << 0); }
     ;
diff --git a/i3-config-wizard/ipc.c b/i3-config-wizard/ipc.c
new file mode 100644 (file)
index 0000000..597a86e
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * vim:ts=8:expandtab
+ *
+ * i3 - an improved dynamic tiling window manager
+ *
+ * © 2009 Michael Stapelberg and contributors
+ *
+ * See file LICENSE for license information.
+ *
+ */
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <err.h>
+
+/*
+ * Formats a message (payload) of the given size and type and sends it to i3 via
+ * the given socket file descriptor.
+ *
+ */
+void ipc_send_message(int sockfd, uint32_t message_size,
+                      uint32_t message_type, uint8_t *payload) {
+        int buffer_size = strlen("i3-ipc") + sizeof(uint32_t) + sizeof(uint32_t) + message_size;
+        char msg[buffer_size];
+        char *walk = msg;
+
+        strcpy(walk, "i3-ipc");
+        walk += strlen("i3-ipc");
+        memcpy(walk, &message_size, sizeof(uint32_t));
+        walk += sizeof(uint32_t);
+        memcpy(walk, &message_type, sizeof(uint32_t));
+        walk += sizeof(uint32_t);
+        memcpy(walk, payload, message_size);
+
+        int sent_bytes = 0;
+        int bytes_to_go = buffer_size;
+        while (sent_bytes < bytes_to_go) {
+                int n = write(sockfd, msg + sent_bytes, bytes_to_go);
+                if (n == -1)
+                        err(EXIT_FAILURE, "write() failed");
+
+                sent_bytes += n;
+                bytes_to_go -= n;
+        }
+}
+
+/*
+ * Connects to the i3 IPC socket and returns the file descriptor for the
+ * socket. die()s if anything goes wrong.
+ *
+ */
+int connect_ipc(char *socket_path) {
+       int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
+        if (sockfd == -1)
+                err(EXIT_FAILURE, "Could not create socket");
+
+        struct sockaddr_un addr;
+        memset(&addr, 0, sizeof(struct sockaddr_un));
+        addr.sun_family = AF_LOCAL;
+        strcpy(addr.sun_path, socket_path);
+        if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
+                err(EXIT_FAILURE, "Could not connect to i3");
+
+       return sockfd;
+}
diff --git a/i3-config-wizard/ipc.h b/i3-config-wizard/ipc.h
new file mode 100644 (file)
index 0000000..c40c909
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _IPC_H
+#define _IPC_H
+
+void ipc_send_message(int sockfd, uint32_t message_size,
+                      uint32_t message_type, uint8_t *payload);
+
+int connect_ipc(char *socket_path);
+
+#endif
index b546f6075e43581d80beb9955d8c1154f0960ddf..a4dd070c5bfc14657ecac51dae0c2dd83cbc68db 100644 (file)
@@ -18,6 +18,7 @@
 #include <stdbool.h>
 #include <unistd.h>
 #include <string.h>
+#include <ctype.h>
 #include <errno.h>
 #include <err.h>
 #include <stdint.h>
@@ -43,6 +44,7 @@
 while (0)
 
 #include "xcb.h"
+#include "ipc.h"
 
 enum { STEP_WELCOME, STEP_GENERATE } current_step = STEP_WELCOME;
 enum { MOD_ALT, MOD_SUPER } modifier = MOD_SUPER;
@@ -52,7 +54,6 @@ static xcb_connection_t *conn;
 static uint32_t font_id;
 static uint32_t font_bold_id;
 static char *socket_path;
-static int sockfd;
 static int font_height;
 static int font_bold_height;
 static xcb_window_t win;
@@ -62,6 +63,7 @@ static xcb_key_symbols_t *symbols;
 xcb_window_t root;
 Display *dpy;
 
+char *rewrite_binding(const char *bindingline);
 static void finish();
 
 /*
@@ -205,36 +207,82 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
     return 1;
 }
 
+/*
+ * Creates the config file and tells i3 to reload.
+ *
+ */
 static void finish() {
-    printf("finishing the wizard\n");
+    printf("creating \"%s\"...\n", config_path);
 
-#if 0
-    dpy = XOpenDisplay(NULL);
+    if (!(dpy = XOpenDisplay(NULL)))
+        errx(1, "Could not connect to X11");
 
     FILE *kc_config = fopen("../i3.config.kc", "r");
+    if (kc_config == NULL)
+        err(1, "Could not open input file \"%s\"", "../i3.config.kc");
+
+    FILE *ks_config = fopen(config_path, "w");
+    if (ks_config == NULL)
+        err(1, "Could not open output config file \"%s\"", config_path);
+
     char *line = NULL;
     size_t len = 0;
     ssize_t read;
+    bool head_of_file = true;
+
+    /* write a header about auto-generation to the output file */
+    fputs("# This file has been auto-generated by i3-config-wizard(1).\n", ks_config);
+    fputs("# It will not be overwritten, so edit it as you like.\n", ks_config);
+    fputs("#\n", ks_config);
+    fputs("# Should you change your keyboard layout somewhen, delete\n", ks_config);
+    fputs("# this file and re-run i3-config-wizard(1).\n", ks_config);
+    fputs("#\n", ks_config);
+    fputs("# See http://i3wm.org/docs/userguide.html\n", ks_config);
+
     while ((read = getline(&line, &len, kc_config)) != -1) {
-        /* See if that line is interesting by skipping leading whitespaces,
-         * then checking for 'bindcode' */
+        /* skip the warning block at the beginning of the input file */
+        if (head_of_file &&
+            strncmp("# WARNING", line, strlen("# WARNING")) == 0)
+            continue;
+
+        head_of_file = false;
+
+        /* Skip leading whitespace */
         char *walk = line;
         while (isspace(*walk) && walk < (line + len))
             walk++;
-        if (strncmp(walk, "bindcode", strlen("bindcode")) != 0)
+
+        /* Set the modifier the user chose */
+        if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) {
+            if (modifier == MOD_ALT)
+                fputs("set $mod Mod1\n", ks_config);
+            else fputs("set $mod Mod4\n", ks_config);
+            continue;
+        }
+
+        /* Check for 'bindcode'. If it’s not a bindcode line, we
+         * just copy it to the output file */
+        if (strncmp(walk, "bindcode", strlen("bindcode")) != 0) {
+            fputs(line, ks_config);
             continue;
+        }
         char *result = rewrite_binding(walk);
-        printf("in:  %s", walk);
-        printf("out: %s", result);
+        fputs(result, ks_config);
         free(result);
-
     }
 
+    /* sync to do our best in order to have the file really stored on disk */
+    fflush(ks_config);
+    fsync(fileno(ks_config));
+
     free(line);
     fclose(kc_config);
+    fclose(ks_config);
 
-    exit(0);
-#endif
+    /* tell i3 to reload the config file */
+    int sockfd = connect_ipc(socket_path);
+    ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload");
+    close(sockfd);
 
     exit(0);
 }