diff --git a/data/rc.xml b/data/rc.xml
new file mode 100644
index 00000000..032d68aa
--- /dev/null
+++ b/data/rc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+ no
+
+
+
diff --git a/include/labwc.h b/include/labwc.h
index 8885c03d..8e1e10d4 100644
--- a/include/labwc.h
+++ b/include/labwc.h
@@ -34,7 +34,6 @@
#define XCURSOR_MOVE "grabbing"
#define XWL_TITLEBAR_HEIGHT (10)
#define XWL_WINDOW_BORDER (3)
-#define LAB_DISABLE_CSD (0)
enum cursor_mode {
LAB_CURSOR_PASSTHROUGH,
diff --git a/include/rcxml.h b/include/rcxml.h
new file mode 100644
index 00000000..4e0c643e
--- /dev/null
+++ b/include/rcxml.h
@@ -0,0 +1,17 @@
+#ifndef RCXML_H
+#define RCXML_H
+
+#include
+#include
+
+struct rcxml {
+ bool client_side_decorations;
+};
+
+extern struct rcxml rc;
+
+void rcxml_init(struct rcxml *rc);
+void rcxml_read(const char *filename);
+void rcxml_set_verbose(void);
+
+#endif /* RCXML_H */
diff --git a/meson.build b/meson.build
index 01d0d941..9c2d8a5e 100644
--- a/meson.build
+++ b/meson.build
@@ -40,13 +40,16 @@ endif
wayland_server = dependency('wayland-server')
wayland_protos = dependency('wayland-protocols')
xkbcommon = dependency('xkbcommon')
+xml2 = dependency('libxml-2.0')
labwc_inc = include_directories('include')
subdir('protocols')
subdir('src')
-labwc_deps = [ server_protos, wayland_server, wlroots, xkbcommon, ]
+labwc_deps = [
+ server_protos, wayland_server, wlroots, xkbcommon, xml2
+]
executable(
meson.project_name(),
diff --git a/src/config/meson.build b/src/config/meson.build
new file mode 100644
index 00000000..19872e98
--- /dev/null
+++ b/src/config/meson.build
@@ -0,0 +1,3 @@
+labwc_sources += files(
+ 'rcxml.c',
+)
diff --git a/src/config/rcxml.c b/src/config/rcxml.c
new file mode 100644
index 00000000..495e5286
--- /dev/null
+++ b/src/config/rcxml.c
@@ -0,0 +1,174 @@
+#define _POSIX_C_SOURCE 200112L
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "rcxml.h"
+
+static bool in_keybind = false;
+static bool is_attribute = false;
+static bool verbose = false;
+
+static void rstrip(char *buf, const char *pattern)
+{
+ char *p = strstr(buf, pattern);
+ if (!p)
+ return;
+ *p = '\0';
+}
+
+static void fill_keybind(xmlNode *n, char *nodename, char *content)
+{
+ rstrip(nodename, ".keybind.keyboard");
+ if (!strcmp(nodename, "name.action")) {
+ ; /* TODO: populate keybind with stuff */
+ }
+}
+
+static bool get_bool(const char *s)
+{
+ if (!s)
+ return false;
+ if (!strcasecmp(s, "yes"))
+ return true;
+ if (!strcasecmp(s, "true"))
+ return true;
+ return false;
+}
+
+static void entry(xmlNode *node, char *nodename, char *content)
+{
+ if (!nodename)
+ return;
+ rstrip(nodename, ".openbox_config");
+ if (verbose) {
+ if (is_attribute)
+ printf("@");
+ printf("%s: %s\n", nodename, content);
+ }
+ if (!content)
+ return;
+ if (in_keybind)
+ fill_keybind(node, nodename, content);
+ if (!strcmp(nodename, "csd.wlroots"))
+ rc.client_side_decorations = get_bool(content);
+}
+
+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)
+ return NULL;
+
+ /* Ignore superflous 'text.' in node name */
+ if (node->parent && !strcmp((char *)node->name, "text"))
+ node = node->parent;
+
+ buf += len;
+ *--buf = 0;
+ len--;
+
+ char *p = buf;
+ p[--len] = 0;
+ for (;;) {
+ const char *name = (char *)node->name;
+ char c;
+ while ((c = *name++) != 0) {
+ *p++ = tolower(c);
+ if (!--len)
+ return buf;
+ }
+ *p = 0;
+ node = node->parent;
+ if (!node || !node->name)
+ return buf;
+ *p++ = '.';
+ if (!--len)
+ return buf;
+ }
+}
+
+static void process_node(xmlNode *node)
+{
+ char *content;
+ static char buffer[256];
+ char *name;
+
+ content = (char *)node->content;
+ if (xmlIsBlankNode(node))
+ return;
+ name = nodename(node, buffer, sizeof(buffer));
+ entry(node, name, content);
+}
+
+static void xml_tree_walk(xmlNode *node);
+
+static void traverse(xmlNode *n)
+{
+ process_node(n);
+ is_attribute = true;
+ for (xmlAttr *attr = n->properties; attr; attr = attr->next)
+ xml_tree_walk(attr->children);
+ is_attribute = false;
+ xml_tree_walk(n->children);
+}
+
+static void xml_tree_walk(xmlNode *node)
+{
+ for (xmlNode *n = node; n && n->name; n = n->next) {
+ if (!strcasecmp((char *)n->name, "comment"))
+ continue;
+ if (!strcasecmp((char *)n->name, "keybind")) {
+ keybind_begin();
+ traverse(n);
+ keybind_end();
+ continue;
+ }
+ traverse(n);
+ }
+}
+
+static void parse_xml(const char *filename)
+{
+ xmlDoc *d = xmlReadFile(filename, NULL, 0);
+ if (!d) {
+ fprintf(stderr, "fatal: error reading file '%s'\n", filename);
+ exit(EXIT_FAILURE);
+ }
+ printf("info: reading config file '%s'\n", filename);
+ xml_tree_walk(xmlDocGetRootElement(d));
+ xmlFreeDoc(d);
+ xmlCleanupParser();
+}
+
+void rcxml_init(struct rcxml *rc)
+{
+ LIBXML_TEST_VERSION
+}
+
+void rcxml_read(const char *filename)
+{
+ parse_xml(filename);
+}
+
+void rcxml_set_verbose(void)
+{
+ verbose = true;
+}
diff --git a/src/main.c b/src/main.c
index c43c5c9b..616b0bab 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,8 @@
#include "labwc.h"
+#include "rcxml.h"
struct server server = { 0 };
+struct rcxml rc = { 0 };
int main(int argc, char *argv[])
{
@@ -23,6 +25,10 @@ int main(int argc, char *argv[])
return 0;
}
+ rcxml_init(&rc);
+ rcxml_set_verbose();
+ rcxml_read("data/rc.xml");
+
/* Wayland requires XDG_RUNTIME_DIR to be set */
if (!getenv("XDG_RUNTIME_DIR")) {
wlr_log(WLR_ERROR, "XDG_RUNTIME_DIR is not set");
diff --git a/src/meson.build b/src/meson.build
index e68751fe..478f34ff 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -11,4 +11,5 @@ labwc_sources = files(
'xwl.c',
)
+subdir('config')
subdir('debug')
diff --git a/src/output.c b/src/output.c
index 8e577fa6..e5a23bcf 100644
--- a/src/output.c
+++ b/src/output.c
@@ -1,4 +1,5 @@
#include "labwc.h"
+#include "rcxml.h"
static float window_active_title_bg[] = { 0.29, 0.55, 0.78, 1.0 };
static float window_active_handle_bg[] = { 0.21, 0.49, 0.71, 1.0 };
@@ -23,7 +24,8 @@ static void render_cycle_box(struct output *output)
if (view != output->server->cycle_view)
continue;
struct wlr_box box;
- if ((view->type == LAB_XWAYLAND_VIEW) || LAB_DISABLE_CSD) {
+ if ((view->type == LAB_XWAYLAND_VIEW) ||
+ !rc.client_side_decorations) {
box = deco_max_extents(view);
} else {
box = view_get_surface_geometry(view);
diff --git a/src/server.c b/src/server.c
index babf0937..e496a534 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1,4 +1,5 @@
#include "labwc.h"
+#include "rcxml.h"
#include
#include
@@ -222,7 +223,7 @@ void server_init(struct server *server)
exit(EXIT_FAILURE);
}
wlr_server_decoration_manager_set_default_mode(
- deco_mgr, LAB_DISABLE_CSD ?
+ deco_mgr, !rc.client_side_decorations ?
WLR_SERVER_DECORATION_MANAGER_MODE_SERVER :
WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT);
diff --git a/src/view.c b/src/view.c
index 1107724c..87d395ea 100644
--- a/src/view.c
+++ b/src/view.c
@@ -1,4 +1,5 @@
#include "labwc.h"
+#include "rcxml.h"
static bool is_toplevel(struct view *view)
{
@@ -19,7 +20,7 @@ void view_init_position(struct view *view)
if (!is_toplevel(view))
return;
struct wlr_box box;
- if (view->type == LAB_XDG_SHELL_VIEW && !LAB_DISABLE_CSD) {
+ if (view->type == LAB_XDG_SHELL_VIEW && rc.client_side_decorations) {
/* CSD */
wlr_xdg_surface_get_geometry(view->xdg_surface, &box);
} else if (!view_want_deco(view)) {
@@ -88,7 +89,7 @@ bool view_want_deco(struct view *view)
{
if (!is_toplevel(view))
return false;
- if (view->type == LAB_XDG_SHELL_VIEW && !LAB_DISABLE_CSD)
+ if (view->type == LAB_XDG_SHELL_VIEW && rc.client_side_decorations)
return false;
if (view->type == LAB_XDG_SHELL_VIEW)
return true;
diff --git a/src/xdg.c b/src/xdg.c
index 52649329..e8ea18a6 100644
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -1,4 +1,5 @@
#include "labwc.h"
+#include "rcxml.h"
struct xdg_deco {
struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration;
@@ -22,7 +23,7 @@ static void xdg_deco_request_mode(struct wl_listener *listener, void *data)
struct xdg_deco *xdg_deco;
xdg_deco = wl_container_of(listener, xdg_deco, request_mode);
enum wlr_xdg_toplevel_decoration_v1_mode mode;
- if (LAB_DISABLE_CSD)
+ if (!rc.client_side_decorations)
mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
else
mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;