Merge branch 'backport' into work
authorDana Jansens <danakj@orodu.net>
Thu, 14 Feb 2008 20:14:41 +0000 (15:14 -0500)
committerDana Jansens <danakj@orodu.net>
Thu, 14 Feb 2008 20:14:41 +0000 (15:14 -0500)
105 files changed:
.gitignore
Makefile.am
README.GIT
configure.ac
data/rc.xml
m4/openbox.m4
obt/Makefile [moved from parser/Makefile with 100% similarity]
obt/display.c [new file with mode: 0644]
obt/display.h [new file with mode: 0644]
obt/internal.h [moved from openbox/xerror.h with 70% similarity]
obt/keyboard.c [moved from openbox/modkeys.c with 64% similarity]
obt/keyboard.h [moved from openbox/modkeys.h with 52% similarity]
obt/mainloop.c [moved from openbox/mainloop.c with 75% similarity]
obt/mainloop.h [new file with mode: 0644]
obt/obt-4.0.pc.in [new file with mode: 0644]
obt/parse.c [new file with mode: 0644]
obt/parse.h [new file with mode: 0644]
obt/paths.c [new file with mode: 0644]
obt/paths.h [new file with mode: 0644]
obt/prop.c [new file with mode: 0644]
obt/prop.h [new file with mode: 0644]
obt/util.h [new file with mode: 0644]
obt/version.h.in [new file with mode: 0644]
obt/xevent.c [new file with mode: 0644]
obt/xevent.h [new file with mode: 0644]
openbox/actions.c
openbox/actions.h
openbox/actions/addremovedesktop.c
openbox/actions/cyclewindows.c
openbox/actions/debug.c
openbox/actions/desktop.c
openbox/actions/directionalwindows.c
openbox/actions/execute.c
openbox/actions/focus.c
openbox/actions/growtoedge.c
openbox/actions/if.c
openbox/actions/layer.c
openbox/actions/maximize.c
openbox/actions/move.c
openbox/actions/moverelative.c
openbox/actions/moveresizeto.c
openbox/actions/movetoedge.c
openbox/actions/resize.c
openbox/actions/resizerelative.c
openbox/actions/restart.c
openbox/actions/showmenu.c
openbox/client.c
openbox/client.h
openbox/client_menu.c
openbox/config.c
openbox/config.h
openbox/debug.c
openbox/debug.h
openbox/dock.c
openbox/dock.h
openbox/event.c
openbox/event.h
openbox/extensions.c [deleted file]
openbox/extensions.h [deleted file]
openbox/focus.c
openbox/focus_cycle.c
openbox/focus_cycle.h
openbox/focus_cycle_indicator.c
openbox/focus_cycle_popup.c
openbox/focus_cycle_popup.h
openbox/frame.c
openbox/framerender.c
openbox/grab.c
openbox/keyboard.c
openbox/mainloop.h [deleted file]
openbox/menu.c
openbox/menu.h
openbox/menuframe.c
openbox/menuframe.h
openbox/mouse.c
openbox/moveresize.c
openbox/openbox.c
openbox/openbox.h
openbox/ping.c
openbox/place.c
openbox/popup.c
openbox/prompt.c
openbox/prompt.h
openbox/resist.c
openbox/resist.h
openbox/screen.c
openbox/session.c
openbox/stacking.c
openbox/startupnotify.c
openbox/translate.c
openbox/translate.h
openbox/window.c
openbox/window.h
openbox/xerror.c [deleted file]
parser/obparser-3.0.pc.in [deleted file]
parser/parse.c [deleted file]
parser/parse.h [deleted file]
po/POTFILES.in
render/obrender-4.0.pc.in [moved from render/obrender-3.0.pc.in with 86% similarity]
render/render.h
render/theme.c
render/theme.h
render/version.h.in [new file with mode: 0644]
tests/overrideinputonly.c [new file with mode: 0644]
version.h.in [deleted file]

index 3baae14..e937405 100644 (file)
@@ -32,7 +32,7 @@ m4/*.m4
 missing
 .dirstamp
 openbox/openbox
-parser/obparser-3.0.pc
+parser/obparser-4.0.pc
 po/Makefile.in.in
 po/Makevars.template
 po/POTFILES
@@ -48,7 +48,8 @@ po/en@boldquot.insert-header
 po/en@quot.insert-header
 po/remove-potcdate.sed
 *.gmo
-render/obrender-3.0.pc
+render/obrender-4.0.pc
+obt/obt-4.0.pc
 tools/gnome-panel-control/gnome-panel-control
 version.h
 .libs
index 051be7d..dd5bb6c 100644 (file)
@@ -8,7 +8,8 @@ rcdir           = $(configdir)/openbox
 xsessionsdir    = $(datadir)/xsessions
 gnomewmfilesdir = $(datadir)/gnome/wm-properties
 pkgconfigdir    = $(libdir)/pkgconfig
-pubincludedir   = $(includedir)/openbox/@OB_VERSION@/openbox
+obtpubincludedir= $(includedir)/openbox/@OBT_VERSION@/obt
+rrpubincludedir = $(includedir)/openbox/@RR_VERSION@/render
 pixmapdir       = $(datadir)/pixmaps
 xsddir          = $(datadir)/openbox
 
@@ -24,8 +25,8 @@ check_PROGRAMS = \
        render/rendertest
 
 lib_LTLIBRARIES = \
-       parser/libobparser.la \
-       render/libobrender.la
+       render/libobrender.la \
+       obt/libobt.la
 
 bin_PROGRAMS = \
        openbox/openbox \
@@ -47,7 +48,7 @@ render_rendertest_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        -DG_LOG_DOMAIN=\"RenderTest\"
 render_rendertest_LDADD = \
-       parser/libobparser.la \
+       obt/libobt.la \
        render/libobrender.la \
        $(GLIB_LIBS) \
        $(PANGO_LIBS) \
@@ -65,9 +66,9 @@ render_libobrender_la_CPPFLAGS = \
        -DG_LOG_DOMAIN=\"ObRender\" \
        -DDEFAULT_THEME=\"$(theme)\"
 render_libobrender_la_LDFLAGS = \
-       -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+       -version-info $(RR_CURRENT):$(RR_REVISION):$(RR_AGE)
 render_libobrender_la_LIBADD = \
-       parser/libobparser.la \
+       obt/libobt.la \
        $(X_LIBS) \
        $(PANGO_LIBS) \
        $(XFT_LIBS) \
@@ -96,33 +97,52 @@ render_libobrender_la_SOURCES = \
        render/theme.h \
        render/theme.c
 
-## parser ##
+## obt ##
 
-parser_libobparser_la_CPPFLAGS = \
+obt_libobt_la_CPPFLAGS = \
+       $(XINERAMA_CFLAGS) \
+       $(XKB_CFLAGS) \
+       $(XRANDR_CFLAGS) \
+       $(XSHAPE_CFLAGS) \
+       $(XSYNC_CFLAGS) \
        $(GLIB_CFLAGS) \
        $(XML_CFLAGS) \
-       -DG_LOG_DOMAIN=\"ObParser\" \
+       -DG_LOG_DOMAIN=\"Obt\" \
        -DLOCALEDIR=\"$(localedir)\" \
        -DDATADIR=\"$(datadir)\" \
        -DCONFIGDIR=\"$(configdir)\"
-parser_libobparser_la_LDFLAGS = \
-       -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
-parser_libobparser_la_LIBADD = \
+obt_libobt_la_LDFLAGS = \
+       -version-info $(OBT_CURRENT):$(OBT_REVISION):$(OBT_AGE)
+obt_libobt_la_LIBADD = \
+       $(XINERAMA_LIBS) \
+       $(XKB_LIBS) \
+       $(XRANDR_LIBS) \
+       $(XSHAPE_LIBS) \
+       $(XSYNC_LIBS) \
        $(GLIB_LIBS) \
-       $(XML_LIBS) 
-parser_libobparser_la_SOURCES = \
-       parser/parse.h \
-       parser/parse.c
+       $(XML_LIBS)
+obt_libobt_la_SOURCES = \
+       obt/display.h \
+       obt/display.c \
+       obt/internal.h \
+       obt/keyboard.h \
+       obt/keyboard.c \
+       obt/mainloop.h \
+       obt/mainloop.c \
+       obt/parse.h \
+       obt/parse.c \
+       obt/paths.h \
+       obt/paths.c \
+       obt/prop.h \
+       obt/prop.c \
+       obt/util.h \
+       obt/xevent.h \
+       obt/xevent.c
 
 ## openbox ##
 
 openbox_openbox_CPPFLAGS = \
        $(SM_CFLAGS) \
-       $(XINERAMA_CFLAGS) \
-       $(XKB_CFLAGS) \
-       $(XRANDR_CFLAGS) \
-       $(XSHAPE_CFLAGS) \
-       $(XSYNC_CFLAGS) \
        $(X_CFLAGS) \
        $(XCURSOR_CFLAGS) \
        $(SM_CFLAGS) \
@@ -136,11 +156,6 @@ openbox_openbox_CPPFLAGS = \
        -DG_LOG_DOMAIN=\"Openbox\"
 openbox_openbox_LDADD = \
        $(SM_LIBS) \
-       $(XINERAMA_LIBS) \
-       $(XKB_LIBS) \
-       $(XRANDR_LIBS) \
-       $(XSHAPE_LIBS) \
-       $(XSYNC_LIBS) \
        $(GLIB_LIBS) \
        $(X_LIBS) \
        $(XCURSOR_LIBS) \
@@ -149,7 +164,7 @@ openbox_openbox_LDADD = \
        $(EFENCE_LIBS) \
        $(LIBINTL) \
        render/libobrender.la \
-       parser/libobparser.la
+       obt/libobt.la
 openbox_openbox_LDFLAGS = -export-dynamic
 openbox_openbox_SOURCES = \
        gettext.h \
@@ -209,8 +224,6 @@ openbox_openbox_SOURCES = \
        openbox/dock.h \
        openbox/event.c \
        openbox/event.h \
-       openbox/extensions.c \
-       openbox/extensions.h \
        openbox/focus.c \
        openbox/focus.h \
        openbox/focus_cycle.c \
@@ -232,15 +245,11 @@ openbox_openbox_SOURCES = \
        openbox/keyboard.h \
        openbox/keytree.c \
        openbox/keytree.h \
-       openbox/mainloop.c \
-       openbox/mainloop.h \
        openbox/menuframe.c \
        openbox/menuframe.h \
        openbox/menu.c \
        openbox/menu.h \
        openbox/misc.h \
-       openbox/modkeys.c \
-       openbox/modkeys.h \
        openbox/mouse.c \
        openbox/mouse.h \
        openbox/moveresize.c \
@@ -256,8 +265,6 @@ openbox_openbox_SOURCES = \
        openbox/prompt.h \
        openbox/popup.c \
        openbox/popup.h \
-       openbox/prop.c \
-       openbox/prop.h \
        openbox/resist.c \
        openbox/resist.h \
        openbox/screen.c \
@@ -271,10 +278,7 @@ openbox_openbox_SOURCES = \
        openbox/translate.c \
        openbox/translate.h \
        openbox/window.c \
-       openbox/window.h \
-       openbox/xerror.c \
-       openbox/xerror.h
-
+       openbox/window.h
 
 ## gnome-panel-control ##
 
@@ -380,7 +384,7 @@ dist_syscrash_theme_DATA= \
 
 ## public headers ##
 
-pubinclude_HEADERS = \
+rrpubinclude_HEADERS = \
        render/color.h \
        render/font.h \
        render/geom.h \
@@ -390,14 +394,22 @@ pubinclude_HEADERS = \
        render/mask.h \
        render/render.h \
        render/theme.h \
-       parser/parse.h
-
-nodist_pubinclude_HEADERS = \
-       version.h
+       render/version.h
+
+obtpubinclude_HEADERS = \
+       obt/display.h \
+       obt/keyboard.h \
+       obt/mainloop.h \
+       obt/parse.h \
+       obt/paths.h \
+       obt/prop.h \
+       obt/util.h \
+       obt/version.h \
+       obt/xevent.h
 
 nodist_pkgconfig_DATA = \
-       render/obrender-3.0.pc \
-       parser/obparser-3.0.pc
+       render/obrender-4.0.pc \
+       obt/obt-4.0.pc
 
 ## data ##
 
@@ -439,7 +451,6 @@ nodist_xsessions_DATA = \
        data/xsession/openbox-kde.desktop
 
 dist_noinst_DATA = \
-       version.h.in \
        data/rc.xsd \
        data/menu.xsd \
        data/xsession/openbox.desktop.in \
@@ -456,8 +467,10 @@ dist_noinst_DATA = \
        doc/openbox-gnome-session.1.in \
        doc/openbox-kde-session.1.sgml \
        doc/openbox-kde-session.1.in \
-       render/obrender-3.0.pc.in \
-       parser/obparser-3.0.pc.in \
+       render/version.h.in \
+       render/obrender-4.0.pc.in \
+       obt/obt-4.0.pc.in \
+       obt/version.h.in \
        tools/themeupdate/themeupdate.py \
        tests/hideshow.py \
        tests/Makefile \
@@ -513,7 +526,7 @@ CLEANFILES = \
 #       $(MAKE) -$(MAKEFLAGS) -C doc/doxygen doc
 
 distclean-local:
-       for d in . m4 po render; do \
+       for d in . m4 po render parser obt openbox; do \
                for p in core core.* gmon.out *\~ *.orig *.rej .\#*; do \
                        rm -f "$$d/$$p"; \
                done \
index c50118e..b4b0557 100644 (file)
@@ -3,7 +3,7 @@ To build Openbox from git you need:
 A C Compiler (GNU GCC 3.2+ suggested)
 GNU Gettext 0.14.4
 GNU Autoconf 2.50+
-GNU Automake 1.9+
+GNU Automake 1.9 (no more, no less)
 GNU Libtool
 Xlib library/headers (devel package)
 Pkg-Config
index 53e5001..463e7fb 100644 (file)
@@ -4,41 +4,65 @@ AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([openbox/openbox.c])
 
 dnl Making releases:
-dnl   OB_MICRO_VERSION += 1;
-dnl   OB_INTERFACE_AGE += 1;
-dnl   OB_BINARY_AGE += 1;
-dnl if any functions have been added, set OB_INTERFACE_AGE to 0.
+dnl   RR_MICRO_VERSION += 1;
+dnl   RR_INTERFACE_AGE += 1;
+dnl   R_BINARY_AGE += 1;
+dnl if any functions have been added, set RR_INTERFACE_AGE to 0.
 dnl if backwards compatibility has been broken,
-dnl set OB_BINARY_AGE and OB_INTERFACE_AGE to 0.
+dnl set RR_BINARY_AGE and RR_INTERFACE_AGE to 0.
 dnl
 dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
 dnl
-OB_MAJOR_VERSION=3
-OB_MINOR_VERSION=4
-OB_MICRO_VERSION=16
-OB_INTERFACE_AGE=0
-OB_BINARY_AGE=0
-OB_VERSION=$OB_MAJOR_VERSION.$OB_MINOR_VERSION
-
-AC_SUBST(OB_MAJOR_VERSION)
-AC_SUBST(OB_MINOR_VERSION)
-AC_SUBST(OB_MICRO_VERSION)
-AC_SUBST(OB_INTERFACE_AGE)
-AC_SUBST(OB_BINARY_AGE)
-AC_SUBST(OB_VERSION)
+RR_MAJOR_VERSION=4
+RR_MINOR_VERSION=0
+RR_MICRO_VERSION=17
+RR_INTERFACE_AGE=0
+RR_BINARY_AGE=0
+RR_VERSION=$RR_MAJOR_VERSION.$RR_MINOR_VERSION
+
+OBT_MAJOR_VERSION=4
+OBT_MINOR_VERSION=0
+OBT_MICRO_VERSION=0
+OBT_INTERFACE_AGE=0
+OBT_BINARY_AGE=0
+OBT_VERSION=$OBT_MAJOR_VERSION.$OBT_MINOR_VERSION
+
+AC_SUBST(RR_MAJOR_VERSION)
+AC_SUBST(RR_MINOR_VERSION)
+AC_SUBST(RR_MICRO_VERSION)
+AC_SUBST(RR_INTERFACE_AGE)
+AC_SUBST(RR_BINARY_AGE)
+AC_SUBST(RR_VERSION)
+AC_SUBST(OBT_MAJOR_VERSION)
+AC_SUBST(OBT_MINOR_VERSION)
+AC_SUBST(OBT_MICRO_VERSION)
+AC_SUBST(OBT_INTERFACE_AGE)
+AC_SUBST(OBT_BINARY_AGE)
+AC_SUBST(OBT_VERSION)
 
 dnl Libtool versioning
-LT_RELEASE=$OB_MAJOR_VERSION.$OB_MINOR_VERSION
-LT_CURRENT=`expr $OB_MICRO_VERSION - $OB_INTERFACE_AGE`
-LT_REVISION=$OB_INTERFACE_AGE
-LT_AGE=`expr $OB_BINARY_AGE - $OB_INTERFACE_AGE`
-LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
-
-AC_SUBST(LT_RELEASE)
-AC_SUBST(LT_CURRENT)
-AC_SUBST(LT_REVISION)
-AC_SUBST(LT_AGE)
-AC_SUBST(LT_CURRENT_MINUS_AGE)
+RR_RELEASE=$RR_MAJOR_VERSION.$RR_MINOR_VERSION
+RR_CURRENT=`expr $RR_MICRO_VERSION - $RR_INTERFACE_AGE`
+RR_REVISION=$RR_INTERFACE_AGE
+RR_AGE=`expr $RR_BINARY_AGE - $RR_INTERFACE_AGE`
+RR_CURRENT_MINUS_AGE=`expr $RR_CURRENT - $RR_AGE`
+
+OBT_RELEASE=$OBT_MAJOR_VERSION.$OBT_MINOR_VERSION
+OBT_CURRENT=`expr $OBT_MICRO_VERSION - $OBT_INTERFACE_AGE`
+OBT_REVISION=$OBT_INTERFACE_AGE
+OBT_AGE=`expr $OBT_BINARY_AGE - $OBT_INTERFACE_AGE`
+OBT_CURRENT_MINUS_AGE=`expr $OBT_CURRENT - $OBT_AGE`
+
+AC_SUBST(RR_RELEASE)
+AC_SUBST(RR_CURRENT)
+AC_SUBST(RR_REVISION)
+AC_SUBST(RR_AGE)
+AC_SUBST(RR_CURRENT_MINUS_AGE)
+AC_SUBST(OBT_RELEASE)
+AC_SUBST(OBT_CURRENT)
+AC_SUBST(OBT_REVISION)
+AC_SUBST(OBT_AGE)
+AC_SUBST(OBT_CURRENT_MINUS_AGE)
 
 AC_PREFIX_DEFAULT([/usr/local])
 test "$prefix" = "NONE" && prefix=$ac_default_prefix
@@ -154,9 +178,10 @@ AC_CONFIG_FILES([
   Makefile
   m4/Makefile
   po/Makefile.in
-  render/obrender-3.0.pc
-  parser/obparser-3.0.pc
-  version.h
+  render/obrender-4.0.pc
+  obt/obt-4.0.pc
+  render/version.h
+  obt/version.h
 ])
 AC_CONFIG_COMMANDS([doc],
                    [test -d doc || mkdir doc])
index ebe2f31..f223f67 100644 (file)
     </mousebind>
 
     <mousebind button="Up" action="Click">
-      <action name="Shade"/>
-      <action name="FocusToBottom"/>
-      <action name="Unfocus"/>
-      <action name="Lower"/>
+      <action name="if">
+        <shaded>no</shaded>
+        <then>
+          <action name="Shade"/>
+          <action name="FocusToBottom"/>
+          <action name="Unfocus"/>
+          <action name="Lower"/>
+        </then>
+      </action>
     </mousebind>
     <mousebind button="Down" action="Click">
-      <action name="Unshade"/>
-      <action name="Raise"/>
+      <action name="if">
+        <shaded>yes</shaded>
+        <then>
+          <action name="Unshade"/>
+          <action name="Raise"/>
+        </then>
+      </action>
     </mousebind>
 
     <mousebind button="Right" action="Press">
   </context>
 
   <context name="Desktop">
-    <mousebind button="Up" action="Press">
+    <mousebind button="Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="Down" action="Press">
+    <mousebind button="Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
 
-    <mousebind button="A-Up" action="Press">
+    <mousebind button="A-Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="A-Down" action="Press">
+    <mousebind button="A-Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
-    <mousebind button="C-A-Up" action="Press">
+    <mousebind button="C-A-Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="C-A-Down" action="Press">
+    <mousebind button="C-A-Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
 
   </context>
 
   <context name="MoveResize">
-    <mousebind button="Up" action="Press">
+    <mousebind button="Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="Down" action="Press">
+    <mousebind button="Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
-    <mousebind button="A-Up" action="Press">
+    <mousebind button="A-Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="A-Down" action="Press">
+    <mousebind button="A-Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
   </context>
index 5c3aeec..5a95e84 100644 (file)
@@ -74,7 +74,7 @@ AC_DEFUN([OB_COMPILER_FLAGS],
     if test "$GCC" = "yes"; then
        AC_MSG_RESULT([yes])
        if test "$DEBUG" = "yes"; then
-           FLAGS="$FLAGS -O0 -g3 -fno-inline -Wwrite-strings"
+           FLAGS="$FLAGS -O0 -ggdb -fno-inline -Wwrite-strings"
            FLAGS="$FLAGS -Wall -Wsign-compare -Waggregate-return"
            FLAGS="$FLAGS -Wcast-qual -Wbad-function-cast -Wpointer-arith"
             # for Python.h
similarity index 100%
rename from parser/Makefile
rename to obt/Makefile
diff --git a/obt/display.c b/obt/display.c
new file mode 100644 (file)
index 0000000..d72f8ad
--- /dev/null
@@ -0,0 +1,152 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/display.c for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/display.h"
+#include "obt/prop.h"
+#include "obt/internal.h"
+#include "obt/keyboard.h"
+
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+Display* obt_display = NULL;
+
+gboolean obt_display_error_occured = FALSE;
+
+gboolean obt_display_extension_xkb       = FALSE;
+gint     obt_display_extension_xkb_basep;
+gboolean obt_display_extension_shape     = FALSE;
+gint     obt_display_extension_shape_basep;
+gboolean obt_display_extension_xinerama  = FALSE;
+gint     obt_display_extension_xinerama_basep;
+gboolean obt_display_extension_randr     = FALSE;
+gint     obt_display_extension_randr_basep;
+gboolean obt_display_extension_sync      = FALSE;
+gint     obt_display_extension_sync_basep;
+
+static gint xerror_handler(Display *d, XErrorEvent *e);
+
+static gboolean xerror_ignore = FALSE;
+
+gboolean obt_display_open(const char *display_name)
+{
+    gchar *n;
+    Display *d = NULL;
+
+    n = display_name ? g_strdup(display_name) : NULL;
+    obt_display = d = XOpenDisplay(n);
+    if (d) {
+        gint junk;
+        (void)junk;
+
+        if (fcntl(ConnectionNumber(d), F_SETFD, 1) == -1)
+            g_message("Failed to set display as close-on-exec");
+        XSetErrorHandler(xerror_handler);
+
+        /* read what extensions are present */
+#ifdef XKB
+        obt_display_extension_xkb =
+            XkbQueryExtension(d, &junk,
+                              &obt_display_extension_xkb_basep, &junk,
+                              NULL, NULL);
+        if (!obt_display_extension_xkb)
+            g_message("XKB extension is not present on the server");
+#endif
+
+#ifdef SHAPE
+        obt_display_extension_shape =
+            XShapeQueryExtension(d, &obt_display_extension_shape_basep,
+                                 &junk);
+        if (!obt_display_extension_shape)
+            g_message("X Shape extension is not present on the server");
+#endif
+
+#ifdef XINERAMA
+        obt_display_extension_xinerama =
+            XineramaQueryExtension(d,
+                                   &obt_display_extension_xinerama_basep,
+                                   &junk) && XineramaIsActive(d);
+        if (!obt_display_extension_xinerama)
+            g_message("Xinerama extension is not present on the server");
+#endif
+
+#ifdef XRANDR
+        obt_display_extension_randr =
+            XRRQueryExtension(d, &obt_display_extension_randr_basep,
+                              &junk);
+        if (!obt_display_extension_randr)
+            g_message("XRandR extension is not present on the server");
+#endif
+
+#ifdef SYNC
+        obt_display_extension_sync =
+            XSyncQueryExtension(d, &obt_display_extension_sync_basep,
+                                &junk) && XSyncInitialize(d, &junk, &junk);
+        if (!obt_display_extension_sync)
+            g_message("X Sync extension is not present on the server or is an "
+                      "incompatible version");
+#endif
+
+        obt_prop_startup();
+        obt_keyboard_reload();
+    }
+    g_free(n);
+
+    return obt_display != NULL;
+}
+
+void obt_display_close()
+{
+    obt_keyboard_shutdown();
+    if (obt_display) XCloseDisplay(obt_display);
+}
+
+static gint xerror_handler(Display *d, XErrorEvent *e)
+{
+#ifdef DEBUG
+    gchar errtxt[128];
+
+    XGetErrorText(d, e->error_code, errtxt, 127);
+    if (!xerror_ignore) {
+        if (e->error_code == BadWindow)
+            /*g_message(_("X Error: %s\n"), errtxt)*/;
+        else
+            g_error("X Error: %s", errtxt);
+    } else
+        g_message("Ignoring XError code %d '%s'", e->error_code, errtxt);
+#else
+    (void)d; (void)e;
+#endif
+
+    obt_display_error_occured = TRUE;
+    return 0;
+}
+
+void obt_display_ignore_errors(gboolean ignore)
+{
+    XSync(obt_display, FALSE);
+    xerror_ignore = ignore;
+    if (ignore) obt_display_error_occured = FALSE;
+}
diff --git a/obt/display.h b/obt/display.h
new file mode 100644 (file)
index 0000000..8c074b5
--- /dev/null
@@ -0,0 +1,68 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/display.h for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_display_h
+#define __obt_display_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+#include <X11/Xutil.h> /* shape.h uses Region which is in here */
+#ifdef    XKB
+#include <X11/XKBlib.h>
+#endif
+#ifdef    SHAPE
+#include <X11/extensions/shape.h>
+#endif
+#ifdef    XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+#ifdef    XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#ifdef    SYNC
+#include <X11/extensions/sync.h>
+#endif
+
+G_BEGIN_DECLS
+
+extern gboolean obt_display_error_occured;
+
+extern gboolean obt_display_extension_xkb;
+extern gint     obt_display_extension_xkb_basep;
+extern gboolean obt_display_extension_shape;
+extern gint     obt_display_extension_shape_basep;
+extern gboolean obt_display_extension_xinerama;
+extern gint     obt_display_extension_xinerama_basep;
+extern gboolean obt_display_extension_randr;
+extern gint     obt_display_extension_randr_basep;
+extern gboolean obt_display_extension_sync;
+extern gint     obt_display_extension_sync_basep;
+
+extern Display* obt_display;
+
+gboolean obt_display_open(const char *display_name);
+void     obt_display_close();
+
+void     obt_display_ignore_errors(gboolean ignore);
+
+#define  obt_root(screen) (RootWindow(obt_display, screen))
+
+G_END_DECLS
+
+#endif /*__obt_display_h*/
similarity index 70%
rename from openbox/xerror.h
rename to obt/internal.h
index de1aa5a..dae854c 100644 (file)
@@ -1,6 +1,7 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
-   xerror.h for the Openbox window manager
+   obt/internal.h for the Openbox window manager
+   Copyright (c) 2006        Mikael Magnusson
    Copyright (c) 2003-2007   Dana Jansens
 
    This program is free software; you can redistribute it and/or modify
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#ifndef __xerror_h
-#define __xerror_h
+#ifndef __obt_internal_h
+#define __obt_internal_h
 
-#include <X11/Xlib.h>
-#include <glib.h>
+void obt_prop_startup();
 
-/* can be used to track errors */
-extern gboolean xerror_occured;
+void obt_keyboard_shutdown();
 
-gint xerror_handler(Display *, XErrorEvent *);
-
-void xerror_set_ignore(gboolean ignore);
-
-#endif
+#endif /* __obt_internal_h */
similarity index 64%
rename from openbox/modkeys.c
rename to obt/keyboard.c
index 9e8da32..710a94c 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
-   modkeys.c for the Openbox window manager
+   obt/keyboard.c for the Openbox window manager
    Copyright (c) 2007        Dana Jansens
 
    This program is free software; you can redistribute it and/or modify
@@ -16,8 +16,8 @@
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#include "modkeys.h"
-#include "openbox.h"
+#include "obt/display.h"
+#include "obt/keyboard.h"
 
 #include <X11/Xlib.h>
 #include <X11/keysym.h>
 #define nth_mask(n) (1 << n)
 
 static void set_modkey_mask(guchar mask, KeySym sym);
+void obt_keyboard_shutdown();
 
 static XModifierKeymap *modmap;
 static KeySym *keymap;
 static gint min_keycode, max_keycode, keysyms_per_keycode;
 /* This is a bitmask of the different masks for each modifier key */
-static guchar modkeys_keys[OB_MODKEY_NUM_KEYS];
+static guchar modkeys_keys[OBT_KEYBOARD_NUM_MODKEYS];
 
 static gboolean alt_l = FALSE;
 static gboolean meta_l = FALSE;
 static gboolean super_l = FALSE;
 static gboolean hyper_l = FALSE;
 
-void modkeys_startup(gboolean reconfigure)
+static gboolean started = FALSE;
+
+void obt_keyboard_reload()
 {
     gint i, j, k;
 
+    if (started) obt_keyboard_shutdown(); /* free stuff */
+    started = TRUE;
+
     /* reset the keys to not be bound to any masks */
-    for (i = 0; i < OB_MODKEY_NUM_KEYS; ++i)
+    for (i = 0; i < OBT_KEYBOARD_NUM_MODKEYS; ++i)
         modkeys_keys[i] = 0;
 
-    modmap = XGetModifierMapping(ob_display);
+    modmap = XGetModifierMapping(obt_display);
     g_assert(modmap->max_keypermod > 0);
 
-    XDisplayKeycodes(ob_display, &min_keycode, &max_keycode);
-    keymap = XGetKeyboardMapping(ob_display, min_keycode,
+    XDisplayKeycodes(obt_display, &min_keycode, &max_keycode);
+    keymap = XGetKeyboardMapping(obt_display, min_keycode,
                                  max_keycode - min_keycode + 1,
                                  &keysyms_per_keycode);
 
@@ -86,18 +92,21 @@ void modkeys_startup(gboolean reconfigure)
     }
 
     /* CapsLock, Shift, and Control are special and hard-coded */
-    modkeys_keys[OB_MODKEY_KEY_CAPSLOCK] = LockMask;
-    modkeys_keys[OB_MODKEY_KEY_SHIFT] = ShiftMask;
-    modkeys_keys[OB_MODKEY_KEY_CONTROL] = ControlMask;
+    modkeys_keys[OBT_KEYBOARD_MODKEY_CAPSLOCK] = LockMask;
+    modkeys_keys[OBT_KEYBOARD_MODKEY_SHIFT] = ShiftMask;
+    modkeys_keys[OBT_KEYBOARD_MODKEY_CONTROL] = ControlMask;
 }
 
