</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>
#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;
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);
--- /dev/null
+#ifndef SPAWN_H
+#define SPAWN_H
+
+void spawn_async_no_shell(char const *command);
+
+#endif /* SPAWN_H */
#include "labwc.h"
+#include "spawn.h"
#include <strings.h>
} 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 {
labwc_sources += files(
'buf.c',
+ 'spawn.c',
)
--- /dev/null
+#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);
+}
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];
}
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");
-}
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)
{
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);
}
}
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)
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);
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)
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) {
fclose(stream);
rcxml_parse_xml(&b);
free(b.buf);
+out:
+ post_processing();
}
void rcxml_get_nodenames(struct buf *b)
return 0;
}
- rcxml_init();
rcxml_read("data/rc.xml");
theme_read("data/themerc");
exit(1);
write(fd, src, sizeof(src) - 1);
- rcxml_init();
rcxml_read(template);
unlink(template);
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);