Merge branch 'backport' into work
authorMikael Magnusson <mikachu@gmail.com>
Sun, 20 Sep 2009 13:50:13 +0000 (15:50 +0200)
committerMikael Magnusson <mikachu@gmail.com>
Sun, 20 Sep 2009 14:03:48 +0000 (16:03 +0200)
1  2 
openbox/client.c
openbox/client.h
openbox/event.c

diff --combined openbox/client.c
  #include "debug.h"
  #include "startupnotify.h"
  #include "dock.h"
 -#include "xerror.h"
  #include "screen.h"
  #include "moveresize.h"
  #include "ping.h"
  #include "place.h"
 -#include "prop.h"
 -#include "extensions.h"
  #include "frame.h"
  #include "session.h"
  #include "event.h"
@@@ -33,7 -36,6 +33,7 @@@
  #include "focus.h"
  #include "stacking.h"
  #include "openbox.h"
 +#include "hooks.h"
  #include "group.h"
  #include "config.h"
  #include "menuframe.h"
@@@ -41,8 -43,6 +41,8 @@@
  #include "mouse.h"
  #include "render/render.h"
  #include "gettext.h"
 +#include "obt/display.h"
 +#include "obt/prop.h"
  
  #ifdef HAVE_UNISTD_H
  #  include <unistd.h>