-void modkeys_shutdown(gboolean reconfigure)
+void obt_keyboard_shutdown()
 {
     XFreeModifiermap(modmap);
+    modmap = NULL;
     XFree(keymap);
+    keymap = NULL;
+    started = FALSE;
 }
 
-guint modkeys_keycode_to_mask(guint keycode)
+guint obt_keyboard_keycode_to_modmask(guint keycode)
 {
     gint i, j;
     guint mask = 0;
@@ -116,7 +125,7 @@ guint modkeys_keycode_to_mask(guint keycode)
     return mask;
 }
 
-guint modkeys_only_modifier_masks(guint mask)
+guint obt_keyboard_only_modmasks(guint mask)
 {
     mask &= ALL_MASKS;
     /* strip off these lock keys. they shouldn't affect key bindings */
@@ -124,12 +133,12 @@ guint modkeys_only_modifier_masks(guint mask)
                           because you could bind it to something else and it
                           should work as that modifier then. i think capslock
                           is weird in xkb. */
-    mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_NUMLOCK);
-    mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_SCROLLLOCK);
+    mask &= ~obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_NUMLOCK);
+    mask &= ~obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SCROLLLOCK);
     return mask;
 }
 
-guint modkeys_key_to_mask(ObModkeysKey key)
+guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key)
 {
     return modkeys_keys[key];
 }
@@ -139,44 +148,44 @@ static void set_modkey_mask(guchar mask, KeySym sym)
     /* find what key this is, and bind it to the mask */
 
     if (sym == XK_Num_Lock)
-        modkeys_keys[OB_MODKEY_KEY_NUMLOCK] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_NUMLOCK] |= mask;
     else if (sym == XK_Scroll_Lock)
-        modkeys_keys[OB_MODKEY_KEY_SCROLLLOCK] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_SCROLLLOCK] |= mask;
 
     else if (sym == XK_Super_L && super_l)
-        modkeys_keys[OB_MODKEY_KEY_SUPER] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_SUPER] |= mask;
     else if (sym == XK_Super_L && !super_l)
         /* left takes precident over right, so erase any masks the right
            key may have set */
-        modkeys_keys[OB_MODKEY_KEY_SUPER] = mask, super_l = TRUE;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_SUPER] = mask, super_l = TRUE;
     else if (sym == XK_Super_R && !super_l)
-        modkeys_keys[OB_MODKEY_KEY_SUPER] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_SUPER] |= mask;
 
     else if (sym == XK_Hyper_L && hyper_l)
-        modkeys_keys[OB_MODKEY_KEY_HYPER] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_HYPER] |= mask;
     else if (sym == XK_Hyper_L && !hyper_l)
-        modkeys_keys[OB_MODKEY_KEY_HYPER] = mask, hyper_l = TRUE;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_HYPER] = mask, hyper_l = TRUE;
     else if (sym == XK_Hyper_R && !hyper_l)
-        modkeys_keys[OB_MODKEY_KEY_HYPER] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_HYPER] |= mask;
 
     else if (sym == XK_Alt_L && alt_l)
-        modkeys_keys[OB_MODKEY_KEY_ALT] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_ALT] |= mask;
     else if (sym == XK_Alt_L && !alt_l)
-        modkeys_keys[OB_MODKEY_KEY_ALT] = mask, alt_l = TRUE;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_ALT] = mask, alt_l = TRUE;
     else if (sym == XK_Alt_R && !alt_l)
-        modkeys_keys[OB_MODKEY_KEY_ALT] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_ALT] |= mask;
 
     else if (sym == XK_Meta_L && meta_l)
-        modkeys_keys[OB_MODKEY_KEY_META] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_META] |= mask;
     else if (sym == XK_Meta_L && !meta_l)
-        modkeys_keys[OB_MODKEY_KEY_META] = mask, meta_l = TRUE;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_META] = mask, meta_l = TRUE;
     else if (sym == XK_Meta_R && !meta_l)
-        modkeys_keys[OB_MODKEY_KEY_META] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_META] |= mask;
 
     /* CapsLock, Shift, and Control are special and hard-coded */
 }
 
-KeyCode modkeys_sym_to_code(KeySym sym)
+KeyCode obt_keyboard_keysym_to_keycode(KeySym sym)
 {
     gint i, j;
 
@@ -188,3 +197,28 @@ KeyCode modkeys_sym_to_code(KeySym sym)
     return 0;
 }
 
+gchar *obt_keyboard_keycode_to_string(guint keycode)
+{
+    KeySym sym;
+
+    if ((sym = XKeycodeToKeysym(obt_display, keycode, 0)) != NoSymbol)
+        return g_locale_to_utf8(XKeysymToString(sym), -1, NULL, NULL, NULL);
+    return NULL;
+}
+
+gunichar obt_keyboard_keycode_to_unichar(guint keycode)
+{
+    gunichar unikey = 0;
+    char *key;
+
+    if ((key = obt_keyboard_keycode_to_string(keycode)) != NULL &&
+        /* don't accept keys that aren't a single letter, like "space" */
+        key[1] == '\0')
+    {
+        unikey = g_utf8_get_char_validated(key, -1);
+        if (unikey == (gunichar)-1 || unikey == (gunichar)-2 || unikey == 0)
+            unikey = 0;
+    }
+    g_free(key);
+    return unikey;
+}
similarity index 52%
rename from openbox/modkeys.h
rename to obt/keyboard.h
index dc72f28..a9029df 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
-   masks.h for the Openbox window manager
+   obt/keyboard.h for the Openbox window manager
    Copyright (c) 2007        Dana Jansens
 
    This program is free software; you can redistribute it and/or modify
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#ifndef ob__modkeys_h
-#define ob__modkeys_h
+#ifndef __obt_keyboard_h
+#define __obt_keyboard_h
 
 #include <glib.h>
 #include <X11/Xlib.h>
 
+G_BEGIN_DECLS
+
 /*! These keys are bound to the modifier masks in any fashion,
   except for CapsLock, Shift, and Control. */
 typedef enum {
-    OB_MODKEY_KEY_CAPSLOCK,
-    OB_MODKEY_KEY_NUMLOCK,
-    OB_MODKEY_KEY_SCROLLLOCK,
-    OB_MODKEY_KEY_SHIFT,
-    OB_MODKEY_KEY_CONTROL,
-    OB_MODKEY_KEY_SUPER,
-    OB_MODKEY_KEY_HYPER,
-    OB_MODKEY_KEY_META,
-    OB_MODKEY_KEY_ALT,
-
-    OB_MODKEY_NUM_KEYS
-} ObModkeysKey;
-
-void modkeys_startup(gboolean reconfigure);
-void modkeys_shutdown(gboolean reconfigure);
-
-/*! Get the modifier masks for a keycode. (eg. a keycode bound to Alt_L could
+    OBT_KEYBOARD_MODKEY_CAPSLOCK,
+    OBT_KEYBOARD_MODKEY_NUMLOCK,
+    OBT_KEYBOARD_MODKEY_SCROLLLOCK,
+    OBT_KEYBOARD_MODKEY_SHIFT,
+    OBT_KEYBOARD_MODKEY_CONTROL,
+    OBT_KEYBOARD_MODKEY_SUPER,
+    OBT_KEYBOARD_MODKEY_HYPER,
+    OBT_KEYBOARD_MODKEY_META,
+    OBT_KEYBOARD_MODKEY_ALT,
+
+    OBT_KEYBOARD_NUM_MODKEYS
+} ObtModkeysKey;
+
+void obt_keyboard_reload();
+
+/*! Get the modifier mask(s) for a KeyCode. (eg. a keycode bound to Alt_L could
   return a mask of (Mod1Mask | Mask3Mask)) */
-guint modkeys_keycode_to_mask(guint keycode);
+guint obt_keyboard_keycode_to_modmask(guint keycode);
 
 /*! Strip off all modifiers except for the modifier keys. This strips stuff
-  like Button1Mask, and also LockMask, NumLockMask, and ScrollLockMask */
-guint modkeys_only_modifier_masks(guint mask);
+  like Button1Mask, and also LockMask, NumlockMask, and ScrolllockMask */
+guint obt_keyboard_only_modmasks(guint mask);
 
 /*! Get the modifier masks for a modifier key. This includes both the left and
   right keys when there are both. */
-guint modkeys_key_to_mask(ObModkeysKey key);
+guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key);
 
 /*! Convert a KeySym to a KeyCode, because the X function is terrible - says
   valgrind. */
-KeyCode modkeys_sym_to_code(KeySym sym);
+KeyCode obt_keyboard_keysym_to_keycode(KeySym sym);
+
+/*! Give the string form of a KeyCode */
+gchar *obt_keyboard_keycode_to_string(guint keycode);
+
+/*! Translate a KeyCode to the unicode character it represents */
+gunichar obt_keyboard_keycode_to_unichar(guint keycode);
+
+
+G_END_DECLS
 
-#endif
+#endif /* __obt_keyboard_h */
similarity index 75%
rename from openbox/mainloop.c
rename to obt/mainloop.c
index b292120..64972dd 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
-   mainloop.c for the Openbox window manager
+   obt/mainloop.c for the Openbox window manager
    Copyright (c) 2006        Mikael Magnusson
    Copyright (c) 2003-2007   Dana Jansens
 
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#include "mainloop.h"
-#include "event.h"
+#include "obt/mainloop.h"
+#include "obt/display.h"
+#include "obt/util.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/select.h>
 #include <signal.h>
 
-typedef struct _ObMainLoopTimer             ObMainLoopTimer;
-typedef struct _ObMainLoopSignal            ObMainLoopSignal;
-typedef struct _ObMainLoopSignalHandlerType ObMainLoopSignalHandlerType;
-typedef struct _ObMainLoopXHandlerType      ObMainLoopXHandlerType;
-typedef struct _ObMainLoopFdHandlerType     ObMainLoopFdHandlerType;
+typedef struct _ObtMainLoopTimer             ObtMainLoopTimer;
+typedef struct _ObtMainLoopSignal            ObtMainLoopSignal;
+typedef struct _ObtMainLoopSignalHandlerType ObtMainLoopSignalHandlerType;
+typedef struct _ObtMainLoopXHandlerType      ObtMainLoopXHandlerType;
+typedef struct _ObtMainLoopFdHandlerType     ObtMainLoopFdHandlerType;
 
 /* this should be more than the number of possible signals on any
    architecture... */
 #define NUM_SIGNALS 99
 
-/* all created ObMainLoops. Used by the signal handler to pass along signals */
+/* all created ObtMainLoops. Used by the signal handler to pass along
+   signals */
 static GSList *all_loops;
 
 /* signals are global to all loops */
@@ -64,11 +66,13 @@ static gint core_signals[] =
 #define NUM_CORE_SIGNALS (sizeof(core_signals) / sizeof(core_signals[0]))
 
 static void sighandler(gint sig);
-static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait);
+static void timer_dispatch(ObtMainLoop *loop, GTimeVal **wait);
 static void fd_handler_destroy(gpointer data);
+static void calc_max_fd(ObtMainLoop *loop);
 
-struct _ObMainLoop
+struct _ObtMainLoop
 {
+    gint ref;
     Display *display;
 
     gboolean run;     /* do keep running */
@@ -90,7 +94,7 @@ struct _ObMainLoop
     GSList *signal_handlers[NUM_SIGNALS];
 };
 
-struct _ObMainLoopTimer
+struct _ObtMainLoopTimer
 {
     gulong delay;
     GSourceFunc func;
@@ -110,42 +114,41 @@ struct _ObMainLoopTimer
     gboolean fired;
 };
 
-struct _ObMainLoopSignalHandlerType
+struct _ObtMainLoopSignalHandlerType
 {
-    ObMainLoop *loop;
+    ObtMainLoop *loop;
     gint signal;
     gpointer data;
-    ObMainLoopSignalHandler func;
+    ObtMainLoopSignalHandler func;
     GDestroyNotify destroy;
 };
 
-struct _ObMainLoopXHandlerType
+struct _ObtMainLoopXHandlerType
 {
-    ObMainLoop *loop;
+    ObtMainLoop *loop;
     gpointer data;
-    ObMainLoopXHandler func;
+    ObtMainLoopXHandler func;
     GDestroyNotify destroy;
 };
 
-struct _ObMainLoopFdHandlerType
+struct _ObtMainLoopFdHandlerType
 {
-    ObMainLoop *loop;
+    ObtMainLoop *loop;
     gint fd;
     gpointer data;
-    ObMainLoopFdHandler func;
+    ObtMainLoopFdHandler func;
     GDestroyNotify destroy;
 };
 
-ObMainLoop *ob_main_loop_new(Display *display)
+ObtMainLoop *obt_main_loop_new()
 {
-    ObMainLoop *loop;
+    ObtMainLoop *loop;
 
-    loop = g_new0(ObMainLoop, 1);
-    loop->display = display;
-    loop->fd_x = ConnectionNumber(display);
+    loop = g_new0(ObtMainLoop, 1);
+    loop->ref = 1;
     FD_ZERO(&loop->fd_set);
-    FD_SET(loop->fd_x, &loop->fd_set);
-    loop->fd_max = loop->fd_x;
+    loop->fd_x = -1;
+    loop->fd_max = -1;
 
     loop->fd_handlers = g_hash_table_new_full(g_int_hash, g_int_equal,
                                               NULL, fd_handler_destroy);
@@ -185,24 +188,29 @@ ObMainLoop *ob_main_loop_new(Display *display)
     return loop;
 }
 
-void ob_main_loop_destroy(ObMainLoop *loop)
+void obt_main_loop_ref(ObtMainLoop *loop)
+{
+    ++loop->ref;
+}
+
+void obt_main_loop_unref(ObtMainLoop *loop)
 {
     guint i;
     GSList *it, *next;
 
-    if (loop) {
+    if (loop && --loop->ref == 0) {
         g_assert(loop->running == FALSE);
 
         for (it = loop->x_handlers; it; it = next) {
-            ObMainLoopXHandlerType *h = it->data;
+            ObtMainLoopXHandlerType *h = it->data;
             next = g_slist_next(it);
-            ob_main_loop_x_remove(loop, h->func);
+            obt_main_loop_x_remove(loop, h->func);
         }
 
         g_hash_table_destroy(loop->fd_handlers);
 
         for (it = loop->timers; it; it = g_slist_next(it)) {
-            ObMainLoopTimer *t = it->data;
+            ObtMainLoopTimer *t = it->data;
             if (t->destroy) t->destroy(t->data);
             g_free(t);
         }
@@ -211,9 +219,9 @@ void ob_main_loop_destroy(ObMainLoop *loop)
 
         for (i = 0; i < NUM_SIGNALS; ++i)
             for (it = loop->signal_handlers[i]; it; it = next) {
-                ObMainLoopSignalHandlerType *h = it->data;
+                ObtMainLoopSignalHandlerType *h = it->data;
                 next = g_slist_next(it);
-                ob_main_loop_signal_remove(loop, h->func);
+                obt_main_loop_signal_remove(loop, h->func);
             }
 
         all_loops = g_slist_remove(all_loops, loop);
@@ -230,7 +238,7 @@ void ob_main_loop_destroy(ObMainLoop *loop)
             }
         }
 
-        g_free(loop);
+        obt_free0(loop, ObtMainLoop, 1);
     }
 }
 
@@ -238,14 +246,14 @@ static void fd_handle_foreach(gpointer key,
                               gpointer value,
                               gpointer data)
 {
-    ObMainLoopFdHandlerType *h = value;
+    ObtMainLoopFdHandlerType *h = value;
     fd_set *set = data;
 
     if (FD_ISSET(h->fd, set))
         h->func(h->fd, h->data);
 }
 
-void ob_main_loop_run(ObMainLoop *loop)
+void obt_main_loop_run(ObtMainLoop *loop)
 {
     XEvent e;
     struct timeval *wait;
@@ -268,7 +276,7 @@ void ob_main_loop_run(ObMainLoop *loop)
                 while (loop->signals_fired[i]) {
                     for (it = loop->signal_handlers[i];
                             it; it = g_slist_next(it)) {
-                        ObMainLoopSignalHandlerType *h = it->data;
+                        ObtMainLoopSignalHandlerType *h = it->data;
                         h->func(i, h->data);
                     }
                     loop->signals_fired[i]--;
@@ -277,12 +285,12 @@ void ob_main_loop_run(ObMainLoop *loop)
             loop->signal_fired = FALSE;
 
             sigprocmask(SIG_SETMASK, &oldset, NULL);
-        } else if (XPending(loop->display)) {
+        } else if (loop->display && XPending(loop->display)) {
             do {
                 XNextEvent(loop->display, &e);
 
                 for (it = loop->x_handlers; it; it = g_slist_next(it)) {
-                    ObMainLoopXHandlerType *h = it->data;
+                    ObtMainLoopXHandlerType *h = it->data;
                     h->func(&e, h->data);
                 }
             } while (XPending(loop->display) && loop->run);
@@ -312,35 +320,45 @@ void ob_main_loop_run(ObMainLoop *loop)
     loop->running = FALSE;
 }
 
-void ob_main_loop_exit(ObMainLoop *loop)
+void obt_main_loop_exit(ObtMainLoop *loop)
 {
     loop->run = FALSE;
 }
 
 /*** XEVENT WATCHERS ***/
 
-void ob_main_loop_x_add(ObMainLoop *loop,
-                        ObMainLoopXHandler handler,
-                        gpointer data,
-                        GDestroyNotify notify)
+void obt_main_loop_x_add(ObtMainLoop *loop,
+                         ObtMainLoopXHandler handler,
+                         gpointer data,
+                         GDestroyNotify notify)
 {
-    ObMainLoopXHandlerType *h;
+    ObtMainLoopXHandlerType *h;
 
-    h = g_new(ObMainLoopXHandlerType, 1);
+    h = g_new(ObtMainLoopXHandlerType, 1);
     h->loop = loop;
     h->func = handler;
     h->data = data;
     h->destroy = notify;
+
+    if (!loop->x_handlers) {
+        g_assert(obt_display); /* is the display open? */
+
+        loop->display = obt_display;
+        loop->fd_x = ConnectionNumber(loop->display);
+        FD_SET(loop->fd_x, &loop->fd_set);
+        calc_max_fd(loop);
+    }
+
     loop->x_handlers = g_slist_prepend(loop->x_handlers, h);
 }
 
-void ob_main_loop_x_remove(ObMainLoop *loop,
-                           ObMainLoopXHandler handler)
+void obt_main_loop_x_remove(ObtMainLoop *loop,
+                            ObtMainLoopXHandler handler)
 {
     GSList *it, *next;
 
     for (it = loop->x_handlers; it; it = next) {
-        ObMainLoopXHandlerType *h = it->data;
+        ObtMainLoopXHandlerType *h = it->data;
         next = g_slist_next(it);
         if (h->func == handler) {
             loop->x_handlers = g_slist_delete_link(loop->x_handlers, it);
@@ -348,6 +366,11 @@ void ob_main_loop_x_remove(ObMainLoop *loop,
             g_free(h);
         }
     }
+
+    if (!loop->x_handlers) {
+        FD_CLR(loop->fd_x, &loop->fd_set);
+        calc_max_fd(loop);
+    }
 }
 
 /*** SIGNAL WATCHERS ***/
@@ -372,23 +395,23 @@ static void sighandler(gint sig)
         }
 
     for (it = all_loops; it; it = g_slist_next(it)) {
-        ObMainLoop *loop = it->data;
+        ObtMainLoop *loop = it->data;
         loop->signal_fired = TRUE;
         loop->signals_fired[sig]++;
     }
 }
 
