make openbox base-dir spec compliant, and change the theme dir structure, so that...
authorDana Jansens <danakj@orodu.net>
Mon, 15 Sep 2003 19:20:05 +0000 (19:20 +0000)
committerDana Jansens <danakj@orodu.net>
Mon, 15 Sep 2003 19:20:05 +0000 (19:20 +0000)
12 files changed:
Makefile.am
configure.ac
openbox/action.c
openbox/config.c
openbox/menu.c
openbox/openbox.c
openbox/openbox.h
openbox/session.c
parser/parse.c
parser/parse.h
render/obrender-3.0.pc.in
render/theme.c

index 99d58b8..32f389c 100644 (file)
@@ -1,14 +1,15 @@
 SUBDIRS = m4 po
 
-themedir        = $(datadir)/openbox/themes
+themedir        = $(datadir)/themes
 localedir       = $(datadir)/locale
-rcdir           = $(datadir)/openbox
+configdir       = $(sysconfdir)/xdg
+rcdir           = $(configdir)/openbox
 desktopfilesdir = $(datadir)/gnome/wm-properties
 pkgconfigdir    = $(libdir)/pkgconfig
 pubincludedir   = $(includedir)/openbox/@OB_VERSION@/openbox
 pixmapdir       = $(datadir)/pixmaps
 
-theme = thebear
+theme = TheBear
 
 AUTOMAKE_OPTIONS = subdir-objects
 ACLOCAL_AMFLAGS = -I m4
@@ -39,13 +40,14 @@ render_libobrender_la_CPPFLAGS = \
        $(X_CFLAGS) \
        $(XFT_CFLAGS) \
        $(GLIB_CFLAGS) \
+       $(XML_CFLAGS) \
        -DG_LOG_DOMAIN=\"ObRender\" \
-       -DDEFAULT_THEME=\"$(theme)\" \
-       -DTHEMEDIR=\"$(themedir)\"
+       -DDEFAULT_THEME=\"$(theme)\"
 render_libobrender_la_LIBADD = \
        $(X_LIBS) \
        $(XFT_LIBS) \
-       $(GLIB_LIBS)
+       $(GLIB_LIBS) \
+       parser/libobparser.la
 render_libobrender_la_SOURCES = \
        gettext.h \
        render/color.h \
@@ -74,7 +76,8 @@ parser_libobparser_la_CPPFLAGS = \
        $(XML_CFLAGS) \
        -DG_LOG_DOMAIN=\"ObParser\" \
        -DLOCALEDIR=\"$(localedir)\" \
-       -DRCDIR=\"$(rcdir)\"
+       -DDATADIR=\"$(datadir)\" \
+       -DCONFIGDIR=\"$(configdir)\"
 parser_libobparser_la_LIBADD = \
        $(GLIB_LIBS) \
        $(XML_LIBS)
@@ -92,7 +95,8 @@ openbox_openbox_CPPFLAGS = \
        $(LIBSN_CFLAGS) \
        $(XML_CFLAGS) \
        -DLOCALEDIR=\"$(localedir)\" \
-       -DRCDIR=\"$(rcdir)\" \
+       -DDATADIR=\"$(datadir)\" \
+       -DCONFIGDIR=\"$(configdir)\" \
        -DG_LOG_DOMAIN=\"Openbox\"
 openbox_openbox_LDADD = \
        $(SM_LIBS) \
@@ -194,43 +198,43 @@ tools_kdetrayproxy_kdetrayproxy_SOURCES = \
 
 ## themes ##
 
-allegro_themedir = $(themedir)/allegro
+allegro_themedir = $(themedir)/Allegro/openbox-3
 dist_allegro_theme_DATA = \
-       themes/allegro/themerc \
-       themes/allegro/bullet.xbm
+       themes/Allegro/openbox-3/themerc \
+       themes/Allegro/openbox-3/bullet.xbm
 
-artwiz_themedir = $(themedir)/artwiz
+artwiz_themedir = $(themedir)/Artwiz/openbox-3
 dist_artwiz_theme_DATA = \
-       themes/artwiz/themerc
+       themes/Artwiz/openbox-3/themerc
 