@@@ -80,7 -80,6 +80,6 @@@ static void client_get_area(ObClient *s
  static void client_get_desktop(ObClient *self);
  static void client_get_state(ObClient *self);
  static void client_get_shaped(ObClient *self);
- static void client_get_mwm_hints(ObClient *self);
  static void client_get_colormap(ObClient *self);
  static void client_set_desktop_recursive(ObClient *self,
                                           guint target,
@@@ -184,8 -183,8 +183,8 @@@ void client_set_list(void
      } else
          windows = NULL;
  
 -    PROP_SETA32(RootWindow(ob_display, ob_screen),
 -                net_client_list, window, (gulong*)windows, size);
 +    OBT_PROP_SETA32(obt_root(ob_screen), NET_CLIENT_LIST, WINDOW,
 +                    (gulong*)windows, size);
  
      if (windows)
          g_free(windows);
      stacking_set_list();
  }
  
 -void client_manage_all(void)
 -{
 -    guint i, j, nchild;
 -    Window w, *children;
 -    XWMHints *wmhints;
 -    XWindowAttributes attrib;
 -
 -    XQueryTree(ob_display, RootWindow(ob_display, ob_screen),
 -               &w, &w, &children, &nchild);
 -
 -    /* remove all icon windows from the list */
 -    for (i = 0; i < nchild; i++) {
 -        if (children[i] == None) continue;
 -        wmhints = XGetWMHints(ob_display, children[i]);
 -        if (wmhints) {
 -            if ((wmhints->flags & IconWindowHint) &&
 -                (wmhints->icon_window != children[i]))
 -                for (j = 0; j < nchild; j++)
 -                    if (children[j] == wmhints->icon_window) {
 -                        children[j] = None;
 -                        break;
 -                    }
 -            XFree(wmhints);
 -        }
 -    }
 -
 -    /* manage windows in reverse order from how they were originally mapped.
 -       this is an attempt to manage children windows before their parents, so
 -       that when the parent is mapped, it can find the child */
 -    for (i = 0; i < nchild; ++i) {
 -        if (children[i] == None)
 -            continue;
 -        if (XGetWindowAttributes(ob_display, children[i], &attrib)) {
 -            if (attrib.override_redirect) continue;
 -
 -            if (attrib.map_state != IsUnmapped)
 -                client_manage(children[i], NULL);
 -        }
 -    }
 -    XFree(children);
 -}
 -
  void client_manage(Window window, ObPrompt *prompt)
  {
      ObClient *self;
 -    XEvent e;
 -    XWindowAttributes attrib;
      XSetWindowAttributes attrib_set;
 -    XWMHints *wmhint;
      gboolean activate = FALSE;
      ObAppSettings *settings;
      gboolean transient = FALSE;
      Time launch_time, map_time;
      guint32 user_time;
  
 -    grab_server(TRUE);
 -
 -    /* check if it has already been unmapped by the time we started
 -       mapping. the grab does a sync so we don't have to here */
 -    if (XCheckTypedWindowEvent(ob_display, window, DestroyNotify, &e) ||
 -        XCheckTypedWindowEvent(ob_display, window, UnmapNotify, &e))
 -    {
 -        XPutBackEvent(ob_display, &e);
 -
 -        ob_debug("Trying to manage unmapped window. Aborting that.\n");
 -        grab_server(FALSE);
 -        return; /* don't manage it */
 -    }
 -
 -    /* make sure it isn't an override-redirect window */
 -    if (!XGetWindowAttributes(ob_display, window, &attrib) ||
 -        attrib.override_redirect)
 -    {
 -        grab_server(FALSE);
 -        return; /* don't manage it */
 -    }
 -
 -    /* is the window a docking app */
 -    if ((wmhint = XGetWMHints(ob_display, window))) {
 -        if ((wmhint->flags & StateHint) &&
 -            wmhint->initial_state == WithdrawnState)
 -        {
 -            dock_add(window, wmhint);
 -            grab_server(FALSE);
 -            XFree(wmhint);
 -            return;
 -        }
 -        XFree(wmhint);
 -    }
 -
 -    ob_debug("Managing window: 0x%lx\n", window);
 +    ob_debug("Managing window: 0x%lx", window);
  
      map_time = event_get_server_time();
  
      attrib_set.event_mask = CLIENT_EVENTMASK |
          (prompt ? prompt->event_mask : 0);
      attrib_set.do_not_propagate_mask = CLIENT_NOPROPAGATEMASK;
 -    XChangeWindowAttributes(ob_display, window,
 +    XChangeWindowAttributes(obt_display, window,
                              CWEventMask|CWDontPropagate, &attrib_set);
  
      /* create the ObClient struct, and populate it from the hints on the
         window */
      self = g_new0(ObClient, 1);
 -    self->obwin.type = Window_Client;
 +    self->obwin.type = OB_WINDOW_CLASS_CLIENT;
      self->window = window;
      self->prompt = prompt;
  
      /* get all the stuff off the window */
      client_get_all(self, TRUE);
  
 -    ob_debug("Window type: %d\n", self->type);
 -    ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0);
 -    ob_debug("Window name: %s class: %s role: %s\n", self->name, self->class, self->role);
 +    ob_debug("Window type: %d", self->type);
 +    ob_debug("Window group: 0x%x", self->group?self->group->leader:0);
 +    ob_debug("Window name: %s class: %s role: %s", self->name, self->class, self->role);
  
      /* per-app settings override stuff from client_get_all, and return the
         settings for other uses too. the returned settings is a shallow copy,
         should be reparented back to root automatically, unless we are managing
         an internal ObPrompt window  */
      if (!self->prompt)
 -        XChangeSaveSet(ob_display, window, SetModeInsert);
 +        XChangeSaveSet(obt_display, window, SetModeInsert);
  
      /* create the decoration frame for the client window */
      self->frame = frame_new(self);
      /* tell startup notification that this app started */
      launch_time = sn_app_started(self->startup_id, self->class, self->name);
  
 -    if (!PROP_GET32(self->window, net_wm_user_time, cardinal, &user_time))
 +    if (!OBT_PROP_GET32(self->window, NET_WM_USER_TIME, CARDINAL, &user_time))
          user_time = map_time;
  
      /* do this after we have a frame.. it uses the frame to help determine the
      }
  
      /* remove the client's border */
 -    XSetWindowBorderWidth(ob_display, self->window, 0);
 +    XSetWindowBorderWidth(obt_display, self->window, 0);
  
      /* adjust the frame to the client's size before showing or placing
         the window */
  
      /* figure out placement for the window if the window is new */
      if (ob_state() == OB_STATE_RUNNING) {
 -        ob_debug("Positioned: %s @ %d %d\n",
 +        ob_debug("Positioned: %s @ %d %d",
                   (!self->positioned ? "no" :
                    (self->positioned == PPosition ? "program specified" :
                     (self->positioned == USPosition ? "user specified" :
                       "program + user specified" :
                       "BADNESS !?")))), place.x, place.y);
  
 -        ob_debug("Sized: %s @ %d %d\n",
 +        ob_debug("Sized: %s @ %d %d",
                   (!self->sized ? "no" :
                    (self->sized == PSize ? "program specified" :
                     (self->sized == USSize ? "user specified" :
          place.width = MIN(place.width, a->width);
          place.height = MIN(place.height, a->height);
  
 -        ob_debug("setting window size to %dx%d\n", place.width, place.height);
 +        ob_debug("setting window size to %dx%d", place.width, place.height);
  
          /* get the size of the client back */
          place.width -= self->frame->size.left + self->frame->size.right;
      }
  
      ob_debug("placing window 0x%x at %d, %d with size %d x %d. "
 -             "some restrictions may apply\n",
 +             "some restrictions may apply",
               self->window, place.x, place.y, place.width, place.height);
      if (self->session)
          ob_debug("  but session requested %d, %d  %d x %d instead, "
 -                 "overriding\n",
 +                 "overriding",
                   self->session->x, self->session->y,
                   self->session->w, self->session->h);
  
      g_free(monitor);
      monitor = NULL;
  
 -    ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s\n",
 +    ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s",
                    activate ? "yes" : "no");
      if (activate) {
          gboolean raise = FALSE;
          /* This is focus stealing prevention */
          ob_debug_type(OB_DEBUG_FOCUS,
                        "Want to focus new window 0x%x at time %u "
 -                      "launched at %u (last user interaction time %u)\n",
 +                      "launched at %u (last user interaction time %u)",
                        self->window, map_time, launch_time,
                        event_last_user_time);
 +        ob_debug_type(OB_DEBUG_FOCUS,
 +                      "Current focus_client: %s",
 +                      (focus_client ? focus_client->title : "(none)"));
 +        ob_debug_type(OB_DEBUG_FOCUS,
 +                      "parent focused: %d  relative focused: %d",
 +                      parent_focused, relative_focused);
  
          if (menu_frame_visible || moveresize_in_progress) {
              activate = FALSE;
              ob_debug_type(OB_DEBUG_FOCUS,
                            "Not focusing the window because the user is inside "
                            "an Openbox menu or is move/resizing a window and "
 -                          "we don't want to interrupt them\n");
 +                          "we don't want to interrupt them");
          }
  
          /* if it's on another desktop */
              raise = TRUE;
              ob_debug_type(OB_DEBUG_FOCUS,
                            "Not focusing the window because its on another "
 -                          "desktop\n");
 +                          "desktop");
          }
          /* If something is focused... */
          else if (focus_client) {
                  ob_debug_type(OB_DEBUG_FOCUS,
                                "Not focusing the window because the user is "
                                "working in another window that is not "
 -                              "its parent\n");
 +                              "its parent");
              }
              /* If the new window is a transient (and its relatives aren't
                 focused) */
                  activate = FALSE;
                  ob_debug_type(OB_DEBUG_FOCUS,
                                "Not focusing the window because it is a "
 -                              "transient, and its relatives aren't focused\n");
 +                              "transient, and its relatives aren't focused");
              }
              /* Don't steal focus from globally active clients.
                 I stole this idea from KWin. It seems nice.
                  activate = FALSE;
                  ob_debug_type(OB_DEBUG_FOCUS,
                                "Not focusing the window because a globally "
 -                              "active client has focus\n");
 +                              "active client has focus");
              }
              /* Don't move focus if it's not going to go to this window
                 anyway */
                  raise = TRUE;
                  ob_debug_type(OB_DEBUG_FOCUS,
                                "Not focusing the window because another window "
 -                              "would get the focus anyway\n");
 +                              "would get the focus anyway");
              }
              /* Don't move focus if the window is not visible on the current
                 desktop and none of its relatives are focused */
          if (!activate) {
              ob_debug_type(OB_DEBUG_FOCUS,
                            "Focus stealing prevention activated for %s at "
 -                          "time %u (last user interaction time %u)\n",
 +                          "time %u (last user interaction time %u)",
                            self->title, map_time, event_last_user_time);
              /* if the client isn't focused, then hilite it so the user
                 knows it is there */
  
      /* add to client list/map */
      client_list = g_list_append(client_list, self);
 -    g_hash_table_insert(window_map, &self->window, self);
 +    window_add(&self->window, CLIENT_AS_WINDOW(self));
  
      /* this has to happen after we're in the client_list */
      if (STRUT_EXISTS(self->strut))
      /* free the ObAppSettings shallow copy */
      g_free(settings);
  
 -    ob_debug("Managed window 0x%lx plate 0x%x (%s)\n",
 +    ob_debug("Managed window 0x%lx plate 0x%x (%s)",
               window, self->frame->window, self->class);
  
 -    return;
 +    hooks_queue(OB_HOOK_WIN_NEW, self);
  }
  
  ObClient *client_fake_manage(Window window)
      ObClient *self;
      ObAppSettings *settings;
  
 -    ob_debug("Pretend-managing window: %lx\n", window);
 +    ob_debug("Pretend-managing window: %lx", window);
  
      /* do this minimal stuff to figure out the client's decorations */
  
      self->frame = frame_new(self);
      frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
  
 -    ob_debug("gave extents left %d right %d top %d bottom %d\n",
 +    ob_debug("gave extents left %d right %d top %d bottom %d",
               self->frame->size.left, self->frame->size.right,
               self->frame->size.top, self->frame->size.bottom);
  
@@@ -634,7 -707,7 +633,7 @@@ void client_unmanage(ObClient *self
      GSList *it;
      gulong ignore_start;
  
 -    ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)\n",
 +    ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)",
               self->window, self->frame->window,
               self->class, self->title ? self->title : "");
  
  
      /* we dont want events no more. do this before hiding the frame so we
         don't generate more events */
 -    XSelectInput(ob_display, self->window, NoEventMask);
 +    XSelectInput(obt_display, self->window, NoEventMask);
  
      /* ignore enter events from the unmap so it doesnt mess with the focus */
      if (!config_focus_under_mouse)
  
      frame_hide(self->frame);
      /* flush to send the hide to the server quickly */
 -    XFlush(ob_display);
 +    XFlush(obt_display);
  
      if (!config_focus_under_mouse)
          event_end_ignore_all_enters(ignore_start);
      /* remove the window from our save set, unless we are managing an internal
         ObPrompt window */
      if (!self->prompt)
 -        XChangeSaveSet(ob_display, self->window, SetModeDelete);
 +        XChangeSaveSet(obt_display, self->window, SetModeDelete);
 +
 +    /* this can't be queued to run later */
 +    hooks_run(OB_HOOK_WIN_CLOSE, self);
  
      /* update the focus lists */
      focus_order_remove(self);
  
      client_list = g_list_remove(client_list, self);
      stacking_remove(self);
 -    g_hash_table_remove(window_map, &self->window);
 +    window_remove(self->window);
  
      /* once the client is out of the list, update the struts to remove its
         influence */
          self->decorations = 0; /* unmanaged windows have no decor */
  
          /* give the client its border back */
 -        XSetWindowBorderWidth(ob_display, self->window, self->border_width);
 +        XSetWindowBorderWidth(obt_display, self->window, self->border_width);
  
          client_move_resize(self, a.x, a.y, a.width, a.height);
      }
      if (ob_state() != OB_STATE_EXITING) {
          /* these values should not be persisted across a window
             unmapping/mapping */
 -        PROP_ERASE(self->window, net_wm_desktop);
 -        PROP_ERASE(self->window, net_wm_state);
 -        PROP_ERASE(self->window, wm_state);
 +        OBT_PROP_ERASE(self->window, NET_WM_DESKTOP);
 +        OBT_PROP_ERASE(self->window, NET_WM_STATE);
 +        OBT_PROP_ERASE(self->window, WM_STATE);
      } else {
          /* if we're left in an unmapped state, the client wont be mapped.
             this is bad, since we will no longer be managing the window on
             restart */
 -        XMapWindow(ob_display, self->window);
 +        XMapWindow(obt_display, self->window);
      }
  
      /* these should not be left on the window ever.  other window managers
         don't necessarily use them and it will mess them up (like compiz) */
 -    PROP_ERASE(self->window, net_wm_visible_name);
 -    PROP_ERASE(self->window, net_wm_visible_icon_name);
 +    OBT_PROP_ERASE(self->window, NET_WM_VISIBLE_NAME);
 +    OBT_PROP_ERASE(self->window, NET_WM_VISIBLE_ICON_NAME);
  
      /* update the list hints */
      client_set_list();
  
 -    ob_debug("Unmanaged window 0x%lx\n", self->window);
 +    ob_debug("Unmanaged window 0x%lx", self->window);
  
      /* free all data allocated in the client struct */
      RrImageUnref(self->icon_set);
