]> git.mdlowis.com Git - proto/labwc.git/commitdiff
src/rcxml.c: parse <keybind>
authorJohan Malm <jgm323@gmail.com>
Fri, 19 Jun 2020 21:00:22 +0000 (22:00 +0100)
committerJohan Malm <jgm323@gmail.com>
Fri, 19 Jun 2020 21:00:22 +0000 (22:00 +0100)
data/rc.xml
include/rcxml.h
include/spawn.h [new file with mode: 0644]
src/action.c
src/common/meson.build
src/common/spawn.c [new file with mode: 0644]
src/config/keybind.c
src/config/rcxml.c
src/main.c
tests/t1000-rcxml-simple-parse.c
tests/t1001-rcxml-nodenames-simple.c

index da9244bfe24d4283c9ba4da8ba2acb7f82ae614f..19798ef943b23f138cd1b8800d59be079822f99b 100644 (file)
   </keyboard>
 </lab>
 
-<!-- keybinds have not been implemented yet. For the time being, we use the
-     following:
-      - Alt+Escape  Exit labwc
-      - Alt+F2      Cycle windows
-      - Alt+F3      Launch dmenu -->
 <keyboard>
-
+  <keybind key="A-Escape">
+    <action name="Exit"/>
+  </keybind>
+  <keybind key="A-Tab">
+    <action name="NextWindow"/>
+  </keybind>
+  <keybind key="A-F2">
+    <action name="NextWindow"/>
+  </keybind>
+  <keybind key="A-F3">
+    <action name="Execute">
+      <command>dmenu_run</command>
+    </action>
+  </keybind>
 </keyboard>
 
 </openbox_config>
index 4bb7ab797a5938d269c7f7735b5e59829bbe44ef..55f9388453779cb99722c463c1f21c2425be045d 100644 (file)
@@ -9,17 +9,24 @@
 
 #include "buf.h"
 
+#define BUG_ON(condition)                                             \
+       do {                                                          \
+               if ((condition) != 0) {                               \
+                       fprintf(stderr, "Badness in %s() at %s:%d\n", \
+                               __func__, __FILE__, __LINE__);        \
+               }                                                     \
+       } while (0)
+
 struct keybind {
-        uint32_t modifiers;
-        xkb_keysym_t *keysyms;
-        size_t keysyms_len;
-        char *action;
-        struct wl_list link;
+       uint32_t modifiers;
+       xkb_keysym_t *keysyms;
+       size_t keysyms_len;
+       char *action;
+       char *command;
+       struct wl_list link;
 };
 