-void ob_main_loop_signal_add(ObMainLoop *loop,
-                             gint signal,
-                             ObMainLoopSignalHandler handler,
-                             gpointer data,
-                             GDestroyNotify notify)
+void obt_main_loop_signal_add(ObtMainLoop *loop,
+                              gint signal,
+                              ObtMainLoopSignalHandler handler,
+                              gpointer data,
+                              GDestroyNotify notify)
 {
-    ObMainLoopSignalHandlerType *h;
+    ObtMainLoopSignalHandlerType *h;
 
     g_return_if_fail(signal < NUM_SIGNALS);
 
-    h = g_new(ObMainLoopSignalHandlerType, 1);
+    h = g_new(ObtMainLoopSignalHandlerType, 1);
     h->loop = loop;
     h->signal = signal;
     h->func = handler;
@@ -412,15 +435,15 @@ void ob_main_loop_signal_add(ObMainLoop *loop,
     all_signals[signal].installed++;
 }
 
-void ob_main_loop_signal_remove(ObMainLoop *loop,
-                                ObMainLoopSignalHandler handler)
+void obt_main_loop_signal_remove(ObtMainLoop *loop,
+                                 ObtMainLoopSignalHandler handler)
 {
     guint i;
     GSList *it, *next;
 
     for (i = 0; i < NUM_SIGNALS; ++i) {
         for (it = loop->signal_handlers[i]; it; it = next) {
-            ObMainLoopSignalHandlerType *h = it->data;
+            ObtMainLoopSignalHandlerType *h = it->data;
 
             next = g_slist_next(it);
 
@@ -447,28 +470,28 @@ void ob_main_loop_signal_remove(ObMainLoop *loop,
 
 static void max_fd_func(gpointer key, gpointer value, gpointer data)
 {
-    ObMainLoop *loop = data;
+    ObtMainLoop *loop = data;
 
     /* key is the fd */
     loop->fd_max = MAX(loop->fd_max, *(gint*)key);
 }
 
-static void calc_max_fd(ObMainLoop *loop)
+static void calc_max_fd(ObtMainLoop *loop)
 {
     loop->fd_max = loop->fd_x;
 
     g_hash_table_foreach(loop->fd_handlers, max_fd_func, loop);
 }
 
-void ob_main_loop_fd_add(ObMainLoop *loop,
-                         gint fd,
-                         ObMainLoopFdHandler handler,
-                         gpointer data,
-                         GDestroyNotify notify)
+void obt_main_loop_fd_add(ObtMainLoop *loop,
+                          gint fd,
+                          ObtMainLoopFdHandler handler,
+                          gpointer data,
+                          GDestroyNotify notify)
 {
-    ObMainLoopFdHandlerType *h;
+    ObtMainLoopFdHandlerType *h;
 
-    h = g_new(ObMainLoopFdHandlerType, 1);
+    h = g_new(ObtMainLoopFdHandlerType, 1);
     h->loop = loop;
     h->fd = fd;
     h->func = handler;
@@ -482,7 +505,7 @@ void ob_main_loop_fd_add(ObMainLoop *loop,
 
 static void fd_handler_destroy(gpointer data)
 {
-    ObMainLoopFdHandlerType *h = data;
+    ObtMainLoopFdHandlerType *h = data;
 
     FD_CLR(h->fd, &h->loop->fd_set);
 
@@ -490,16 +513,17 @@ static void fd_handler_destroy(gpointer data)
         h->destroy(h->data);
 }
 
-void ob_main_loop_fd_remove(ObMainLoop *loop,
-                            gint fd)
+void obt_main_loop_fd_remove(ObtMainLoop *loop,
+                             gint fd)
 {
     g_hash_table_remove(loop->fd_handlers, &fd);
+    calc_max_fd(loop);
 }
 
 /*** TIMEOUTS ***/
 
 #define NEAREST_TIMEOUT(loop) \
-    (((ObMainLoopTimer*)(loop)->timers->data)->timeout)
+    (((ObtMainLoopTimer*)(loop)->timers->data)->timeout)
 
 static glong timecompare(GTimeVal *a, GTimeVal *b)
 {
@@ -508,11 +532,11 @@ static glong timecompare(GTimeVal *a, GTimeVal *b)
     return a->tv_usec - b->tv_usec;
 }
 
-static void insert_timer(ObMainLoop *loop, ObMainLoopTimer *ins)
+static void insert_timer(ObtMainLoop *loop, ObtMainLoopTimer *ins)
 {
     GSList *it;
     for (it = loop->timers; it; it = g_slist_next(it)) {
-        ObMainLoopTimer *t = it->data;
+        ObtMainLoopTimer *t = it->data;
         if (timecompare(&ins->timeout, &t->timeout) <= 0) {
             loop->timers = g_slist_insert_before(loop->timers, it, ins);
             break;
@@ -522,14 +546,14 @@ static void insert_timer(ObMainLoop *loop, ObMainLoopTimer *ins)
         loop->timers = g_slist_append(loop->timers, ins);
 }
 
-void ob_main_loop_timeout_add(ObMainLoop *loop,
-                              gulong microseconds,
-                              GSourceFunc handler,
-                              gpointer data,
-                              GEqualFunc cmp,
-                              GDestroyNotify notify)
+void obt_main_loop_timeout_add(ObtMainLoop *loop,
+                               gulong microseconds,
+                               GSourceFunc handler,
+                               gpointer data,
+                               GEqualFunc cmp,
+                               GDestroyNotify notify)
 {
-    ObMainLoopTimer *t = g_new(ObMainLoopTimer, 1);
+    ObtMainLoopTimer *t = g_new(ObtMainLoopTimer, 1);
 
     g_assert(microseconds > 0); /* if it's 0 it'll cause an infinite loop */
 
@@ -546,25 +570,25 @@ void ob_main_loop_timeout_add(ObMainLoop *loop,
     insert_timer(loop, t);
 }
 
-void ob_main_loop_timeout_remove(ObMainLoop *loop,
-                                 GSourceFunc handler)
+void obt_main_loop_timeout_remove(ObtMainLoop *loop,
+                                  GSourceFunc handler)
 {
     GSList *it;
 
     for (it = loop->timers; it; it = g_slist_next(it)) {
-        ObMainLoopTimer *t = it->data;
+        ObtMainLoopTimer *t = it->data;
         if (t->func == handler)
             t->del_me = TRUE;
     }
 }
 
-void ob_main_loop_timeout_remove_data(ObMainLoop *loop, GSourceFunc handler,
-                                      gpointer data, gboolean cancel_dest)
+void obt_main_loop_timeout_remove_data(ObtMainLoop *loop, GSourceFunc handler,
+                                       gpointer data, gboolean cancel_dest)
 {
     GSList *it;
 
     for (it = loop->timers; it; it = g_slist_next(it)) {
-        ObMainLoopTimer *t = it->data;
+        ObtMainLoopTimer *t = it->data;
         if (t->func == handler && t->equal(t->data, data)) {
             t->del_me = TRUE;
             if (cancel_dest)
@@ -574,7 +598,7 @@ void ob_main_loop_timeout_remove_data(ObMainLoop *loop, GSourceFunc handler,
 }
 
 /* find the time to wait for the nearest timeout */
-static gboolean nearest_timeout_wait(ObMainLoop *loop, GTimeVal *tm)
+static gboolean nearest_timeout_wait(ObtMainLoop *loop, GTimeVal *tm)
 {
   if (loop->timers == NULL)
     return FALSE;
@@ -594,7 +618,7 @@ static gboolean nearest_timeout_wait(ObMainLoop *loop, GTimeVal *tm)
   return TRUE;
 }
 
-static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
+static void timer_dispatch(ObtMainLoop *loop, GTimeVal **wait)
 {
     GSList *it, *next;
 
@@ -603,7 +627,7 @@ static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
     g_get_current_time(&loop->now);
 
     for (it = loop->timers; it; it = next) {
-        ObMainLoopTimer *curr;
+        ObtMainLoopTimer *curr;
 
         next = g_slist_next(it);
 
diff --git a/obt/mainloop.h b/obt/mainloop.h
new file mode 100644 (file)
index 0000000..cce7d5b
--- /dev/null
@@ -0,0 +1,81 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/mainloop.h for the Openbox window manager
+   Copyright (c) 2006        Mikael Magnusson
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_mainloop_h
+#define __obt_mainloop_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ObtMainLoop ObtMainLoop;
+
+ObtMainLoop *obt_main_loop_new();
+void        obt_main_loop_ref(ObtMainLoop *loop);
+void        obt_main_loop_unref(ObtMainLoop *loop);
+
+typedef void (*ObtMainLoopXHandler) (const XEvent *e, gpointer data);
+
+void obt_main_loop_x_add(ObtMainLoop *loop,
+                         ObtMainLoopXHandler handler,
+                         gpointer data,
+                         GDestroyNotify notify);
+void obt_main_loop_x_remove(ObtMainLoop *loop,
+                            ObtMainLoopXHandler handler);
+
+typedef void (*ObtMainLoopFdHandler) (gint fd, gpointer data);
+
+void obt_main_loop_fd_add(ObtMainLoop *loop,
+                          gint fd,
+                          ObtMainLoopFdHandler handler,
+                          gpointer data,
+                          GDestroyNotify notify);
+void obt_main_loop_fd_remove(ObtMainLoop *loop,
+                             gint fd);
+
+typedef void (*ObtMainLoopSignalHandler) (gint signal, gpointer data);
+
+void obt_main_loop_signal_add(ObtMainLoop *loop,
+                              gint signal,
+                              ObtMainLoopSignalHandler handler,
+                              gpointer data,
+                              GDestroyNotify notify);
+void obt_main_loop_signal_remove(ObtMainLoop *loop,
+                                 ObtMainLoopSignalHandler handler);
+
+void obt_main_loop_timeout_add(ObtMainLoop *loop,
+                               gulong microseconds,
+                               GSourceFunc handler,
+                               gpointer data,
+                               GEqualFunc cmp,
+                               GDestroyNotify notify);
+void obt_main_loop_timeout_remove(ObtMainLoop *loop,
+                                  GSourceFunc handler);
+void obt_main_loop_timeout_remove_data(ObtMainLoop *loop,
+                                       GSourceFunc handler,
+                                       gpointer data,
+                                       gboolean cancel_dest);
+
+void obt_main_loop_run(ObtMainLoop *loop);
+void obt_main_loop_exit(ObtMainLoop *loop);
+
+G_END_DECLS
+
+#endif
diff --git a/obt/obt-4.0.pc.in b/obt/obt-4.0.pc.in
new file mode 100644 (file)
index 0000000..ee2a3f0
--- /dev/null
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+xcflags=@X_CFLAGS@
+xlibs=@X_LIBS@
+
+Name: Obt
+Description: Openbox Toolkit Library
+Version: @VERSION@
+Requires: glib-2.0
+Libs: -L${libdir} -lobrender ${xlibs}
+Cflags: -I${includedir}/openbox/@OB_VERSION@ ${xcflags}
diff --git a/obt/parse.c b/obt/parse.c
new file mode 100644 (file)
index 0000000..d181b67
--- /dev/null
@@ -0,0 +1,413 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/parse.c for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/parse.h"
+#include "obt/paths.h"
+
+#include <glib.h>
+
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+struct Callback {
+    gchar *tag;
+    ObtParseCallback func;
+    gpointer data;
+};
+
+struct _ObtParseInst {
+    gint ref;
+    ObtPaths *xdg_paths;
+    GHashTable *callbacks;
+    xmlDocPtr doc;
+    xmlNodePtr root;
+    gchar *path;
+};
+
+static void destfunc(struct Callback *c)
+{
+    g_free(c->tag);
+    g_free(c);
+}
+
+ObtParseInst* obt_parse_instance_new(void)
+{
+    ObtParseInst *i = g_new(ObtParseInst, 1);
+    i->ref = 1;
+    i->xdg_paths = obt_paths_new();
+    i->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+                                         (GDestroyNotify)destfunc);
+    i->doc = NULL;
+    i->root = NULL;
+    i->path = NULL;
+    return i;
+}
+
+void obt_parse_instance_ref(ObtParseInst *i)
+{
+    ++i->ref;
+}
+
+void obt_parse_instance_unref(ObtParseInst *i)
+{
+    if (i && --i->ref == 0) {
+        obt_paths_unref(i->xdg_paths);
+        g_hash_table_destroy(i->callbacks);
+        g_free(i);
+    }
+}
+
+xmlDocPtr obt_parse_doc(ObtParseInst *i)
+{
+    g_assert(i->doc); /* a doc is open? */
+    return i->doc;
+}
+
+xmlNodePtr obt_parse_root(ObtParseInst *i)
+{
+    g_assert(i->doc); /* a doc is open? */
+    return i->root;
+}
+
+void obt_parse_register(ObtParseInst *i, const gchar *tag,
+                        ObtParseCallback func, gpointer data)
+{
+    struct Callback *c;
+
+    if ((c = g_hash_table_lookup(i->callbacks, tag))) {
+        g_error("Tag '%s' already registered", tag);
+        return;
+    }
+
+    c = g_new(struct Callback, 1);
+    c->tag = g_strdup(tag);
+    c->func = func;
+    c->data = data;
+    g_hash_table_insert(i->callbacks, c->tag, c);
+}
+
+static gboolean load_file(ObtParseInst *i,
+                          const gchar *domain,
+                          const gchar *filename,
+                          const gchar *root_node,
+                          GSList *paths)
+{
+    GSList *it;
+    gboolean r = FALSE;
+
+    g_assert(i->doc == NULL); /* another doc isn't open already? */
+
+    for (it = paths; !r && it; it = g_slist_next(it)) {
+        gchar *path;
+        struct stat s;
+
+        if (!domain && !filename) /* given a full path to the file */
+            path = g_strdup(it->data);
+        else
+            path = g_build_filename(it->data, domain, filename, NULL);
+
+        if (stat(path, &s) >= 0) {
+            /* XML_PARSE_BLANKS is needed apparently, or the tree can end up
+               with extra nodes in it. */
+            i->doc = xmlReadFile(path, NULL, (XML_PARSE_NOBLANKS |
+                                              XML_PARSE_RECOVER));
+            if (i->doc) {
+                i->root = xmlDocGetRootElement(i->doc);
+                if (!i->root) {
+                    xmlFreeDoc(i->doc);
+                    i->doc = NULL;
+                    g_message("%s is an empty XML document", path);
+                }
+                else if (xmlStrcmp(i->root->name,
+                                   (const xmlChar*)root_node)) {
+                    xmlFreeDoc(i->doc);
+                    i->doc = NULL;
+                    i->root = NULL;
+                    g_message("XML document %s is of wrong type. Root "
+                              "node is not '%s'", path, root_node);
+                }
+                else {
+                    i->path = g_strdup(path);
+                    r = TRUE; /* ok! */
+                }
+            }
+        }
+
+        g_free(path);
+    }
+
+    return r;
+}
+
+gboolean obt_parse_load_file(ObtParseInst *i,
+                             const gchar *path,
+                             const gchar *root_node)
+{
+    GSList *paths;
+    gboolean r;
+
+    paths = g_slist_append(NULL, g_strdup(path));
+
+    r = load_file(i, NULL, NULL, root_node, paths);
+
+    while (paths) {
+        g_free(paths->data);
+        paths = g_slist_delete_link(paths, paths);
+    }
+    return r;
+}
+
+gboolean obt_parse_load_config_file(ObtParseInst *i,
+                                    const gchar *domain,
+                                    const gchar *filename,
+                                    const gchar *root_node)
+{
+    GSList *it, *paths = NULL;
+    gboolean r;
+
+    for (it = obt_paths_config_dirs(i->xdg_paths); it; it = g_slist_next(it))
+        paths = g_slist_append(paths, g_strdup(it->data));
+
+    r = load_file(i, domain, filename, root_node, paths);
+
+    while (paths) {
+        g_free(paths->data);
+        paths = g_slist_delete_link(paths, paths);
+    }
+    return r;
+}
+
+gboolean obt_parse_load_data_file(ObtParseInst *i,
+                                  const gchar *domain,
+                                  const gchar *filename,
+                                  const gchar *root_node)
+{
+    GSList *it, *paths = NULL;
+    gboolean r;
+
+    for (it = obt_paths_data_dirs(i->xdg_paths); it; it = g_slist_next(it))
+        paths = g_slist_append(paths, g_strdup(it->data));
+
+    r = load_file(i, domain, filename, root_node, paths);
+
+    while (paths) {
+        g_free(paths->data);
+        paths = g_slist_delete_link(paths, paths);
+    }
+    return r;
+}
+
+gboolean obt_parse_load_theme_file(ObtParseInst *i,
+                                   const gchar *theme,
+                                   const gchar *domain,
+                                   const gchar *filename,
+                                   const gchar *root_node)
+{
+    GSList *it, *paths = NULL;
+    gboolean r;
+
+    /* use ~/.themes for backwards compatibility */
+    paths = g_slist_append
+        (paths, g_build_filename(g_get_home_dir(), ".themes", theme, NULL));
+
+    for (it = obt_paths_data_dirs(i->xdg_paths); it; it = g_slist_next(it))
+        paths = g_slist_append
+            (paths, g_build_filename(it->data, "themes", theme, NULL));
+
+    r = load_file(i, domain, filename, root_node, paths);
+
+    while (paths) {
+        g_free(paths->data);
+        paths = g_slist_delete_link(paths, paths);
+    }
+    return r;
+}
+
+
+gboolean obt_parse_load_mem(ObtParseInst *i,
+                            gpointer data, guint len, const gchar *root_node)
+{
+    gboolean r = FALSE;
+
+    g_assert(i->doc == NULL); /* another doc isn't open already? */
+
+    i->doc = xmlParseMemory(data, len);
+    if (i) {
+        i->root = xmlDocGetRootElement(i->doc);
+        if (!i->root) {
+            xmlFreeDoc(i->doc);
+            i->doc = NULL;
+            g_message("Given memory is an empty document");
+        }
+        else if (xmlStrcmp(i->root->name, (const xmlChar*)root_node)) {
+            xmlFreeDoc(i->doc);
+            i->doc = NULL;
+            i->root = NULL;
+            g_message("XML Document in given memory is of wrong "
+                      "type. Root node is not '%s'\n", root_node);
+        }
+        else
+            r = TRUE; /* ok ! */
+    }
+    return r;
+}
+
+void obt_parse_close(ObtParseInst *i)
+{
+    if (i && i->doc) {
+        xmlFreeDoc(i->doc);
+        g_free(i->path);
+        i->doc = NULL;
+        i->root = NULL;
+        i->path = NULL;
+    }
+}
+
+void obt_parse_tree(ObtParseInst *i, xmlNodePtr node)
+{
+    g_assert(i->doc); /* a doc is open? */
+
+    while (node) {
+        struct Callback *c = g_hash_table_lookup(i->callbacks, node->name);
+        if (c) c->func(node, c->data);
+        node = node->next;
+    }
+}
+
+void obt_parse_tree_from_root(ObtParseInst *i)
+{
+    obt_parse_tree(i, i->root->children);
+}
+
+gchar *obt_parse_node_string(xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeGetContent(node);
+    gchar *s = g_strdup(c ? (gchar*)c : "");
+    xmlFree(c);
+    return s;
+}
+
+gint obt_parse_node_int(xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeGetContent(node);
+    gint i = c ? atoi((gchar*)c) : 0;
+    xmlFree(c);
+    return i;
+}
+
+gboolean obt_parse_node_bool(xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeGetContent(node);
+    gboolean b = FALSE;
+    if (c && !xmlStrcasecmp(c, (const xmlChar*) "true"))
+        b = TRUE;
+    else if (c && !xmlStrcasecmp(c, (const xmlChar*) "yes"))
+        b = TRUE;
+    else if (c && !xmlStrcasecmp(c, (const xmlChar*) "on"))
+        b = TRUE;
+    xmlFree(c);
+    return b;
+}
+
+gboolean obt_parse_node_contains(xmlNodePtr node, const gchar *val)
+{
+    xmlChar *c = xmlNodeGetContent(node);
+    gboolean r;
+    r = !xmlStrcasecmp(c, (const xmlChar*) val);
+    xmlFree(c);
+    return r;
+}
+
+xmlNodePtr obt_parse_find_node(xmlNodePtr node, const gchar *tag)
+{
+    while (node) {
+        if (!xmlStrcmp(node->name, (const xmlChar*) tag))
+            return node;
+        node = node->next;
+    }
+    return NULL;
+}
+
+gboolean obt_parse_attr_bool(xmlNodePtr node, const gchar *name,
+                             gboolean *value)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
+            *value = TRUE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
+            *value = TRUE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
+            *value = TRUE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "false"))
+            *value = FALSE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "no"))
+            *value = FALSE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "off"))
+            *value = FALSE, r = TRUE;
+    }
+    xmlFree(c);
+    return r;
+}
+
+gboolean obt_parse_attr_int(xmlNodePtr node, const gchar *name, gint *value)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        *value = atoi((gchar*)c);
+        r = TRUE;
+    }
+    xmlFree(c);
+    return r;
+}
+
+gboolean obt_parse_attr_string(xmlNodePtr node, const gchar *name,
+                               gchar **value)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        *value = g_strdup((gchar*)c);
+        r = TRUE;
+    }
+    xmlFree(c);
+    return r;
+}
+
+gboolean obt_parse_attr_contains(xmlNodePtr node, const gchar *name,
+                                 const gchar *val)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c)
+        r = !xmlStrcasecmp(c, (const xmlChar*) val);
+    xmlFree(c);
+    return r;
+}
diff --git a/obt/parse.h b/obt/parse.h
new file mode 100644 (file)
index 0000000..8e5acd7
--- /dev/null
@@ -0,0 +1,85 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/parse.h for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_parse_h
+#define __obt_parse_h
+
+#include <libxml/parser.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ObtParseInst ObtParseInst;
+
+typedef void (*ObtParseCallback)(xmlNodePtr node, gpointer data);
+
+ObtParseInst* obt_parse_instance_new();
+void obt_parse_instance_ref(ObtParseInst *inst);
+void obt_parse_instance_unref(ObtParseInst *inst);
+
+gboolean obt_parse_load_file(ObtParseInst *inst,
+                             const gchar *path,
+                             const gchar *root_node);
+gboolean obt_parse_load_config_file(ObtParseInst *inst,
+                                    const gchar *domain,
+                                    const gchar *filename,
+                                    const gchar *root_node);
+gboolean obt_parse_load_data_file(ObtParseInst *inst,
+                                  const gchar *domain,
+                                  const gchar *filename,
+                                  const gchar *root_node);
+gboolean obt_parse_load_theme_file(ObtParseInst *inst,
+                                   const gchar *theme,
+                                   const gchar *domain,
+                                   const gchar *filename,
+                                   const gchar *root_node);
+gboolean obt_parse_load_mem(ObtParseInst *inst,
+                            gpointer data, guint len, const gchar *root_node);
+
+xmlDocPtr obt_parse_doc(ObtParseInst *inst);
+xmlNodePtr obt_parse_root(ObtParseInst *inst);
+
+void obt_parse_close(ObtParseInst *inst);
+
+void obt_parse_register(ObtParseInst *inst, const gchar *tag,
+                        ObtParseCallback func, gpointer data);
+void obt_parse_tree(ObtParseInst *i, xmlNodePtr node);
+void obt_parse_tree_from_root(ObtParseInst *i);
+
+
+/* helpers */
+
+xmlNodePtr obt_parse_find_node(xmlNodePtr node, const gchar *name);
+
+gboolean obt_parse_node_contains (xmlNodePtr node, const gchar *val);
+gchar   *obt_parse_node_string   (xmlNodePtr node);
+gint     obt_parse_node_int      (xmlNodePtr node);
+gboolean obt_parse_node_bool     (xmlNodePtr node);
+
+gboolean obt_parse_attr_contains (xmlNodePtr node, const gchar *name,
+                                  const gchar *val);
+gboolean obt_parse_attr_string   (xmlNodePtr node, const gchar *name,
+                                  gchar **value);
+gboolean obt_parse_attr_int      (xmlNodePtr node, const gchar *name,
+                                  gint *value);
+gboolean obt_parse_attr_bool     (xmlNodePtr node, const gchar *name,
+                                  gboolean *value);
+
+G_END_DECLS
+
+#endif
diff --git a/obt/paths.c b/obt/paths.c
new file mode 100644 (file)
index 0000000..6100499
--- /dev/null
@@ -0,0 +1,247 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/paths.c for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/paths.h"
+#include "obt/util.h"
+
+#ifdef HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
+
+struct _ObtPaths
+{
+    gint   ref;
+    gchar  *config_home;
+    gchar  *data_home;
+    gchar  *cache_home;
+    GSList *config_dirs;
+    GSList *data_dirs;
+};
+
+static gint slist_path_cmp(const gchar *a, const gchar *b)
+{
+    return strcmp(a, b);
+}
+
+typedef GSList* (*GSListFunc) (gpointer list, gconstpointer data);
+
+static GSList* slist_path_add(GSList *list, gpointer data, GSListFunc func)
+{
+    g_assert(func);
+
+    if (!data)
+        return list;
+
+    if (!g_slist_find_custom(list, data, (GCompareFunc) slist_path_cmp))
+        list = func(list, data);
+    else
+        g_free(data);
+
+    return list;
+}
+
+static GSList* split_paths(const gchar *paths)
+{
+    GSList *list = NULL;
+    gchar **spl, **it;
+
+    if (!paths)
+        return NULL;
+    spl = g_strsplit(paths, ":", -1);
+    for (it = spl; *it; ++it)
+        list = slist_path_add(list, *it, (GSListFunc) g_slist_append);
+    g_free(spl);
+    return list;
+}
+
+ObtPaths* obt_paths_new(void)
+{
+    ObtPaths *p;
+    const gchar *path;
+
+    p = g_new0(ObtPaths, 1);
+    p->ref = 1;
+
+    path = g_getenv("XDG_CONFIG_HOME");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->config_home = g_build_filename(path, NULL);
+    else
+        p->config_home = g_build_filename(g_get_home_dir(), ".config", NULL);
+
+    path = g_getenv("XDG_DATA_HOME");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->data_home = g_build_filename(path, NULL);
+    else
+        p->data_home = g_build_filename(g_get_home_dir(), ".local",
+                                        "share", NULL);
+
+    path = g_getenv("XDG_CACHE_HOME");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->cache_home = g_build_filename(path, NULL);
+    else
+        p->cache_home = g_build_filename(g_get_home_dir(), ".cache", NULL);
+
+    path = g_getenv("XDG_CONFIG_DIRS");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->config_dirs = split_paths(path);
+    else {
+        p->config_dirs = slist_path_add(p->config_dirs,
+                                        g_strdup(CONFIGDIR),
+                                        (GSListFunc) g_slist_append);
+        p->config_dirs = slist_path_add(p->config_dirs,
+                                        g_build_filename
+                                        (G_DIR_SEPARATOR_S,
+                                         "etc", "xdg", NULL),
+                                        (GSListFunc) g_slist_append);
+    }
+    p->config_dirs = slist_path_add(p->config_dirs,
+                                    g_strdup(p->config_home),
+                                    (GSListFunc) g_slist_prepend);
+
+    path = g_getenv("XDG_DATA_DIRS");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->data_dirs = split_paths(path);
+    else {
+        p->data_dirs = slist_path_add(p->data_dirs,
+                                      g_strdup(DATADIR),
+                                      (GSListFunc) g_slist_append);
+        p->data_dirs = slist_path_add(p->data_dirs,
+                                      g_build_filename
+                                      (G_DIR_SEPARATOR_S,
+                                       "usr", "local", "share", NULL),
+                                      (GSListFunc) g_slist_append);
+        p->data_dirs = slist_path_add(p->data_dirs,
+                                      g_build_filename
+                                      (G_DIR_SEPARATOR_S,
+                                       "usr", "share", NULL),
+                                      (GSListFunc) g_slist_append);
+    }
+    p->data_dirs = slist_path_add(p->data_dirs,
+                                  g_strdup(p->data_home),
+                                  (GSListFunc) g_slist_prepend);
+    return p;
+}
+
+void obt_paths_ref(ObtPaths *p)
+{
+    ++p->ref;
+}
+
+void obt_paths_unref(ObtPaths *p)
+{
+    if (p && --p->ref == 0) {
+        GSList *it;
+
+        for (it = p->config_dirs; it; it = g_slist_next(it))
+            g_free(it->data);
+        g_slist_free(p->config_dirs);
+        for (it = p->data_dirs; it; it = g_slist_next(it))
+            g_free(it->data);
+        g_slist_free(p->data_dirs);
+        g_free(p->config_home);
+        g_free(p->data_home);
+        g_free(p->cache_home);
+
+        obt_free0(p, ObtPaths, 1);
+    }
+}
+
+gchar *obt_paths_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;
+}
+
+gboolean obt_paths_mkdir(const gchar *path, gint mode)
+{
+    gboolean ret = TRUE;
+
+    g_return_val_if_fail(path != NULL, FALSE);
+    g_return_val_if_fail(path[0] != '\0', FALSE);
+
+    if (!g_file_test(path, G_FILE_TEST_IS_DIR))
+        if (mkdir(path, mode) == -1)
+            ret = FALSE;
+
+    return ret;
+}
+
+gboolean obt_paths_mkdir_path(const gchar *path, gint mode)
+{
+    gboolean ret = TRUE;
+
+    g_return_val_if_fail(path != NULL, FALSE);
+    g_return_val_if_fail(path[0] == '/', FALSE);
+
+    if (!g_file_test(path, G_FILE_TEST_IS_DIR)) {
+        gchar *c, *e;
+
+        c = g_strdup(path);
+        e = c;
+        while ((e = strchr(e + 1, '/'))) {
+            *e = '\0';
+            if (!(ret = obt_paths_mkdir(c, mode)))
+                goto parse_mkdir_path_end;
+            *e = '/';
+        }
+        ret = obt_paths_mkdir(c, mode);
+
+    parse_mkdir_path_end:
+        g_free(c);
+    }
+
+    return ret;
+}
+
+const gchar* obt_paths_config_home(ObtPaths *p)
+{
+    return p->config_home;
+}
+
+const gchar* obt_paths_data_home(ObtPaths *p)
+{
+    return p->data_home;
+}
+
+const gchar* obt_paths_cache_home(ObtPaths *p)
+{
+    return p->cache_home;
+}
+
+GSList* obt_paths_config_dirs(ObtPaths *p)
+{
+    return p->config_dirs;
+}
+
+GSList* obt_paths_data_dirs(ObtPaths *p)
+{
+    return p->data_dirs;
+}
diff --git a/obt/paths.h b/obt/paths.h
new file mode 100644 (file)
index 0000000..a6e32ae
--- /dev/null
@@ -0,0 +1,44 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/paths.h for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_paths_h
+#define __obt_paths_h
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ObtPaths ObtPaths;
+
+ObtPaths* obt_paths_new();
+void obt_paths_ref(ObtPaths *p);
+void obt_paths_unref(ObtPaths *p);
+
+const gchar* obt_paths_config_home(ObtPaths *p);
+const gchar* obt_paths_data_home(ObtPaths *p);
+const gchar* obt_paths_cache_home(ObtPaths *p);
+GSList* obt_paths_config_dirs(ObtPaths *p);
+GSList* obt_paths_data_dirs(ObtPaths *p);
+
+gchar *obt_paths_expand_tilde(const gchar *f);
+gboolean obt_paths_mkdir(const gchar *path, gint mode);
+gboolean obt_paths_mkdir_path(const gchar *path, gint mode);
+
+G_END_DECLS
+
+#endif
diff --git a/obt/prop.c b/obt/prop.c
new file mode 100644 (file)
index 0000000..89d3950
--- /dev/null
@@ -0,0 +1,495 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/prop.c for the Openbox window manager
+   Copyright (c) 2006        Mikael Magnusson
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/prop.h"
+#include "obt/display.h"
+
+#include <X11/Xatom.h>
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
+
+Atom prop_atoms[OBT_PROP_NUM_ATOMS];
+gboolean prop_started = FALSE;
+
+#define CREATE_NAME(var, name) (prop_atoms[OBT_PROP_##var] = \
+                                XInternAtom((obt_display), (name), FALSE))
+#define CREATE(var) CREATE_NAME(var, #var)
+#define CREATE_(var) CREATE_NAME(var, "_" #var)
+
+void obt_prop_startup()
+{
+    if (prop_started) return;
+    prop_started = TRUE;
+
+    g_assert(obt_display);
+
+    CREATE(CARDINAL);
+    CREATE(WINDOW);
+    CREATE(PIXMAP);
+    CREATE(ATOM);
+    CREATE(STRING);
+    CREATE_NAME(UTF8, "UTF8_STRING");
+
+    CREATE(MANAGER);
+
+    CREATE(WM_COLORMAP_WINDOWS);
+    CREATE(WM_PROTOCOLS);
+    CREATE(WM_STATE);
+    CREATE(WM_CHANGE_STATE);
+    CREATE(WM_DELETE_WINDOW);
+    CREATE(WM_TAKE_FOCUS);
+    CREATE(WM_NAME);
+    CREATE(WM_ICON_NAME);
+    CREATE(WM_CLASS);
+    CREATE(WM_WINDOW_ROLE);
+    CREATE(WM_CLIENT_MACHINE);
+    CREATE(WM_COMMAND);
+    CREATE(WM_CLIENT_LEADER);
+    CREATE_(MOTIF_WM_HINTS);
+
+    CREATE(SM_CLIENT_ID);
+
+    CREATE_(NET_WM_FULL_PLACEMENT);
+
+    CREATE_(NET_SUPPORTED);
+    CREATE_(NET_CLIENT_LIST);
+    CREATE_(NET_CLIENT_LIST_STACKING);
+    CREATE_(NET_NUMBER_OF_DESKTOPS);
+    CREATE_(NET_DESKTOP_GEOMETRY);
+    CREATE_(NET_DESKTOP_VIEWPORT);
+    CREATE_(NET_CURRENT_DESKTOP);
+    CREATE_(NET_DESKTOP_NAMES);
+    CREATE_(NET_ACTIVE_WINDOW);
+/*    CREATE_(NET_RESTACK_WINDOW);*/
+    CREATE_(NET_WORKAREA);
+    CREATE_(NET_SUPPORTING_WM_CHECK);
+    CREATE_(NET_DESKTOP_LAYOUT);
+    CREATE_(NET_SHOWING_DESKTOP);
+
+    CREATE_(NET_CLOSE_WINDOW);
+    CREATE_(NET_WM_MOVERESIZE);
+    CREATE_(NET_MOVERESIZE_WINDOW);
+    CREATE_(NET_REQUEST_FRAME_EXTENTS);
+    CREATE_(NET_RESTACK_WINDOW);
+
+    CREATE_(NET_STARTUP_ID);
+
+    CREATE_(NET_WM_NAME);
+    CREATE_(NET_WM_VISIBLE_NAME);
+    CREATE_(NET_WM_ICON_NAME);
+    CREATE_(NET_WM_VISIBLE_ICON_NAME);
+    CREATE_(NET_WM_DESKTOP);
+    CREATE_(NET_WM_WINDOW_TYPE);
+    CREATE_(NET_WM_STATE);
+    CREATE_(NET_WM_STRUT);
+    CREATE_(NET_WM_STRUT_PARTIAL);
+    CREATE_(NET_WM_ICON);
+    CREATE_(NET_WM_ICON_GEOMETRY);
+    CREATE_(NET_WM_PID);
+    CREATE_(NET_WM_ALLOWED_ACTIONS);
+    CREATE_(NET_WM_USER_TIME);
+/*  CREATE_(NET_WM_USER_TIME_WINDOW); */
+    CREATE_(KDE_NET_WM_FRAME_STRUT);
+    CREATE_(NET_FRAME_EXTENTS);
+
+    CREATE_(NET_WM_PING);
+#ifdef SYNC
+    CREATE_(NET_WM_SYNC_REQUEST);
+    CREATE_(NET_WM_SYNC_REQUEST_COUNTER);
+#endif
+
+    CREATE_(NET_WM_WINDOW_TYPE_DESKTOP);
+    CREATE_(NET_WM_WINDOW_TYPE_DOCK);
+    CREATE_(NET_WM_WINDOW_TYPE_TOOLBAR);
+    CREATE_(NET_WM_WINDOW_TYPE_MENU);
+    CREATE_(NET_WM_WINDOW_TYPE_UTILITY);
+    CREATE_(NET_WM_WINDOW_TYPE_SPLASH);
+    CREATE_(NET_WM_WINDOW_TYPE_DIALOG);
+    CREATE_(NET_WM_WINDOW_TYPE_NORMAL);
+
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPLEFT] = 0;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOP] = 1;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPRIGHT] = 2;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_RIGHT] = 3;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT] = 4;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOM] = 5;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT] = 6;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_LEFT] = 7;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_MOVE] = 8;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_KEYBOARD] = 9;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_MOVE_KEYBOARD] = 10;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_CANCEL] = 11;
+
+    CREATE_(NET_WM_ACTION_MOVE);
+    CREATE_(NET_WM_ACTION_RESIZE);
+    CREATE_(NET_WM_ACTION_MINIMIZE);
+    CREATE_(NET_WM_ACTION_SHADE);
+    CREATE_(NET_WM_ACTION_MAXIMIZE_HORZ);
+    CREATE_(NET_WM_ACTION_MAXIMIZE_VERT);
+    CREATE_(NET_WM_ACTION_FULLSCREEN);
+    CREATE_(NET_WM_ACTION_CHANGE_DESKTOP);
+    CREATE_(NET_WM_ACTION_CLOSE);
+    CREATE_(NET_WM_ACTION_ABOVE);
+    CREATE_(NET_WM_ACTION_BELOW);
+
+    CREATE_(NET_WM_STATE_MODAL);
+/*    CREATE_(NET_WM_STATE_STICKY);*/
+    CREATE_(NET_WM_STATE_MAXIMIZED_VERT);
+    CREATE_(NET_WM_STATE_MAXIMIZED_HORZ);
+    CREATE_(NET_WM_STATE_SHADED);
+    CREATE_(NET_WM_STATE_SKIP_TASKBAR);
+    CREATE_(NET_WM_STATE_SKIP_PAGER);
+    CREATE_(NET_WM_STATE_HIDDEN);
+    CREATE_(NET_WM_STATE_FULLSCREEN);
+    CREATE_(NET_WM_STATE_ABOVE);
+    CREATE_(NET_WM_STATE_BELOW);
+    CREATE_(NET_WM_STATE_DEMANDS_ATTENTION);
+
+    prop_atoms[OBT_PROP_NET_WM_STATE_ADD] = 1;
+    prop_atoms[OBT_PROP_NET_WM_STATE_REMOVE] = 0;
+    prop_atoms[OBT_PROP_NET_WM_STATE_TOGGLE] = 2;
+
+    prop_atoms[OBT_PROP_NET_WM_ORIENTATION_HORZ] = 0;
+    prop_atoms[OBT_PROP_NET_WM_ORIENTATION_VERT] = 1;
+    prop_atoms[OBT_PROP_NET_WM_TOPLEFT] = 0;
+    prop_atoms[OBT_PROP_NET_WM_TOPRIGHT] = 1;
+    prop_atoms[OBT_PROP_NET_WM_BOTTOMRIGHT] = 2;
+    prop_atoms[OBT_PROP_NET_WM_BOTTOMLEFT] = 3;
+
+    CREATE_(KDE_WM_CHANGE_STATE);
+    CREATE_(KDE_NET_WM_WINDOW_TYPE_OVERRIDE);
+
+/*
+    CREATE_NAME(ROOTPMAPId, "_XROOTPMAP_ID");
+    CREATE_NAME(ESETROOTId, "ESETROOT_PMAP_ID");
+*/
+
+    CREATE_(OPENBOX_PID);
+    CREATE_(OB_THEME);
+    CREATE_(OB_CONFIG_FILE);
+    CREATE_(OB_WM_ACTION_UNDECORATE);
+    CREATE_(OB_WM_STATE_UNDECORATED);
+    CREATE_(OB_CONTROL);
+}
+
+Atom obt_prop_atom(ObtPropAtom a)
+{
+    g_assert(prop_started);
+    g_assert(a < OBT_PROP_NUM_ATOMS);
+    return prop_atoms[a];
+}
+
+static gboolean get_prealloc(Window win, Atom prop, Atom type, gint size,
+                             guchar *data, gulong num)
+{
+    gboolean ret = FALSE;
+    gint res;
+    guchar *xdata = NULL;
+    Atom ret_type;
+    gint ret_size;
+    gulong ret_items, bytes_left;
+    glong num32 = 32 / size * num; /* num in 32-bit elements */
+
+    res = XGetWindowProperty(obt_display, win, prop, 0l, num32,
+                             FALSE, type, &ret_type, &ret_size,
+                             &ret_items, &bytes_left, &xdata);
+    if (res == Success && ret_items && xdata) {
+        if (ret_size == size && ret_items >= num) {
+            guint i;
+            for (i = 0; i < num; ++i)
+                switch (size) {
+                case 8:
+                    data[i] = xdata[i];
+                    break;
+                case 16:
+                    ((guint16*)data)[i] = ((gushort*)xdata)[i];
+                    break;
+                case 32:
+                    ((guint32*)data)[i] = ((gulong*)xdata)[i];
+                    break;
+                default:
+                    g_assert_not_reached(); /* unhandled size */
+                }
+            ret = TRUE;
+        }
+        XFree(xdata);
+    }
+    return ret;
+}
+
+static gboolean get_all(Window win, Atom prop, Atom type, gint size,
+                        guchar **data, guint *num)
+{
+    gboolean ret = FALSE;
+    gint res;
+    guchar *xdata = NULL;
+    Atom ret_type;
+    gint ret_size;
+    gulong ret_items, bytes_left;
+
+    res = XGetWindowProperty(obt_display, win, prop, 0l, G_MAXLONG,
+                             FALSE, type, &ret_type, &ret_size,
+                             &ret_items, &bytes_left, &xdata);
+    if (res == Success) {
+        if (ret_size == size && ret_items > 0) {
+            guint i;
+
+            *data = g_malloc(ret_items * (size / 8));
+            for (i = 0; i < ret_items; ++i)
+                switch (size) {
+                case 8:
+                    (*data)[i] = xdata[i];
+                    break;
+                case 16:
+                    ((guint16*)*data)[i] = ((gushort*)xdata)[i];
+                    break;
+                case 32:
+                    ((guint32*)*data)[i] = ((gulong*)xdata)[i];
+                    break;
+                default:
+                    g_assert_not_reached(); /* unhandled size */
+                }
+            *num = ret_items;
+            ret = TRUE;
+        }
+        XFree(xdata);
+    }
+    return ret;
+}
+
+static gboolean get_stringlist(Window win, Atom prop, gchar ***list, gint *nstr)
+{
+    XTextProperty tprop;
+    gboolean ret = FALSE;
+
+    if (XGetTextProperty(obt_display, win, &tprop, prop) && tprop.nitems) {
+        if (XTextPropertyToStringList(&tprop, list, nstr))
+            ret = TRUE;
+        XFree(tprop.value);
+    }
+    return ret;
+}
+
+gboolean obt_prop_get32(Window win, Atom prop, Atom type, guint32 *ret)
+{
+    return get_prealloc(win, prop, type, 32, (guchar*)ret, 1);
+}
+
+gboolean obt_prop_get_array32(Window win, Atom prop, Atom type, guint32 **ret,
+                              guint *nret)
+{
+    return get_all(win, prop, type, 32, (guchar**)ret, nret);
+}
+
+gboolean obt_prop_get_string_locale(Window win, Atom prop, gchar **ret)
+{
+    gchar **list;
+    gint nstr;
+    gchar *s;
+
+    if (get_stringlist(win, prop, &list, &nstr) && nstr) {
+        s = g_locale_to_utf8(list[0], -1, NULL, NULL, NULL);
+        XFreeStringList(list);
+        if (s) {
+            *ret = s;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+gboolean obt_prop_get_strings_locale(Window win, Atom prop, gchar ***ret)
+{
+    GSList *strs = NULL, *it;
+    gchar *raw, *p;
+    guint num, i, count = 0;
+
+    if (get_all(win, prop, OBT_PROP_ATOM(STRING), 8,
+                (guchar**)&raw, &num))
+    {
+        p = raw;
+        while (p < raw + num) {
+            ++count;
+            strs = g_slist_append(strs, p);
+            p += strlen(p) + 1; /* next string */
+        }
+
+        *ret = g_new0(gchar*, count + 1);
+        (*ret)[count] = NULL; /* null terminated list */
+
+        for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) {
+            (*ret)[i] = g_locale_to_utf8(it->data, -1, NULL, NULL, NULL);
+            /* make sure translation did not fail */
+            if (!(*ret)[i])
+                (*ret)[i] = g_strdup("");
+        }
+        g_free(raw);
+        g_slist_free(strs);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+gboolean obt_prop_get_string_utf8(Window win, Atom prop, gchar **ret)
+{
+    gchar *raw;
+    gchar *str;
+    guint num;
+
+    if (get_all(win, prop, OBT_PROP_ATOM(UTF8), 8,
+                (guchar**)&raw, &num))
+    {
+        str = g_strndup(raw, num); /* grab the first string from the list */
+        g_free(raw);
+        if (g_utf8_validate(str, -1, NULL)) {
+            *ret = str;
+            return TRUE;
+        }
+        g_free(str);
+    }
+    return FALSE;
+}
+
+gboolean obt_prop_get_strings_utf8(Window win, Atom prop, gchar ***ret)
+{
+    GSList *strs = NULL, *it;
+    gchar *raw, *p;
+    guint num, i, count = 0;
+
+    if (get_all(win, prop, OBT_PROP_ATOM(UTF8), 8,
+                (guchar**)&raw, &num))
+    {
+        p = raw;
+        while (p < raw + num) {
+            ++count;
+            strs = g_slist_append(strs, p);
+            p += strlen(p) + 1; /* next string */
+        }
+
+        *ret = g_new0(gchar*, count + 1);
+
+        for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) {
+            if (g_utf8_validate(it->data, -1, NULL))
+                (*ret)[i] = g_strdup(it->data);
+            else
+                (*ret)[i] = g_strdup("");
+        }
+        g_free(raw);
+        g_slist_free(strs);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+void obt_prop_set32(Window win, Atom prop, Atom type, gulong val)
+{
+    XChangeProperty(obt_display, win, prop, type, 32, PropModeReplace,
+                    (guchar*)&val, 1);
+}
+
+void obt_prop_set_array32(Window win, Atom prop, Atom type, gulong *val,
+                      guint num)
+{
+    XChangeProperty(obt_display, win, prop, type, 32, PropModeReplace,
+                    (guchar*)val, num);
+}
+
+void obt_prop_set_string_locale(Window win, Atom prop, const gchar *val)
+{
+    gchar const *s[2] = { val, NULL };
+    obt_prop_set_strings_locale(win, prop, s);
+}
+
+void obt_prop_set_strings_locale(Window win, Atom prop, const gchar **strs)
+{
+    gint i, count;
+    gchar **lstrs;
+    XTextProperty tprop;
+
+    /* count the strings in strs, and convert them to the locale format */
+    for (count = 0; strs[count]; ++count);
+    lstrs = g_new0(char*, count);
+    for (i = 0; i < count; ++i) {
+        lstrs[i] = g_locale_from_utf8(strs[i], -1, NULL, NULL, NULL);
+        if (!lstrs[i]) {
+            lstrs[i] = g_strdup(""); /* make it an empty string */
+            g_warning("Unable to translate string '%s' from UTF8 to locale "
+                      "format", strs[i]);
+        }
+    }
+
+
+    XStringListToTextProperty(lstrs, count, &tprop);
+    XSetTextProperty(obt_display, win, &tprop, prop);
+    XFree(tprop.value);
+}
+
+void obt_prop_set_string_utf8(Window win, Atom prop, const gchar *val)
+{
+    XChangeProperty(obt_display, win, prop, OBT_PROP_ATOM(UTF8), 8,
+                    PropModeReplace, (const guchar*)val, strlen(val));
+}
+
+void obt_prop_set_strings_utf8(Window win, Atom prop, const gchar **strs)
+{
+    GString *str;
+    gchar const **s;
+
+    str = g_string_sized_new(0);
+    for (s = strs; *s; ++s) {
+        str = g_string_append(str, *s);
+        str = g_string_append_c(str, '\0');
+    }
+    XChangeProperty(obt_display, win, prop, obt_prop_atom(OBT_PROP_UTF8), 8,
+                    PropModeReplace, (guchar*)str->str, str->len);
+    g_string_free(str, TRUE);
+}
+
+void obt_prop_erase(Window win, Atom prop)
+{
+    XDeleteProperty(obt_display, win, prop);
+}
+
+void obt_prop_message(gint screen, Window about, Atom messagetype,
+                      glong data0, glong data1, glong data2, glong data3,
+                      glong data4, glong mask)
+{
+    obt_prop_message_to(obt_root(screen), about, messagetype,
+                        data0, data1, data2, data3, data4, mask);
+}
+
+void obt_prop_message_to(Window to, Window about,
+                         Atom messagetype,
+                         glong data0, glong data1, glong data2, glong data3,
+                         glong data4, glong mask)
+{
+    XEvent ce;
+    ce.xclient.type = ClientMessage;
+    ce.xclient.message_type = messagetype;
+    ce.xclient.display = obt_display;
+    ce.xclient.window = about;
+    ce.xclient.format = 32;
+    ce.xclient.data.l[0] = data0;
+    ce.xclient.data.l[1] = data1;
+    ce.xclient.data.l[2] = data2;
+    ce.xclient.data.l[3] = data3;
+    ce.xclient.data.l[4] = data4;
+    XSendEvent(obt_display, to, FALSE, mask, &ce);
+}
diff --git a/obt/prop.h b/obt/prop.h
new file mode 100644 (file)
index 0000000..e123611
--- /dev/null
@@ -0,0 +1,278 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/prop.h for the Openbox window manager
+   Copyright (c) 2006        Mikael Magnusson
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_prop_h
+#define __obt_prop_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+    /* types */
+    OBT_PROP_CARDINAL, /*!< The atom which represents the Cardinal data type */
+    OBT_PROP_WINDOW,   /*!< The atom which represents window ids */
+    OBT_PROP_PIXMAP,   /*!< The atom which represents pixmap ids */
+    OBT_PROP_ATOM,     /*!< The atom which represents atom values */
+    OBT_PROP_STRING,   /*!< The atom which represents ascii strings */
+    OBT_PROP_UTF8,     /*!< The atom which represents utf8-encoded strings */
+
+    /* selection stuff */
+    OBT_PROP_MANAGER,
+
+    /* window hints */
+    OBT_PROP_WM_COLORMAP_WINDOWS,
+    OBT_PROP_WM_PROTOCOLS,
+    OBT_PROP_WM_STATE,
+    OBT_PROP_WM_DELETE_WINDOW,
+    OBT_PROP_WM_TAKE_FOCUS,
+    OBT_PROP_WM_CHANGE_STATE,
+    OBT_PROP_WM_NAME,
+    OBT_PROP_WM_ICON_NAME,
+    OBT_PROP_WM_CLASS,
+    OBT_PROP_WM_WINDOW_ROLE,
+    OBT_PROP_WM_CLIENT_MACHINE,
+    OBT_PROP_WM_COMMAND,
+    OBT_PROP_WM_CLIENT_LEADER,
+    OBT_PROP_MOTIF_WM_HINTS,
+
+    /* SM atoms */
+    OBT_PROP_SM_CLIENT_ID,
+
+    /* NETWM atoms */
+
+    /* Atoms that are used inside messages - these don't go in net_supported */
+
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPLEFT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOP,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPRIGHT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_RIGHT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOM,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_LEFT,
+    OBT_PROP_NET_WM_MOVERESIZE_MOVE,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_KEYBOARD,
+    OBT_PROP_NET_WM_MOVERESIZE_MOVE_KEYBOARD,
+    OBT_PROP_NET_WM_MOVERESIZE_CANCEL,
+
+    OBT_PROP_NET_WM_STATE_ADD,
+    OBT_PROP_NET_WM_STATE_REMOVE,
+    OBT_PROP_NET_WM_STATE_TOGGLE,
+
+    OBT_PROP_NET_WM_ORIENTATION_HORZ,
+    OBT_PROP_NET_WM_ORIENTATION_VERT,
+    OBT_PROP_NET_WM_TOPLEFT,
+    OBT_PROP_NET_WM_TOPRIGHT,
+    OBT_PROP_NET_WM_BOTTOMRIGHT,
+    OBT_PROP_NET_WM_BOTTOMLEFT,
+
+    OBT_PROP_PRIVATE_PADDING1,
+    OBT_PROP_PRIVATE_PADDING2,
+    OBT_PROP_PRIVATE_PADDING3,
+    OBT_PROP_PRIVATE_PADDING4,
+    OBT_PROP_PRIVATE_PADDING5,
+    OBT_PROP_PRIVATE_PADDING6,
+    OBT_PROP_PRIVATE_PADDING7,
+    OBT_PROP_PRIVATE_PADDING8,
+    OBT_PROP_PRIVATE_PADDING9,
+    OBT_PROP_PRIVATE_PADDING10,
+    OBT_PROP_PRIVATE_PADDING11,
+    OBT_PROP_PRIVATE_PADDING12,
+
+    /* Everything below here must go in net_supported on the root window */
+
+    /* root window properties */
+    OBT_PROP_NET_SUPPORTED,
+    OBT_PROP_NET_CLIENT_LIST,
+    OBT_PROP_NET_CLIENT_LIST_STACKING,
+    OBT_PROP_NET_NUMBER_OF_DESKTOPS,
+    OBT_PROP_NET_DESKTOP_GEOMETRY,
+    OBT_PROP_NET_DESKTOP_VIEWPORT,
+    OBT_PROP_NET_CURRENT_DESKTOP,
+    OBT_PROP_NET_DESKTOP_NAMES,
+    OBT_PROP_NET_ACTIVE_WINDOW,
+/*    Atom net_restack_window;*/
+    OBT_PROP_NET_WORKAREA,
+    OBT_PROP_NET_SUPPORTING_WM_CHECK,
+    OBT_PROP_NET_DESKTOP_LAYOUT,
+    OBT_PROP_NET_SHOWING_DESKTOP,
+
+    /* root window messages */
+    OBT_PROP_NET_CLOSE_WINDOW,
+    OBT_PROP_NET_WM_MOVERESIZE,
+    OBT_PROP_NET_MOVERESIZE_WINDOW,
+    OBT_PROP_NET_REQUEST_FRAME_EXTENTS,
+    OBT_PROP_NET_RESTACK_WINDOW,
+
+    /* helpful hints to apps that aren't used for anything */
+    OBT_PROP_NET_WM_FULL_PLACEMENT,
+
+    /* startup-notification extension */
+    OBT_PROP_NET_STARTUP_ID,
+
+    /* application window properties */
+    OBT_PROP_NET_WM_NAME,
+    OBT_PROP_NET_WM_VISIBLE_NAME,
+    OBT_PROP_NET_WM_ICON_NAME,
+    OBT_PROP_NET_WM_VISIBLE_ICON_NAME,
+    OBT_PROP_NET_WM_DESKTOP,
+    OBT_PROP_NET_WM_WINDOW_TYPE,
+    OBT_PROP_NET_WM_STATE,
+    OBT_PROP_NET_WM_STRUT,
+    OBT_PROP_NET_WM_STRUT_PARTIAL,
+    OBT_PROP_NET_WM_ICON,
+    OBT_PROP_NET_WM_ICON_GEOMETRY,
+    OBT_PROP_NET_WM_PID,
+    OBT_PROP_NET_WM_ALLOWED_ACTIONS,
+    OBT_PROP_NET_WM_USER_TIME,
+/*  OBT_PROP_NET_WM_USER_TIME_WINDOW, */
+    OBT_PROP_NET_FRAME_EXTENTS,
+
+    /* application protocols */
+    OBT_PROP_NET_WM_PING,
+#ifdef SYNC
+    OBT_PROP_NET_WM_SYNC_REQUEST,
+    OBT_PROP_NET_WM_SYNC_REQUEST_COUNTER,
+#endif
+
+    OBT_PROP_NET_WM_WINDOW_TYPE_DESKTOP,
+    OBT_PROP_NET_WM_WINDOW_TYPE_DOCK,
+    OBT_PROP_NET_WM_WINDOW_TYPE_TOOLBAR,
+    OBT_PROP_NET_WM_WINDOW_TYPE_MENU,
+    OBT_PROP_NET_WM_WINDOW_TYPE_UTILITY,
+    OBT_PROP_NET_WM_WINDOW_TYPE_SPLASH,
+    OBT_PROP_NET_WM_WINDOW_TYPE_DIALOG,
+    OBT_PROP_NET_WM_WINDOW_TYPE_NORMAL,
+
+    OBT_PROP_NET_WM_ACTION_MOVE,
+    OBT_PROP_NET_WM_ACTION_RESIZE,
+    OBT_PROP_NET_WM_ACTION_MINIMIZE,
+    OBT_PROP_NET_WM_ACTION_SHADE,
+/*    OBT_PROP_NET_WM_ACTION_STICK,*/
+    OBT_PROP_NET_WM_ACTION_MAXIMIZE_HORZ,
+    OBT_PROP_NET_WM_ACTION_MAXIMIZE_VERT,
+    OBT_PROP_NET_WM_ACTION_FULLSCREEN,
+    OBT_PROP_NET_WM_ACTION_CHANGE_DESKTOP,
+    OBT_PROP_NET_WM_ACTION_CLOSE,
+    OBT_PROP_NET_WM_ACTION_ABOVE,
+    OBT_PROP_NET_WM_ACTION_BELOW,
+
+    OBT_PROP_NET_WM_STATE_MODAL,
+/*    OBT_PROP_NET_WM_STATE_STICKY,*/
+    OBT_PROP_NET_WM_STATE_MAXIMIZED_VERT,
+    OBT_PROP_NET_WM_STATE_MAXIMIZED_HORZ,
+    OBT_PROP_NET_WM_STATE_SHADED,
+    OBT_PROP_NET_WM_STATE_SKIP_TASKBAR,
+    OBT_PROP_NET_WM_STATE_SKIP_PAGER,
+    OBT_PROP_NET_WM_STATE_HIDDEN,
+    OBT_PROP_NET_WM_STATE_FULLSCREEN,
+    OBT_PROP_NET_WM_STATE_ABOVE,
+    OBT_PROP_NET_WM_STATE_BELOW,
+    OBT_PROP_NET_WM_STATE_DEMANDS_ATTENTION,
+
+    /* KDE atoms */
+
+    OBT_PROP_KDE_WM_CHANGE_STATE,
+    OBT_PROP_KDE_NET_WM_FRAME_STRUT,
+    OBT_PROP_KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
+
+/*
+    OBT_PROP_ROOTPMAPID,
+    OBT_PROP_ESETROOTID,
+*/
+
+    /* Openbox specific atoms */
+
+    OBT_PROP_OB_WM_ACTION_UNDECORATE,
+    OBT_PROP_OB_WM_STATE_UNDECORATED,
+    OBT_PROP_OPENBOX_PID, /* this is depreecated in favour of ob_control */
+    OBT_PROP_OB_THEME,
+    OBT_PROP_OB_CONFIG_FILE,
+    OBT_PROP_OB_CONTROL,
+
+    OBT_PROP_NUM_ATOMS
+} ObtPropAtom;
+
+Atom obt_prop_atom(ObtPropAtom a);
+
+gboolean obt_prop_get32(Window win, Atom prop, Atom type, guint32 *ret);
+gboolean obt_prop_get_array32(Window win, Atom prop, Atom type, guint32 **ret,
+                              guint *nret);
+gboolean obt_prop_get_string_locale(Window win, Atom prop, gchar **ret);
+gboolean obt_prop_get_string_utf8(Window win, Atom prop, gchar **ret);
+gboolean obt_prop_get_strings_locale(Window win, Atom prop, gchar ***ret);
+gboolean obt_prop_get_strings_utf8(Window win, Atom prop, gchar ***ret);
+
+void obt_prop_set32(Window win, Atom prop, Atom type, gulong val);
+void obt_prop_set_array32(Window win, Atom prop, Atom type, gulong *val,
+                          guint num);
+void obt_prop_set_string_locale(Window win, Atom prop, const gchar *val);
+void obt_prop_set_string_utf8(Window win, Atom prop, const gchar *val);
+void obt_prop_set_strings_locale(Window win, Atom prop, const gchar **strs);
+void obt_prop_set_strings_utf8(Window win, Atom prop, const gchar **strs);
+
+void obt_prop_erase(Window win, Atom prop);
+
+void obt_prop_message(gint screen, Window about, Atom messagetype,
+                      glong data0, glong data1, glong data2, glong data3,
+                      glong data4, glong mask);
+void obt_prop_message_to(Window to, Window about, Atom messagetype,
+                         glong data0, glong data1, glong data2, glong data3,
+                         glong data4, glong mask);
+
+#define OBT_PROP_ATOM(prop) obt_prop_atom(OBT_PROP_##prop)
+
+#define OBT_PROP_GET32(win, prop, type, ret) \
+    (obt_prop_get32(win, OBT_PROP_ATOM(prop), OBT_PROP_ATOM(type), ret))
+#define OBT_PROP_GETA32(win, prop, type, ret, nret) \
+    (obt_prop_get_array32(win, OBT_PROP_ATOM(prop), OBT_PROP_ATOM(type), \
+                          ret, nret))
+#define OBT_PROP_GETS(win, prop, type, ret) \
+    (obt_prop_get_string_##type(win, OBT_PROP_ATOM(prop), ret))
+#define OBT_PROP_GETSS(win, prop, type, ret) \
+    (obt_prop_get_strings_##type(win, OBT_PROP_ATOM(prop), ret))
+
+#define OBT_PROP_SET32(win, prop, type, val) \
+    (obt_prop_set32(win, OBT_PROP_ATOM(prop), OBT_PROP_ATOM(type), val))
+#define OBT_PROP_SETA32(win, prop, type, val, num) \
+    (obt_prop_set_array32(win, OBT_PROP_ATOM(prop), OBT_PROP_ATOM(type), \
+                          val, num))
+#define OBT_PROP_SETS(win, prop, type, val) \
+    (obt_prop_set_string_##type(win, OBT_PROP_ATOM(prop), val))
+#define OBT_PROP_SETSS(win, prop, type, strs) \
+    (obt_prop_set_strings_##type(win, OBT_PROP_ATOM(prop), strs))
+
+#define OBT_PROP_ERASE(win, prop) (obt_prop_erase(win, OBT_PROP_ATOM(prop)))
+
+#define OBT_PROP_MSG(screen, about, msgtype, data0, data1, data2, data3, \
+                     data4) \
+    (obt_prop_message(screen, about, OBT_PROP_ATOM(msgtype), \
+                      data0, data1, data2, data3, data4, \
+                      SubstructureNotifyMask | SubstructureRedirectMask))
+
+#define OBT_PROP_MSG_TO(to, about, msgtype, data0, data1, data2, data3, \
+                        data4, mask) \
+    (obt_prop_message_to(to, about, OBT_PROP_ATOM(msgtype), \
+                         data0, data1, data2, data3, data4, mask))
+
+G_END_DECLS
+
+#endif /* __obt_prop_h */
diff --git a/obt/util.h b/obt/util.h
new file mode 100644 (file)
index 0000000..ff44d36
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/util.h for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_util_h
+#define __obt_util_h
+
+#include <glib.h>
+
+#ifdef HAVE_STRING_H
+#  include <string.h> /* for memset() */
+#endif
+
+G_BEGIN_DECLS
+
+/* Util funcs */
+#define obt_free g_free
+#define obt_free0(p, type, num) memset((p), 0, sizeof(type) * (num)), g_free(p)
+
+G_END_DECLS
+
+
+#endif /*__obt_util_h*/
diff --git a/obt/version.h.in b/obt/version.h.in
new file mode 100644 (file)
index 0000000..8adfcf8
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef obt__version_h
+#define obt__version_h
+
+#define OBT_MAJOR_VERSION @OBT_MAJOR_VERSION@
+#define OBT_MINOR_VERSION @OBT_MINOR_VERSION@
+#define OBT_MICRO_VERSION @OBT_MICRO_VERSION@
+#define OBT_VERSION OBT_MAJOR_VERSION.OBT_MINOR_VERSION.OBT_MICRO_VERSION
+
+#define OBT_CHECK_VERSION(major,minor,micro) \
+    (OBT_MAJOR_VERSION > (major) || \
+     (OBT_MAJOR_VERSION == (major) && OBT_MINOR_VERSION > (minor)) || \
+     (OBT_MAJOR_VERSION == (major) && OBT_MINOR_VERSION == (minor) && \
+      OBT_MICRO_VERSION >= (micro)))
+
+#endif
diff --git a/obt/xevent.c b/obt/xevent.c
new file mode 100644 (file)
index 0000000..9732c8f
--- /dev/null
@@ -0,0 +1,134 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/xevent.c for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/xevent.h"
+#include "obt/mainloop.h"
+#include "obt/util.h"
+
+typedef struct _ObtXEventBinding ObtXEventBinding;
+
+struct _ObtXEventHandler
+{
+    gint ref;
+    ObtMainLoop *loop;
+
+    /* An array of hash tables where the key is the window, and the value is
+       the ObtXEventBinding */
+    GHashTable **bindings;
+    gint num_event_types; /* the length of the bindings array */
+};
+
+struct _ObtXEventBinding
+{
+    Window win;
+    ObtXEventCallback func;
+    gpointer data;
+};
+
+static void xevent_handler(const XEvent *e, gpointer data);
+static guint window_hash(Window *w) { return *w; }
+static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
+
+ObtXEventHandler* xevent_new()
+{
+    ObtXEventHandler *h;
+
+    h = g_new0(ObtXEventHandler, 1);
+    h->ref = 1;
+
+    return h;
+}
+
+void xevent_ref(ObtXEventHandler *h)
+{
+    ++h->ref;
+}
+
+void xevent_unref(ObtXEventHandler *h)
+{
+    if (h && --h->ref == 0) {
+        gint i;
+
+        if (h->loop)
+            obt_main_loop_x_remove(h->loop, xevent_handler);
+        for (i = 0; i < h->num_event_types; ++i)
+            g_hash_table_destroy(h->bindings[i]);
+        g_free(h->bindings);
+
+        obt_free0(h, ObtXEventHandler, 1);
+    }
+}
+
+void xevent_register(ObtXEventHandler *h, ObtMainLoop *loop)
+{
+    h->loop = loop;
+    obt_main_loop_x_add(loop, xevent_handler, h, NULL);
+}
+
+void xevent_set_handler(ObtXEventHandler *h, gint type, Window win,
+                        ObtXEventCallback func, gpointer data)
+{
+    ObtXEventBinding *b;
+
+    g_assert(func);
+
+    /* make sure we have a spot for the event */
+    if (type + 1 < h->num_event_types) {
+        gint i;
+        h->bindings = g_renew(GHashTable*, h->bindings, type + 1);
+        for (i = h->num_event_types; i < type + 1; ++i)
+            h->bindings[i] = g_hash_table_new_full((GHashFunc)window_hash,
+                                                   (GEqualFunc)window_comp,
+                                                   NULL, g_free);
+        h->num_event_types = type + 1;
+    }
+
+    b = g_new(ObtXEventBinding, 1);
+    b->win = win;
+    b->func = func;
+    b->data = data;
+    g_hash_table_replace(h->bindings[type], &b->win, b);
+}
+
+void xevent_remove_handler(ObtXEventHandler *h, gint type, Window win)
+{
+    g_assert(type < h->num_event_types);
+    g_assert(win);
+
+    g_hash_table_remove(h->bindings[type], &win);
+}
+
+static void xevent_handler(const XEvent *e, gpointer data)
+{
+    ObtXEventHandler *h;
+    ObtXEventBinding *b;
+
+    h = data;
+
+    if (e->type < h->num_event_types) {
+        const gint all = OBT_XEVENT_ALL_WINDOWS;
+        /* run the all_windows handler first */
+        b = g_hash_table_lookup(h->bindings[e->xany.type], &all);
+        if (b) b->func(e, b->data);
+        /* then run the per-window handler */
+        b = g_hash_table_lookup(h->bindings[e->xany.type], &e->xany.window);
+        if (b) b->func(e, b->data);
+    }
+    else
+        g_message("Unhandled X Event type %d", e->xany.type);
+}
diff --git a/obt/xevent.h b/obt/xevent.h
new file mode 100644 (file)
index 0000000..a93a1a6
--- /dev/null
@@ -0,0 +1,48 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/xevent.h for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_xevent_h
+#define __obt_xevent_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+struct _ObtMainLoop;
+
+typedef struct _ObtXEventHandler ObtXEventHandler;
+
+typedef void (*ObtXEventCallback) (const XEvent *e, gpointer data);
+
+ObtXEventHandler* xevent_new();
+void              xevent_ref(ObtXEventHandler *h);
+void              xevent_unref(ObtXEventHandler *h);
+
+void              xevent_register(ObtXEventHandler *h,
+                                  struct _ObtMainLoop *loop);
+
+#define OBT_XEVENT_ALL_WINDOWS None
+
+void xevent_set_handler(ObtXEventHandler *h, gint type, Window win,
+                        ObtXEventCallback func, gpointer data);
+void xevent_remove_handler(ObtXEventHandler *h, gint type, Window win);
+
+G_END_DECLS
+
+#endif /*__obt_xevent_h*/
index 32b3d27..5bd7013 100644 (file)
@@ -159,23 +159,21 @@ ObActionsAct* actions_parse_string(const gchar *name)
 
     if ((act = actions_build_act_from_string(name)))
         if (act->def->setup)
-            act->options = act->def->setup(NULL, NULL, NULL);
+            act->options = act->def->setup(NULL);
 
     return act;
 }
 
-ObActionsAct* actions_parse(ObParseInst *i,
-                            xmlDocPtr doc,
-                            xmlNodePtr node)
+ObActionsAct* actions_parse(xmlNodePtr node)
 {
     gchar *name;
     ObActionsAct *act = NULL;
 
-    if (parse_attr_string("name", node, &name)) {
+    if (obt_parse_attr_string(node, "name", &name)) {
         if ((act = actions_build_act_from_string(name)))
             /* there is more stuff to parse here */
             if (act->def->setup)
-                act->options = act->def->setup(i, doc, node->xmlChildrenNode);
+                act->options = act->def->setup(node->children);
 
         g_free(name);
     }
index 6db6f8d..7975d4e 100644 (file)
@@ -18,7 +18,8 @@
 
 #include "misc.h"
 #include "frame.h"
-#include "parser/parse.h"
+#include "obt/parse.h"
+
 #include <glib.h>
 #include <X11/Xlib.h>
 
@@ -30,8 +31,7 @@ typedef struct _ObActionsGlobalData   ObActionsGlobalData;
 typedef struct _ObActionsClientData   ObActionsClientData;
 typedef struct _ObActionsSelectorData ObActionsSelectorData;
 
-typedef gpointer (*ObActionsDataSetupFunc)(ObParseInst *i,
-                                           xmlDocPtr doc, xmlNodePtr node);
+typedef gpointer (*ObActionsDataSetupFunc)(xmlNodePtr node);
 typedef void     (*ObActionsDataFreeFunc)(gpointer options);
 typedef gboolean (*ObActionsRunFunc)(ObActionsData *data,
                                      gpointer options);
@@ -64,9 +64,7 @@ gboolean actions_register(const gchar *name,
                           ObActionsInteractiveInputFunc i_input,
                           ObActionsInteractiveCancelFunc i_cancel);
 
-ObActionsAct* actions_parse(ObParseInst *i,
-                            xmlDocPtr doc,
-                            xmlNodePtr node);
+ObActionsAct* actions_parse(xmlNodePtr node);
 ObActionsAct* actions_parse_string(const gchar *name);
 
 gboolean actions_act_is_interactive(ObActionsAct *act);
index 8125b9b..b6e621a 100644 (file)
@@ -7,36 +7,28 @@ typedef struct {
     gboolean add;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_add_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_remove_func(ObParseInst *i,
-                                  xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_add_func(xmlNodePtr node);
+static gpointer setup_remove_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_addremovedesktop_startup(void)
 {
-    actions_register("AddDesktop",
-                     setup_add_func,
-                     free_func,
-                     run_func,
+    actions_register("AddDesktop", setup_add_func, g_free, run_func,
                      NULL, NULL);
-    actions_register("RemoveDesktop",
-                     setup_remove_func,
-                     free_func,
-                     run_func,
+    actions_register("RemoveDesktop", setup_remove_func, g_free, run_func,
                      NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("where", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "where"))) {
+        gchar *s = obt_parse_node_string(n);
         if (!g_ascii_strcasecmp(s, "last"))
             o->current = FALSE;
         else if (!g_ascii_strcasecmp(s, "current"))
@@ -47,28 +39,20 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static gpointer setup_add_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_add_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->add = TRUE;
     return o;
 }
 
-static gpointer setup_remove_func(ObParseInst *i,
-                                  xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_remove_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->add = FALSE;
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
index cb341af..44d87cf 100644 (file)
@@ -8,23 +8,21 @@
 
 typedef struct {
     gboolean linear;
-    gboolean dialog;
     gboolean dock_windows;
     gboolean desktop_windows;
     gboolean all_desktops;
     gboolean forward;
     gboolean bar;
     gboolean raise;
+    ObFocusCyclePopupMode dialog_mode;
     GSList *actions;
 } Options;
 
 static gboolean cycling = FALSE;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_forward_func(ObParseInst *i, xmlDocPtr doc,
-                                   xmlNodePtr node);
-static gpointer setup_backward_func(ObParseInst *i, xmlDocPtr doc,
-                                    xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_forward_func(xmlNodePtr node);
+static gpointer setup_backward_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 static gboolean i_input_func(guint initial_state,
@@ -43,38 +41,42 @@ void action_cyclewindows_startup(void)
                      run_func, i_input_func, i_cancel_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
-    o->dialog = TRUE;
     o->bar = TRUE;
-
-    if ((n = parse_find_node("linear", node)))
-        o->linear = parse_bool(doc, n);
-    if ((n = parse_find_node("dialog", node)))
-        o->dialog = parse_bool(doc, n);
-    if ((n = parse_find_node("bar", node)))
-        o->bar = parse_bool(doc, n);
-    if ((n = parse_find_node("raise", node)))
-        o->raise = parse_bool(doc, n);
-    if ((n = parse_find_node("panels", node)))
-        o->dock_windows = parse_bool(doc, n);
-    if ((n = parse_find_node("desktop", node)))
-        o->desktop_windows = parse_bool(doc, n);
-    if ((n = parse_find_node("allDesktops", node)))
-        o->all_desktops = parse_bool(doc, n);
-
-    if ((n = parse_find_node("finalactions", node))) {
+    o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_LIST;
+
+    if ((n = obt_parse_find_node(node, "linear")))
+        o->linear = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "dialog"))) {
+        if (obt_parse_node_contains(n, "none"))
+            o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_NONE;
+        else if (obt_parse_node_contains(n, "icons"))
+            o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_ICONS;
+    }
+    if ((n = obt_parse_find_node(node, "bar")))
+        o->bar = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "raise")))
+        o->raise = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "panels")))
+        o->dock_windows = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "desktop")))
+        o->desktop_windows = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "allDesktops")))
+        o->all_desktops = obt_parse_node_bool(n);
+
+    if ((n = obt_parse_find_node(node, "finalactions"))) {
         xmlNodePtr m;
 
-        m = parse_find_node("action", n->xmlChildrenNode);
+        m = obt_parse_find_node(n->children, "action");
         while (m) {
-            ObActionsAct *action = actions_parse(i, doc, m);
+            ObActionsAct *action = actions_parse(m);
             if (action) o->actions = g_slist_prepend(o->actions, action);
-            m = parse_find_node("action", m->next);
+            m = obt_parse_find_node(m->next, "action");
         }
     }
     else {
@@ -89,18 +91,16 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static gpointer setup_forward_func(ObParseInst *i, xmlDocPtr doc,
-                                   xmlNodePtr node)
+static gpointer setup_forward_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->forward = TRUE;
     return o;
 }
 