@@@ -820,7 -890,7 +819,7 @@@ static ObAppSettings *client_get_settin
              match = FALSE;
  
          if (match) {
 -            ob_debug("Window matching: %s\n", app->name);
 +            ob_debug("Window matching: %s", app->name);
  
              /* copy the settings to our struct, overriding the existing
                 settings if they are not defaults */
@@@ -875,17 -945,17 +874,17 @@@ static void client_restore_session_stat
      GList *it;
  
      ob_debug_type(OB_DEBUG_SM,
 -                  "Restore session for client %s\n", self->title);
 +                  "Restore session for client %s", self->title);
  
      if (!(it = session_state_find(self))) {
          ob_debug_type(OB_DEBUG_SM,
 -                      "Session data not found for client %s\n", self->title);
 +                      "Session data not found for client %s", self->title);
          return;
      }
  
      self->session = it->data;
  
 -    ob_debug_type(OB_DEBUG_SM, "Session data loaded for client %s\n",
 +    ob_debug_type(OB_DEBUG_SM, "Session data loaded for client %s",
                    self->title);
  
      RECT_SET_POINT(self->area, self->session->x, self->session->y);
          self->area.width = self->session->w;
      if (self->session->h > 0)
          self->area.height = self->session->h;
 -    XResizeWindow(ob_display, self->window,
 +    XResizeWindow(obt_display, self->window,
                    self->area.width, self->area.height);
  
      self->desktop = (self->session->desktop == DESKTOP_ALL ?
                       self->session->desktop :
                       MIN(screen_num_desktops - 1, self->session->desktop));
 -    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
 +    OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, self->desktop);
  
      self->shaded = self->session->shaded;
      self->iconic = self->session->iconic;
@@@ -1128,11 -1198,10 +1127,11 @@@ static void client_get_all(ObClient *se
  
  static void client_get_startup_id(ObClient *self)
  {
 -    if (!(PROP_GETS(self->window, net_startup_id, utf8, &self->startup_id)))
 +    if (!(OBT_PROP_GETS(self->window, NET_STARTUP_ID, utf8,
 +                        &self->startup_id)))
          if (self->group)
 -            PROP_GETS(self->group->leader,
 -                      net_startup_id, utf8, &self->startup_id);
 +            OBT_PROP_GETS(self->group->leader,
 +                          NET_STARTUP_ID, utf8, &self->startup_id);
  }
  
  static void client_get_area(ObClient *self)
      XWindowAttributes wattrib;
      Status ret;
  
 -    ret = XGetWindowAttributes(ob_display, self->window, &wattrib);
 +    ret = XGetWindowAttributes(obt_display, self->window, &wattrib);
      g_assert(ret != BadWindow);
  
      RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
      POINT_SET(self->root_pos, wattrib.x, wattrib.y);
      self->border_width = wattrib.border_width;
  
 -    ob_debug("client area: %d %d  %d %d  bw %d\n", wattrib.x, wattrib.y,
 +    ob_debug("client area: %d %d  %d %d  bw %d", wattrib.x, wattrib.y,
               wattrib.width, wattrib.height, wattrib.border_width);
  }
  
@@@ -1155,12 -1224,12 +1154,12 @@@ static void client_get_desktop(ObClien
  {
      guint32 d = screen_num_desktops; /* an always-invalid value */
  
 -    if (PROP_GET32(self->window, net_wm_desktop, cardinal, &d)) {
 +    if (OBT_PROP_GET32(self->window, NET_WM_DESKTOP, CARDINAL, &d)) {
          if (d >= screen_num_desktops && d != DESKTOP_ALL)
              self->desktop = screen_num_desktops - 1;
          else
              self->desktop = d;
 -        ob_debug("client requested desktop 0x%x\n", self->desktop);
 +        ob_debug("client requested desktop 0x%x", self->desktop);
      } else {
          GSList *it;
          gboolean first = TRUE;
          if (all != screen_num_desktops) {
              self->desktop = all;
  
 -            ob_debug("client desktop set from parents: 0x%x\n",
 +            ob_debug("client desktop set from parents: 0x%x",
                       self->desktop);
          }
          /* try get from the startup-notification protocol */
              if (self->desktop >= screen_num_desktops &&
                  self->desktop != DESKTOP_ALL)
                  self->desktop = screen_num_desktops - 1;
 -            ob_debug("client desktop set from startup-notification: 0x%x\n",
 +            ob_debug("client desktop set from startup-notification: 0x%x",
                       self->desktop);
          }
          /* defaults to the current desktop */
          else {
              self->desktop = screen_desktop;
 -            ob_debug("client desktop set to the current desktop: %d\n",
 +            ob_debug("client desktop set to the current desktop: %d",
                       self->desktop);
          }
      }
@@@ -1208,32 -1277,32 +1207,32 @@@ static void client_get_state(ObClient *
      guint32 *state;
      guint num;
  
 -    if (PROP_GETA32(self->window, net_wm_state, atom, &state, &num)) {
 +    if (OBT_PROP_GETA32(self->window, NET_WM_STATE, ATOM, &state, &num)) {
          gulong i;
          for (i = 0; i < num; ++i) {
 -            if (state[i] == prop_atoms.net_wm_state_modal)
 +            if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MODAL))
                  self->modal = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_shaded)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SHADED))
                  self->shaded = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_hidden)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN))
                  self->iconic = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_skip_taskbar)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR))
                  self->skip_taskbar = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_skip_pager)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER))
                  self->skip_pager = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_fullscreen)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN))
                  self->fullscreen = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_maximized_vert)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT))
                  self->max_vert = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_maximized_horz)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ))
                  self->max_horz = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_above)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_ABOVE))
                  self->above = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_below)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_BELOW))
                  self->below = TRUE;
 -            else if (state[i] == prop_atoms.net_wm_state_demands_attention)
 +            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION))
                  self->demands_attention = TRUE;
 -            else if (state[i] == prop_atoms.ob_wm_state_undecorated)
 +            else if (state[i] == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED))
                  self->undecorated = TRUE;
          }
  