-void keybind_add(struct wl_list *keybinds, const char *keybind, const char *action);
-void keybind_init();
-void keybind_print();
+struct keybind *keybind_add(const char *keybind);
 
 struct rcxml {
        bool client_side_decorations;
@@ -28,7 +35,6 @@ struct rcxml {
 
 extern struct rcxml rc;
 
-void rcxml_init();
 void rcxml_parse_xml(struct buf *b);
 void rcxml_read(const char *filename);
 void rcxml_get_nodenames(struct buf *b);
diff --git a/include/spawn.h b/include/spawn.h
new file mode 100644 (file)
index 0000000..730bb08
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef SPAWN_H
+#define SPAWN_H
+
+void spawn_async_no_shell(char const *command);
+
+#endif /* SPAWN_H */
index 4087f341d52bf158963f3cb98d2a0370c388997b..8bbfb80430116167e8753e959cb5bb360a54f26e 100644 (file)
@@ -1,4 +1,5 @@
 #include "labwc.h"
+#include "spawn.h"
 
 #include <strings.h>
 
@@ -11,8 +12,7 @@ void action(struct server *server, struct keybind *keybind)
        } else if (!strcasecmp(keybind->action, "NextWindow")) {
                server->cycle_view = next_toplevel(view_front_toplevel(server));
        } else if (!strcasecmp(keybind->action, "Execute")) {
-               if (!fork())
-                       execl("/bin/dmenu_run", "/bin/dmenu_run", (void *)NULL);
+               spawn_async_no_shell(keybind->command);
        } else if (!strcasecmp(keybind->action, "debug-views")) {
                dbg_show_views(server);
        } else {
index d14bba6c6b2c9807490393e123a90c94eb3b3220..36446b5950db501fb27c0017051420f366e8402e 100644 (file)
@@ -1,3 +1,4 @@
 labwc_sources += files(
   'buf.c',
+  'spawn.c',
 )
diff --git a/src/common/spawn.c b/src/common/spawn.c
new file mode 100644 (file)
index 0000000..62eb80e
--- /dev/null
@@ -0,0 +1,22 @@
+#include <glib.h>
+
+void spawn_async_no_shell(char const *command)
+{
+       GError *err = NULL;
+       gchar **argv = NULL;
+
+       g_shell_parse_argv((gchar *)command, NULL, &argv, &err);
+       if (err) {
+               g_message("%s", err->message);
+               g_error_free(err);
+               return;
+       }
+       g_spawn_async(NULL, argv, NULL,
+                     G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+                     NULL, NULL, NULL, &err);
+       if (err) {
+               g_message("%s", err->message);
+               g_error_free(err);
+       }
+       g_strfreev(argv);
+}
index 81f53c01264e997767492de86dd15d014c823ffa..36c0985a573cacb67181c59fc647a0fc3bdbeb6e 100644 (file)
@@ -20,8 +20,7 @@ static uint32_t parse_modifier(const char *symname)
                return 0;
 }
 
-void keybind_add(struct wl_list *keybinds, const char *keybind,
-                const char *action)
+struct keybind *keybind_add(const char *keybind)
 {
        struct keybind *k = calloc(1, sizeof(struct keybind));
        xkb_keysym_t keysyms[32];
@@ -47,16 +46,10 @@ void keybind_add(struct wl_list *keybinds, const char *keybind,
        }
        g_strfreev(symnames);
        if (!k)
-               return;
-       wl_list_insert(keybinds, &k->link);
-       k->action = strdup(action);
+               return NULL;
+       wl_list_insert(&rc.keybinds, &k->link);
        k->keysyms = malloc(k->keysyms_len * sizeof(xkb_keysym_t));
        memcpy(k->keysyms, keysyms, k->keysyms_len * sizeof(xkb_keysym_t));
+       return k;
 }
 
-void keybind_init()
-{
-       keybind_add(&rc.keybinds, "A-Escape", "Exit");
-       keybind_add(&rc.keybinds, "A-Tab", "NextWindow");
-       keybind_add(&rc.keybinds, "A-F3", "Execute");
-}
index 3efb15e7bc740699685dcac188a05417d6f45585..7196daf815dda77174537f405b03a6a5ae0b23f0 100644 (file)
@@ -16,6 +16,7 @@ static bool in_keybind = false;
 static bool is_attribute = false;
 static bool write_to_nodename_buffer = false;
 static struct buf *nodename_buffer;
+static struct keybind *current_keybind;
 
 static void rstrip(char *buf, const char *pattern)
 {
@@ -27,9 +28,21 @@ static void rstrip(char *buf, const char *pattern)
 
 static void fill_keybind(xmlNode *n, char *nodename, char *content)
 {
+       if (!content)
+               return;
        rstrip(nodename, ".keybind.keyboard");
+       if (!strcmp(nodename, "key")) {
+               current_keybind = keybind_add(content);
+               fprintf(stderr, "[bind] %s: ", content);
+       }
+       /* We expect <keybind key=""> to come first */
+       BUG_ON(!current_keybind);
        if (!strcmp(nodename, "name.action")) {
-               ; /* TODO: populate keybind with stuff */
+               current_keybind->action = strdup(content);
+               fprintf(stderr, "%s", content);
+       } else if (!strcmp(nodename, "command.action")) {
+               current_keybind->command = strdup(content);
+               fprintf(stderr, " - %s", content);
        }
 }
 
@@ -69,18 +82,6 @@ static void entry(xmlNode *node, char *nodename, char *content)
                setenv("XKB_DEFAULT_LAYOUT", content, 1);
 }
 
-static void keybind_begin(void)
-{
-       /* TODO: xcalloc struct keybind */
-       in_keybind = true;
-}
-
-static void keybind_end(void)
-{
-       in_keybind = false;
-       /* TODO: wl_list_add keybind */
-}
-
 static char *nodename(xmlNode *node, char *buf, int len)
 {
        if (!node || !node->name)
@@ -141,9 +142,10 @@ static void xml_tree_walk(xmlNode *node)
                if (!strcasecmp((char *)n->name, "comment"))
                        continue;
                if (!strcasecmp((char *)n->name, "keybind")) {
-                       keybind_begin();
+                       in_keybind = true;
                        traverse(n);
-                       keybind_end();
+                       in_keybind = false;
+                       fprintf(stderr, "\n");
                        continue;
                }
                traverse(n);
@@ -163,11 +165,29 @@ void rcxml_parse_xml(struct buf *b)
        xmlCleanupParser();
 }
 
-void rcxml_init()
+static void rcxml_init()
 {
        LIBXML_TEST_VERSION
-       wl_list_init(&rc.keybinds);
-       keybind_init();
+}
+
+static void bind(const char *binding, const char *action)
+{
+       if (!binding || !action)
+               return;
+       struct keybind *k = keybind_add(binding);
+       if (k)
+               k->action = strdup(action);
+       fprintf(stderr, "binding: %s: %s\n", binding, action);
+}
+
+static void post_processing(void)
+{
+       if (!wl_list_length(&rc.keybinds)) {
+               fprintf(stderr, "info: loading default key bindings\n");
+               bind("A-Escape", "Exit");
+               bind("A-Tab", "NextWindow");
+               bind("A-F3", "Execute");
+       }
 }
 
 void rcxml_read(const char *filename)
@@ -177,11 +197,14 @@ void rcxml_read(const char *filename)
        size_t len = 0;
        struct buf b;
 
+       rcxml_init();
+       wl_list_init(&rc.keybinds);
+
        /* Read <filename> into buffer and then call rcxml_parse_xml() */
        stream = fopen(filename, "r");
        if (!stream) {
                fprintf(stderr, "warn: cannot read '%s'\n", filename);
-               return;
+               goto out;
        }
        buf_init(&b);
        while (getline(&line, &len, stream) != -1) {
@@ -194,6 +217,8 @@ void rcxml_read(const char *filename)
        fclose(stream);
        rcxml_parse_xml(&b);
        free(b.buf);
+out:
+       post_processing();
 }
 
 void rcxml_get_nodenames(struct buf *b)
index 3541ab9d83c31953383da7dfefde3ef0352766b4..3ae32391b4b407eb101063754dcde9569ca1a7ed 100644 (file)
@@ -26,7 +26,6 @@ int main(int argc, char *argv[])
                return 0;
        }
 
-       rcxml_init();
        rcxml_read("data/rc.xml");
        theme_read("data/themerc");
 
index cb41d0c14f5b9828c9d4f4a63317b38f43deb22c..e54fd2b26c91c25a3a663603f408d34dc69f903c 100644 (file)
@@ -27,7 +27,6 @@ int main(int argc, char **argv)
                exit(1);
        write(fd, src, sizeof(src) - 1);
 
-       rcxml_init();
        rcxml_read(template);
        unlink(template);
 
index 88c5a6f7639c88938689e6781a3af658d6ba505d..b90155bdada953b3740a0e6351c00bff75d389ef 100644 (file)
@@ -35,7 +35,6 @@ int main(int argc, char **argv)
        plan(1);
        diag("Parse simple rc.xml and read nodenames");
 
-       rcxml_init();
        rcxml_get_nodenames(&actual);
        rcxml_parse_xml(&source);
        printf("%s\n", actual.buf);