-static gpointer setup_backward_func(ObParseInst *i, xmlDocPtr doc,
-                                    xmlNodePtr node)
+static gpointer setup_backward_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->forward = FALSE;
     return o;
 }
@@ -129,7 +129,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
                      o->linear,
                      TRUE,
                      o->bar,
-                     o->dialog,
+                     o->dialog_mode,
                      FALSE, FALSE);
     cycling = TRUE;
 
@@ -189,7 +189,7 @@ static void end_cycle(gboolean cancel, guint state, Options *o)
                      o->linear,
                      TRUE,
                      o->bar,
-                     o->dialog,
+                     o->dialog_mode,
                      TRUE, cancel);
     cycling = FALSE;
 
index f71b685..99e838a 100644 (file)
@@ -5,39 +5,32 @@ typedef struct {
     gchar   *str;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_debug_startup(void)
 {
-    actions_register("Debug",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Debug", setup_func, free_func, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("string", node)))
-        o->str = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "string")))
+        o->str = obt_parse_node_string(n);
     return o;
 }
 
 static void free_func(gpointer options)
 {
     Options *o = options;
-
-    if (o) {
-        g_free(o->str);
-        g_free(o);
-    }
+    g_free(o->str);
+    g_free(o);
 }
 
 /* Always return FALSE because its not interactive */