@@@ -1245,14 -1314,14 +1244,14 @@@ static void client_get_shaped(ObClient 
  {
      self->shaped = FALSE;
  #ifdef SHAPE
 -    if (extensions_shape) {
 +    if (obt_display_extension_shape) {
          gint foo;
          guint ufoo;
          gint s;
  
 -        XShapeSelectInput(ob_display, self->window, ShapeNotifyMask);
 +        XShapeSelectInput(obt_display, self->window, ShapeNotifyMask);
  
 -        XShapeQueryExtents(ob_display, self->window, &s, &foo,
 +        XShapeQueryExtents(obt_display, self->window, &s, &foo,
                             &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo,
                             &ufoo);
          self->shaped = !!s;
@@@ -1266,22 -1335,22 +1265,22 @@@ void client_update_transient_for(ObClie
      ObClient *target = NULL;
      gboolean trangroup = FALSE;
  
 -    if (XGetTransientForHint(ob_display, self->window, &t)) {
 +    if (XGetTransientForHint(obt_display, self->window, &t)) {
          if (t != self->window) { /* can't be transient to itself! */
 -            target = g_hash_table_lookup(window_map, &t);
 +            ObWindow *tw = window_find(t);
              /* if this happens then we need to check for it */
 -            g_assert(target != self);
 -            if (target && !WINDOW_IS_CLIENT(target)) {
 +            g_assert(tw != CLIENT_AS_WINDOW(self));
 +            if (tw && WINDOW_IS_CLIENT(tw)) {
                  /* watch out for windows with a parent that is something
                     different, like a dockapp for example */
 -                target = NULL;
 +                target = WINDOW_AS_CLIENT(tw);
              }
          }
  
          /* Setting the transient_for to Root is actually illegal, however
             applications from time have done this to specify transient for
             their group */
 -        if (!target && self->group && t == RootWindow(ob_display, ob_screen))
 +        if (!target && self->group && t == obt_root(ob_screen))
              trangroup = TRUE;
      } else if (self->group && self->transient)
          trangroup = TRUE;
@@@ -1409,15 -1478,15 +1408,15 @@@ static void client_update_transient_tre
      }
  }
  
static void client_get_mwm_hints(ObClient *self)
+ void client_get_mwm_hints(ObClient *self)
  {
      guint num;
      guint32 *hints;
  
      self->mwmhints.flags = 0; /* default to none */
  
 -    if (PROP_GETA32(self->window, motif_wm_hints, motif_wm_hints,
 -                    &hints, &num)) {
 +    if (OBT_PROP_GETA32(self->window, MOTIF_WM_HINTS, MOTIF_WM_HINTS,
 +                        &hints, &num)) {
          if (num >= OB_MWM_ELEMENTS) {
              self->mwmhints.flags = hints[0];
              self->mwmhints.functions = hints[1];
@@@ -1436,27 -1505,26 +1435,27 @@@ void client_get_type_and_transientness(
      self->type = -1;
      self->transient = FALSE;
  
 -    if (PROP_GETA32(self->window, net_wm_window_type, atom, &val, &num)) {
 +    if (OBT_PROP_GETA32(self->window, NET_WM_WINDOW_TYPE, ATOM, &val, &num)) {
          /* use the first value that we know about in the array */
          for (i = 0; i < num; ++i) {
 -            if (val[i] == prop_atoms.net_wm_window_type_desktop)
 +            if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP))
                  self->type = OB_CLIENT_TYPE_DESKTOP;
 -            else if (val[i] == prop_atoms.net_wm_window_type_dock)
 +            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DOCK))
                  self->type = OB_CLIENT_TYPE_DOCK;
 -            else if (val[i] == prop_atoms.net_wm_window_type_toolbar)
 +            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_TOOLBAR))
                  self->type = OB_CLIENT_TYPE_TOOLBAR;
 -            else if (val[i] == prop_atoms.net_wm_window_type_menu)
 +            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU))
                  self->type = OB_CLIENT_TYPE_MENU;
 -            else if (val[i] == prop_atoms.net_wm_window_type_utility)
 +            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_UTILITY))
                  self->type = OB_CLIENT_TYPE_UTILITY;
 -            else if (val[i] == prop_atoms.net_wm_window_type_splash)
 +            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_SPLASH))
                  self->type = OB_CLIENT_TYPE_SPLASH;
 -            else if (val[i] == prop_atoms.net_wm_window_type_dialog)
 +            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG))
                  self->type = OB_CLIENT_TYPE_DIALOG;
 -            else if (val[i] == prop_atoms.net_wm_window_type_normal)
 +            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_NORMAL))
                  self->type = OB_CLIENT_TYPE_NORMAL;
 -            else if (val[i] == prop_atoms.kde_net_wm_window_type_override) {
 +            else if (val[i] == OBT_PROP_ATOM(KDE_NET_WM_WINDOW_TYPE_OVERRIDE))
 +            {
                  /* prevent this window from getting any decor or
                     functionality */
                  self->mwmhints.flags &= (OB_MWM_FLAG_FUNCTIONS |
          g_free(val);
      }
  
 -    if (XGetTransientForHint(ob_display, self->window, &t))
 +    if (XGetTransientForHint(obt_display, self->window, &t))
          self->transient = TRUE;
  
      if (self->type == (ObClientType) -1) {
  void client_update_protocols(ObClient *self)
  {
      guint32 *proto;
 -    guint num_return, i;
 +    guint num_ret, i;
  
      self->focus_notify = FALSE;
      self->delete_window = FALSE;
  
 -    if (PROP_GETA32(self->window, wm_protocols, atom, &proto, &num_return)) {
 -        for (i = 0; i < num_return; ++i) {
 -            if (proto[i] == prop_atoms.wm_delete_window)
 +    if (OBT_PROP_GETA32(self->window, WM_PROTOCOLS, ATOM, &proto, &num_ret)) {
 +        for (i = 0; i < num_ret; ++i) {
 +            if (proto[i] == OBT_PROP_ATOM(WM_DELETE_WINDOW))
                  /* this means we can request the window to close */
                  self->delete_window = TRUE;
 -            else if (proto[i] == prop_atoms.wm_take_focus)
 +            else if (proto[i] == OBT_PROP_ATOM(WM_TAKE_FOCUS))
                  /* if this protocol is requested, then the window will be
                     notified whenever we want it to receive focus */
                  self->focus_notify = TRUE;
 -            else if (proto[i] == prop_atoms.net_wm_ping)
 +            else if (proto[i] == OBT_PROP_ATOM(NET_WM_PING))
                  /* if this protocol is requested, then the window will allow
                     pings to determine if it is still alive */
                  self->ping = TRUE;
  #ifdef SYNC
 -            else if (proto[i] == prop_atoms.net_wm_sync_request)
 +            else if (proto[i] == OBT_PROP_ATOM(NET_WM_SYNC_REQUEST))
                  /* if this protocol is requested, then resizing the
                     window will be synchronized between the frame and the
                     client */
@@@ -1531,8 -1599,7 +1530,8 @@@ void client_update_sync_request_counter
  {
      guint32 i;
  
 -    if (PROP_GET32(self->window, net_wm_sync_request_counter, cardinal, &i)) {
 +    if (OBT_PROP_GET32(self->window, NET_WM_SYNC_REQUEST_COUNTER, CARDINAL,&i))
 +    {
          self->sync_counter = i;
      } else
          self->sync_counter = None;
@@@ -1543,7 -1610,7 +1542,7 @@@ static void client_get_colormap(ObClien
  {
      XWindowAttributes wa;
  
 -    if (XGetWindowAttributes(ob_display, self->window, &wa))
 +    if (XGetWindowAttributes(obt_display, self->window, &wa))
          client_update_colormap(self, wa.colormap);
  }
  
@@@ -1551,7 -1618,7 +1550,7 @@@ void client_update_colormap(ObClient *s
  {
      if (colormap == self->colormap) return;
  
 -    ob_debug("Setting client %s colormap: 0x%x\n", self->title, colormap);
 +    ob_debug("Setting client %s colormap: 0x%x", self->title, colormap);
  
      if (client_focused(self)) {
          screen_install_colormap(self, FALSE); /* uninstall old one */
@@@ -1575,7 -1642,7 +1574,7 @@@ void client_update_normal_hints(ObClien
      SIZE_SET(self->max_size, G_MAXINT, G_MAXINT);
  
      /* get the hints from the window */
 -    if (XGetWMNormalHints(ob_display, self->window, &size, &ret)) {
 +    if (XGetWMNormalHints(obt_display, self->window, &size, &ret)) {
          /* normal windows can't request placement! har har
          if (!client_normal(self))
          */
          if (size.flags & PResizeInc && size.width_inc && size.height_inc)
              SIZE_SET(self->size_inc, size.width_inc, size.height_inc);
  
 -        ob_debug("Normal hints: min size (%d %d) max size (%d %d)\n   "
 -                 "size inc (%d %d) base size (%d %d)\n",
 +        ob_debug("Normal hints: min size (%d %d) max size (%d %d)",
                   self->min_size.width, self->min_size.height,
 -                 self->max_size.width, self->max_size.height,
 +                 self->max_size.width, self->max_size.height);
 +        ob_debug("size inc (%d %d) base size (%d %d)",
                   self->size_inc.width, self->size_inc.height,
                   self->base_size.width, self->base_size.height);
      }
      else
 -        ob_debug("Normal hints: not set\n");
 +        ob_debug("Normal hints: not set");
  }
  
  void client_setup_decor_and_functions(ObClient *self, gboolean reconfig)
@@@ -1787,38 -1854,38 +1786,38 @@@ static void client_change_allowed_actio
  
      /* desktop windows are kept on all desktops */
      if (self->type != OB_CLIENT_TYPE_DESKTOP)
 -        actions[num++] = prop_atoms.net_wm_action_change_desktop;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_CHANGE_DESKTOP);
  
      if (self->functions & OB_CLIENT_FUNC_SHADE)
 -        actions[num++] = prop_atoms.net_wm_action_shade;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_SHADE);
      if (self->functions & OB_CLIENT_FUNC_CLOSE)
 -        actions[num++] = prop_atoms.net_wm_action_close;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_CLOSE);
      if (self->functions & OB_CLIENT_FUNC_MOVE)
 -        actions[num++] = prop_atoms.net_wm_action_move;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MOVE);
      if (self->functions & OB_CLIENT_FUNC_ICONIFY)
 -        actions[num++] = prop_atoms.net_wm_action_minimize;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MINIMIZE);
      if (self->functions & OB_CLIENT_FUNC_RESIZE)
 -        actions[num++] = prop_atoms.net_wm_action_resize;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_RESIZE);
      if (self->functions & OB_CLIENT_FUNC_FULLSCREEN)
 -        actions[num++] = prop_atoms.net_wm_action_fullscreen;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_FULLSCREEN);
      if (self->functions & OB_CLIENT_FUNC_MAXIMIZE) {
 -        actions[num++] = prop_atoms.net_wm_action_maximize_horz;
 -        actions[num++] = prop_atoms.net_wm_action_maximize_vert;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MAXIMIZE_HORZ);
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MAXIMIZE_VERT);
      }
      if (self->functions & OB_CLIENT_FUNC_ABOVE)
 -        actions[num++] = prop_atoms.net_wm_action_above;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_ABOVE);
      if (self->functions & OB_CLIENT_FUNC_BELOW)
 -        actions[num++] = prop_atoms.net_wm_action_below;
 +        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_BELOW);
      if (self->functions & OB_CLIENT_FUNC_UNDECORATE)
 -        actions[num++] = prop_atoms.ob_wm_action_undecorate;
 +        actions[num++] = OBT_PROP_ATOM(OB_WM_ACTION_UNDECORATE);
  
 -    PROP_SETA32(self->window, net_wm_allowed_actions, atom, actions, num);
 +    OBT_PROP_SETA32(self->window, NET_WM_ALLOWED_ACTIONS, ATOM, actions, num);
  
 -   /* make sure the window isn't breaking any rules now
 +    /* make sure the window isn't breaking any rules now
  
 -   don't check ICONIFY here.  just cuz a window can't iconify doesnt mean
 -   it can't be iconified with its parent
 -   */
 +       don't check ICONIFY here.  just cuz a window can't iconify doesnt mean
 +       it can't be iconified with its parent
 +    */
  
      if (!(self->functions & OB_CLIENT_FUNC_SHADE) && self->shaded) {
          if (self->frame) client_shade(self, FALSE);
@@@ -1842,7 -1909,7 +1841,7 @@@ void client_update_wmhints(ObClient *se
      /* assume a window takes input if it doesn't specify */
      self->can_focus = TRUE;
  
 -    if ((hints = XGetWMHints(ob_display, self->window)) != NULL) {
 +    if ((hints = XGetWMHints(obt_display, self->window)) != NULL) {
          gboolean ur;
  
          if (hints->flags & InputHint)
@@@ -1931,10 -1998,10 +1930,10 @@@ void client_update_title(ObClient *self
      g_free(self->original_title);
  
      /* try netwm */
 -    if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) {
 +    if (!OBT_PROP_GETS(self->window, NET_WM_NAME, utf8, &data)) {
          /* try old x stuff */
 -        if (!(PROP_GETS(self->window, wm_name, locale, &data)
 -              || PROP_GETS(self->window, wm_name, utf8, &data))) {
 +        if (!(OBT_PROP_GETS(self->window, WM_NAME, locale, &data)
 +              || OBT_PROP_GETS(self->window, WM_NAME, utf8, &data))) {
              if (self->transient) {
      /*
      GNOME alert windows are not given titles:
          g_free(data);
      }
  
 -    PROP_SETS(self->window, net_wm_visible_name, visible);
 +    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_NAME, utf8, visible);
      self->title = visible;
  
      if (self->frame)
      g_free(self->icon_title);
  
      /* try netwm */
 -    if (!PROP_GETS(self->window, net_wm_icon_name, utf8, &data))
 +    if (!OBT_PROP_GETS(self->window, NET_WM_ICON_NAME, utf8, &data))
          /* try old x stuff */
 -        if (!(PROP_GETS(self->window, wm_icon_name, locale, &data) ||
 -              PROP_GETS(self->window, wm_icon_name, utf8, &data)))
 +        if (!(OBT_PROP_GETS(self->window, WM_ICON_NAME, locale, &data) ||
 +              OBT_PROP_GETS(self->window, WM_ICON_NAME, utf8, &data)))
              data = g_strdup(self->title);
  
      if (self->client_machine) {
          g_free(data);
      }
  
 -    PROP_SETS(self->window, net_wm_visible_icon_name, visible);
 +    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_ICON_NAME, utf8, visible);
      self->icon_title = visible;
  }
  
@@@ -2005,9 -2072,8 +2004,9 @@@ void client_update_strut(ObClient *self
      gboolean got = FALSE;
      StrutPartial strut;
  
 -    if (PROP_GETA32(self->window, net_wm_strut_partial, cardinal,
 -                    &data, &num)) {
 +    if (OBT_PROP_GETA32(self->window, NET_WM_STRUT_PARTIAL, CARDINAL,
 +                        &data, &num))
 +    {
          if (num == 12) {
              got = TRUE;
              STRUT_PARTIAL_SET(strut,
      }
  
      if (!got &&
 -        PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) {
 +        OBT_PROP_GETA32(self->window, NET_WM_STRUT, CARDINAL, &data, &num)) {
          if (num == 4) {
              Rect *a;
  
@@@ -2068,7 -2134,7 +2067,7 @@@ void client_update_icons(ObClient *self
         icon */
      grab_server(TRUE);
  
 -    if (PROP_GETA32(self->window, net_wm_icon, cardinal, &data, &num)) {
 +    if (OBT_PROP_GETA32(self->window, NET_WM_ICON, CARDINAL, &data, &num)) {
          /* figure out how many valid icons are in here */
          i = 0;
          num_seen = 0;
      if (!img) {
          XWMHints *hints;
  
 -        if ((hints = XGetWMHints(ob_display, self->window))) {
 +        if ((hints = XGetWMHints(obt_display, self->window))) {
              if (hints->flags & IconPixmapHint) {
                  gboolean xicon;
 -                xerror_set_ignore(TRUE);
 +                obt_display_ignore_errors(TRUE);
                  xicon = RrPixmapToRGBA(ob_rr_inst,
                                         hints->icon_pixmap,
                                         (hints->flags & IconMaskHint ?
                                          hints->icon_mask : None),
                                         (gint*)&w, (gint*)&h, &data);
 -                xerror_set_ignore(FALSE);
 +                obt_display_ignore_errors(FALSE);
  
                  if (xicon) {
                      if (w > 0 && h > 0) {
                  (((icon[i] >> RrDefaultRedOffset) & 0xff) << 16) +
                  (((icon[i] >> RrDefaultGreenOffset) & 0xff) << 8) +
                  (((icon[i] >> RrDefaultBlueOffset) & 0xff) << 0);
 -        PROP_SETA32(self->window, net_wm_icon, cardinal, ldata, w*h+2);
 +        OBT_PROP_SETA32(self->window, NET_WM_ICON, CARDINAL, ldata, w*h+2);
          g_free(ldata);
      } else if (self->frame)
          /* don't draw the icon empty if we're just setting one now anyways,
@@@ -2189,8 -2255,7 +2188,8 @@@ void client_update_icon_geometry(ObClie
  
      RECT_SET(self->icon_geometry, 0, 0, 0, 0);
  
 -    if (PROP_GETA32(self->window, net_wm_icon_geometry, cardinal, &data, &num))
 +    if (OBT_PROP_GETA32(self->window, NET_WM_ICON_GEOMETRY, CARDINAL,
 +                        &data, &num))
      {
          if (num == 4)
              /* don't let them set it with an area < 0 */
@@@ -2207,23 -2272,23 +2206,23 @@@ static void client_get_session_ids(ObCl
      gchar *s;
      gchar **ss;
  
 -    if (!PROP_GET32(self->window, wm_client_leader, window, &leader))
 +    if (!OBT_PROP_GET32(self->window, WM_CLIENT_LEADER, WINDOW, &leader))
          leader = None;
  
      /* get the SM_CLIENT_ID */
      got = FALSE;
      if (leader)
 -        got = PROP_GETS(leader, sm_client_id, locale, &self->sm_client_id);
 +        got = OBT_PROP_GETS(leader, SM_CLIENT_ID, locale, &self->sm_client_id);
      if (!got)
 -        PROP_GETS(self->window, sm_client_id, locale, &self->sm_client_id);
 +        OBT_PROP_GETS(self->window, SM_CLIENT_ID, locale, &self->sm_client_id);
  
      /* get the WM_CLASS (name and class). make them "" if they are not
         provided */
      got = FALSE;
      if (leader)
 -        got = PROP_GETSS(leader, wm_class, locale, &ss);
 +        got = OBT_PROP_GETSS(leader, WM_CLASS, locale, &ss);
      if (!got)
 -        got = PROP_GETSS(self->window, wm_class, locale, &ss);
 +        got = OBT_PROP_GETSS(self->window, WM_CLASS, locale, &ss);
  
      if (got) {
          if (ss[0]) {
      /* get the WM_WINDOW_ROLE. make it "" if it is not provided */
      got = FALSE;
      if (leader)
 -        got = PROP_GETS(leader, wm_window_role, locale, &s);
 +        got = OBT_PROP_GETS(leader, WM_WINDOW_ROLE, locale, &s);
      if (!got)
 -        got = PROP_GETS(self->window, wm_window_role, locale, &s);
 +        got = OBT_PROP_GETS(self->window, WM_WINDOW_ROLE, locale, &s);
  
      if (got)
          self->role = s;
      got = FALSE;
  
      if (leader)
 -        got = PROP_GETSS(leader, wm_command, locale, &ss);
 +        got = OBT_PROP_GETSS(leader, WM_COMMAND, locale, &ss);
      if (!got)
 -        got = PROP_GETSS(self->window, wm_command, locale, &ss);
 +        got = OBT_PROP_GETSS(self->window, WM_COMMAND, locale, &ss);
  
      if (got) {
          /* merge/mash them all together */
      /* get the WM_CLIENT_MACHINE */
      got = FALSE;
      if (leader)
 -        got = PROP_GETS(leader, wm_client_machine, locale, &s);
 +        got = OBT_PROP_GETS(leader, WM_CLIENT_MACHINE, locale, &s);
      if (!got)
 -        got = PROP_GETS(self->window, wm_client_machine, locale, &s);
 +        got = OBT_PROP_GETS(self->window, WM_CLIENT_MACHINE, locale, &s);
  
      if (got) {
          gchar localhost[128];
  
          /* see if it has the PID set too (the PID requires that the
             WM_CLIENT_MACHINE be set) */
 -        if (PROP_GET32(self->window, net_wm_pid, cardinal, &pid))
 +        if (OBT_PROP_GET32(self->window, NET_WM_PID, CARDINAL, &pid))
              self->pid = pid;
      }
  }
@@@ -2315,12 -2380,12 +2314,12 @@@ static void client_change_wm_state(ObCl
          self->wmstate = NormalState;
  
      if (old != self->wmstate) {
 -        PROP_MSG(self->window, kde_wm_change_state,
 -                 self->wmstate, 1, 0, 0);
 +        OBT_PROP_MSG(ob_screen, self->window, KDE_WM_CHANGE_STATE,
 +                     self->wmstate, 1, 0, 0, 0);
  
          state[0] = self->wmstate;
          state[1] = None;
 -        PROP_SETA32(self->window, wm_state, wm_state, state, 2);
 +        OBT_PROP_SETA32(self->window, WM_STATE, WM_STATE, state, 2);
      }
  }
  
@@@ -2331,30 -2396,30 +2330,30 @@@ static void client_change_state(ObClien
  
      num = 0;
      if (self->modal)
 -        netstate[num++] = prop_atoms.net_wm_state_modal;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MODAL);
      if (self->shaded)
 -        netstate[num++] = prop_atoms.net_wm_state_shaded;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SHADED);
      if (self->iconic)
 -        netstate[num++] = prop_atoms.net_wm_state_hidden;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_HIDDEN);
      if (self->skip_taskbar)
 -        netstate[num++] = prop_atoms.net_wm_state_skip_taskbar;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR);
      if (self->skip_pager)
 -        netstate[num++] = prop_atoms.net_wm_state_skip_pager;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER);
      if (self->fullscreen)
 -        netstate[num++] = prop_atoms.net_wm_state_fullscreen;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN);
      if (self->max_vert)
 -        netstate[num++] = prop_atoms.net_wm_state_maximized_vert;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT);
      if (self->max_horz)
 -        netstate[num++] = prop_atoms.net_wm_state_maximized_horz;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ);
      if (self->above)
 -        netstate[num++] = prop_atoms.net_wm_state_above;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_ABOVE);
      if (self->below)
 -        netstate[num++] = prop_atoms.net_wm_state_below;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_BELOW);
      if (self->demands_attention)
 -        netstate[num++] = prop_atoms.net_wm_state_demands_attention;
 +        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION);
      if (self->undecorated)
 -        netstate[num++] = prop_atoms.ob_wm_state_undecorated;
 -    PROP_SETA32(self->window, net_wm_state, atom, netstate, num);
 +        netstate[num++] = OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED);
 +    OBT_PROP_SETA32(self->window, NET_WM_STATE, ATOM, netstate, num);
  
      if (self->frame)
          frame_adjust_state(self->frame);
@@@ -2547,8 -2612,6 +2546,8 @@@ gboolean client_show(ObClient *self
             desktop!
          */
          client_change_wm_state(self);
 +
 +        hooks_queue(OB_HOOK_WIN_VISIBLE, self);
      }
      return show;
  }
@@@ -2587,8 -2650,6 +2586,8 @@@ gboolean client_hide(ObClient *self
             desktop!
          */
          client_change_wm_state(self);
 +
 +        hooks_queue(OB_HOOK_WIN_INVISIBLE, self);
      }
      return hide;
  }
@@@ -2656,7 -2717,7 +2655,7 @@@ static void client_apply_startup_state(
         pre-max/pre-fullscreen values
      */
      client_try_configure(self, &x, &y, &w, &h, &l, &l, FALSE);
 -    ob_debug("placed window 0x%x at %d, %d with size %d x %d\n",
 +    ob_debug("placed window 0x%x at %d, %d with size %d x %d",
               self->window, x, y, w, h);
      /* save the area, and make it where it should be for the premax stuff */
      oldarea = self->area;
      client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
  
      /* set the desktop hint, to make sure that it always exists */
 -    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
 +    OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, self->desktop);
  
      /* nothing to do for the other states:
         skip_taskbar
@@@ -2974,7 -3035,7 +2973,7 @@@ void client_configure(ObClient *self, g
  
      /* if the client is enlarging, then resize the client before the frame */
      if (send_resize_client && (w > oldw || h > oldh)) {
 -        XMoveResizeWindow(ob_display, self->window,
 +        XMoveResizeWindow(obt_display, self->window,
                            self->frame->size.left, self->frame->size.top,
                            MAX(w, oldw), MAX(h, oldh));
          frame_adjust_client_area(self->frame);
          XEvent event;
  
          event.type = ConfigureNotify;
 -        event.xconfigure.display = ob_display;
 +        event.xconfigure.display = obt_display;
          event.xconfigure.event = self->window;
          event.xconfigure.window = self->window;
  
 -        ob_debug("Sending ConfigureNotify to %s for %d,%d %dx%d\n",
 +        ob_debug("Sending ConfigureNotify to %s for %d,%d %dx%d",
                   self->title, self->root_pos.x, self->root_pos.y, w, h);
  
          /* root window real coords */
       */
      if (send_resize_client && (w <= oldw || h <= oldh)) {
          frame_adjust_client_area(self->frame);
 -        XMoveResizeWindow(ob_display, self->window,
 +        XMoveResizeWindow(obt_display, self->window,
                            self->frame->size.left, self->frame->size.top, w, h);
      }
  
 -    XFlush(ob_display);
 +    XFlush(obt_display);
  
      /* if it moved between monitors, then this can affect the stacking
         layer of this window or others - for fullscreen windows */
@@@ -3121,7 -3182,7 +3120,7 @@@ void client_fullscreen(ObClient *self, 
          RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0);
      }
  
 -    ob_debug("Window %s going fullscreen (%d)\n",
 +    ob_debug("Window %s going fullscreen (%d)",
               self->title, self->fullscreen);
  
      client_setup_decor_and_functions(self, FALSE);
@@@ -3146,7 -3207,7 +3145,7 @@@ static void client_iconify_recursive(Ob
      gboolean changed = FALSE;
  
      if (self->iconic != iconic) {
 -        ob_debug("%sconifying window: 0x%lx\n", (iconic ? "I" : "Uni"),
 +        ob_debug("%sconifying window: 0x%lx", (iconic ? "I" : "Uni"),
                   self->window);
  
          if (iconic) {
              frame_begin_iconify_animation(self->frame, iconic);
          /* do this after starting the animation so it doesn't flash */
          client_showhide(self);
 +
 +        hooks_queue((iconic ? OB_HOOK_WIN_ICONIC : OB_HOOK_WIN_UNICONIC),
 +                    self);
      }
  
      /* iconify all direct transients, and deiconify all transients
@@@ -3272,8 -3330,6 +3271,8 @@@ void client_maximize(ObClient *self, gb
  
      client_setup_decor_and_functions(self, FALSE);
      client_move_resize(self, x, y, w, h);
 +
 +    hooks_queue((max ? OB_HOOK_WIN_MAX : OB_HOOK_WIN_UNMAX), self);
  }
  
  void client_shade(ObClient *self, gboolean shade)
      client_change_wm_state(self); /* the window is being hidden/shown */
      /* resize the frame to just the titlebar */
      frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
 +
 +    hooks_queue((shade ? OB_HOOK_WIN_SHADE : OB_HOOK_WIN_UNSHADE), self);
  }
  
  static void client_ping_event(ObClient *self, gboolean dead)
@@@ -3328,12 -3382,12 +3327,12 @@@ void client_close(ObClient *self
      if (!self->delete_window)
          /* don't use client_kill(), we should only kill based on PID in
             response to a lack of PING replies */
 -        XKillClient(ob_display, self->window);
 +        XKillClient(obt_display, self->window);
      else {
          /* request the client to close with WM_DELETE_WINDOW */
 -        PROP_MSG_TO(self->window, self->window, wm_protocols,
 -                    prop_atoms.wm_delete_window, event_curtime, 0, 0, 0,
 -                    NoEventMask);
 +        OBT_PROP_MSG_TO(self->window, self->window, WM_PROTOCOLS,
 +                        OBT_PROP_ATOM(WM_DELETE_WINDOW), event_curtime,
 +                        0, 0, 0, NoEventMask);
  
          /* we're trying to close the window, so see if it is responding. if it
             is not, then we will let them kill the window */
@@@ -3441,14 -3495,14 +3440,14 @@@ void client_kill(ObClient *self
              client_update_title(self);
          }
          else {
 -            ob_debug("killing window 0x%x with pid %lu, with SIGKILL\n",
 +            ob_debug("killing window 0x%x with pid %lu, with SIGKILL",
                       self->window, self->pid);
              kill(self->pid, SIGKILL); /* kill -9 */
          }
      }
      else {
          /* running on a remote host */
 -        XKillClient(ob_display, self->window);
 +        XKillClient(obt_display, self->window);
      }
  }
  
@@@ -3478,13 -3532,13 +3477,13 @@@ static void client_set_desktop_recursiv
  
      if (target != self->desktop && self->type != OB_CLIENT_TYPE_DESKTOP) {
  
 -        ob_debug("Setting desktop %u\n", target+1);
 +        ob_debug("Setting desktop %u", target+1);
  
          g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
  
          old = self->desktop;
          self->desktop = target;
 -        PROP_SET32(self->window, net_wm_desktop, cardinal, target);
 +        OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, target);
          /* the frame can display the current desktop state */
          frame_adjust_state(self->frame);
          /* 'move' the window to the new desktop */
              /* the new desktop's geometry may be different, so we may need to
                 resize, for example if we are maximized */
              client_reconfigure(self, FALSE);
 +
 +        if (old != self->desktop)
 +            hooks_queue(OB_HOOK_WIN_DESK_CHANGE, self);
      }
  
      /* move all transients */
@@@ -3544,14 -3595,14 +3543,14 @@@ static gboolean client_validate_unmap(O
      XEvent e;
      gboolean ret = TRUE;
  
 -    if (XCheckTypedWindowEvent(ob_display, self->window, UnmapNotify, &e)) {
 +    if (XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) {
          if (n < self->ignore_unmaps) // ignore this one, but look for more
              ret = client_validate_unmap(self, n+1);
          else
              ret = FALSE; // the window is going to become unmanaged
  
          /* put them back on the event stack so they end up in the same order */
 -        XPutBackEvent(ob_display, &e);
 +        XPutBackEvent(obt_display, &e);
      }
  
      return ret;
@@@ -3561,10 -3612,10 +3560,10 @@@ gboolean client_validate(ObClient *self
  {
      XEvent e;
  
 -    XSync(ob_display, FALSE); /* get all events on the server */
 +    XSync(obt_display, FALSE); /* get all events on the server */
  
 -    if (XCheckTypedWindowEvent(ob_display, self->window, DestroyNotify, &e)) {
 -        XPutBackEvent(ob_display, &e);
 +    if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e)) {
 +        XPutBackEvent(obt_display, &e);
          return FALSE;
      }
  
@@@ -3601,11 -3652,10 +3600,11 @@@ void client_set_state(ObClient *self, A
      gboolean above = self->above;
      gboolean below = self->below;
      gint i;
 +    gboolean value;
  
 -    if (!(action == prop_atoms.net_wm_state_add ||
 -          action == prop_atoms.net_wm_state_remove ||
 -          action == prop_atoms.net_wm_state_toggle))
 +    if (!(action == OBT_PROP_ATOM(NET_WM_STATE_ADD) ||
 +          action == OBT_PROP_ATOM(NET_WM_STATE_REMOVE) ||
 +          action == OBT_PROP_ATOM(NET_WM_STATE_TOGGLE)))
          /* an invalid action was passed to the client message, ignore it */
          return;
  
          if (!state) continue;
  
          /* if toggling, then pick whether we're adding or removing */
 -        if (action == prop_atoms.net_wm_state_toggle) {
 -            if (state == prop_atoms.net_wm_state_modal)
 -                action = modal ? prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_maximized_vert)
 -                action = self->max_vert ? prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_maximized_horz)
 -                action = self->max_horz ? prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_shaded)
 -                action = shaded ? prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_skip_taskbar)
 -                action = self->skip_taskbar ?
 -                    prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_skip_pager)
 -                action = self->skip_pager ?
 -                    prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_hidden)
 -                action = self->iconic ?
 -                    prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_fullscreen)
 -                action = fullscreen ?
 -                    prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_above)
 -                action = self->above ? prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_below)
 -                action = self->below ? prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.net_wm_state_demands_attention)
 -                action = self->demands_attention ?
 -                    prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 -            else if (state == prop_atoms.ob_wm_state_undecorated)
 -                action = undecorated ? prop_atoms.net_wm_state_remove :
 -                    prop_atoms.net_wm_state_add;
 +        if (action == OBT_PROP_ATOM(NET_WM_STATE_TOGGLE)) {
 +            if (state == OBT_PROP_ATOM(NET_WM_STATE_MODAL))
 +                value = modal;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT))
 +                value = self->max_vert;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ))
 +                value = self->max_horz;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SHADED))
 +                value = shaded;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR))
 +                value = self->skip_taskbar;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER))
 +                value = self->skip_pager;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN))
 +                value = self->iconic;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN))
 +                value = fullscreen;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_ABOVE))
 +                value = self->above;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_BELOW))
 +                value = self->below;
 +            else if (state == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION))
 +                value = self->demands_attention;
 +            else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED))
 +                value = undecorated;
 +            action = value ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
 +                             OBT_PROP_ATOM(NET_WM_STATE_ADD);
          }
  
 -        if (action == prop_atoms.net_wm_state_add) {
 -            if (state == prop_atoms.net_wm_state_modal) {
 -                modal = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_maximized_vert) {
 -                max_vert = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_maximized_horz) {
 -                max_horz = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_shaded) {
 -                shaded = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_skip_taskbar) {
 -                self->skip_taskbar = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_skip_pager) {
 -                self->skip_pager = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_hidden) {
 -                iconic = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_fullscreen) {
 -                fullscreen = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_above) {
 -                above = TRUE;
 +        value = action == OBT_PROP_ATOM(NET_WM_STATE_ADD);
 +        if (state == OBT_PROP_ATOM(NET_WM_STATE_MODAL)) {
 +            modal = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT)) {
 +            max_vert = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ)) {
 +            max_horz = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SHADED)) {
 +            shaded = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR)) {
 +            self->skip_taskbar = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER)) {
 +            self->skip_pager = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN)) {
 +            iconic = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN)) {
 +            fullscreen = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_ABOVE)) {
 +            above = value;
 +            /* only unset below when setting above, otherwise you can't get to
 +               the normal layer */
 +            if (value)
                  below = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_below) {
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_BELOW)) {
 +            /* and vice versa */
 +            if (value)
                  above = FALSE;
 -                below = TRUE;
 -            } else if (state == prop_atoms.net_wm_state_demands_attention) {
 -                demands_attention = TRUE;
 -            } else if (state == prop_atoms.ob_wm_state_undecorated) {
 -                undecorated = TRUE;
 -            }
 -
 -        } else { /* action == prop_atoms.net_wm_state_remove */
 -            if (state == prop_atoms.net_wm_state_modal) {
 -                modal = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_maximized_vert) {
 -                max_vert = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_maximized_horz) {
 -                max_horz = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_shaded) {
 -                shaded = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_skip_taskbar) {
 -                self->skip_taskbar = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_skip_pager) {
 -                self->skip_pager = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_hidden) {
 -                iconic = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_fullscreen) {
 -                fullscreen = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_above) {
 -                above = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_below) {
 -                below = FALSE;
 -            } else if (state == prop_atoms.net_wm_state_demands_attention) {
 -                demands_attention = FALSE;
 -            } else if (state == prop_atoms.ob_wm_state_undecorated) {
 -                undecorated = FALSE;
 -            }
 +            below = value;
 +        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION)){
 +            demands_attention = value;
 +        } else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED)) {
 +            undecorated = value;
          }
      }
  