-blah41_themedir = $(themedir)/blah41
+blah41_themedir = $(themedir)/Blah41/openbox-3
 dist_blah41_theme_DATA = \
-       themes/blah41/themerc
+       themes/Blah41/openbox-3/themerc
 
-om4ob_themedir = $(themedir)/om4ob
+om4ob_themedir = $(themedir)/Om4Ob/openbox-3
 dist_om4ob_theme_DATA = \
-       themes/om4ob/themerc \
-       themes/om4ob/close_hover.xbm \
-       themes/om4ob/close.xbm \
-       themes/om4ob/desk_hover.xbm \
-       themes/om4ob/desk_toggled.xbm \
-       themes/om4ob/desk.xbm \
-       themes/om4ob/iconify_hover.xbm \
-       themes/om4ob/iconify_pressed.xbm \
-       themes/om4ob/iconify.xbm \
-       themes/om4ob/max_disabled.xbm \
-       themes/om4ob/max_hover.xbm \
-       themes/om4ob/max_pressed.xbm \
-       themes/om4ob/max_toggled.xbm \
-       themes/om4ob/max.xbm \
-       themes/om4ob/shade_disabled.xbm \
-       themes/om4ob/shade_hover.xbm \
-       themes/om4ob/shade_toggled.xbm \
-       themes/om4ob/shade.xbm
-
-thebear_themedir = $(themedir)/thebear
+       themes/Om4Ob/openbox-3/themerc \
+       themes/Om4Ob/openbox-3/close_hover.xbm \
+       themes/Om4Ob/openbox-3/close.xbm \
+       themes/Om4Ob/openbox-3/desk_hover.xbm \
+       themes/Om4Ob/openbox-3/desk_toggled.xbm \
+       themes/Om4Ob/openbox-3/desk.xbm \
+       themes/Om4Ob/openbox-3/iconify_hover.xbm \
+       themes/Om4Ob/openbox-3/iconify_pressed.xbm \
+       themes/Om4Ob/openbox-3/iconify.xbm \
+       themes/Om4Ob/openbox-3/max_disabled.xbm \
+       themes/Om4Ob/openbox-3/max_hover.xbm \
+       themes/Om4Ob/openbox-3/max_pressed.xbm \
+       themes/Om4Ob/openbox-3/max_toggled.xbm \
+       themes/Om4Ob/openbox-3/max.xbm \
+       themes/Om4Ob/openbox-3/shade_disabled.xbm \
+       themes/Om4Ob/openbox-3/shade_hover.xbm \
+       themes/Om4Ob/openbox-3/shade_toggled.xbm \
+       themes/Om4Ob/openbox-3/shade.xbm
+
+thebear_themedir = $(themedir)/TheBear
 dist_thebear_theme_DATA = \
-       themes/thebear/themerc
+       themes/TheBear/openbox-3/themerc
 
 
 ## public headers ##
index 299bcd3..9807c79 100644 (file)
@@ -15,9 +15,9 @@ dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
 dnl
 OB_MAJOR_VERSION=3
 OB_MINOR_VERSION=0
-OB_MICRO_VERSION=0
+OB_MICRO_VERSION=1
 OB_INTERFACE_AGE=0
-OB_BINARY_AGE=0
+OB_BINARY_AGE=1
 OB_VERSION=$OB_MAJOR_VERSION.$OB_MINOR_VERSION
 
 AC_SUBST(OB_MAJOR_VERSION)
index 0a969a8..adfa2d9 100644 (file)
@@ -723,7 +723,7 @@ ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
             if (act->func == action_execute || act->func == action_restart) {
                 if ((n = parse_find_node("execute", node->xmlChildrenNode))) {
                     gchar *s = parse_string(doc, n);
-                    act->data.execute.path = ob_expand_tilde(s);
+                    act->data.execute.path = parse_expand_tilde(s);
                     g_free(s);
                 }
             } else if (act->func == action_showmenu) {
index 4251390..b6ec290 100644 (file)
@@ -189,7 +189,7 @@ static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
 
         g_free(config_theme);
         c = parse_string(doc, n);
-        config_theme = ob_expand_tilde(c);
+        config_theme = parse_expand_tilde(c);
         g_free(c);
     }
     if ((n = parse_find_node("titleLayout", node))) {
@@ -304,7 +304,7 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, void *d)
 
             c = parse_string(doc, node);
             config_menu_files = g_slist_append(config_menu_files,
-                                               ob_expand_tilde(c));
+                                               parse_expand_tilde(c));
             g_free(c);
         }
     }
