Merge branch 'backport' into work
authorDana Jansens <danakj@orodu.net>
Thu, 7 Feb 2008 07:06:42 +0000 (02:06 -0500)
committerDana Jansens <danakj@orodu.net>
Thu, 7 Feb 2008 07:06:42 +0000 (02:06 -0500)
Conflicts:

openbox/config.c

1  2 
data/rc.xml
openbox/client.h
openbox/config.c
openbox/config.h
openbox/event.c
openbox/focus.c
openbox/menuframe.c
openbox/openbox.c
openbox/place.c
openbox/stacking.c
render/theme.c

diff --combined data/rc.xml
      </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>
    <!-- default menu file (or custom one in $HOME/.config/openbox/) -->
    <file>menu.xml</file>
    <hideDelay>200</hideDelay>
+   <!-- if a press-release lasts longer than this setting (in milliseconds), the
+        menu is hidden again -->
    <middle>no</middle>
+   <!-- center submenus vertically about the parent entry -->
    <submenuShowDelay>100</submenuShowDelay>
+   <!-- this one is easy, time to delay before showing a submenu after hovering
+        over the parent entry -->
    <applicationIcons>yes</applicationIcons>
+   <!-- controls if icons appear in the client-list-(combined-)menu -->
+   <manageDesktops>yes</manageDesktops>
+   <!-- show the manage desktops section in the client-list-(combined-)menu -->
  </menu>
  
  <applications>
      <shade>no</shade>
      # make the window shaded when it appears, or not
  
-     <position>
+     <position force="no">
        # the position is only used if both an x and y coordinate are provided
        # (and not set to 'default')
+       # when force is "yes", then the window will be placed here even if it
+       # says you want it placed elsewhere.  this is to override buggy
+       # applications who refuse to behave
        <x>center</x>
        # a number like 50, or 'center' to center on screen. use a negative number
        # to start from the right (or bottom for <y>), ie -50 is 50 pixels from the
diff --combined openbox/client.h
@@@ -322,7 -322,10 +322,7 @@@ typedef void (*ObClientCallback)(ObClie
  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
 -*/
 +/*! Manages a given window */
  void client_manage(Window win);
  /*! Unmanages all managed windows */
  void client_unmanage_all();
@@@ -688,7 -691,9 +688,9 @@@ ObClient *client_direct_parent(ObClien
  */
  ObClient *client_search_top_direct_parent(ObClient *self);
  
- /*! Is one client a direct child of another (i.e. not through the group.) */
+ /*! Is one client a direct child of another (i.e. not through the group.)
+   This checks more than one level, so there may be another direct child in
+   between */
  gboolean client_is_direct_child(ObClient *parent, ObClient *child);
  
  /*! Search for a parent of a client. This only searches up *ONE LEVEL*, and
diff --combined openbox/config.c
  #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;
@@@ -88,6 -89,7 +88,7 @@@ guint    config_menu_hide_delay
  gboolean config_menu_middle;
  guint    config_submenu_show_delay;
  gboolean config_menu_client_list_icons;
+ gboolean config_menu_manage_desktops;
  
  GSList *config_menu_files;
  
@@@ -136,14 -138,16 +137,15 @@@ void config_app_settings_copy_non_defau
  
      if (src->pos_given) {
          dst->pos_given = TRUE;
+         dst->pos_force = src->pos_force;
          dst->position = src->position;
          dst->monitor = src->monitor;
      }
  }
  
 -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 {
     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;
      gboolean name_set, class_set;
      gboolean x_pos_given;
      while (app) {
          name_set = class_set = x_pos_given = FALSE;
  
 -        class_set = parse_attr_string("class", app, &class);
 -        name_set = parse_attr_string("name", app, &name);
 +        class_set = obt_parse_attr_string(app, "class", &class);
 +        name_set = obt_parse_attr_string(app, "name", &name);
          if (class_set || name_set) {
              xmlNodePtr n, c;
              ObAppSettings *settings = config_create_app_settings();;
              if (class_set)
                  settings->class = g_pattern_spec_new(class);
  
 -            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;
                      }
                  }
              }
  
 -            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"))
                      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;
                          settings->max_vert = TRUE;
                      } else
                          settings->max_horz = settings->max_vert =
 -                            parse_bool(doc, n);
 +                            obt_parse_node_bool(n);
                      g_free(s);
                  }
  
              name = class = role = NULL;
          }
  
 -        app = parse_find_node("application", app->next);
 +        app = obt_parse_find_node(app->next, "application");
      }
  }
  
  
  */
  
 -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");
          }
      }
  
      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");
          }
  }
  
  
  */
  
 -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;
  
      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;
          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"))
          *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;
  
          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);
              }
          }
      }
  }
  
 -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;
      }
  }
  
 -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,
 -                                               parse_expand_tilde(c));
 +                                               obt_paths_expand_tilde(c));
              g_free(c);
          }
 -        if ((n = parse_find_node("hideDelay", node)))
 -            config_menu_hide_delay = parse_int(doc, n);
 -        if ((n = parse_find_node("middle", node)))
 -            config_menu_middle = parse_bool(doc, n);
 -        if ((n = parse_find_node("submenuShowDelay", node)))
 -            config_submenu_show_delay = parse_int(doc, n);
 -        if ((n = parse_find_node("applicationIcons", node)))
 -            config_menu_client_list_icons = parse_bool(doc, n);
 -        if ((n = parse_find_node("manageDesktops", node)))
 -            config_menu_manage_desktops = parse_bool(doc, n);
 +        if ((n = obt_parse_find_node(node, "hideDelay")))
 +            config_menu_hide_delay = obt_parse_node_int(n);
 +        if ((n = obt_parse_find_node(node, "middle")))
 +            config_menu_middle = obt_parse_node_bool(n);
 +        if ((n = obt_parse_find_node(node, "submenuShowDelay")))
 +            config_submenu_show_delay = obt_parse_node_int(n);
 +        if ((n = obt_parse_find_node(node, "applicationIcons")))
 +            config_menu_client_list_icons = obt_parse_node_bool(n);
++        if ((n = obt_parse_find_node(node, "manageDesktops")))
++            config_menu_manage_desktops = obt_parse_node_bool(n);
      }
  }
  
 -static void parse_resistance(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
 -                             gpointer data)
 +static void parse_resistance(xmlNodePtr node, gpointer d)
  {
      xmlNodePtr n;
  
      node = node->children;
 -    if ((n = parse_find_node("strength", node)))
 -        config_resist_win = parse_int(doc, n);
 -    if ((n = parse_find_node("screen_edge_strength", node)))
 -        config_resist_edge = parse_int(doc, n);
 +    if ((n = obt_parse_find_node(node, "strength")))
 +        config_resist_win = obt_parse_node_int(n);
 +    if ((n = obt_parse_find_node(node, "screen_edge_strength")))
 +        config_resist_edge = obt_parse_node_int(n);
  }
  
  typedef struct
@@@ -861,7 -883,7 +867,7 @@@ static void bind_default_mouse(void
                     actions_parse_string(it->actname));
  }
  
 -void config_startup(ObParseInst *i)
 +void config_startup(ObtParseInst *i)
  {
      config_focus_new = TRUE;
      config_focus_follow = FALSE;
      config_focus_last = TRUE;
      config_focus_under_mouse = FALSE;
  
 -    parse_register(i, "focus", parse_focus, NULL);
 +    obt_parse_register(i, "focus", parse_focus, NULL);
  
      config_place_policy = OB_PLACE_POLICY_SMART;
      config_place_center = TRUE;
      config_place_monitor = OB_PLACE_MONITOR_ANY;
  
 -    parse_register(i, "placement", parse_placement, NULL);
 +    obt_parse_register(i, "placement", parse_placement, NULL);
  
      STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  
 -    parse_register(i, "margins", parse_margins, NULL);
 +    obt_parse_register(i, "margins", parse_margins, NULL);
  
      config_theme = NULL;
  
      config_font_menuitem = NULL;
      config_font_menutitle = NULL;
  
 -    parse_register(i, "theme", parse_theme, NULL);
 +    obt_parse_register(i, "theme", parse_theme, NULL);
  
      config_desktops_num = 4;
      config_screen_firstdesk = 1;
      config_desktops_names = NULL;
      config_desktop_popup_time = 875;
  
 -    parse_register(i, "desktops", parse_desktops, NULL);
 +    obt_parse_register(i, "desktops", parse_desktops, NULL);
  
      config_resize_redraw = TRUE;
      config_resize_popup_show = 1; /* nonpixel increments */
      GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
      GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
  
 -    parse_register(i, "resize", parse_resize, NULL);
 +    obt_parse_register(i, "resize", parse_resize, NULL);
  
      config_dock_layer = OB_STACKING_LAYER_ABOVE;
      config_dock_pos = OB_DIRECTION_NORTHEAST;
      config_dock_app_move_button = 2; /* middle */
      config_dock_app_move_modifiers = 0;
  
 -    parse_register(i, "dock", parse_dock, NULL);
 +    obt_parse_register(i, "dock", parse_dock, NULL);
  
      translate_key("C-g", &config_keyboard_reset_state,
                    &config_keyboard_reset_keycode);
  
      bind_default_keyboard();
  
 -    parse_register(i, "keyboard", parse_keyboard, NULL);
 +    obt_parse_register(i, "keyboard", parse_keyboard, NULL);
  
      config_mouse_threshold = 8;
      config_mouse_dclicktime = 200;
  
      bind_default_mouse();
  
 -    parse_register(i, "mouse", parse_mouse, NULL);
 +    obt_parse_register(i, "mouse", parse_mouse, NULL);
  
      config_resist_win = 10;
      config_resist_edge = 20;
  
 -    parse_register(i, "resistance", parse_resistance, NULL);
 +    obt_parse_register(i, "resistance", parse_resistance, NULL);
  
      config_menu_hide_delay = 250;
      config_menu_middle = FALSE;
      config_submenu_show_delay = 0;
      config_menu_client_list_icons = TRUE;
+     config_menu_manage_desktops = TRUE;
      config_menu_files = NULL;
  
 -    parse_register(i, "menu", parse_menu, NULL);
 +    obt_parse_register(i, "menu", parse_menu, NULL);
  
      config_per_app_settings = NULL;
  
 -    parse_register(i, "applications", parse_per_app_settings, NULL);
 +    obt_parse_register(i, "applications", parse_per_app_settings, NULL);
  }
  
  void config_shutdown(void)
diff --combined openbox/config.h
  #include "geom.h"
  #include "moveresize.h"
  #include "render/render.h"
 +#include "obt/parse.h"
  
  #include <glib.h>
  
 -struct _ObParseInst;
 -
  typedef struct _ObAppSettings ObAppSettings;
  
  struct _ObAppSettings
@@@ -40,6 -41,7 +40,7 @@@
  
      GravityPoint position;
      gboolean pos_given;
+     gboolean pos_force;
  
      guint desktop;
      gint shade;
@@@ -175,14 -177,16 +176,16 @@@ extern guint    config_menu_hide_delay
  extern gboolean config_menu_middle;
  /*! Delay before opening a submenu in milliseconds */
  extern guint    config_submenu_show_delay;
- /*! show icons in client_list_menu */
+ /*! Show icons in client_list_menu */
  extern gboolean config_menu_client_list_icons;
+ /*! Show manage desktops in client_list_menu */
+ extern gboolean config_menu_manage_desktops;
  /*! User-specified menu files */
  extern GSList *config_menu_files;
  /*! Per app settings */
  extern GSList *config_per_app_settings;
  
 -void config_startup(struct _ObParseInst *i);
 +void config_startup(ObtParseInst *i);
  void config_shutdown();
  
  /*! Create an ObAppSettings structure with the default values */
diff --combined openbox/event.c
@@@ -24,6 -24,8 +24,6 @@@
  #include "dock.h"
  #include "actions.h"
  #include "client.h"
 -#include "xerror.h"
 -#include "prop.h"
  #include "config.h"
  #include "screen.h"
  #include "frame.h"
  #include "menu.h"
  #include "menuframe.h"
  #include "keyboard.h"
 -#include "modkeys.h"
  #include "mouse.h"
 -#include "mainloop.h"
  #include "focus.h"
  #include "focus_cycle.h"
  #include "moveresize.h"
  #include "group.h"
  #include "stacking.h"
 -#include "extensions.h"
 -#include "translate.h"
  #include "ping.h"
 +#include "obt/display.h"
 +#include "obt/prop.h"
 +#include "obt/keyboard.h"
  
  #include <X11/Xlib.h>
  #include <X11/Xatom.h>
@@@ -83,13 -86,13 +83,13 @@@ typedef struc
  
  static void event_process(const XEvent *e, gpointer data);
  static void event_handle_root(XEvent *e);
 -static gboolean event_handle_menu_keyboard(XEvent *e);
 -static gboolean event_handle_menu(XEvent *e);
 +static gboolean event_handle_menu_input(XEvent *e);
 +static void event_handle_menu(ObMenuFrame *frame, XEvent *e);
  static void event_handle_dock(ObDock *s, XEvent *e);
  static void event_handle_dockapp(ObDockApp *app, XEvent *e);
  static void event_handle_client(ObClient *c, XEvent *e);
  static void event_handle_user_input(ObClient *client, XEvent *e);
- static gboolean is_enter_focus_event_ignored(XEvent *e);
+ static gboolean is_enter_focus_event_ignored(gulong serial);
  static void event_ignore_enter_range(gulong start, gulong end);
  
  static void focus_delay_dest(gpointer data);
@@@ -120,9 -123,9 +120,9 @@@ static void ice_watch(IceConn conn, Ice
  
      if (opening) {
          fd = IceConnectionNumber(conn);
 -        ob_main_loop_fd_add(ob_main_loop, fd, ice_handler, conn, NULL);
 +        obt_main_loop_fd_add(ob_main_loop, fd, ice_handler, conn, NULL);
      } else {
 -        ob_main_loop_fd_remove(ob_main_loop, fd);
 +        obt_main_loop_fd_remove(ob_main_loop, fd);
          fd = -1;
      }
  }