@@@ -3765,12 -3853,12 +3764,12 @@@ gboolean client_focus(ObClient *self
  
      if (!client_can_focus(self)) {
          ob_debug_type(OB_DEBUG_FOCUS,
 -                      "Client %s can't be focused\n", self->title);
 +                      "Client %s can't be focused", self->title);
          return FALSE;
      }
  
      ob_debug_type(OB_DEBUG_FOCUS,
 -                  "Focusing client \"%s\" (0x%x) at time %u\n",
 +                  "Focusing client \"%s\" (0x%x) at time %u",
                    self->title, self->window, event_curtime);
  
      /* if using focus_delay, stop the timer now so that focus doesn't
  
      event_cancel_all_key_grabs();
  
 -    xerror_set_ignore(TRUE);
 -    xerror_occured = FALSE;
 +    obt_display_ignore_errors(TRUE);
  
      if (self->can_focus) {
          /* This can cause a BadMatch error with CurrentTime, or if an app
             passed in a bad time for _NET_WM_ACTIVE_WINDOW. */
 -        XSetInputFocus(ob_display, self->window, RevertToPointerRoot,
 +        XSetInputFocus(obt_display, self->window, RevertToPointerRoot,
                         event_curtime);
      }
  
      if (self->focus_notify) {
          XEvent ce;
          ce.xclient.type = ClientMessage;
 -        ce.xclient.message_type = prop_atoms.wm_protocols;
 -        ce.xclient.display = ob_display;
 +        ce.xclient.message_type = OBT_PROP_ATOM(WM_PROTOCOLS);
 +        ce.xclient.display = obt_display;
          ce.xclient.window = self->window;
          ce.xclient.format = 32;
 -        ce.xclient.data.l[0] = prop_atoms.wm_take_focus;
 +        ce.xclient.data.l[0] = OBT_PROP_ATOM(WM_TAKE_FOCUS);
          ce.xclient.data.l[1] = event_curtime;
          ce.xclient.data.l[2] = 0l;
          ce.xclient.data.l[3] = 0l;
          ce.xclient.data.l[4] = 0l;
 -        XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce);
 +        XSendEvent(obt_display, self->window, FALSE, NoEventMask, &ce);
      }
  
 -    xerror_set_ignore(FALSE);
 +    obt_display_ignore_errors(FALSE);
  
 -    ob_debug_type(OB_DEBUG_FOCUS, "Error focusing? %d\n", xerror_occured);
 -    return !xerror_occured;
 +    ob_debug_type(OB_DEBUG_FOCUS, "Error focusing? %d",
 +                  obt_display_error_occured);
 +    return !obt_display_error_occured;
  }
  
  static void client_present(ObClient *self, gboolean here, gboolean raise,
@@@ -3927,9 -4015,6 +3926,9 @@@ void client_set_undecorated(ObClient *s
          self->undecorated = undecorated;
          client_setup_decor_and_functions(self, TRUE);
          client_change_state(self); /* reflect this in the state hints */
 +
 +        hooks_queue((undecorated ?
 +                     OB_HOOK_WIN_UNDECORATED : OB_HOOK_WIN_DECORATED), self);
      }
  }
  