index d939ed5..37268bb 100644 (file)
@@ -26,10 +26,8 @@ typedef struct {
     gboolean follow;
 } Options;
 
-static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node);
-static gpointer setup_send_func(ObParseInst *i, xmlDocPtr doc,
-                                xmlNodePtr node);
+static gpointer setup_go_func(xmlNodePtr node);
+static gpointer setup_send_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_desktop_startup(void)
@@ -40,8 +38,7 @@ void action_desktop_startup(void)
                      NULL, NULL);
 }
 
-static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node)
+static gpointer setup_go_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -53,8 +50,8 @@ static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
     /* wrap by default - it's handy! */
     o->rel.wrap = TRUE;
 
-    if ((n = parse_find_node("to", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "to"))) {
+        gchar *s = obt_parse_node_string(n);
         if (!g_ascii_strcasecmp(s, "last"))
             o->type = LAST;
         else if (!g_ascii_strcasecmp(s, "next")) {
@@ -89,29 +86,28 @@ static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
         }
         else {
             o->type = ABSOLUTE;
-            o->abs.desktop = parse_int(doc, n) - 1;
+            o->abs.desktop = obt_parse_node_int(n) - 1;
         }
         g_free(s);
     }
 
-    if ((n = parse_find_node("wrap", node)))
-        o->rel.wrap = parse_bool(doc, n);
+    if ((n = obt_parse_find_node(node, "wrap")))
+        o->rel.wrap = obt_parse_node_bool(n);
 
     return o;
 }
 
-static gpointer setup_send_func(ObParseInst *i, xmlDocPtr doc,
-                                xmlNodePtr node)
+static gpointer setup_send_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
-    o = setup_go_func(i, doc, node);
+    o = setup_go_func(node);
     o->send = TRUE;
     o->follow = TRUE;
 
-    if ((n = parse_find_node("follow", node)))
-        o->follow = parse_bool(doc, n);
+    if ((n = obt_parse_find_node(node, "follow")))
+        o->follow = obt_parse_node_bool(n);
 
     return o;
 }
index 55c9e60..c5c25c1 100644 (file)
@@ -20,11 +20,9 @@ typedef struct {
 
 static gboolean cycling = FALSE;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_cycle_func(ObParseInst *i, xmlDocPtr doc,
-                                 xmlNodePtr node);
-static gpointer setup_target_func(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_cycle_func(xmlNodePtr node);
+static gpointer setup_target_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 static gboolean i_input_func(guint initial_state,
@@ -43,7 +41,7 @@ void action_directionalwindows_startup(void)
                      run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -52,18 +50,18 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o->dialog = TRUE;
     o->bar = TRUE;
 
-    if ((n = parse_find_node("dialog", node)))
-        o->dialog = parse_bool(doc, n);
-    if ((n = parse_find_node("bar", node)))
-        o->bar = parse_bool(doc, n);
-    if ((n = parse_find_node("raise", node)))
-        o->raise = parse_bool(doc, n);
-    if ((n = parse_find_node("panels", node)))
-        o->dock_windows = parse_bool(doc, n);
-    if ((n = parse_find_node("desktop", node)))
-        o->desktop_windows = parse_bool(doc, n);
-    if ((n = parse_find_node("direction", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "dialog")))
+        o->dialog = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "bar")))
+        o->bar = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "raise")))
+        o->raise = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "panels")))
+        o->dock_windows = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "desktop")))
+        o->desktop_windows = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "direction"))) {
+        gchar *s = obt_parse_node_string(n);
         if (!g_ascii_strcasecmp(s, "north") ||
             !g_ascii_strcasecmp(s, "up"))
             o->direction = OB_DIRECTION_NORTH;
@@ -87,14 +85,14 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
         g_free(s);
     }
 
-    if ((n = parse_find_node("finalactions", node))) {
+    if ((n = obt_parse_find_node(node, "finalactions"))) {
         xmlNodePtr m;
 
-        m = parse_find_node("action", n->xmlChildrenNode);
+        m = obt_parse_find_node(n->children, "action");
         while (m) {
-            ObActionsAct *action = actions_parse(i, doc, m);
+            ObActionsAct *action = actions_parse(m);
             if (action) o->actions = g_slist_prepend(o->actions, action);
-            m = parse_find_node("action", m->next);
+            m = obt_parse_find_node(m->next, "action");
         }
     }
     else {
@@ -109,18 +107,16 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static gpointer setup_cycle_func(ObParseInst *i, xmlDocPtr doc,
-                                 xmlNodePtr node)
+static gpointer setup_cycle_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->interactive = TRUE;
     return o;
 }
 
-static gpointer setup_target_func(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node)
+static gpointer setup_target_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->interactive = FALSE;
     return o;
 }
index a857b1b..c534ba8 100644 (file)
@@ -2,6 +2,7 @@
 #include "openbox/event.h"
 #include "openbox/startupnotify.h"
 #include "openbox/screen.h"
+#include "obt/paths.h"
 #include "gettext.h"
 
 #ifdef HAVE_STDLIB_H
@@ -16,7 +17,7 @@ typedef struct {
     gchar   *sn_wmclass;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 /*
@@ -29,38 +30,34 @@ static void     i_cancel_func(gpointer options);
 
 void action_execute_startup(void)
 {
-    actions_register("Execute",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Execute", setup_func, free_func, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("command", node)) ||
-        (n = parse_find_node("execute", node)))
+    if ((n = obt_parse_find_node(node, "command")) ||
+        (n = obt_parse_find_node(node, "execute")))
     {
-        gchar *s = parse_string(doc, n);
-        o->cmd = parse_expand_tilde(s);
+        gchar *s = obt_parse_node_string(n);
+        o->cmd = obt_paths_expand_tilde(s);
         g_free(s);
     }
 
-    if ((n = parse_find_node("startupnotify", node))) {
+    if ((n = obt_parse_find_node(node, "startupnotify"))) {
         xmlNodePtr m;
-        if ((m = parse_find_node("enabled", n->xmlChildrenNode)))
-            o->sn = parse_bool(doc, m);
-        if ((m = parse_find_node("name", n->xmlChildrenNode)))
-            o->sn_name = parse_string(doc, m);
-        if ((m = parse_find_node("icon", n->xmlChildrenNode)))
-            o->sn_icon = parse_string(doc, m);
-        if ((m = parse_find_node("wmclass", n->xmlChildrenNode)))
-            o->sn_wmclass = parse_string(doc, m);
+        if ((m = obt_parse_find_node(n->children, "enabled")))
+            o->sn = obt_parse_node_bool(m);
+        if ((m = obt_parse_find_node(n->children, "name")))
+            o->sn_name = obt_parse_node_string(m);
+        if ((m = obt_parse_find_node(n->children, "icon")))
+            o->sn_icon = obt_parse_node_string(m);
+        if ((m = obt_parse_find_node(n->children, "wmclass")))
+            o->sn_wmclass = obt_parse_node_string(m);
     }
     return o;
 }
index 0ef9d26..4d0f220 100644 (file)
@@ -7,38 +7,26 @@ typedef struct {
     gboolean here;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_focus_startup(void)
 {
-    actions_register("Focus",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Focus", setup_func, g_free, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("here", node)))
-        o->here = parse_bool(doc, n);
+    if ((n = obt_parse_find_node(node, "here")))
+        o->here = obt_parse_node_bool(n);
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
index 69b8ef7..a37e3a2 100644 (file)
@@ -7,31 +7,32 @@
 
 typedef struct {
     ObDirection dir;
+    gboolean shrink;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_shrink_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_growtoedge_startup(void)
 {
-    actions_register("GrowToEdge",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("GrowToEdge", setup_func,
+                     g_free, run_func, NULL, NULL);
+    actions_register("ShrinkToEdge", setup_shrink_func,
+                     g_free, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
     o->dir = OB_DIRECTION_NORTH;
+    o->shrink = FALSE;
 
-    if ((n = parse_find_node("direction", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "direction"))) {
+        gchar *s = obt_parse_node_string(n);
         if (!g_ascii_strcasecmp(s, "north") ||
             !g_ascii_strcasecmp(s, "up"))
             o->dir = OB_DIRECTION_NORTH;
@@ -50,11 +51,14 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static void free_func(gpointer options)
+static gpointer setup_shrink_func(xmlNodePtr node)
 {
-    Options *o = options;
+    Options *o;
 
-    g_free(o);
+    o = setup_func(node);
+    o->shrink = TRUE;
+
+    return o;
 }
 
 static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h)
@@ -98,11 +102,13 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         return FALSE;
     }
 
-    /* try grow */
-    client_find_resize_directional(data->client, o->dir, TRUE,
-                                   &x, &y, &w, &h);
-    if (do_grow(data, x, y, w, h))
-        return FALSE;
+    if (!o->shrink) {
+        /* try grow */
+        client_find_resize_directional(data->client, o->dir, TRUE,
+                                       &x, &y, &w, &h);
+        if (do_grow(data, x, y, w, h))
+            return FALSE;
+    }
 
     /* we couldn't grow, so try shrink! */
     opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
index a35c61f..63a7fbc 100644 (file)
@@ -23,81 +23,77 @@ typedef struct {
     GSList *elseacts;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_if_startup(void)
 {
-    actions_register("If",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("If", setup_func, free_func, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("shaded", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_parse_find_node(node, "shaded"))) {
+        if (obt_parse_node_bool(n))
             o->shaded_on = TRUE;
         else
             o->shaded_off = TRUE;
     }
-    if ((n = parse_find_node("maximized", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_parse_find_node(node, "maximized"))) {
+        if (obt_parse_node_bool(n))
             o->maxfull_on = TRUE;
         else
             o->maxfull_off = TRUE;
     }
-    if ((n = parse_find_node("maximizedhorizontal", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_parse_find_node(node, "maximizedhorizontal"))) {
+        if (obt_parse_node_bool(n))
             o->maxhorz_on = TRUE;
         else
             o->maxhorz_off = TRUE;
     }
-    if ((n = parse_find_node("maximizedvertical", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_parse_find_node(node, "maximizedvertical"))) {
+        if (obt_parse_node_bool(n))
             o->maxvert_on = TRUE;
         else
             o->maxvert_off = TRUE;
     }
-    if ((n = parse_find_node("iconified", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_parse_find_node(node, "iconified"))) {
+        if (obt_parse_node_bool(n))
             o->iconic_on = TRUE;
         else
             o->iconic_off = TRUE;
     }
-    if ((n = parse_find_node("focused", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_parse_find_node(node, "focused"))) {
+        if (obt_parse_node_bool(n))
             o->focused = TRUE;
         else
             o->unfocused = TRUE;
     }
 
-    if ((n = parse_find_node("then", node))) {
+    if ((n = obt_parse_find_node(node, "then"))) {
         xmlNodePtr m;
 
-        m = parse_find_node("action", n->xmlChildrenNode);
+        m = obt_parse_find_node(n->children, "action");
         while (m) {
-            ObActionsAct *action = actions_parse(i, doc, m);
+            ObActionsAct *action = actions_parse(m);
             if (action) o->thenacts = g_slist_prepend(o->thenacts, action);
-            m = parse_find_node("action", m->next);
+            m = obt_parse_find_node(m->next, "action");
         }
     }
-    if ((n = parse_find_node("else", node))) {
+    if ((n = obt_parse_find_node(node, "else"))) {
         xmlNodePtr m;
 
-        m = parse_find_node("action", n->xmlChildrenNode);
+        m = obt_parse_find_node(n->children, "action");
         while (m) {
-            ObActionsAct *action = actions_parse(i, doc, m);
+            ObActionsAct *action = actions_parse(m);
             if (action) o->elseacts = g_slist_prepend(o->elseacts, action);
-            m = parse_find_node("action", m->next);
+            m = obt_parse_find_node(m->next, "action");
         }
     }
 
@@ -108,6 +104,15 @@ static void free_func(gpointer options)
 {
     Options *o = options;
 
+    while (o->thenacts) {
+        actions_act_unref(o->thenacts->data);
+        o->thenacts = g_slist_delete_link(o->thenacts, o->thenacts);
+    }
+    while (o->elseacts) {
+        actions_act_unref(o->elseacts->data);
+        o->elseacts = g_slist_delete_link(o->elseacts, o->elseacts);
+    }
+
     g_free(o);
 }
 
index 92fa480..bbfda57 100644 (file)
@@ -6,11 +6,9 @@ typedef struct {
     gboolean toggle;
 } Options;
 
-static gpointer setup_func_top(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_func_bottom(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node);
-static gpointer setup_func_send(ObParseInst *i, xmlDocPtr doc,
-                                xmlNodePtr node);
+static gpointer setup_func_top(xmlNodePtr node);
+static gpointer setup_func_bottom(xmlNodePtr node);
+static gpointer setup_func_send(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_layer_startup(void)
@@ -23,7 +21,7 @@ void action_layer_startup(void)
                      run_func, NULL, NULL);
 }
 
-static gpointer setup_func_top(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func_top(xmlNodePtr node)
 {
     Options *o = g_new0(Options, 1);
     o->layer = 1;
@@ -31,8 +29,7 @@ static gpointer setup_func_top(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static gpointer setup_func_bottom(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node)
+static gpointer setup_func_bottom(xmlNodePtr node)
 {
     Options *o = g_new0(Options, 1);
     o->layer = -1;
@@ -40,16 +37,15 @@ static gpointer setup_func_bottom(ObParseInst *i, xmlDocPtr doc,
     return o;
 }
 
-static gpointer setup_func_send(ObParseInst *i, xmlDocPtr doc,
-                                xmlNodePtr node)
+static gpointer setup_func_send(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("layer", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "layer"))) {
+        gchar *s = obt_parse_node_string(n);
         if (!g_ascii_strcasecmp(s, "above") ||
             !g_ascii_strcasecmp(s, "top"))
             o->layer = 1;
index bb6f470..45e8b38 100644 (file)
@@ -12,7 +12,7 @@ typedef struct {
     MaxDirection dir;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func_on(ObActionsData *data, gpointer options);
 static gboolean run_func_off(ObActionsData *data, gpointer options);
 static gboolean run_func_toggle(ObActionsData *data, gpointer options);
@@ -27,7 +27,7 @@ void action_maximize_startup(void)
                      NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -35,8 +35,8 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o = g_new0(Options, 1);
     o->dir = BOTH;
 
-    if ((n = parse_find_node("direction", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "direction"))) {
+        gchar *s = obt_parse_node_string(n);
         if (!g_ascii_strcasecmp(s, "vertical") ||
             !g_ascii_strcasecmp(s, "vert"))
             o->dir = VERT;
index 1a8ea20..ddd3f59 100644 (file)
@@ -1,6 +1,6 @@
 #include "openbox/actions.h"
-#include "openbox/prop.h"
 #include "openbox/moveresize.h"
+#include "obt/prop.h"
 
 static gboolean run_func(ObActionsData *data, gpointer options);
 
@@ -19,8 +19,8 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         guint32 corner;
 
         corner = data->button != 0 ?
-            prop_atoms.net_wm_moveresize_move :
-            prop_atoms.net_wm_moveresize_move_keyboard;
+            OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE) :
+            OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD);
 
         moveresize_start(data->client, data->x, data->y, data->button, corner);
     }
index 1d1189c..ccdff54 100644 (file)
@@ -9,41 +9,29 @@ typedef struct {
     gint y;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_moverelative_startup(void)
 {
-    actions_register("MoveRelative",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("MoveRelative", setup_func, g_free, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("x", node)))
-        o->x = parse_int(doc, n);
-    if ((n = parse_find_node("y", node)))
-        o->y = parse_int(doc, n);
+    if ((n = obt_parse_find_node(node, "x")))
+        o->x = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "y")))
+        o->y = obt_parse_node_int(n);
 
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
index 860bf73..d355daf 100644 (file)
@@ -21,23 +21,18 @@ typedef struct {
     gint monitor;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_moveresizeto_startup(void)
 {
-    actions_register("MoveResizeTo",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("MoveResizeTo", setup_func, g_free, run_func, NULL, NULL);
 }
 
-static void parse_coord(xmlDocPtr doc, xmlNodePtr n, gint *pos,
+static void parse_coord(xmlNodePtr n, gint *pos,
                         gboolean *opposite, gboolean *center)
 {
-    gchar *s = parse_string(doc, n);
+    gchar *s = obt_parse_node_string(n);
     if (g_ascii_strcasecmp(s, "current") != 0) {
         if (!g_ascii_strcasecmp(s, "center"))
             *center = TRUE;
@@ -53,7 +48,7 @@ static void parse_coord(xmlDocPtr doc, xmlNodePtr n, gint *pos,
     g_free(s);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -65,32 +60,32 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o->h = G_MININT;
     o->monitor = CURRENT_MONITOR;
 
-    if ((n = parse_find_node("x", node)))
-        parse_coord(doc, n, &o->x, &o->xopposite, &o->xcenter);
+    if ((n = obt_parse_find_node(node, "x")))
+        parse_coord(n, &o->x, &o->xopposite, &o->xcenter);
 
-    if ((n = parse_find_node("y", node)))
-        parse_coord(doc, n, &o->y, &o->yopposite, &o->ycenter);
+    if ((n = obt_parse_find_node(node, "y")))
+        parse_coord(n, &o->y, &o->yopposite, &o->ycenter);
 
-    if ((n = parse_find_node("width", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "width"))) {
+        gchar *s = obt_parse_node_string(n);
         if (g_ascii_strcasecmp(s, "current") != 0)
-            o->w = parse_int(doc, n);
+            o->w = obt_parse_node_int(n);
         g_free(s);
     }
-    if ((n = parse_find_node("height", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "height"))) {
+        gchar *s = obt_parse_node_string(n);
         if (g_ascii_strcasecmp(s, "current") != 0)
-            o->h = parse_int(doc, n);
+            o->h = obt_parse_node_int(n);
         g_free(s);
     }
 
-    if ((n = parse_find_node("monitor", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "monitor"))) {
+        gchar *s = obt_parse_node_string(n);
         if (g_ascii_strcasecmp(s, "current") != 0) {
             if (!g_ascii_strcasecmp(s, "all"))
                 o->monitor = ALL_MONITORS;
             else
-                o->monitor = parse_int(doc, n) - 1;
+                o->monitor = obt_parse_node_int(n) - 1;
         }
         g_free(s);
     }
@@ -98,13 +93,6 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
index 5941bde..f360ddd 100644 (file)
@@ -9,20 +9,15 @@ typedef struct {
     ObDirection dir;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_movetoedge_startup(void)
 {
-    actions_register("MoveToEdge",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("MoveToEdge", setup_func, g_free, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -30,8 +25,8 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o = g_new0(Options, 1);
     o->dir = OB_DIRECTION_NORTH;
 
-    if ((n = parse_find_node("direction", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "direction"))) {
+        gchar *s = obt_parse_node_string(n);
         if (!g_ascii_strcasecmp(s, "north") ||
             !g_ascii_strcasecmp(s, "up"))
             o->dir = OB_DIRECTION_NORTH;
@@ -50,13 +45,6 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
index 3714e38..47f45f5 100644 (file)
@@ -1,16 +1,15 @@
 #include "openbox/actions.h"
-#include "openbox/prop.h"
 #include "openbox/moveresize.h"
 #include "openbox/client.h"
 #include "openbox/frame.h"
+#include "obt/prop.h"
 
 typedef struct {
     gboolean corner_specified;
     guint32 corner;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
@@ -18,40 +17,36 @@ static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
 
 void action_resize_startup(void)
 {
-    actions_register("Resize",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Resize", setup_func, g_free, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("edge", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "edge"))) {
+        gchar *s = obt_parse_node_string(n);
 
         o->corner_specified = TRUE;
         if (!g_ascii_strcasecmp(s, "top"))
-            o->corner = prop_atoms.net_wm_moveresize_size_top;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP);
         else if (!g_ascii_strcasecmp(s, "bottom"))
-            o->corner = prop_atoms.net_wm_moveresize_size_bottom;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM);
         else if (!g_ascii_strcasecmp(s, "left"))
-            o->corner = prop_atoms.net_wm_moveresize_size_left;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
         else if (!g_ascii_strcasecmp(s, "right"))
-            o->corner = prop_atoms.net_wm_moveresize_size_right;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
         else if (!g_ascii_strcasecmp(s, "topleft"))
-            o->corner = prop_atoms.net_wm_moveresize_size_topleft;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT);
         else if (!g_ascii_strcasecmp(s, "topright"))
-            o->corner = prop_atoms.net_wm_moveresize_size_topright;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
         else if (!g_ascii_strcasecmp(s, "bottomleft"))
-            o->corner = prop_atoms.net_wm_moveresize_size_bottomleft;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
         else if (!g_ascii_strcasecmp(s, "bottomright"))
-            o->corner = prop_atoms.net_wm_moveresize_size_bottomright;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
         else
             o->corner_specified = FALSE;
 
@@ -60,13 +55,6 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
@@ -77,7 +65,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         guint32 corner;
 
         if (!data->button)
-            corner = prop_atoms.net_wm_moveresize_size_keyboard;
+            corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD);
         else if (o->corner_specified)
             corner = o->corner; /* it was specified in the binding */
         else
@@ -163,30 +151,30 @@ static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
     if (shaded) {
         /* for shaded windows, you can only resize west/east and move */
         if (b)
-            return prop_atoms.net_wm_moveresize_size_left;
+            return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
         if (c)
-            return prop_atoms.net_wm_moveresize_size_right;
-        return prop_atoms.net_wm_moveresize_move;
+            return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE);
     }
 
     if (y < A && y >= C)
-        return prop_atoms.net_wm_moveresize_size_topleft;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT);
     else if (y >= A && y >= B && a)
-        return prop_atoms.net_wm_moveresize_size_top;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP);
     else if (y < B && y >= D)
-        return prop_atoms.net_wm_moveresize_size_topright;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
     else if (y < C && y >= E && b)
-        return prop_atoms.net_wm_moveresize_size_left;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
     else if (y < D && y >= F && c)
-        return prop_atoms.net_wm_moveresize_size_right;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
     else if (y < E && y >= G)
-        return prop_atoms.net_wm_moveresize_size_bottomleft;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
     else if (y < G && y < H && d)
-        return prop_atoms.net_wm_moveresize_size_bottom;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM);
     else if (y >= H && y < F)
-        return prop_atoms.net_wm_moveresize_size_bottomright;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
     else
-        return prop_atoms.net_wm_moveresize_move;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE);
 
 #undef X
 #undef A
index f705c29..5742e1f 100644 (file)
@@ -11,47 +11,36 @@ typedef struct {
     gint bottom;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_resizerelative_startup(void)
 {
-    actions_register("ResizeRelative",
-                     setup_func,
-                     free_func,
-                     run_func,
+    actions_register("ResizeRelative", setup_func, g_free, run_func,
                      NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("left", node)))
-        o->left = parse_int(doc, n);
-    if ((n = parse_find_node("right", node)))
-        o->right = parse_int(doc, n);
-    if ((n = parse_find_node("top", node)) ||
-        (n = parse_find_node("up", node)))
-        o->top = parse_int(doc, n);
-    if ((n = parse_find_node("bottom", node)) ||
-        (n = parse_find_node("down", node)))
-        o->bottom = parse_int(doc, n);
+    if ((n = obt_parse_find_node(node, "left")))
+        o->left = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "right")))
+        o->right = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "top")) ||
+        (n = obt_parse_find_node(node, "up")))
+        o->top = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "bottom")) ||
+        (n = obt_parse_find_node(node, "down")))
+        o->bottom = obt_parse_node_int(n);
 
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
index 4b52f9d..47f332b 100644 (file)
@@ -1,35 +1,32 @@
 #include "openbox/actions.h"
 #include "openbox/openbox.h"
+#include "obt/paths.h"
 
 typedef struct {
     gchar   *cmd;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_restart_startup(void)
 {
-    actions_register("Restart",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Restart", setup_func, free_func, run_func, NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("command", node)) ||
-        (n = parse_find_node("execute", node)))
+    if ((n = obt_parse_find_node(node, "command")) ||
+        (n = obt_parse_find_node(node, "execute")))
     {
-        gchar *s = parse_string(doc, n);
-        o->cmd = parse_expand_tilde(s);
+        gchar *s = obt_parse_node_string(n);
+        o->cmd = obt_paths_expand_tilde(s);
         g_free(s);
     }
     return o;
@@ -38,11 +35,8 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
 static void free_func(gpointer options)
 {
     Options *o = options;
-
-    if (o) {
-        g_free(o->cmd);
-        g_free(o);
-    }
+    g_free(o->cmd);
+    g_free(o);
 }
 
 /* Always return FALSE because its not interactive */
index c1d53e4..9590bd1 100644 (file)
@@ -6,7 +6,7 @@ typedef struct {
     gchar   *name;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
@@ -16,15 +16,15 @@ void action_showmenu_startup(void)
                      NULL, NULL);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("menu", node)))
-        o->name = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "menu")))
+        o->name = obt_parse_node_string(n);
     return o;
 }
 
index 9fa311c..946e80d 100644 (file)
 #include "debug.h"
 #include "startupnotify.h"
 #include "dock.h"
-#include "xerror.h"
 #include "screen.h"
 #include "moveresize.h"
 #include "ping.h"
 #include "place.h"
-#include "prop.h"
-#include "extensions.h"
 #include "frame.h"
 #include "session.h"
 #include "event.h"
@@ -43,6 +40,8 @@
 #include "mouse.h"
 #include "render/render.h"
 #include "gettext.h"
+#include "obt/display.h"
+#include "obt/prop.h"
 
 #ifdef HAVE_UNISTD_H
 #  include <unistd.h>
@@ -185,8 +184,8 @@ void client_set_list(void)
     } else
         windows = NULL;
 
-    PROP_SETA32(RootWindow(ob_display, ob_screen),
-                net_client_list, window, (gulong*)windows, size);
+    OBT_PROP_SETA32(obt_root(ob_screen), NET_CLIENT_LIST, WINDOW,
+                    (gulong*)windows, size);
 
     if (windows)
         g_free(windows);
@@ -194,97 +193,17 @@ void client_set_list(void)
     stacking_set_list();
 }
 
-void client_manage_all(void)
-{
-    guint i, j, nchild;
-    Window w, *children;
-    XWMHints *wmhints;
-    XWindowAttributes attrib;
-
-    XQueryTree(ob_display, RootWindow(ob_display, ob_screen),
-               &w, &w, &children, &nchild);
-
-    /* remove all icon windows from the list */
-    for (i = 0; i < nchild; i++) {
-        if (children[i] == None) continue;
-        wmhints = XGetWMHints(ob_display, children[i]);
-        if (wmhints) {
-            if ((wmhints->flags & IconWindowHint) &&
-                (wmhints->icon_window != children[i]))
-                for (j = 0; j < nchild; j++)
-                    if (children[j] == wmhints->icon_window) {
-                        children[j] = None;
-                        break;
-                    }
-            XFree(wmhints);
-        }
-    }
-
-    /* manage windows in reverse order from how they were originally mapped.
-       this is an attempt to manage children windows before their parents, so
-       that when the parent is mapped, it can find the child */
-    for (i = 0; i < nchild; ++i) {
-        if (children[i] == None)
-            continue;
-        if (XGetWindowAttributes(ob_display, children[i], &attrib)) {
-            if (attrib.override_redirect) continue;
-
-            if (attrib.map_state != IsUnmapped)
-                client_manage(children[i], NULL);
-        }
-    }
-    XFree(children);
-}
-
 void client_manage(Window window, ObPrompt *prompt)
 {
     ObClient *self;
-    XEvent e;
-    XWindowAttributes attrib;
     XSetWindowAttributes attrib_set;
-    XWMHints *wmhint;
     gboolean activate = FALSE;
     ObAppSettings *settings;
     gboolean transient = FALSE;
     Rect place, *monitor;
     Time launch_time, map_time;
 
-    grab_server(TRUE);
-
-    /* check if it has already been unmapped by the time we started
-       mapping. the grab does a sync so we don't have to here */
-    if (XCheckTypedWindowEvent(ob_display, window, DestroyNotify, &e) ||
-        XCheckTypedWindowEvent(ob_display, window, UnmapNotify, &e))
-    {
-        XPutBackEvent(ob_display, &e);
-
-        ob_debug("Trying to manage unmapped window. Aborting that.\n");
-        grab_server(FALSE);
-        return; /* don't manage it */
-    }
-
-    /* make sure it isn't an override-redirect window */
-    if (!XGetWindowAttributes(ob_display, window, &attrib) ||
-        attrib.override_redirect)
-    {
-        grab_server(FALSE);
-        return; /* don't manage it */
-    }
-
-    /* is the window a docking app */
-    if ((wmhint = XGetWMHints(ob_display, window))) {
-        if ((wmhint->flags & StateHint) &&
-            wmhint->initial_state == WithdrawnState)
-        {
-            dock_add(window, wmhint);
-            grab_server(FALSE);
-            XFree(wmhint);
-            return;
-        }
-        XFree(wmhint);
-    }
-
-    ob_debug("Managing window: 0x%lx\n", window);
+    ob_debug("Managing window: 0x%lx", window);
 
     map_time = event_get_server_time();
 
@@ -293,13 +212,13 @@ void client_manage(Window window, ObPrompt *prompt)
     attrib_set.event_mask = CLIENT_EVENTMASK |
         (prompt ? prompt->event_mask : 0);
     attrib_set.do_not_propagate_mask = CLIENT_NOPROPAGATEMASK;
-    XChangeWindowAttributes(ob_display, window,
+    XChangeWindowAttributes(obt_display, window,
                             CWEventMask|CWDontPropagate, &attrib_set);
 
     /* create the ObClient struct, and populate it from the hints on the
        window */
     self = g_new0(ObClient, 1);
-    self->obwin.type = Window_Client;
+    self->obwin.type = OB_WINDOW_CLASS_CLIENT;
     self->window = window;
     self->prompt = prompt;
 
@@ -311,8 +230,8 @@ void client_manage(Window window, ObPrompt *prompt)
     /* get all the stuff off the window */
     client_get_all(self, TRUE);
 
-    ob_debug("Window type: %d\n", self->type);
-    ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0);
+    ob_debug("Window type: %d", self->type);
+    ob_debug("Window group: 0x%x", self->group?self->group->leader:0);
 
     /* now we have all of the window's information so we can set this up.
        do this before creating the frame, so it can tell that we are still
@@ -323,7 +242,7 @@ void client_manage(Window window, ObPrompt *prompt)
        should be reparented back to root automatically, unless we are managing
        an internal ObPrompt window  */
     if (!self->prompt)
-        XChangeSaveSet(ob_display, window, SetModeInsert);
+        XChangeSaveSet(obt_display, window, SetModeInsert);
 
     /* create the decoration frame for the client window */
     self->frame = frame_new(self);
@@ -368,7 +287,7 @@ void client_manage(Window window, ObPrompt *prompt)
     }
 
     /* remove the client's border */
-    XSetWindowBorderWidth(ob_display, self->window, 0);
+    XSetWindowBorderWidth(obt_display, self->window, 0);
 
     /* adjust the frame to the client's size before showing or placing
        the window */
@@ -381,7 +300,7 @@ void client_manage(Window window, ObPrompt *prompt)
 
     /* figure out placement for the window if the window is new */
     if (ob_state() == OB_STATE_RUNNING) {
-        ob_debug("Positioned: %s @ %d %d\n",
+        ob_debug("Positioned: %s @ %d %d",
                  (!self->positioned ? "no" :
                   (self->positioned == PPosition ? "program specified" :
                    (self->positioned == USPosition ? "user specified" :
@@ -389,7 +308,7 @@ void client_manage(Window window, ObPrompt *prompt)
                      "program + user specified" :
                      "BADNESS !?")))), place.x, place.y);
 
-        ob_debug("Sized: %s @ %d %d\n",
+        ob_debug("Sized: %s @ %d %d",
                  (!self->sized ? "no" :
                   (self->sized == PSize ? "program specified" :
                    (self->sized == USSize ? "user specified" :
@@ -461,7 +380,7 @@ void client_manage(Window window, ObPrompt *prompt)
         place.width = MIN(place.width, a->width);
         place.height = MIN(place.height, a->height);
 
-        ob_debug("setting window size to %dx%d\n", place.width, place.height);
+        ob_debug("setting window size to %dx%d", place.width, place.height);
 
         /* get the size of the client back */
         place.width -= self->frame->size.left + self->frame->size.right;
@@ -471,11 +390,11 @@ void client_manage(Window window, ObPrompt *prompt)
     }
 
     ob_debug("placing window 0x%x at %d, %d with size %d x %d. "
-             "some restrictions may apply\n",
+             "some restrictions may apply",
              self->window, place.x, place.y, place.width, place.height);
     if (self->session)
         ob_debug("  but session requested %d, %d  %d x %d instead, "
-                 "overriding\n",
+                 "overriding",
                  self->session->x, self->session->y,
                  self->session->w, self->session->h);
 
@@ -490,7 +409,7 @@ void client_manage(Window window, ObPrompt *prompt)
     g_free(monitor);
     monitor = NULL;
 
-    ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s\n",
+    ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s",
                   activate ? "yes" : "no");
     if (activate) {
         gboolean raise = FALSE;
@@ -498,7 +417,7 @@ void client_manage(Window window, ObPrompt *prompt)
         /* This is focus stealing prevention */
         ob_debug_type(OB_DEBUG_FOCUS,
                       "Want to focus new window 0x%x at time %u "
-                      "launched at %u (last user interaction time %u)\n",
+                      "launched at %u (last user interaction time %u)",
                       self->window, map_time, launch_time,
                       event_last_user_time);
 
@@ -508,7 +427,7 @@ void client_manage(Window window, ObPrompt *prompt)
             ob_debug_type(OB_DEBUG_FOCUS,
                           "Not focusing the window because the user is inside "
                           "an Openbox menu or is move/resizing a window and "
-                          "we don't want to interrupt them\n");
+                          "we don't want to interrupt them");
         }
 
         /* if it's on another desktop */
@@ -522,7 +441,7 @@ void client_manage(Window window, ObPrompt *prompt)
             raise = TRUE;
             ob_debug_type(OB_DEBUG_FOCUS,
                           "Not focusing the window because its on another "
-                          "desktop\n");
+                          "desktop");
         }
         /* If something is focused, and it's not our relative... */
         else if (focus_client && client_search_focus_tree_full(self) == NULL &&
@@ -539,14 +458,14 @@ void client_manage(Window window, ObPrompt *prompt)
                 activate = FALSE;
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "Not focusing the window because the user is "
-                              "working in another window\n");
+                              "working in another window");
             }
             /* If its a transient (and its parents aren't focused) */
             else if (client_has_parent(self)) {
                 activate = FALSE;
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "Not focusing the window because it is a "
-                              "transient, and its relatives aren't focused\n");
+                              "transient, and its relatives aren't focused");
             }
             /* Don't steal focus from globally active clients.
                I stole this idea from KWin. It seems nice.
@@ -557,7 +476,7 @@ void client_manage(Window window, ObPrompt *prompt)
                 activate = FALSE;
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "Not focusing the window because a globally "
-                              "active client has focus\n");
+                              "active client has focus");
             }
             /* Don't move focus if it's not going to go to this window
                anyway */
@@ -566,7 +485,7 @@ void client_manage(Window window, ObPrompt *prompt)
                 raise = TRUE;
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "Not focusing the window because another window "
-                              "would get the focus anyway\n");
+                              "would get the focus anyway");
             }
             else if (!(self->desktop == screen_desktop ||
                        self->desktop == DESKTOP_ALL))