index 231777f..39dd60d 100644 (file)
@@ -34,35 +34,6 @@ static void parse_menu_separator(ObParseInst *i,
 static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
                        gpointer data);
 
-static gboolean menu_open(gchar *file, xmlDocPtr *doc, xmlNodePtr *node)
-{
-    gboolean loaded = TRUE;
-    gchar *p;
-
-    if (file[0] == '/') {
-        if (!parse_load(file, "openbox_menu", doc, node)) {
-            g_warning("Failed to load menu from '%s'", file);
-            loaded = FALSE;
-        }
-    } else {
-        p = g_build_filename(g_get_home_dir(), ".openbox", file, NULL);
-        if (!parse_load(p, "openbox_menu", doc, node)) {
-            g_free(p);
-            p = g_build_filename(RCDIR, file, NULL);
-            if (!parse_load(p, "openbox_menu", doc, node)) {
-                g_free(p);
-                p = g_strdup(file);
-                if (!parse_load(p, "openbox_menu", doc, node)) {
-                    g_warning("Failed to load menu from '%s'", file);
-                    loaded = FALSE;
-                }
-            }
-        }
-        g_free(p);
-    }
-    return loaded;
-}
-
 static void client_dest(gpointer client)
 {
     /* menus can be associated with a client, so close any that are since
@@ -94,14 +65,14 @@ void menu_startup(gboolean reconfig)
                    parse_menu_separator, &menu_parse_state);
 
     for (it = config_menu_files; it; it = g_slist_next(it)) {
-        if (menu_open(it->data, &doc, &node)) {
+        if (parse_load_menu(it->data, &doc, &node)) {
             loaded = TRUE;
             parse_tree(menu_parse_inst, doc, node->children);
             xmlFreeDoc(doc);
         }
     }
     if (!loaded) {
-        if (menu_open("menu.xml", &doc, &node)) {
+        if (parse_load_menu("menu.xml", &doc, &node)) {
             parse_tree(menu_parse_inst, doc, node->children);
             xmlFreeDoc(doc);
         }
@@ -225,7 +196,7 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         if ((menu = menu_new(name, title, NULL))) {
             menu->pipe_creator = state->pipe_creator;
             if (parse_attr_string("execute", node, &script)) {
-                menu->execute = ob_expand_tilde(script);
+                menu->execute = parse_expand_tilde(script);
             } else {
                 ObMenu *old;
 
index a3adb10..a8102c3 100644 (file)
@@ -29,7 +29,6 @@
 #  include <fcntl.h>
 #endif
 #ifdef HAVE_SIGNAL_H
-#define __USE_UNIX98
 #  include <signal.h>
 #endif
 #ifdef HAVE_STDLIB_H
@@ -68,8 +67,6 @@ static void parse_args(int argc, char **argv);
 
 int main(int argc, char **argv)
 {
-    char *path;
-
 #ifdef DEBUG
     ob_debug_show_output(TRUE);
 #endif
@@ -83,24 +80,10 @@ int main(int argc, char **argv)
     bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
     textdomain(PACKAGE_NAME);
 
-    /* create the ~/.openbox dir */
-    path = g_build_filename(g_get_home_dir(), ".openbox", NULL);
-    mkdir(path, (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP |
-                 S_IROTH | S_IWOTH | S_IXOTH));
-    g_free(path);
-    /* create the ~/.openbox/themes dir */
-    path = g_build_filename(g_get_home_dir(), ".openbox", "themes", NULL);
-    mkdir(path, (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP |
-                 S_IROTH | S_IWOTH | S_IXOTH));
-    g_free(path);
-    /* create the ~/.openbox/sessions dir */
-    path = g_build_filename(g_get_home_dir(), ".openbox", "sessions", NULL);
-    mkdir(path, (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP |
-                 S_IROTH | S_IWOTH | S_IXOTH));
-    g_free(path);
-
     g_set_prgname(argv[0]);
      
+    parse_paths_startup();
+
     session_startup(&argc, &argv);
 
     /* parse out command line args */
@@ -291,6 +274,8 @@ int main(int argc, char **argv)
 
     XCloseDisplay(ob_display);
 
+    parse_paths_shutdown();
+
     if (restart) {
         if (restart_path != NULL) {
             int argcp;
@@ -404,6 +389,12 @@ void ob_restart()
     ob_exit();
 }
 
+void ob_reconfigure()
+{
+    reconfigure = TRUE;
+    ob_exit();
+}
+
 void ob_exit()
 {
     ob_main_loop_exit(ob_main_loop);
@@ -425,22 +416,3 @@ ObState ob_state()
 {
     return state;
 }
-
-gchar *ob_expand_tilde(const gchar *f)
-{
-    gchar **spl;
-    gchar *ret;
-
-    if (!f)
-        return NULL;
-    spl = g_strsplit(f, "~", 0);
-    ret = g_strjoinv(g_get_home_dir(), spl);
-    g_strfreev(spl);
-    return ret;
-}
-
-void ob_reconfigure()
-{
-    reconfigure = TRUE;
-    ob_exit();
-}
index 9d7551b..a4e87a3 100644 (file)
@@ -41,6 +41,4 @@ Cursor ob_cursor(ObCursor cursor);
 
 KeyCode ob_keycode(ObKey key);
 
-gchar *ob_expand_tilde(const gchar *f);
-
 #endif
index 181dfe8..9ce0467 100644 (file)
@@ -42,6 +42,7 @@ static gchar      *save_file;
 static gchar      *sm_id;
 static gint        sm_argc;
 static gchar     **sm_argv;
+static gchar      *sm_sessions_path;
 
 static void session_load(char *path);
 static gboolean session_save();
@@ -141,6 +142,10 @@ void session_startup(int *argc, char ***argv)
     if (sm_disable)
         return;
 
+    sm_sessions_path = g_build_filename(parse_xdg_data_home_path(),
+                                        "openbox", "sessions", NULL);
+    parse_mkdir_path(sm_sessions_path, 0700);
+
     if (save_file)
         session_load(save_file);
 
@@ -224,6 +229,7 @@ void session_startup(int *argc, char ***argv)
 
 void session_shutdown()
 {
+    g_free(sm_sessions_path);
     g_free(save_file);
     g_free(sm_id);
 
@@ -298,8 +304,7 @@ static gboolean session_save()
                                (int) time(NULL),
                                (int) getpid(),
                                g_random_int());
-    save_file = g_build_filename(g_get_home_dir(), ".openbox", "sessions",
-                                 filename, NULL);
+    save_file = g_build_filename(sm_sessions_path, filename, NULL);
     g_free(filename);
 
     f = fopen(save_file, "w");
index a335315..e79eec6 100644 (file)
@@ -1,5 +1,14 @@
 #include "parse.h"
 #include <glib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+static gboolean xdg_start;
+static gchar   *xdg_config_home_path;
+static gchar   *xdg_data_home_path;
+static GSList  *xdg_config_dir_paths;
+static GSList  *xdg_data_dir_paths;
 
 struct Callback {
     char *tag;
@@ -52,25 +61,40 @@ void parse_register(ObParseInst *i, const char *tag,
 
 gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root)
 {
-    char *path;
+    GSList *it;
+    gchar *path;
     gboolean r = FALSE;
 
-    path = g_build_filename(g_get_home_dir(), ".openbox", "rc.xml", NULL);
-    if (parse_load(path, "openbox_config", doc, root)) {
-        r = TRUE;
-    } else {
+    for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) {
+        path = g_build_filename(it->data, "openbox", "rc.xml", NULL);
+        r = parse_load(path, "openbox_config", doc, root);
         g_free(path);
-        path = g_build_filename(RCDIR, "rc.xml", NULL);
-        if (parse_load(path, "openbox_config", doc, root)) {
-            r = TRUE;
-        }
     }
-    g_free(path);
     if (!r)
         g_warning("unable to find a valid config file, using defaults");
     return r;
 }
 
+gboolean parse_load_menu(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root)
+{
+    GSList *it;
+    gchar *path;
+    gboolean r = FALSE;
+
+    if (file[0] == '/') {
+        r = parse_load(file, "openbox_menu", doc, root);
+    } else {
+        for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) {
+            path = g_build_filename(it->data, "openbox", file, NULL);
+            r = parse_load(path, "openbox_menu", doc, root);
+            g_free(path);
+        }
+    }
+    if (!r)
+        g_warning("unable to find a valid menu file '%s'", file);
+    return r;
+}
+
 gboolean parse_load(const char *path, const char *rootname,
                     xmlDocPtr *doc, xmlNodePtr *root)
 {
@@ -216,3 +240,144 @@ gboolean parse_attr_contains(const char *val, xmlNodePtr node,
     xmlFree(c);
     return r;
 }
+
+static GSList* split_paths(const gchar *paths)
+{
+    GSList *list = NULL;
+    gchar *c, *e, *s;
+
+    c = g_strdup(paths);
+    s = c;
+    e = c - 1;
+    g_message("paths %s", paths);
+    while ((e = strchr(e + 1, ':'))) {
+        *e = '\0';
+        g_message("s %s", s);
+        if (s[0] != '\0')
+            list = g_slist_append(list, g_strdup(s));
+        s = e + 1;
+    }
+    if (s[0] != '\0')
+        list = g_slist_append(list, g_strdup(s));
+    g_free(c);
+    return list;
+}
+
+void parse_paths_startup()
+{
+    gchar *path;
+
+    if (xdg_start)
+        return;
+    xdg_start = TRUE;
+
+    path = getenv("XDG_CONFIG_HOME");
+    if (path && path[0] != '\0') /* not unset or empty */
+        xdg_config_home_path = g_build_filename(path, NULL);
+    else
+        xdg_config_home_path = g_build_filename(g_get_home_dir(), ".config",
+                                                NULL);
+
+    path = getenv("XDG_DATA_HOME");
+    if (path && path[0] != '\0') /* not unset or empty */
+        xdg_data_home_path = g_build_filename(path, NULL);
+    else
+        xdg_data_home_path = g_build_filename(g_get_home_dir(), ".local",
+                                              "share", NULL);
+
+    path = getenv("XDG_CONFIG_DIRS");
+    if (path && path[0] != '\0') /* not unset or empty */
+        xdg_config_dir_paths = split_paths(path);
+    else {
+        xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
+                                              g_build_filename
+                                              (G_DIR_SEPARATOR_S,
+                                               "etc", "xdg", NULL));
+        xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
+                                              g_strdup(CONFIGDIR));
+    }
+    xdg_config_dir_paths = g_slist_prepend(xdg_config_dir_paths,
+                                           xdg_config_home_path);
+    
+    path = getenv("XDG_DATA_DIRS");
+    if (path && path[0] != '\0') /* not unset or empty */
+        xdg_data_dir_paths = split_paths(path);
+    else {
+        xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
+                                            g_build_filename
+                                            (G_DIR_SEPARATOR_S,
+                                             "usr", "local", "share", NULL));
+        xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
+                                            g_build_filename
+                                            (G_DIR_SEPARATOR_S,
+                                             "usr", "share", NULL));
+        xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
+                                              g_strdup(DATADIR));
+    }
+    xdg_data_dir_paths = g_slist_prepend(xdg_data_dir_paths,
+                                         xdg_data_home_path);
+}
+
+void parse_paths_shutdown()
+{
+    GSList *it;
+
+    if (!xdg_start)
+        return;
+    xdg_start = FALSE;
+
+    for (it = xdg_config_dir_paths; it; it = g_slist_next(it))
+        g_free(it->data);
+    g_slist_free(xdg_config_dir_paths);
+    xdg_config_dir_paths = NULL;
+}
+
+gchar *parse_expand_tilde(const gchar *f)
+{
+    gchar **spl;
+    gchar *ret;
+
+    if (!f)
+        return NULL;
+    spl = g_strsplit(f, "~", 0);
+    ret = g_strjoinv(g_get_home_dir(), spl);
+    g_strfreev(spl);
+    return ret;
+}
+
+void parse_mkdir_path(const gchar *path, gint mode)
+{
+    gchar *c, *e;
+
+    g_assert(path[0] == '/');
+
+    c = g_strdup(path);
+    e = c;
+    while ((e = strchr(e + 1, '/'))) {
+        *e = '\0';
+        mkdir(c, mode);
+        *e = '/';
+    }
+    mkdir(c, mode);
+    g_free(c);
+}
+
+const gchar* parse_xdg_config_home_path()
+{
+    return xdg_config_home_path;
+}
+
+const gchar* parse_xdg_data_home_path()
+{
+    return xdg_data_home_path;
+}
+
+GSList* parse_xdg_config_dir_paths()
+{
+    return xdg_config_dir_paths;
+}
+
+GSList* parse_xdg_data_dir_paths()
+{
+    return xdg_data_dir_paths;
+}
index e6052cf..ec90b47 100644 (file)
@@ -12,8 +12,10 @@ typedef void (*ParseCallback)(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
 ObParseInst* parse_startup();
 void parse_shutdown(ObParseInst *inst);
 
-/* Loads Openbox's rc, from $HOME or $PREFIX as a fallback */
+/* Loads Openbox's rc, from the normal paths */
 gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root);
