Merge branch 'backport' into work
authorDana Jansens <danakj@orodu.net>
Mon, 21 Dec 2009 15:43:38 +0000 (10:43 -0500)
committerDana Jansens <danakj@orodu.net>
Mon, 21 Dec 2009 15:43:38 +0000 (10:43 -0500)
1  2 
.gitignore
Makefile.am
data/rc.xml
openbox/event.c

diff --combined .gitignore
@@@ -32,7 -32,7 +32,7 @@@ m4/*.m
  missing
  .dirstamp
  openbox/openbox
 -parser/obparser-3.0.pc
 +parser/obparser-4.0.pc
  po/Makefile.in.in
  po/Makevars.template
  po/POTFILES
@@@ -48,11 -48,10 +48,11 @@@ po/en@boldquot.insert-heade
  po/en@quot.insert-header
  po/remove-potcdate.sed
  *.gmo
 -render/obrender-3.0.pc
 +render/obrender-4.0.pc
 +obt/obt-4.0.pc
  tools/gnome-panel-control/gnome-panel-control
  tools/gdm-control/gdm-control
- tools/obprop/obprop
+ tools/obxprop/obxprop
  version.h
  .libs
  .deps
diff --combined Makefile.am
@@@ -8,8 -8,7 +8,8 @@@ rcdir           = $(configdir)/openbo
  xsessionsdir    = $(datadir)/xsessions
  gnomewmfilesdir = $(datadir)/gnome/wm-properties
  pkgconfigdir    = $(libdir)/pkgconfig
 -pubincludedir   = $(includedir)/openbox/@OB_VERSION@/openbox
 +obtpubincludedir= $(includedir)/openbox/@OBT_VERSION@/obt
 +rrpubincludedir = $(includedir)/openbox/@RR_VERSION@/render
  pixmapdir       = $(datadir)/pixmaps
  xsddir          = $(datadir)/openbox
  secretbindir    = $(libdir)/openbox
@@@ -27,14 -26,14 +27,14 @@@ check_PROGRAMS = 
        render/rendertest
  
  lib_LTLIBRARIES = \
 -      parser/libobparser.la \
 +      obt/libobt.la \
        render/libobrender.la
  
  bin_PROGRAMS = \
        openbox/openbox \
        tools/gdm-control/gdm-control \
        tools/gnome-panel-control/gnome-panel-control \
-       tools/obprop/obprop
+       tools/obxprop/obxprop
  
  dist_secretbin_SCRIPTS = \
        tools/xdg-autostart/xdg-autostart
@@@ -48,13 -47,15 +48,13 @@@ nodist_bin_SCRIPTS = 
  
  render_rendertest_CPPFLAGS = \
        $(PANGO_CFLAGS) \
 -      $(XFT_CFLAGS) \
        $(GLIB_CFLAGS) \
        -DG_LOG_DOMAIN=\"RenderTest\"
  render_rendertest_LDADD = \
 -      parser/libobparser.la \
 +      obt/libobt.la \
        render/libobrender.la \
        $(GLIB_LIBS) \
        $(PANGO_LIBS) \
 -      $(XFT_LIBS) \
        $(XML_LIBS) \
        $(X_LIBS)
  render_rendertest_SOURCES = render/test.c
@@@ -64,14 -65,16 +64,14 @@@ render_libobrender_la_CPPFLAGS = 
        $(GLIB_CFLAGS) \
        $(XML_CFLAGS) \
        $(PANGO_CFLAGS) \
 -      $(XFT_CFLAGS) \
        -DG_LOG_DOMAIN=\"ObRender\" \
        -DDEFAULT_THEME=\"$(theme)\"
  render_libobrender_la_LDFLAGS = \
 -      -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 +      -version-info $(RR_CURRENT):$(RR_REVISION):$(RR_AGE)
  render_libobrender_la_LIBADD = \
 -      parser/libobparser.la \
 +      obt/libobt.la \
        $(X_LIBS) \
        $(PANGO_LIBS) \
 -      $(XFT_LIBS) \
        $(GLIB_LIBS) \
        $(XML_LIBS)
  render_libobrender_la_SOURCES = \
        render/theme.h \
        render/theme.c
  
 -## parser ##
 +## obt ##
  
 -parser_libobparser_la_CPPFLAGS = \
 +obt_libobt_la_CPPFLAGS = \
 +      $(XINERAMA_CFLAGS) \
 +      $(XKB_CFLAGS) \
 +      $(XRANDR_CFLAGS) \
 +      $(XSHAPE_CFLAGS) \
 +      $(XSYNC_CFLAGS) \
        $(GLIB_CFLAGS) \
        $(XML_CFLAGS) \
 -      -DG_LOG_DOMAIN=\"ObParser\" \
 +      -DG_LOG_DOMAIN=\"Obt\" \
        -DLOCALEDIR=\"$(localedir)\" \
        -DDATADIR=\"$(datadir)\" \
        -DCONFIGDIR=\"$(configdir)\"
 -parser_libobparser_la_LDFLAGS = \
 -      -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 -parser_libobparser_la_LIBADD = \
 +obt_libobt_la_LDFLAGS = \
 +      -version-info $(OBT_CURRENT):$(OBT_REVISION):$(OBT_AGE)
 +obt_libobt_la_LIBADD = \
 +      $(XINERAMA_LIBS) \
 +      $(XKB_LIBS) \
 +      $(XRANDR_LIBS) \
 +      $(XSHAPE_LIBS) \
 +      $(XSYNC_LIBS) \
        $(GLIB_LIBS) \
 -      $(XML_LIBS) 
 -parser_libobparser_la_SOURCES = \
 -      parser/parse.h \
 -      parser/parse.c
 +      $(XML_LIBS)
 +obt_libobt_la_SOURCES = \
 +      obt/display.h \
 +      obt/display.c \
 +      obt/internal.h \
 +      obt/keyboard.h \
 +      obt/keyboard.c \
 +      obt/mainloop.h \
 +      obt/mainloop.c \
 +      obt/parse.h \
 +      obt/parse.c \
 +      obt/paths.h \
 +      obt/paths.c \
 +      obt/prop.h \
 +      obt/prop.c \
 +      obt/util.h \
 +      obt/xevent.h \
 +      obt/xevent.c
  
  ## openbox ##
  
  openbox_openbox_CPPFLAGS = \
        $(SM_CFLAGS) \
 -      $(XINERAMA_CFLAGS) \
 -      $(XKB_CFLAGS) \
 -      $(XRANDR_CFLAGS) \
 -      $(XSHAPE_CFLAGS) \
 -      $(XSYNC_CFLAGS) \
        $(X_CFLAGS) \
        $(XCURSOR_CFLAGS) \
        $(SM_CFLAGS) \
        -DG_LOG_DOMAIN=\"Openbox\"
  openbox_openbox_LDADD = \
        $(SM_LIBS) \
 -      $(XINERAMA_LIBS) \
 -      $(XKB_LIBS) \
 -      $(XRANDR_LIBS) \
 -      $(XSHAPE_LIBS) \
 -      $(XSYNC_LIBS) \
        $(GLIB_LIBS) \
        $(X_LIBS) \
        $(XCURSOR_LIBS) \
        $(EFENCE_LIBS) \
        $(LIBINTL) \
        render/libobrender.la \
 -      parser/libobparser.la
 +      obt/libobt.la
  openbox_openbox_LDFLAGS = -export-dynamic
  openbox_openbox_SOURCES = \
        gettext.h \
        openbox/actions/resizerelative.c \
        openbox/actions/restart.c \
        openbox/actions/shade.c \
 +      openbox/actions/shadelowerraise.c \
        openbox/actions/showdesktop.c \
        openbox/actions/showmenu.c \
        openbox/actions/unfocus.c \
        openbox/dock.h \
        openbox/event.c \
        openbox/event.h \
 -      openbox/extensions.c \
 -      openbox/extensions.h \
        openbox/focus.c \
        openbox/focus.h \
        openbox/focus_cycle.c \
        openbox/keyboard.h \
        openbox/keytree.c \
        openbox/keytree.h \
 -      openbox/mainloop.c \
 -      openbox/mainloop.h \
        openbox/menuframe.c \
        openbox/menuframe.h \
        openbox/menu.c \
        openbox/menu.h \
        openbox/misc.h \
 -      openbox/modkeys.c \
 -      openbox/modkeys.h \
        openbox/mouse.c \
        openbox/mouse.h \
        openbox/moveresize.c \
        openbox/prompt.h \
        openbox/popup.c \
        openbox/popup.h \
 -      openbox/prop.c \
 -      openbox/prop.h \
        openbox/resist.c \
        openbox/resist.h \
        openbox/screen.c \
        openbox/translate.c \
        openbox/translate.h \
        openbox/window.c \
 -      openbox/window.h \
 -      openbox/xerror.c \
 -      openbox/xerror.h
 -
 +      openbox/window.h
  
  ## gnome-panel-control ##
  
@@@ -290,16 -289,16 +290,16 @@@ tools_gnome_panel_control_gnome_panel_c
  tools_gnome_panel_control_gnome_panel_control_SOURCES = \
        tools/gnome-panel-control/gnome-panel-control.c
  
- ## obprop ##
+ ## obxprop ##
  
- tools_obprop_obprop_CPPFLAGS = \
+ tools_obxprop_obxprop_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        $(X_CFLAGS)
- tools_obprop_obprop_LDADD = \
+ tools_obxprop_obxprop_LDADD = \
        $(GLIB_LIBS) \
        $(X_LIBS)
- tools_obprop_obprop_SOURCES = \
-       tools/obprop/obprop.c
+ tools_obxprop_obxprop_SOURCES = \
+       tools/obxprop/obxprop.c
  
  ## gdm-control ##
  
@@@ -407,7 -406,7 +407,7 @@@ dist_syscrash_theme_DATA= 
  
  ## public headers ##
  
 -pubinclude_HEADERS = \
 +rrpubinclude_HEADERS = \
        render/color.h \
        render/font.h \
        render/geom.h \
        render/mask.h \
        render/render.h \
        render/theme.h \
 -      parser/parse.h
 -
 -nodist_pubinclude_HEADERS = \
 -      version.h
 +      render/version.h
 +
 +obtpubinclude_HEADERS = \
 +      obt/display.h \
 +      obt/keyboard.h \
 +      obt/mainloop.h \
 +      obt/parse.h \
 +      obt/paths.h \
 +      obt/prop.h \
 +      obt/util.h \
 +      obt/version.h \
 +      obt/xevent.h
  
  nodist_pkgconfig_DATA = \
 -      render/obrender-3.0.pc \
 -      parser/obparser-3.0.pc
 +      render/obrender-4.0.pc \
 +      obt/obt-4.0.pc
  
  ## data ##
  
@@@ -484,6 -475,7 +484,6 @@@ nodist_xsessions_DATA = 
        data/xsession/openbox-kde.desktop
  
  dist_noinst_DATA = \
 -      version.h.in \
        data/autostart.sh.in \
        data/rc.xsd \
        data/menu.xsd \
        doc/openbox-gnome-session.1.in \
        doc/openbox-kde-session.1.sgml \
        doc/openbox-kde-session.1.in \
 -      render/obrender-3.0.pc.in \
 -      parser/obparser-3.0.pc.in \
 +      render/version.h.in \
 +      render/obrender-4.0.pc.in \
 +      obt/obt-4.0.pc.in \
 +      obt/version.h.in \
        tools/themeupdate/themeupdate.py \
        tests/hideshow.py \
        tests/Makefile \
@@@ -560,7 -550,7 +560,7 @@@ CLEANFILES = 
  #       $(MAKE) -$(MAKEFLAGS) -C doc/doxygen doc
  
  distclean-local:
 -      for d in . m4 po render; do \
 +      for d in . m4 po render parser obt openbox; do \
                for p in core core.* gmon.out *\~ *.orig *.rej .\#*; do \
                        rm -f "$$d/$$p"; \
                done \
diff --combined data/rc.xml
      <slant>normal</slant>
      <!-- 'italic' or 'normal' -->
    </font>
 -  <font place="OnScreenDisplay">
 +  <font place="ActiveOnScreenDisplay">
 +    <name>sans</name>
 +    <size>9</size>
 +    <!-- font size in points -->
 +    <weight>bold</weight>
 +    <!-- 'bold' or 'normal' -->
 +    <slant>normal</slant>
 +    <!-- 'italic' or 'normal' -->
 +  </font>
 +  <font place="InactiveOnScreenDisplay">
      <name>sans</name>
      <size>9</size>
      <!-- font size in points -->
      </action>
    </keybind>
  
 +  <!-- Keybindings for window switching with the arrow keys -->
 +  <keybind key="W-S-Right">
 +    <action name="DirectionalCycleWindows">
 +      <direction>right</direction>
 +    </action>
 +  </keybind>
 +  <keybind key="W-S-Left">
 +    <action name="DirectionalCycleWindows">
 +      <direction>left</direction>
 +    </action>
 +  </keybind>
 +  <keybind key="W-S-Up">
 +    <action name="DirectionalCycleWindows">
 +      <direction>up</direction>
 +    </action>
 +  </keybind>
 +  <keybind key="W-S-Down">
 +    <action name="DirectionalCycleWindows">
 +      <direction>down</direction>
 +    </action>
 +  </keybind>
 +
    <!-- Keybindings for running applications -->
    <keybind key="W-e">
      <action name="Execute">
      </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>
    # this is an example with comments through out. use these to make your
    # own rules, but without the comments of course.
  
-   <application name="the window's _OB_NAME property (see obprop)"
-               class="the window's _OB_CLASS property (see obprop)"
-                role="the window's _OB_ROLE property (see obprop)"
-                type="the window's _NET_WM_WINDOW_TYPE (see obprob)..
+   <application name="the window's _OB_NAME property (see obxprop)"
+               class="the window's _OB_CLASS property (see obxprop)"
+                role="the window's _OB_ROLE property (see obxprop)"
+                type="the window's _NET_WM_WINDOW_TYPE (see obxprob)..
                        (if unspecified, then it is 'dialog' for child windows)">
    # the name or the class can be set, or both. this is used to match
    # windows when they appear. role can optionally be set as well, to
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 "prompt.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>
@@@ -84,8 -87,8 +84,8 @@@ 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 gboolean event_handle_prompt(ObPrompt *p, XEvent *e);
  static void event_handle_dock(ObDock *s, XEvent *e);
  static void event_handle_dockapp(ObDockApp *app, XEvent *e);
@@@ -97,7 -100,6 +97,7 @@@ static void event_ignore_enter_range(gu
  static void focus_delay_dest(gpointer data);
  static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
  static gboolean focus_delay_func(gpointer data);
 +static gboolean unfocus_delay_func(gpointer data);
  static void focus_delay_client_dest(ObClient *client, gpointer data);
  
  Time event_curtime = CurrentTime;
@@@ -123,9 -125,9 +123,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;
      }
  }
@@@ -135,7 -137,7 +135,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);
@@@ -162,15 -164,9 +162,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
@@@ -238,8 -232,8 +238,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;
          }
@@@ -267,34 -261,34 +267,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;
@@@ -324,7 -318,7 +324,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.. */
@@@ -417,7 -411,6 +417,7 @@@ static void print_focusevent(XEvent *e
      case NotifyGrab:         modestr="NotifyGrab";         break;
      case NotifyUngrab:       modestr="NotifyUngrab";       break;
      case NotifyWhileGrabbed: modestr="NotifyWhileGrabbed"; break;
 +    default:                 g_assert_not_reached();
      }
      switch (detail) {
      case NotifyAncestor:    detailstr="NotifyAncestor";    break;
      case NotifyPointer:     detailstr="NotifyPointer";     break;
      case NotifyPointerRoot: detailstr="NotifyPointerRoot"; break;
      case NotifyDetailNone:  detailstr="NotifyDetailNone";  break;
 +    default:                g_assert_not_reached();
      }
  
      if (mode == NotifyGrab || mode == NotifyUngrab)
  
      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);