@@ -582,7 +501,7 @@ void client_manage(Window window, ObPrompt *prompt)
         if (!activate) {
             ob_debug_type(OB_DEBUG_FOCUS,
                           "Focus stealing prevention activated for %s at "
-                          "time %u (last user interactioon time %u)\n",
+                          "time %u (last user interactioon time %u)",
                           self->title, map_time, event_last_user_time);
             /* if the client isn't focused, then hilite it so the user
                knows it is there */
@@ -627,7 +546,7 @@ void client_manage(Window window, ObPrompt *prompt)
 
     /* add to client list/map */
     client_list = g_list_append(client_list, self);
-    g_hash_table_insert(window_map, &self->window, self);
+    window_add(&self->window, CLIENT_AS_WINDOW(self));
 
     /* this has to happen after we're in the client_list */
     if (STRUT_EXISTS(self->strut))
@@ -639,10 +558,8 @@ void client_manage(Window window, ObPrompt *prompt)
     /* free the ObAppSettings shallow copy */
     g_free(settings);
 
-    ob_debug("Managed window 0x%lx plate 0x%x (%s)\n",
+    ob_debug("Managed window 0x%lx plate 0x%x (%s)",
              window, self->frame->window, self->class);
-
-    return;
 }
 
 
@@ -651,7 +568,7 @@ ObClient *client_fake_manage(Window window)
     ObClient *self;
     ObAppSettings *settings;
 
-    ob_debug("Pretend-managing window: %lx\n", window);
+    ob_debug("Pretend-managing window: %lx", window);
 
     /* do this minimal stuff to figure out the client's decorations */
 
@@ -669,7 +586,7 @@ ObClient *client_fake_manage(Window window)
     self->frame = frame_new(self);
     frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
 
-    ob_debug("gave extents left %d right %d top %d bottom %d\n",
+    ob_debug("gave extents left %d right %d top %d bottom %d",
              self->frame->size.left, self->frame->size.right,
              self->frame->size.top, self->frame->size.bottom);
 
@@ -690,7 +607,7 @@ void client_unmanage(ObClient *self)
     GSList *it;
     gulong ignore_start;
 
-    ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)\n",
+    ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)",
              self->window, self->frame->window,
              self->class, self->title ? self->title : "");
 
@@ -698,7 +615,7 @@ void client_unmanage(ObClient *self)
 
     /* we dont want events no more. do this before hiding the frame so we
        don't generate more events */
-    XSelectInput(ob_display, self->window, NoEventMask);
+    XSelectInput(obt_display, self->window, NoEventMask);
 
     /* ignore enter events from the unmap so it doesnt mess with the focus */
     if (!config_focus_under_mouse)
@@ -706,7 +623,7 @@ void client_unmanage(ObClient *self)
 
     frame_hide(self->frame);
     /* flush to send the hide to the server quickly */
-    XFlush(ob_display);
+    XFlush(obt_display);
 
     if (!config_focus_under_mouse)
         event_end_ignore_all_enters(ignore_start);
@@ -716,7 +633,7 @@ void client_unmanage(ObClient *self)
     /* remove the window from our save set, unless we are managing an internal
        ObPrompt window */
     if (!self->prompt)
-        XChangeSaveSet(ob_display, self->window, SetModeDelete);
+        XChangeSaveSet(obt_display, self->window, SetModeDelete);
 
     /* update the focus lists */
     focus_order_remove(self);
@@ -731,7 +648,7 @@ void client_unmanage(ObClient *self)
 
     client_list = g_list_remove(client_list, self);
     stacking_remove(self);
-    g_hash_table_remove(window_map, &self->window);
+    window_remove(self->window);
 
     /* once the client is out of the list, update the struts to remove its
        influence */
@@ -784,7 +701,7 @@ void client_unmanage(ObClient *self)
         self->decorations = 0; /* unmanaged windows have no decor */
 
         /* give the client its border back */
-        XSetWindowBorderWidth(ob_display, self->window, self->border_width);
+        XSetWindowBorderWidth(obt_display, self->window, self->border_width);
 
         client_move_resize(self, a.x, a.y, a.width, a.height);
     }
@@ -797,25 +714,25 @@ void client_unmanage(ObClient *self)
     if (ob_state() != OB_STATE_EXITING) {
         /* these values should not be persisted across a window
            unmapping/mapping */
-        PROP_ERASE(self->window, net_wm_desktop);
-        PROP_ERASE(self->window, net_wm_state);
-        PROP_ERASE(self->window, wm_state);
+        OBT_PROP_ERASE(self->window, NET_WM_DESKTOP);
+        OBT_PROP_ERASE(self->window, NET_WM_STATE);
+        OBT_PROP_ERASE(self->window, WM_STATE);
     } else {
         /* if we're left in an unmapped state, the client wont be mapped.
            this is bad, since we will no longer be managing the window on
            restart */
-        XMapWindow(ob_display, self->window);
+        XMapWindow(obt_display, self->window);
     }
 
     /* these should not be left on the window ever.  other window managers
        don't necessarily use them and it will mess them up (like compiz) */
-    PROP_ERASE(self->window, net_wm_visible_name);
-    PROP_ERASE(self->window, net_wm_visible_icon_name);
+    OBT_PROP_ERASE(self->window, NET_WM_VISIBLE_NAME);
+    OBT_PROP_ERASE(self->window, NET_WM_VISIBLE_ICON_NAME);
 
     /* update the list hints */
     client_set_list();
 
-    ob_debug("Unmanaged window 0x%lx\n", self->window);
+    ob_debug("Unmanaged window 0x%lx", self->window);
 
     /* free all data allocated in the client struct */
     RrImageUnref(self->icon_set);
@@ -873,7 +790,7 @@ static ObAppSettings *client_get_settings_state(ObClient *self)
             match = FALSE;
 
         if (match) {
-            ob_debug("Window matching: %s\n", app->name);
+            ob_debug("Window matching: %s", app->name);
 
             /* copy the settings to our struct, overriding the existing
                settings if they are not defaults */
@@ -928,17 +845,17 @@ static void client_restore_session_state(ObClient *self)
     GList *it;
 
     ob_debug_type(OB_DEBUG_SM,
-                  "Restore session for client %s\n", self->title);
+                  "Restore session for client %s", self->title);
 
     if (!(it = session_state_find(self))) {
         ob_debug_type(OB_DEBUG_SM,
-                      "Session data not found for client %s\n", self->title);
+                      "Session data not found for client %s", self->title);
         return;
     }
 
     self->session = it->data;
 
-    ob_debug_type(OB_DEBUG_SM, "Session data loaded for client %s\n",
+    ob_debug_type(OB_DEBUG_SM, "Session data loaded for client %s",
                   self->title);
 
     RECT_SET_POINT(self->area, self->session->x, self->session->y);
@@ -948,13 +865,13 @@ static void client_restore_session_state(ObClient *self)
         self->area.width = self->session->w;
     if (self->session->h > 0)
         self->area.height = self->session->h;
-    XResizeWindow(ob_display, self->window,
+    XResizeWindow(obt_display, self->window,
                   self->area.width, self->area.height);
 
     self->desktop = (self->session->desktop == DESKTOP_ALL ?
                      self->session->desktop :
                      MIN(screen_num_desktops - 1, self->session->desktop));
-    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
+    OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, self->desktop);
 
     self->shaded = self->session->shaded;
     self->iconic = self->session->iconic;
@@ -1181,10 +1098,11 @@ static void client_get_all(ObClient *self, gboolean real)
 
 static void client_get_startup_id(ObClient *self)
 {
-    if (!(PROP_GETS(self->window, net_startup_id, utf8, &self->startup_id)))
+    if (!(OBT_PROP_GETS(self->window, NET_STARTUP_ID, utf8,
+                        &self->startup_id)))
         if (self->group)
-            PROP_GETS(self->group->leader,
-                      net_startup_id, utf8, &self->startup_id);
+            OBT_PROP_GETS(self->group->leader,
+                          NET_STARTUP_ID, utf8, &self->startup_id);
 }
 
 static void client_get_area(ObClient *self)
@@ -1192,14 +1110,14 @@ static void client_get_area(ObClient *self)
     XWindowAttributes wattrib;
     Status ret;
 
-    ret = XGetWindowAttributes(ob_display, self->window, &wattrib);
+    ret = XGetWindowAttributes(obt_display, self->window, &wattrib);
     g_assert(ret != BadWindow);
 
     RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
     POINT_SET(self->root_pos, wattrib.x, wattrib.y);
     self->border_width = wattrib.border_width;
 
-    ob_debug("client area: %d %d  %d %d  bw %d\n", wattrib.x, wattrib.y,
+    ob_debug("client area: %d %d  %d %d  bw %d", wattrib.x, wattrib.y,
              wattrib.width, wattrib.height, wattrib.border_width);
 }
 
@@ -1207,12 +1125,12 @@ static void client_get_desktop(ObClient *self)
 {
     guint32 d = screen_num_desktops; /* an always-invalid value */
 
-    if (PROP_GET32(self->window, net_wm_desktop, cardinal, &d)) {
+    if (OBT_PROP_GET32(self->window, NET_WM_DESKTOP, CARDINAL, &d)) {
         if (d >= screen_num_desktops && d != DESKTOP_ALL)
             self->desktop = screen_num_desktops - 1;
         else
             self->desktop = d;
-        ob_debug("client requested desktop 0x%x\n", self->desktop);
+        ob_debug("client requested desktop 0x%x", self->desktop);
     } else {
         GSList *it;
         gboolean first = TRUE;
@@ -1235,7 +1153,7 @@ static void client_get_desktop(ObClient *self)
         if (all != screen_num_desktops) {
             self->desktop = all;
 
-            ob_debug("client desktop set from parents: 0x%x\n",
+            ob_debug("client desktop set from parents: 0x%x",
                      self->desktop);
         }
         /* try get from the startup-notification protocol */
@@ -1243,13 +1161,13 @@ static void client_get_desktop(ObClient *self)
             if (self->desktop >= screen_num_desktops &&
                 self->desktop != DESKTOP_ALL)
                 self->desktop = screen_num_desktops - 1;
-            ob_debug("client desktop set from startup-notification: 0x%x\n",
+            ob_debug("client desktop set from startup-notification: 0x%x",
                      self->desktop);
         }
         /* defaults to the current desktop */
         else {
             self->desktop = screen_desktop;
-            ob_debug("client desktop set to the current desktop: %d\n",
+            ob_debug("client desktop set to the current desktop: %d",
                      self->desktop);
         }
     }
@@ -1260,32 +1178,32 @@ static void client_get_state(ObClient *self)
     guint32 *state;
     guint num;
 
-    if (PROP_GETA32(self->window, net_wm_state, atom, &state, &num)) {
+    if (OBT_PROP_GETA32(self->window, NET_WM_STATE, ATOM, &state, &num)) {
         gulong i;
         for (i = 0; i < num; ++i) {
-            if (state[i] == prop_atoms.net_wm_state_modal)
+            if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MODAL))
                 self->modal = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_shaded)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SHADED))
                 self->shaded = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_hidden)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN))
                 self->iconic = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_skip_taskbar)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR))
                 self->skip_taskbar = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_skip_pager)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER))
                 self->skip_pager = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_fullscreen)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN))
                 self->fullscreen = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_maximized_vert)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT))
                 self->max_vert = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_maximized_horz)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ))
                 self->max_horz = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_above)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_ABOVE))
                 self->above = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_below)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_BELOW))
                 self->below = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_demands_attention)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION))
                 self->demands_attention = TRUE;
-            else if (state[i] == prop_atoms.ob_wm_state_undecorated)
+            else if (state[i] == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED))
                 self->undecorated = TRUE;
         }
 
@@ -1297,14 +1215,14 @@ static void client_get_shaped(ObClient *self)
 {
     self->shaped = FALSE;
 #ifdef   SHAPE
-    if (extensions_shape) {
+    if (obt_display_extension_shape) {
         gint foo;
         guint ufoo;
         gint s;
 
-        XShapeSelectInput(ob_display, self->window, ShapeNotifyMask);
+        XShapeSelectInput(obt_display, self->window, ShapeNotifyMask);
 
-        XShapeQueryExtents(ob_display, self->window, &s, &foo,
+        XShapeQueryExtents(obt_display, self->window, &s, &foo,
                            &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo,
                            &ufoo);
         self->shaped = (s != 0);
@@ -1318,22 +1236,22 @@ void client_update_transient_for(ObClient *self)
     ObClient *target = NULL;
     gboolean trangroup = FALSE;
 
-    if (XGetTransientForHint(ob_display, self->window, &t)) {
+    if (XGetTransientForHint(obt_display, self->window, &t)) {
         if (t != self->window) { /* cant be transient to itself! */
-            target = g_hash_table_lookup(window_map, &t);
+            ObWindow *tw = window_find(t);
             /* if this happens then we need to check for it*/
-            g_assert(target != self);
-            if (target && !WINDOW_IS_CLIENT(target)) {
-                /* this can happen when a dialog is a child of
-                   a dockapp, for example */
-                target = NULL;
+            g_assert(tw != CLIENT_AS_WINDOW(self));
+            if (tw && WINDOW_IS_CLIENT(tw)) {
+                /* watch out for windows with a parent that is something
+                   different, like a dockapp for example */
+                target = WINDOW_AS_CLIENT(tw);
             }
         }
 
         /* Setting the transient_for to Root is actually illegal, however
            applications from time have done this to specify transient for
            their group */
-        if (!target && self->group && t == RootWindow(ob_display, ob_screen))
+        if (!target && self->group && t == obt_root(ob_screen))
             trangroup = TRUE;
     } else if (self->group && self->transient)
         trangroup = TRUE;
@@ -1469,8 +1387,8 @@ static void client_get_mwm_hints(ObClient *self)
 
     self->mwmhints.flags = 0; /* default to none */
 
-    if (PROP_GETA32(self->window, motif_wm_hints, motif_wm_hints,
-                    &hints, &num)) {
+    if (OBT_PROP_GETA32(self->window, MOTIF_WM_HINTS, MOTIF_WM_HINTS,
+                        &hints, &num)) {
         if (num >= OB_MWM_ELEMENTS) {
             self->mwmhints.flags = hints[0];
             self->mwmhints.functions = hints[1];
@@ -1489,26 +1407,27 @@ void client_get_type_and_transientness(ObClient *self)
     self->type = -1;
     self->transient = FALSE;
 
-    if (PROP_GETA32(self->window, net_wm_window_type, atom, &val, &num)) {
+    if (OBT_PROP_GETA32(self->window, NET_WM_WINDOW_TYPE, ATOM, &val, &num)) {
         /* use the first value that we know about in the array */
         for (i = 0; i < num; ++i) {
-            if (val[i] == prop_atoms.net_wm_window_type_desktop)
+            if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP))
                 self->type = OB_CLIENT_TYPE_DESKTOP;
-            else if (val[i] == prop_atoms.net_wm_window_type_dock)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DOCK))
                 self->type = OB_CLIENT_TYPE_DOCK;
-            else if (val[i] == prop_atoms.net_wm_window_type_toolbar)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_TOOLBAR))
                 self->type = OB_CLIENT_TYPE_TOOLBAR;
-            else if (val[i] == prop_atoms.net_wm_window_type_menu)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU))
                 self->type = OB_CLIENT_TYPE_MENU;
-            else if (val[i] == prop_atoms.net_wm_window_type_utility)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_UTILITY))
                 self->type = OB_CLIENT_TYPE_UTILITY;
-            else if (val[i] == prop_atoms.net_wm_window_type_splash)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_SPLASH))
                 self->type = OB_CLIENT_TYPE_SPLASH;
-            else if (val[i] == prop_atoms.net_wm_window_type_dialog)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG))
                 self->type = OB_CLIENT_TYPE_DIALOG;
-            else if (val[i] == prop_atoms.net_wm_window_type_normal)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_NORMAL))
                 self->type = OB_CLIENT_TYPE_NORMAL;