+/* Loads an Openbox menu, from the normal paths */
+gboolean parse_load_menu(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root);
 
 void parse_register(ObParseInst *inst, const char *tag,
                     ParseCallback func, gpointer data);
@@ -44,4 +46,20 @@ gboolean parse_attr_contains(const char *val, xmlNodePtr node,
 gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value);
 gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value);
 
+/* paths */
+
+void parse_paths_startup();
+void parse_paths_shutdown();
+
+const gchar* parse_xdg_config_home_path();
+const gchar* parse_xdg_data_home_path();
+GSList* parse_xdg_config_dir_paths();
+GSList* parse_xdg_data_dir_paths();
+
+/*! Expands the ~ character to the home directory throughout the given
+  string */
+gchar *parse_expand_tilde(const gchar *f);
+/*! Makes a directory and all its parents */
+void parse_mkdir_path(const gchar *path, gint mode);
+
 #endif
index 11a9177..ab908ac 100644 (file)
@@ -6,6 +6,6 @@ includedir=@includedir@
 Name: ObRender
 Description: Openbox Render Library
 Version: @VERSION@
-Requires: 
+Requires: obparser-3.0
 Libs: -L${libdir} -lobrender
 Cflags: -I${includedir}/openbox/@OB_VERSION@
index 907fd0b..8ad8c84 100644 (file)
@@ -4,6 +4,7 @@
 #include "mask.h"
 #include "theme.h"
 #include "icon.h"