@@@ -4121,15 -4206,15 +4120,15 @@@ static void detect_edge(Rect area, ObDi
              g_assert_not_reached();
      }
  
 -    ob_debug("my head %d size %d\n", my_head, my_size);
 -    ob_debug("head %d tail %d dest %d\n", head, tail, *dest);
 +    ob_debug("my head %d size %d", my_head, my_size);
 +    ob_debug("head %d tail %d dest %d", head, tail, *dest);
      if (!skip_head) {
 -        ob_debug("using near edge %d\n", head);
 +        ob_debug("using near edge %d", head);
          *dest = head;
          *near_edge = TRUE;
      }
      else if (!skip_tail) {
 -        ob_debug("using far edge %d\n", tail);
 +        ob_debug("using far edge %d", tail);
          *dest = tail;
          *near_edge = FALSE;
      }
@@@ -4194,7 -4279,7 +4193,7 @@@ void client_find_edge_directional(ObCli
              cur->desktop != screen_desktop)
              continue;
  
 -        ob_debug("trying window %s\n", cur->title);
 +        ob_debug("trying window %s", cur->title);
  
          detect_edge(cur->frame->area, dir, my_head, my_size, my_edge_start,
                      my_edge_size, dest, near_edge);
@@@ -4315,10 -4400,10 +4314,10 @@@ void client_find_resize_directional(ObC
          g_assert_not_reached();
      }
  
 -    ob_debug("head %d dir %d\n", head, dir);
 +    ob_debug("head %d dir %d", head, dir);
      client_find_edge_directional(self, dir, head, 1,
                                   e_start, e_size, &e, &near);
 -    ob_debug("edge %d\n", e);
 +    ob_debug("edge %d", e);
      *x = self->frame->area.x;
      *y = self->frame->area.y;
      *w = self->frame->area.width;