@@@ -462,15 -454,13 +462,15 @@@ 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;
      ObPrompt *prompt = NULL;
  
      /* make a copy we can mangle */
      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);
              /* events on clients can be events on prompt windows too */
              prompt = client->prompt;
              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;
 -        case Window_Prompt:
 +        case OB_WINDOW_CLASS_PROMPT:
              prompt = WINDOW_AS_PROMPT(obwin);
              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, NULL);
 +        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("Keyboard map changed. Reloading keyboard bindings.\n");
 +        ob_debug("Keyboard map changed. Reloading keyboard bindings.");
          ob_set_state(OB_STATE_RECONFIGURING);
 -        modkeys_shutdown(TRUE);
 -        modkeys_startup(TRUE);
 +        obt_keyboard_reload();
          keyboard_rebind();
          ob_set_state(OB_STATE_RUNNING);
      }
      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)
      else 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);
@@@ -755,7 -747,7 +755,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:
@@@ -825,17 -817,17 +825,17 @@@ void event_enter_client(ObClient *clien
          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;
      }
  }
  
 +void event_leave_client(ObClient *client)
 +{
 +    g_assert(config_focus_follow);
 +
 +    if (is_enter_focus_event_ignored(event_curserial)) {
 +        ob_debug_type(OB_DEBUG_FOCUS, "Ignoring leave event with serial %lu\n"
 +                      "on client 0x%x", event_curserial, client->window);
 +        return;
 +    }
 +
 +    if (client == focus_client) {
 +        if (config_focus_delay) {
 +            ObFocusDelayData *data;
 +
 +            obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func);
 +
 +            data = g_new(ObFocusDelayData, 1);
 +            data->client = client;
 +            data->time = event_curtime;
 +            data->serial = event_curserial;
 +
 +            obt_main_loop_timeout_add(ob_main_loop,
 +                                      config_focus_delay * 1000,
 +                                      unfocus_delay_func,
 +                                      data, focus_delay_cmp, focus_delay_dest);
 +        } else {
 +            ObFocusDelayData data;
 +            data.client = client;
 +            data.time = event_curtime;
 +            data.serial = event_curserial;
 +            unfocus_delay_func(&data);
 +        }
 +    }
 +}
 +
  static gboolean *context_to_button(ObFrame *f, ObFrameContext con, gboolean press)
  {
      if (press) {
@@@ -920,12 -877,12 +920,12 @@@ static void compress_client_message_eve
                                            Atom msgtype)
  {
      /* compress changes into a single change */
 -    while (XCheckTypedWindowEvent(ob_display, window, e->type, ce)) {
 +    while (XCheckTypedWindowEvent(obt_display, 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;
@@@ -1044,24 -1001,21 +1044,24 @@@ 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));
              if (grab_on_keyboard())
                  break;
 -            if (config_focus_follow && config_focus_delay &&
 +            if (config_focus_follow &&
                  /* leave inferior events can happen when the mouse goes onto
                     the window's border and then into the window before the
                     delay is up */
                  e->xcrossing.detail != NotifyInferior)
              {
 -                ob_main_loop_timeout_remove_data(ob_main_loop,
 -                                                 focus_delay_func,
 -                                                 client, FALSE);
 +                if (config_focus_delay)
 +                    obt_main_loop_timeout_remove_data(ob_main_loop,
 +                                                      focus_delay_func,
 +                                                      client, FALSE);
 +                if (config_unfocus_leave)
 +                    event_leave_client(client);
              }
              break;
          default:
              {
                  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,
                                e->xcrossing.serial,
                                (client?client->window:0));
 -                if (config_focus_follow)
 +                if (config_focus_follow) {
 +                    if (config_focus_delay)
 +                        obt_main_loop_timeout_remove_data(ob_main_loop,
 +                                                          unfocus_delay_func,
 +                                                          client, FALSE);
                      event_enter_client(client);
 +                }
              }
              break;
          default:
          RECT_TO_DIMS(client->area, x, y, w, h);
  
          ob_debug("ConfigureRequest for \"%s\" desktop %d wmstate %d "
 -                 "visible %d\n"
 -                 "                     x %d y %d w %d h %d b %d\n",
 +                 "visible %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_client_message_event(e, &ce, client->window, msgtype);
              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_client_message_event(e, &ce, client->window, msgtype);
              if ((unsigned)e->xclient.data.l[0] < screen_num_desktops ||
                  (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", client->title);
 +                              "missing source indication", client->title);
              client_activate(client, FALSE, 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");
 +            int x, y, w, h, lw, lh;
 +
 +            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);
  
 -            /* make sure the client's sizes are within its bounds, but only
 -               reconfigure the window if it needs to. emacs will update its
 -               normal hints every time it receives a conigurenotify */
 -            client_reconfigure(client, FALSE);
 -        } else if (msgtype == prop_atoms.motif_wm_hints) {
 +            x = client->area.x;
 +            y = client->area.y;
 +            w = client->area.width;
 +            h = client->area.height;
 +
 +            /* apply the new normal hints */
 +            client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
 +            /* make sure the window is visible, and if the window is resized
 +               off-screen due to the normal hints changing then this will push
 +               it back onto the screen. */
 +            client_find_onscreen(client, &x, &y, w, h, FALSE);
 +
 +            /* make sure the client's sizes are within its bounds, but don't
 +               make it reply with a configurenotify unless something changed.
 +               emacs will update its normal hints every time it receives a
 +               configurenotify */
 +            client_configure(client, x, y, w, h, FALSE, TRUE, FALSE);
 +        } else if (msgtype == OBT_PROP_ATOM(MOTIF_WM_HINTS)) {
              client_get_mwm_hints(client);
              /* This can override some mwm hints */
              client_get_type_and_transientness(client);
              /* 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 ||
 -                 msgtype == prop_atoms.net_wm_strut_partial) {
 +        else if (msgtype == OBT_PROP_ATOM(NET_WM_STRUT) ||
 +                 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
  #ifdef SHAPE
          {
              int kind;
 -            if (extensions_shape && e->type == extensions_shape_event_basep) {
 +            if (obt_display_extension_shape &&
 +                e->type == obt_display_extension_shape_basep)
 +            {
                  switch (((XShapeEvent*)e)->kind) {
                      case ShapeBounding:
                      case ShapeClip:
                          client->shaped_input = ((XShapeEvent*)e)->shaped;
                          kind = ShapeInput;
                          break;
 +                    default:
 +                        g_assert_not_reached();
                  }
                  frame_adjust_shape_kind(client->frame, kind);
              }
@@@ -1691,11 -1623,11 +1691,11 @@@ static void event_handle_dockapp(ObDock
              app->ignore_unmaps--;
              break;
          }
 -        dock_remove(app, TRUE);
 +        dock_unmanage(app, TRUE);
          break;
      case DestroyNotify:
      case ReparentNotify:
 -        dock_remove(app, FALSE);
 +        dock_unmanage(app, FALSE);
          break;
      case ConfigureNotify:
          dock_app_configure(app, e->xconfigure.width, e->xconfigure.height);
@@@ -1742,160 -1674,125 +1742,160 @@@ static gboolean event_handle_prompt(ObP
      return FALSE;
  }
  
 -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 || ev->type == ButtonPress) {
 +        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)))
 +            {
 +                if (ev->type == ButtonPress && e->frame->child)
 +                    menu_frame_select(e->frame->child, NULL, TRUE);
 +                menu_frame_select(e->frame, e, TRUE);
 +                if (ev->type == ButtonRelease)
 +                    menu_entry_frame_execute(e, ev->xbutton.state);
 +            }
 +            else if (ev->type == ButtonRelease)
 +                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 (ob_keycode_match(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 (ob_keycode_match(keycode, OB_KEY_LEFT)) {
 -            /* Left goes to the parent menu */
 -            if (frame->parent)
 -                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 (ob_keycode_match(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 (ob_keycode_match(keycode, OB_KEY_UP)) {
 -            menu_frame_select_previous(frame);
 -            ret = TRUE;
 -        }
 +            if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) {
 +                menu_frame_hide_all();
 +                ret = TRUE;
 +            }
  
 -        else if (ob_keycode_match(keycode, OB_KEY_DOWN)) {
 -            menu_frame_select_next(frame);
 -            ret = TRUE;
 -        }
 -    }
 +            else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
 +                /* Left goes to the parent menu */
 +                if (frame->parent)
 +                    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 (ob_keycode_match(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 (ob_keycode_match(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 (ob_keycode_match(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 (ob_keycode_match(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 (ob_keycode_match(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);
  
 -                if (unikey == entrykey) {
 -                    if (found == NULL) found = e;
 -                    ++num_found;
 +                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;
                  }
  
 -                /* 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)
              break;
  
          if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
-             (f = find_active_menu()) && f->selected == e &&
-             e->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU)
+             (f = find_active_menu()) && f->selected == e)
          {
              ObMenuEntryFrame *u = menu_entry_frame_under(ev->xcrossing.x_root,
                                                           ev->xcrossing.y_root);
                  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 */
@@@ -2000,37 -1925,22 +1999,37 @@@ static gboolean focus_delay_func(gpoint
      return FALSE; /* no repeat */
  }
  
 +static gboolean unfocus_delay_func(gpointer data)
 +{
 +    ObFocusDelayData *d = data;
 +    Time old = event_curtime;
 +
 +    event_curtime = d->time;
 +    event_curserial = d->serial;
 +    focus_nothing();
 +    event_curtime = old;
 +    return FALSE; /* no repeat */
 +}
 +
  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);
 +    obt_main_loop_timeout_remove_data(ob_main_loop, unfocus_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);
 +    obt_main_loop_timeout_remove(ob_main_loop, unfocus_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(gulong serial)
@@@ -2087,24 -1997,24 +2086,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(guint32 t1, guint32 t2)
@@@ -2139,9 -2049,9 +2138,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;
  }