-            else if (val[i] == prop_atoms.kde_net_wm_window_type_override) {
+            else if (val[i] == OBT_PROP_ATOM(KDE_NET_WM_WINDOW_TYPE_OVERRIDE))
+            {
                 /* prevent this window from getting any decor or
                    functionality */
                 self->mwmhints.flags &= (OB_MWM_FLAG_FUNCTIONS |
@@ -1522,7 +1441,7 @@ void client_get_type_and_transientness(ObClient *self)
         g_free(val);
     }
 
-    if (XGetTransientForHint(ob_display, self->window, &t))
+    if (XGetTransientForHint(obt_display, self->window, &t))
         self->transient = TRUE;
 
     if (self->type == (ObClientType) -1) {
@@ -1548,26 +1467,26 @@ void client_get_type_and_transientness(ObClient *self)
 void client_update_protocols(ObClient *self)
 {
     guint32 *proto;
-    guint num_return, i;
+    guint num_ret, i;
 
     self->focus_notify = FALSE;
     self->delete_window = FALSE;
 
-    if (PROP_GETA32(self->window, wm_protocols, atom, &proto, &num_return)) {
-        for (i = 0; i < num_return; ++i) {
-            if (proto[i] == prop_atoms.wm_delete_window)
+    if (OBT_PROP_GETA32(self->window, WM_PROTOCOLS, ATOM, &proto, &num_ret)) {
+        for (i = 0; i < num_ret; ++i) {
+            if (proto[i] == OBT_PROP_ATOM(WM_DELETE_WINDOW))
                 /* this means we can request the window to close */
                 self->delete_window = TRUE;
-            else if (proto[i] == prop_atoms.wm_take_focus)
+            else if (proto[i] == OBT_PROP_ATOM(WM_TAKE_FOCUS))
                 /* if this protocol is requested, then the window will be
                    notified whenever we want it to receive focus */
                 self->focus_notify = TRUE;
-            else if (proto[i] == prop_atoms.net_wm_ping)
+            else if (proto[i] == OBT_PROP_ATOM(NET_WM_PING))
                 /* if this protocol is requested, then the window will allow
                    pings to determine if it is still alive */
                 self->ping = TRUE;
 #ifdef SYNC
-            else if (proto[i] == prop_atoms.net_wm_sync_request)
+            else if (proto[i] == OBT_PROP_ATOM(NET_WM_SYNC_REQUEST))
                 /* if this protocol is requested, then resizing the
                    window will be synchronized between the frame and the
                    client */
@@ -1583,7 +1502,8 @@ void client_update_sync_request_counter(ObClient *self)
 {
     guint32 i;
 
-    if (PROP_GET32(self->window, net_wm_sync_request_counter, cardinal, &i)) {
+    if (OBT_PROP_GET32(self->window, NET_WM_SYNC_REQUEST_COUNTER, CARDINAL,&i))
+    {
         self->sync_counter = i;
     } else
         self->sync_counter = None;
@@ -1594,7 +1514,7 @@ static void client_get_colormap(ObClient *self)
 {
     XWindowAttributes wa;
 
-    if (XGetWindowAttributes(ob_display, self->window, &wa))
+    if (XGetWindowAttributes(obt_display, self->window, &wa))
         client_update_colormap(self, wa.colormap);
 }
 
@@ -1602,7 +1522,7 @@ void client_update_colormap(ObClient *self, Colormap colormap)
 {
     if (colormap == self->colormap) return;
 
-    ob_debug("Setting client %s colormap: 0x%x\n", self->title, colormap);
+    ob_debug("Setting client %s colormap: 0x%x", self->title, colormap);
 
     if (client_focused(self)) {
         screen_install_colormap(self, FALSE); /* uninstall old one */
@@ -1626,7 +1546,7 @@ void client_update_normal_hints(ObClient *self)
     SIZE_SET(self->max_size, G_MAXINT, G_MAXINT);
 
     /* get the hints from the window */
-    if (XGetWMNormalHints(ob_display, self->window, &size, &ret)) {
+    if (XGetWMNormalHints(obt_display, self->window, &size, &ret)) {
         /* normal windows can't request placement! har har
         if (!client_normal(self))
         */
@@ -1657,15 +1577,15 @@ void client_update_normal_hints(ObClient *self)
         if (size.flags & PResizeInc && size.width_inc && size.height_inc)
             SIZE_SET(self->size_inc, size.width_inc, size.height_inc);
 
-        ob_debug("Normal hints: min size (%d %d) max size (%d %d)\n   "
-                 "size inc (%d %d) base size (%d %d)\n",
+        ob_debug("Normal hints: min size (%d %d) max size (%d %d)",
                  self->min_size.width, self->min_size.height,
-                 self->max_size.width, self->max_size.height,
+                 self->max_size.width, self->max_size.height);
+        ob_debug("size inc (%d %d) base size (%d %d)",
                  self->size_inc.width, self->size_inc.height,
                  self->base_size.width, self->base_size.height);
     }
     else
-        ob_debug("Normal hints: not set\n");
+        ob_debug("Normal hints: not set");
 }
 
 void client_setup_decor_and_functions(ObClient *self, gboolean reconfig)
@@ -1838,38 +1758,38 @@ static void client_change_allowed_actions(ObClient *self)
 
     /* desktop windows are kept on all desktops */
     if (self->type != OB_CLIENT_TYPE_DESKTOP)
-        actions[num++] = prop_atoms.net_wm_action_change_desktop;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_CHANGE_DESKTOP);
 
     if (self->functions & OB_CLIENT_FUNC_SHADE)
-        actions[num++] = prop_atoms.net_wm_action_shade;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_SHADE);
     if (self->functions & OB_CLIENT_FUNC_CLOSE)
-        actions[num++] = prop_atoms.net_wm_action_close;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_CLOSE);
     if (self->functions & OB_CLIENT_FUNC_MOVE)
-        actions[num++] = prop_atoms.net_wm_action_move;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MOVE);
     if (self->functions & OB_CLIENT_FUNC_ICONIFY)
-        actions[num++] = prop_atoms.net_wm_action_minimize;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MINIMIZE);
     if (self->functions & OB_CLIENT_FUNC_RESIZE)
-        actions[num++] = prop_atoms.net_wm_action_resize;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_RESIZE);
     if (self->functions & OB_CLIENT_FUNC_FULLSCREEN)
-        actions[num++] = prop_atoms.net_wm_action_fullscreen;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_FULLSCREEN);
     if (self->functions & OB_CLIENT_FUNC_MAXIMIZE) {
-        actions[num++] = prop_atoms.net_wm_action_maximize_horz;
-        actions[num++] = prop_atoms.net_wm_action_maximize_vert;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MAXIMIZE_HORZ);
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MAXIMIZE_VERT);
     }
     if (self->functions & OB_CLIENT_FUNC_ABOVE)
-        actions[num++] = prop_atoms.net_wm_action_above;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_ABOVE);
     if (self->functions & OB_CLIENT_FUNC_BELOW)
-        actions[num++] = prop_atoms.net_wm_action_below;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_BELOW);
     if (self->functions & OB_CLIENT_FUNC_UNDECORATE)
-        actions[num++] = prop_atoms.ob_wm_action_undecorate;
+        actions[num++] = OBT_PROP_ATOM(OB_WM_ACTION_UNDECORATE);
 
-    PROP_SETA32(self->window, net_wm_allowed_actions, atom, actions, num);
+    OBT_PROP_SETA32(self->window, NET_WM_ALLOWED_ACTIONS, ATOM, actions, num);
 
-   /* make sure the window isn't breaking any rules now
+    /* make sure the window isn't breaking any rules now
 
-   don't check ICONIFY here.  just cuz a window can't iconify doesnt mean
-   it can't be iconified with its parent
-   */
+       don't check ICONIFY here.  just cuz a window can't iconify doesnt mean
+       it can't be iconified with its parent
+    */
 
     if (!(self->functions & OB_CLIENT_FUNC_SHADE) && self->shaded) {
         if (self->frame) client_shade(self, FALSE);
@@ -1893,7 +1813,7 @@ void client_update_wmhints(ObClient *self)
     /* assume a window takes input if it doesnt specify */
     self->can_focus = TRUE;
 
-    if ((hints = XGetWMHints(ob_display, self->window)) != NULL) {
+    if ((hints = XGetWMHints(obt_display, self->window)) != NULL) {
         gboolean ur;
 
         if (hints->flags & InputHint)
@@ -1982,10 +1902,10 @@ void client_update_title(ObClient *self)
     g_free(self->original_title);
 
     /* try netwm */
-    if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) {
+    if (!OBT_PROP_GETS(self->window, NET_WM_NAME, utf8, &data)) {
         /* try old x stuff */
-        if (!(PROP_GETS(self->window, wm_name, locale, &data)
-              || PROP_GETS(self->window, wm_name, utf8, &data))) {
+        if (!(OBT_PROP_GETS(self->window, WM_NAME, locale, &data)
+              || OBT_PROP_GETS(self->window, WM_NAME, utf8, &data))) {
             if (self->transient) {
     /*
     GNOME alert windows are not given titles:
@@ -2013,7 +1933,7 @@ void client_update_title(ObClient *self)
         g_free(data);
     }
 
-    PROP_SETS(self->window, net_wm_visible_name, visible);
+    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_NAME, utf8, visible);
     self->title = visible;
 
     if (self->frame)
@@ -2024,10 +1944,10 @@ void client_update_title(ObClient *self)
     g_free(self->icon_title);
 
     /* try netwm */
-    if (!PROP_GETS(self->window, net_wm_icon_name, utf8, &data))
+    if (!OBT_PROP_GETS(self->window, NET_WM_ICON_NAME, utf8, &data))
         /* try old x stuff */
-        if (!(PROP_GETS(self->window, wm_icon_name, locale, &data) ||
-              PROP_GETS(self->window, wm_icon_name, utf8, &data)))
+        if (!(OBT_PROP_GETS(self->window, WM_ICON_NAME, locale, &data) ||
+              OBT_PROP_GETS(self->window, WM_ICON_NAME, utf8, &data)))
             data = g_strdup(self->title);
 
     if (self->client_machine) {
@@ -2045,7 +1965,7 @@ void client_update_title(ObClient *self)
         g_free(data);
     }
 
-    PROP_SETS(self->window, net_wm_visible_icon_name, visible);
+    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_ICON_NAME, utf8, visible);
     self->icon_title = visible;
 }
 
@@ -2056,8 +1976,9 @@ void client_update_strut(ObClient *self)
     gboolean got = FALSE;
     StrutPartial strut;
 
-    if (PROP_GETA32(self->window, net_wm_strut_partial, cardinal,
-                    &data, &num)) {
+    if (OBT_PROP_GETA32(self->window, NET_WM_STRUT_PARTIAL, CARDINAL,
+                        &data, &num))
+    {
         if (num == 12) {
             got = TRUE;
             STRUT_PARTIAL_SET(strut,
@@ -2069,7 +1990,7 @@ void client_update_strut(ObClient *self)
     }
 
     if (!got &&
-        PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) {
+        OBT_PROP_GETA32(self->window, NET_WM_STRUT, CARDINAL, &data, &num)) {
         if (num == 4) {
             Rect *a;
 
@@ -2118,7 +2039,7 @@ void client_update_icons(ObClient *self)
        icon */
     grab_server(TRUE);
 
-    if (PROP_GETA32(self->window, net_wm_icon, cardinal, &data, &num)) {
+    if (OBT_PROP_GETA32(self->window, NET_WM_ICON, CARDINAL, &data, &num)) {
         /* figure out how many valid icons are in here */
         i = 0;
         num_seen = 0;
@@ -2170,16 +2091,16 @@ void client_update_icons(ObClient *self)
     if (!img) {
         XWMHints *hints;
 
-        if ((hints = XGetWMHints(ob_display, self->window))) {
+        if ((hints = XGetWMHints(obt_display, self->window))) {
             if (hints->flags & IconPixmapHint) {
                 gboolean xicon;
-                xerror_set_ignore(TRUE);
+                obt_display_ignore_errors(TRUE);
                 xicon = RrPixmapToRGBA(ob_rr_inst,
                                        hints->icon_pixmap,
                                        (hints->flags & IconMaskHint ?
                                         hints->icon_mask : None),
                                        (gint*)&w, (gint*)&h, &data);
-                xerror_set_ignore(FALSE);
+                obt_display_ignore_errors(FALSE);
 
 
                 if (xicon) {
@@ -2223,7 +2144,7 @@ void client_update_icons(ObClient *self)
                 (((icon[i] >> RrDefaultRedOffset) & 0xff) << 16) +
                 (((icon[i] >> RrDefaultGreenOffset) & 0xff) << 8) +
                 (((icon[i] >> RrDefaultBlueOffset) & 0xff) << 0);
-        PROP_SETA32(self->window, net_wm_icon, cardinal, ldata, w*h+2);
+        OBT_PROP_SETA32(self->window, NET_WM_ICON, CARDINAL, ldata, w*h+2);
         g_free(ldata);
     } else if (self->frame)
         /* don't draw the icon empty if we're just setting one now anyways,
@@ -2240,7 +2161,8 @@ void client_update_icon_geometry(ObClient *self)
 
     RECT_SET(self->icon_geometry, 0, 0, 0, 0);
 
-    if (PROP_GETA32(self->window, net_wm_icon_geometry, cardinal, &data, &num))
+    if (OBT_PROP_GETA32(self->window, NET_WM_ICON_GEOMETRY, CARDINAL,
+                        &data, &num))
     {
         if (num == 4)
             /* don't let them set it with an area < 0 */
@@ -2257,23 +2179,23 @@ static void client_get_session_ids(ObClient *self)
     gchar *s;
     gchar **ss;
 
-    if (!PROP_GET32(self->window, wm_client_leader, window, &leader))
+    if (!OBT_PROP_GET32(self->window, WM_CLIENT_LEADER, WINDOW, &leader))
         leader = None;
 
     /* get the SM_CLIENT_ID */
     got = FALSE;
     if (leader)
-        got = PROP_GETS(leader, sm_client_id, locale, &self->sm_client_id);
+        got = OBT_PROP_GETS(leader, SM_CLIENT_ID, locale, &self->sm_client_id);
     if (!got)
-        PROP_GETS(self->window, sm_client_id, locale, &self->sm_client_id);
+        OBT_PROP_GETS(self->window, SM_CLIENT_ID, locale, &self->sm_client_id);
 
     /* get the WM_CLASS (name and class). make them "" if they are not
        provided */
     got = FALSE;
     if (leader)
-        got = PROP_GETSS(leader, wm_class, locale, &ss);
+        got = OBT_PROP_GETSS(leader, WM_CLASS, locale, &ss);
     if (!got)
-        got = PROP_GETSS(self->window, wm_class, locale, &ss);
+        got = OBT_PROP_GETSS(self->window, WM_CLASS, locale, &ss);
 
     if (got) {
         if (ss[0]) {
@@ -2290,9 +2212,9 @@ static void client_get_session_ids(ObClient *self)
     /* get the WM_WINDOW_ROLE. make it "" if it is not provided */
     got = FALSE;
     if (leader)
-        got = PROP_GETS(leader, wm_window_role, locale, &s);
+        got = OBT_PROP_GETS(leader, WM_WINDOW_ROLE, locale, &s);
     if (!got)
-        got = PROP_GETS(self->window, wm_window_role, locale, &s);
+        got = OBT_PROP_GETS(self->window, WM_WINDOW_ROLE, locale, &s);
 
     if (got)
         self->role = s;
@@ -2303,9 +2225,9 @@ static void client_get_session_ids(ObClient *self)
     got = FALSE;
 
     if (leader)
-        got = PROP_GETSS(leader, wm_command, locale, &ss);
+        got = OBT_PROP_GETSS(leader, WM_COMMAND, locale, &ss);
     if (!got)
-        got = PROP_GETSS(self->window, wm_command, locale, &ss);
+        got = OBT_PROP_GETSS(self->window, WM_COMMAND, locale, &ss);
 
     if (got) {
         /* merge/mash them all together */
@@ -2328,9 +2250,9 @@ static void client_get_session_ids(ObClient *self)
     /* get the WM_CLIENT_MACHINE */
     got = FALSE;
     if (leader)
-        got = PROP_GETS(leader, wm_client_machine, locale, &s);
+        got = OBT_PROP_GETS(leader, WM_CLIENT_MACHINE, locale, &s);
     if (!got)
-        got = PROP_GETS(self->window, wm_client_machine, locale, &s);
+        got = OBT_PROP_GETS(self->window, WM_CLIENT_MACHINE, locale, &s);
 
     if (got) {
         gchar localhost[128];
@@ -2345,7 +2267,7 @@ static void client_get_session_ids(ObClient *self)
 
         /* see if it has the PID set too (the PID requires that the
            WM_CLIENT_MACHINE be set) */
-        if (PROP_GET32(self->window, net_wm_pid, cardinal, &pid))
+        if (OBT_PROP_GET32(self->window, NET_WM_PID, CARDINAL, &pid))
             self->pid = pid;
     }
 }
@@ -2365,12 +2287,12 @@ static void client_change_wm_state(ObClient *self)
         self->wmstate = NormalState;
 
     if (old != self->wmstate) {
-        PROP_MSG(self->window, kde_wm_change_state,
-                 self->wmstate, 1, 0, 0);
+        OBT_PROP_MSG(ob_screen, self->window, KDE_WM_CHANGE_STATE,
+                     self->wmstate, 1, 0, 0, 0);
 
         state[0] = self->wmstate;
         state[1] = None;
-        PROP_SETA32(self->window, wm_state, wm_state, state, 2);
+        OBT_PROP_SETA32(self->window, WM_STATE, WM_STATE, state, 2);
     }
 }
 
@@ -2381,30 +2303,30 @@ static void client_change_state(ObClient *self)
 
     num = 0;
     if (self->modal)
-        netstate[num++] = prop_atoms.net_wm_state_modal;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MODAL);
     if (self->shaded)
-        netstate[num++] = prop_atoms.net_wm_state_shaded;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SHADED);
     if (self->iconic)
-        netstate[num++] = prop_atoms.net_wm_state_hidden;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_HIDDEN);
     if (self->skip_taskbar)
-        netstate[num++] = prop_atoms.net_wm_state_skip_taskbar;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR);
     if (self->skip_pager)
-        netstate[num++] = prop_atoms.net_wm_state_skip_pager;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER);
     if (self->fullscreen)
-        netstate[num++] = prop_atoms.net_wm_state_fullscreen;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN);
     if (self->max_vert)
-        netstate[num++] = prop_atoms.net_wm_state_maximized_vert;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT);
     if (self->max_horz)
-        netstate[num++] = prop_atoms.net_wm_state_maximized_horz;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ);
     if (self->above)
-        netstate[num++] = prop_atoms.net_wm_state_above;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_ABOVE);
     if (self->below)
-        netstate[num++] = prop_atoms.net_wm_state_below;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_BELOW);
     if (self->demands_attention)
-        netstate[num++] = prop_atoms.net_wm_state_demands_attention;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION);
     if (self->undecorated)
-        netstate[num++] = prop_atoms.ob_wm_state_undecorated;
-    PROP_SETA32(self->window, net_wm_state, atom, netstate, num);
+        netstate[num++] = OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED);
+    OBT_PROP_SETA32(self->window, NET_WM_STATE, ATOM, netstate, num);
 
     if (self->frame)
         frame_adjust_state(self->frame);
@@ -2710,7 +2632,7 @@ static void client_apply_startup_state(ObClient *self,
        pre-max/pre-fullscreen values
     */
     client_try_configure(self, &x, &y, &w, &h, &l, &l, FALSE);
-    ob_debug("placed window 0x%x at %d, %d with size %d x %d\n",
+    ob_debug("placed window 0x%x at %d, %d with size %d x %d",
              self->window, x, y, w, h);
     /* save the area, and make it where it should be for the premax stuff */
     oldarea = self->area;
@@ -2750,7 +2672,7 @@ static void client_apply_startup_state(ObClient *self,
     client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
 
     /* set the desktop hint, to make sure that it always exists */
-    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
+    OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, self->desktop);
 
     /* nothing to do for the other states:
        skip_taskbar
@@ -3026,7 +2948,7 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
 
     /* if the client is enlarging, then resize the client before the frame */
     if (send_resize_client && (w > oldw || h > oldh)) {
-        XMoveResizeWindow(ob_display, self->window,
+        XMoveResizeWindow(obt_display, self->window,
                           self->frame->size.left, self->frame->size.top,
                           MAX(w, oldw), MAX(h, oldh));
         frame_adjust_client_area(self->frame);
@@ -3092,11 +3014,11 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
         XEvent event;
 
         event.type = ConfigureNotify;
-        event.xconfigure.display = ob_display;
+        event.xconfigure.display = obt_display;
         event.xconfigure.event = self->window;
         event.xconfigure.window = self->window;
 
-        ob_debug("Sending ConfigureNotify to %s for %d,%d %dx%d\n",
+        ob_debug("Sending ConfigureNotify to %s for %d,%d %dx%d",
                  self->title, self->root_pos.x, self->root_pos.y, w, h);
 
         /* root window real coords */
@@ -3118,11 +3040,11 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
      */
     if (send_resize_client && (w <= oldw || h <= oldh)) {
         frame_adjust_client_area(self->frame);
-        XMoveResizeWindow(ob_display, self->window,
+        XMoveResizeWindow(obt_display, self->window,
                           self->frame->size.left, self->frame->size.top, w, h);
     }
 
-    XFlush(ob_display);
+    XFlush(obt_display);
 
     /* if it moved between monitors, then this can affect the stacking
        layer of this window or others - for fullscreen windows */
@@ -3173,7 +3095,7 @@ void client_fullscreen(ObClient *self, gboolean fs)
         RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0);
     }
 
-    ob_debug("Window %s going fullscreen (%d)\n",
+    ob_debug("Window %s going fullscreen (%d)",
              self->title, self->fullscreen);
 
     client_setup_decor_and_functions(self, FALSE);
@@ -3199,7 +3121,7 @@ static void client_iconify_recursive(ObClient *self,
 
 
     if (self->iconic != iconic) {
-        ob_debug("%sconifying window: 0x%lx\n", (iconic ? "I" : "Uni"),
+        ob_debug("%sconifying window: 0x%lx", (iconic ? "I" : "Uni"),
                  self->window);
 
         if (iconic) {
@@ -3374,12 +3296,12 @@ void client_close(ObClient *self)
     if (!self->delete_window)
         /* don't use client_kill(), we should only kill based on PID in
            response to a lack of PING replies */
-        XKillClient(ob_display, self->window);
+        XKillClient(obt_display, self->window);
     else {
         /* request the client to close with WM_DELETE_WINDOW */
-        PROP_MSG_TO(self->window, self->window, wm_protocols,
-                    prop_atoms.wm_delete_window, event_curtime, 0, 0, 0,
-                    NoEventMask);
+        OBT_PROP_MSG_TO(self->window, self->window, WM_PROTOCOLS,
+                        OBT_PROP_ATOM(WM_DELETE_WINDOW), event_curtime,
+                        0, 0, 0, NoEventMask);
 
         /* we're trying to close the window, so see if it is responding. if it
            is not, then we will let them kill the window */
@@ -3462,14 +3384,14 @@ void client_kill(ObClient *self)
             client_update_title(self);
         }
         else {
-            ob_debug("killing window 0x%x with pid %lu, with SIGKILL\n",
+            ob_debug("killing window 0x%x with pid %lu, with SIGKILL",
                      self->window, self->pid);
             kill(self->pid, SIGKILL); /* kill -9 */
         }
     }
     else {
         /* running on a remote host */
-        XKillClient(ob_display, self->window);
+        XKillClient(obt_display, self->window);
     }
 }
 
@@ -3499,13 +3421,13 @@ static void client_set_desktop_recursive(ObClient *self,
 
     if (target != self->desktop && self->type != OB_CLIENT_TYPE_DESKTOP) {
 
-        ob_debug("Setting desktop %u\n", target+1);
+        ob_debug("Setting desktop %u", target+1);
 
         g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
 
         old = self->desktop;
         self->desktop = target;
-        PROP_SET32(self->window, net_wm_desktop, cardinal, target);
+        OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, target);
         /* the frame can display the current desktop state */
         frame_adjust_state(self->frame);
         /* 'move' the window to the new desktop */
@@ -3561,11 +3483,12 @@ gboolean client_validate(ObClient *self)
 {
     XEvent e;
 
-    XSync(ob_display, FALSE); /* get all events on the server */
+    XSync(obt_display, FALSE); /* get all events on the server */
 
-    if (XCheckTypedWindowEvent(ob_display, self->window, DestroyNotify, &e) ||
-        XCheckTypedWindowEvent(ob_display, self->window, UnmapNotify, &e)) {
-        XPutBackEvent(ob_display, &e);
+    if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e) ||
+        XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e))
+    {
+        XPutBackEvent(obt_display, &e);
         return FALSE;
     }
 
@@ -3600,9 +3523,9 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
     gboolean below = self->below;
     gint i;
 
-    if (!(action == prop_atoms.net_wm_state_add ||
-          action == prop_atoms.net_wm_state_remove ||
-          action == prop_atoms.net_wm_state_toggle))
+    if (!(action == OBT_PROP_ATOM(NET_WM_STATE_ADD) ||
+          action == OBT_PROP_ATOM(NET_WM_STATE_REMOVE) ||
+          action == OBT_PROP_ATOM(NET_WM_STATE_TOGGLE)))
         /* an invalid action was passed to the client message, ignore it */
         return;
 
@@ -3612,103 +3535,103 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
         if (!state) continue;
 
         /* if toggling, then pick whether we're adding or removing */
-        if (action == prop_atoms.net_wm_state_toggle) {
-            if (state == prop_atoms.net_wm_state_modal)
-                action = modal ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_maximized_vert)
-                action = self->max_vert ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_maximized_horz)
-                action = self->max_horz ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_shaded)
-                action = shaded ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_skip_taskbar)
+        if (action == OBT_PROP_ATOM(NET_WM_STATE_TOGGLE)) {
+            if (state == OBT_PROP_ATOM(NET_WM_STATE_MODAL))
+                action = modal ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT))
+                action = self->max_vert ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ))
+                action = self->max_horz ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SHADED))
+                action = shaded ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR))
                 action = self->skip_taskbar ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_skip_pager)
+                    OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER))
                 action = self->skip_pager ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_hidden)
+                    OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN))
                 action = self->iconic ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_fullscreen)
+                    OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN))
                 action = fullscreen ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_above)
-                action = self->above ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_below)
-                action = self->below ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_demands_attention)
+                    OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_ABOVE))
+                action = self->above ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_BELOW))
+                action = self->below ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION))
                 action = self->demands_attention ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.ob_wm_state_undecorated)
-                action = undecorated ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
+                    OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
+            else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED))
+                action = undecorated ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                    OBT_PROP_ATOM(NET_WM_STATE_ADD);
         }
 
-        if (action == prop_atoms.net_wm_state_add) {
-            if (state == prop_atoms.net_wm_state_modal) {
+        if (action == OBT_PROP_ATOM(NET_WM_STATE_ADD)) {
+            if (state == OBT_PROP_ATOM(NET_WM_STATE_MODAL)) {
                 modal = TRUE;
-            } else if (state == prop_atoms.net_wm_state_maximized_vert) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT)) {
                 max_vert = TRUE;
-            } else if (state == prop_atoms.net_wm_state_maximized_horz) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ)) {
                 max_horz = TRUE;
-            } else if (state == prop_atoms.net_wm_state_shaded) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SHADED)) {
                 shaded = TRUE;
-            } else if (state == prop_atoms.net_wm_state_skip_taskbar) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR)) {
                 self->skip_taskbar = TRUE;
-            } else if (state == prop_atoms.net_wm_state_skip_pager) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER)) {
                 self->skip_pager = TRUE;
-            } else if (state == prop_atoms.net_wm_state_hidden) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN)) {
                 iconic = TRUE;
-            } else if (state == prop_atoms.net_wm_state_fullscreen) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN)) {
                 fullscreen = TRUE;
-            } else if (state == prop_atoms.net_wm_state_above) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_ABOVE)) {
                 above = TRUE;
                 below = FALSE;
-            } else if (state == prop_atoms.net_wm_state_below) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_BELOW)) {
                 above = FALSE;
                 below = TRUE;
-            } else if (state == prop_atoms.net_wm_state_demands_attention) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION)){
                 demands_attention = TRUE;
-            } else if (state == prop_atoms.ob_wm_state_undecorated) {
+            } else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED)) {
                 undecorated = TRUE;
             }
 
-        } else { /* action == prop_atoms.net_wm_state_remove */
-            if (state == prop_atoms.net_wm_state_modal) {
+        } else { /* action == OBT_PROP_ATOM(NET_WM_STATE_REMOVE) */
+            if (state == OBT_PROP_ATOM(NET_WM_STATE_MODAL)) {
                 modal = FALSE;
-            } else if (state == prop_atoms.net_wm_state_maximized_vert) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT)) {
                 max_vert = FALSE;
-            } else if (state == prop_atoms.net_wm_state_maximized_horz) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ)) {
                 max_horz = FALSE;
-            } else if (state == prop_atoms.net_wm_state_shaded) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SHADED)) {
                 shaded = FALSE;
-            } else if (state == prop_atoms.net_wm_state_skip_taskbar) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR)) {
                 self->skip_taskbar = FALSE;
-            } else if (state == prop_atoms.net_wm_state_skip_pager) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER)) {
                 self->skip_pager = FALSE;
-            } else if (state == prop_atoms.net_wm_state_hidden) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN)) {
                 iconic = FALSE;
-            } else if (state == prop_atoms.net_wm_state_fullscreen) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN)) {
                 fullscreen = FALSE;
-            } else if (state == prop_atoms.net_wm_state_above) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_ABOVE)) {
                 above = FALSE;
-            } else if (state == prop_atoms.net_wm_state_below) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_BELOW)) {
                 below = FALSE;
-            } else if (state == prop_atoms.net_wm_state_demands_attention) {
+            } else if (state == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION)){
                 demands_attention = FALSE;
-            } else if (state == prop_atoms.ob_wm_state_undecorated) {
+            } else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED)) {
                 undecorated = FALSE;
             }
         }
@@ -3800,12 +3723,12 @@ gboolean client_focus(ObClient *self)
 
     if (!client_can_focus(self)) {
         ob_debug_type(OB_DEBUG_FOCUS,
-                      "Client %s can't be focused\n", self->title);
+                      "Client %s can't be focused", self->title);
         return FALSE;
     }
 
     ob_debug_type(OB_DEBUG_FOCUS,
-                  "Focusing client \"%s\" (0x%x) at time %u\n",
+                  "Focusing client \"%s\" (0x%x) at time %u",
                   self->title, self->window, event_curtime);
 
     /* if using focus_delay, stop the timer now so that focus doesn't
@@ -3821,35 +3744,35 @@ gboolean client_focus(ObClient *self)
     */
     event_cancel_all_key_grabs();
 
-    xerror_set_ignore(TRUE);
-    xerror_occured = FALSE;
+    obt_display_ignore_errors(TRUE);
 
     if (self->can_focus) {
         /* This can cause a BadMatch error with CurrentTime, or if an app
            passed in a bad time for _NET_WM_ACTIVE_WINDOW. */
-        XSetInputFocus(ob_display, self->window, RevertToPointerRoot,
+        XSetInputFocus(obt_display, self->window, RevertToPointerRoot,
                        event_curtime);
     }
 
     if (self->focus_notify) {
         XEvent ce;
         ce.xclient.type = ClientMessage;
-        ce.xclient.message_type = prop_atoms.wm_protocols;
-        ce.xclient.display = ob_display;
+        ce.xclient.message_type = OBT_PROP_ATOM(WM_PROTOCOLS);
+        ce.xclient.display = obt_display;
         ce.xclient.window = self->window;
         ce.xclient.format = 32;
-        ce.xclient.data.l[0] = prop_atoms.wm_take_focus;
+        ce.xclient.data.l[0] = OBT_PROP_ATOM(WM_TAKE_FOCUS);
         ce.xclient.data.l[1] = event_curtime;
         ce.xclient.data.l[2] = 0l;
         ce.xclient.data.l[3] = 0l;
         ce.xclient.data.l[4] = 0l;
-        XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce);
+        XSendEvent(obt_display, self->window, FALSE, NoEventMask, &ce);
     }
 
-    xerror_set_ignore(FALSE);
+    obt_display_ignore_errors(FALSE);
 
-    ob_debug_type(OB_DEBUG_FOCUS, "Error focusing? %d\n", xerror_occured);
-    return !xerror_occured;
+    ob_debug_type(OB_DEBUG_FOCUS, "Error focusing? %d",
+                  obt_display_error_occured);
+    return !obt_display_error_occured;
 }
 
 static void client_present(ObClient *self, gboolean here, gboolean raise,
@@ -4142,15 +4065,15 @@ static void detect_edge(Rect area, ObDirection dir,
             g_assert_not_reached();
     }
 
-    ob_debug("my head %d size %d\n", my_head, my_size);
-    ob_debug("head %d tail %d deest %d\n", head, tail, *dest);
+    ob_debug("my head %d size %d", my_head, my_size);
+    ob_debug("head %d tail %d deest %d", head, tail, *dest);
     if (!skip_head) {
-        ob_debug("using near edge %d\n", head);
+        ob_debug("using near edge %d", head);
         *dest = head;
         *near_edge = TRUE;
     }
     else if (!skip_tail) {
-        ob_debug("using far edge %d\n", tail);
+        ob_debug("using far edge %d", tail);
         *dest = tail;
         *near_edge = FALSE;
     }
@@ -4215,7 +4138,7 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
             cur->desktop != screen_desktop)
             continue;
 
-        ob_debug("trying window %s\n", cur->title);
+        ob_debug("trying window %s", cur->title);
 
         detect_edge(cur->frame->area, dir, my_head, my_size, my_edge_start,
                     my_edge_size, dest, near_edge);
@@ -4336,10 +4259,10 @@ void client_find_resize_directional(ObClient *self, ObDirection side,
         g_assert_not_reached();
     }
 
-    ob_debug("head %d dir %d\n", head, dir);
+    ob_debug("head %d dir %d", head, dir);
     client_find_edge_directional(self, dir, head, 1,
                                  e_start, e_size, &e, &near);
-    ob_debug("edge %d\n", e);
+    ob_debug("edge %d", e);
     *x = self->frame->area.x;
     *y = self->frame->area.y;
     *w = self->frame->area.width;
index c2461cb..c24fcb2 100644 (file)
@@ -321,8 +321,6 @@ typedef void (*ObClientCallback)(ObClient *client, gpointer data);
 void client_add_destroy_notify(ObClientCallback func, gpointer data);
 void client_remove_destroy_notify(ObClientCallback func);
 