+#include "parser/parse.h"
 
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
@@ -1059,21 +1060,29 @@ void RrThemeFree(RrTheme *theme)
 
 static XrmDatabase loaddb(RrTheme *theme, char *name)
 {
-    XrmDatabase db;
+    GSList *it;
+    XrmDatabase db = NULL;
+    gchar *s;
 
-    char *s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
-                               name, "themerc", NULL);
-    if ((db = XrmGetFileDatabase(s)))
-        theme->path = g_path_get_dirname(s);
-    g_free(s);
-    if (db == NULL) {
-       char *s = g_build_filename(THEMEDIR, name, "themerc", NULL);
+    if (name[0] == '/') {
+        s = g_build_filename(name, "openbox-3", "themerc", NULL);
        if ((db = XrmGetFileDatabase(s)))
             theme->path = g_path_get_dirname(s);
-       g_free(s);
+        g_free(s);
+    } else {
+        for (it = parse_xdg_data_dir_paths(); !db && it;
+             it = g_slist_next(it))
+        {
+            s = g_build_filename(it->data, "themes", name,
+                                 "openbox-3", "themerc", NULL);
+            if ((db = XrmGetFileDatabase(s)))
+                theme->path = g_path_get_dirname(s);
+            g_free(s);
+        }
     }
+
     if (db == NULL) {
-        char *s = g_build_filename(name, "themerc", NULL);
+        s = g_build_filename(name, "themerc", NULL);
        if ((db = XrmGetFileDatabase(s)))
             theme->path = g_path_get_dirname(s);
         g_free(s);