diff --combined openbox/client.h
@@@ -323,13 -323,15 +323,13 @@@ 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
    @param prompt This specifies an ObPrompt which is being managed.  It is
                  possible to manage Openbox-owned windows through this.
  */
  void client_manage(Window win, struct _ObPrompt *prompt);
  /*! Unmanages all managed windows */
 -void client_unmanage_all();
 +void client_unmanage_all(void);
  /*! Unmanages a given client */
  void client_unmanage(ObClient *client);
  
@@@ -342,7 -344,7 +342,7 @@@ ObClient *client_fake_manage(Window win
  void client_fake_unmanage(ObClient *self);
  
  /*! Sets the client list on the root window from the client_list */
 -void client_set_list();
 +void client_set_list(void);
  
  /*! Determines if the client should be shown or hidden currently.
    @return TRUE if it should be visible; otherwise, FALSE.
@@@ -632,6 -634,8 +632,8 @@@ void client_setup_decor_and_functions(O
  
  /*! Sets the window's type and transient flag */
  void client_get_type_and_transientness(ObClient *self);
+ /*! Gets the motif wm hints */
+ void client_get_mwm_hints(ObClient *self);
  
  /*! Returns a client's icon set, or its parents (recursively) if it doesn't
    have one
@@@ -723,7 -727,7 +725,7 @@@ void client_set_layer(ObClient *self, g
  
  guint client_monitor(ObClient *self);
  
 -ObClient* client_under_pointer();
 +ObClient* client_under_pointer(void);
  
  gboolean client_has_group_siblings(ObClient *self);
  
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 "hooks.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>
@@@ -85,8 -87,8 +85,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);
@@@ -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.. */
@@@ -434,7 -428,7 +434,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);
@@@ -460,15 -454,13 +460,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);
               e->type == MotionNotify)
          event_handle_user_input(client, e);
  
 +    XFlush(obt_display);
 +
 +    /* run all the hooks at once */
 +    hooks_run_queue();
 +
      /* if something happens and it's not from an XEvent, then we don't know
         the time */
      event_curtime = CurrentTime;
