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>
</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>

View 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);

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 "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 {

View file

@ -1,3 +1,4 @@
labwc_sources += files(
'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;
}
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");
}

View 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)

View file

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

View 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);

View 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);