src/rcxml.c: parse <keybind>

This commit is contained in:
Johan Malm 2020-06-19 22:00:22 +01:00
parent f6578248c0
commit 158f42d1e8
11 changed files with 108 additions and 50 deletions

View file

@ -14,13 +14,21 @@
</keyboard> </keyboard>
</lab> </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> <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> </keyboard>
</openbox_config> </openbox_config>

View file

@ -9,17 +9,24 @@
#include "buf.h" #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 { struct keybind {
uint32_t modifiers; uint32_t modifiers;
xkb_keysym_t *keysyms; xkb_keysym_t *keysyms;
size_t keysyms_len; size_t keysyms_len;
char *action; char *action;
char *command;
struct wl_list link; struct wl_list link;
}; };
void keybind_add(struct wl_list *keybinds, const char *keybind, const char *action); struct keybind *keybind_add(const char *keybind);
void keybind_init();
void keybind_print();
struct rcxml { struct rcxml {
bool client_side_decorations; bool client_side_decorations;
@ -28,7 +35,6 @@ struct rcxml {
extern struct rcxml rc; extern struct rcxml rc;
void rcxml_init();
void rcxml_parse_xml(struct buf *b); void rcxml_parse_xml(struct buf *b);
void rcxml_read(const char *filename); void rcxml_read(const char *filename);
void rcxml_get_nodenames(struct buf *b); void rcxml_get_nodenames(struct buf *b);

6
include/spawn.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef SPAWN_H
#define SPAWN_H
void spawn_async_no_shell(char const *command);
#endif /* SPAWN_H */

View file

@ -1,4 +1,5 @@
#include "labwc.h" #include "labwc.h"
#include "spawn.h"
#include <strings.h> #include <strings.h>
@ -11,8 +12,7 @@ void action(struct server *server, struct keybind *keybind)
} else if (!strcasecmp(keybind->action, "NextWindow")) { } else if (!strcasecmp(keybind->action, "NextWindow")) {
server->cycle_view = next_toplevel(view_front_toplevel(server)); server->cycle_view = next_toplevel(view_front_toplevel(server));
} else if (!strcasecmp(keybind->action, "Execute")) { } else if (!strcasecmp(keybind->action, "Execute")) {
if (!fork()) spawn_async_no_shell(keybind->command);
execl("/bin/dmenu_run", "/bin/dmenu_run", (void *)NULL);
} else if (!strcasecmp(keybind->action, "debug-views")) { } else if (!strcasecmp(keybind->action, "debug-views")) {
dbg_show_views(server); dbg_show_views(server);
} else { } else {

View file

@ -1,3 +1,4 @@
labwc_sources += files( labwc_sources += files(
'buf.c', 'buf.c',
'spawn.c',
) )

22
src/common/spawn.c Normal file
View file

@ -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);
}

View file

@ -20,8 +20,7 @@ static uint32_t parse_modifier(const char *symname)
return 0; return 0;
} }
void keybind_add(struct wl_list *keybinds, const char *keybind, struct keybind *keybind_add(const char *keybind)
const char *action)
{ {
struct keybind *k = calloc(1, sizeof(struct keybind)); struct keybind *k = calloc(1, sizeof(struct keybind));
xkb_keysym_t keysyms[32]; xkb_keysym_t keysyms[32];
@ -47,16 +46,10 @@ void keybind_add(struct wl_list *keybinds, const char *keybind,
} }
g_strfreev(symnames); g_strfreev(symnames);
if (!k) if (!k)
return; return NULL;
wl_list_insert(keybinds, &k->link); wl_list_insert(&rc.keybinds, &k->link);
k->action = strdup(action);
k->keysyms = malloc(k->keysyms_len * sizeof(xkb_keysym_t)); k->keysyms = malloc(k->keysyms_len * sizeof(xkb_keysym_t));
memcpy(k->keysyms, keysyms, 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");
}

View file

@ -16,6 +16,7 @@ static bool in_keybind = false;
static bool is_attribute = false; static bool is_attribute = false;
static bool write_to_nodename_buffer = false; static bool write_to_nodename_buffer = false;
static struct buf *nodename_buffer; static struct buf *nodename_buffer;
static struct keybind *current_keybind;
static void rstrip(char *buf, const char *pattern) 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) static void fill_keybind(xmlNode *n, char *nodename, char *content)
{ {
if (!content)
return;
rstrip(nodename, ".keybind.keyboard"); 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")) { 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); 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) static char *nodename(xmlNode *node, char *buf, int len)
{ {
if (!node || !node->name) if (!node || !node->name)
@ -141,9 +142,10 @@ static void xml_tree_walk(xmlNode *node)
if (!strcasecmp((char *)n->name, "comment")) if (!strcasecmp((char *)n->name, "comment"))
continue; continue;
if (!strcasecmp((char *)n->name, "keybind")) { if (!strcasecmp((char *)n->name, "keybind")) {
keybind_begin(); in_keybind = true;
traverse(n); traverse(n);
keybind_end(); in_keybind = false;
fprintf(stderr, "\n");
continue; continue;
} }
traverse(n); traverse(n);
@ -163,11 +165,29 @@ void rcxml_parse_xml(struct buf *b)
xmlCleanupParser(); xmlCleanupParser();
} }
void rcxml_init() static void rcxml_init()
{ {
LIBXML_TEST_VERSION 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) void rcxml_read(const char *filename)
@ -177,11 +197,14 @@ void rcxml_read(const char *filename)
size_t len = 0; size_t len = 0;
struct buf b; struct buf b;
rcxml_init();
wl_list_init(&rc.keybinds);
/* Read <filename> into buffer and then call rcxml_parse_xml() */ /* Read <filename> into buffer and then call rcxml_parse_xml() */
stream = fopen(filename, "r"); stream = fopen(filename, "r");
if (!stream) { if (!stream) {
fprintf(stderr, "warn: cannot read '%s'\n", filename); fprintf(stderr, "warn: cannot read '%s'\n", filename);
return; goto out;
} }
buf_init(&b); buf_init(&b);
while (getline(&line, &len, stream) != -1) { while (getline(&line, &len, stream) != -1) {
@ -194,6 +217,8 @@ void rcxml_read(const char *filename)
fclose(stream); fclose(stream);
rcxml_parse_xml(&b); rcxml_parse_xml(&b);
free(b.buf); free(b.buf);
out:
post_processing();
} }
void rcxml_get_nodenames(struct buf *b) void rcxml_get_nodenames(struct buf *b)

View file

@ -26,7 +26,6 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
rcxml_init();
rcxml_read("data/rc.xml"); rcxml_read("data/rc.xml");
theme_read("data/themerc"); theme_read("data/themerc");

View file

@ -27,7 +27,6 @@ int main(int argc, char **argv)
exit(1); exit(1);
write(fd, src, sizeof(src) - 1); write(fd, src, sizeof(src) - 1);
rcxml_init();
rcxml_read(template); rcxml_read(template);
unlink(template); unlink(template);

View file

@ -35,7 +35,6 @@ int main(int argc, char **argv)
plan(1); plan(1);
diag("Parse simple rc.xml and read nodenames"); diag("Parse simple rc.xml and read nodenames");
rcxml_init();
rcxml_get_nodenames(&actual); rcxml_get_nodenames(&actual);
rcxml_parse_xml(&source); rcxml_parse_xml(&source);
printf("%s\n", actual.buf); printf("%s\n", actual.buf);