@@@ -758,7 -747,7 +758,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:
@@@ -828,17 -817,17 +828,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;
@@@ -888,12 -877,12 +888,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;
@@@ -1012,7 -1001,7 +1012,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:
              {
                  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 "
 -                 "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, TRUE, 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);
                 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) {
++        } 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);
+             /* Apply the changes to the window */
+             client_setup_decor_and_functions(client, TRUE);
          } else if (msgtype == XA_WM_HINTS) {
              client_update_wmhints(client);
          } else if (msgtype == XA_WM_TRANSIENT_FOR) {
              /* 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:
@@@ -1630,11 -1626,11 +1637,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);
@@@ -1681,160 -1677,125 +1688,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 (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 */
 -            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 (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 */
 +                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 (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;
              }
 +        }
 +
 +        /* Use KeyRelease events for running things so that the key release
 +           doesn't get sent to the focused application.
  
 -            it = start;
 -            do {
 -                ObMenuEntryFrame *e = it->data;
 -                gunichar entrykey = 0;
 +           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);
  
 -                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;
 +            /* 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 */
              if (!client || !frame_iconify_animating(client->frame))
                  mouse_event(client, e);
          } else
 -            keyboard_event((focus_cycle_target ? focus_cycle_target :
 -                            (client ? client : focus_client)), e);
 +            keyboard_event(event_target_client(client), e);
      }
  }
  
 +ObClient* event_target_client(ObClient *client)
 +{
 +    return (focus_cycle_target ? focus_cycle_target :
 +            (client ? client : focus_client));
 +}
 +
  static void focus_delay_dest(gpointer data)
  {
      g_free(data);
@@@ -1944,20 -1929,20 +1951,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(gulong serial)
@@@ -2014,24 -1999,24 +2021,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)
@@@ -2066,9 -2051,9 +2073,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;
  }