diff --git a/data/rc.xml b/data/rc.xml index da9244bf..19798ef9 100644 --- a/data/rc.xml +++ b/data/rc.xml @@ -14,13 +14,21 @@ - - + + + + + + + + + + + + dmenu_run + + diff --git a/include/rcxml.h b/include/rcxml.h index 4bb7ab79..55f93884 100644 --- a/include/rcxml.h +++ b/include/rcxml.h @@ -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 index 00000000..730bb08c --- /dev/null +++ b/include/spawn.h @@ -0,0 +1,6 @@ +#ifndef SPAWN_H +#define SPAWN_H + +void spawn_async_no_shell(char const *command); + +#endif /* SPAWN_H */ diff --git a/src/action.c b/src/action.c index 4087f341..8bbfb804 100644 --- a/src/action.c +++ b/src/action.c @@ -1,4 +1,5 @@ #include "labwc.h" +#include "spawn.h" #include @@ -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 { diff --git a/src/common/meson.build b/src/common/meson.build index d14bba6c..36446b59 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -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 index 00000000..62eb80e5 --- /dev/null +++ b/src/common/spawn.c @@ -0,0 +1,22 @@ +#include + +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); +} diff --git a/src/config/keybind.c b/src/config/keybind.c index 81f53c01..36c0985a 100644 --- a/src/config/keybind.c +++ b/src/config/keybind.c @@ -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"); -} diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 3efb15e7..7196daf8 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -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 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 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) diff --git a/src/main.c b/src/main.c index 3541ab9d..3ae32391 100644 --- a/src/main.c +++ b/src/main.c @@ -26,7 +26,6 @@ int main(int argc, char *argv[]) return 0; } - rcxml_init(); rcxml_read("data/rc.xml"); theme_read("data/themerc"); diff --git a/tests/t1000-rcxml-simple-parse.c b/tests/t1000-rcxml-simple-parse.c index cb41d0c1..e54fd2b2 100644 --- a/tests/t1000-rcxml-simple-parse.c +++ b/tests/t1000-rcxml-simple-parse.c @@ -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); diff --git a/tests/t1001-rcxml-nodenames-simple.c b/tests/t1001-rcxml-nodenames-simple.c index 88c5a6f7..b90155bd 100644 --- a/tests/t1001-rcxml-nodenames-simple.c +++ b/tests/t1001-rcxml-nodenames-simple.c @@ -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);