-/*! Manages all existing windows */
-void client_manage_all();
 /*! Manages a given window
   @param prompt This specifies an ObPrompt which is being managed.  It is
                 possible to manage Openbox-owned windows through this.
index f35b5bd..04f50e8 100644 (file)
@@ -27,8 +27,8 @@
 #include "frame.h"
 #include "moveresize.h"
 #include "event.h"
-#include "prop.h"
 #include "gettext.h"
+#include "obt/prop.h"
 
 #include <glib.h>
 
@@ -141,7 +141,7 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
 
         screen_pointer_pos(&x, &y);
         moveresize_start(c, x, y, 0,
-                         prop_atoms.net_wm_moveresize_move_keyboard);
+                         OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD));
         break;
     case CLIENT_RESIZE:
         /* this needs to grab the keyboard so hide the menu */
@@ -150,7 +150,7 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
 
         screen_pointer_pos(&x, &y);
         moveresize_start(c, x, y, 0,
-                         prop_atoms.net_wm_moveresize_size_keyboard);
+                         OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD));
         break;
     case CLIENT_CLOSE:
         client_close(c);
index c82e3b3..b5b4ef4 100644 (file)
 #include "keyboard.h"
 #include "mouse.h"
 #include "actions.h"
-#include "prop.h"
 #include "translate.h"
 #include "client.h"
 #include "screen.h"
-#include "parser/parse.h"
 #include "openbox.h"
 #include "gettext.h"
+#include "obt/paths.h"
 
 gboolean config_focus_new;
 gboolean config_focus_follow;
@@ -146,10 +145,9 @@ void config_app_settings_copy_non_defaults(const ObAppSettings *src,
     }
 }
 
-static void config_parse_gravity_coord(xmlDocPtr doc, xmlNodePtr node,
-                                       GravityCoord *c)
+static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
 {
-    gchar *s = parse_string(doc, node);
+    gchar *s = obt_parse_node_string(node);
     if (!g_ascii_strcasecmp(s, "center"))
         c->center = TRUE;
     else {
@@ -191,10 +189,9 @@ static void config_parse_gravity_coord(xmlDocPtr doc, xmlNodePtr node,
    the monitor, so <position><x>center</x></position><monitor>2</monitor>
    will center the window on the second monitor.
 */
-static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
-                                   xmlNodePtr node, gpointer data)
+static void parse_per_app_settings(xmlNodePtr node, gpointer d)
 {
-    xmlNodePtr app = parse_find_node("application", node->children);
+    xmlNodePtr app = obt_parse_find_node(node->children, "application");
     gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
     gboolean name_set, class_set, type_set;
     gboolean x_pos_given;
@@ -202,9 +199,9 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
     while (app) {
         name_set = class_set = type_set = x_pos_given = FALSE;
 
-        class_set = parse_attr_string("class", app, &class);
-        name_set = parse_attr_string("name", app, &name);
-        type_set = parse_attr_string("type", app, &type);
+        class_set = obt_parse_attr_string(app, "class", &class);
+        name_set = obt_parse_attr_string(app, "name", &name);
+        type_set = obt_parse_attr_string(app, "type", &type);
         if (class_set || name_set) {
             xmlNodePtr n, c;
             ObAppSettings *settings = config_create_app_settings();;
@@ -234,57 +231,55 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
                     settings->type = OB_CLIENT_TYPE_DESKTOP;
             }
 
-            if (parse_attr_string("role", app, &role))
+            if (obt_parse_attr_string(app, "role", &role))
                 settings->role = g_pattern_spec_new(role);
 
-            if ((n = parse_find_node("decor", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->decor = parse_bool(doc, n);
+            if ((n = obt_parse_find_node(app->children, "decor")))
+                if (!obt_parse_node_contains(n, "default"))
+                    settings->decor = obt_parse_node_bool(n);
 
-            if ((n = parse_find_node("shade", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->shade = parse_bool(doc, n);
+            if ((n = obt_parse_find_node(app->children, "shade")))
+                if (!obt_parse_node_contains(n, "default"))
+                    settings->shade = obt_parse_node_bool(n);
 
-            if ((n = parse_find_node("position", app->children))) {
-                if ((c = parse_find_node("x", n->children)))
-                    if (!parse_contains("default", doc, c)) {
-                        config_parse_gravity_coord(doc, c,
-                                                   &settings->position.x);
+            if ((n = obt_parse_find_node(app->children, "position"))) {
+                if ((c = obt_parse_find_node(n->children, "x")))
+                    if (!obt_parse_node_contains(c, "default")) {
+                        config_parse_gravity_coord(c, &settings->position.x);
                         x_pos_given = TRUE;
                     }
 
-                if (x_pos_given && (c = parse_find_node("y", n->children)))
-                    if (!parse_contains("default", doc, c)) {
-                        config_parse_gravity_coord(doc, c,
-                                                   &settings->position.y);
+                if (x_pos_given && (c = obt_parse_find_node(n->children, "y")))
+                    if (!obt_parse_node_contains(c, "default")) {
+                        config_parse_gravity_coord(c, &settings->position.y);
                         settings->pos_given = TRUE;
                     }
 
                 if (settings->pos_given &&
-                    (c = parse_find_node("monitor", n->children)))
-                    if (!parse_contains("default", doc, c)) {
-                        gchar *s = parse_string(doc, c);
+                    (c = obt_parse_find_node(n->children, "monitor")))
+                    if (!obt_parse_node_contains(c, "default")) {
+                        gchar *s = obt_parse_node_string(c);
                         if (!g_ascii_strcasecmp(s, "mouse"))
                             settings->monitor = 0;
                         else
-                            settings->monitor = parse_int(doc, c) + 1;
+                            settings->monitor = obt_parse_node_int(c) + 1;
                         g_free(s);
                     }
 
-                parse_attr_bool("force", n, &settings->pos_force);
+                obt_parse_attr_bool(n, "force", &settings->pos_force);
             }
 
-            if ((n = parse_find_node("focus", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->focus = parse_bool(doc, n);
+            if ((n = obt_parse_find_node(app->children, "focus")))
+                if (!obt_parse_node_contains(n, "default"))
+                    settings->focus = obt_parse_node_bool(n);
 
-            if ((n = parse_find_node("desktop", app->children))) {
-                if (!parse_contains("default", doc, n)) {
-                    gchar *s = parse_string(doc, n);
+            if ((n = obt_parse_find_node(app->children, "desktop"))) {
+                if (!obt_parse_node_contains(n, "default")) {
+                    gchar *s = obt_parse_node_string(n);
                     if (!g_ascii_strcasecmp(s, "all"))
                         settings->desktop = DESKTOP_ALL;
                     else {
-                        gint i = parse_int(doc, n);
+                        gint i = obt_parse_node_int(n);
                         if (i > 0)
                             settings->desktop = i;
                     }
@@ -292,9 +287,9 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
                 }
             }
 
-            if ((n = parse_find_node("layer", app->children)))
-                if (!parse_contains("default", doc, n)) {
-                    gchar *s = parse_string(doc, n);
+            if ((n = obt_parse_find_node(app->children, "layer")))
+                if (!obt_parse_node_contains(n, "default")) {
+                    gchar *s = obt_parse_node_string(n);
                     if (!g_ascii_strcasecmp(s, "above"))
                         settings->layer = 1;
                     else if (!g_ascii_strcasecmp(s, "below"))
@@ -304,25 +299,25 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
                     g_free(s);
                 }
 
-            if ((n = parse_find_node("iconic", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->iconic = parse_bool(doc, n);
+            if ((n = obt_parse_find_node(app->children, "iconic")))
+                if (!obt_parse_node_contains(n, "default"))
+                    settings->iconic = obt_parse_node_bool(n);
 
-            if ((n = parse_find_node("skip_pager", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->skip_pager = parse_bool(doc, n);
+            if ((n = obt_parse_find_node(app->children, "skip_pager")))
+                if (!obt_parse_node_contains(n, "default"))
+                    settings->skip_pager = obt_parse_node_bool(n);
 
-            if ((n = parse_find_node("skip_taskbar", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->skip_taskbar = parse_bool(doc, n);
+            if ((n = obt_parse_find_node(app->children, "skip_taskbar")))
+                if (!obt_parse_node_contains(n, "default"))
+                    settings->skip_taskbar = obt_parse_node_bool(n);
 
-            if ((n = parse_find_node("fullscreen", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->fullscreen = parse_bool(doc, n);
+            if ((n = obt_parse_find_node(app->children, "fullscreen")))
+                if (!obt_parse_node_contains(n, "default"))
+                    settings->fullscreen = obt_parse_node_bool(n);
 
-            if ((n = parse_find_node("maximized", app->children)))
-                if (!parse_contains("default", doc, n)) {
-                    gchar *s = parse_string(doc, n);
+            if ((n = obt_parse_find_node(app->children, "maximized")))
+                if (!obt_parse_node_contains(n, "default")) {
+                    gchar *s = obt_parse_node_string(n);
                     if (!g_ascii_strcasecmp(s, "horizontal")) {
                         settings->max_horz = TRUE;
                         settings->max_vert = FALSE;
@@ -331,7 +326,7 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
                         settings->max_vert = TRUE;
                     } else
                         settings->max_horz = settings->max_vert =
-                            parse_bool(doc, n);
+                            obt_parse_node_bool(n);
                     g_free(s);
                 }
 
@@ -343,7 +338,7 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
             name = class = role = NULL;
         }
 
-        app = parse_find_node("application", app->next);
+        app = obt_parse_find_node(app->next, "application");
     }
 }
 
@@ -357,34 +352,33 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
 
 */
 
-static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                      GList *keylist)
+static void parse_key(xmlNodePtr node, GList *keylist)
 {
     gchar *key;
     xmlNodePtr n;
     gboolean is_chroot = FALSE;
 
-    if (!parse_attr_string("key", node, &key))
+    if (!obt_parse_attr_string(node, "key", &key))
         return;
 
-    parse_attr_bool("chroot", node, &is_chroot);
+    obt_parse_attr_bool(node, "chroot", &is_chroot);
 
     keylist = g_list_append(keylist, key);
 
-    if ((n = parse_find_node("keybind", node->children))) {
+    if ((n = obt_parse_find_node(node->children, "keybind"))) {
         while (n) {
-            parse_key(i, doc, n, keylist);
-            n = parse_find_node("keybind", n->next);
+            parse_key(n, keylist);
+            n = obt_parse_find_node(n->next, "keybind");
         }
     }
-    else if ((n = parse_find_node("action", node->children))) {
+    else if ((n = obt_parse_find_node(node->children, "action"))) {
         while (n) {
             ObActionsAct *action;
 
-            action = actions_parse(i, doc, n);
+            action = actions_parse(n);
             if (action)
                 keyboard_bind(keylist, action);
-            n = parse_find_node("action", n->next);
+            n = obt_parse_find_node(n->next, "action");
         }
     }
 
@@ -395,25 +389,24 @@ static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
     keylist = g_list_delete_link(keylist, g_list_last(keylist));
 }
 
-static void parse_keyboard(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                           gpointer data)
+static void parse_keyboard(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
     gchar *key;
 
     keyboard_unbind_all();
 
-    if ((n = parse_find_node("chainQuitKey", node->children))) {
-        key = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node->children, "chainQuitKey"))) {
+        key = obt_parse_node_string(n);
         translate_key(key, &config_keyboard_reset_state,
                       &config_keyboard_reset_keycode);
         g_free(key);
     }
 
-    if ((n = parse_find_node("keybind", node->children)))
+    if ((n = obt_parse_find_node(node->children, "keybind")))
         while (n) {
-            parse_key(i, doc, n, NULL);
-            n = parse_find_node("keybind", n->next);
+            parse_key(n, NULL);
+            n = obt_parse_find_node(n->next, "keybind");
         }
 }
 
@@ -427,8 +420,7 @@ static void parse_keyboard(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
 
 */
 
-static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                        gpointer data)
+static void parse_mouse(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n, nbut, nact;
     gchar *buttonstr;
@@ -439,141 +431,137 @@ static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
 
     node = node->children;
 
-    if ((n = parse_find_node("dragThreshold", node)))
-        config_mouse_threshold = parse_int(doc, n);
-    if ((n = parse_find_node("doubleClickTime", node)))
-        config_mouse_dclicktime = parse_int(doc, n);
-    if ((n = parse_find_node("screenEdgeWarpTime", node)))
-        config_mouse_screenedgetime = parse_int(doc, n);
+    if ((n = obt_parse_find_node(node, "dragThreshold")))
+        config_mouse_threshold = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "doubleClickTime")))
+        config_mouse_dclicktime = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "screenEdgeWarpTime")))
+        config_mouse_screenedgetime = obt_parse_node_int(n);
 
-    n = parse_find_node("context", node);
+    n = obt_parse_find_node(node, "context");
     while (n) {
-        if (!parse_attr_string("name", n, &contextstr))
+        if (!obt_parse_attr_string(n, "name", &contextstr))
             goto next_n;
-        nbut = parse_find_node("mousebind", n->children);
+        nbut = obt_parse_find_node(n->children, "mousebind");
         while (nbut) {
-            if (!parse_attr_string("button", nbut, &buttonstr))
+            if (!obt_parse_attr_string(nbut, "button", &buttonstr))
                 goto next_nbut;
-            if (parse_attr_contains("press", nbut, "action")) {
+            if (obt_parse_attr_contains(nbut, "action", "press")) {
                 mact = OB_MOUSE_ACTION_PRESS;
-            } else if (parse_attr_contains("release", nbut, "action")) {
+            } else if (obt_parse_attr_contains(nbut, "action", "release")) {
                 mact = OB_MOUSE_ACTION_RELEASE;
-            } else if (parse_attr_contains("click", nbut, "action")) {
+            } else if (obt_parse_attr_contains(nbut, "action", "click")) {
                 mact = OB_MOUSE_ACTION_CLICK;
-            } else if (parse_attr_contains("doubleclick", nbut,"action")) {
+            } else if (obt_parse_attr_contains(nbut, "action","doubleclick")) {
                 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
-            } else if (parse_attr_contains("drag", nbut, "action")) {
+            } else if (obt_parse_attr_contains(nbut, "action", "drag")) {
                 mact = OB_MOUSE_ACTION_MOTION;
             } else
                 goto next_nbut;
-            nact = parse_find_node("action", nbut->children);
+            nact = obt_parse_find_node(nbut->children, "action");
             while (nact) {
                 ObActionsAct *action;
 
-                if ((action = actions_parse(i, doc, nact)))
+                if ((action = actions_parse(nact)))
                     mouse_bind(buttonstr, contextstr, mact, action);
-                nact = parse_find_node("action", nact->next);
+                nact = obt_parse_find_node(nact->next, "action");
             }
             g_free(buttonstr);
         next_nbut:
-            nbut = parse_find_node("mousebind", nbut->next);
+            nbut = obt_parse_find_node(nbut->next, "mousebind");
         }
         g_free(contextstr);
     next_n:
-        n = parse_find_node("context", n->next);
+        n = obt_parse_find_node(n->next, "context");
     }
 }
 
-static void parse_focus(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                        gpointer data)
+static void parse_focus(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("focusNew", node)))
-        config_focus_new = parse_bool(doc, n);
-    if ((n = parse_find_node("followMouse", node)))
-        config_focus_follow = parse_bool(doc, n);
-    if ((n = parse_find_node("focusDelay", node)))
-        config_focus_delay = parse_int(doc, n);
-    if ((n = parse_find_node("raiseOnFocus", node)))
-        config_focus_raise = parse_bool(doc, n);
-    if ((n = parse_find_node("focusLast", node)))
-        config_focus_last = parse_bool(doc, n);
-    if ((n = parse_find_node("underMouse", node)))
-        config_focus_under_mouse = parse_bool(doc, n);
+    if ((n = obt_parse_find_node(node, "focusNew")))
+        config_focus_new = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "followMouse")))
+        config_focus_follow = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "focusDelay")))
+        config_focus_delay = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "raiseOnFocus")))
+        config_focus_raise = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "focusLast")))
+        config_focus_last = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "underMouse")))
+        config_focus_under_mouse = obt_parse_node_bool(n);
 }
 
-static void parse_placement(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                            gpointer data)
+static void parse_placement(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("policy", node)))
-        if (parse_contains("UnderMouse", doc, n))
+    if ((n = obt_parse_find_node(node, "policy")))
+        if (obt_parse_node_contains(n, "UnderMouse"))
             config_place_policy = OB_PLACE_POLICY_MOUSE;
-    if ((n = parse_find_node("center", node)))
-        config_place_center = parse_bool(doc, n);
-    if ((n = parse_find_node("monitor", node))) {
-        if (parse_contains("active", doc, n))
+    if ((n = obt_parse_find_node(node, "center")))
+        config_place_center = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "monitor"))) {
+        if (obt_parse_node_contains(n, "active"))
             config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
-        else if (parse_contains("mouse", doc, n))
+        else if (obt_parse_node_contains(n, "mouse"))
             config_place_monitor = OB_PLACE_MONITOR_MOUSE;
     }
 }
 
-static void parse_margins(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                          gpointer data)
+static void parse_margins(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("top", node)))
-        config_margins.top = MAX(0, parse_int(doc, n));
-    if ((n = parse_find_node("left", node)))
-        config_margins.left = MAX(0, parse_int(doc, n));
-    if ((n = parse_find_node("right", node)))
-        config_margins.right = MAX(0, parse_int(doc, n));
-    if ((n = parse_find_node("bottom", node)))
-        config_margins.bottom = MAX(0, parse_int(doc, n));
+    if ((n = obt_parse_find_node(node, "top")))
+        config_margins.top = MAX(0, obt_parse_node_int(n));
+    if ((n = obt_parse_find_node(node, "left")))
+        config_margins.left = MAX(0, obt_parse_node_int(n));
+    if ((n = obt_parse_find_node(node, "right")))
+        config_margins.right = MAX(0, obt_parse_node_int(n));
+    if ((n = obt_parse_find_node(node, "bottom")))
+        config_margins.bottom = MAX(0, obt_parse_node_int(n));
 }
 
-static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                        gpointer data)
+static void parse_theme(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("name", node))) {
+    if ((n = obt_parse_find_node(node, "name"))) {
         gchar *c;
 
         g_free(config_theme);
-        c = parse_string(doc, n);
-        config_theme = parse_expand_tilde(c);
+        c = obt_parse_node_string(n);
+        config_theme = obt_paths_expand_tilde(c);
         g_free(c);
     }
-    if ((n = parse_find_node("titleLayout", node))) {
+    if ((n = obt_parse_find_node(node, "titleLayout"))) {
         gchar *c, *d;
 
         g_free(config_title_layout);
-        config_title_layout = parse_string(doc, n);
+        config_title_layout = obt_parse_node_string(n);
 
         /* replace duplicates with spaces */
         for (c = config_title_layout; *c != '\0'; ++c)
             for (d = c+1; *d != '\0'; ++d)
                 if (*c == *d) *d = ' ';
     }
-    if ((n = parse_find_node("keepBorder", node)))
-        config_theme_keepborder = parse_bool(doc, n);
-    if ((n = parse_find_node("animateIconify", node)))
-        config_animate_iconify = parse_bool(doc, n);
+    if ((n = obt_parse_find_node(node, "keepBorder")))
+        config_theme_keepborder = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "animateIconify")))
+        config_animate_iconify = obt_parse_node_bool(n);
 
-    n = parse_find_node("font", node);
+    n = obt_parse_find_node(node, "font");
     while (n) {
         xmlNodePtr   fnode;
         RrFont     **font;
@@ -582,35 +570,35 @@ static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         RrFontWeight weight = RrDefaultFontWeight;
         RrFontSlant  slant = RrDefaultFontSlant;
 
-        if (parse_attr_contains("ActiveWindow", n, "place"))
+        if (obt_parse_attr_contains(n, "place", "ActiveWindow"))
             font = &config_font_activewindow;
-        else if (parse_attr_contains("InactiveWindow", n, "place"))
+        else if (obt_parse_attr_contains(n, "place", "InactiveWindow"))
             font = &config_font_inactivewindow;
-        else if (parse_attr_contains("MenuHeader", n, "place"))
+        else if (obt_parse_attr_contains(n, "place", "MenuHeader"))
             font = &config_font_menutitle;
-        else if (parse_attr_contains("MenuItem", n, "place"))
+        else if (obt_parse_attr_contains(n, "place", "MenuItem"))
             font = &config_font_menuitem;
-        else if (parse_attr_contains("OnScreenDisplay", n, "place"))
+        else if (obt_parse_attr_contains(n, "place", "OnScreenDisplay"))
             font = &config_font_osd;
         else
             goto next_font;
 
-        if ((fnode = parse_find_node("name", n->children))) {
+        if ((fnode = obt_parse_find_node(n->children, "name"))) {
             g_free(name);
-            name = parse_string(doc, fnode);
+            name = obt_parse_node_string(fnode);
         }
-        if ((fnode = parse_find_node("size", n->children))) {
-            int s = parse_int(doc, fnode);
+        if ((fnode = obt_parse_find_node(n->children, "size"))) {
+            int s = obt_parse_node_int(fnode);
             if (s > 0) size = s;
         }
-        if ((fnode = parse_find_node("weight", n->children))) {
-            gchar *w = parse_string(doc, fnode);
+        if ((fnode = obt_parse_find_node(n->children, "weight"))) {
+            gchar *w = obt_parse_node_string(fnode);
             if (!g_ascii_strcasecmp(w, "Bold"))
                 weight = RR_FONTWEIGHT_BOLD;
             g_free(w);
         }
-        if ((fnode = parse_find_node("slant", n->children))) {
-            gchar *s = parse_string(doc, fnode);
+        if ((fnode = obt_parse_find_node(n->children, "slant"))) {
+            gchar *s = obt_parse_node_string(fnode);
             if (!g_ascii_strcasecmp(s, "Italic"))
                 slant = RR_FONTSLANT_ITALIC;
             if (!g_ascii_strcasecmp(s, "Oblique"))
@@ -621,28 +609,27 @@ static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
         g_free(name);
     next_font:
-        n = parse_find_node("font", n->next);
+        n = obt_parse_find_node(n->next, "font");
     }
 }
 
-static void parse_desktops(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                           gpointer data)
+static void parse_desktops(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("number", node))) {
-        gint d = parse_int(doc, n);
+    if ((n = obt_parse_find_node(node, "number"))) {
+        gint d = obt_parse_node_int(n);
         if (d > 0)
             config_desktops_num = (unsigned) d;
     }
-    if ((n = parse_find_node("firstdesk", node))) {
-        gint d = parse_int(doc, n);
+    if ((n = obt_parse_find_node(node, "firstdesk"))) {
+        gint d = obt_parse_node_int(n);
         if (d > 0)
             config_screen_firstdesk = (unsigned) d;
     }
-    if ((n = parse_find_node("names", node))) {
+    if ((n = obt_parse_find_node(node, "names"))) {
         GSList *it;
         xmlNodePtr nname;
 
@@ -651,51 +638,51 @@ static void parse_desktops(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         g_slist_free(config_desktops_names);
         config_desktops_names = NULL;
 
-        nname = parse_find_node("name", n->children);
+        nname = obt_parse_find_node(n->children, "name");
         while (nname) {
-            config_desktops_names = g_slist_append(config_desktops_names,
-                                                   parse_string(doc, nname));
-            nname = parse_find_node("name", nname->next);
+            config_desktops_names =
+                g_slist_append(config_desktops_names,
+                               obt_parse_node_string(nname));
+            nname = obt_parse_find_node(nname->next, "name");
         }
     }
-    if ((n = parse_find_node("popupTime", node)))
-        config_desktop_popup_time = parse_int(doc, n);
+    if ((n = obt_parse_find_node(node, "popupTime")))
+        config_desktop_popup_time = obt_parse_node_int(n);
 }
 
-static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                         gpointer data)
+static void parse_resize(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("drawContents", node)))
-        config_resize_redraw = parse_bool(doc, n);
-    if ((n = parse_find_node("popupShow", node))) {
-        config_resize_popup_show = parse_int(doc, n);
-        if (parse_contains("Always", doc, n))
+    if ((n = obt_parse_find_node(node, "drawContents")))
+        config_resize_redraw = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "popupShow"))) {
+        config_resize_popup_show = obt_parse_node_int(n);
+        if (obt_parse_node_contains(n, "Always"))
             config_resize_popup_show = 2;
-        else if (parse_contains("Never", doc, n))
+        else if (obt_parse_node_contains(n, "Never"))
             config_resize_popup_show = 0;
-        else if (parse_contains("Nonpixel", doc, n))
+        else if (obt_parse_node_contains(n, "Nonpixel"))
             config_resize_popup_show = 1;
     }
-    if ((n = parse_find_node("popupPosition", node))) {
-        if (parse_contains("Top", doc, n))
+    if ((n = obt_parse_find_node(node, "popupPosition"))) {
+        if (obt_parse_node_contains(n, "Top"))
             config_resize_popup_pos = OB_RESIZE_POS_TOP;
-        else if (parse_contains("Center", doc, n))
+        else if (obt_parse_node_contains(n, "Center"))
             config_resize_popup_pos = OB_RESIZE_POS_CENTER;
-        else if (parse_contains("Fixed", doc, n)) {
+        else if (obt_parse_node_contains(n, "Fixed")) {
             config_resize_popup_pos = OB_RESIZE_POS_FIXED;
 
-            if ((n = parse_find_node("popupFixedPosition", node))) {
+            if ((n = obt_parse_find_node(node, "popupFixedPosition"))) {
                 xmlNodePtr n2;
 
-                if ((n2 = parse_find_node("x", n->children)))
-                    config_parse_gravity_coord(doc, n2,
+                if ((n2 = obt_parse_find_node(n->children, "x")))
+                    config_parse_gravity_coord(n2,
                                                &config_resize_popup_fixed.x);
-                if ((n2 = parse_find_node("y", n->children)))
-                    config_parse_gravity_coord(doc, n2,
+                if ((n2 = obt_parse_find_node(n->children, "y")))
+                    config_parse_gravity_coord(n2,
                                                &config_resize_popup_fixed.y);
 
                 config_resize_popup_fixed.x.pos =
@@ -707,72 +694,71 @@ static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
     }
 }
 
-static void parse_dock(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                       gpointer data)
+static void parse_dock(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("position", node))) {
-        if (parse_contains("TopLeft", doc, n))
+    if ((n = obt_parse_find_node(node, "position"))) {
+        if (obt_parse_node_contains(n, "TopLeft"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_NORTHWEST;
-        else if (parse_contains("Top", doc, n))
+        else if (obt_parse_node_contains(n, "Top"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_NORTH;
-        else if (parse_contains("TopRight", doc, n))
+        else if (obt_parse_node_contains(n, "TopRight"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_NORTHEAST;
-        else if (parse_contains("Right", doc, n))
+        else if (obt_parse_node_contains(n, "Right"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_EAST;
-        else if (parse_contains("BottomRight", doc, n))
+        else if (obt_parse_node_contains(n, "BottomRight"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_SOUTHEAST;
-        else if (parse_contains("Bottom", doc, n))
+        else if (obt_parse_node_contains(n, "Bottom"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_SOUTH;
-        else if (parse_contains("BottomLeft", doc, n))
+        else if (obt_parse_node_contains(n, "BottomLeft"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_SOUTHWEST;
-        else if (parse_contains("Left", doc, n))
+        else if (obt_parse_node_contains(n, "Left"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_WEST;
-        else if (parse_contains("Floating", doc, n))
+        else if (obt_parse_node_contains(n, "Floating"))
             config_dock_floating = TRUE;
     }
     if (config_dock_floating) {
-        if ((n = parse_find_node("floatingX", node)))
-            config_dock_x = parse_int(doc, n);
-        if ((n = parse_find_node("floatingY", node)))
-            config_dock_y = parse_int(doc, n);
+        if ((n = obt_parse_find_node(node, "floatingX")))
+            config_dock_x = obt_parse_node_int(n);
+        if ((n = obt_parse_find_node(node, "floatingY")))
+            config_dock_y = obt_parse_node_int(n);
     } else {
-        if ((n = parse_find_node("noStrut", node)))
-            config_dock_nostrut = parse_bool(doc, n);
+        if ((n = obt_parse_find_node(node, "noStrut")))
+            config_dock_nostrut = obt_parse_node_bool(n);
     }
-    if ((n = parse_find_node("stacking", node))) {
-        if (parse_contains("above", doc, n))
-            config_dock_layer = OB_STACKING_LAYER_ABOVE;
-        else if (parse_contains("normal", doc, n))
+    if ((n = obt_parse_find_node(node, "stacking"))) {
+        if (obt_parse_node_contains(n, "normal"))
             config_dock_layer = OB_STACKING_LAYER_NORMAL;
-        else if (parse_contains("below", doc, n))
+        else if (obt_parse_node_contains(n, "below"))
             config_dock_layer = OB_STACKING_LAYER_BELOW;
+        else if (obt_parse_node_contains(n, "above"))
+            config_dock_layer = OB_STACKING_LAYER_ABOVE;
     }
-    if ((n = parse_find_node("direction", node))) {
-        if (parse_contains("horizontal", doc, n))
+    if ((n = obt_parse_find_node(node, "direction"))) {
+        if (obt_parse_node_contains(n, "horizontal"))
             config_dock_orient = OB_ORIENTATION_HORZ;
-        else if (parse_contains("vertical", doc, n))
+        else if (obt_parse_node_contains(n, "vertical"))
             config_dock_orient = OB_ORIENTATION_VERT;
     }
-    if ((n = parse_find_node("autoHide", node)))
-        config_dock_hide = parse_bool(doc, n);
-    if ((n = parse_find_node("hideDelay", node)))
-        config_dock_hide_delay = parse_int(doc, n);
-    if ((n = parse_find_node("showDelay", node)))
-        config_dock_show_delay = parse_int(doc, n);
-    if ((n = parse_find_node("moveButton", node))) {
-        gchar *str = parse_string(doc, n);
+    if ((n = obt_parse_find_node(node, "autoHide")))
+        config_dock_hide = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "hideDelay")))
+        config_dock_hide_delay = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "showDelay")))
+        config_dock_show_delay = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "moveButton"))) {
+        gchar *str = obt_parse_node_string(n);
         guint b, s;
         if (translate_button(str, &s, &b)) {
             config_dock_app_move_button = b;
@@ -784,42 +770,40 @@ static void parse_dock(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
     }
 }
 
-static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                       gpointer data)
+static void parse_menu(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
     for (node = node->children; node; node = node->next) {
         if (!xmlStrcasecmp(node->name, (const xmlChar*) "file")) {
             gchar *c;
 
-            c = parse_string(doc, node);
+            c = obt_parse_node_string(node);
             config_menu_files = g_slist_append(config_menu_files,
-    &