@@@ -132,7 -135,7 +132,7 @@@ void event_startup(gboolean reconfig
  {
      if (reconfig) return;
  
 -    ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
 +    obt_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
  
  #ifdef USE_SM
      IceAddConnectionWatch(ice_watch, NULL);
@@@ -159,15 -162,9 +159,15 @@@ static Window event_get_window(XEvent *
      /* pick a window */
      switch (e->type) {
      case SelectionClear:
 -        window = RootWindow(ob_display, ob_screen);
 +        window = obt_root(ob_screen);
 +        break;
 +    case CreateNotify:
 +        window = e->xcreatewindow.window;
          break;
      case MapRequest:
 +        window = e->xmaprequest.window;
 +        break;
 +    case MapNotify:
          window = e->xmap.window;
          break;
      case UnmapNotify:
          break;
      default:
  #ifdef XKB
 -        if (extensions_xkb && e->type == extensions_xkb_event_basep) {
 +        if (obt_display_extension_xkb &&
 +            e->type == obt_display_extension_xkb_basep)
 +        {
              switch (((XkbAnyEvent*)e)->xkb_type) {
              case XkbBellNotify:
                  window = ((XkbBellNotifyEvent*)e)->window;
          } else
  #endif
  #ifdef SYNC
 -        if (extensions_sync &&
 -            e->type == extensions_sync_event_basep + XSyncAlarmNotify)
 +        if (obt_display_extension_sync &&
 +            e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
          {
              window = None;
          } else
@@@ -235,8 -230,8 +235,8 @@@ static void event_set_curtime(XEvent *e
          break;
      default:
  #ifdef SYNC
 -        if (extensions_sync &&
 -            e->type == extensions_sync_event_basep + XSyncAlarmNotify)
 +        if (obt_display_extension_sync &&
 +            e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
          {
              t = ((XSyncAlarmNotifyEvent*)e)->time;
          }
@@@ -264,34 -259,34 +264,34 @@@ static void event_hack_mods(XEvent *e
      switch (e->type) {
      case ButtonPress:
      case ButtonRelease:
 -        e->xbutton.state = modkeys_only_modifier_masks(e->xbutton.state);
 +        e->xbutton.state = obt_keyboard_only_modmasks(e->xbutton.state);
          break;
      case KeyPress:
 -        e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
 +        e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state);
          break;
      case KeyRelease:
  #ifdef XKB
          /* If XKB is present, then the modifiers are all strange from its
             magic.  Our X core protocol stuff won't work, so we use this to
             find what the modifier state is instead. */
 -        if (XkbGetState(ob_display, XkbUseCoreKbd, &xkb_state) == Success)
 +        if (XkbGetState(obt_display, XkbUseCoreKbd, &xkb_state) == Success)
              e->xkey.state =
 -                modkeys_only_modifier_masks(xkb_state.compat_state);
 +                obt_keyboard_only_modmasks(xkb_state.compat_state);
          else
  #endif
          {
 -            e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
 +            e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state);
              /* remove from the state the mask of the modifier key being
                 released, if it is a modifier key being released that is */
 -            e->xkey.state &= ~modkeys_keycode_to_mask(e->xkey.keycode);
 +            e->xkey.state &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode);
          }
          break;
      case MotionNotify:
 -        e->xmotion.state = modkeys_only_modifier_masks(e->xmotion.state);
 +        e->xmotion.state = obt_keyboard_only_modmasks(e->xmotion.state);
          /* compress events */
          {
              XEvent ce;
 -            while (XCheckTypedWindowEvent(ob_display, e->xmotion.window,
 +            while (XCheckTypedWindowEvent(obt_display, e->xmotion.window,
                                            e->type, &ce)) {
                  e->xmotion.x = ce.xmotion.x;
                  e->xmotion.y = ce.xmotion.y;
@@@ -321,7 -316,7 +321,7 @@@ static gboolean wanted_focusevent(XEven
  
          /* These are the ones we want.. */
  
 -        if (win == RootWindow(ob_display, ob_screen)) {
 +        if (win == obt_root(ob_screen)) {
              /* If looking for a focus in on a client, then always return
                 FALSE for focus in's to the root window */
              if (in_client_only)
             but has disappeared.
          */
          if (in_client_only) {
 -            ObWindow *w = g_hash_table_lookup(window_map, &e->xfocus.window);
 +            ObWindow *w = window_find(e->xfocus.window);
              if (!w || !WINDOW_IS_CLIENT(w))
                  return FALSE;
          }
              return FALSE;
  
          /* Focus left the root window revertedto state */
 -        if (win == RootWindow(ob_display, ob_screen))
 +        if (win == obt_root(ob_screen))
              return FALSE;
  
          /* These are the ones we want.. */
@@@ -431,7 -426,7 +431,7 @@@ static void print_focusevent(XEvent *e
  
      g_assert(modestr);
      g_assert(detailstr);
 -    ob_debug_type(OB_DEBUG_FOCUS, "Focus%s 0x%x mode=%s detail=%s\n",
 +    ob_debug_type(OB_DEBUG_FOCUS, "Focus%s 0x%x mode=%s detail=%s",
                    (e->xfocus.type == FocusIn ? "In" : "Out"),
                    win,
                    modestr, detailstr);
@@@ -457,41 -452,39 +457,41 @@@ static gboolean event_ignore(XEvent *e
  
  static void event_process(const XEvent *ec, gpointer data)
  {
 +    XEvent ee, *e;
 +    ObEventData *ed = data;
 +
      Window window;
      ObClient *client = NULL;
      ObDock *dock = NULL;
      ObDockApp *dockapp = NULL;
      ObWindow *obwin = NULL;
 -    XEvent ee, *e;
 -    ObEventData *ed = data;
 +    ObMenuFrame *menu = NULL;
  
      /* make a copy we can mangle */
      ee = *ec;
      e = &ee;
  
      window = event_get_window(e);
 -    if ((obwin = g_hash_table_lookup(window_map, &window))) {
 +    if (window == obt_root(ob_screen))
 +        /* don't do any lookups, waste of cpu */;
 +    else if ((obwin = window_find(window))) {
          switch (obwin->type) {
 -        case Window_Dock:
 +        case OB_WINDOW_CLASS_DOCK:
              dock = WINDOW_AS_DOCK(obwin);
              break;
 -        case Window_DockApp:
 -            dockapp = WINDOW_AS_DOCKAPP(obwin);
 -            break;
 -        case Window_Client:
 +        case OB_WINDOW_CLASS_CLIENT:
              client = WINDOW_AS_CLIENT(obwin);
              break;
 -        case Window_Menu:
 -            /* not to be used for events */
 -            g_assert_not_reached();
 +        case OB_WINDOW_CLASS_MENUFRAME:
 +            menu = WINDOW_AS_MENUFRAME(obwin);
              break;
 -        case Window_Internal:
 +        case OB_WINDOW_CLASS_INTERNAL:
              /* we don't do anything with events directly on these windows */
              break;
          }
      }
 +    else
 +        dockapp = dock_find_dockapp(window);
  
      event_set_curtime(e);
      event_curserial = e->xany.serial;
  
      /* deal with it in the kernel */
  
 -    if (menu_frame_visible &&
 -        (e->type == EnterNotify || e->type == LeaveNotify))
 -    {
 -        /* crossing events for menu */
 -        event_handle_menu(e);
 -    } else if (e->type == FocusIn) {
 +    if (e->type == FocusIn) {
          if (client &&
              e->xfocus.detail == NotifyInferior)
          {
              XEvent ce;
  
              ob_debug_type(OB_DEBUG_FOCUS,
 -                          "Focus went to root or pointer root/none\n");
 +                          "Focus went to root or pointer root/none");
  
              if (e->xfocus.detail == NotifyInferior ||
                  e->xfocus.detail == NotifyNonlinear)
                 But if the other focus in is something like PointerRoot then we
                 still want to fall back.
              */
 -            if (XCheckIfEvent(ob_display, &ce, event_look_for_focusin_client,
 +            if (XCheckIfEvent(obt_display, &ce, event_look_for_focusin_client,
                                NULL))
              {
 -                XPutBackEvent(ob_display, &ce);
 +                XPutBackEvent(obt_display, &ce);
                  ob_debug_type(OB_DEBUG_FOCUS,
 -                              "  but another FocusIn is coming\n");
 +                              "  but another FocusIn is coming");
              } else {
                  /* Focus has been reverted.
  
          else if (!client)
          {
              ob_debug_type(OB_DEBUG_FOCUS,
 -                          "Focus went to a window that is already gone\n");
 +                          "Focus went to a window that is already gone");
  
              /* If you send focus to a window and then it disappears, you can
                 get the FocusIn for it, after it is unmanaged.
          XEvent ce;
  
          /* Look for the followup FocusIn */
 -        if (!XCheckIfEvent(ob_display, &ce, event_look_for_focusin, NULL)) {
 +        if (!XCheckIfEvent(obt_display, &ce, event_look_for_focusin, NULL)) {
              /* There is no FocusIn, this means focus went to a window that
                 is not being managed, or a window on another screen. */
              Window win, root;
              gint i;
              guint u;
 -            xerror_set_ignore(TRUE);
 -            if (XGetInputFocus(ob_display, &win, &i) != 0 &&
 -                XGetGeometry(ob_display, win, &root, &i,&i,&u,&u,&u,&u) != 0 &&
 -                root != RootWindow(ob_display, ob_screen))
 +            obt_display_ignore_errors(TRUE);
 +            if (XGetInputFocus(obt_display, &win, &i) &&
 +                XGetGeometry(obt_display, win, &root, &i,&i,&u,&u,&u,&u) &&
 +                root != obt_root(ob_screen))
              {
                  ob_debug_type(OB_DEBUG_FOCUS,
 -                              "Focus went to another screen !\n");
 +                              "Focus went to another screen !");
                  focus_left_screen = TRUE;
              }
              else
                  ob_debug_type(OB_DEBUG_FOCUS,
 -                              "Focus went to a black hole !\n");
 -            xerror_set_ignore(FALSE);
 +                              "Focus went to a black hole !");
 +            obt_display_ignore_errors(FALSE);
              /* nothing is focused */
              focus_set_client(NULL);
          } else {
                  /* The FocusIn was ignored, this means it was on a window
                     that isn't a client. */
                  ob_debug_type(OB_DEBUG_FOCUS,
 -                              "Focus went to an unmanaged window 0x%x !\n",
 +                              "Focus went to an unmanaged window 0x%x !",
                                ce.xfocus.window);
                  focus_fallback(TRUE, config_focus_under_mouse, TRUE, TRUE);
              }
          event_handle_dockapp(dockapp, e);
      else if (dock)
          event_handle_dock(dock, e);
 -    else if (window == RootWindow(ob_display, ob_screen))
 +    else if (menu)
 +        event_handle_menu(menu, e);
 +    else if (window == obt_root(ob_screen))
          event_handle_root(e);
      else if (e->type == MapRequest)
 -        client_manage(window);
 +        window_manage(window);
      else if (e->type == MappingNotify) {
          /* keyboard layout changes for modifier mapping changes. reload the
             modifier map, and rebind all the key bindings as appropriate */
 -        ob_debug("Kepboard map changed. Reloading keyboard bindings.\n");
 -        modkeys_shutdown(TRUE);
 -        modkeys_startup(TRUE);
 +        ob_debug("Kepboard map changed. Reloading keyboard bindings.");
 +        obt_keyboard_reload();
          keyboard_rebind();
      }
      else if (e->type == ClientMessage) {
          /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for
             windows that are not managed yet. */
 -        if (e->xclient.message_type == prop_atoms.net_request_frame_extents) {
 +        if (e->xclient.message_type ==
 +            OBT_PROP_ATOM(NET_REQUEST_FRAME_EXTENTS))
 +        {
              /* Pretend to manage the client, getting information used to
                 determine its decorations */
              ObClient *c = client_fake_manage(e->xclient.window);
              vals[1] = c->frame->size.right;
              vals[2] = c->frame->size.top;
              vals[3] = c->frame->size.bottom;
 -            PROP_SETA32(e->xclient.window, net_frame_extents,
 -                        cardinal, vals, 4);
 +            OBT_PROP_SETA32(e->xclient.window, NET_FRAME_EXTENTS,
 +                            CARDINAL, vals, 4);
  
              /* Free the pretend client */
              client_fake_unmanage(c);
  
          /* we are not to be held responsible if someone sends us an
             invalid request! */
 -        xerror_set_ignore(TRUE);
 -        XConfigureWindow(ob_display, window,
 +        obt_display_ignore_errors(TRUE);
 +        XConfigureWindow(obt_display, window,
                           e->xconfigurerequest.value_mask, &xwc);
 -        xerror_set_ignore(FALSE);
 +        obt_display_ignore_errors(FALSE);
      }
  #ifdef SYNC
 -    else if (extensions_sync &&
 -        e->type == extensions_sync_event_basep + XSyncAlarmNotify)
 +    else if (obt_display_extension_sync &&
 +             e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
      {
          XSyncAlarmNotifyEvent *se = (XSyncAlarmNotifyEvent*)e;
          if (se->alarm == moveresize_alarm && moveresize_in_progress)
      if (e->type == ButtonPress || e->type == ButtonRelease) {
          /* If the button press was on some non-root window, or was physically
             on the root window, then process it */
 -        if (window != RootWindow(ob_display, ob_screen) ||
 +        if (window != obt_root(ob_screen) ||
              e->xbutton.subwindow == None)
          {
              event_handle_user_input(client, e);
          else {
              ObWindow *w;
  
 -            if ((w = g_hash_table_lookup(window_map, &e->xbutton.subwindow)) &&
 +            if ((w = window_find(e->xbutton.subwindow)) &&
                  WINDOW_IS_INTERNAL(w))
              {
                  event_handle_user_input(client, e);
@@@ -740,7 -735,7 +740,7 @@@ static void event_handle_root(XEvent *e
  
      switch(e->type) {
      case SelectionClear:
 -        ob_debug("Another WM has requested to replace us. Exiting.\n");
 +        ob_debug("Another WM has requested to replace us. Exiting.");
          ob_exit_replace();
          break;
  
          if (e->xclient.format != 32) break;
  
          msgtype = e->xclient.message_type;
 -        if (msgtype == prop_atoms.net_current_desktop) {
 +        if (msgtype == OBT_PROP_ATOM(NET_CURRENT_DESKTOP)) {
              guint d = e->xclient.data.l[0];
              if (d < screen_num_desktops) {
                  event_curtime = e->xclient.data.l[1];
                  if (event_curtime == 0)
                      ob_debug_type(OB_DEBUG_APP_BUGS,
                                    "_NET_CURRENT_DESKTOP message is missing "
 -                                  "a timestamp\n");
 +                                  "a timestamp");
                  screen_set_desktop(d, TRUE);
              }
 -        } else if (msgtype == prop_atoms.net_number_of_desktops) {
 +        } else if (msgtype == OBT_PROP_ATOM(NET_NUMBER_OF_DESKTOPS)) {
              guint d = e->xclient.data.l[0];
              if (d > 0 && d <= 1000)
                  screen_set_num_desktops(d);
 -        } else if (msgtype == prop_atoms.net_showing_desktop) {
 +        } else if (msgtype == OBT_PROP_ATOM(NET_SHOWING_DESKTOP)) {
              screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
 -        } else if (msgtype == prop_atoms.ob_control) {
 -            ob_debug("OB_CONTROL: %d\n", e->xclient.data.l[0]);
 +        } else if (msgtype == OBT_PROP_ATOM(OB_CONTROL)) {
 +            ob_debug("OB_CONTROL: %d", e->xclient.data.l[0]);
              if (e->xclient.data.l[0] == 1)
                  ob_reconfigure();
              else if (e->xclient.data.l[0] == 2)
                  ob_restart();
              else if (e->xclient.data.l[0] == 3)
                  ob_exit(0);
 -        } else if (msgtype == prop_atoms.wm_protocols) {
 -            if ((Atom)e->xclient.data.l[0] == prop_atoms.net_wm_ping)
 +        } else if (msgtype == OBT_PROP_ATOM(WM_PROTOCOLS)) {
 +            if ((Atom)e->xclient.data.l[0] == OBT_PROP_ATOM(NET_WM_PING))
                  ping_got_pong(e->xclient.data.l[1]);
          }
          break;
      case PropertyNotify:
 -        if (e->xproperty.atom == prop_atoms.net_desktop_names) {
 -            ob_debug("UPDATE DESKTOP NAMES\n");
 +        if (e->xproperty.atom == OBT_PROP_ATOM(NET_DESKTOP_NAMES)) {
 +            ob_debug("UPDATE DESKTOP NAMES");
              screen_update_desktop_names();
          }
 -        else if (e->xproperty.atom == prop_atoms.net_desktop_layout)
 +        else if (e->xproperty.atom == OBT_PROP_ATOM(NET_DESKTOP_LAYOUT))
              screen_update_layout();
          break;
      case ConfigureNotify:
@@@ -800,21 -795,27 +800,27 @@@ void event_enter_client(ObClient *clien
  {
      g_assert(config_focus_follow);
  
+     if (is_enter_focus_event_ignored(event_curserial)) {
+         ob_debug_type(OB_DEBUG_FOCUS, "Ignoring enter event with serial %lu\n"
+                       "on client 0x%x", event_curserial, client->window);
+         return;
+     }
      if (client_enter_focusable(client) && client_can_focus(client)) {
          if (config_focus_delay) {
              ObFocusDelayData *data;
  
 -            ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
 +            obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
  
              data = g_new(ObFocusDelayData, 1);
              data->client = client;
              data->time = event_curtime;
              data->serial = event_curserial;
  
 -            ob_main_loop_timeout_add(ob_main_loop,
 -                                     config_focus_delay * 1000,
 -                                     focus_delay_func,
 -                                     data, focus_delay_cmp, focus_delay_dest);
 +            obt_main_loop_timeout_add(ob_main_loop,
 +                                      config_focus_delay * 1000,
 +                                      focus_delay_func,
 +                                      data, focus_delay_cmp, focus_delay_dest);
          } else {
              ObFocusDelayData data;
              data.client = client;
@@@ -992,7 -993,7 +998,7 @@@ static void event_handle_client(ObClien
                  event_end_ignore_all_enters(event_start_ignore_all_enters());
  
              ob_debug_type(OB_DEBUG_FOCUS,
 -                          "%sNotify mode %d detail %d on %lx\n",
 +                          "%sNotify mode %d detail %d on %lx",
                            (e->type == EnterNotify ? "Enter" : "Leave"),
                            e->xcrossing.mode,
                            e->xcrossing.detail, (client?client->window:0));
                     delay is up */
                  e->xcrossing.detail != NotifyInferior)
              {
 -                ob_main_loop_timeout_remove_data(ob_main_loop,
 -                                                 focus_delay_func,
 -                                                 client, FALSE);
 +                obt_main_loop_timeout_remove_data(ob_main_loop,
 +                                                  focus_delay_func,
 +                                                  client, FALSE);
              }
              break;
          default:
              if (e->xcrossing.mode == NotifyGrab ||
                  e->xcrossing.mode == NotifyUngrab ||
                  /*ignore enters when we're already in the window */
-                 e->xcrossing.detail == NotifyInferior ||
-                 is_enter_focus_event_ignored(e))
+                 e->xcrossing.detail == NotifyInferior)
              {
                  ob_debug_type(OB_DEBUG_FOCUS,
                                "%sNotify mode %d detail %d serial %lu on %lx "
 -                              "IGNORED\n",
 +                              "IGNORED",
                                (e->type == EnterNotify ? "Enter" : "Leave"),
                                e->xcrossing.mode,
                                e->xcrossing.detail,
              else {
                  ob_debug_type(OB_DEBUG_FOCUS,
                                "%sNotify mode %d detail %d serial %lu on %lx, "
 -                              "focusing window\n",
 +                              "focusing window",
                                (e->type == EnterNotify ? "Enter" : "Leave"),
                                e->xcrossing.mode,
                                e->xcrossing.detail,
          RECT_TO_DIMS(client->area, x, y, w, h);
  
          ob_debug("ConfigureRequest for \"%s\" desktop %d wmstate %d "
 -                 "visibile %d\n"
 -                 "                     x %d y %d w %d h %d b %d\n",
 +                 "visibile %d",
                   client->title,
 -                 screen_desktop, client->wmstate, client->frame->visible,
 +                 screen_desktop, client->wmstate, client->frame->visible);
 +        ob_debug("                     x %d y %d w %d h %d b %d",
                   x, y, w, h, client->border_width);
  
          if (e->xconfigurerequest.value_mask & CWBorderWidth)
              /* get the sibling */
              if (e->xconfigurerequest.value_mask & CWSibling) {
                  ObWindow *win;
 -                win = g_hash_table_lookup(window_map,
 -                                          &e->xconfigurerequest.above);
 +                win = window_find(e->xconfigurerequest.above);
                  if (win && WINDOW_IS_CLIENT(win) &&
                      WINDOW_AS_CLIENT(win) != client)
                  {
          }
  
          ob_debug("ConfigureRequest x(%d) %d y(%d) %d w(%d) %d h(%d) %d "
 -                 "move %d resize %d\n",
 +                 "move %d resize %d",
                   e->xconfigurerequest.value_mask & CWX, x,
                   e->xconfigurerequest.value_mask & CWY, y,
                   e->xconfigurerequest.value_mask & CWWidth, w,
              ob_debug_type(OB_DEBUG_APP_BUGS,
                            "Application %s is trying to move via "
                            "ConfigureRequest to it's root window position "
 -                          "but it is not using StaticGravity\n",
 +                          "but it is not using StaticGravity",
                            client->title);
              /* don't move it */
              x = client->area.x;
  
              client_find_onscreen(client, &x, &y, w, h, FALSE);
  
 -            ob_debug("Granting ConfigureRequest x %d y %d w %d h %d\n",
 +            ob_debug("Granting ConfigureRequest x %d y %d w %d h %d",
                       x, y, w, h);
              client_configure(client, x, y, w, h, FALSE, TRUE, TRUE);
          }
          break;
      }
      case UnmapNotify:
 +        ob_debug("UnmapNotify for window 0x%x eventwin 0x%x sendevent %d "
 +                 "ignores left %d",
 +                 client->window, e->xunmap.event, e->xunmap.from_configure,
 +                 client->ignore_unmaps);
          if (client->ignore_unmaps) {
              client->ignore_unmaps--;
              break;
          }
 -        ob_debug("UnmapNotify for window 0x%x eventwin 0x%x sendevent %d "
 -                 "ignores left %d\n",
 -                 client->window, e->xunmap.event, e->xunmap.from_configure,
 -                 client->ignore_unmaps);
          client_unmanage(client);
          break;
      case DestroyNotify:
 -        ob_debug("DestroyNotify for window 0x%x\n", client->window);
 +        ob_debug("DestroyNotify for window 0x%x", client->window);
          client_unmanage(client);
          break;
      case ReparentNotify:
  
          /* we don't want the reparent event, put it back on the stack for the
             X server to deal with after we unmanage the window */
 -        XPutBackEvent(ob_display, e);
 +        XPutBackEvent(obt_display, e);
  
 -        ob_debug("ReparentNotify for window 0x%x\n", client->window);
 +        ob_debug("ReparentNotify for window 0x%x", client->window);
          client_unmanage(client);
          break;
      case MapRequest:
 -        ob_debug("MapRequest for 0x%lx\n", client->window);
 +        ob_debug("MapRequest for 0x%lx", client->window);
          if (!client->iconic) break; /* this normally doesn't happen, but if it
                                         does, we don't want it!
                                         it can happen now when the window is on
          if (e->xclient.format != 32) return;
  
          msgtype = e->xclient.message_type;
 -        if (msgtype == prop_atoms.wm_change_state) {
 +        if (msgtype == OBT_PROP_ATOM(WM_CHANGE_STATE)) {
              /* compress changes into a single change */
 -            while (XCheckTypedWindowEvent(ob_display, client->window,
 +            while (XCheckTypedWindowEvent(obt_display, client->window,
                                            e->type, &ce)) {
                  /* XXX: it would be nice to compress ALL messages of a
                     type, not just messages in a row without other
                     message types between. */
                  if (ce.xclient.message_type != msgtype) {
 -                    XPutBackEvent(ob_display, &ce);
 +                    XPutBackEvent(obt_display, &ce);
                      break;
                  }
                  e->xclient = ce.xclient;
              }
              client_set_wm_state(client, e->xclient.data.l[0]);
 -        } else if (msgtype == prop_atoms.net_wm_desktop) {
 +        } else if (msgtype == OBT_PROP_ATOM(NET_WM_DESKTOP)) {
              /* compress changes into a single change */
 -            while (XCheckTypedWindowEvent(ob_display, client->window,
 +            while (XCheckTypedWindowEvent(obt_display, client->window,
                                            e->type, &ce)) {
                  /* XXX: it would be nice to compress ALL messages of a
                     type, not just messages in a row without other
                     message types between. */
                  if (ce.xclient.message_type != msgtype) {
 -                    XPutBackEvent(ob_display, &ce);
 +                    XPutBackEvent(obt_display, &ce);
                      break;
                  }
                  e->xclient = ce.xclient;
                  (unsigned)e->xclient.data.l[0] == DESKTOP_ALL)
                  client_set_desktop(client, (unsigned)e->xclient.data.l[0],
                                     FALSE, FALSE);
 -        } else if (msgtype == prop_atoms.net_wm_state) {
 +        } else if (msgtype == OBT_PROP_ATOM(NET_WM_STATE)) {
              gulong ignore_start;
  
              /* can't compress these */
 -            ob_debug("net_wm_state %s %ld %ld for 0x%lx\n",
 +            ob_debug("net_wm_state %s %ld %ld for 0x%lx",
                       (e->xclient.data.l[0] == 0 ? "Remove" :
                        e->xclient.data.l[0] == 1 ? "Add" :
                        e->xclient.data.l[0] == 2 ? "Toggle" : "INVALID"),
                               e->xclient.data.l[1], e->xclient.data.l[2]);
              if (!config_focus_under_mouse)
                  event_end_ignore_all_enters(ignore_start);
 -        } else if (msgtype == prop_atoms.net_close_window) {
 -            ob_debug("net_close_window for 0x%lx\n", client->window);
 +        } else if (msgtype == OBT_PROP_ATOM(NET_CLOSE_WINDOW)) {
 +            ob_debug("net_close_window for 0x%lx", client->window);
              client_close(client);
 -        } else if (msgtype == prop_atoms.net_active_window) {
 -            ob_debug("net_active_window for 0x%lx source=%s\n",
 +        } else if (msgtype == OBT_PROP_ATOM(NET_ACTIVE_WINDOW)) {
 +            ob_debug("net_active_window for 0x%lx source=%s",
                       client->window,
                       (e->xclient.data.l[0] == 0 ? "unknown" :
                        (e->xclient.data.l[0] == 1 ? "application" :
                  if (e->xclient.data.l[1] == 0)
                      ob_debug_type(OB_DEBUG_APP_BUGS,
                                    "_NET_ACTIVE_WINDOW message for window %s is"
 -                                  " missing a timestamp\n", client->title);
 +                                  " missing a timestamp", client->title);
              } else
                  ob_debug_type(OB_DEBUG_APP_BUGS,
                                "_NET_ACTIVE_WINDOW message for window %s is "
 -                              "missing source indication\n");
 +                              "missing source indication");
              client_activate(client, FALSE, TRUE, TRUE,
                              (e->xclient.data.l[0] == 0 ||
                               e->xclient.data.l[0] == 2));
 -        } else if (msgtype == prop_atoms.net_wm_moveresize) {
 -            ob_debug("net_wm_moveresize for 0x%lx direction %d\n",
 +        } else if (msgtype == OBT_PROP_ATOM(NET_WM_MOVERESIZE)) {
 +            ob_debug("net_wm_moveresize for 0x%lx direction %d",
                       client->window, e->xclient.data.l[2]);
              if ((Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_topleft ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_top ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_topright ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_right ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_right ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_bottomright ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_bottom ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_bottomleft ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_left ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_move ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_size_keyboard ||
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD) ||
                  (Atom)e->xclient.data.l[2] ==
 -                prop_atoms.net_wm_moveresize_move_keyboard) {
 -
 +                OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
 +            {
                  moveresize_start(client, e->xclient.data.l[0],
                                   e->xclient.data.l[1], e->xclient.data.l[3],
                                   e->xclient.data.l[2]);
              }
              else if ((Atom)e->xclient.data.l[2] ==
 -                     prop_atoms.net_wm_moveresize_cancel)
 +                     OBT_PROP_ATOM(NET_WM_MOVERESIZE_CANCEL))
                  moveresize_end(TRUE);
 -        } else if (msgtype == prop_atoms.net_moveresize_window) {
 +        } else if (msgtype == OBT_PROP_ATOM(NET_MOVERESIZE_WINDOW)) {
              gint ograv, x, y, w, h;
  
              ograv = client->gravity;
              else
                  h = client->area.height;
  
 -            ob_debug("MOVERESIZE x %d %d y %d %d (gravity %d)\n",
 +            ob_debug("MOVERESIZE x %d %d y %d %d (gravity %d)",
                       e->xclient.data.l[0] & 1 << 8, x,
                       e->xclient.data.l[0] & 1 << 9, y,
                       client->gravity);
              client_configure(client, x, y, w, h, FALSE, TRUE, FALSE);
  
              client->gravity = ograv;
 -        } else if (msgtype == prop_atoms.net_restack_window) {
 +        } else if (msgtype == OBT_PROP_ATOM(NET_RESTACK_WINDOW)) {
              if (e->xclient.data.l[0] != 2) {
                  ob_debug_type(OB_DEBUG_APP_BUGS,
                                "_NET_RESTACK_WINDOW sent for window %s with "
 -                              "invalid source indication %ld\n",
 +                              "invalid source indication %ld",
                                client->title, e->xclient.data.l[0]);
              } else {
                  ObClient *sibling = NULL;
                  if (e->xclient.data.l[1]) {
 -                    ObWindow *win = g_hash_table_lookup
 -                        (window_map, &e->xclient.data.l[1]);
 +                    ObWindow *win = window_find(e->xclient.data.l[1]);
                      if (WINDOW_IS_CLIENT(win) &&
                          WINDOW_AS_CLIENT(win) != client)
                      {
                      if (sibling == NULL)
                          ob_debug_type(OB_DEBUG_APP_BUGS,
                                        "_NET_RESTACK_WINDOW sent for window %s "
 -                                      "with invalid sibling 0x%x\n",
 +                                      "with invalid sibling 0x%x",
                                   client->title, e->xclient.data.l[1]);
                  }
                  if (e->xclient.data.l[2] == Below ||
                  } else
                      ob_debug_type(OB_DEBUG_APP_BUGS,
                                    "_NET_RESTACK_WINDOW sent for window %s "
 -                                  "with invalid detail %d\n",
 +                                  "with invalid detail %d",
                                    client->title, e->xclient.data.l[2]);
              }
          }
          if (!client_validate(client)) break;
  
          /* compress changes to a single property into a single change */
 -        while (XCheckTypedWindowEvent(ob_display, client->window,
 +        while (XCheckTypedWindowEvent(obt_display, client->window,
                                        e->type, &ce)) {
              Atom a, b;
  
  
              if (a == b)
                  continue;
 -            if ((a == prop_atoms.net_wm_name ||
 -                 a == prop_atoms.wm_name ||
 -                 a == prop_atoms.net_wm_icon_name ||
 -                 a == prop_atoms.wm_icon_name)
 +            if ((a == OBT_PROP_ATOM(NET_WM_NAME) ||
 +                 a == OBT_PROP_ATOM(WM_NAME) ||
 +                 a == OBT_PROP_ATOM(NET_WM_ICON_NAME) ||
 +                 a == OBT_PROP_ATOM(WM_ICON_NAME))
                  &&
 -                (b == prop_atoms.net_wm_name ||
 -                 b == prop_atoms.wm_name ||
 -                 b == prop_atoms.net_wm_icon_name ||
 -                 b == prop_atoms.wm_icon_name)) {
 +                (b == OBT_PROP_ATOM(NET_WM_NAME) ||
 +                 b == OBT_PROP_ATOM(WM_NAME) ||
 +                 b == OBT_PROP_ATOM(NET_WM_ICON_NAME) ||
 +                 b == OBT_PROP_ATOM(WM_ICON_NAME))) {
                  continue;
              }
 -            if (a == prop_atoms.net_wm_icon &&
 -                b == prop_atoms.net_wm_icon)
 +            if (a == OBT_PROP_ATOM(NET_WM_ICON) &&
 +                b == OBT_PROP_ATOM(NET_WM_ICON))
                  continue;
  
 -            XPutBackEvent(ob_display, &ce);
 +            XPutBackEvent(obt_display, &ce);
              break;
          }
  
          msgtype = e->xproperty.atom;
          if (msgtype == XA_WM_NORMAL_HINTS) {
 -            ob_debug("Update NORMAL hints\n");
 +            ob_debug("Update NORMAL hints");
              client_update_normal_hints(client);
              /* normal hints can make a window non-resizable */
              client_setup_decor_and_functions(client, FALSE);
              /* type may have changed, so update the layer */
              client_calc_layer(client);
              client_setup_decor_and_functions(client, TRUE);
 -        } else if (msgtype == prop_atoms.net_wm_name ||
 -                   msgtype == prop_atoms.wm_name ||
 -                   msgtype == prop_atoms.net_wm_icon_name ||
 -                   msgtype == prop_atoms.wm_icon_name) {
 +        } else if (msgtype == OBT_PROP_ATOM(NET_WM_NAME) ||
 +                   msgtype == OBT_PROP_ATOM(WM_NAME) ||
 +                   msgtype == OBT_PROP_ATOM(NET_WM_ICON_NAME) ||
 +                   msgtype == OBT_PROP_ATOM(WM_ICON_NAME)) {
              client_update_title(client);
 -        } else if (msgtype == prop_atoms.wm_protocols) {
 +        } else if (msgtype == OBT_PROP_ATOM(WM_PROTOCOLS)) {
              client_update_protocols(client);
              client_setup_decor_and_functions(client, TRUE);
          }
 -        else if (msgtype == prop_atoms.net_wm_strut) {
 +        else if (msgtype == OBT_PROP_ATOM(NET_WM_STRUT)) {
              client_update_strut(client);
          }
 -        else if (msgtype == prop_atoms.net_wm_strut_partial) {
 +        else if (msgtype == OBT_PROP_ATOM(NET_WM_STRUT_PARTIAL)) {
              client_update_strut(client);
          }
 -        else if (msgtype == prop_atoms.net_wm_icon) {
 +        else if (msgtype == OBT_PROP_ATOM(NET_WM_ICON)) {
              client_update_icons(client);
          }
 -        else if (msgtype == prop_atoms.net_wm_icon_geometry) {
 +        else if (msgtype == OBT_PROP_ATOM(NET_WM_ICON_GEOMETRY)) {
              client_update_icon_geometry(client);
          }
 -        else if (msgtype == prop_atoms.net_wm_user_time) {
 +        else if (msgtype == OBT_PROP_ATOM(NET_WM_USER_TIME)) {
              guint32 t;
              if (client == focus_client &&
 -                PROP_GET32(client->window, net_wm_user_time, cardinal, &t) &&
 -                t && !event_time_after(t, e->xproperty.time) &&
 +                OBT_PROP_GET32(client->window, NET_WM_USER_TIME, CARDINAL, &t)
 +                && t && !event_time_after(t, e->xproperty.time) &&
                  (!event_last_user_time ||
                   event_time_after(t, event_last_user_time)))
              {
              }
          }
  #ifdef SYNC
 -        else if (msgtype == prop_atoms.net_wm_sync_request_counter) {
 +        else if (msgtype == OBT_PROP_ATOM(NET_WM_SYNC_REQUEST_COUNTER)) {
              client_update_sync_request_counter(client);
          }
  #endif
      default:
          ;
  #ifdef SHAPE
 -        if (extensions_shape && e->type == extensions_shape_event_basep) {
 +        if (obt_display_extension_shape &&
 +            e->type == obt_display_extension_shape_basep)
 +        {
              client->shaped = ((XShapeEvent*)e)->shaped;
              frame_adjust_shape(client->frame);
          }
@@@ -1629,13 -1629,13 +1634,13 @@@ static void event_handle_dockapp(ObDock
              app->ignore_unmaps--;
              break;
          }
 -        dock_remove(app, TRUE);
 +        dock_unmanage(app, TRUE);
          break;
      case DestroyNotify:
 -        dock_remove(app, FALSE);
 +        dock_unmanage(app, FALSE);
          break;
      case ReparentNotify:
 -        dock_remove(app, FALSE);
 +        dock_unmanage(app, FALSE);
          break;
      case ConfigureNotify:
          dock_app_configure(app, e->xconfigure.width, e->xconfigure.height);
@@@ -1667,156 -1667,124 +1672,156 @@@ static ObMenuFrame* find_active_or_last
      return ret;
  }
  
 -static gboolean event_handle_menu_keyboard(XEvent *ev)
 +static gboolean event_handle_menu_input(XEvent *ev)
  {
 -    guint keycode, state;
 -    gunichar unikey;
 -    ObMenuFrame *frame;
      gboolean ret = FALSE;
  
 -    keycode = ev->xkey.keycode;
 -    state = ev->xkey.state;
 -    unikey = translate_unichar(keycode);
 +    if (ev->type == ButtonRelease) {
 +        ObMenuEntryFrame *e;
  
 -    frame = find_active_or_last_menu();
 -    if (frame == NULL)
 -        g_assert_not_reached(); /* there is no active menu */
 +        if (menu_hide_delay_reached() &&
 +            (ev->xbutton.button < 4 || ev->xbutton.button > 5))
 +        {
 +            if ((e = menu_entry_frame_under(ev->xbutton.x_root,
 +                                            ev->xbutton.y_root)))
 +            {
 +                menu_frame_select(e->frame, e, TRUE);
 +                menu_entry_frame_execute(e, ev->xbutton.state);
 +            }
 +            else
 +                menu_frame_hide_all();
 +        }
 +        ret = TRUE;
 +    }
 +    else if (ev->type == MotionNotify) {
 +        ObMenuFrame *f;
 +        ObMenuEntryFrame *e;
  
 -    /* Allow control while going thru the menu */
 -    else if (ev->type == KeyPress && (state & ~ControlMask) == 0) {
 -        frame->got_press = TRUE;
 +        if ((e = menu_entry_frame_under(ev->xmotion.x_root,
 +                                        ev->xmotion.y_root)))
 +            if (!(f = find_active_menu()) ||
 +                f == e->frame ||
 +                f->parent == e->frame ||
 +                f->child == e->frame)
 +                menu_frame_select(e->frame, e, FALSE);
 +    }
 +    else if (ev->type == KeyPress || ev->type == KeyRelease) {
 +        guint keycode, state;
 +        gunichar unikey;
 +        ObMenuFrame *frame;
  
 -        if (keycode == ob_keycode(OB_KEY_ESCAPE)) {
 -            menu_frame_hide_all();
 -            ret = TRUE;
 -        }
 +        keycode = ev->xkey.keycode;
 +        state = ev->xkey.state;
 +        unikey = obt_keyboard_keycode_to_unichar(keycode);
  
 -        else if (keycode == ob_keycode(OB_KEY_LEFT)) {
 -            /* Left goes to the parent menu */
 -            menu_frame_select(frame, NULL, TRUE);
 -            ret = TRUE;
 -        }
 +        frame = find_active_or_last_menu();
 +        if (frame == NULL)
 +            g_assert_not_reached(); /* there is no active menu */
  
 -        else if (keycode == ob_keycode(OB_KEY_RIGHT)) {
 -            /* Right goes to the selected submenu */
 -            if (frame->child) menu_frame_select_next(frame->child);
 -            ret = TRUE;
 -        }
 +        /* Allow control while going thru the menu */
 +        else if (ev->type == KeyPress && (state & ~ControlMask) == 0) {
 +            frame->got_press = TRUE;
  
 -        else if (keycode == ob_keycode(OB_KEY_UP)) {
 -            menu_frame_select_previous(frame);
 -            ret = TRUE;
 -        }
 +            if (keycode == ob_keycode(OB_KEY_ESCAPE)) {
 +                menu_frame_hide_all();
 +                ret = TRUE;
 +            }
  
 -        else if (keycode == ob_keycode(OB_KEY_DOWN)) {
 -            menu_frame_select_next(frame);
 -            ret = TRUE;
 -        }
 -    }
 +            else if (keycode == ob_keycode(OB_KEY_LEFT)) {
 +                /* Left goes to the parent menu */
 +                menu_frame_select(frame, NULL, TRUE);
 +                ret = TRUE;
 +            }
  
 -    /* Use KeyRelease events for running things so that the key release doesn't
 -       get sent to the focused application.
 +            else if (keycode == ob_keycode(OB_KEY_RIGHT)) {
 +                /* Right goes to the selected submenu */
 +                if (frame->child) menu_frame_select_next(frame->child);
 +                ret = TRUE;
 +            }
  
 -       Allow ControlMask only, and don't bother if the menu is empty */
 -    else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 &&
 -             frame->entries && frame->got_press)
 -    {
 -        if (keycode == ob_keycode(OB_KEY_RETURN)) {
 -            /* Enter runs the active item or goes into the submenu.
 -               Control-Enter runs it without closing the menu. */
 -            if (frame->child)
 -                menu_frame_select_next(frame->child);
 -            else if (frame->selected)
 -                menu_entry_frame_execute(frame->selected, state);
 -
 -            ret = TRUE;
 -        }
 +            else if (keycode == ob_keycode(OB_KEY_UP)) {
 +                menu_frame_select_previous(frame);
 +                ret = TRUE;
 +            }
  
 -        /* keyboard accelerator shortcuts. (if it was a valid key) */
 -        else if (unikey != 0) {
 -            GList *start;
 -            GList *it;
 -            ObMenuEntryFrame *found = NULL;
 -            guint num_found = 0;
 -
 -            /* start after the selected one */
 -            start = frame->entries;
 -            if (frame->selected) {
 -                for (it = start; frame->selected != it->data;
 -                     it = g_list_next(it))
 -                    g_assert(it != NULL); /* nothing was selected? */
 -                /* next with wraparound */
 -                start = g_list_next(it);
 -                if (start == NULL) start = frame->entries;
 +            else if (keycode == ob_keycode(OB_KEY_DOWN)) {
 +                menu_frame_select_next(frame);
 +                ret = TRUE;
              }
 +        }
  
 -            it = start;
 -            do {
 -                ObMenuEntryFrame *e = it->data;
 -                gunichar entrykey = 0;
 +        /* Use KeyRelease events for running things so that the key release
 +           doesn't get sent to the focused application.
  
 -                if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL)
 -                    entrykey = e->entry->data.normal.shortcut;
 -                else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
 -                    entrykey = e->entry->data.submenu.submenu->shortcut;
 +           Allow ControlMask only, and don't bother if the menu is empty */
 +        else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 &&
 +                 frame->entries && frame->got_press)
 +        {
 +            if (keycode == ob_keycode(OB_KEY_RETURN)) {
 +                /* Enter runs the active item or goes into the submenu.
 +                   Control-Enter runs it without closing the menu. */
 +                if (frame->child)
 +                    menu_frame_select_next(frame->child);
 +                else if (frame->selected)
 +                    menu_entry_frame_execute(frame->selected, state);
 +
 +                ret = TRUE;
 +            }
  
 -                if (unikey == entrykey) {
 -                    if (found == NULL) found = e;
 -                    ++num_found;
 +            /* keyboard accelerator shortcuts. (if it was a valid key) */
 +            else if (unikey != 0) {
 +                GList *start;
 +                GList *it;
 +                ObMenuEntryFrame *found = NULL;
 +                guint num_found = 0;
 +
 +                /* start after the selected one */
 +                start = frame->entries;
 +                if (frame->selected) {
 +                    for (it = start; frame->selected != it->data;
 +                         it = g_list_next(it))
 +                        g_assert(it != NULL); /* nothing was selected? */
 +                    /* next with wraparound */
 +                    start = g_list_next(it);
 +                    if (start == NULL) start = frame->entries;
                  }
  
 -                /* next with wraparound */
 -                it = g_list_next(it);
 -                if (it == NULL) it = frame->entries;
 -            } while (it != start);
 +                it = start;
 +                do {
 +                    ObMenuEntryFrame *e = it->data;
 +                    gunichar entrykey = 0;
  
 -            if (found) {
 -                if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
 -                    num_found == 1)
 -                {
 -                    menu_frame_select(frame, found, TRUE);
 -                    usleep(50000); /* highlight the item for a short bit so the
 -                                      user can see what happened */
 -                    menu_entry_frame_execute(found, state);
 -                } else {
 -                    menu_frame_select(frame, found, TRUE);
 -                    if (num_found == 1)
 -                        menu_frame_select_next(frame->child);
 -                }
 +                    if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL)
 +                        entrykey = e->entry->data.normal.shortcut;
 +                    else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
 +                        entrykey = e->entry->data.submenu.submenu->shortcut;
  
 -                ret = TRUE;
 +                    if (unikey == entrykey) {
 +                        if (found == NULL) found = e;
 +                        ++num_found;
 +                    }
 +
 +                    /* next with wraparound */
 +                    it = g_list_next(it);
 +                    if (it == NULL) it = frame->entries;
 +                } while (it != start);
 +
 +                if (found) {
 +                    if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
 +                        num_found == 1)
 +                    {
 +                        menu_frame_select(frame, found, TRUE);
 +                        usleep(50000); /* highlight the item for a short bit so
 +                                          the user can see what happened */
 +                        menu_entry_frame_execute(found, state);
 +                    } else {
 +                        menu_frame_select(frame, found, TRUE);
 +                        if (num_found == 1)
 +                            menu_frame_select_next(frame->child);
 +                    }
 +
 +                    ret = TRUE;
 +                }
              }
          }
      }
      return ret;
  }
  
 -static gboolean event_handle_menu(XEvent *ev)
 +static void event_handle_menu(ObMenuFrame *frame, XEvent *ev)
  {
      ObMenuFrame *f;
      ObMenuEntryFrame *e;
 -    gboolean ret = TRUE;
  
      switch (ev->type) {
 -    case ButtonRelease:
 -        if (menu_hide_delay_reached() &&
 -            (ev->xbutton.button < 4 || ev->xbutton.button > 5))
 -        {
 -            if ((e = menu_entry_frame_under(ev->xbutton.x_root,
 -                                            ev->xbutton.y_root)))
 -            {
 -                menu_frame_select(e->frame, e, TRUE);
 -                menu_entry_frame_execute(e, ev->xbutton.state);
 -            }
 -            else
 -                menu_frame_hide_all();
 -        }
 -        break;
      case EnterNotify:
          if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window))) {
              if (e->ignore_enters)
              menu_frame_select(e->frame, NULL, FALSE);
          }
          break;
 -    case MotionNotify:
 -        if ((e = menu_entry_frame_under(ev->xmotion.x_root,
 -                                        ev->xmotion.y_root)))
 -            if (!(f = find_active_menu()) ||
 -                f == e->frame ||
 -                f->parent == e->frame ||
 -                f->child == e->frame)
 -                menu_frame_select(e->frame, e, FALSE);
 -        break;
 -    case KeyPress:
 -    case KeyRelease:
 -        ret = event_handle_menu_keyboard(ev);
 -        break;
      }
 -    return ret;
  }
  
  static void event_handle_user_input(ObClient *client, XEvent *e)
               e->type == KeyRelease);
  
      if (menu_frame_visible) {
 -        if (event_handle_menu(e))
 +        if (event_handle_menu_input(e))
              /* don't use the event if the menu used it, but if the menu
                 didn't use it and it's a keypress that is bound, it will
                 close the menu and be used */
@@@ -1921,20 -1918,20 +1926,20 @@@ static gboolean focus_delay_func(gpoint
  
  static void focus_delay_client_dest(ObClient *client, gpointer data)
  {
 -    ob_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func,
 -                                     client, FALSE);
 +    obt_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func,
 +                                      client, FALSE);
  }
  
  void event_halt_focus_delay(void)
  {
      /* ignore all enter events up till the event which caused this to occur */
      if (event_curserial) event_ignore_enter_range(1, event_curserial);
 -    ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
 +    obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
  }
  
  gulong event_start_ignore_all_enters(void)
  {
 -    return NextRequest(ob_display);
 +    return NextRequest(obt_display);
  }
  
  static void event_ignore_enter_range(gulong start, gulong end)
      r->end = end;
      ignore_serials = g_slist_prepend(ignore_serials, r);
  
 -    ob_debug_type(OB_DEBUG_FOCUS, "ignoring enters from %lu until %lu\n",
 +    ob_debug_type(OB_DEBUG_FOCUS, "ignoring enters from %lu until %lu",
                    r->start, r->end);
  
      /* increment the serial so we don't ignore events we weren't meant to */
 -    PROP_ERASE(screen_support_win, motif_wm_hints);
 +    OBT_PROP_ERASE(screen_support_win, MOTIF_WM_HINTS);
  }
  
  void event_end_ignore_all_enters(gulong start)
         movement will be ignored until we create some further network traffic.
         Instead ignore up to NextRequest-1, then when we increment the serial,
         we will be *past* the range of ignored serials */
 -    event_ignore_enter_range(start, NextRequest(ob_display)-1);
 +    event_ignore_enter_range(start, NextRequest(obt_display)-1);
  }
  
- static gboolean is_enter_focus_event_ignored(XEvent *e)
+ static gboolean is_enter_focus_event_ignored(gulong serial)
  {
      GSList *it, *next;
  
-     g_assert(e->type == EnterNotify &&
-              !(e->xcrossing.mode == NotifyGrab ||
-                e->xcrossing.mode == NotifyUngrab ||
-                e->xcrossing.detail == NotifyInferior));
      for (it = ignore_serials; it; it = next) {
          ObSerialRange *r = it->data;
  
          next = g_slist_next(it);
  
-         if ((glong)(e->xany.serial - r->end) > 0) {
+         if ((glong)(serial - r->end) > 0) {
              /* past the end */
              ignore_serials = g_slist_delete_link(ignore_serials, it);
              g_free(r);
          }
-         else if ((glong)(e->xany.serial - r->start) >= 0)
+         else if ((glong)(serial - r->start) >= 0)
              return TRUE;
      }
      return FALSE;
@@@ -1996,24 -1988,24 +1996,24 @@@ void event_cancel_all_key_grabs(void
  {
      if (actions_interactive_act_running()) {
          actions_interactive_cancel_act();
 -        ob_debug("KILLED interactive action\n");
 +        ob_debug("KILLED interactive action");
      }
      else if (menu_frame_visible) {
          menu_frame_hide_all();
 -        ob_debug("KILLED open menus\n");
 +        ob_debug("KILLED open menus");
      }
      else if (moveresize_in_progress) {
          moveresize_end(TRUE);
 -        ob_debug("KILLED interactive moveresize\n");
 +        ob_debug("KILLED interactive moveresize");
      }
      else if (grab_on_keyboard()) {
          ungrab_keyboard();
 -        ob_debug("KILLED active grab on keyboard\n");
 +        ob_debug("KILLED active grab on keyboard");
      }
      else
          ungrab_passive_key();
  
 -    XSync(ob_display, FALSE);
 +    XSync(obt_display, FALSE);
  }
  
  gboolean event_time_after(Time t1, Time t2)
@@@ -2046,9 -2038,9 +2046,9 @@@ Time event_get_server_time(void
      /* Generate a timestamp */
      XEvent event;
  
 -    XChangeProperty(ob_display, screen_support_win,
 -                    prop_atoms.wm_class, prop_atoms.string,
 +    XChangeProperty(obt_display, screen_support_win,
 +                    OBT_PROP_ATOM(WM_CLASS), OBT_PROP_ATOM(STRING),
                      8, PropModeAppend, NULL, 0);
 -    XWindowEvent(ob_display, screen_support_win, PropertyChangeMask, &event);
 +    XWindowEvent(obt_display, screen_support_win, PropertyChangeMask, &event);
      return event.xproperty.time;
  }
diff --combined openbox/focus.c
  #include "group.h"
  #include "focus_cycle.h"
  #include "screen.h"
 -#include "prop.h"
  #include "keyboard.h"
  #include "focus.h"
  #include "stacking.h"
 +#include "obt/prop.h"
  
  #include <X11/Xlib.h>
  #include <glib.h>
@@@ -52,11 -52,19 +52,19 @@@ void focus_shutdown(gboolean reconfig
      if (reconfig) return;
  
      /* reset focus to root */
 -    XSetInputFocus(ob_display, PointerRoot, RevertToNone, CurrentTime);
 +    XSetInputFocus(obt_display, PointerRoot, RevertToNone, CurrentTime);
  }
  
  static void push_to_top(ObClient *client)
  {
+     ObClient *p;
+     /* if it is modal for a single window, then put that window at the top
+        of the focus order first, so it will be right after ours. the same is
+        done with stacking */
+     if (client->modal && (p = client_direct_parent(client)))
+         push_to_top(p);
      focus_order = g_list_remove(focus_order, client);
      focus_order = g_list_prepend(focus_order, client);
  }
@@@ -66,7 -74,7 +74,7 @@@ void focus_set_client(ObClient *client
      Window active;
  
      ob_debug_type(OB_DEBUG_FOCUS,
 -                  "focus_set_client 0x%lx\n", client ? client->window : 0);
 +                  "focus_set_client 0x%lx", client ? client->window : 0);
  
      if (focus_client == client)
          return;
@@@ -91,7 -99,8 +99,7 @@@
      /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
      if (ob_state() != OB_STATE_EXITING) {
          active = client ? client->window : None;
 -        PROP_SET32(RootWindow(ob_display, ob_screen),
 -                   net_active_window, window, active);
 +        OBT_PROP_SET32(obt_root(ob_screen), NET_ACTIVE_WINDOW, WINDOW, active);
      }
  }
  
@@@ -103,18 -112,18 +111,18 @@@ static ObClient* focus_fallback_target(
      GList *it;
      ObClient *c;
  
 -    ob_debug_type(OB_DEBUG_FOCUS, "trying pointer stuff\n");
 +    ob_debug_type(OB_DEBUG_FOCUS, "trying pointer stuff");
      if (allow_pointer && config_focus_follow)
          if ((c = client_under_pointer()) &&
              (allow_refocus || client_focus_target(c) != old) &&
              (client_normal(c) &&
               client_focus(c)))
          {
 -            ob_debug_type(OB_DEBUG_FOCUS, "found in pointer stuff\n");
 +            ob_debug_type(OB_DEBUG_FOCUS, "found in pointer stuff");
              return c;
          }
  
 -    ob_debug_type(OB_DEBUG_FOCUS, "trying the focus order\n");
 +    ob_debug_type(OB_DEBUG_FOCUS, "trying the focus order");
      for (it = focus_order; it; it = g_list_next(it)) {
          c = it->data;
          /* fallback focus to a window if:
              (allow_refocus || client_focus_target(c) != old) &&
              client_focus(c))
          {
 -            ob_debug_type(OB_DEBUG_FOCUS, "found in focus order\n");
 +            ob_debug_type(OB_DEBUG_FOCUS, "found in focus order");
              return c;
          }
      }
  
 -    ob_debug_type(OB_DEBUG_FOCUS, "trying a desktop window\n");
 +    ob_debug_type(OB_DEBUG_FOCUS, "trying a desktop window");
      for (it = focus_order; it; it = g_list_next(it)) {
          c = it->data;
          /* fallback focus to a window if:
              (allow_refocus || client_focus_target(c) != old) &&
              client_focus(c))
          {
 -            ob_debug_type(OB_DEBUG_FOCUS, "found a desktop window\n");
 +            ob_debug_type(OB_DEBUG_FOCUS, "found a desktop window");
              return c;
          }
      }
@@@ -198,7 -207,7 +206,7 @@@ void focus_nothing(void
      event_cancel_all_key_grabs();
  
      /* when nothing will be focused, send focus to the backup target */
 -    XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot,
 +    XSetInputFocus(obt_display, screen_support_win, RevertToPointerRoot,
                     event_curtime);
  }
  
diff --combined openbox/menuframe.c
@@@ -24,6 -24,7 +24,6 @@@
  #include "actions.h"
  #include "grab.h"
  #include "openbox.h"
 -#include "mainloop.h"
  #include "config.h"
  #include "render/theme.h"
  
@@@ -50,7 -51,7 +50,7 @@@ static void menu_frame_hide(ObMenuFram
  static Window createWindow(Window parent, gulong mask,
                             XSetWindowAttributes *attrib)
  {
 -    return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
 +    return XCreateWindow(obt_display, parent, 0, 0, 1, 1, 0,
                           RrDepth(ob_rr_inst), InputOutput,
                           RrVisual(ob_rr_inst), mask, attrib);
  }
@@@ -77,7 -78,7 +77,7 @@@ ObMenuFrame* menu_frame_new(ObMenu *men
      XSetWindowAttributes attr;
  
      self = g_new0(ObMenuFrame, 1);
 -    self->type = Window_Menu;
 +    self->obwin.type = OB_WINDOW_CLASS_MENUFRAME;
      self->menu = menu;
      self->selected = NULL;
      self->client = client;
      self->show_from = show_from;
  
      attr.event_mask = FRAME_EVENTMASK;
 -    self->window = createWindow(RootWindow(ob_display, ob_screen),
 +    self->window = createWindow(obt_root(ob_screen),
                                  CWEventMask, &attr);
  
 -    XSetWindowBorderWidth(ob_display, self->window, ob_rr_theme->mbwidth);
 -    XSetWindowBorder(ob_display, self->window,
 +    XSetWindowBorderWidth(obt_display, self->window, ob_rr_theme->mbwidth);
 +    XSetWindowBorder(obt_display, self->window,
                       RrColorPixel(ob_rr_theme->menu_border_color));
  
      self->a_items = RrAppearanceCopy(ob_rr_theme->a_menu);
  
 -    stacking_add(MENU_AS_WINDOW(self));
 +    window_add(&self->window, MENUFRAME_AS_WINDOW(self));
 +    stacking_add(MENUFRAME_AS_WINDOW(self));
  
      return self;
  }
@@@ -108,12 -108,11 +108,12 @@@ void menu_frame_free(ObMenuFrame *self
              self->entries = g_list_delete_link(self->entries, self->entries);
          }
  
 -        stacking_remove(MENU_AS_WINDOW(self));
 +        stacking_remove(MENUFRAME_AS_WINDOW(self));
 +        window_remove(self->window);
  
          RrAppearanceFree(self->a_items);
  
 -        XDestroyWindow(ob_display, self->window);
 +        XDestroyWindow(obt_display, self->window);
  
          g_free(self);
      }
@@@ -145,10 -144,8 +145,10 @@@ static ObMenuEntryFrame* menu_entry_fra
          g_hash_table_insert(menu_frame_map, &self->bullet, self);
      }
  
 -    XMapWindow(ob_display, self->window);
 -    XMapWindow(ob_display, self->text);
 +    XMapWindow(obt_display, self->window);
 +    XMapWindow(obt_display, self->text);
 +
 +    window_add(&self->window, MENUFRAME_AS_WINDOW(self->frame));
  
      return self;
  }
@@@ -158,18 -155,16 +158,18 @@@ static void menu_entry_frame_free(ObMen
      if (self) {
          menu_entry_unref(self->entry);
  
 -        XDestroyWindow(ob_display, self->text);
 -        XDestroyWindow(ob_display, self->window);
 +        window_remove(self->window);
 +
 +        XDestroyWindow(obt_display, self->text);
 +        XDestroyWindow(obt_display, self->window);
          g_hash_table_remove(menu_frame_map, &self->text);
          g_hash_table_remove(menu_frame_map, &self->window);
          if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
 -            XDestroyWindow(ob_display, self->icon);
 +            XDestroyWindow(obt_display, self->icon);
              g_hash_table_remove(menu_frame_map, &self->icon);
          }
          if (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
 -            XDestroyWindow(ob_display, self->bullet);
 +            XDestroyWindow(obt_display, self->bullet);
              g_hash_table_remove(menu_frame_map, &self->bullet);
          }
  
  void menu_frame_move(ObMenuFrame *self, gint x, gint y)
  {
      RECT_SET_POINT(self->area, x, y);
 -    XMoveWindow(ob_display, self->window, self->area.x, self->area.y);
 +    XMoveWindow(obt_display, self->window, self->area.x, self->area.y);
  }
  
  static void menu_frame_place_topmenu(ObMenuFrame *self, gint *x, gint *y)
@@@ -339,7 -334,7 +339,7 @@@ static void menu_entry_frame_render(ObM
          g_assert_not_reached();
      }
      RECT_SET_SIZE(self->area, self->frame->inner_w, th);
 -    XResizeWindow(ob_display, self->window,
 +    XResizeWindow(obt_display, self->window,
                    self->area.width, self->area.height);
      item_a->surface.parent = self->frame->a_items;
      item_a->surface.parentx = self->area.x;
              text_a->texture[0].data.text.shortcut = FALSE;
          break;
      case OB_MENU_ENTRY_TYPE_SEPARATOR:
-         if (self->entry->data.separator.label != NULL)
+         if (self->entry->data.separator.label != NULL) {
              text_a = ob_rr_theme->a_menu_text_title;
+             text_a->texture[0].data.text.string =
+                 self->entry->data.separator.label;
+         }
          else
              text_a = ob_rr_theme->a_menu_text_normal;
          break;
  
      switch (self->entry->type) {
      case OB_MENU_ENTRY_TYPE_NORMAL:
 -        XMoveResizeWindow(ob_display, self->text,
 +        XMoveResizeWindow(obt_display, self->text,
                            self->frame->text_x, PADDING,
                            self->frame->text_w,
                            ITEM_HEIGHT - 2*PADDING);
                  ITEM_HEIGHT - 2*PADDING);
          break;
      case OB_MENU_ENTRY_TYPE_SUBMENU:
 -        XMoveResizeWindow(ob_display, self->text,
 +        XMoveResizeWindow(obt_display, self->text,
                            self->frame->text_x, PADDING,
                            self->frame->text_w - ITEM_HEIGHT,
                            ITEM_HEIGHT - 2*PADDING);
      case OB_MENU_ENTRY_TYPE_SEPARATOR:
          if (self->entry->data.separator.label != NULL) {
              /* labeled separator */
 -            XMoveResizeWindow(ob_display, self->text,
 +            XMoveResizeWindow(obt_display, self->text,
                                ob_rr_theme->paddingx, ob_rr_theme->paddingy,
                                self->area.width - 2*ob_rr_theme->paddingx,
                                ob_rr_theme->menu_title_height -
              RrAppearance *clear;
  
              /* unlabeled separaator */
 -            XMoveResizeWindow(ob_display, self->text, PADDING, PADDING,
 +            XMoveResizeWindow(obt_display, self->text, PADDING, PADDING,
                                self->area.width - 2*PADDING, SEPARATOR_HEIGHT);
  
              clear = ob_rr_theme->a_clear_tex;
      {
          RrAppearance *clear;
  
 -        XMoveResizeWindow(ob_display, self->icon,
 +        XMoveResizeWindow(obt_display, self->icon,
                            PADDING, frame->item_margin.top,
                            ITEM_HEIGHT - frame->item_margin.top
                            - frame->item_margin.bottom,
                  - frame->item_margin.bottom,
                  ITEM_HEIGHT - frame->item_margin.top
                  - frame->item_margin.bottom);
 -        XMapWindow(ob_display, self->icon);
 +        XMapWindow(obt_display, self->icon);
      } else if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
                 self->entry->data.normal.mask)
      {
          RrColor *c;
          RrAppearance *clear;
  
 -        XMoveResizeWindow(ob_display, self->icon,
 +        XMoveResizeWindow(obt_display, self->icon,
                            PADDING, frame->item_margin.top,
                            ITEM_HEIGHT - frame->item_margin.top
                            - frame->item_margin.bottom,
                  - frame->item_margin.bottom,
                  ITEM_HEIGHT - frame->item_margin.top
                  - frame->item_margin.bottom);
 -        XMapWindow(ob_display, self->icon);
 +        XMapWindow(obt_display, self->icon);
      } else
 -        XUnmapWindow(ob_display, self->icon);
 +        XUnmapWindow(obt_display, self->icon);
  
      if (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
          RrAppearance *bullet_a;
 -        XMoveResizeWindow(ob_display, self->bullet,
 +        XMoveResizeWindow(obt_display, self->bullet,
                            self->frame->text_x + self->frame->text_w -
                            ITEM_HEIGHT + PADDING, PADDING,
                            ITEM_HEIGHT - 2*PADDING,
          RrPaint(bullet_a, self->bullet,
                  ITEM_HEIGHT - 2*PADDING,
                  ITEM_HEIGHT - 2*PADDING);
 -        XMapWindow(ob_display, self->bullet);
 +        XMapWindow(obt_display, self->bullet);
      } else
 -        XUnmapWindow(ob_display, self->bullet);
 +        XUnmapWindow(obt_display, self->bullet);
  
 -    XFlush(ob_display);
 +    XFlush(obt_display);
  }
  
  /*! this code is taken from the menu_frame_render. if that changes, this won't
@@@ -667,10 -665,10 +670,10 @@@ void menu_frame_render(ObMenuFrame *sel
          }
  
          RECT_SET_POINT(e->area, 0, h+e->border);
 -        XMoveWindow(ob_display, e->window,
 +        XMoveWindow(obt_display, e->window,
                      e->area.x-e->border, e->area.y-e->border);
 -        XSetWindowBorderWidth(ob_display, e->window, e->border);
 -        XSetWindowBorder(ob_display, e->window,
 +        XSetWindowBorderWidth(obt_display, e->window, e->border);
 +        XSetWindowBorder(obt_display, e->window,
                           RrColorPixel(ob_rr_theme->menu_border_color));
  
  
      if (!w) w = 10;
      if (!h) h = 3;
  
 -    XResizeWindow(ob_display, self->window, w, h);
 +    XResizeWindow(obt_display, self->window, w, h);
  
      self->inner_w = w;
  
  
      RECT_SET_SIZE(self->area, w, h);
  
 -    XFlush(ob_display);
 +    XFlush(obt_display);
  }
  
  static void menu_frame_update(ObMenuFrame *self)
@@@ -948,7 -946,7 +951,7 @@@ gboolean menu_frame_show_topmenu(ObMenu
  
      menu_frame_move(self, x, y);
  
 -    XMapWindow(ob_display, self->window);
 +    XMapWindow(obt_display, self->window);
  
      if (screen_pointer_pos(&px, &py)) {
          ObMenuEntryFrame *e = menu_entry_frame_under(px, py);
@@@ -991,7 -989,7 +994,7 @@@ gboolean menu_frame_show_submenu(ObMenu
      }
      menu_frame_move(self, x + dx, y + dy);
  
 -    XMapWindow(ob_display, self->window);
 +    XMapWindow(obt_display, self->window);
  
      if (screen_pointer_pos(&px, &py)) {
          ObMenuEntryFrame *e = menu_entry_frame_under(px, py);
@@@ -1028,7 -1026,7 +1031,7 @@@ static void menu_frame_hide(ObMenuFram
          ungrab_keyboard();
      }
  
 -    XUnmapWindow(ob_display, self->window);
 +    XUnmapWindow(obt_display, self->window);
  
      menu_frame_free(self);
  }
@@@ -1039,8 -1037,8 +1042,8 @@@ void menu_frame_hide_all(void
  
      if (config_submenu_show_delay) {
          /* remove any submenu open requests */
 -        ob_main_loop_timeout_remove(ob_main_loop,
 -                                    menu_entry_frame_submenu_timeout);
 +        obt_main_loop_timeout_remove(ob_main_loop,
 +                                     menu_entry_frame_submenu_timeout);
      }
      if ((it = g_list_last(menu_frame_visible)))
          menu_frame_hide(it->data);
@@@ -1054,8 -1052,8 +1057,8 @@@ void menu_frame_hide_all_client(ObClien
          if (f->client == client) {
              if (config_submenu_show_delay) {
                  /* remove any submenu open requests */
 -                ob_main_loop_timeout_remove(ob_main_loop,
 -                                            menu_entry_frame_submenu_timeout);
 +                obt_main_loop_timeout_remove(ob_main_loop,
 +                                             menu_entry_frame_submenu_timeout);
              }
              menu_frame_hide(f);
          }
@@@ -1121,8 -1119,8 +1124,8 @@@ void menu_frame_select(ObMenuFrame *sel
  
      if (config_submenu_show_delay) {
          /* remove any submenu open requests */
 -        ob_main_loop_timeout_remove(ob_main_loop,
 -                                    menu_entry_frame_submenu_timeout);
 +        obt_main_loop_timeout_remove(ob_main_loop,
 +                                     menu_entry_frame_submenu_timeout);
      }
  
      self->selected = entry;
          if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
              if (config_submenu_show_delay && !immediate) {
                  /* initiate a new submenu open request */
 -                ob_main_loop_timeout_add(ob_main_loop,
 -                                         config_submenu_show_delay * 1000,
 -                                         menu_entry_frame_submenu_timeout,
 -                                         self->selected, g_direct_equal,
 -                                         NULL);
 +                obt_main_loop_timeout_add(ob_main_loop,
 +                                          config_submenu_show_delay * 1000,
 +                                          menu_entry_frame_submenu_timeout,
 +                                          self->selected, g_direct_equal,
 +                                          NULL);
              } else {
                  menu_entry_frame_show_submenu(self->selected);
              }
diff --combined openbox/openbox.c
  #include "openbox.h"
  #include "session.h"
  #include "dock.h"
 -#include "modkeys.h"
  #include "event.h"
  #include "menu.h"
  #include "client.h"
 -#include "xerror.h"
 -#include "prop.h"
  #include "screen.h"
  #include "actions.h"
  #include "startupnotify.h"
  #include "framerender.h"
  #include "keyboard.h"
  #include "mouse.h"
 -#include "extensions.h"
  #include "menuframe.h"
  #include "grab.h"
  #include "group.h"
  #include "config.h"
  #include "ping.h"
 -#include "mainloop.h"
  #include "gettext.h"
 -#include "parser/parse.h"
  #include "render/render.h"
  #include "render/theme.h"
 +#include "obt/display.h"
 +#include "obt/prop.h"
 +#include "obt/keyboard.h"
 +#include "obt/parse.h"
  
  #ifdef HAVE_FCNTL_H
  #  include <fcntl.h>
  #include <X11/Xlib.h>
  #include <X11/keysym.h>
  
 -
 -RrInstance *ob_rr_inst;
 -RrTheme    *ob_rr_theme;
 -ObMainLoop *ob_main_loop;
 -Display    *ob_display;
 -gint        ob_screen;
 -gboolean    ob_replace_wm = FALSE;
 -gboolean    ob_sm_use = TRUE;
 -gchar      *ob_sm_id = NULL;
 -gchar      *ob_sm_save_file = NULL;
 -gboolean    ob_sm_restore = TRUE;
 -gboolean    ob_debug_xinerama = FALSE;
 +RrInstance  *ob_rr_inst;
 +RrTheme     *ob_rr_theme;
 +ObtMainLoop *ob_main_loop;
 +gint         ob_screen;
 +gboolean     ob_replace_wm = FALSE;
 +gboolean     ob_sm_use = TRUE;
 +gchar       *ob_sm_id = NULL;
 +gchar       *ob_sm_save_file = NULL;
 +gboolean     ob_sm_restore = TRUE;
 +gboolean     ob_debug_xinerama = FALSE;
  
  static ObState   state;
  static gboolean  xsync = FALSE;
@@@ -117,8 -121,6 +117,8 @@@ gint main(gint argc, gchar **argv
  
      state = OB_STATE_STARTING;
  
 +    ob_debug_startup();
 +
      /* initialize the locale */
      if (!setlocale(LC_ALL, ""))
          g_message("Couldn't set locale from environment.");
      bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
      textdomain(PACKAGE_NAME);
  
 -    if (chdir(g_get_home_dir()) == -1)
 -        g_message(_("Unable to change to home directory '%s': %s"),
 -                  g_get_home_dir(), g_strerror(errno));
 -
      /* parse the command line args, which can change the argv[0] */
      parse_args(&argc, argv);
      /* parse the environment variables */
      program_name = g_path_get_basename(argv[0]);
      g_set_prgname(program_name);
  
 -    if (!remote_control) {
 -        parse_paths_startup();
 -
 +    if (!remote_control)
          session_startup(argc, argv);
 -    }
  
 -
 -    ob_display = XOpenDisplay(NULL);
 -    if (ob_display == NULL)
 +    if (!obt_display_open(NULL))
          ob_exit_with_error(_("Failed to open the display from the DISPLAY environment variable."));
 -    if (fcntl(ConnectionNumber(ob_display), F_SETFD, 1) == -1)
 -        ob_exit_with_error("Failed to set display as close-on-exec");
  
      if (remote_control) {
 -        prop_startup();
 -
          /* Send client message telling the OB process to:
           * remote_control = 1 -> reconfigure
           * remote_control = 2 -> restart */
 -        PROP_MSG(RootWindow(ob_display, ob_screen),
 -                 ob_control, remote_control, 0, 0, 0);
 -        XCloseDisplay(ob_display);
 +        OBT_PROP_MSG(ob_screen, obt_root(ob_screen),
 +                     OB_CONTROL, remote_control, 0, 0, 0, 0);
 +        obt_display_close(obt_display);
          exit(EXIT_SUCCESS);
      }
  
 -    ob_main_loop = ob_main_loop_new(ob_display);
 +    ob_main_loop = obt_main_loop_new();
  
      /* set up signal handler */
 -    ob_main_loop_signal_add(ob_main_loop, SIGUSR1, signal_handler, NULL, NULL);
 -    ob_main_loop_signal_add(ob_main_loop, SIGUSR2, signal_handler, NULL, NULL);
 -    ob_main_loop_signal_add(ob_main_loop, SIGTERM, signal_handler, NULL, NULL);
 -    ob_main_loop_signal_add(ob_main_loop, SIGINT, signal_handler, NULL, NULL);
 -    ob_main_loop_signal_add(ob_main_loop, SIGHUP, signal_handler, NULL, NULL);
 -    ob_main_loop_signal_add(ob_main_loop, SIGPIPE, signal_handler, NULL, NULL);
 -    ob_main_loop_signal_add(ob_main_loop, SIGCHLD, signal_handler, NULL, NULL);
 +    obt_main_loop_signal_add(ob_main_loop, SIGUSR1, signal_handler, NULL,NULL);
 +    obt_main_loop_signal_add(ob_main_loop, SIGUSR2, signal_handler, NULL,NULL);
 +    obt_main_loop_signal_add(ob_main_loop, SIGTERM, signal_handler, NULL,NULL);
 +    obt_main_loop_signal_add(ob_main_loop, SIGINT, signal_handler,  NULL,NULL);
 +    obt_main_loop_signal_add(ob_main_loop, SIGHUP, signal_handler,  NULL,NULL);
 +    obt_main_loop_signal_add(ob_main_loop, SIGPIPE, signal_handler, NULL,NULL);
 +    obt_main_loop_signal_add(ob_main_loop, SIGCHLD, signal_handler, NULL,NULL);
  
 -    ob_screen = DefaultScreen(ob_display);
 +    ob_screen = DefaultScreen(obt_display);
  
 -    ob_rr_inst = RrInstanceNew(ob_display, ob_screen);
 +    ob_rr_inst = RrInstanceNew(obt_display, ob_screen);
      if (ob_rr_inst == NULL)
          ob_exit_with_error(_("Failed to initialize the obrender library."));
  
 -    XSynchronize(ob_display, xsync);
 +    XSynchronize(obt_display, xsync);
  
      /* check for locale support */
      if (!XSupportsLocale())
      if (!XSetLocaleModifiers(""))
          g_message(_("Cannot set locale modifiers for the X server."));
  
 -    /* set our error handler */
 -    XSetErrorHandler(xerror_handler);
 -
      /* set the DISPLAY environment variable for any lauched children, to the
         display we're using, so they open in the right place. */
 -    setenv("DISPLAY", DisplayString(ob_display), TRUE);
 +    setenv("DISPLAY", DisplayString(obt_display), TRUE);
  
      /* create available cursors */
      cursors[OB_CURSOR_NONE] = None;
      cursors[OB_CURSOR_NORTHWEST] = load_cursor("top_left_corner",
                                                 XC_top_left_corner);
  
 -
 -    prop_startup(); /* get atoms values for the display */
 -    extensions_query_all(); /* find which extensions are present */
 -
      if (screen_annex()) { /* it will be ours! */
          do {
 -            modkeys_startup(reconfigure);
 +            if (reconfigure) obt_keyboard_reload();
  
              /* get the keycodes for keys we use */
 -            keys[OB_KEY_RETURN] = modkeys_sym_to_code(XK_Return);
 -            keys[OB_KEY_ESCAPE] = modkeys_sym_to_code(XK_Escape);
 -            keys[OB_KEY_LEFT] = modkeys_sym_to_code(XK_Left);
 -            keys[OB_KEY_RIGHT] = modkeys_sym_to_code(XK_Right);
 -            keys[OB_KEY_UP] = modkeys_sym_to_code(XK_Up);
 -            keys[OB_KEY_DOWN] = modkeys_sym_to_code(XK_Down);
 +            keys[OB_KEY_RETURN] = obt_keyboard_keysym_to_keycode(XK_Return);
 +            keys[OB_KEY_ESCAPE] = obt_keyboard_keysym_to_keycode(XK_Escape);
 +            keys[OB_KEY_LEFT] = obt_keyboard_keysym_to_keycode(XK_Left);
 +            keys[OB_KEY_RIGHT] = obt_keyboard_keysym_to_keycode(XK_Right);
 +            keys[OB_KEY_UP] = obt_keyboard_keysym_to_keycode(XK_Up);
 +            keys[OB_KEY_DOWN] = obt_keyboard_keysym_to_keycode(XK_Down);
  
              {
 -                ObParseInst *i;
 -                xmlDocPtr doc;
 -                xmlNodePtr node;
 +                ObtParseInst *i;
  
                  /* startup the parsing so everything can register sections
                     of the rc */
 -                i = parse_startup();
 +                i = obt_parse_instance_new();
  
                  /* register all the available actions */
                  actions_startup(reconfigure);
                  config_startup(i);
  
                  /* parse/load user options */
 -                if (parse_load_rc(config_file, &doc, &node)) {
 -                    parse_tree(i, doc, node->xmlChildrenNode);
 -                    parse_close(doc);
 +                if ((config_file &&
 +                     obt_parse_load_file(i, config_file, "openbox_config")) ||
 +                    obt_parse_load_config_file(i, "openbox", "rc.xml",
 +                                               "openbox_config"))
 +                {
 +                    obt_parse_tree_from_root(i);
 +                    obt_parse_close(i);
                  }
                  else {
                      g_message(_("Unable to find a valid config file, using some simple defaults"));
                      gchar *p = g_filename_to_utf8(config_file, -1,
                                                    NULL, NULL, NULL);
                      if (p)
 -                        PROP_SETS(RootWindow(ob_display, ob_screen),
 -                                  ob_config_file, p);
 +                        OBT_PROP_SETS(obt_root(ob_screen), OB_CONFIG_FILE,
 +                                      utf8, p);
                      g_free(p);
                  }
                  else
 -                    PROP_ERASE(RootWindow(ob_display, ob_screen),
 -                               ob_config_file);
 +                    OBT_PROP_ERASE(obt_root(ob_screen), OB_CONFIG_FILE);
  
                  /* we're done with parsing now, kill it */
 -                parse_shutdown(i);
 +                obt_parse_instance_unref(i);
              }
  
              /* load the theme specified in the rc file */
                  if (ob_rr_theme == NULL)
                      ob_exit_with_error(_("Unable to load a theme."));
  
 -                PROP_SETS(RootWindow(ob_display, ob_screen),
 -                          ob_theme, ob_rr_theme->name);
 +                OBT_PROP_SETS(obt_root(ob_screen),
 +                              OB_THEME, utf8, ob_rr_theme->name);
              }
  
              if (reconfigure) {
                  ObWindow *w;
  
                  /* get all the existing windows */
 -                client_manage_all();
 +                window_manage_all();
                  focus_nothing();
  
                  /* focus what was focused if a wm was already running */
 -                if (PROP_GET32(RootWindow(ob_display, ob_screen),
 -                               net_active_window, window, &xid) &&
 -                    (w = g_hash_table_lookup(window_map, &xid)) &&
 -                    WINDOW_IS_CLIENT(w))
 +                if (OBT_PROP_GET32(obt_root(ob_screen),
 +                                   NET_ACTIVE_WINDOW, WINDOW, &xid) &&
 +                    (w = window_find(xid)) && WINDOW_IS_CLIENT(w))
                  {
                      client_focus(WINDOW_AS_CLIENT(w));
                  }
              reconfigure = FALSE;
  
              state = OB_STATE_RUNNING;
 -            ob_main_loop_run(ob_main_loop);
 +            obt_main_loop_run(ob_main_loop);
              state = OB_STATE_EXITING;
  
 -            if (!reconfigure) {
 -                dock_remove_all();
 -                client_unmanage_all();
 -            }
 +            if (!reconfigure)
 +                window_unmanage_all();
  
              menu_shutdown(reconfigure);
              menu_frame_shutdown(reconfigure);
              event_shutdown(reconfigure);
              config_shutdown();
              actions_shutdown(reconfigure);
 -            modkeys_shutdown(reconfigure);
          } while (reconfigure);
      }
  
 -    XSync(ob_display, FALSE);
 +    XSync(obt_display, FALSE);
  
      RrThemeFree(ob_rr_theme);
      RrInstanceFree(ob_rr_inst);
  
      session_shutdown(being_replaced);
  
 -    XCloseDisplay(ob_display);
 -
 -    parse_paths_shutdown();
 +    obt_display_close(obt_display);
  
      if (restart) {
          if (restart_path != NULL) {
      g_free(ob_sm_id);
      g_free(program_name);
  
 +    ob_debug_shutdown();
 +
      return exitcode;
  }
  
@@@ -437,11 -462,11 +437,11 @@@ static void signal_handler(gint signal
  {
      switch (signal) {
      case SIGUSR1:
 -        ob_debug("Caught signal %d. Restarting.\n", signal);
 +        ob_debug("Caught signal %d. Restarting.", signal);
          ob_restart();
          break;
      case SIGUSR2:
 -        ob_debug("Caught signal %d. Reconfiguring.\n", signal);
 +        ob_debug("Caught signal %d. Reconfiguring.", signal);
          ob_reconfigure();
          break;
      case SIGCHLD:
          while (waitpid(-1, NULL, WNOHANG) > 0);
          break;
      default:
 -        ob_debug("Caught signal %d. Exiting.\n", signal);
 +        ob_debug("Caught signal %d. Exiting.", signal);
          /* TERM and INT return a 0 code */
          ob_exit(!(signal == SIGTERM || signal == SIGINT));
      }
@@@ -484,7 -509,6 +484,7 @@@ static void print_help(
      g_print(_("  --sync              Run in synchronous mode\n"));
      g_print(_("  --debug             Display debugging output\n"));
      g_print(_("  --debug-focus       Display debugging output for focus handling\n"));
 +    g_print(_("  --debug-session     Display debugging output for session managment\n"));
      g_print(_("  --debug-xinerama    Split the display into fake xinerama screens\n"));
      g_print(_("\nPlease report bugs at %s\n"), PACKAGE_BUGREPORT);
  }
@@@ -531,19 -555,16 +531,19 @@@ static void parse_args(gint *argc, gcha
              xsync = TRUE;
          }
          else if (!strcmp(argv[i], "--debug")) {
 -            ob_debug_show_output(TRUE);
 -            ob_debug_enable(OB_DEBUG_SM, TRUE);
 +            ob_debug_enable(OB_DEBUG_NORMAL, TRUE);
              ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE);
          }
          else if (!strcmp(argv[i], "--debug-focus")) {
 -            ob_debug_show_output(TRUE);
 -            ob_debug_enable(OB_DEBUG_SM, TRUE);
 +            ob_debug_enable(OB_DEBUG_NORMAL, TRUE);
              ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE);
              ob_debug_enable(OB_DEBUG_FOCUS, TRUE);
          }
 +        else if (!strcmp(argv[i], "--debug-session")) {
 +            ob_debug_enable(OB_DEBUG_NORMAL, TRUE);
 +            ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE);
 +            ob_debug_enable(OB_DEBUG_SM, TRUE);
 +        }
          else if (!strcmp(argv[i], "--debug-xinerama")) {
              ob_debug_xinerama = TRUE;
          }
          }
          else if (!strcmp(argv[i], "--config-file")) {
              if (i == *argc - 1) /* no args left */
-                 /* not translated cuz it's sekret */
                  g_printerr(_("--config-file requires an argument\n"));
              else {
                  /* this will be in the current locale encoding, which is
                  ob_sm_save_file = g_strdup(argv[i+1]);
                  remove_args(argc, argv, i, 2);
                  --i; /* this arg was removed so go back */
 -                ob_debug_type(OB_DEBUG_SM, "--sm-save-file %s\n",
 +                ob_debug_type(OB_DEBUG_SM, "--sm-save-file %s",
                                ob_sm_save_file);
              }
          }
                  ob_sm_id = g_strdup(argv[i+1]);
                  remove_args(argc, argv, i, 2);
                  --i; /* this arg was removed so go back */
 -                ob_debug_type(OB_DEBUG_SM, "--sm-client-id %s\n", ob_sm_id);
 +                ob_debug_type(OB_DEBUG_SM, "--sm-client-id %s", ob_sm_id);
              }
          }
          else if (!strcmp(argv[i], "--sm-disable")) {
@@@ -613,10 -633,10 +612,10 @@@ static Cursor load_cursor(const gchar *
      Cursor c = None;
  
  #if USE_XCURSOR
 -    c = XcursorLibraryLoadCursor(ob_display, name);
 +    c = XcursorLibraryLoadCursor(obt_display, name);
  #endif
      if (c == None)
 -        c = XCreateFontCursor(ob_display, fontval);
 +        c = XCreateFontCursor(obt_display, fontval);
      return c;
  }
  
@@@ -648,14 -668,14 +647,14 @@@ void ob_reconfigure(
  void ob_exit(gint code)
  {
      exitcode = code;
 -    ob_main_loop_exit(ob_main_loop);
 +    obt_main_loop_exit(ob_main_loop);
  }
  
  void ob_exit_replace()
  {
      exitcode = 0;
      being_replaced = TRUE;
 -    ob_main_loop_exit(ob_main_loop);
 +    obt_main_loop_exit(ob_main_loop);
  }
  
  Cursor ob_cursor(ObCursor cursor)
diff --combined openbox/place.c
@@@ -76,7 -76,7 +76,7 @@@ static Rect **pick_head(ObClient *c
      /* try direct parent first */
      if ((p = client_direct_parent(c))) {
          add_choice(choice, client_monitor(p));
 -        ob_debug("placement adding choice %d for parent\n",
 +        ob_debug("placement adding choice %d for parent",
                   client_monitor(p));
      }
  
@@@ -92,7 -92,7 +92,7 @@@
                   itc->desktop == DESKTOP_ALL || c->desktop == DESKTOP_ALL))
              {
                  add_choice(choice, client_monitor(it->data));
 -                ob_debug("placement adding choice %d for group sibling\n",
 +                ob_debug("placement adding choice %d for group sibling",
                           client_monitor(it->data));
              }
          }
              if (itc != c) {
                  add_choice(choice, client_monitor(it->data));
                  ob_debug("placement adding choice %d for group sibling on "
 -                         "another desktop\n", client_monitor(it->data));
 +                         "another desktop", client_monitor(it->data));
              }
          }
      }
          config_place_monitor != OB_PLACE_MONITOR_MOUSE)
      {
          add_choice(choice, client_monitor(focus_client));
 -        ob_debug("placement adding choice %d for normal focused window\n",
 +        ob_debug("placement adding choice %d for normal focused window",
                   client_monitor(focus_client));
      }
  
          g_free(monitor);
          if (contain) {
              add_choice(choice, i);
 -            ob_debug("placement adding choice %d for mouse pointer\n", i);
 +            ob_debug("placement adding choice %d for mouse pointer", i);
              break;
          }
      }
@@@ -489,8 -489,9 +489,9 @@@ gboolean place_client(ObClient *client
      gboolean userplaced = FALSE;
  
      /* per-app settings override program specified position
-      * but not user specified */
-     if ((client->positioned & USPosition) ||
+      * but not user specified, unless pos_force is enabled */
+     if (((client->positioned & USPosition) &&
+          !(settings && settings->pos_given && settings->pos_force)) ||
          ((client->positioned & PPosition) &&
           !(settings && settings->pos_given)))
          return FALSE;
diff --combined openbox/stacking.c
@@@ -18,6 -18,7 +18,6 @@@
  */
  
  #include "openbox.h"
 -#include "prop.h"
  #include "screen.h"
  #include "focus.h"
  #include "client.h"
@@@ -26,7 -27,6 +26,7 @@@
  #include "window.h"
  #include "event.h"
  #include "debug.h"
 +#include "obt/prop.h"
  
  GList  *stacking_list = NULL;
  /*! When true, stacking changes will not be reflected on the screen.  This is
@@@ -55,8 -55,8 +55,8 @@@ void stacking_set_list(void
          }
      }
  
 -    PROP_SETA32(RootWindow(ob_display, ob_screen),
 -                net_client_list_stacking, window, (gulong*)windows, i);
 +    OBT_PROP_SETA32(obt_root(ob_screen), NET_CLIENT_LIST_STACKING, WINDOW,
 +                    (gulong*)windows, i);
  
      g_free(windows);
  }
@@@ -105,7 -105,7 +105,7 @@@ static void do_restack(GList *wins, GLi
  #endif
  
      if (!pause_changes)
 -        XRestackWindows(ob_display, win, i);
 +        XRestackWindows(obt_display, win, i);
      g_free(win);
  
      stacking_set_list();
@@@ -132,7 -132,7 +132,7 @@@ void stacking_temp_raise(ObWindow *wind
  
      win[1] = window_top(window);
      start = event_start_ignore_all_enters();
 -    XRestackWindows(ob_display, win, 2);
 +    XRestackWindows(obt_display, win, 2);
      event_end_ignore_all_enters(start);
  
      pause_changes = TRUE;
@@@ -150,7 -150,7 +150,7 @@@ void stacking_restore(void
      for (i = 1, it = stacking_list; it; ++i, it = g_list_next(it))
          win[i] = window_top(it->data);
      start = event_start_ignore_all_enters();
 -    XRestackWindows(ob_display, win, i);
 +    XRestackWindows(obt_display, win, i);
      event_end_ignore_all_enters(start);
      g_free(win);
  
@@@ -221,6 -221,15 +221,15 @@@ static void restack_windows(ObClient *s
      GList *modals = NULL;
      GList *trans = NULL;
  
+     if (raise) {
+         ObClient *p;
+         /* if a window is modal for another single window, then raise it to the
+            top too, the same is done with the focus order */
+         while (selected->modal && (p = client_direct_parent(selected)))
+             selected = p;
+     }
      /* remove first so we can't run into ourself */
      it = g_list_find(stacking_list, selected);
      g_assert(it);
@@@ -624,20 -633,21 +633,20 @@@ gboolean stacking_restack_request(ObCli
                      sibling->iconic))
      {
          ob_debug("Setting restack sibling to NULL, they are not on the same "
 -                 "desktop or it is iconified\n");
 +                 "desktop or it is iconified");
          sibling = NULL;
      }
  
      switch (detail) {
      case Below:
 -        ob_debug("Restack request Below for client %s sibling %s\n",
 +        ob_debug("Restack request Below for client %s sibling %s",
                   client->title, sibling ? sibling->title : "(all)");
          /* just lower it */
          stacking_lower(CLIENT_AS_WINDOW(client));
          ret = TRUE;
          break;
      case BottomIf:
 -        ob_debug("Restack request BottomIf for client %s sibling "
 -                 "%s\n",
 +        ob_debug("Restack request BottomIf for client %s sibling %s",
                   client->title, sibling ? sibling->title : "(all)");
          /* if this client occludes sibling (or anything if NULL), then
             lower it to the bottom */
          }
          break;
      case Above:
 -        ob_debug("Restack request Above for client %s sibling %s\n",
 +        ob_debug("Restack request Above for client %s sibling %s",
                   client->title, sibling ? sibling->title : "(all)");
          stacking_raise(CLIENT_AS_WINDOW(client));
          ret = TRUE;
          break;
      case TopIf:
 -        ob_debug("Restack request TopIf for client %s sibling %s\n",
 +        ob_debug("Restack request TopIf for client %s sibling %s",
                   client->title, sibling ? sibling->title : "(all)");
          if (stacking_occluded(client, sibling)) {
              stacking_raise(CLIENT_AS_WINDOW(client));
          }
          break;
      case Opposite:
 -        ob_debug("Restack request Opposite for client %s sibling "
 -                 "%s\n",
 +        ob_debug("Restack request Opposite for client %s sibling %s",
                   client->title, sibling ? sibling->title : "(all)");
          if (stacking_occluded(client, sibling)) {
              stacking_raise(CLIENT_AS_WINDOW(client));
diff --combined render/theme.c
@@@ -23,7 -23,7 +23,7 @@@
  #include "mask.h"
  #include "theme.h"
  #include "icon.h"
 -#include "parser/parse.h"
 +#include "obt/paths.h"
  
  #include <X11/Xlib.h>
  #include <X11/Xresource.h>
@@@ -897,13 -897,9 +897,9 @@@ RrTheme* RrThemeNew(const RrInstance *i
              j = (i > 0 ? 0 : 255);
              i = ABS(i*255/100);
  
-             theme->title_focused_shadow_color = RrColorNew(inst, j, j, j);
-             theme->title_focused_shadow_alpha = i;
              theme->osd_shadow_color = RrColorNew(inst, j, j, j);
              theme->osd_shadow_alpha = i;
          } else {
-             theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0);
-             theme->title_focused_shadow_alpha = 50;
              theme->osd_shadow_color = RrColorNew(inst, 0, 0, 0);
              theme->osd_shadow_alpha = 50;
          }
@@@ -1560,10 -1556,6 +1556,10 @@@ static XrmDatabase loaddb(const gchar *
              *path = g_path_get_dirname(s);
          g_free(s);
      } else {
 +        ObtPaths *p;
 +
 +        p = obt_paths_new();
 +
          /* XXX backwards compatibility, remove me sometime later */
          s = g_build_filename(g_get_home_dir(), ".themes", name,
                               "openbox-3", "themerc", NULL);
              *path = g_path_get_dirname(s);
          g_free(s);
  
 -        for (it = parse_xdg_data_dir_paths(); !db && it;
 -             it = g_slist_next(it))
 +        for (it = obt_paths_data_dirs(p); !db && it; it = g_slist_next(it))
          {
              s = g_build_filename(it->data, "themes", name,
                                   "openbox-3", "themerc", NULL);
                  *path = g_path_get_dirname(s);
              g_free(s);
          }
 +
 +        obt_paths_unref(p);
      }
  
      if (db == NULL) {