]> Dogcows Code - chaz/openbox/commitdiff
import from bb-cvs
authorDana Jansens <danakj@orodu.net>
Sat, 25 May 2002 00:29:44 +0000 (00:29 +0000)
committerDana Jansens <danakj@orodu.net>
Sat, 25 May 2002 00:29:44 +0000 (00:29 +0000)
added slit and enable-clobber defines back in Makefile.am

69 files changed:
src/BaseDisplay.cc
src/BaseDisplay.h [deleted file]
src/BaseDisplay.hh [new file with mode: 0644]
src/Basemenu.cc
src/Basemenu.h [deleted file]
src/Clientmenu.cc
src/Clientmenu.hh [moved from src/Clientmenu.h with 77% similarity]
src/Color.cc [new file with mode: 0644]
src/Color.hh [new file with mode: 0644]
src/Configmenu.cc
src/Configmenu.hh [moved from src/Configmenu.h with 63% similarity]
src/GCCache.cc [new file with mode: 0644]
src/GCCache.hh [new file with mode: 0644]
src/Geometry.cc [deleted file]
src/Geometry.h [deleted file]
src/Iconmenu.cc
src/Iconmenu.h [deleted file]
src/Image.cc
src/Image.h [deleted file]
src/Image.hh [new file with mode: 0644]
src/ImageControl.cc [new file with mode: 0644]
src/Makefile.am
src/Netizen.cc
src/Netizen.hh [moved from src/Netizen.h with 86% similarity]
src/Resource.cc [deleted file]
src/Resource.h [deleted file]
src/Rootmenu.cc
src/Rootmenu.hh [moved from src/Rootmenu.h with 79% similarity]
src/Screen.cc
src/Screen.h [deleted file]
src/Screen.hh [new file with mode: 0644]
src/Slit.cc
src/Slit.h [deleted file]
src/Texture.cc [new file with mode: 0644]
src/Texture.hh [new file with mode: 0644]
src/Timer.cc
src/Timer.h [deleted file]
src/Timer.hh [new file with mode: 0644]
src/Toolbar.cc
src/Toolbar.h [deleted file]
src/Toolbar.hh [new file with mode: 0644]
src/Util.cc
src/Util.h [deleted file]
src/Util.hh [new file with mode: 0644]
src/Window.cc
src/Window.h [deleted file]
src/Window.hh [new file with mode: 0644]
src/Windowmenu.cc
src/Windowmenu.h [deleted file]
src/Workspace.cc
src/Workspace.h [deleted file]
src/Workspace.hh [new file with mode: 0644]
src/Workspacemenu.cc
src/Workspacemenu.hh [moved from src/Workspacemenu.h with 78% similarity]
src/XAtom.cc [deleted file]
src/XAtom.h [deleted file]
src/XDisplay.cc [deleted file]
src/XDisplay.h [deleted file]
src/XScreen.cc [deleted file]
src/XScreen.h [deleted file]
src/blackbox.cc [new file with mode: 0644]
src/blackbox.hh [new file with mode: 0644]
src/bsd-snprintf.c [deleted file]
src/bsd-snprintf.h [deleted file]
src/i18n.cc
src/i18n.hh [moved from src/i18n.h with 92% similarity]
src/main.cc
src/openbox.cc [deleted file]
src/openbox.h [deleted file]

index 3ee81fb065b957c4c65ec1818a201b506c4a80fc..6726cbace53068a4af16709b14b4b67127364771 100644 (file)
@@ -1,5 +1,6 @@
-// BaseDisplay.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// BaseDisplay.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
+extern "C" {
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 #include <X11/Xutil.h>
-#include <X11/cursorfont.h>
 #include <X11/keysym.h>
 
 #ifdef    SHAPE
 #  include <stdio.h>
 #endif // HAVE_STDIO_H
 
-#ifdef    HAVE_STDLIB_H
+#ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif // HAVE_STDLIB_H
 
-#ifdef    HAVE_STRING_H
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
 
 #  include <sys/types.h>
 #  include <sys/wait.h>
 #endif // HAVE_SYS_WAIT_H
+}
 
-#if defined(HAVE_PROCESS_H) && defined(__EMX__)
-#  include <process.h>
-#endif //   HAVE_PROCESS_H             __EMX__
+#include <sstream>
+using std::string;
 
-#include "i18n.h"
-#include "BaseDisplay.h"
-#include "Timer.h"
+#include "i18n.hh"
+#include "BaseDisplay.hh"
+#include "GCCache.hh"
+#include "Timer.hh"
+#include "Util.hh"
 
-#include <algorithm>
 
 // X error handler to handle any and all X errors while the application is
 // running
-static Bool internal_error = False;
+static bool internal_error = False;
 static Window last_bad_window = None;
 
 BaseDisplay *base_display;
 
-static int handleXErrors(Display *d, XErrorEvent *e) {
 #ifdef    DEBUG
+static int handleXErrors(Display *d, XErrorEvent *e) {
   char errtxt[128];
 
   XGetErrorText(d, e->error_code, errtxt, 128);
-  fprintf(stderr, i18n(BaseDisplaySet, BaseDisplayXError,
-                       "%s:  X error: %s(%d) opcodes %d/%d\n  resource 0x%lx\n"
-                       ),
+  fprintf(stderr,
+          i18n(BaseDisplaySet, BaseDisplayXError,
+               "%s:  X error: %s(%d) opcodes %d/%d\n  resource 0x%lx\n"),
           base_display->getApplicationName(), errtxt, e->error_code,
           e->request_code, e->minor_code, e->resourceid);
+#else
+static int handleXErrors(Display *, XErrorEvent *e) {
 #endif // DEBUG
 
   if (e->error_code == BadWindow) last_bad_window = e->resourceid;
@@ -121,11 +119,11 @@ static int handleXErrors(Display *d, XErrorEvent *e) {
 // signal handler to allow for proper and gentle shutdown
 
 #ifndef   HAVE_SIGACTION
-static RETSIGTYPE signalhandler(int sig)
+static RETSIGTYPE signalhandler(int sig) {
 #else //  HAVE_SIGACTION
-static void signalhandler(int sig)
+static void signalhandler(int sig) {
 #endif // HAVE_SIGACTION
-{
+
   static int re_enter = 0;
 
   switch (sig) {
@@ -177,31 +175,10 @@ static void signalhandler(int sig)
 }
 
 
-// convenience functions
-#ifndef    __EMX__
-void bexec(const char *command, char* displaystring) {
-  if (! fork()) {
-    setsid();
-    putenv(displaystring);
-    execl("/bin/sh", "/bin/sh", "-c", command, NULL);
-    exit(0);
-  }
-}
-#endif // !__EMX__
+BaseDisplay::BaseDisplay(const char *app_name, const char *dpy_name) {
+  application_name = app_name;
 
-char *bstrdup(const char *s) {
-  const int l = strlen(s) + 1;
-  char *n = new char[l];
-  strncpy(n, s, l);
-  return n;
-}
-
-BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) {
-  application_name = bstrdup(app_name);
-
-  _startup = True;
-  _shutdown = False;
-  server_grabs = 0;
+  run_state = STARTUP;
   last_bad_window = None;
 
   ::base_display = this;
@@ -235,8 +212,9 @@ BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) {
 #endif // HAVE_SIGACTION
 
   if (! (display = XOpenDisplay(dpy_name))) {
-    fprintf(stderr, i18n(BaseDisplaySet, BaseDisplayXConnectFail,
-                         "BaseDisplay::BaseDisplay: connection to X server failed.\n"));
+    fprintf(stderr,
+            i18n(BaseDisplaySet, BaseDisplayXConnectFail,
+               "BaseDisplay::BaseDisplay: connection to X server failed.\n"));
     ::exit(2);
   } else if (fcntl(ConnectionNumber(display), F_SETFD, 1) == -1) {
     fprintf(stderr,
@@ -255,93 +233,12 @@ BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) {
   shape.extensions = False;
 #endif // SHAPE
 
-  xa_wm_colormap_windows =
-    XInternAtom(display, "WM_COLORMAP_WINDOWS", False);
-  xa_wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False);
-  xa_wm_state = XInternAtom(display, "WM_STATE", False);
-  xa_wm_change_state = XInternAtom(display, "WM_CHANGE_STATE", False);
-  xa_wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
-  xa_wm_take_focus = XInternAtom(display, "WM_TAKE_FOCUS", False);
-  motif_wm_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
-
-  openbox_hints = XInternAtom(display, "_BLACKBOX_HINTS", False);
-  openbox_attributes = XInternAtom(display, "_BLACKBOX_ATTRIBUTES", False);
-  openbox_change_attributes =
-    XInternAtom(display, "_BLACKBOX_CHANGE_ATTRIBUTES", False);
-
-  openbox_structure_messages =
-    XInternAtom(display, "_BLACKBOX_STRUCTURE_MESSAGES", False);
-  openbox_notify_startup =
-    XInternAtom(display, "_BLACKBOX_NOTIFY_STARTUP", False);
-  openbox_notify_window_add =
-    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_ADD", False);
-  openbox_notify_window_del =
-    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_DEL", False);
-  openbox_notify_current_workspace =
-    XInternAtom(display, "_BLACKBOX_NOTIFY_CURRENT_WORKSPACE", False);
-  openbox_notify_workspace_count =
-    XInternAtom(display, "_BLACKBOX_NOTIFY_WORKSPACE_COUNT", False);
-  openbox_notify_window_focus =
-    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_FOCUS", False);
-  openbox_notify_window_raise =
-    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_RAISE", False);
-  openbox_notify_window_lower =
-    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_LOWER", False);
-
-  openbox_change_workspace =
-    XInternAtom(display, "_BLACKBOX_CHANGE_WORKSPACE", False);
-  openbox_change_window_focus =
-    XInternAtom(display, "_BLACKBOX_CHANGE_WINDOW_FOCUS", False);
-  openbox_cycle_window_focus =
-    XInternAtom(display, "_BLACKBOX_CYCLE_WINDOW_FOCUS", False);
-
-#ifdef    NEWWMSPEC
-
-  net_supported = XInternAtom(display, "_NET_SUPPORTED", False);
-  net_client_list = XInternAtom(display, "_NET_CLIENT_LIST", False);
-  net_client_list_stacking = XInternAtom(display, "_NET_CLIENT_LIST_STACKING", False);
-  net_number_of_desktops = XInternAtom(display, "_NET_NUMBER_OF_DESKTOPS", False);
-  net_desktop_geometry = XInternAtom(display, "_NET_DESKTOP_GEOMETRY", False);
-  net_desktop_viewport = XInternAtom(display, "_NET_DESKTOP_VIEWPORT", False);
-  net_current_desktop = XInternAtom(display, "_NET_CURRENT_DESKTOP", False);
-  net_desktop_names = XInternAtom(display, "_NET_DESKTOP_NAMES", False);
-  net_active_window = XInternAtom(display, "_NET_ACTIVE_WINDOW", False);
-  net_workarea = XInternAtom(display, "_NET_WORKAREA", False);
-  net_supporting_wm_check = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
-  net_virtual_roots = XInternAtom(display, "_NET_VIRTUAL_ROOTS", False);
-
-  net_close_window = XInternAtom(display, "_NET_CLOSE_WINDOW", False);
-  net_wm_moveresize = XInternAtom(display, "_NET_WM_MOVERESIZE", False);
-
-  net_properties = XInternAtom(display, "_NET_PROPERTIES", False);
-  net_wm_name = XInternAtom(display, "_NET_WM_NAME", False);
-  net_wm_desktop = XInternAtom(display, "_NET_WM_DESKTOP", False);
-  net_wm_window_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
-  net_wm_state = XInternAtom(display, "_NET_WM_STATE", False);
-  net_wm_strut = XInternAtom(display, "_NET_WM_STRUT", False);
-  net_wm_icon_geometry = XInternAtom(display, "_NET_WM_ICON_GEOMETRY", False);
-  net_wm_icon = XInternAtom(display, "_NET_WM_ICON", False);
-  net_wm_pid = XInternAtom(display, "_NET_WM_PID", False);
-  net_wm_handled_icons = XInternAtom(display, "_NET_WM_HANDLED_ICONS", False);
-
-  net_wm_ping = XInternAtom(display, "_NET_WM_PING", False);
-
-#endif // NEWWMSPEC
-
-  cursor.session = XCreateFontCursor(display, XC_left_ptr);
-  cursor.move = XCreateFontCursor(display, XC_fleur);
-  cursor.ll_angle = XCreateFontCursor(display, XC_ll_angle);
-  cursor.lr_angle = XCreateFontCursor(display, XC_lr_angle);
-  cursor.ul_angle = XCreateFontCursor(display, XC_ul_angle);
-  cursor.ur_angle = XCreateFontCursor(display, XC_ur_angle);
-
   XSetErrorHandler((XErrorHandler) handleXErrors);
 
-  screenInfoList.reserve(numberOfScreens());
-  for (unsigned int s = 0; s < numberOfScreens(); s++)
-    screenInfoList.push_back(new ScreenInfo(*this, s));
+  screenInfoList.reserve(ScreenCount(display));
+  for (int i = 0; i < ScreenCount(display); ++i)
+    screenInfoList.push_back(ScreenInfo(this, i));
 
-#ifndef   NOCLOBBER
   NumLockMask = ScrollLockMask = 0;
 
   const XModifierKeymap* const modmap = XGetModifierMapping(display);
@@ -355,15 +252,15 @@ BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) {
     // get the values of the keyboard lock modifiers
     // Note: Caps lock is not retrieved the same way as Scroll and Num lock
     // since it doesn't need to be.
-    const KeyCode num_lock_code = XKeysymToKeycode(display, XK_Num_Lock);
-    const KeyCode scroll_lock_code = XKeysymToKeycode(display, XK_Scroll_Lock);
+    const KeyCode num_lock = XKeysymToKeycode(display, XK_Num_Lock);
+    const KeyCode scroll_lock = XKeysymToKeycode(display, XK_Scroll_Lock);
 
     for (size_t cnt = 0; cnt < size; ++cnt) {
       if (! modmap->modifiermap[cnt]) continue;
 
-      if (num_lock_code == modmap->modifiermap[cnt])
+      if (num_lock == modmap->modifiermap[cnt])
         NumLockMask = mask_table[cnt / modmap->max_keypermod];
-      if (scroll_lock_code == modmap->modifiermap[cnt])
+      if (scroll_lock == modmap->modifiermap[cnt])
         ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
     }
   }
@@ -379,20 +276,13 @@ BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) {
   MaskListLength = sizeof(MaskList) / sizeof(MaskList[0]);
 
   if (modmap) XFreeModifiermap(const_cast<XModifierKeymap*>(modmap));
-#else
-  NumLockMask = Mod2Mask;
-  ScrollLockMask = Mod5Mask;
-#endif // NOCLOBBER
+
+  gccache = 0;
 }
 
 
 BaseDisplay::~BaseDisplay(void) {
-  std::for_each(screenInfoList.begin(), screenInfoList.end(),
-                PointerAssassin());
-  // we don't create the BTimers, we don't delete them
-
-  if (application_name != NULL)
-    delete [] application_name;
+  delete gccache;
 
   XCloseDisplay(display);
 }
@@ -401,24 +291,18 @@ BaseDisplay::~BaseDisplay(void) {
 void BaseDisplay::eventLoop(void) {
   run();
 
-  int xfd = ConnectionNumber(display);
+  const int xfd = ConnectionNumber(display);
 
-  while ((! _shutdown) && (! internal_error)) {
+  while (run_state == RUNNING && ! internal_error) {
     if (XPending(display)) {
       XEvent e;
       XNextEvent(display, &e);
 
-      if (last_bad_window != None && e.xany.window == last_bad_window) {
-#ifdef    DEBUG
-        fprintf(stderr, i18n(BaseDisplaySet,
-                             BaseDisplayBadWindowRemove,
-                             "BaseDisplay::eventLoop(): removing bad window "
-                             "from event queue\n"));
-#endif // DEBUG
-      } else {
-        last_bad_window = None;
-        process_event(&e);
-      }
+      if (last_bad_window != None && e.xany.window == last_bad_window)
+        continue;
+
+      last_bad_window = None;
+      process_event(&e);
     } else {
       fd_set rfds;
       timeval now, tm, *timeout = (timeval *) 0;
@@ -426,33 +310,11 @@ void BaseDisplay::eventLoop(void) {
       FD_ZERO(&rfds);
       FD_SET(xfd, &rfds);
 
-      if (!timerList.empty()) {
-        gettimeofday(&now, 0);
-
-        tm.tv_sec = tm.tv_usec = 0l;
-
-        BTimer *timer = timerList.front();
-        ASSERT(timer != NULL);
+      if (! timerList.empty()) {
+        const BTimer* const timer = timerList.top();
 
-        tm.tv_sec = timer->getStartTime().tv_sec +
-          timer->getTimeout().tv_sec - now.tv_sec;
-        tm.tv_usec = timer->getStartTime().tv_usec +
-          timer->getTimeout().tv_usec - now.tv_usec;
-
-        while (tm.tv_usec >= 1000000) {
-          tm.tv_sec++;
-          tm.tv_usec -= 1000000;
-        }
-
-        while (tm.tv_usec < 0) {
-          if (tm.tv_sec > 0) {
-            tm.tv_sec--;
-            tm.tv_usec += 1000000;
-          } else {
-            tm.tv_usec = 0;
-            break;
-          }
-        }
+        gettimeofday(&now, 0);
+        tm = timer->timeRemaining(now);
 
         timeout = &tm;
       }
@@ -462,105 +324,53 @@ void BaseDisplay::eventLoop(void) {
       // check for timer timeout
       gettimeofday(&now, 0);
 
-      TimerList::iterator it;
-      for (it = timerList.begin(); it != timerList.end(); ++it) {
-        BTimer *timer = *it;
-        ASSERT(timer != NULL);
-
-        tm.tv_sec = timer->getStartTime().tv_sec +
-          timer->getTimeout().tv_sec;
-        tm.tv_usec = timer->getStartTime().tv_usec +
-          timer->getTimeout().tv_usec;
-
-        if ((now.tv_sec < tm.tv_sec) ||
-            (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec))
+      // there is a small chance for deadlock here:
+      // *IF* the timer list keeps getting refreshed *AND* the time between
+      // timer->start() and timer->shouldFire() is within the timer's period
+      // then the timer will keep firing.  This should be VERY near impossible.
+      while (! timerList.empty()) {
+        BTimer *timer = timerList.top();
+        if (! timer->shouldFire(now))
           break;
 
-        timer->fireTimeout();
+        timerList.pop();
 
-        // restart the current timer so that the start time is updated
-        if (! timer->doOnce()) {
-          // reorder
-          removeTimer(timer);
-          addTimer(timer);
+        timer->fireTimeout();
+        timer->halt();
+        if (timer->isRecurring())
           timer->start();
-        } else
-          timer->stop();
-        it = timerList.begin(); // we no longer have any idea if the iterator is
-        // valid, but what was at the front() is no
-        // longer.
       }
     }
   }
 }
 
 
-const Bool BaseDisplay::validateWindow(Window window) {
-  XEvent event;
-  if (XCheckTypedWindowEvent(display, window, DestroyNotify, &event)) {
-    XPutBackEvent(display, &event);
-
-    return False;
-  }
-
-  return True;
-}
-
-
-void BaseDisplay::grab(void) {
-  if (! server_grabs++)
-    XGrabServer(display);
-}
-
-
-void BaseDisplay::ungrab(void) {
-  if (! --server_grabs)
-    XUngrabServer(display);
-}
-
-
 void BaseDisplay::addTimer(BTimer *timer) {
-  ASSERT(timer != (BTimer *) 0);
-
-  TimerList::iterator it;
-  for (it = timerList.begin(); it != timerList.end(); ++it) {
-    BTimer *tmp = *it;
-    if ((tmp->getTimeout().tv_sec > timer->getTimeout().tv_sec) ||
-        ((tmp->getTimeout().tv_sec == timer->getTimeout().tv_sec) &&
-         (tmp->getTimeout().tv_usec >= timer->getTimeout().tv_usec)))
-      break;
-  }
+  if (! timer) return;
 
-  timerList.insert(it, timer);
+  timerList.push(timer);
 }
 
 
 void BaseDisplay::removeTimer(BTimer *timer) {
-  ASSERT(timer != (BTimer *) 0);
-  timerList.remove(timer);
+  timerList.release(timer);
 }
 
 
 /*
- * Grabs a button, but also grabs the button in every possible combination with
- * the keyboard lock keys, so that they do not cancel out the event.
+ * Grabs a button, but also grabs the button in every possible combination
+ * with the keyboard lock keys, so that they do not cancel out the event.
  */
 void BaseDisplay::grabButton(unsigned int button, unsigned int modifiers,
-                             Window grab_window, Bool owner_events,
+                             Window grab_window, bool owner_events,
                              unsigned int event_mask, int pointer_mode,
-                             int keybaord_mode, Window confine_to,
-                             Cursor cursor) const
-{
-#ifndef   NOCLOBBER
-  for (size_t cnt = 0; cnt < MaskListLength; ++cnt)
+                             int keyboard_mode, Window confine_to,
+                             Cursor cursor) const {
+  for (size_t cnt = 0; cnt < MaskListLength; ++cnt) {
     XGrabButton(display, button, modifiers | MaskList[cnt], grab_window,
-                owner_events, event_mask, pointer_mode, keybaord_mode,
+                owner_events, event_mask, pointer_mode, keyboard_mode,
                 confine_to, cursor);
-#else  // NOCLOBBER
-  XGrabButton(display, button, modifiers, grab_window,
-              owner_events, event_mask, pointer_mode, keybaord_mode,
-              confine_to, cursor);
-#endif // NOCLOBBER
+  }
 }
 
 /*
@@ -569,26 +379,37 @@ void BaseDisplay::grabButton(unsigned int button, unsigned int modifiers,
  */
 void BaseDisplay::ungrabButton(unsigned int button, unsigned int modifiers,
                                Window grab_window) const {
-#ifndef   NOCLOBBER
-  for (size_t cnt = 0; cnt < MaskListLength; ++cnt)
+  for (size_t cnt = 0; cnt < MaskListLength; ++cnt) {
     XUngrabButton(display, button, modifiers | MaskList[cnt], grab_window);
-#else  // NOCLOBBER
-  XUngrabButton(display, button, modifiers, grab_window);
-#endif // NOCLOBBER
+  }
+}
+
+
+const ScreenInfo* BaseDisplay::getScreenInfo(unsigned int s) const {
+  if (s < screenInfoList.size())
+    return &screenInfoList[s];
+  return (const ScreenInfo*) 0;
 }
 
 
-ScreenInfo::ScreenInfo(BaseDisplay &d, int num) : basedisplay(d),
-screen_number(num)
+BGCCache *BaseDisplay::gcCache(void) const
 {
+    if (! gccache) gccache = new BGCCache(this);
+    return gccache;
+}
+
 
-  root_window = RootWindow(basedisplay.getXDisplay(), screen_number);
-  depth = DefaultDepth(basedisplay.getXDisplay(), screen_number);
+ScreenInfo::ScreenInfo(BaseDisplay *d, unsigned int num) {
+  basedisplay = d;
+  screen_number = num;
 
-  m_size = Size(WidthOfScreen(ScreenOfDisplay(basedisplay.getXDisplay(),
-                                              screen_number)),
-                HeightOfScreen(ScreenOfDisplay(basedisplay.getXDisplay(),
-                                               screen_number)));
+  root_window = RootWindow(basedisplay->getXDisplay(), screen_number);
+  depth = DefaultDepth(basedisplay->getXDisplay(), screen_number);
+
+  rect.setSize(WidthOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(),
+                                             screen_number)),
+               HeightOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(),
+                                              screen_number)));
 
   // search for a TrueColor Visual... if we can't find one... we will use the
   // default visual for the screen
@@ -600,10 +421,10 @@ screen_number(num)
 
   visual = (Visual *) 0;
 
-  if ((vinfo_return = XGetVisualInfo(basedisplay.getXDisplay(),
-                                     VisualScreenMask | VisualClassMask,
-                                     &vinfo_template, &vinfo_nitems)) &&
-      vinfo_nitems > 0) {
+  vinfo_return = XGetVisualInfo(basedisplay->getXDisplay(),
+                                VisualScreenMask | VisualClassMask,
+                                &vinfo_template, &vinfo_nitems);
+  if (vinfo_return && vinfo_nitems > 0) {
     for (int i = 0; i < vinfo_nitems; i++) {
       if (depth < (vinfo_return + i)->depth) {
         depth = (vinfo_return + i)->depth;
@@ -615,10 +436,20 @@ screen_number(num)
   }
 
   if (visual) {
-    colormap = XCreateColormap(basedisplay.getXDisplay(), root_window,
+    colormap = XCreateColormap(basedisplay->getXDisplay(), root_window,
                                visual, AllocNone);
   } else {
-    visual = DefaultVisual(basedisplay.getXDisplay(), screen_number);
-    colormap = DefaultColormap(basedisplay.getXDisplay(), screen_number);
+    visual = DefaultVisual(basedisplay->getXDisplay(), screen_number);
+    colormap = DefaultColormap(basedisplay->getXDisplay(), screen_number);
   }
+
+  // get the default display string and strip the screen number
+  string default_string = DisplayString(basedisplay->getXDisplay());
+  const string::size_type pos = default_string.rfind(".");
+  if (pos != string::npos)
+    default_string.resize(pos);
+
+  std::ostringstream formatter;
+  formatter << "DISPLAY=" << default_string << '.' << screen_number;
+  display_string = formatter.str();
 }
diff --git a/src/BaseDisplay.h b/src/BaseDisplay.h
deleted file mode 100644 (file)
index 8bd13e8..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-// BaseDisplay.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __BaseDisplay_hh
-#define   __BaseDisplay_hh
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-
-// forward declaration
-class BaseDisplay;
-class ScreenInfo;
-
-#include "Timer.h"
-#include "Geometry.h"
-#include "Util.h"
-#include <vector>
-#include <list>
-
-#define AttribShaded      (1l << 0)
-#define AttribMaxHoriz    (1l << 1)
-#define AttribMaxVert     (1l << 2)
-#define AttribOmnipresent (1l << 3)
-#define AttribWorkspace   (1l << 4)
-#define AttribStack       (1l << 5)
-#define AttribDecoration  (1l << 6)
-
-#define StackTop          (0)
-#define StackNormal       (1)
-#define StackBottom       (2)
-
-#define DecorNone         (0)
-#define DecorNormal       (1)
-#define DecorTiny         (2)
-#define DecorTool         (3)
-
-typedef struct _openbox_hints {
-  unsigned long flags, attrib, workspace, stack, decoration;
-} OpenboxHints;
-
-typedef struct _openbox_attributes {
-  unsigned long flags, attrib, workspace, stack, decoration;
-  int premax_x, premax_y;
-  unsigned int premax_w, premax_h;
-} OpenboxAttributes;
-
-#define PropOpenboxHintsElements      (5)
-#define PropOpenboxAttributesElements (9)
-
-#ifndef    __EMX__
-void bexec(const char *, char *);
-#endif // !__EMX__
-
-char *bstrdup(const char *);
-
-class BaseDisplay {
-private:
-  struct cursor {
-    Cursor session, move, ll_angle, lr_angle, ul_angle, ur_angle;
-  } cursor;
-
-  struct shape {
-    Bool extensions;
-    int event_basep, error_basep;
-  } shape;
-
-#ifndef   NOCLOBBER
-  unsigned int MaskList[8];
-  size_t MaskListLength;
-#endif // NOCLOBBER
-  
-  Atom xa_wm_colormap_windows, xa_wm_protocols, xa_wm_state,
-    xa_wm_delete_window, xa_wm_take_focus, xa_wm_change_state,
-    motif_wm_hints;
-
-  // NETAttributes
-  Atom openbox_attributes, openbox_change_attributes, openbox_hints;
-
-  // NETStructureMessages
-  Atom openbox_structure_messages, openbox_notify_startup,
-    openbox_notify_window_add, openbox_notify_window_del,
-    openbox_notify_window_focus, openbox_notify_current_workspace,
-    openbox_notify_workspace_count, openbox_notify_window_raise,
-    openbox_notify_window_lower;
-
-  // message_types for client -> wm messages
-  Atom openbox_change_workspace, openbox_change_window_focus,
-    openbox_cycle_window_focus;
-
-#ifdef    NEWWMSPEC
-
-  // root window properties
-  Atom net_supported, net_client_list, net_client_list_stacking,
-    net_number_of_desktops, net_desktop_geometry, net_desktop_viewport,
-    net_current_desktop, net_desktop_names, net_active_window, net_workarea,
-    net_supporting_wm_check, net_virtual_roots;
-
-  // root window messages
-  Atom net_close_window, net_wm_moveresize;
-
-  // application window properties
-  Atom net_properties, net_wm_name, net_wm_desktop, net_wm_window_type,
-    net_wm_state, net_wm_strut, net_wm_icon_geometry, net_wm_icon, net_wm_pid,
-    net_wm_handled_icons;
-
-  // application protocols
-  Atom net_wm_ping;
-
-#endif // NEWWMSPEC
-
-  Bool _startup, _shutdown;
-  Display *display;
-
-  typedef std::vector<ScreenInfo*> ScreenInfoList;
-  ScreenInfoList screenInfoList;
-  typedef std::list<BTimer*> TimerList;
-  TimerList timerList;
-
-  char *display_name, *application_name;
-  unsigned int server_grabs, colors_per_channel;
-
-
-protected:
-  // pure virtual function... you must override this
-  virtual void process_event(XEvent *) = 0;
-
-  // the masks of the modifiers which are ignored in button events.
-  int NumLockMask, ScrollLockMask;
-
-
-public:
-  BaseDisplay(const char *, char * = 0);
-  virtual ~BaseDisplay();
-
-  inline const Atom &getWMChangeStateAtom() const
-    { return xa_wm_change_state; }
-  inline const Atom &getWMStateAtom() const
-    { return xa_wm_state; }
-  inline const Atom &getWMDeleteAtom() const
-    { return xa_wm_delete_window; }
-  inline const Atom &getWMProtocolsAtom() const
-    { return xa_wm_protocols; }
-  inline const Atom &getWMTakeFocusAtom() const
-    { return xa_wm_take_focus; }
-  inline const Atom &getWMColormapAtom() const
-    { return xa_wm_colormap_windows; }
-  inline const Atom &getMotifWMHintsAtom() const
-    { return motif_wm_hints; }
-
-  // this atom is for normal app->WM hints about decorations, stacking,
-  // starting workspace etc...
-  inline const Atom &getOpenboxHintsAtom() const
-    { return openbox_hints;}
-
-  // these atoms are for normal app->WM interaction beyond the scope of the
-  // ICCCM...
-  inline const Atom &getOpenboxAttributesAtom() const
-    { return openbox_attributes; }
-  inline const Atom &getOpenboxChangeAttributesAtom() const
-    { return openbox_change_attributes; }
-
-  // these atoms are for window->WM interaction, with more control and
-  // information on window "structure"... common examples are
-  // notifying apps when windows are raised/lowered... when the user changes
-  // workspaces... i.e. "pager talk"
-  inline const Atom &getOpenboxStructureMessagesAtom() const
-    { return openbox_structure_messages; }
-
-  // *Notify* portions of the NETStructureMessages protocol
-  inline const Atom &getOpenboxNotifyStartupAtom() const
-    { return openbox_notify_startup; }
-  inline const Atom &getOpenboxNotifyWindowAddAtom() const
-    { return openbox_notify_window_add; }
-  inline const Atom &getOpenboxNotifyWindowDelAtom() const
-    { return openbox_notify_window_del; }
-  inline const Atom &getOpenboxNotifyWindowFocusAtom() const
-    { return openbox_notify_window_focus; }
-  inline const Atom &getOpenboxNotifyCurrentWorkspaceAtom() const
-    { return openbox_notify_current_workspace; }
-  inline const Atom &getOpenboxNotifyWorkspaceCountAtom() const
-    { return openbox_notify_workspace_count; }
-  inline const Atom &getOpenboxNotifyWindowRaiseAtom() const
-    { return openbox_notify_window_raise; }
-  inline const Atom &getOpenboxNotifyWindowLowerAtom() const
-    { return openbox_notify_window_lower; }
-
-  // atoms to change that request changes to the desktop environment during
-  // runtime... these messages can be sent by any client... as the sending
-  // client window id is not included in the ClientMessage event...
-  inline const Atom &getOpenboxChangeWorkspaceAtom() const
-    { return openbox_change_workspace; }
-  inline const Atom &getOpenboxChangeWindowFocusAtom() const
-    { return openbox_change_window_focus; }
-  inline const Atom &getOpenboxCycleWindowFocusAtom() const
-    { return openbox_cycle_window_focus; }
-
-#ifdef    NEWWMSPEC
-
-  // root window properties
-  inline const Atom &getNETSupportedAtom() const
-    { return net_supported; }
-  inline const Atom &getNETClientListAtom() const
-    { return net_client_list; }
-  inline const Atom &getNETClientListStackingAtom() const
-    { return net_client_list_stacking; }
-  inline const Atom &getNETNumberOfDesktopsAtom() const
-    { return net_number_of_desktops; }
-  inline const Atom &getNETDesktopGeometryAtom() const
-    { return net_desktop_geometry; }
-  inline const Atom &getNETDesktopViewportAtom() const
-    { return net_desktop_viewport; }
-  inline const Atom &getNETCurrentDesktopAtom() const
-    { return net_current_desktop; }
-  inline const Atom &getNETDesktopNamesAtom() const
-    { return net_desktop_names; }
-  inline const Atom &getNETActiveWindowAtom() const
-    { return net_active_window; }
-  inline const Atom &getNETWorkareaAtom() const
-    { return net_workarea; }
-  inline const Atom &getNETSupportingWMCheckAtom() const
-    { return net_supporting_wm_check; }
-  inline const Atom &getNETVirtualRootsAtom() const
-    { return net_virtual_roots; }
-
-  // root window messages
-  inline const Atom &getNETCloseWindowAtom() const
-    { return net_close_window; }
-  inline const Atom &getNETWMMoveResizeAtom() const
-    { return net_wm_moveresize; }
-
-  // application window properties
-  inline const Atom &getNETPropertiesAtom() const
-    { return net_properties; }
-  inline const Atom &getNETWMNameAtom() const
-    { return net_wm_name; }
-  inline const Atom &getNETWMDesktopAtom() const
-    { return net_wm_desktop; }
-  inline const Atom &getNETWMWindowTypeAtom() const
-    { return net_wm_window_type; }
-  inline const Atom &getNETWMStateAtom() const
-    { return net_wm_state; }
-  inline const Atom &getNETWMStrutAtom() const
-    { return net_wm_strut; }
-  inline const Atom &getNETWMIconGeometryAtom() const
-    { return net_wm_icon_geometry; }
-  inline const Atom &getNETWMIconAtom() const
-    { return net_wm_icon; }
-  inline const Atom &getNETWMPidAtom() const
-    { return net_wm_pid; }
-  inline const Atom &getNETWMHandledIconsAtom() const
-    { return net_wm_handled_icons; }
-
-  // application protocols
-  inline const Atom &getNETWMPingAtom() const
-    { return net_wm_ping; }
-
-#endif // NEWWMSPEC
-
-  inline ScreenInfo *getScreenInfo(unsigned int s) {
-    ASSERT(s < screenInfoList.size());
-    return screenInfoList[s];
-  }
-
-  inline const Bool &hasShapeExtensions() const
-    { return shape.extensions; }
-  inline const Bool &doShutdown() const
-    { return _shutdown; }
-  inline const Bool &isStartup() const
-    { return _startup; }
-
-  inline const Cursor &getSessionCursor() const
-    { return cursor.session; }
-  inline const Cursor &getMoveCursor() const
-    { return cursor.move; }
-  inline const Cursor &getLowerLeftAngleCursor() const
-    { return cursor.ll_angle; }
-  inline const Cursor &getLowerRightAngleCursor() const
-    { return cursor.lr_angle; }
-  inline const Cursor &getUpperLeftAngleCursor() const
-    { return cursor.ul_angle; }
-  inline const Cursor &getUpperRightAngleCursor() const
-    { return cursor.ur_angle; }
-
-  inline Display *getXDisplay() { return display; }
-
-  inline const char *getXDisplayName() const
-    { return (const char *) display_name; }
-  inline const char *getApplicationName() const
-    { return (const char *) application_name; }
-
-  inline const unsigned int numberOfScreens() const
-    { return ScreenCount(display); }
-  inline const int &getShapeEventBase() const
-    { return shape.event_basep; }
-
-  inline void shutdown() { _shutdown = True; }
-  inline void run() { _startup = _shutdown = False; }
-
-  const Bool validateWindow(Window);
-
-  void grabButton(unsigned int, unsigned int, Window, Bool, unsigned int, int,
-      int, Window, Cursor) const;
-  void ungrabButton(unsigned int button, unsigned int modifiers,
-      Window grab_window) const;
-  
-  void grab();
-  void ungrab();
-  void eventLoop();
-  void addTimer(BTimer *);
-  void removeTimer(BTimer *);
-
-  // another pure virtual... this is used to handle signals that BaseDisplay
-  // doesn't understand itself
-  virtual Bool handleSignal(int) = 0;
-};
-
-
-class ScreenInfo {
-private:
-  BaseDisplay &basedisplay;
-  Visual *visual;
-  Window root_window;
-  Colormap colormap;
-
-  int depth, screen_number;
-  Size m_size;
-
-
-public:
-  ScreenInfo(BaseDisplay &, int);
-
-  inline BaseDisplay &getBaseDisplay() { return basedisplay; }
-
-  inline Visual *getVisual() const { return visual; }
-  inline const Window &getRootWindow() const { return root_window; }
-  inline const Colormap &getColormap() const { return colormap; }
-
-  inline const int &getDepth() const { return depth; }
-  inline const int &getScreenNumber() const { return screen_number; }
-
-//  inline const unsigned int &getWidth() const { return width; }
-//  inline const unsigned int &getHeight() const { return height; }
-  inline const Size &size() const { return m_size; }
-};
-
-
-#endif // __BaseDisplay_hh
diff --git a/src/BaseDisplay.hh b/src/BaseDisplay.hh
new file mode 100644 (file)
index 0000000..7a6251d
--- /dev/null
@@ -0,0 +1,156 @@
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// BaseDisplay.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef   __BaseDisplay_hh
+#define   __BaseDisplay_hh
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+}
+
+#include <vector>
+#include <string>
+
+// forward declaration
+class BaseDisplay;
+class BGCCache;
+
+#include "Timer.hh"
+#include "Util.hh"
+
+class ScreenInfo {
+private:
+  BaseDisplay *basedisplay;
+  Visual *visual;
+  Window root_window;
+  Colormap colormap;
+
+  int depth;
+  unsigned int screen_number;
+  std::string display_string;
+  Rect rect;
+
+public:
+  ScreenInfo(BaseDisplay *d, unsigned int num);
+
+  inline BaseDisplay *getBaseDisplay(void) const { return basedisplay; }
+  inline Visual *getVisual(void) const { return visual; }
+  inline Window getRootWindow(void) const { return root_window; }
+  inline Colormap getColormap(void) const { return colormap; }
+  inline int getDepth(void) const { return depth; }
+  inline unsigned int getScreenNumber(void) const
+    { return screen_number; }
+  inline const Rect& getRect(void) const { return rect; }
+  inline unsigned int getWidth(void) const { return rect.width(); }
+  inline unsigned int getHeight(void) const { return rect.height(); }
+  inline const std::string& displayString(void) const
+  { return display_string; }
+};
+
+
+class BaseDisplay: public TimerQueueManager {
+private:
+  struct BShape {
+    bool extensions;
+    int event_basep, error_basep;
+  };
+  BShape shape;
+
+  unsigned int MaskList[8];
+  size_t MaskListLength;
+
+  enum RunState { STARTUP, RUNNING, SHUTDOWN };
+  RunState run_state;
+
+  Display *display;
+  mutable BGCCache *gccache;
+
+  typedef std::vector<ScreenInfo> ScreenInfoList;
+  ScreenInfoList screenInfoList;
+  TimerQueue timerList;
+
+  const char *display_name, *application_name;
+
+  // no copying!
+  BaseDisplay(const BaseDisplay &);
+  BaseDisplay& operator=(const BaseDisplay&);
+
+protected:
+  // pure virtual function... you must override this
+  virtual void process_event(XEvent *e) = 0;
+
+  // the masks of the modifiers which are ignored in button events.
+  int NumLockMask, ScrollLockMask;
+
+
+public:
+  BaseDisplay(const char *app_name, const char *dpy_name = 0);
+  virtual ~BaseDisplay(void);
+
+  const ScreenInfo* getScreenInfo(const unsigned int s) const;
+
+  BGCCache *gcCache(void) const;
+
+  inline bool hasShapeExtensions(void) const
+    { return shape.extensions; }
+  inline bool doShutdown(void) const
+    { return run_state == SHUTDOWN; }
+  inline bool isStartup(void) const
+    { return run_state == STARTUP; }
+
+  inline Display *getXDisplay(void) const { return display; }
+
+  inline const char *getXDisplayName(void) const
+    { return display_name; }
+  inline const char *getApplicationName(void) const
+    { return application_name; }
+
+  inline unsigned int getNumberOfScreens(void) const
+    { return screenInfoList.size(); }
+  inline int getShapeEventBase(void) const
+    { return shape.event_basep; }
+
+  inline void shutdown(void) { run_state = SHUTDOWN; }
+  inline void run(void) { run_state = RUNNING; }
+
+  void grabButton(unsigned int button, unsigned int modifiers,
+                  Window grab_window, bool owner_events,
+                  unsigned int event_mask, int pointer_mode,
+                  int keyboard_mode, Window confine_to, Cursor cursor) const;
+  void ungrabButton(unsigned int button, unsigned int modifiers,
+                    Window grab_window) const;
+
+  void eventLoop(void);
+
+  // from TimerQueueManager interface
+  virtual void addTimer(BTimer *timer);
+  virtual void removeTimer(BTimer *timer);
+
+  // another pure virtual... this is used to handle signals that BaseDisplay
+  // doesn't understand itself
+  virtual bool handleSignal(int sig) = 0;
+};
+
+
+#endif // __BaseDisplay_hh
index c3052826262ede5148b1b881fbb04913757d5b73..fa2f4b0060185bca1b0a2e6320dc9199c0585ddd 100644 (file)
@@ -1,5 +1,6 @@
-// Basemenu.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Basemenu.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
+extern "C" {
 #ifdef    HAVE_STDIO_H
 #  include <stdio.h>
 #endif // HAVE_STDIO_H
 
-#ifdef    HAVE_STDLIB_H
+#ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif // HAVE_STDLIB_H
 
-#ifdef    HAVE_STRING_H
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
+}
 
 #include <algorithm>
-using std::min;
-using std::max;
+using namespace std;
+
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "Basemenu.hh"
+#include "GCCache.hh"
+#include "Image.hh"
+#include "Screen.hh"
+#include "Util.hh"
 
-#include "i18n.h"
-#include "openbox.h"
-#include "Basemenu.h"
-#include "Screen.h"
 
 static Basemenu *shown = (Basemenu *) 0;
 
-Basemenu::Basemenu(BScreen &scrn) : openbox(scrn.getOpenbox()), screen(scrn) {
-  image_ctrl = screen.getImageControl();
-  display = openbox.getXDisplay();
+Basemenu::Basemenu(BScreen *scrn) {
+  screen = scrn;
+  blackbox = screen->getBlackbox();
+  image_ctrl = screen->getImageControl();
+  display = blackbox->getXDisplay();
   parent = (Basemenu *) 0;
   alignment = AlignDontCare;
 
@@ -85,24 +87,22 @@ Basemenu::Basemenu(BScreen &scrn) : openbox(scrn.getOpenbox()), screen(scrn) {
     menu.hilite_pixmap =
     menu.sel_pixmap = None;
 
-  menu.bevel_w = screen.getBevelWidth();
+  menu.bevel_w = screen->getBevelWidth();
 
   if (i18n.multibyte())
     menu.width = menu.title_h = menu.item_w = menu.frame_h =
-      screen.getMenuStyle()->t_fontset_extents->max_ink_extent.height +
+      screen->getMenuStyle()->t_fontset_extents->max_ink_extent.height +
       (menu.bevel_w  * 2);
   else
     menu.width = menu.title_h = menu.item_w = menu.frame_h =
-      screen.getMenuStyle()->t_font->ascent +
-      screen.getMenuStyle()->t_font->descent + (menu.bevel_w * 2);
-
-  menu.label = 0;
+      screen->getMenuStyle()->t_font->ascent +
+      screen->getMenuStyle()->t_font->descent + (menu.bevel_w * 2);
 
   menu.sublevels =
     menu.persub =
     menu.minsub = 0;
 
-  MenuStyle *style = screen.getMenuStyle();
+  MenuStyle *style = screen->getMenuStyle();
   if (i18n.multibyte()) {
     menu.item_h = style->f_fontset_extents->max_ink_extent.height +
       (menu.bevel_w);
@@ -111,59 +111,71 @@ Basemenu::Basemenu(BScreen &scrn) : openbox(scrn.getOpenbox()), screen(scrn) {
       (menu.bevel_w);
   }
 
-  menu.height = menu.title_h + screen.getBorderWidth() + menu.frame_h;
+  menu.height = menu.title_h + screen->getBorderWidth() + menu.frame_h;
 
   unsigned long attrib_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
     CWColormap | CWOverrideRedirect | CWEventMask;
   XSetWindowAttributes attrib;
   attrib.background_pixmap = None;
   attrib.background_pixel = attrib.border_pixel =
-    screen.getBorderColor()->getPixel();
-  attrib.colormap = screen.getColormap();
+    screen->getBorderColor()->pixel();
+  attrib.colormap = screen->getColormap();
   attrib.override_redirect = True;
   attrib.event_mask = ButtonPressMask | ButtonReleaseMask |
     ButtonMotionMask | ExposureMask;
 
   menu.window =
-    XCreateWindow(display, screen.getRootWindow(), menu.x, menu.y, menu.width,
-                  menu.height, screen.getBorderWidth(), screen.getDepth(),
-                  InputOutput, screen.getVisual(), attrib_mask, &attrib);
-  openbox.saveMenuSearch(menu.window, this);
+    XCreateWindow(display, screen->getRootWindow(),
+                  menu.x, menu.y, menu.width, menu.height,
+                  screen->getBorderWidth(), screen->getDepth(),
+                  InputOutput, screen->getVisual(), attrib_mask, &attrib);
+  blackbox->saveMenuSearch(menu.window, this);
 
   attrib_mask = CWBackPixmap | CWBackPixel | CWBorderPixel | CWEventMask;
-  attrib.background_pixel = screen.getBorderColor()->getPixel();
+  attrib.background_pixel = screen->getBorderColor()->pixel();
   attrib.event_mask |= EnterWindowMask | LeaveWindowMask;
 
   menu.title =
     XCreateWindow(display, menu.window, 0, 0, menu.width, menu.height, 0,
-                  screen.getDepth(), InputOutput, screen.getVisual(),
+                  screen->getDepth(), InputOutput, screen->getVisual(),
                   attrib_mask, &attrib);
-  openbox.saveMenuSearch(menu.title, this);
+  blackbox->saveMenuSearch(menu.title, this);
 
   attrib.event_mask |= PointerMotionMask;
   menu.frame = XCreateWindow(display, menu.window, 0,
-                             menu.title_h + screen.getBorderWidth(),
+                             menu.title_h + screen->getBorderWidth(),
                              menu.width, menu.frame_h, 0,
-                             screen.getDepth(), InputOutput,
-                             screen.getVisual(), attrib_mask, &attrib);
-  openbox.saveMenuSearch(menu.frame, this);
+                             screen->getDepth(), InputOutput,
+                             screen->getVisual(), attrib_mask, &attrib);
+  blackbox->saveMenuSearch(menu.frame, this);
 
   // even though this is the end of the constructor the menu is still not
   // completely created.  items must be inserted and it must be update()'d
 }
 
-
 Basemenu::~Basemenu(void) {
   XUnmapWindow(display, menu.window);
 
   if (shown && shown->getWindowID() == getWindowID())
     shown = (Basemenu *) 0;
 
-  while (!menuitems.empty())
-    remove(0);
+  MenuItems::const_iterator it = menuitems.begin();
+  while (it != menuitems.end()) {
+    BasemenuItem *item = *it;
+    if ((! internal_menu)) {
+      Basemenu *tmp = (Basemenu *) item->submenu();
+      if (tmp) {
+        if (! tmp->internal_menu) {
+          delete tmp;
+        } else {
+          tmp->internal_hide();
+        }
+      }
+    }
+    ++it;
+  }
 
-  if (menu.label)
-    delete [] menu.label;
+  std::for_each(menuitems.begin(), menuitems.end(), PointerAssassin());
 
   if (menu.title_pixmap)
     image_ctrl->removeImage(menu.title_pixmap);
@@ -177,98 +189,84 @@ Basemenu::~Basemenu(void) {
   if (menu.sel_pixmap)
     image_ctrl->removeImage(menu.sel_pixmap);
 
-  openbox.removeMenuSearch(menu.title);
+  blackbox->removeMenuSearch(menu.title);
   XDestroyWindow(display, menu.title);
 
-  openbox.removeMenuSearch(menu.frame);
+  blackbox->removeMenuSearch(menu.frame);
   XDestroyWindow(display, menu.frame);
 
-  openbox.removeMenuSearch(menu.window);
+  blackbox->removeMenuSearch(menu.window);
   XDestroyWindow(display, menu.window);
 }
 
 
-int Basemenu::insert(const char *l, int function, const char *e, int pos) {
-  char *label = 0, *exec = 0;
+BasemenuItem::~BasemenuItem(void) {}
 
-  if (l) label = bstrdup(l);
-  if (e) exec = bstrdup(e);
 
-  BasemenuItem *item = new BasemenuItem(label, function, exec);
-  if (pos == -1)
-    menuitems.push_back(item);
-  else
-    menuitems.insert(menuitems.begin() + pos, item);
+BasemenuItem *Basemenu::find(int index) {
+  if (index < 0 || index > static_cast<signed>(menuitems.size()))
+    return (BasemenuItem*) 0;
 
-  return menuitems.size();
+  return *(menuitems.begin() + index);
 }
 
 
-int Basemenu::insert(const char *l, Basemenu *submenu, int pos) {
-  char *label = 0;
-
-  if (l) label = bstrdup(l);
-
-  BasemenuItem *item = new BasemenuItem(label, submenu);
-  if (pos == -1)
+int Basemenu::insert(BasemenuItem *item, int pos) {
+  if (pos < 0) {
     menuitems.push_back(item);
-  else
-    menuitems.insert(menuitems.begin() + pos, item);
+  } else {
+    assert(pos < static_cast<signed>(menuitems.size()));
+    menuitems.insert((menuitems.begin() + pos), item);
+  }
+  return menuitems.size();
+}
 
-  submenu->parent = this;
 
-  return menuitems.size();
+int Basemenu::insert(const string& label, int function,
+                     const string& exec, int pos) {
+  BasemenuItem *item = new BasemenuItem(label, function, exec);
+  return insert(item, pos);
 }
 
 
-int Basemenu::insert(const char **ulabel, int pos, int function) {
-  BasemenuItem *item = new BasemenuItem(ulabel, function);
-  if (pos == -1)
-    menuitems.push_back(item);
-  else
-    menuitems.insert(menuitems.begin() + pos, item);
+int Basemenu::insert(const string& label, Basemenu *submenu, int pos) {
+  BasemenuItem *item = new BasemenuItem(label, submenu);
+  submenu->parent = this;
 
-  return menuitems.size();
+  return insert(item, pos);
 }
 
 
 int Basemenu::remove(int index) {
-  if (index < 0 || index > (signed)menuitems.size()) return -1;
-
-  BasemenuItem *item = menuitems[index];
-  menuitems.erase(menuitems.begin() + index);
-
-  if (item) {
-    if ((!internal_menu) && (item->submenu())) {
-      Basemenu *tmp = (Basemenu *) item->submenu();
+  BasemenuItem *item = find(index);
+  if (! item) return -1;
 
+  if ((! internal_menu)) {
+    Basemenu *tmp = (Basemenu *) item->submenu();
+    if (tmp) {
       if (! tmp->internal_menu) {
         delete tmp;
       } else {
         tmp->internal_hide();
       }
     }
-
-    if (item->label())
-      delete [] item->label();
-
-    if (item->exec())
-      delete [] item->exec();
-
-    delete item;
   }
 
+  delete item;
+
   if (which_sub == index)
     which_sub = -1;
   else if (which_sub > index)
     which_sub--;
 
+  menuitems.erase(menuitems.begin() + index);
+
   return menuitems.size();
 }
 
 
 void Basemenu::update(void) {
-  MenuStyle *style = screen.getMenuStyle();
+  MenuStyle *style = screen->getMenuStyle();
   if (i18n.multibyte()) {
     menu.item_h = style->f_fontset_extents->max_ink_extent.height +
       menu.bevel_w;
@@ -282,18 +280,15 @@ void Basemenu::update(void) {
   }
 
   if (title_vis) {
-    const char *s = (menu.label) ? menu.label :
-      i18n(BasemenuSet, BasemenuOpenboxMenu,
-           "Openbox Menu");
+    const char *s = getLabel();
     int l = strlen(s);
 
-
     if (i18n.multibyte()) {
       XRectangle ink, logical;
-      XmbTextExtents(screen.getMenuStyle()->t_fontset, s, l, &ink, &logical);
+      XmbTextExtents(screen->getMenuStyle()->t_fontset, s, l, &ink, &logical);
       menu.item_w = logical.width;
     } else {
-      menu.item_w = XTextWidth(screen.getMenuStyle()->t_font, s, l);
+      menu.item_w = XTextWidth(screen->getMenuStyle()->t_font, s, l);
     }
 
     menu.item_w += (menu.bevel_w * 2);
@@ -301,37 +296,38 @@ void Basemenu::update(void) {
     menu.item_w = 1;
   }
 
-  int ii = 0;
-  menuitemList::const_iterator it = menuitems.begin();
-  for (; it != menuitems.end(); it++) {
-    const char *s = (((*it)->u && *(*it)->u) ? *(*it)->u :
-                     (((*it)->l) ? (*it)->l : (const char *) 0));
+  unsigned int ii = 0;
+  MenuItems::iterator it = menuitems.begin(), end = menuitems.end();
+  for (; it != end; ++it) {
+    BasemenuItem *tmp = *it;
+    const char *s = tmp->l.c_str();
     int l = strlen(s);
 
     if (i18n.multibyte()) {
       XRectangle ink, logical;
-      XmbTextExtents(screen.getMenuStyle()->f_fontset, s, l, &ink, &logical);
+      XmbTextExtents(screen->getMenuStyle()->f_fontset, s, l, &ink, &logical);
       ii = logical.width;
     } else
-      ii = XTextWidth(screen.getMenuStyle()->f_font, s, l);
+      ii = XTextWidth(screen->getMenuStyle()->f_font, s, l);
 
     ii += (menu.bevel_w * 2) + (menu.item_h * 2);
 
-    menu.item_w = ((menu.item_w < (unsigned int) ii) ? ii : menu.item_w);
+    menu.item_w = ((menu.item_w < ii) ? ii : menu.item_w);
   }
 
-  if (menuitems.size()) {
+  if (! menuitems.empty()) {
     menu.sublevels = 1;
 
-    while (((menu.item_h * (menuitems.size() + 1) / menu.sublevels)
-            + menu.title_h + screen.getBorderWidth()) >
-           screen.size().h())
+    unsigned int menu_size = menuitems.size();
+    while (((menu.item_h * (menu_size + 1) / menu.sublevels)
+            + menu.title_h + screen->getBorderWidth()) >
+           screen->getHeight())
       menu.sublevels++;
 
     if (menu.sublevels < menu.minsub) menu.sublevels = menu.minsub;
 
-    menu.persub = menuitems.size() / menu.sublevels;
-    if (menuitems.size() % menu.sublevels) menu.persub++;
+    menu.persub = menu_size / menu.sublevels;
+    if (menu_size % menu.sublevels) menu.persub++;
   } else {
     menu.sublevels = 0;
     menu.persub = 0;
@@ -341,7 +337,7 @@ void Basemenu::update(void) {
   if (! menu.width) menu.width = menu.item_w;
 
   menu.frame_h = (menu.item_h * menu.persub);
-  menu.height = ((title_vis) ? menu.title_h + screen.getBorderWidth() : 0) +
+  menu.height = ((title_vis) ? menu.title_h + screen->getBorderWidth() : 0) +
     menu.frame_h;
   if (! menu.frame_h) menu.frame_h = 1;
   if (menu.height < 1) menu.height = 1;
@@ -350,14 +346,14 @@ void Basemenu::update(void) {
   BTexture *texture;
   if (title_vis) {
     tmp = menu.title_pixmap;
-    texture = &(screen.getMenuStyle()->title);
-    if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
+    texture = &(screen->getMenuStyle()->title);
+    if (texture->texture() == (BTexture::Flat | BTexture::Solid)) {
       menu.title_pixmap = None;
       XSetWindowBackground(display, menu.title,
-                           texture->getColor()->getPixel());
+                           texture->color().pixel());
     } else {
       menu.title_pixmap =
-        image_ctrl->renderImage(menu.width, menu.title_h, texture);
+        image_ctrl->renderImage(menu.width, menu.title_h, *texture);
       XSetWindowBackgroundPixmap(display, menu.title, menu.title_pixmap);
     }
     if (tmp) image_ctrl->removeImage(tmp);
@@ -365,35 +361,35 @@ void Basemenu::update(void) {
   }
 
   tmp = menu.frame_pixmap;
-  texture = &(screen.getMenuStyle()->frame);
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
+  texture = &(screen->getMenuStyle()->frame);
+  if (texture->texture() == (BTexture::Flat | BTexture::Solid)) {
     menu.frame_pixmap = None;
     XSetWindowBackground(display, menu.frame,
-                         texture->getColor()->getPixel());
+                         texture->color().pixel());
   } else {
     menu.frame_pixmap =
-      image_ctrl->renderImage(menu.width, menu.frame_h, texture);
+      image_ctrl->renderImage(menu.width, menu.frame_h, *texture);
     XSetWindowBackgroundPixmap(display, menu.frame, menu.frame_pixmap);
   }
   if (tmp) image_ctrl->removeImage(tmp);
 
   tmp = menu.hilite_pixmap;
-  texture = &(screen.getMenuStyle()->hilite);
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
+  texture = &(screen->getMenuStyle()->hilite);
+  if (texture->texture() == (BTexture::Flat | BTexture::Solid)) {
     menu.hilite_pixmap = None;
   } else {
     menu.hilite_pixmap =
-      image_ctrl->renderImage(menu.item_w, menu.item_h, texture);
+      image_ctrl->renderImage(menu.item_w, menu.item_h, *texture);
   }
   if (tmp) image_ctrl->removeImage(tmp);
 
   tmp = menu.sel_pixmap;
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
+  if (texture->texture() == (BTexture::Flat | BTexture::Solid)) {
     menu.sel_pixmap = None;
   } else {
     int hw = menu.item_h / 2;
     menu.sel_pixmap =
-      image_ctrl->renderImage(hw, hw, texture);
+      image_ctrl->renderImage(hw, hw, *texture);
   }
   if (tmp) image_ctrl->removeImage(tmp);
 
@@ -404,7 +400,7 @@ void Basemenu::update(void) {
 
   XMoveResizeWindow(display, menu.frame, 0,
                     ((title_vis) ? menu.title_h +
-                     screen.getBorderWidth() : 0), menu.width,
+                     screen->getBorderWidth() : 0), menu.width,
                     menu.frame_h);
 
   XClearWindow(display, menu.window);
@@ -413,7 +409,8 @@ void Basemenu::update(void) {
 
   if (title_vis && visible) redrawTitle();
 
-  for (int i = 0; visible && i < (signed)menuitems.size(); i++) {
+  const int menu_size = menuitems.size();
+  for (int i = 0; visible && i < menu_size; i++) {
     if (i == which_sub) {
       drawItem(i, True, 0);
       drawSubmenu(i);
@@ -456,10 +453,9 @@ void Basemenu::hide(void) {
 
 
 void Basemenu::internal_hide(void) {
-  if (which_sub != -1) {
-    BasemenuItem *tmp = menuitems[which_sub];
+  BasemenuItem *tmp = find(which_sub);
+  if (tmp)
     tmp->submenu()->internal_hide();
-  }
 
   if (parent && (! torn)) {
     parent->drawItem(parent->which_sub, False, True);
@@ -486,154 +482,156 @@ void Basemenu::move(int x, int y) {
 
 
 void Basemenu::redrawTitle(void) {
-  char *text = (char *) ((menu.label) ? menu.label :
-                         i18n(BasemenuSet, BasemenuOpenboxMenu,
-                              "Openbox Menu"));
+  const char *text = (! menu.label.empty()) ? getLabel() :
+    i18n(BasemenuSet, BasemenuBlackboxMenu, "Blackbox Menu");
   int dx = menu.bevel_w, len = strlen(text);
   unsigned int l;
 
   if (i18n.multibyte()) {
     XRectangle ink, logical;
-    XmbTextExtents(screen.getMenuStyle()->t_fontset, text, len, &ink, &logical);
+    XmbTextExtents(screen->getMenuStyle()->t_fontset, text, len,
+                   &ink, &logical);
     l = logical.width;
   } else {
-    l = XTextWidth(screen.getMenuStyle()->t_font, text, len);
+    l = XTextWidth(screen->getMenuStyle()->t_font, text, len);
   }
 
   l +=  (menu.bevel_w * 2);
 
-  switch (screen.getMenuStyle()->t_justify) {
-  case BScreen::RightJustify:
+  switch (screen->getMenuStyle()->t_justify) {
+  case RightJustify:
     dx += menu.width - l;
     break;
 
-  case BScreen::CenterJustify:
+  case CenterJustify:
     dx += (menu.width - l) / 2;
     break;
+
+  case LeftJustify:
+  default:
+    break;
   }
 
-  MenuStyle *style = screen.getMenuStyle();
+  MenuStyle *style = screen->getMenuStyle();
+  BPen pen(style->t_text, style->t_font);
   if (i18n.multibyte())
-    XmbDrawString(display, menu.title, style->t_fontset, style->t_text_gc, dx,
+    XmbDrawString(display, menu.title, style->t_fontset, pen.gc(), dx,
                   (menu.bevel_w - style->t_fontset_extents->max_ink_extent.y),
                   text, len);
   else
-    XDrawString(display, menu.title, style->t_text_gc, dx,
+    XDrawString(display, menu.title, pen.gc(), dx,
                 (style->t_font->ascent + menu.bevel_w), text, len);
 }
 
 
 void Basemenu::drawSubmenu(int index) {
-  if (which_sub != -1 && which_sub != index) {
-    BasemenuItem *itmp = menuitems[which_sub];
+  BasemenuItem *item = find(which_sub);
+  if (item && item->submenu() && ! item->submenu()->isTorn() &&
+      which_sub != index)
+    item->submenu()->internal_hide();
+
+  item = find(index);
+  if (! item)
+    return;
+  Basemenu *submenu = item->submenu();
+
+  if (submenu && visible && ! submenu->isTorn() && item->isEnabled()) {
+    if (submenu->parent != this) submenu->parent = this;
+    int sbl = index / menu.persub, i = index - (sbl * menu.persub),
+      x = menu.x + ((menu.item_w * (sbl + 1)) + screen->getBorderWidth()), y;
+
+    if (alignment == AlignTop) {
+      y = (((shifted) ? menu.y_shift : menu.y) +
+           ((title_vis) ? menu.title_h + screen->getBorderWidth() : 0) -
+           ((submenu->title_vis) ?
+            submenu->menu.title_h + screen->getBorderWidth() : 0));
+    } else {
+      y = (((shifted) ? menu.y_shift : menu.y) +
+           (menu.item_h * i) +
+           ((title_vis) ? menu.title_h + screen->getBorderWidth() : 0) -
+           ((submenu->title_vis) ?
+            submenu->menu.title_h + screen->getBorderWidth() : 0));
+    }
 
-    if (! itmp->submenu()->isTorn())
-      itmp->submenu()->internal_hide();
-  }
+    if (alignment == AlignBottom &&
+        (y + submenu->menu.height) > ((shifted) ? menu.y_shift :
+                                              menu.y) + menu.height)
+      y = (((shifted) ? menu.y_shift : menu.y) +
+           menu.height - submenu->menu.height);
 
-  if (index >= 0 && index < (signed)menuitems.size()) {
-    BasemenuItem *item = menuitems[index];
-    if (item->submenu() && visible && (! item->submenu()->isTorn()) &&
-        item->isEnabled()) {
-      if (item->submenu()->parent != this) item->submenu()->parent = this;
-      int sbl = index / menu.persub, i = index - (sbl * menu.persub),
-      x = menu.x +
-        ((menu.item_w * (sbl + 1)) + screen.getBorderWidth()), y;
-
-      if (alignment == AlignTop)
-        y = (((shifted) ? menu.y_shift : menu.y) +
-             ((title_vis) ? menu.title_h + screen.getBorderWidth() : 0) -
-             ((item->submenu()->title_vis) ?
-              item->submenu()->menu.title_h + screen.getBorderWidth() : 0));
-      else
-        y = (((shifted) ? menu.y_shift : menu.y) +
-             (menu.item_h * i) +
-             ((title_vis) ? menu.title_h + screen.getBorderWidth() : 0) -
-             ((item->submenu()->title_vis) ?
-              item->submenu()->menu.title_h + screen.getBorderWidth() : 0));
-
-      if (alignment == AlignBottom &&
-          (y + item->submenu()->menu.height) > ((shifted) ? menu.y_shift :
-                                                menu.y) + menu.height)
-        y = (((shifted) ? menu.y_shift : menu.y) +
-             menu.height - item->submenu()->menu.height);
-
-      if ((x + item->submenu()->getWidth()) > screen.size().w()) {
-        x = ((shifted) ? menu.x_shift : menu.x) -
-          item->submenu()->getWidth() - screen.getBorderWidth();
-      }
+    if ((x + submenu->getWidth()) > screen->getWidth())
+      x = ((shifted) ? menu.x_shift : menu.x) -
+        submenu->getWidth() - screen->getBorderWidth();
 
-      if (x < 0) x = 0;
+    if (x < 0) x = 0;
 
-      if ((y + item->submenu()->getHeight()) > screen.size().h())
-        y = screen.size().h() - item->submenu()->getHeight() -
-          (screen.getBorderWidth() * 2);
-      if (y < 0) y = 0;
+    if ((y + submenu->getHeight()) > screen->getHeight())
+      y = screen->getHeight() - submenu->getHeight() -
+        (screen->getBorderWidth() * 2);
+    if (y < 0) y = 0;
 
-      item->submenu()->move(x, y);
-      if (! moving) drawItem(index, True);
+    submenu->move(x, y);
+    if (! moving) drawItem(index, True);
 
-      if (! item->submenu()->isVisible())
-        item->submenu()->show();
-      item->submenu()->moving = moving;
-      which_sub = index;
-    } else {
-      which_sub = -1;
-    }
+    if (! submenu->isVisible())
+      submenu->show();
+    submenu->moving = moving;
+    which_sub = index;
+  } else {
+    which_sub = -1;
   }
 }
 
 
 bool Basemenu::hasSubmenu(int index) {
-  if (index < 0 | index >= (signed)menuitems.size())
-    return false;
-  return (menuitems[index]->submenu());
+  BasemenuItem *item = find(index);
+  if (item && item->submenu())
+    return True;
+  return False;
 }
 
 
-void Basemenu::drawItem(int index, Bool highlight, Bool clear,
+void Basemenu::drawItem(int index, bool highlight, bool clear,
                         int x, int y, unsigned int w, unsigned int h)
 {
-  if (index < 0 || index > (signed)menuitems.size()) return;
-
-  BasemenuItem *item = menuitems[index];
+  BasemenuItem *item = find(index);
   if (! item) return;
 
-  Bool dotext = True, dohilite = True, dosel = True;
-  const char *text = (item->ulabel()) ? *item->ulabel() : item->label();
+  bool dotext = True, dohilite = True, dosel = True;
+  const char *text = item->label();
   int sbl = index / menu.persub, i = index - (sbl * menu.persub);
   int item_x = (sbl * menu.item_w), item_y = (i * menu.item_h);
   int hilite_x = item_x, hilite_y = item_y, hoff_x = 0, hoff_y = 0;
   int text_x = 0, text_y = 0, len = strlen(text), sel_x = 0, sel_y = 0;
   unsigned int hilite_w = menu.item_w, hilite_h = menu.item_h, text_w = 0,
-  text_h = 0;
+    text_h = 0;
   unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4;
 
   if (text) {
     if (i18n.multibyte()) {
       XRectangle ink, logical;
-      XmbTextExtents(screen.getMenuStyle()->f_fontset,
+      XmbTextExtents(screen->getMenuStyle()->f_fontset,
                      text, len, &ink, &logical);
       text_w = logical.width;
       text_y = item_y + (menu.bevel_w / 2) -
-        screen.getMenuStyle()->f_fontset_extents->max_ink_extent.y;
+        screen->getMenuStyle()->f_fontset_extents->max_ink_extent.y;
     } else {
-      text_w = XTextWidth(screen.getMenuStyle()->f_font, text, len);
+      text_w = XTextWidth(screen->getMenuStyle()->f_font, text, len);
       text_y =  item_y +
-        screen.getMenuStyle()->f_font->ascent +
+        screen->getMenuStyle()->f_font->ascent +
         (menu.bevel_w / 2);
     }
 
-    switch(screen.getMenuStyle()->f_justify) {
-    case BScreen::LeftJustify:
+    switch(screen->getMenuStyle()->f_justify) {
+    case LeftJustify:
       text_x = item_x + menu.bevel_w + menu.item_h + 1;
       break;
 
-    case BScreen::RightJustify:
+    case RightJustify:
       text_x = item_x + menu.item_w - (menu.item_h + menu.bevel_w + text_w);
       break;
 
-    case BScreen::CenterJustify:
+    case CenterJustify:
       text_x = item_x + ((menu.item_w + 1 - text_w) / 2);
       break;
     }
@@ -641,16 +639,15 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear,
     text_h = menu.item_h - menu.bevel_w;
   }
 
-  GC gc =
-    ((highlight || item->isSelected()) ? screen.getMenuStyle()->h_text_gc :
-     screen.getMenuStyle()->f_text_gc),
-  tgc =
-    ((highlight) ? screen.getMenuStyle()->h_text_gc :
-     ((item->isEnabled()) ? screen.getMenuStyle()->f_text_gc :
-      screen.getMenuStyle()->d_text_gc));
+  MenuStyle *style = screen->getMenuStyle();
+  BPen pen((highlight || item->isSelected()) ? style->h_text : style->f_text),
+      textpen((highlight) ? style->h_text :
+              item->isEnabled() ? style->f_text : style->d_text, style->f_font),
+      hipen(style->hilite.color());
+
 
   sel_x = item_x;
-  if (screen.getMenuStyle()->bullet_pos == Right)
+  if (screen->getMenuStyle()->bullet_pos == Right)
     sel_x += (menu.item_w - menu.item_h - menu.bevel_w);
   sel_x += quarter_w;
   sel_y = item_y + quarter_w;
@@ -660,8 +657,8 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear,
                False);
   } else if (! (x == y && y == -1 && w == h && h == 0)) {
     // calculate the which part of the hilite to redraw
-    if (! (max(item_x, x) <= (signed) min(item_x + menu.item_w, x + w) &&
-           max(item_y, y) <= (signed) min(item_y + menu.item_h, y + h))) {
+    if (! (max(item_x, x) <= min<signed>(item_x + menu.item_w, x + w) &&
+           max(item_y, y) <= min<signed>(item_y + menu.item_h, y + h))) {
       dohilite = False;
     } else {
       hilite_x = max(item_x, x);
@@ -672,57 +669,53 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear,
       hoff_y = hilite_y % menu.item_h;
     }
 
-    // check if we need to redraw the text    
+    // check if we need to redraw the text
     int text_ry = item_y + (menu.bevel_w / 2);
-    if (! (max(text_x, x) <= (signed) min(text_x + text_w, x + w) &&
-           max(text_ry, y) <= (signed) min(text_ry + text_h, y + h)))
+    if (! (max(text_x, x) <= min<signed>(text_x + text_w, x + w) &&
+           max(text_ry, y) <= min<signed>(text_ry + text_h, y + h)))
       dotext = False;
 
     // check if we need to redraw the select pixmap/menu bullet
-    if (! (max(sel_x, x) <= (signed) min(sel_x + half_w, x + w) &&
-           max(sel_y, y) <= (signed) min(sel_y + half_w, y + h)))
+    if (! (max(sel_x, x) <= min<signed>(sel_x + half_w, x + w) &&
+           max(sel_y, y) <= min<signed>(sel_y + half_w, y + h)))
       dosel = False;
   }
 
   if (dohilite && highlight && (menu.hilite_pixmap != ParentRelative)) {
     if (menu.hilite_pixmap)
       XCopyArea(display, menu.hilite_pixmap, menu.frame,
-                screen.getMenuStyle()->hilite_gc, hoff_x, hoff_y,
+                hipen.gc(), hoff_x, hoff_y,
                 hilite_w, hilite_h, hilite_x, hilite_y);
     else
-      XFillRectangle(display, menu.frame,
-                     screen.getMenuStyle()->hilite_gc,
+      XFillRectangle(display, menu.frame, hipen.gc(),
                      hilite_x, hilite_y, hilite_w, hilite_h);
   } else if (dosel && item->isSelected() &&
              (menu.sel_pixmap != ParentRelative)) {
     if (menu.sel_pixmap)
-      XCopyArea(display, menu.sel_pixmap, menu.frame,
-                screen.getMenuStyle()->hilite_gc, 0, 0,
+      XCopyArea(display, menu.sel_pixmap, menu.frame, hipen.gc(), 0, 0,
                 half_w, half_w, sel_x, sel_y);
     else
-      XFillRectangle(display, menu.frame,
-                     screen.getMenuStyle()->hilite_gc,
-                     sel_x, sel_y, half_w, half_w);
+      XFillRectangle(display, menu.frame, hipen.gc(), sel_x, sel_y, half_w, half_w);
   }
 
   if (dotext && text) {
     if (i18n.multibyte())
-      XmbDrawString(display, menu.frame, screen.getMenuStyle()->f_fontset,
-                    tgc, text_x, text_y, text, len);
+      XmbDrawString(display, menu.frame, screen->getMenuStyle()->f_fontset,
+                    textpen.gc(), text_x, text_y, text, len);
     else
-      XDrawString(display, menu.frame, tgc, text_x, text_y, text, len);
+      XDrawString(display, menu.frame, textpen.gc(), text_x, text_y, text, len);
   }
 
   if (dosel && item->submenu()) {
-    switch (screen.getMenuStyle()->bullet) {
+    switch (screen->getMenuStyle()->bullet) {
     case Square:
-      XDrawRectangle(display, menu.frame, gc, sel_x, sel_y, half_w, half_w);
+      XDrawRectangle(display, menu.frame, pen.gc(), sel_x, sel_y, half_w, half_w);
       break;
 
     case Triangle:
       XPoint tri[3];
 
-      if (screen.getMenuStyle()->bullet_pos == Right) {
+      if (screen->getMenuStyle()->bullet_pos == Right) {
         tri[0].x = sel_x + quarter_w - 2;
         tri[0].y = sel_y + quarter_w - 2;
         tri[1].x = 4;
@@ -738,7 +731,7 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear,
         tri[2].y = -4;
       }
 
-      XFillPolygon(display, menu.frame, gc, tri, 3, Convex,
+      XFillPolygon(display, menu.frame, pen.gc(), tri, 3, Convex,
                    CoordModePrevious);
       break;
 
@@ -754,7 +747,7 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear,
       dia[3].x = -3;
       dia[3].y = 3;
 
-      XFillPolygon(display, menu.frame, gc, dia, 4, Convex,
+      XFillPolygon(display, menu.frame, pen.gc(), dia, 4, Convex,
                    CoordModePrevious);
       break;
     }
@@ -762,18 +755,13 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear,
 }
 
 
-void Basemenu::setLabel(const char *l) {
-  if (menu.label)
-    delete [] menu.label;
-
-  if (l) menu.label = bstrdup(l);
-  else menu.label = 0;
+void Basemenu::setLabel(const string& label) {
+  menu.label = label;
 }
 
 
 void Basemenu::setItemSelected(int index, bool sel) {
-  if (index < 0 || index >= (signed)menuitems.size()) return;
-
+  assert(index >= 0);
   BasemenuItem *item = find(index);
   if (! item) return;
 
@@ -783,18 +771,16 @@ void Basemenu::setItemSelected(int index, bool sel) {
 
 
 bool Basemenu::isItemSelected(int index) {
-  if (index < 0 || index >= (signed)menuitems.size()) return false;
-
+  assert(index >= 0);
   BasemenuItem *item = find(index);
-  if (! item) return false;
+  if (! item) return False;
 
   return item->isSelected();
 }
 
 
 void Basemenu::setItemEnabled(int index, bool enable) {
-  if (index < 0 || index >= (signed)menuitems.size()) return;
-
+  assert(index >= 0);
   BasemenuItem *item = find(index);
   if (! item) return;
 
@@ -804,8 +790,7 @@ void Basemenu::setItemEnabled(int index, bool enable) {
 
 
 bool Basemenu::isItemEnabled(int index) {
-  if (index < 0 || index >= (signed)menuitems.size()) return false;
-
+  assert(index >= 0);
   BasemenuItem *item = find(index);
   if (! item) return False;
 
@@ -818,11 +803,11 @@ void Basemenu::buttonPressEvent(XButtonEvent *be) {
     int sbl = (be->x / menu.item_w), i = (be->y / menu.item_h);
     int w = (sbl * menu.persub) + i;
 
-    if (w < (signed)menuitems.size() && w >= 0) {
+    BasemenuItem *item = find(w);
+    if (item) {
       which_press = i;
       which_sbl = sbl;
 
-      BasemenuItem *item = menuitems[w];
 
       if (item->submenu())
         drawSubmenu(w);
@@ -845,32 +830,33 @@ void Basemenu::buttonReleaseEvent(XButtonEvent *re) {
         drawSubmenu(which_sub);
     }
 
-    if (re->x >= 0 && re->x <= (signed) menu.width &&
-        re->y >= 0 && re->y <= (signed) menu.title_h)
+    if (re->x >= 0 && re->x <= static_cast<signed>(menu.width) &&
+        re->y >= 0 && re->y <= static_cast<signed>(menu.title_h))
       if (re->button == 3)
         hide();
   } else if (re->window == menu.frame &&
-             re->x >= 0 && re->x < (signed) menu.width &&
-             re->y >= 0 && re->y < (signed) menu.frame_h) {
+             re->x >= 0 && re->x < static_cast<signed>(menu.width) &&
+             re->y >= 0 && re->y < static_cast<signed>(menu.frame_h)) {
     if (re->button == 3) {
       hide();
     } else {
       int sbl = (re->x / menu.item_w), i = (re->y / menu.item_h),
-      ix = sbl * menu.item_w, iy = i * menu.item_h,
-      w = (sbl * menu.persub) + i,
-      p = (which_sbl * menu.persub) + which_press;
+        ix = sbl * menu.item_w, iy = i * menu.item_h,
+        w = (sbl * menu.persub) + i,
+        p = (which_sbl * menu.persub) + which_press;
 
-      if (w < (signed)menuitems.size() && w >= 0) {
+      if (w >= 0 && w < static_cast<signed>(menuitems.size())) {
         drawItem(p, (p == which_sub), True);
 
         if  (p == w && isItemEnabled(w)) {
-          if (re->x > ix && re->x < (signed) (ix + menu.item_w) &&
-              re->y > iy && re->y < (signed) (iy + menu.item_h)) {
+          if (re->x > ix && re->x < static_cast<signed>(ix + menu.item_w) &&
+              re->y > iy && re->y < static_cast<signed>(iy + menu.item_h)) {
             itemSelected(re->button, w);
           }
         }
-      } else
+      } else {
         drawItem(p, False, True);
+      }
     }
   }
 }
@@ -891,7 +877,7 @@ void Basemenu::motionNotifyEvent(XMotionEvent *me) {
           drawSubmenu(which_sub);
       } else {
         menu.x = me->x_root - menu.x_move,
-        menu.y = me->y_root - menu.y_move;
+          menu.y = me->y_root - menu.y_move;
 
         XMoveWindow(display, menu.window, menu.x, menu.y);
 
@@ -900,16 +886,16 @@ void Basemenu::motionNotifyEvent(XMotionEvent *me) {
       }
     }
   } else if ((! (me->state & Button1Mask)) && me->window == menu.frame &&
-             me->x >= 0 && me->x < (signed) menu.width &&
-             me->y >= 0 && me->y < (signed) menu.frame_h) {
+             me->x >= 0 && me->x < static_cast<signed>(menu.width) &&
+             me->y >= 0 && me->y < static_cast<signed>(menu.frame_h)) {
     int sbl = (me->x / menu.item_w), i = (me->y / menu.item_h),
-    w = (sbl * menu.persub) + i;
+      w = (sbl * menu.persub) + i;
 
     if ((i != which_press || sbl != which_sbl) &&
-        (w < (signed)menuitems.size() && w >= 0)) {
+        (w >= 0 && w < static_cast<signed>(menuitems.size()))) {
       if (which_press != -1 && which_sbl != -1) {
         int p = (which_sbl * menu.persub) + which_press;
-        BasemenuItem *item = menuitems[p];
+        BasemenuItem *item = find(p);
 
         drawItem(p, False, True);
         if (item->submenu())
@@ -923,7 +909,7 @@ void Basemenu::motionNotifyEvent(XMotionEvent *me) {
       which_press = i;
       which_sbl = sbl;
 
-      BasemenuItem *itmp = menuitems[w];
+      BasemenuItem *itmp = find(w);
 
       if (itmp->submenu())
         drawSubmenu(w);
@@ -943,20 +929,21 @@ void Basemenu::exposeEvent(XExposeEvent *ee) {
     // items down in that sublevel
 
     int sbl = (ee->x / menu.item_w), id = (ee->y / menu.item_h),
-    // next... figure out how many sublevels over the redraw spans
-    sbl_d = ((ee->x + ee->width) / menu.item_w),
-    // then we see how many items down to redraw
-    id_d = ((ee->y + ee->height) / menu.item_h);
+      // next... figure out how many sublevels over the redraw spans
+      sbl_d = ((ee->x + ee->width) / menu.item_w),
+      // then we see how many items down to redraw
+      id_d = ((ee->y + ee->height) / menu.item_h);
 
     if (id_d > menu.persub) id_d = menu.persub;
 
     // draw the sublevels and the number of items the exposure spans
-    menuitemList::const_iterator it = menuitems.begin();
+    MenuItems::iterator it,
+      end = menuitems.end();
     int i, ii;
     for (i = sbl; i <= sbl_d; i++) {
       // set the iterator to the first item in the sublevel needing redrawing
       it = menuitems.begin() + (id + (i * menu.persub));
-      for (ii = id; ii <= id_d && it != menuitems.end(); it++, ii++) {
+      for (ii = id; ii <= id_d && it != end; ++it, ii++) {
         int index = ii + (i * menu.persub);
         // redraw the item
         drawItem(index, (which_sub == index), False,
@@ -970,21 +957,21 @@ void Basemenu::exposeEvent(XExposeEvent *ee) {
 void Basemenu::enterNotifyEvent(XCrossingEvent *ce) {
   if (ce->window == menu.frame) {
     menu.x_shift = menu.x, menu.y_shift = menu.y;
-    if (menu.x + menu.width > screen.size().w()) {
-      menu.x_shift = screen.size().w() - menu.width -
-        screen.getBorderWidth();
+    if (menu.x + menu.width > screen->getWidth()) {
+      menu.x_shift = screen->getWidth() - menu.width -
+        screen->getBorderWidth();
       shifted = True;
     } else if (menu.x < 0) {
-      menu.x_shift = -screen.getBorderWidth();
+      menu.x_shift = -screen->getBorderWidth();
       shifted = True;
     }
 
-    if (menu.y + menu.height > screen.size().h()) {
-      menu.y_shift = screen.size().h() - menu.height -
-        screen.getBorderWidth();
+    if (menu.y + menu.height > screen->getHeight()) {
+      menu.y_shift = screen->getHeight() - menu.height -
+        screen->getBorderWidth();
       shifted = True;
-    } else if (menu.y + (signed) menu.title_h < 0) {
-      menu.y_shift = -screen.getBorderWidth();
+    } else if (menu.y + static_cast<signed>(menu.title_h) < 0) {
+      menu.y_shift = -screen->getBorderWidth();
       shifted = True;
     }
 
@@ -992,10 +979,10 @@ void Basemenu::enterNotifyEvent(XCrossingEvent *ce) {
       XMoveWindow(display, menu.window, menu.x_shift, menu.y_shift);
 
     if (which_sub != -1) {
-      BasemenuItem *tmp = menuitems[which_sub];
+      BasemenuItem *tmp = find(which_sub);
       if (tmp->submenu()->isVisible()) {
         int sbl = (ce->x / menu.item_w), i = (ce->y / menu.item_h),
-        w = (sbl * menu.persub) + i;
+          w = (sbl * menu.persub) + i;
 
         if (w != which_sub && (! tmp->submenu()->isTorn())) {
           tmp->submenu()->internal_hide();
@@ -1031,11 +1018,18 @@ void Basemenu::leaveNotifyEvent(XCrossingEvent *ce) {
 
 void Basemenu::reconfigure(void) {
   XSetWindowBackground(display, menu.window,
-                       screen.getBorderColor()->getPixel());
+                       screen->getBorderColor()->pixel());
   XSetWindowBorder(display, menu.window,
-                   screen.getBorderColor()->getPixel());
-  XSetWindowBorderWidth(display, menu.window, screen.getBorderWidth());
+                   screen->getBorderColor()->pixel());
+  XSetWindowBorderWidth(display, menu.window, screen->getBorderWidth());
 
-  menu.bevel_w = screen.getBevelWidth();
+  menu.bevel_w = screen->getBevelWidth();
   update();
 }
+
+
+void Basemenu::changeItemLabel(unsigned int index, const string& label) {
+  BasemenuItem *item = find(index);
+  assert(item);
+  item->newLabel(label);
+}
diff --git a/src/Basemenu.h b/src/Basemenu.h
deleted file mode 100644 (file)
index 35a9791..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-// Basemenu.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Basemenu_hh
-#define   __Basemenu_hh
-
-#include <X11/Xlib.h>
-
-class Openbox;
-class BImageControl;
-class BScreen;
-class Basemenu;
-class BasemenuItem;
-#include <vector>
-typedef std::vector<BasemenuItem *> menuitemList;
-
-class Basemenu {
-private:
-  menuitemList menuitems;
-  Openbox &openbox;
-  Basemenu *parent;
-  BImageControl *image_ctrl;
-  BScreen &screen;
-
-  Bool moving, visible, movable, torn, internal_menu, title_vis, shifted,
-    hide_tree;
-  Display *display;
-  int which_sub, which_press, which_sbl, alignment;
-
-  struct _menu {
-    Pixmap frame_pixmap, title_pixmap, hilite_pixmap, sel_pixmap;
-    Window window, frame, title;
-
-    char *label;
-    int x, y, x_move, y_move, x_shift, y_shift, sublevels, persub, minsub,
-      grab_x, grab_y;
-    unsigned int width, height, title_h, frame_h, item_w, item_h, bevel_w,
-      bevel_h;
-  } menu;
-
-
-protected:
-  inline BasemenuItem *find(int index) { return menuitems[index]; }
-  inline void setTitleVisibility(Bool b) { title_vis = b; }
-  inline void setMovable(Bool b) { movable = b; }
-  inline void setHideTree(Bool h) { hide_tree = h; }
-  inline void setMinimumSublevels(int m) { menu.minsub = m; }
-
-  virtual void itemSelected(int, int) = 0;
-  virtual void drawItem(int, Bool = False, Bool = False,
-                       int = -1, int = -1, unsigned int = 0,
-                       unsigned int = 0);
-  virtual void redrawTitle();
-  virtual void internal_hide(void);
-
-
-public:
-  Basemenu(BScreen &);
-  virtual ~Basemenu(void);
-
-  inline const Bool &isTorn(void) const { return torn; }
-  inline const Bool &isVisible(void) const { return visible; }
-
-  inline BScreen &getScreen(void) { return screen; }
-
-  inline const Window &getWindowID(void) const { return menu.window; }
-
-  inline const char *getLabel(void) const { return menu.label; }
-
-  int insert(const char *, int = 0, const char * = (const char *) 0, int = -1);
-  int insert(const char **, int = -1, int = 0);
-  int insert(const char *, Basemenu *, int = -1);
-  int remove(int);
-
-  inline int getX(void) const { return menu.x; }
-  inline int getY(void) const { return menu.y; }
-  inline unsigned int getCount(void) { return menuitems.size(); }
-  inline int getCurrentSubmenu(void) const { return which_sub; }
-
-  inline unsigned int getWidth(void) const { return menu.width; }
-  inline unsigned int getHeight(void) const { return menu.height; }
-  inline unsigned int getTitleHeight(void) const { return menu.title_h; }
-
-  inline void setInternalMenu(void) { internal_menu = True; }
-  inline void setAlignment(int a) { alignment = a; }
-  inline void setTorn(void) { torn = True; }
-  inline void removeParent(void)
-    { if (internal_menu) parent = (Basemenu *) 0; }
-
-  bool hasSubmenu(int);
-  bool isItemSelected(int);
-  bool isItemEnabled(int);
-
-  void buttonPressEvent(XButtonEvent *);
-  void buttonReleaseEvent(XButtonEvent *);
-  void motionNotifyEvent(XMotionEvent *);
-  void enterNotifyEvent(XCrossingEvent *);
-  void leaveNotifyEvent(XCrossingEvent *);
-  void exposeEvent(XExposeEvent *);
-  void reconfigure(void);
-  void setLabel(const char *n);
-  void move(int, int);
-  void update(void);
-  void setItemSelected(int, bool);
-  void setItemEnabled(int, bool);
-
-  virtual void drawSubmenu(int);
-  virtual void show(void);
-  virtual void hide(void);
-
-  enum { AlignDontCare = 1, AlignTop, AlignBottom };
-  enum { Right = 1, Left };
-  enum { Empty = 0, Square, Triangle, Diamond };
-};
-
-
-class BasemenuItem {
-private:
-  Basemenu *s;
-  const char **u, *l, *e;
-  int f, enabled, selected;
-
-  friend class Basemenu;
-
-protected:
-
-public:
-  BasemenuItem(const char *lp, int fp, const char *ep = (const char *) 0):
-    s(0), u(0), l(lp), e(ep), f(fp), enabled(1), selected(0) {}
-
-  BasemenuItem(const char *lp, Basemenu *mp): s(mp), u(0), l(lp), e(0), f(0),
-                                             enabled(1), selected(0) {}
-
-  BasemenuItem(const char **up, int fp): s(0), u(up), l(0), e(0), f(fp),
-                                        enabled(1), selected(0) {}
-
-  inline const char *exec(void) const { return e; }
-  inline const char *label(void) const { return l; }
-  inline const char **ulabel(void) const { return u; }
-  inline const int &function(void) const { return f; }
-  inline Basemenu *submenu(void) { return s; }
-
-  inline const int &isEnabled(void) const { return enabled; }
-  inline void setEnabled(int e) { enabled = e; }
-  inline const int &isSelected(void) const { return selected; }
-  inline void setSelected(int s) { selected = s; }
-};
-
-
-#endif // __Basemenu_hh
index 34ed6f11192aa4a0ab8b521bb6310a0d9bfd0227..07f70439106fe0957ad725b8265e267b4842fc2f 100644 (file)
@@ -1,5 +1,6 @@
-// Clientmenu.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Clientmenu.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "openbox.h"
-#include "Clientmenu.h"
-#include "Screen.h"
-#include "Window.h"
-#include "Workspace.h"
-#include "Workspacemenu.h"
+#include "blackbox.hh"
+#include "Clientmenu.hh"
+#include "Screen.hh"
+#include "Window.hh"
+#include "Workspace.hh"
+#include "Workspacemenu.hh"
+
 
+Clientmenu::Clientmenu(Workspace *ws) : Basemenu(ws->getScreen()) {
+  wkspc = ws;
 
-Clientmenu::Clientmenu(Workspace &ws) : Basemenu(ws.getScreen()),
-  screen(ws.getScreen()), wkspc(ws)
-{
   setInternalMenu();
 }
 
 
-void Clientmenu::itemSelected(int button, int index) {
+void Clientmenu::itemSelected(int button, unsigned int index) {
   if (button > 2) return;
 
-  OpenboxWindow *win = wkspc.getWindow(index);
+  BlackboxWindow *win = wkspc->getWindow(index);
   if (win) {
     if (button == 1) {
-      if (! wkspc.isCurrent()) wkspc.setCurrent();
+      if (! wkspc->isCurrent()) wkspc->setCurrent();
     } else if (button == 2) {
-      if (! wkspc.isCurrent()) win->deiconify(True, False);
+      if (! wkspc->isCurrent()) win->deiconify(True, False);
     }
-    wkspc.raiseWindow(win);
+    wkspc->raiseWindow(win);
     win->setInputFocus();
   }
 
-  if (! (screen.getWorkspacemenu()->isTorn() || isTorn())) hide();
+  Workspacemenu* wkspcmenu = wkspc->getScreen()->getWorkspacemenu();
+  if (! (wkspcmenu->isTorn() || isTorn())) hide();
 }
similarity index 77%
rename from src/Clientmenu.h
rename to src/Clientmenu.hh
index 88aeba6c36721f5b8a6e95e184ca9ac3b7631449..70cc2aa0e0e44bc97831560b5ccc3e1d375be159 100644 (file)
@@ -1,5 +1,6 @@
-// Clientmenu.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Clientmenu.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 #ifndef   __Clientmenu_hh
 #define   __Clientmenu_hh
 
-#include "Basemenu.h"
+#include "Basemenu.hh"
 class Workspace;
 class BScreen;
 
 class Clientmenu : public Basemenu {
 private:
-  BScreen &screen;
-  Workspace &wkspc;
+  Workspace *wkspc;
+
+  Clientmenu(const Clientmenu&);
+  Clientmenu& operator=(const Clientmenu&);
 
 protected:
-  virtual void itemSelected(int, int);
+  virtual void itemSelected(int button, unsigned int index);
 
 public:
-  Clientmenu(Workspace &);
+  Clientmenu(Workspace *ws);
 };
 
 
diff --git a/src/Color.cc b/src/Color.cc
new file mode 100644 (file)
index 0000000..7a36b03
--- /dev/null
@@ -0,0 +1,242 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Color.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
+// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifdef HAVE_CONFIG_H
+#  include "../config.h"
+#endif // HAVE_CONFIG_H
+
+#include "Color.hh"
+#include "BaseDisplay.hh"
+
+extern "C" {
+#include <stdio.h>
+}
+
+
+BColor::ColorCache BColor::colorcache;
+bool BColor::cleancache = false;
+
+BColor::BColor(const BaseDisplay * const _display, unsigned int _screen)
+  : allocated(false), r(-1), g(-1), b(-1), p(0), dpy(_display), scrn(_screen)
+{}
+
+BColor::BColor(int _r, int _g, int _b,
+               const BaseDisplay * const _display, unsigned int _screen)
+  : allocated(false), r(_r), g(_g), b(_b), p(0), dpy(_display), scrn(_screen)
+{}
+
+
+BColor::BColor(const std::string &_name,
+               const BaseDisplay * const _display, unsigned int _screen)
+  : allocated(false), r(-1), g(-1), b(-1), p(0), dpy(_display), scrn(_screen),
+    colorname(_name) {
+  parseColorName();
+}
+
+
+BColor::~BColor(void) {
+  deallocate();
+}
+
+
+void BColor::setDisplay(const BaseDisplay * const _display,
+                        unsigned int _screen) {
+  if (_display == display() && _screen == screen()) {
+    // nothing to do
+    return;
+  }
+
+  deallocate();
+
+  dpy = _display;
+  scrn = _screen;
+
+  if (! colorname.empty()) {
+    parseColorName();
+  }
+}
+
+
+unsigned long BColor::pixel(void) const {
+  if (! allocated) {
+    // mutable
+    BColor *that = (BColor *) this;
+    that->allocate();
+  }
+
+  return p;
+}
+
+
+void BColor::parseColorName(void) {
+  assert(dpy != 0);
+
+  if (colorname.empty()) {
+    fprintf(stderr, "BColor: empty colorname, cannot parse (using black)\n");
+    setRGB(0, 0, 0);
+  }
+
+  if (scrn == ~(0u))
+    scrn = DefaultScreen(display()->getXDisplay());
+  Colormap colormap = display()->getScreenInfo(scrn)->getColormap();
+
+  // get rgb values from colorname
+  XColor xcol;
+  xcol.red = 0;
+  xcol.green = 0;
+  xcol.blue = 0;
+  xcol.pixel = 0;
+
+  if (! XParseColor(display()->getXDisplay(), colormap,
+                    colorname.c_str(), &xcol)) {
+    fprintf(stderr, "BColor::allocate: color parse error: \"%s\"\n",
+            colorname.c_str());
+    setRGB(0, 0, 0);
+    return;
+  }
+
+  setRGB(xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8);
+}
+
+
+void BColor::allocate(void) {
+  assert(dpy != 0);
+
+  if (scrn == ~(0u)) scrn = DefaultScreen(display()->getXDisplay());
+  Colormap colormap = display()->getScreenInfo(scrn)->getColormap();
+
+  if (! isValid()) {
+    if (colorname.empty()) {
+      fprintf(stderr, "BColor: cannot allocate invalid color (using black)\n");
+      setRGB(0, 0, 0);
+    } else {
+      parseColorName();
+    }
+  }
+
+  // see if we have allocated this color before
+  RGB rgb(display(), scrn, r, g, b);
+  ColorCache::iterator it = colorcache.find(rgb);
+  if (it != colorcache.end()) {
+    // found
+    allocated = true;
+    p = (*it).second.p;
+    (*it).second.count++;
+    return;
+  }
+
+  // allocate color from rgb values
+  XColor xcol;
+  xcol.red =   r | r << 8;
+  xcol.green = g | g << 8;
+  xcol.blue =  b | b << 8;
+  xcol.pixel = 0;
+
+  if (! XAllocColor(display()->getXDisplay(), colormap, &xcol)) {
+    fprintf(stderr, "BColor::allocate: color alloc error: rgb:%x/%x/%x\n",
+            r, g, b);
+    xcol.pixel = 0;
+  }
+
+  p = xcol.pixel;
+  allocated = true;
+
+  colorcache.insert(ColorCacheItem(rgb, PixelRef(p)));
+
+  if (cleancache)
+    doCacheCleanup();
+}
+
+
+void BColor::deallocate(void) {
+  if (! allocated)
+    return;
+
+  assert(dpy != 0);
+
+  ColorCache::iterator it = colorcache.find(RGB(display(), scrn, r, g, b));
+  if (it != colorcache.end()) {
+    if ((*it).second.count >= 1)
+      (*it).second.count--;
+  }
+
+  if (cleancache)
+    doCacheCleanup();
+
+  allocated = false;
+}
+
+
+BColor &BColor::operator=(const BColor &c) {
+  deallocate();
+
+  setRGB(c.r, c.g, c.b);
+  colorname = c.colorname;
+  dpy = c.dpy;
+  scrn = c.scrn;
+  return *this;
+}
+
+
+void BColor::cleanupColorCache(void) {
+  cleancache = true;
+}
+
+
+void BColor::doCacheCleanup(void) {
+  // ### TODO - support multiple displays!
+  ColorCache::iterator it = colorcache.begin();
+  if (it == colorcache.end()) {
+    // nothing to do
+    return;
+  }
+
+  const BaseDisplay* const display = (*it).first.display;
+  unsigned long *pixels = new unsigned long[ colorcache.size() ];
+  unsigned int i, count;
+
+  for (i = 0; i < display->getNumberOfScreens(); i++) {
+    count = 0;
+    it = colorcache.begin();
+
+    while (it != colorcache.end()) {
+      if ((*it).second.count != 0 || (*it).first.screen != i) {
+        ++it;
+        continue;
+      }
+
+      pixels[ count++ ] = (*it).second.p;
+      ColorCache::iterator it2 = it;
+      ++it;
+      colorcache.erase(it2);
+    }
+
+    if (count > 0)
+      XFreeColors(display->getXDisplay(),
+                  display->getScreenInfo(i)->getColormap(),
+                  pixels, count, 0);
+  }
+
+  delete [] pixels;
+  cleancache = false;
+}
diff --git a/src/Color.hh b/src/Color.hh
new file mode 100644 (file)
index 0000000..9eb8ef2
--- /dev/null
@@ -0,0 +1,128 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Color.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
+// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef COLOR_HH
+#define COLOR_HH
+
+extern "C" {
+#include <X11/Xlib.h>
+}
+
+#include <map>
+#include <string>
+
+class BaseDisplay;
+
+class BColor {
+public:
+  BColor(const BaseDisplay * const _display = 0, unsigned int _screen = ~(0u));
+  BColor(int _r, int _g, int _b,
+         const BaseDisplay * const _display, unsigned int _screen = ~(0u));
+  BColor(const std::string &_name,
+         const BaseDisplay * const _display, unsigned int _screen = ~(0u));
+  ~BColor(void);
+
+  inline const std::string &name(void) const { return colorname; }
+
+  inline int   red(void) const { return r; }
+  inline int green(void) const { return g; }
+  inline int  blue(void) const { return b; }
+  void setRGB(int _r, int _g, int _b) {
+    deallocate();
+    r = _r;
+    g = _g;
+    b = _b;
+  }
+
+  inline const BaseDisplay *display(void) const { return dpy; }
+  inline unsigned int screen(void) const { return scrn; }
+  void setDisplay(const BaseDisplay * const _display,
+                  unsigned int _screen = ~(0u));
+
+  inline bool isAllocated(void) const { return allocated; }
+
+  inline bool isValid(void) const { return r != -1 && g != -1 && b != -1; }
+
+  unsigned long pixel(void) const;
+
+  // operators
+  BColor &operator=(const BColor &c);
+  inline bool operator==(const BColor &c) const
+  { return (r == c.r && b == c.b && b == c.b); }
+  inline bool operator!=(const BColor &c) const
+  { return (! operator==(c)); }
+
+  static void cleanupColorCache(void);
+
+private:
+  void parseColorName(void);
+  void allocate(void);
+  void deallocate(void);
+
+  bool allocated;
+  int r, g, b;
+  unsigned long p;
+  const BaseDisplay *dpy;
+  unsigned int scrn;
+  std::string colorname;
+
+  // global color allocator/deallocator
+  struct RGB {
+    const BaseDisplay* const display;
+    const unsigned int screen;
+    const int r, g, b;
+
+    RGB(void) : display(0), screen(~(0u)), r(-1), g(-1), b(-1) { }
+    RGB(const BaseDisplay * const a, const unsigned int b,
+        const int x, const int y, const int z)
+      : display(a), screen(b), r(x), g(y), b(z) {}
+    RGB(const RGB &x)
+      : display(x.display), screen(x.screen), r(x.r), g(x.g), b(x.b) {}
+
+    inline bool operator==(const RGB &x) const {
+      return display == x.display &&
+              screen == x.screen &&
+                   r == x.r && g == x.g && b == x.b;
+    }
+
+    inline bool operator<(const RGB &x) const {
+      unsigned long p1, p2;
+      p1 = (screen << 24 | r << 16 | g << 8 | b) & 0x00ffffff;
+      p2 = (x.screen << 24 | x.r << 16 | x.g << 8 | x.b) & 0x00ffffff;
+      return p1 < p2;
+    }
+  };
+  struct PixelRef {
+    const unsigned long p;
+    unsigned int count;
+    inline PixelRef(void) : p(0), count(0) { }
+    inline PixelRef(const unsigned long x) : p(x), count(1) { }
+  };
+  typedef std::map<RGB,PixelRef> ColorCache;
+  typedef ColorCache::value_type ColorCacheItem;
+  static ColorCache colorcache;
+  static bool cleancache;
+  static void doCacheCleanup(void);
+};
+
+#endif // COLOR_HH
index 7a16576d0fcd875bffaca4a39e66434f1dd39204..3a314af575fdf5af8cf6928d6dc24182e0956b26 100644 (file)
@@ -1,6 +1,6 @@
-// Configmenu.cc for Openbox
-// Copyright (c) 2002 - 2002 Ben Jansens <ben@orodu.net>
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Configmenu.cc for Blackbox - An X11 Window Manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#  define _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 # include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "i18n.h"
-#include "Configmenu.h"
-#include "Toolbar.h"
-#include "Window.h"
-#include "Screen.h"
+#include "i18n.hh"
+#include "Configmenu.hh"
+#include "Image.hh"
+#include "Toolbar.hh"
+#include "Window.hh"
+#include "Screen.hh"
 
-Configmenu::Configmenu(BScreen &scr) : Basemenu(scr), screen(scr)
-{
-  setLabel(i18n(ConfigmenuSet, ConfigmenuConfigOptions,
-                "Config options"));
+Configmenu::Configmenu(BScreen *scr) : Basemenu(scr) {
+  setLabel(i18n(ConfigmenuSet, ConfigmenuConfigOptions, "Config options"));
   setInternalMenu();
 
   focusmenu = new Focusmenu(this);
@@ -60,28 +53,21 @@ Configmenu::Configmenu(BScreen &scr) : Basemenu(scr), screen(scr)
               "Focus New Windows"), 4);
   insert(i18n(ConfigmenuSet, ConfigmenuFocusLast,
               "Focus Last Window on Workspace"), 5);
-  insert(i18n(ConfigmenuSet, ConfigmenuHideToolbar,
-              "Hide toolbar"), 6);
   update();
 
-  setValues();
-}
-
-void Configmenu::setValues() {
-  setItemSelected(2, screen.imageDither());
-  setItemSelected(3, screen.opaqueMove());
-  setItemSelected(4, screen.fullMax());
-  setItemSelected(5, screen.focusNew());
-  setItemSelected(6, screen.focusLast());
-  setItemSelected(7, screen.hideToolbar());
+  setItemSelected(2, getScreen()->getImageControl()->doDither());
+  setItemSelected(3, getScreen()->doOpaqueMove());
+  setItemSelected(4, getScreen()->doFullMax());
+  setItemSelected(5, getScreen()->doFocusNew());
+  setItemSelected(6, getScreen()->doFocusLast());
 }
 
-Configmenu::~Configmenu() {
+Configmenu::~Configmenu(void) {
   delete focusmenu;
   delete placementmenu;
 }
 
-void Configmenu::itemSelected(int button, int index) {
+void Configmenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
@@ -92,87 +78,73 @@ void Configmenu::itemSelected(int button, int index) {
 
   switch(item->function()) {
   case 1: { // dither
-    screen.setImageDither(!screen.imageDither());
+    getScreen()->getImageControl()->
+      setDither((! getScreen()->getImageControl()->doDither()));
 
-    setItemSelected(index, screen.imageDither());
+    setItemSelected(index, getScreen()->getImageControl()->doDither());
 
     break;
   }
 
   case 2: { // opaque move
-    screen.setOpaqueMove(!screen.opaqueMove());
+    getScreen()->saveOpaqueMove((! getScreen()->doOpaqueMove()));
 
-    setItemSelected(index, screen.opaqueMove());
+    setItemSelected(index, getScreen()->doOpaqueMove());
 
     break;
   }
 
   case 3: { // full maximization
-    screen.setFullMax(!screen.fullMax());
+    getScreen()->saveFullMax((! getScreen()->doFullMax()));
 
-    setItemSelected(index, screen.fullMax());
+    setItemSelected(index, getScreen()->doFullMax());
 
     break;
   }
   case 4: { // focus new windows
-    screen.setFocusNew(!screen.focusNew());
+    getScreen()->saveFocusNew((! getScreen()->doFocusNew()));
 
-    setItemSelected(index, screen.focusNew());
+    setItemSelected(index, getScreen()->doFocusNew());
     break;
   }
 
   case 5: { // focus last window on workspace
-    screen.setFocusLast(!screen.focusLast());
-    setItemSelected(index, screen.focusLast());
-    break;
-  }
-  case 6:{ //toggle toolbar hide
-    screen.setHideToolbar(!screen.hideToolbar());
-    setItemSelected(index, screen.hideToolbar());
+    getScreen()->saveFocusLast((! getScreen()->doFocusLast()));
+    setItemSelected(index, getScreen()->doFocusLast());
     break;
   }
   } // switch
 }
 
-void Configmenu::reconfigure() {
-  setValues();
+
+void Configmenu::reconfigure(void) {
   focusmenu->reconfigure();
   placementmenu->reconfigure();
 
   Basemenu::reconfigure();
 }
 
-Configmenu::Focusmenu::Focusmenu(Configmenu *cm) : Basemenu(cm->screen) {
-  configmenu = cm;
 
-  setLabel(i18n(ConfigmenuSet, ConfigmenuFocusModel,
-                "Focus Model"));
+Configmenu::Focusmenu::Focusmenu(Configmenu *cm) : Basemenu(cm->getScreen()) {
+  setLabel(i18n(ConfigmenuSet, ConfigmenuFocusModel, "Focus Model"));
   setInternalMenu();
 
-  insert(i18n(ConfigmenuSet, ConfigmenuClickToFocus,
-              "Click To Focus"), 1);
-  insert(i18n(ConfigmenuSet, ConfigmenuSloppyFocus,
-              "Sloppy Focus"), 2);
-  insert(i18n(ConfigmenuSet, ConfigmenuAutoRaise,
-              "Auto Raise"), 3);
+  insert(i18n(ConfigmenuSet, ConfigmenuClickToFocus, "Click To Focus"), 1);
+  insert(i18n(ConfigmenuSet, ConfigmenuSloppyFocus, "Sloppy Focus"), 2);
+  insert(i18n(ConfigmenuSet, ConfigmenuAutoRaise, "Auto Raise"), 3);
+  insert(i18n(ConfigmenuSet, ConfigmenuClickRaise, "Click Raise"), 4);
   update();
 
-  setValues();
+  setItemSelected(0, (! getScreen()->isSloppyFocus()));
+  setItemSelected(1, getScreen()->isSloppyFocus());
+  setItemEnabled(2, getScreen()->isSloppyFocus());
+  setItemSelected(2, getScreen()->doAutoRaise());
+  setItemEnabled(3, getScreen()->isSloppyFocus());
+  setItemSelected(3, getScreen()->doClickRaise());
 }
 
-void Configmenu::Focusmenu::setValues() {
-  setItemSelected(0, !configmenu->screen.sloppyFocus());
-  setItemSelected(1, configmenu->screen.sloppyFocus());
-  setItemEnabled(2, configmenu->screen.sloppyFocus());
-  setItemSelected(2, configmenu->screen.autoRaise());
-}
 
-void Configmenu::Focusmenu::reconfigure() {
-  setValues();
-  Basemenu::reconfigure();
-}
-
-void Configmenu::Focusmenu::itemSelected(int button, int index) {
+void Configmenu::Focusmenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
@@ -183,101 +155,81 @@ void Configmenu::Focusmenu::itemSelected(int button, int index) {
 
   switch (item->function()) {
   case 1: // click to focus
-    configmenu->screen.setSloppyFocus(false);
-    configmenu->screen.setAutoRaise(false);
-    // make windows all grab button1 clicks
-    configmenu->screen.reconfigure();
+    getScreen()->toggleFocusModel(BScreen::ClickToFocus);
     break;
 
   case 2: // sloppy focus
-    configmenu->screen.setSloppyFocus(true);
-    // make windows stop grabbing button1 clicks
-    configmenu->screen.reconfigure();
+    getScreen()->toggleFocusModel(BScreen::SloppyFocus);
     break;
 
   case 3: // auto raise with sloppy focus
-    configmenu->screen.setAutoRaise(!configmenu->screen.autoRaise());
+    getScreen()->saveAutoRaise(! getScreen()->doAutoRaise());
+    break;
+
+  case 4: // click raise with sloppy focus
+    getScreen()->saveClickRaise(! getScreen()->doClickRaise());
+    getScreen()->updateFocusModel();
     break;
   }
 
-  setItemSelected(0, !configmenu->screen.sloppyFocus());
-  setItemSelected(1, configmenu->screen.sloppyFocus());
-  setItemEnabled(2, configmenu->screen.sloppyFocus());
-  setItemSelected(2, configmenu->screen.autoRaise());
+  setItemSelected(0, (! getScreen()->isSloppyFocus()));
+  setItemSelected(1, getScreen()->isSloppyFocus());
+  setItemEnabled(2, getScreen()->isSloppyFocus());
+  setItemSelected(2, getScreen()->doAutoRaise());
+  setItemEnabled(3, getScreen()->isSloppyFocus());
+  setItemSelected(3, getScreen()->doClickRaise());
 }
 
-Configmenu::Placementmenu::Placementmenu(Configmenu *cm) :
-Basemenu(cm->screen) {
-  configmenu = cm;
 
-  setLabel(i18n(ConfigmenuSet, ConfigmenuWindowPlacement,
-                "Window Placement"));
+Configmenu::Placementmenu::Placementmenu(Configmenu *cm):
+  Basemenu(cm->getScreen()) {
+  setLabel(i18n(ConfigmenuSet, ConfigmenuWindowPlacement, "Window Placement"));
   setInternalMenu();
 
-  insert(i18n(ConfigmenuSet, ConfigmenuSmartRows,
-              "Smart Placement (Rows)"),
+  insert(i18n(ConfigmenuSet, ConfigmenuSmartRows, "Smart Placement (Rows)"),
          BScreen::RowSmartPlacement);
-  insert(i18n(ConfigmenuSet, ConfigmenuSmartCols,
-              "Smart Placement (Columns)"),
+  insert(i18n(ConfigmenuSet, ConfigmenuSmartCols, "Smart Placement (Columns)"),
          BScreen::ColSmartPlacement);
-  insert(i18n(ConfigmenuSet, ConfigmenuCascade,
-              "Cascade Placement"), BScreen::CascadePlacement);
-  insert(i18n(ConfigmenuSet, ConfigmenuBestFit,
-              "Best Fit Placement"), BScreen::BestFitPlacement);
-  insert(i18n(ConfigmenuSet, ConfigmenuUnderMouse,
-              "Under Mouse Placement"),
-         BScreen::UnderMousePlacement);
-  insert(i18n(ConfigmenuSet, ConfigmenuClickMouse,
-              "Click Mouse Placement"),
-         BScreen::ClickMousePlacement);
-  insert(i18n(ConfigmenuSet, ConfigmenuLeftRight,
-              "Left to Right"), BScreen::LeftRight);
-  insert(i18n(ConfigmenuSet, ConfigmenuRightLeft,
-              "Right to Left"), BScreen::RightLeft);
-  insert(i18n(ConfigmenuSet, ConfigmenuTopBottom,
-              "Top to Bottom"), BScreen::TopBottom);
-  insert(i18n(ConfigmenuSet, ConfigmenuBottomTop,
-              "Bottom to Top"), BScreen::BottomTop);
+  insert(i18n(ConfigmenuSet, ConfigmenuCascade, "Cascade Placement"),
+         BScreen::CascadePlacement);
+  insert(i18n(ConfigmenuSet, ConfigmenuLeftRight, "Left to Right"),
+         BScreen::LeftRight);
+  insert(i18n(ConfigmenuSet, ConfigmenuRightLeft, "Right to Left"),
+         BScreen::RightLeft);
+  insert(i18n(ConfigmenuSet, ConfigmenuTopBottom, "Top to Bottom"),
+         BScreen::TopBottom);
+  insert(i18n(ConfigmenuSet, ConfigmenuBottomTop, "Bottom to Top"),
+         BScreen::BottomTop);
   update();
 
-  setValues();
-}
+  switch (getScreen()->getPlacementPolicy()) {
+  case BScreen::RowSmartPlacement:
+    setItemSelected(0, True);
+    break;
+
+  case BScreen::ColSmartPlacement:
+    setItemSelected(1, True);
+    break;
 
-void Configmenu::Placementmenu::setValues() {
-  const int p = configmenu->screen.placementPolicy();
-  setItemSelected(0, p == BScreen::RowSmartPlacement);
-  setItemSelected(1, p == BScreen::ColSmartPlacement);
-  setItemSelected(2, p == BScreen::CascadePlacement);
-  setItemSelected(3, p == BScreen::BestFitPlacement);
-  setItemSelected(4, p == BScreen::UnderMousePlacement);
-  setItemSelected(5, p == BScreen::ClickMousePlacement);
+  case BScreen::CascadePlacement:
+    setItemSelected(2, True);
+    break;
+  }
 
-  bool rl = (configmenu->screen.rowPlacementDirection() ==
+  bool rl = (getScreen()->getRowPlacementDirection() ==
              BScreen::LeftRight),
-  tb = (configmenu->screen.colPlacementDirection() ==
-        BScreen::TopBottom);
-
-  setItemSelected(6, rl);
-  setItemEnabled(6, (p != BScreen::UnderMousePlacement &&
-                     p != BScreen::ClickMousePlacement));
-  setItemSelected(7, !rl);
-  setItemEnabled(7, (p != BScreen::UnderMousePlacement &&
-                     p != BScreen::ClickMousePlacement));
-
-  setItemSelected(8, tb);
-  setItemEnabled(8, (p != BScreen::UnderMousePlacement &&
-                     p != BScreen::ClickMousePlacement));
-  setItemSelected(9, !tb);
-  setItemEnabled(9, (p != BScreen::UnderMousePlacement &&
-                     p != BScreen::ClickMousePlacement));
-}
+    tb = (getScreen()->getColPlacementDirection() ==
+          BScreen::TopBottom);
 
-void Configmenu::Placementmenu::reconfigure() {
-  setValues();
-  Basemenu::reconfigure();
+  setItemSelected(3, rl);
+  setItemSelected(4, ! rl);
+
+  setItemSelected(5, tb);
+  setItemSelected(6, ! tb);
 }
 
-void Configmenu::Placementmenu::itemSelected(int button, int index) {
+
+void Configmenu::Placementmenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
@@ -288,44 +240,62 @@ void Configmenu::Placementmenu::itemSelected(int button, int index) {
 
   switch (item->function()) {
   case BScreen::RowSmartPlacement:
-    configmenu->screen.setPlacementPolicy(item->function());
+    getScreen()->savePlacementPolicy(item->function());
+
+    setItemSelected(0, True);
+    setItemSelected(1, False);
+    setItemSelected(2, False);
+
     break;
 
   case BScreen::ColSmartPlacement:
-    configmenu->screen.setPlacementPolicy(item->function());
-    break;
+    getScreen()->savePlacementPolicy(item->function());
 
-  case BScreen::CascadePlacement:
-    configmenu->screen.setPlacementPolicy(item->function());
-    break;
+    setItemSelected(0, False);
+    setItemSelected(1, True);
+    setItemSelected(2, False);
 
-  case BScreen::BestFitPlacement:
-    configmenu->screen.setPlacementPolicy(item->function());
     break;
 
-  case BScreen::UnderMousePlacement:
-    configmenu->screen.setPlacementPolicy(item->function());
-    break;
+  case BScreen::CascadePlacement:
+    getScreen()->savePlacementPolicy(item->function());
+
+    setItemSelected(0, False);
+    setItemSelected(1, False);
+    setItemSelected(2, True);
 
-  case BScreen::ClickMousePlacement:
-    configmenu->screen.setPlacementPolicy(item->function());
     break;
 
   case BScreen::LeftRight:
-    configmenu->screen.setRowPlacementDirection(BScreen::LeftRight);
+    getScreen()->saveRowPlacementDirection(BScreen::LeftRight);
+
+    setItemSelected(3, True);
+    setItemSelected(4, False);
+
     break;
 
   case BScreen::RightLeft:
-    configmenu->screen.setRowPlacementDirection(BScreen::RightLeft);
+    getScreen()->saveRowPlacementDirection(BScreen::RightLeft);
+
+    setItemSelected(3, False);
+    setItemSelected(4, True);
+
     break;
 
   case BScreen::TopBottom:
-    configmenu->screen.setColPlacementDirection(BScreen::TopBottom);
+    getScreen()->saveColPlacementDirection(BScreen::TopBottom);
+
+    setItemSelected(5, True);
+    setItemSelected(6, False);
+
     break;
 
   case BScreen::BottomTop:
-    configmenu->screen.setColPlacementDirection(BScreen::BottomTop);
+    getScreen()->saveColPlacementDirection(BScreen::BottomTop);
+
+    setItemSelected(5, False);
+    setItemSelected(6, True);
+
     break;
   }
-  setValues();
 }
similarity index 63%
rename from src/Configmenu.h
rename to src/Configmenu.hh
index dd343b6aa4fd85f4287ffa1e1c532570094c6ea5..101b021b9a46e77ccfbd18f11f7f65179e880c69 100644 (file)
@@ -1,5 +1,6 @@
-// Configmenu.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Configmenu.hh for Blackbox - An X11 Window Manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 #ifndef   __Configmenu_hh
 #define   __Configmenu_hh
 
-#include "Basemenu.h"
+#include "Basemenu.hh"
 
 // forward declaration
-class Openbox;
+class Blackbox;
 class BScreen;
 class Configmenu;
 
@@ -34,51 +35,48 @@ class Configmenu : public Basemenu {
 private:
   class Focusmenu : public Basemenu {
   private:
-    Configmenu *configmenu;
+    Focusmenu(const Focusmenu&);
+    Focusmenu& operator=(const Focusmenu&);
 
   protected:
-    virtual void itemSelected(int, int);
-    virtual void setValues();
+    virtual void itemSelected(int button, unsigned int index);
 
   public:
-    Focusmenu(Configmenu *);
-    void reconfigure();
+    Focusmenu(Configmenu *cm);
   };
 
   class Placementmenu : public Basemenu {
   private:
-    Configmenu *configmenu;
+    Placementmenu(const Placementmenu&);
+    Placementmenu& operator=(const Placementmenu&);
 
   protected:
-    virtual void itemSelected(int, int);
-    virtual void setValues();
-
+    virtual void itemSelected(int button, unsigned int index);
 
   public:
-    Placementmenu(Configmenu *);
-    void reconfigure();
+    Placementmenu(Configmenu *cm);
   };
 
-  BScreen &screen;
   Focusmenu *focusmenu;
   Placementmenu *placementmenu;
 
   friend class Focusmenu;
   friend class Placementmenu;
 
-protected:
-  virtual void itemSelected(int, int);
-  virtual void setValues();
+  Configmenu(const Configmenu&);
+  Configmenu& operator=(const Configmenu&);
 
+protected:
+  virtual void itemSelected(int button, unsigned int index);
 
 public:
-  Configmenu(BScreen &);
-  virtual ~Configmenu();
+  Configmenu(BScreen *scr);
+  virtual ~Configmenu(void);
 
-  inline Basemenu *getFocusmenu() { return focusmenu; }
-  inline Basemenu *getPlacementmenu() { return placementmenu; }
+  inline Basemenu *getFocusmenu(void) { return focusmenu; }
+  inline Basemenu *getPlacementmenu(void) { return placementmenu; }
 
-  void reconfigure();
+  void reconfigure(void);
 };
 
 #endif // __Configmenu_hh
diff --git a/src/GCCache.cc b/src/GCCache.cc
new file mode 100644 (file)
index 0000000..941d67e
--- /dev/null
@@ -0,0 +1,197 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// GCCache.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
+// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifdef HAVE_CONFIG_H
+#  include "../config.h"
+#endif // HAVE_CONFIG_H
+
+extern "C" {
+#include <stdio.h>
+}
+
+#include "GCCache.hh"
+#include "BaseDisplay.hh"
+#include "Color.hh"
+#include "Util.hh"
+
+
+void BGCCacheContext::set(const BColor &_color,
+                          const XFontStruct * const _font,
+                          const int _function, const int _subwindow) {
+  XGCValues gcv;
+  pixel = gcv.foreground = _color.pixel();
+  function = gcv.function = _function;
+  subwindow = gcv.subwindow_mode = _subwindow;
+  unsigned long mask = GCForeground | GCFunction | GCSubwindowMode;
+
+  if (_font) {
+    fontid = gcv.font = _font->fid;
+    mask |= GCFont;
+  } else {
+    fontid = 0;
+  }
+
+  XChangeGC(display->getXDisplay(), gc, mask, &gcv);
+}
+
+
+void BGCCacheContext::set(const XFontStruct * const _font) {
+  if (! _font) {
+    fontid = 0;
+    return;
+  }
+
+  XGCValues gcv;
+  fontid = gcv.font = _font->fid;
+  XChangeGC(display->getXDisplay(), gc, GCFont, &gcv);
+}
+
+
+BGCCache::BGCCache(const BaseDisplay * const _display)
+  : display(_display),  context_count(128u),
+    cache_size(16u), cache_buckets(8u),
+    cache_total_size(cache_size * cache_buckets) {
+
+  contexts = new BGCCacheContext*[context_count];
+  unsigned int i;
+  for (i = 0; i < context_count; i++) {
+    contexts[i] = new BGCCacheContext(display);
+  }
+
+  cache = new BGCCacheItem*[cache_total_size];
+  for (i = 0; i < cache_total_size; ++i) {
+    cache[i] = new BGCCacheItem;
+  }
+}
+
+
+BGCCache::~BGCCache(void) {
+  std::for_each(contexts, contexts + context_count, PointerAssassin());
+  std::for_each(cache, cache + cache_total_size, PointerAssassin());
+  delete [] cache;
+  delete [] contexts;
+  cache = 0;
+  contexts = 0;
+}
+
+
+BGCCacheContext *BGCCache::nextContext(unsigned int scr) {
+  Window hd = display->getScreenInfo(scr)->getRootWindow();
+
+  BGCCacheContext *c;
+
+  for (unsigned int i = 0; i < context_count; ++i) {
+    c = contexts[i];
+
+    if (! c->gc) {
+      c->gc = XCreateGC(display->getXDisplay(), hd, 0, 0);
+      c->used = false;
+      c->screen = scr;
+    }
+    if (! c->used && c->screen == scr) {
+      c->used = true;
+      return c;
+    }
+  }
+
+  fprintf(stderr, "BGCCache: context fault!\n");
+  abort();
+}
+
+
+void BGCCache::release(BGCCacheContext *ctx) {
+  ctx->used = false;
+}
+
+
+BGCCacheItem *BGCCache::find(const BColor &_color,
+                             const XFontStruct * const _font,
+                             int _function, int _subwindow) {
+  const unsigned long pixel = _color.pixel();
+  const unsigned int screen = _color.screen();
+  const int key = _color.red() ^ _color.green() ^ _color.blue();
+  int k = (key % cache_size) * cache_buckets;
+  int i = 0; // loop variable
+  BGCCacheItem *c = cache[ k ], *prev = 0;
+
+  // this will either loop 8 times then return/abort or it will stop matching
+  while (c->ctx &&
+         (c->ctx->pixel != pixel || c->ctx->function != _function ||
+          c->ctx->subwindow != _subwindow || c->ctx->screen != screen)) {
+    if (i < 7) {
+      prev = c;
+      c = cache[ ++k ];
+      ++i;
+      continue;
+    }
+    if (c->count == 0 && c->ctx->screen == screen) {
+      // use this cache item
+      c->ctx->set(_color, _font, _function, _subwindow);
+      c->ctx->used = true;
+      c->count = 1;
+      c->hits = 1;
+      return c;
+    }
+    // cache fault!
+    fprintf(stderr, "BGCCache: cache fault\n");
+    abort();
+  }
+
+  const unsigned long fontid = _font ? _font->fid : 0;
+  if (c->ctx) {
+    // reuse existing context
+    if (fontid && fontid != c->ctx->fontid)
+      c->ctx->set(_font);
+    c->count++;
+    c->hits++;
+    if (prev && c->hits > prev->hits) {
+      cache[ k     ] = prev;
+      cache[ k - 1 ] = c;
+    }
+  } else {
+    c->ctx = nextContext(screen);
+    c->ctx->set(_color, _font, _function, _subwindow);
+    c->ctx->used = true;
+    c->count = 1;
+    c->hits = 1;
+  }
+
+  return c;
+}
+
+
+void BGCCache::release(BGCCacheItem *_item) {
+  _item->count--;
+}
+
+
+void BGCCache::purge(void) {
+  for (unsigned int i = 0; i < cache_total_size; ++i) {
+    BGCCacheItem *d = cache[ i ];
+
+    if (d->ctx && d->count == 0) {
+      release(d->ctx);
+      d->ctx = 0;
+    }
+  }
+}
diff --git a/src/GCCache.hh b/src/GCCache.hh
new file mode 100644 (file)
index 0000000..2e34139
--- /dev/null
@@ -0,0 +1,133 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// GCCache.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
+// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef GCCACHE_HH
+#define GCCACHE_HH
+
+extern "C" {
+#include <X11/Xlib.h>
+}
+
+#include "BaseDisplay.hh"
+#include "Color.hh"
+
+class BGCCacheItem;
+
+class BGCCacheContext {
+public:
+  void set(const BColor &_color, const XFontStruct * const _font,
+           const int _function, const int _subwindow);
+  void set(const XFontStruct * const _font);
+
+private:
+  BGCCacheContext(const BaseDisplay * const _display)
+    : display(_display), gc(0), pixel(0ul), fontid(0ul),
+      function(0), subwindow(0), used(false), screen(~(0u)) {}
+
+  const BaseDisplay *display;
+  GC gc;
+  unsigned long pixel;
+  unsigned long fontid;
+  int function;
+  int subwindow;
+  bool used;
+  unsigned int screen;
+
+  BGCCacheContext(const BGCCacheContext &_nocopy);
+  BGCCacheContext &operator=(const BGCCacheContext &_nocopy);
+
+  friend class BGCCache;
+  friend class BGCCacheItem;
+};
+
+class BGCCacheItem {
+public:
+  inline const GC &gc(void) const { return ctx->gc; }
+
+private:
+  BGCCacheItem(void) : ctx(0), count(0), hits(0), fault(false) { }
+
+  BGCCacheContext *ctx;
+  unsigned int count;
+  unsigned int hits;
+  bool fault;
+
+  BGCCacheItem(const BGCCacheItem &_nocopy);
+  BGCCacheItem &operator=(const BGCCacheItem &_nocopy);
+
+  friend class BGCCache;
+};
+
+class BGCCache {
+public:
+  explicit BGCCache(const BaseDisplay * const _display);
+  ~BGCCache(void);
+
+  // cleans up the cache
+  void purge(void);
+
+  BGCCacheItem *find(const BColor &_color, const XFontStruct * const _font = 0,
+                     int _function = GXcopy, int _subwindow = ClipByChildren);
+  void release(BGCCacheItem *_item);
+
+private:
+  BGCCacheContext *nextContext(unsigned int _screen);
+  void release(BGCCacheContext *ctx);
+
+  // this is closely modelled after the Qt GC cache, but with some of the
+  // complexity stripped out
+  const BaseDisplay *display;
+
+  const unsigned int context_count;
+  const unsigned int cache_size;
+  const unsigned int cache_buckets;
+  const unsigned int cache_total_size;
+  BGCCacheContext **contexts;
+  BGCCacheItem **cache;
+};
+
+class BPen {
+public:
+  inline BPen(const BColor &_color,  const XFontStruct * const _font = 0,
+              int _function = GXcopy, int _subwindow = ClipByChildren)
+    : color(_color), font(_font), function(_function), subwindow(_subwindow),
+      cache(_color.display()->gcCache()), item(0) { }
+  inline ~BPen(void) { if (item) cache->release(item); }
+
+  inline const GC &gc(void) const {
+    if (! item) item = cache->find(color, font, function, subwindow);
+    return item->gc();
+  }
+
+private:
+  const BColor &color;
+  const XFontStruct *font;
+  int function;
+  int subwindow;
+
+  mutable BGCCache *cache;
+  mutable BGCCacheItem *item;
+};
+
+
+#endif // GCCACHE_HH
diff --git a/src/Geometry.cc b/src/Geometry.cc
deleted file mode 100644 (file)
index cdc3947..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-// Geometry.cc for Openbox
-// Copyright (c) 2002 - 2002 ben Jansens (ben@orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#include "Geometry.h"
-
-Point::Point() : m_x(0), m_y(0) {
-}
-
-Point::Point(const Point &point) : m_x(point.m_x), m_y(point.m_y) {
-}
-
-Point::Point(const int x, const int y) : m_x(x), m_y(y) {
-}
-
-void Point::setX(const int x) {
-  m_x = x;
-}
-
-void Point::setY(const int y) {
-  m_y = y;
-}
-
-Size::Size() : m_w(0), m_h(0) {
-}
-
-Size::Size(const Size &size) : m_w(size.m_w), m_h(size.m_h) {
-}
-
-Size::Size(const unsigned int w, const unsigned int h) : m_w(w), m_h(h) {
-}
-
-void Size::setW(const unsigned int w) {
-  m_w = w;
-}
-
-void Size::setH(const unsigned int h) {
-  m_h = h;
-}
-
-Rect::Rect() : m_origin(0, 0), m_size(0, 0) {
-}
-
-Rect::Rect(const Point &origin, const Size &size) : m_origin(origin),
-  m_size(size) {
-}
-
-Rect::Rect(const int x, const int y, const unsigned int w, const unsigned int h)
-  : m_origin(x, y), m_size(w, h) {
-}
-
-void Rect::setSize(const Size &size) {
-  m_size = size;
-}
-
-void Rect::setSize(const unsigned int w, const unsigned int h) {
-  m_size.setW(w);
-  m_size.setH(h);
-}
-
-void Rect::setOrigin(const Point &origin) {
-  m_origin = origin;
-}
-
-void Rect::setOrigin(const int x, const int y) {
-  m_origin.setX(x);
-  m_origin.setY(y);
-}
-
-void Rect::setX(const int x) {
-  m_origin.setX(x);
-}
-
-void Rect::setY(const int y) {
-  m_origin.setY(y);
-}
-
-void Rect::setW(unsigned int w) {
-  m_size.setW(w);
-}
-
-void Rect::setH(unsigned int h) {
-  m_size.setH(h);
-}
-
-bool Rect::Intersect(const Rect &r) const {
-  return
-    (x() < (r.x()+(signed)r.w()) ) &&
-    ( (x()+(signed)w()) > r.x()) &&
-    (y() < (r.y()+(signed)r.h()) ) &&
-    ( (y()+(signed)h()) > r.y());
-}
-
-Rect Rect::Inflate(const unsigned int i) const {
-  return Rect(x(), y(), w()+i, h()+i);
-}
-
-Rect Rect::Inflate(const unsigned int iw, const unsigned int ih) const {
-  return Rect(x(), y(), w()+iw, h()+ih);
-}
-
-Rect Rect::Inflate(const Size &i) const {
-  return Rect(x(), y(), w()+i.w(), h()+i.h());
-}
-
-Rect Rect::Deflate(const unsigned int d) const {
-  return Rect(x(), y(), w()-d, h()-d);
-}
-
-Rect Rect::Deflate(const unsigned int dw, const unsigned int dh) const {
-  return Rect(x(), y(), w()-dw, h()-dh);
-}
-
-Rect Rect::Deflate(const Size &d) const {
-  return Rect(x(), y(), w()-d.w(), h()-d.h());
-}
-
-Rect Rect::Translate(const int t) const {
-  return Rect(x()+t, y()+t, w(), h());
-}
-
-Rect Rect::Translate(const int tx, const int ty) const {
-  return Rect(x()+tx, y()+ty, w(), h());
-}
-
-Rect Rect::Translate(const Point &t) const {
-  return Rect(x()+t.x(), y()+t.y(), w(), h());
-}
diff --git a/src/Geometry.h b/src/Geometry.h
deleted file mode 100644 (file)
index 0ca914b..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-// Geometry.h for Openbox
-// Copyright (c) 2002 - 2002 ben Jansens (ben@orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __geometry_h
-#define   __geometry_h
-
-class Point{
-  int m_x, m_y;
-public:
-  Point();
-  Point(const Point &point);
-  Point(const int x, const int y);
-
-  void setX(const int x);
-  inline int x() const {
-    return m_x;
-  }
-
-  void setY(const int y);
-  inline int y() const {
-    return m_y;
-  }
-};
-
-class Size{
-  unsigned int m_w, m_h;
-public:
-  Size();
-  Size(const Size &size);
-  Size(const unsigned int w, const unsigned int h);
-
-  void setW(const unsigned int w);
-  inline unsigned int w() const {
-    return m_w;
-  }
-
-  void setH(const unsigned int h);
-  inline unsigned int h() const {
-    return m_h;
-  }
-};
-
-class Rect{
-  Point m_origin;
-  Size m_size;
-public:
-  Rect();
-  Rect(const Point &origin, const Size &size);
-  Rect(const int x, const int y, const unsigned int w, const unsigned int h);
-  
-  void setSize(const Size &size);
-  void setSize(const unsigned int w, const unsigned int h);
-  inline const Size &size() const {
-    return const_cast<const Size &>(m_size);
-  }
-  
-  void setOrigin(const Point &origin);
-  void setOrigin(const int x, const int y);
-  inline const Point &origin() const {
-    return const_cast<const Point &>(m_origin);
-  }
-  
-  void setX(const int x);
-  inline int x() const {
-    return m_origin.x();
-  }
-
-  void setY(const int y);
-  inline int y() const {
-    return m_origin.y();
-  }
-
-  void setW(const unsigned int w);
-  inline unsigned int w() const {
-    return m_size.w();
-  }
-
-  void setH(const unsigned int h);
-  inline unsigned int h() const {
-    return m_size.h();
-  }
-
-  bool Intersect(const Rect &r) const;
-  // returns a rect that is this rect increased in size by the passed in amount
-  Rect Inflate(const unsigned int i) const;
-  Rect Inflate(const unsigned int iw, const unsigned int ih) const;
-  Rect Inflate(const Size &i) const;
-  // returns a rect that is this rect decreased in size by the passed in amount
-  Rect Deflate(const unsigned int d) const;
-  Rect Deflate(const unsigned int dw, const unsigned int dh) const;
-  Rect Deflate(const Size &d) const;
-  // returns a rect that is moved the amount specified
-  Rect Translate(const int t) const;
-  Rect Translate(const int tx, const int ty) const;
-  Rect Translate(const Point &t) const;
-};  
-
-#endif // __geometry_h
index 984cdfa919acc38877cf9599a1f423fd2c759586..dba587a2bdebffc11d7969ecc6d4bed158edafb7 100644 (file)
@@ -1,5 +1,6 @@
-// Iconmenu.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Icon.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "i18n.h"
-#include "Iconmenu.h"
-#include "Screen.h"
-#include "Window.h"
+#include "i18n.hh"
+#include "Iconmenu.hh"
+#include "Screen.hh"
+#include "Window.hh"
 
 
-Iconmenu::Iconmenu(BScreen &scrn) : Basemenu(scrn), screen(scrn) {
+Iconmenu::Iconmenu(BScreen *scrn) : Basemenu(scrn) {
   setInternalMenu();
 
   setLabel(i18n(IconSet, IconIcons, "Icons"));
@@ -44,12 +39,12 @@ Iconmenu::Iconmenu(BScreen &scrn) : Basemenu(scrn), screen(scrn) {
 }
 
 
-void Iconmenu::itemSelected(int button, int index) {
+void Iconmenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
-  if (index >= 0 && index < screen.getIconCount()) {
-    OpenboxWindow *win = screen.getIcon(index);
+  if (index < getScreen()->getIconCount()) {
+    BlackboxWindow *win = getScreen()->getIcon(index);
 
     if (win) {
       win->deiconify();
@@ -57,6 +52,6 @@ void Iconmenu::itemSelected(int button, int index) {
     }
   }
 
-  if (! (screen.getWorkspacemenu()->isTorn() || isTorn()))
+  if (! (getScreen()->getWorkspacemenu()->isTorn() || isTorn()))
     hide();
 }
diff --git a/src/Iconmenu.h b/src/Iconmenu.h
deleted file mode 100644 (file)
index 609f03a..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// Iconmenu.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Icon_hh
-#define   __Icon_hh
-
-#include "Basemenu.h"
-
-// forward declaration
-class Iconmenu;
-class BScreen;
-
-class Iconmenu : public Basemenu {
-private:
-  BScreen &screen;
-
-protected:
-  virtual void itemSelected(int, int);
-
-public:
-  Iconmenu(BScreen &);
-};
-
-
-#endif // __Icon_hh
index 0172f53f21a4c9161b9a2de63b748a553587a443..c20c4f7c981af1c4a1507c57d027edbabafafc5c 100644 (file)
@@ -1,5 +1,6 @@
-// Image.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Image.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "i18n.h"
-#include "BaseDisplay.h"
-#include "Image.h"
-
-#ifdef    HAVE_SYS_TYPES_H
-#  include <sys/types.h>
-#endif // HAVE_SYS_TYPES_H
-
-#ifndef u_int32_t
-#  ifdef uint_32_t
-typedef uint32_t u_int32_t;
-#  else
-#    ifdef __uint32_t
-typedef __uint32_t u_int32_t;
-#    else
-typedef unsigned int u_int32_t;
-#    endif
-#  endif
-#endif
-
-#ifdef    HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif // HAVE_STDLIB_H
-
-#ifdef    HAVE_STRING_H
-#  include <string.h>
-#endif // HAVE_STRING_H
-
 #ifdef    HAVE_STDIO_H
 #  include <stdio.h>
 #endif // HAVE_STDIO_H
 
-#ifdef    HAVE_CTYPE_H
-#  include <ctype.h>
-#endif // HAVE_CTYPE_H
-
 #include <algorithm>
-using std::min;
 using std::max;
+using std::min;
 
-static unsigned long bsqrt(unsigned long x) {
-  if (x <= 0) return 0;
-  if (x == 1) return 1;
+#include "blackbox.hh"
+#include "i18n.hh"
+#include "BaseDisplay.hh"
+#include "GCCache.hh"
+#include "Image.hh"
+#include "Texture.hh"
 
-  unsigned long r = x >> 1;
-  unsigned long q;
 
-  while (1) {
-    q = x / r;
-    if (q >= r) return r;
-    r = (r + q) >> 1;
-  }
-}
+BImage::BImage(BImageControl *c, unsigned int w, unsigned int h) {
+  control = c;
 
-
-BImage::BImage(BImageControl &c, unsigned int w, unsigned int h) : control(c) {
   width = ((signed) w > 0) ? w : 1;
   height = ((signed) h > 0) ? h : 1;
 
@@ -95,15 +53,15 @@ BImage::BImage(BImageControl &c, unsigned int w, unsigned int h) : control(c) {
 
   xtable = ytable = (unsigned int *) 0;
 
-  cpc = control.getColorsPerChannel();
+  cpc = control->getColorsPerChannel();
   cpccpc = cpc * cpc;
 
-  control.getColorTables(&red_table, &green_table, &blue_table,
-                         &red_offset, &green_offset, &blue_offset,
-                         &red_bits, &green_bits, &blue_bits);
+  control->getColorTables(&red_table, &green_table, &blue_table,
+                          &red_offset, &green_offset, &blue_offset,
+                          &red_bits, &green_bits, &blue_bits);
 
-  if (control.getVisual()->c_class != TrueColor)
-    control.getXColorTable(&colors, &ncolors);
+  if (control->getVisual()->c_class != TrueColor)
+    control->getXColorTable(&colors, &ncolors);
 }
 
 
@@ -114,149 +72,122 @@ BImage::~BImage(void) {
 }
 
 
-Pixmap BImage::render(BTexture *texture) {
-  if (texture->getTexture() & BImage_ParentRelative)
+Pixmap BImage::render(const BTexture &texture) {
+  if ((texture.texture() & BTexture::Parent_Relative))
     return ParentRelative;
-  else if (texture->getTexture() & BImage_Solid)
+  else if ((texture.texture() & BTexture::Solid))
     return render_solid(texture);
-  else if (texture->getTexture() & BImage_Gradient)
+  else if ((texture.texture() & BTexture::Gradient))
     return render_gradient(texture);
-
   return None;
 }
 
 
-Pixmap BImage::render_solid(BTexture *texture) {
-  Pixmap pixmap = XCreatePixmap(control.getBaseDisplay().getXDisplay(),
-                                control.getDrawable(), width,
-                                height, control.getDepth());
+Pixmap BImage::render_solid(const BTexture &texture) {
+  Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
+                               control->getDrawable(), width,
+                               height, control->getDepth());
   if (pixmap == None) {
     fprintf(stderr, i18n(ImageSet, ImageErrorCreatingSolidPixmap,
                          "BImage::render_solid: error creating pixmap\n"));
     return None;
   }
 
-  XGCValues gcv;
-  GC gc, hgc, lgc;
-
-  gcv.foreground = texture->getColor()->getPixel();
-  gcv.fill_style = FillSolid;
-  gc = XCreateGC(control.getBaseDisplay().getXDisplay(), pixmap,
-                 GCForeground | GCFillStyle, &gcv);
-
-  gcv.foreground = texture->getHiColor()->getPixel();
-  hgc = XCreateGC(control.getBaseDisplay().getXDisplay(), pixmap,
-                  GCForeground, &gcv);
-
-  gcv.foreground = texture->getLoColor()->getPixel();
-  lgc = XCreateGC(control.getBaseDisplay().getXDisplay(), pixmap,
-                  GCForeground, &gcv);
+  Display *display = control->getBaseDisplay()->getXDisplay();
 
-  XFillRectangle(control.getBaseDisplay().getXDisplay(), pixmap, gc, 0, 0,
-                 width, height);
+  BPen pen(texture.color());
+  BPen penlight(texture.lightColor());
+  BPen penshadow(texture.shadowColor());
 
-#ifdef    INTERLACE
-  if (texture->getTexture() & BImage_Interlaced) {
-    gcv.foreground = texture->getColorTo()->getPixel();
-    GC igc = XCreateGC(control.getBaseDisplay().getXDisplay(), pixmap,
-                       GCForeground, &gcv);
+  XFillRectangle(display, pixmap, pen.gc(), 0, 0, width, height);
 
+  if (texture.texture() & BTexture::Interlaced) {
+    BPen peninterlace(texture.colorTo());
     register unsigned int i = 0;
     for (; i < height; i += 2)
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, igc,
-                0, i, width, i);
-
-    XFreeGC(control.getBaseDisplay().getXDisplay(), igc);
+      XDrawLine(display, pixmap, peninterlace.gc(), 0, i, width, i);
   }
-#endif // INTERLACE
-
 
-  if (texture->getTexture() & BImage_Bevel1) {
-    if (texture->getTexture() & BImage_Raised) {
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc,
+  if (texture.texture() & BTexture::Bevel1) {
+    if (texture.texture() & BTexture::Raised) {
+      XDrawLine(display, pixmap, penshadow.gc(),
                 0, height - 1, width - 1, height - 1);
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc,
+      XDrawLine(display, pixmap, penshadow.gc(),
                 width - 1, height - 1, width - 1, 0);
 
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc,
+      XDrawLine(display, pixmap, penlight.gc(),
                 0, 0, width - 1, 0);
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc,
+      XDrawLine(display, pixmap, penlight.gc(),
                 0, height - 1, 0, 0);
-    } else if (texture->getTexture() & BImage_Sunken) {
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc,
+    } else if (texture.texture() & BTexture::Sunken) {
+      XDrawLine(display, pixmap, penlight.gc(),
                 0, height - 1, width - 1, height - 1);
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc,
+      XDrawLine(display, pixmap, penlight.gc(),
                 width - 1, height - 1, width - 1, 0);
 
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc,
+      XDrawLine(display, pixmap, penshadow.gc(),
                 0, 0, width - 1, 0);
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc,
+      XDrawLine(display, pixmap, penshadow.gc(),
                 0, height - 1, 0, 0);
     }
-  } else if (texture->getTexture() & BImage_Bevel2) {
-    if (texture->getTexture() & BImage_Raised) {
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc,
+  } else if (texture.texture() & BTexture::Bevel2) {
+    if (texture.texture() & BTexture::Raised) {
+      XDrawLine(display, pixmap, penshadow.gc(),
                 1, height - 3, width - 3, height - 3);
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc,
+      XDrawLine(display, pixmap, penshadow.gc(),
                 width - 3, height - 3, width - 3, 1);
 
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc,
+      XDrawLine(display, pixmap, penlight.gc(),
                 1, 1, width - 3, 1);
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc,
+      XDrawLine(display, pixmap, penlight.gc(),
                 1, height - 3, 1, 1);
-    } else if (texture->getTexture() & BImage_Sunken) {
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc,
+    } else if (texture.texture() & BTexture::Sunken) {
+      XDrawLine(display, pixmap, penlight.gc(),
                 1, height - 3, width - 3, height - 3);
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc,
+      XDrawLine(display, pixmap, penlight.gc(),
                 width - 3, height - 3, width - 3, 1);
 
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc,
+      XDrawLine(display, pixmap, penshadow.gc(),
                 1, 1, width - 3, 1);
-      XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc,
+      XDrawLine(display, pixmap, penshadow.gc(),
                 1, height - 3, 1, 1);
     }
   }
 
-  XFreeGC(control.getBaseDisplay().getXDisplay(), gc);
-  XFreeGC(control.getBaseDisplay().getXDisplay(), hgc);
-  XFreeGC(control.getBaseDisplay().getXDisplay(), lgc);
-
   return pixmap;
 }
 
 
-Pixmap BImage::render_gradient(BTexture *texture) {
 int inverted = 0;
+Pixmap BImage::render_gradient(const BTexture &texture) {
+ int inverted = 0;
 
-#ifdef    INTERLACE
-  interlaced = texture->getTexture() & BImage_Interlaced;
-#endif // INTERLACE
+  interlaced = texture.texture() & BTexture::Interlaced;
 
-  if (texture->getTexture() & BImage_Sunken) {
-    from = texture->getColorTo();
-    to = texture->getColor();
+  if (texture.texture() & BTexture::Sunken) {
+    from = texture.colorTo();
+    to = texture.color();
 
-    if (! (texture->getTexture() & BImage_Invert)) inverted = 1;
+    if (! (texture.texture() & BTexture::Invert)) inverted = 1;
   } else {
-    from = texture->getColor();
-    to = texture->getColorTo();
+    from = texture.color();
+    to = texture.colorTo();
 
-    if (texture->getTexture() & BImage_Invert) inverted = 1;
+    if (texture.texture() & BTexture::Invert) inverted = 1;
   }
 
-  control.getGradientBuffers(width, height, &xtable, &ytable);
+  control->getGradientBuffers(width, height, &xtable, &ytable);
 
-  if (texture->getTexture() & BImage_Diagonal) dgradient();
-  else if (texture->getTexture() & BImage_Elliptic) egradient();
-  else if (texture->getTexture() & BImage_Horizontal) hgradient();
-  else if (texture->getTexture() & BImage_Pyramid) pgradient();
-  else if (texture->getTexture() & BImage_Rectangle) rgradient();
-  else if (texture->getTexture() & BImage_Vertical) vgradient();
-  else if (texture->getTexture() & BImage_CrossDiagonal) cdgradient();
-  else if (texture->getTexture() & BImage_PipeCross) pcgradient();
+  if (texture.texture() & BTexture::Diagonal) dgradient();
+  else if (texture.texture() & BTexture::Elliptic) egradient();
+  else if (texture.texture() & BTexture::Horizontal) hgradient();
+  else if (texture.texture() & BTexture::Pyramid) pgradient();
+  else if (texture.texture() & BTexture::Rectangle) rgradient();
+  else if (texture.texture() & BTexture::Vertical) vgradient();
+  else if (texture.texture() & BTexture::CrossDiagonal) cdgradient();
+  else if (texture.texture() & BTexture::PipeCross) pcgradient();
 
-  if (texture->getTexture() & BImage_Bevel1) bevel1();
-  else if (texture->getTexture() & BImage_Bevel2) bevel2();
+  if (texture.texture() & BTexture::Bevel1) bevel1();
+  else if (texture.texture() & BTexture::Bevel2) bevel2();
 
   if (inverted) invert();
 
@@ -267,10 +198,253 @@ Pixmap BImage::render_gradient(BTexture *texture) {
 }
 
 
+static const unsigned char dither4[4][4] = {
+  {0, 4, 1, 5},
+  {6, 2, 7, 3},
+  {1, 5, 0, 4},
+  {7, 3, 6, 2}
+};
+
+
+/*
+ * Helper function for TrueColorDither and renderXImage
+ *
+ * This handles the proper setting of the image data based on the image depth
+ * and the machine's byte ordering
+ */
+static inline
+void assignPixelData(unsigned int bit_depth, unsigned char **data,
+                    unsigned long pixel) {
+  unsigned char *pixel_data = *data;
+  switch (bit_depth) {
+  case  8: //  8bpp
+    *pixel_data++ = pixel;
+    break;
+
+  case 16: // 16bpp LSB
+    *pixel_data++ = pixel;
+    *pixel_data++ = pixel >> 8;
+    break;
+
+  case 17: // 16bpp MSB
+    *pixel_data++ = pixel >> 8;
+    *pixel_data++ = pixel;
+    break;
+
+  case 24: // 24bpp LSB
+    *pixel_data++ = pixel;
+    *pixel_data++ = pixel >> 8;
+    *pixel_data++ = pixel >> 16;
+    break;
+
+  case 25: // 24bpp MSB
+    *pixel_data++ = pixel >> 16;
+    *pixel_data++ = pixel >> 8;
+    *pixel_data++ = pixel;
+    break;
+
+  case 32: // 32bpp LSB
+    *pixel_data++ = pixel;
+    *pixel_data++ = pixel >> 8;
+    *pixel_data++ = pixel >> 16;
+    *pixel_data++ = pixel >> 24;
+    break;
+
+  case 33: // 32bpp MSB
+    *pixel_data++ = pixel >> 24;
+    *pixel_data++ = pixel >> 16;
+    *pixel_data++ = pixel >> 8;
+    *pixel_data++ = pixel;
+    break;
+  }
+  *data = pixel_data; // assign back so we don't lose our place
+}
+
+
+// algorithm: ordered dithering... many many thanks to rasterman
+// (raster@rasterman.com) for telling me about this... portions of this
+// code is based off of his code in Imlib
+void BImage::TrueColorDither(unsigned int bit_depth, int bytes_per_line,
+                            unsigned char *pixel_data) {
+  unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
+  unsigned char *ppixel_data = pixel_data;
+  unsigned long pixel;
+
+  for (y = 0, offset = 0; y < height; y++) {
+    dithy = y & 0x3;
+
+    for (x = 0; x < width; x++, offset++) {
+      dithx = x & 0x3;
+      r = red[offset];
+      g = green[offset];
+      b = blue[offset];
+
+      er = r & (red_bits - 1);
+      eg = g & (green_bits - 1);
+      eb = b & (blue_bits - 1);
+
+      r = red_table[r];
+      g = green_table[g];
+      b = blue_table[b];
+
+      if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
+      if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
+      if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
+
+      pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
+      assignPixelData(bit_depth, &pixel_data, pixel);
+    }
+
+    pixel_data = (ppixel_data += bytes_per_line);
+  }
+}
+
+#ifdef ORDEREDPSEUDO
+const static unsigned char dither8[8][8] = {
+  { 0,  32, 8,  40, 2,  34, 10, 42},
+  { 48, 16, 56, 24, 50, 18, 58, 26},
+  { 12, 44, 4,  36, 14, 46, 6,  38},
+  { 60, 28, 52, 20, 62, 30, 54, 22},
+  { 3,  35, 11, 43, 1,  33, 9,  41},
+  { 51, 19, 59, 27, 49, 17, 57, 25},
+  { 15, 47, 7,  39, 13, 45, 5,  37},
+  { 63, 31, 55, 23, 61, 29, 53, 21}
+};
+
+void BImage::OrderedPseudoColorDither(int bytes_per_line,
+                                     unsigned char *pixel_data) {
+  unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
+  unsigned long pixel;
+  unsigned char *ppixel_data = pixel_data;
+
+  for (y = 0, offset = 0; y < height; y++) {
+    dithy = y & 7;
+
+    for (x = 0; x < width; x++, offset++) {
+      dithx = x & 7;
+
+      r = red[offset];
+      g = green[offset];
+      b = blue[offset];
+
+      er = r & (red_bits - 1);
+      eg = g & (green_bits - 1);
+      eb = b & (blue_bits - 1);
+
+      r = red_table[r];
+      g = green_table[g];
+      b = blue_table[b];
+
+      if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
+      if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
+      if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
+
+      pixel = (r * cpccpc) + (g * cpc) + b;
+      *(pixel_data++) = colors[pixel].pixel;
+    }
+
+    pixel_data = (ppixel_data += bytes_per_line);
+  }
+}
+#endif
+
+void BImage::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) {
+  short *terr,
+    *rerr = new short[width + 2],
+    *gerr = new short[width + 2],
+    *berr = new short[width + 2],
+    *nrerr = new short[width + 2],
+    *ngerr = new short[width + 2],
+    *nberr = new short[width + 2];
+
+  int rr, gg, bb, rer, ger, ber;
+  int dd = 255 / control->getColorsPerChannel();
+  unsigned int x, y, r, g, b, offset;
+  unsigned long pixel;
+  unsigned char *ppixel_data = pixel_data;
+
+  for (x = 0; x < width; x++) {
+    *(rerr + x) = *(red + x);
+    *(gerr + x) = *(green + x);
+    *(berr + x) = *(blue + x);
+  }
+
+  *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
+
+  for (y = 0, offset = 0; y < height; y++) {
+    if (y < (height - 1)) {
+      int i = offset + width;
+      for (x = 0; x < width; x++, i++) {
+       *(nrerr + x) = *(red + i);
+       *(ngerr + x) = *(green + i);
+       *(nberr + x) = *(blue + i);
+      }
+
+      *(nrerr + x) = *(red + (--i));
+      *(ngerr + x) = *(green + i);
+      *(nberr + x) = *(blue + i);
+    }
+
+    for (x = 0; x < width; x++) {
+      rr = rerr[x];
+      gg = gerr[x];
+      bb = berr[x];
+
+      if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
+      if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
+      if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
+
+      r = red_table[rr];
+      g = green_table[gg];
+      b = blue_table[bb];
+
+      rer = rerr[x] - r*dd;
+      ger = gerr[x] - g*dd;
+      ber = berr[x] - b*dd;
+
+      pixel = (r * cpccpc) + (g * cpc) + b;
+      *pixel_data++ = colors[pixel].pixel;
+
+      r = rer >> 1;
+      g = ger >> 1;
+      b = ber >> 1;
+      rerr[x+1] += r;
+      gerr[x+1] += g;
+      berr[x+1] += b;
+      nrerr[x] += r;
+      ngerr[x] += g;
+      nberr[x] += b;
+    }
+
+    offset += width;
+
+    pixel_data = (ppixel_data += bytes_per_line);
+
+    terr = rerr;
+    rerr = nrerr;
+    nrerr = terr;
+
+    terr = gerr;
+    gerr = ngerr;
+    ngerr = terr;
+
+    terr = berr;
+    berr = nberr;
+    nberr = terr;
+  }
+
+  delete [] rerr;
+  delete [] gerr;
+  delete [] berr;
+  delete [] nrerr;
+  delete [] ngerr;
+  delete [] nberr;
+}
+
 XImage *BImage::renderXImage(void) {
   XImage *image =
-    XCreateImage(control.getBaseDisplay().getXDisplay(),
-                 control.getVisual(), control.getDepth(), ZPixmap, 0, 0,
+    XCreateImage(control->getBaseDisplay()->getXDisplay(),
+                 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
                  width, height, 32, 0);
 
   if (! image) {
@@ -283,347 +457,108 @@ XImage *BImage::renderXImage(void) {
   image->data = (char *) 0;
 
   unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
-  register unsigned int x, y, dithx, dithy, r, g, b, o, er, eg, eb, offset;
 
-  unsigned char *pixel_data = d, *ppixel_data = d;
-  unsigned long pixel;
+  unsigned int o = image->bits_per_pixel +
+    ((image->byte_order == MSBFirst) ? 1 : 0);
+
+  if (control->doDither() && width > 1 && height > 1) {
+    switch (control->getVisual()->c_class) {
+    case TrueColor:
+      TrueColorDither(o, image->bytes_per_line, d);
+      break;
 
-  o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0);
-
-  if (control.doDither() && width > 1 && height > 1) {
-    unsigned char dither4[4][4] = { {0, 4, 1, 5},
-      {6, 2, 7, 3},
-      {1, 5, 0, 4},
-      {7, 3, 6, 2} };
-
-#ifdef    ORDEREDPSEUDO
-      unsigned char dither8[8][8] = { { 0,  32, 8,  40, 2,  34, 10, 42 },
-        { 48, 16, 56, 24, 50, 18, 58, 26 },
-        { 12, 44, 4,  36, 14, 46, 6,  38 },
-        { 60, 28, 52, 20, 62, 30, 54, 22 },
-        { 3,  35, 11, 43, 1,  33, 9,  41 },
-        { 51, 19, 59, 27, 49, 17, 57, 25 },
-        { 15, 47, 7,  39, 13, 45, 5,  37 },
-        { 63, 31, 55, 23, 61, 29, 53, 21 } };
-#endif // ORDEREDPSEUDO
-
-        switch (control.getVisual()->c_class) {
-        case TrueColor:
-          // algorithm: ordered dithering... many many thanks to rasterman
-          // (raster@rasterman.com) for telling me about this... portions of this
-          // code is based off of his code in Imlib
-          for (y = 0, offset = 0; y < height; y++) {
-            dithy = y & 0x3;
-
-            for (x = 0; x < width; x++, offset++) {
-              dithx = x & 0x3;
-              r = red[offset];
-              g = green[offset];
-              b = blue[offset];
-
-              er = r & (red_bits - 1);
-              eg = g & (green_bits - 1);
-              eb = b & (blue_bits - 1);
-
-              r = red_table[r];
-              g = green_table[g];
-              b = blue_table[b];
-
-              if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
-              if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
-              if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
-
-              pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
-
-              switch (o) {
-              case  8: //  8bpp
-                *pixel_data++ = pixel;
-                break;
-
-              case 16: // 16bpp LSB
-                *pixel_data++ = pixel;
-                *pixel_data++ = pixel >> 8;
-                break;
-
-              case 17: // 16bpp MSB
-                *pixel_data++ = pixel >> 8;
-                *pixel_data++ = pixel;
-                break;
-
-              case 24: // 24bpp LSB
-                *pixel_data++ = pixel;
-                *pixel_data++ = pixel >> 8;
-                *pixel_data++ = pixel >> 16;
-                break;
-
-              case 25: // 24bpp MSB
-                *pixel_data++ = pixel >> 16;
-                *pixel_data++ = pixel >> 8;
-                *pixel_data++ = pixel;
-                break;
-
-              case 32: // 32bpp LSB
-                *pixel_data++ = pixel;
-                *pixel_data++ = pixel >> 8;
-                *pixel_data++ = pixel >> 16;
-                *pixel_data++ = pixel >> 24;
-                break;
-
-              case 33: // 32bpp MSB
-                *pixel_data++ = pixel >> 24;
-                *pixel_data++ = pixel >> 16;
-                *pixel_data++ = pixel >> 8;
-                *pixel_data++ = pixel;
-                break;
-              }
-            }
-
-            pixel_data = (ppixel_data += image->bytes_per_line);
-          }
-
-          break;
-
-        case StaticColor:
-        case PseudoColor: {
-#ifndef   ORDEREDPSEUDO
-          short *terr,
-          *rerr = new short[width + 2],
-          *gerr = new short[width + 2],
-          *berr = new short[width + 2],
-          *nrerr = new short[width + 2],
-          *ngerr = new short[width + 2],
-          *nberr = new short[width + 2];
-          int rr, gg, bb, rer, ger, ber;
-          int dd = 255 / control.getColorsPerChannel();
-
-          for (x = 0; x < width; x++) {
-            *(rerr + x) = *(red + x);
-            *(gerr + x) = *(green + x);
-            *(berr + x) = *(blue + x);
-          }
-
-          *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
-#endif // ORDEREDPSEUDO
-
-          for (y = 0, offset = 0; y < height; y++) {
-#ifdef    ORDEREDPSEUDO
-            dithy = y & 7;
-
-            for (x = 0; x < width; x++, offset++) {
-              dithx = x & 7;
-
-              r = red[offset];
-              g = green[offset];
-              b = blue[offset];
-
-              er = r & (red_bits - 1);
-              eg = g & (green_bits - 1);
-              eb = b & (blue_bits - 1);
-
-              r = red_table[r];
-              g = green_table[g];
-              b = blue_table[b];
-
-              if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
-              if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
-              if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
-
-              pixel = (r * cpccpc) + (g * cpc) + b;
-              *(pixel_data++) = colors[pixel].pixel;
-            }
-
-            pixel_data = (ppixel_data += image->bytes_per_line);
-          }
-#else // !ORDEREDPSEUDO
-          if (y < (height - 1)) {
-            int i = offset + width;
-            for (x = 0; x < width; x++, i++) {
-              *(nrerr + x) = *(red + i);
-              *(ngerr + x) = *(green + i);
-              *(nberr + x) = *(blue + i);
-            }
-
-            *(nrerr + x) = *(red + (--i));
-            *(ngerr + x) = *(green + i);
-            *(nberr + x) = *(blue + i);
-          }
-
-          for (x = 0; x < width; x++) {
-            rr = rerr[x];
-            gg = gerr[x];
-            bb = berr[x];
-
-            if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
-            if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
-            if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
-
-            r = red_table[rr];
-            g = green_table[gg];
-            b = blue_table[bb];
-
-            rer = rerr[x] - r*dd;
-            ger = gerr[x] - g*dd;
-            ber = berr[x] - b*dd;
-
-            pixel = (r * cpccpc) + (g * cpc) + b;
-            *pixel_data++ = colors[pixel].pixel;
-
-            r = rer >> 1;
-            g = ger >> 1;
-            b = ber >> 1;
-            rerr[x+1] += r;
-            gerr[x+1] += g;
-            berr[x+1] += b;
-            nrerr[x] += r;
-            ngerr[x] += g;
-            nberr[x] += b;
-          }
-
-          offset += width;
-
-          pixel_data = (ppixel_data += image->bytes_per_line);
-
-          terr = rerr;
-          rerr = nrerr;
-          nrerr = terr;
-
-          terr = gerr;
-          gerr = ngerr;
-          ngerr = terr;
-
-          terr = berr;
-          berr = nberr;
-          nberr = terr;
+    case StaticColor:
+    case PseudoColor: {
+#ifdef ORDEREDPSEUDO
+      OrderedPseudoColorDither(image->bytes_per_line, d);
+#else
+      PseudoColorDither(image->bytes_per_line, d);
+#endif
+      break;
+    }
+
+    default:
+      fprintf(stderr, i18n(ImageSet, ImageUnsupVisual,
+                           "BImage::renderXImage: unsupported visual\n"));
+      delete [] d;
+      XDestroyImage(image);
+      return (XImage *) 0;
+    }
+  } else {
+    register unsigned int x, y, r, g, b, offset;
+
+    unsigned char *pixel_data = d, *ppixel_data = d;
+    unsigned long pixel;
+
+    switch (control->getVisual()->c_class) {
+    case StaticColor:
+    case PseudoColor:
+      for (y = 0, offset = 0; y < height; y++) {
+        for (x = 0; x < width; x++, offset++) {
+         r = red_table[red[offset]];
+          g = green_table[green[offset]];
+         b = blue_table[blue[offset]];
+
+         pixel = (r * cpccpc) + (g * cpc) + b;
+         *pixel_data++ = colors[pixel].pixel;
         }
 
-          delete [] rerr;
-          delete [] gerr;
-          delete [] berr;
-          delete [] nrerr;
-          delete [] ngerr;
-          delete [] nberr;
-#endif // ORDEREDPSUEDO
-
-          break; }
-
-  default:
-          fprintf(stderr, i18n(ImageSet, ImageUnsupVisual,
-                               "BImage::renderXImage: unsupported visual\n"));
-          delete [] d;
-          XDestroyImage(image);
-          return (XImage *) 0;
-  }
-} else {
-  switch (control.getVisual()->c_class) {
-  case StaticColor:
-  case PseudoColor:
-    for (y = 0, offset = 0; y < height; y++) {
-      for (x = 0; x < width; x++, offset++) {
-        r = red_table[red[offset]];
-        g = green_table[green[offset]];
-        b = blue_table[blue[offset]];
-
-        pixel = (r * cpccpc) + (g * cpc) + b;
-        *pixel_data++ = colors[pixel].pixel;
+        pixel_data = (ppixel_data += image->bytes_per_line);
       }
 
-      pixel_data = (ppixel_data += image->bytes_per_line);
-    }
+      break;
 
-    break;
+    case TrueColor:
+      for (y = 0, offset = 0; y < height; y++) {
+        for (x = 0; x < width; x++, offset++) {
+         r = red_table[red[offset]];
+         g = green_table[green[offset]];
+         b = blue_table[blue[offset]];
 
-  case TrueColor:
-    for (y = 0, offset = 0; y < height; y++) {
-      for (x = 0; x < width; x++, offset++) {
-        r = red_table[red[offset]];
-        g = green_table[green[offset]];
-        b = blue_table[blue[offset]];
-
-        pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
-
-        switch (o) {
-        case  8: //  8bpp
-          *pixel_data++ = pixel;
-          break;
-
-        case 16: // 16bpp LSB
-          *pixel_data++ = pixel;
-          *pixel_data++ = pixel >> 8;
-          break;
-
-        case 17: // 16bpp MSB
-          *pixel_data++ = pixel >> 8;
-          *pixel_data++ = pixel;
-          break;
-
-        case 24: // 24bpp LSB
-          *pixel_data++ = pixel;
-          *pixel_data++ = pixel >> 8;
-          *pixel_data++ = pixel >> 16;
-          break;
-
-        case 25: // 24bpp MSB
-          *pixel_data++ = pixel >> 16;
-          *pixel_data++ = pixel >> 8;
-          *pixel_data++ = pixel;
-          break;
-
-        case 32: // 32bpp LSB
-          *pixel_data++ = pixel;
-          *pixel_data++ = pixel >> 8;
-          *pixel_data++ = pixel >> 16;
-          *pixel_data++ = pixel >> 24;
-          break;
-
-        case 33: // 32bpp MSB
-          *pixel_data++ = pixel >> 24;
-          *pixel_data++ = pixel >> 16;
-          *pixel_data++ = pixel >> 8;
-          *pixel_data++ = pixel;
-          break;
+         pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
+         assignPixelData(o, &pixel_data, pixel);
         }
+
+        pixel_data = (ppixel_data += image->bytes_per_line);
       }
 
-      pixel_data = (ppixel_data += image->bytes_per_line);
-    }
+      break;
 
-    break;
+    case StaticGray:
+    case GrayScale:
+      for (y = 0, offset = 0; y < height; y++) {
+       for (x = 0; x < width; x++, offset++) {
+         r = *(red_table + *(red + offset));
+         g = *(green_table + *(green + offset));
+         b = *(blue_table + *(blue + offset));
 
-  case StaticGray:
-  case GrayScale:
-    for (y = 0, offset = 0; y < height; y++) {
-      for (x = 0; x < width; x++, offset++) {
-        r = *(red_table + *(red + offset));
-        g = *(green_table + *(green + offset));
-        b = *(blue_table + *(blue + offset));
+         g = ((r * 30) + (g * 59) + (b * 11)) / 100;
+         *pixel_data++ = colors[g].pixel;
+       }
 
-        g = ((r * 30) + (g * 59) + (b * 11)) / 100;
-        *pixel_data++ = colors[g].pixel;
+       pixel_data = (ppixel_data += image->bytes_per_line);
       }
 
-      pixel_data = (ppixel_data += image->bytes_per_line);
-    }
-
-    break;
+      break;
 
-  default:
-    fprintf(stderr, i18n(ImageSet, ImageUnsupVisual,
-                         "BImage::renderXImage: unsupported visual\n"));
-    delete [] d;
-    XDestroyImage(image);
-    return (XImage *) 0;
+    default:
+      fprintf(stderr, i18n(ImageSet, ImageUnsupVisual,
+                           "BImage::renderXImage: unsupported visual\n"));
+      delete [] d;
+      XDestroyImage(image);
+      return (XImage *) 0;
+    }
   }
-}
 
-image->data = (char *) d;
-return image;
+  image->data = (char *) d;
+  return image;
 }
 
 
 Pixmap BImage::renderPixmap(void) {
   Pixmap pixmap =
-    XCreatePixmap(control.getBaseDisplay().getXDisplay(),
-                  control.getDrawable(), width, height, control.getDepth());
+    XCreatePixmap(control->getBaseDisplay()->getXDisplay(),
+                  control->getDrawable(), width, height, control->getDepth());
 
   if (pixmap == None) {
     fprintf(stderr, i18n(ImageSet, ImageErrorCreatingPixmap,
@@ -634,17 +569,17 @@ Pixmap BImage::renderPixmap(void) {
   XImage *image = renderXImage();
 
   if (! image) {
-    XFreePixmap(control.getBaseDisplay().getXDisplay(), pixmap);
+    XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
     return None;
   } else if (! image->data) {
     XDestroyImage(image);
-    XFreePixmap(control.getBaseDisplay().getXDisplay(), pixmap);
+    XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap);
     return None;
   }
 
-  XPutImage(control.getBaseDisplay().getXDisplay(), pixmap,
-            DefaultGC(control.getBaseDisplay().getXDisplay(),
-                      control.getScreenInfo().getScreenNumber()),
+  XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap,
+           DefaultGC(control->getBaseDisplay()->getXDisplay(),
+                     control->getScreenInfo()->getScreenNumber()),
             image, 0, 0, 0, 0, width, height);
 
   if (image->data) {
@@ -799,7 +734,7 @@ void BImage::bevel1(void) {
 void BImage::bevel2(void) {
   if (width > 4 && height > 4) {
     unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
-    *pg = green + width + 1, *pb = blue + width + 1;
+      *pg = green + width + 1, *pb = blue + width + 1;
     unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
 
     while (--w) {
@@ -900,17 +835,17 @@ void BImage::dgradient(void) {
   // modified for interlacing by Brad Hughes
 
   float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
-  xr = (float) from->getRed(),
-  xg = (float) from->getGreen(),
-  xb = (float) from->getBlue();
+    xr = (float) from.red(),
+    xg = (float) from.green(),
+    xb = (float) from.blue();
   unsigned char *pr = red, *pg = green, *pb = blue;
   unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
 
   register unsigned int x, y;
 
-  dry = drx = (float) (to->getRed() - from->getRed());
-  dgy = dgx = (float) (to->getGreen() - from->getGreen());
-  dby = dbx = (float) (to->getBlue() - from->getBlue());
+  dry = drx = (float) (to.red() - from.red());
+  dgy = dgx = (float) (to.green() - from.green());
+  dby = dbx = (float) (to.blue() - from.blue());
 
   // Create X table
   drx /= w;
@@ -944,10 +879,7 @@ void BImage::dgradient(void) {
 
   // Combine tables to create gradient
 
-#ifdef    INTERLACE
   if (! interlaced) {
-#endif // INTERLACE
-
     // normal dgradient
     for (yt = ytable, y = 0; y < height; y++, yt += 3) {
       for (xt = xtable, x = 0; x < width; x++) {
@@ -956,8 +888,6 @@ void BImage::dgradient(void) {
         *(pb++) = *(xt++) + *(yt + 2);
       }
     }
-
-#ifdef    INTERLACE
   } else {
     // faked interlacing effect
     unsigned char channel, channel2;
@@ -998,29 +928,26 @@ void BImage::dgradient(void) {
       }
     }
   }
-#endif // INTERLACE
-
 }
 
 
 void BImage::hgradient(void) {
   float drx, dgx, dbx,
-  xr = (float) from->getRed(),
-  xg = (float) from->getGreen(),
-  xb = (float) from->getBlue();
+    xr = (float) from.red(),
+    xg = (float) from.green(),
+    xb = (float) from.blue();
   unsigned char *pr = red, *pg = green, *pb = blue;
 
   register unsigned int x, y;
 
-  drx = (float) (to->getRed() - from->getRed());
-  dgx = (float) (to->getGreen() - from->getGreen());
-  dbx = (float) (to->getBlue() - from->getBlue());
+  drx = (float) (to.red() - from.red());
+  dgx = (float) (to.green() - from.green());
+  dbx = (float) (to.blue() - from.blue());
 
   drx /= width;
   dgx /= width;
   dbx /= width;
 
-#ifdef    INTERLACE
   if (interlaced && height > 2) {
     // faked interlacing effect
     unsigned char channel, channel2;
@@ -1076,8 +1003,6 @@ void BImage::hgradient(void) {
       memcpy(pb, (blue + offset), width);
     }
   } else {
-#endif // INTERLACE
-
     // normal hgradient
     for (x = 0; x < width; x++) {
       *(pr++) = (unsigned char) (xr);
@@ -1094,32 +1019,27 @@ void BImage::hgradient(void) {
       memcpy(pg, green, width);
       memcpy(pb, blue, width);
     }
-
-#ifdef    INTERLACE
   }
-#endif // INTERLACE
-
 }
 
 
 void BImage::vgradient(void) {
   float dry, dgy, dby,
-  yr = (float) from->getRed(),
-  yg = (float) from->getGreen(),
-  yb = (float) from->getBlue();
+    yr = (float) from.red(),
+    yg = (float) from.green(),
+    yb = (float) from.blue();
   unsigned char *pr = red, *pg = green, *pb = blue;
 
   register unsigned int y;
 
-  dry = (float) (to->getRed() - from->getRed());
-  dgy = (float) (to->getGreen() - from->getGreen());
-  dby = (float) (to->getBlue() - from->getBlue());
+  dry = (float) (to.red() - from.red());
+  dgy = (float) (to.green() - from.green());
+  dby = (float) (to.blue() - from.blue());
 
   dry /= height;
   dgy /= height;
   dby /= height;
 
-#ifdef    INTERLACE
   if (interlaced) {
     // faked interlacing effect
     unsigned char channel, channel2;
@@ -1162,8 +1082,6 @@ void BImage::vgradient(void) {
       yb += dby;
     }
   } else {
-#endif // INTERLACE
-
     // normal vgradient
     for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
       memset(pr, (unsigned char) yr, width);
@@ -1174,31 +1092,27 @@ void BImage::vgradient(void) {
       yg += dgy;
       yb += dby;
     }
-
-#ifdef    INTERLACE
   }
-#endif // INTERLACE
-
 }
 
 
 void BImage::pgradient(void) {
   // pyramid gradient -  based on original dgradient, written by
   // Mosfet (mosfet@kde.org)
-  // adapted from kde sources for Openbox by Brad Hughes
+  // adapted from kde sources for Blackbox by Brad Hughes
 
   float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
-  xr, xg, xb;
+    xr, xg, xb;
   int rsign, gsign, bsign;
   unsigned char *pr = red, *pg = green, *pb = blue;
-  unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(),
-  *xt = xtable, *yt = ytable;
+  unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
+    *xt = xtable, *yt = ytable;
 
   register unsigned int x, y;
 
-  dry = drx = (float) (to->getRed() - from->getRed());
-  dgy = dgx = (float) (to->getGreen() - from->getGreen());
-  dby = dbx = (float) (to->getBlue() - from->getBlue());
+  dry = drx = (float) (to.red() - from.red());
+  dgy = dgx = (float) (to.green() - from.green());
+  dby = dbx = (float) (to.blue() - from.blue());
 
   rsign = (drx < 0) ? -1 : 1;
   gsign = (dgx < 0) ? -1 : 1;
@@ -1240,10 +1154,7 @@ void BImage::pgradient(void) {
 
   // Combine tables to create gradient
 
-#ifdef    INTERLACE
   if (! interlaced) {
-#endif // INTERLACE
-
     // normal pgradient
     for (yt = ytable, y = 0; y < height; y++, yt += 3) {
       for (xt = xtable, x = 0; x < width; x++) {
@@ -1252,8 +1163,6 @@ void BImage::pgradient(void) {
         *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
       }
     }
-
-#ifdef    INTERLACE
   } else {
     // faked interlacing effect
     unsigned char channel, channel2;
@@ -1294,26 +1203,25 @@ void BImage::pgradient(void) {
       }
     }
   }
-#endif // INTERLACE
 }
 
 
 void BImage::rgradient(void) {
   // rectangle gradient -  based on original dgradient, written by
   // Mosfet (mosfet@kde.org)
-  // adapted from kde sources for Openbox by Brad Hughes
+  // adapted from kde sources for Blackbox by Brad Hughes
 
   float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
   int rsign, gsign, bsign;
   unsigned char *pr = red, *pg = green, *pb = blue;
-  unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(),
-  *xt = xtable, *yt = ytable;
+  unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
+    *xt = xtable, *yt = ytable;
 
   register unsigned int x, y;
 
-  dry = drx = (float) (to->getRed() - from->getRed());
-  dgy = dgx = (float) (to->getGreen() - from->getGreen());
-  dby = dbx = (float) (to->getBlue() - from->getBlue());
+  dry = drx = (float) (to.red() - from.red());
+  dgy = dgx = (float) (to.green() - from.green());
+  dby = dbx = (float) (to.blue() - from.blue());
 
   rsign = (drx < 0) ? -2 : 2;
   gsign = (dgx < 0) ? -2 : 2;
@@ -1355,10 +1263,7 @@ void BImage::rgradient(void) {
 
   // Combine tables to create gradient
 
-#ifdef    INTERLACE
   if (! interlaced) {
-#endif // INTERLACE
-
     // normal rgradient
     for (yt = ytable, y = 0; y < height; y++, yt += 3) {
       for (xt = xtable, x = 0; x < width; x++) {
@@ -1367,8 +1272,6 @@ void BImage::rgradient(void) {
         *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
       }
     }
-
-#ifdef    INTERLACE
   } else {
     // faked interlacing effect
     unsigned char channel, channel2;
@@ -1409,28 +1312,27 @@ void BImage::rgradient(void) {
       }
     }
   }
-#endif // INTERLACE
 }
 
 
 void BImage::egradient(void) {
   // elliptic gradient -  based on original dgradient, written by
   // Mosfet (mosfet@kde.org)
-  // adapted from kde sources for Openbox by Brad Hughes
+  // adapted from kde sources for Blackbox by Brad Hughes
 
   float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
   int rsign, gsign, bsign;
   unsigned char *pr = red, *pg = green, *pb = blue;
   unsigned int *xt = xtable, *yt = ytable,
-  tr = (unsigned long) to->getRed(),
-  tg = (unsigned long) to->getGreen(),
-  tb = (unsigned long) to->getBlue();
+    tr = (unsigned long) to.red(),
+    tg = (unsigned long) to.green(),
+    tb = (unsigned long) to.blue();
 
   register unsigned int x, y;
 
-  dry = drx = (float) (to->getRed() - from->getRed());
-  dgy = dgx = (float) (to->getGreen() - from->getGreen());
-  dby = dbx = (float) (to->getBlue() - from->getBlue());
+  dry = drx = (float) (to.red() - from.red());
+  dgy = dgx = (float) (to.green() - from.green());
+  dby = dbx = (float) (to.blue() - from.blue());
 
   rsign = (drx < 0) ? -1 : 1;
   gsign = (dgx < 0) ? -1 : 1;
@@ -1472,23 +1374,18 @@ void BImage::egradient(void) {
 
   // Combine tables to create gradient
 
-#ifdef    INTERLACE
   if (! interlaced) {
-#endif // INTERLACE
-
     // normal egradient
     for (yt = ytable, y = 0; y < height; y++, yt += 3) {
       for (xt = xtable, x = 0; x < width; x++) {
         *(pr++) = (unsigned char)
-          (tr - (rsign * control.getSqrt(*(xt++) + *(yt))));
+          (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
         *(pg++) = (unsigned char)
-          (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1))));
+          (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
         *(pb++) = (unsigned char)
-          (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2))));
+          (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
       }
     }
-
-#ifdef    INTERLACE
   } else {
     // faked interlacing effect
     unsigned char channel, channel2;
@@ -1497,37 +1394,37 @@ void BImage::egradient(void) {
       for (xt = xtable, x = 0; x < width; x++) {
         if (y & 1) {
           channel = (unsigned char)
-            (tr - (rsign * control.getSqrt(*(xt++) + *(yt))));
+            (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
           channel2 = (channel >> 1) + (channel >> 2);
           if (channel2 > channel) channel2 = 0;
           *(pr++) = channel2;
 
           channel = (unsigned char)
-            (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1))));
+            (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
           channel2 = (channel >> 1) + (channel >> 2);
           if (channel2 > channel) channel2 = 0;
           *(pg++) = channel2;
 
           channel = (unsigned char)
-            (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2))));
+            (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
           channel2 = (channel >> 1) + (channel >> 2);
           if (channel2 > channel) channel2 = 0;
           *(pb++) = channel2;
         } else {
           channel = (unsigned char)
-            (tr - (rsign * control.getSqrt(*(xt++) + *(yt))));
+            (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
           channel2 = channel + (channel >> 3);
           if (channel2 < channel) channel2 = ~0;
           *(pr++) = channel2;
 
           channel = (unsigned char)
-            (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1))));
+          (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
           channel2 = channel + (channel >> 3);
           if (channel2 < channel) channel2 = ~0;
           *(pg++) = channel2;
 
           channel = (unsigned char)
-            (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2))));
+            (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
           channel2 = channel + (channel >> 3);
           if (channel2 < channel) channel2 = ~0;
           *(pb++) = channel2;
@@ -1535,28 +1432,27 @@ void BImage::egradient(void) {
       }
     }
   }
-#endif // INTERLACE
 }
 
 
 void BImage::pcgradient(void) {
   // pipe cross gradient -  based on original dgradient, written by
   // Mosfet (mosfet@kde.org)
-  // adapted from kde sources for Openbox by Brad Hughes
+  // adapted from kde sources for Blackbox by Brad Hughes
 
   float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
   int rsign, gsign, bsign;
   unsigned char *pr = red, *pg = green, *pb = blue;
   unsigned int *xt = xtable, *yt = ytable,
-  tr = to->getRed(),
-  tg = to->getGreen(),
-  tb = to->getBlue();
+    tr = to.red(),
+    tg = to.green(),
+    tb = to.blue();
 
   register unsigned int x, y;
 
-  dry = drx = (float) (to->getRed() - from->getRed());
-  dgy = dgx = (float) (to->getGreen() - from->getGreen());
-  dby = dbx = (float) (to->getBlue() - from->getBlue());
+  dry = drx = (float) (to.red() - from.red());
+  dgy = dgx = (float) (to.green() - from.green());
+  dby = dbx = (float) (to.blue() - from.blue());
 
   rsign = (drx < 0) ? -2 : 2;
   gsign = (dgx < 0) ? -2 : 2;
@@ -1598,10 +1494,7 @@ void BImage::pcgradient(void) {
 
   // Combine tables to create gradient
 
-#ifdef    INTERLACE
   if (! interlaced) {
-#endif // INTERLACE
-
     // normal pcgradient
     for (yt = ytable, y = 0; y < height; y++, yt += 3) {
       for (xt = xtable, x = 0; x < width; x++) {
@@ -1610,8 +1503,6 @@ void BImage::pcgradient(void) {
         *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
       }
     }
-
-#ifdef    INTERLACE
   } else {
     // faked interlacing effect
     unsigned char channel, channel2;
@@ -1652,27 +1543,26 @@ void BImage::pcgradient(void) {
       }
     }
   }
-#endif // INTERLACE
 }
 
 
 void BImage::cdgradient(void) {
   // cross diagonal gradient -  based on original dgradient, written by
   // Mosfet (mosfet@kde.org)
-  // adapted from kde sources for Openbox by Brad Hughes
+  // adapted from kde sources for Blackbox by Brad Hughes
 
   float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
-  xr = (float) from->getRed(),
-  xg = (float) from->getGreen(),
-  xb = (float) from->getBlue();
+    xr = (float) from.red(),
+    xg = (float) from.green(),
+    xb = (float) from.blue();
   unsigned char *pr = red, *pg = green, *pb = blue;
   unsigned int w = width * 2, h = height * 2, *xt, *yt;
 
   register unsigned int x, y;
 
-  dry = drx = (float) (to->getRed() - from->getRed());
-  dgy = dgx = (float) (to->getGreen() - from->getGreen());
-  dby = dbx = (float) (to->getBlue() - from->getBlue());
+  dry = drx = (float) (to.red() - from.red());
+  dgy = dgx = (float) (to.green() - from.green());
+  dby = dbx = (float) (to.blue() - from.blue());
 
   // Create X table
   drx /= w;
@@ -1706,10 +1596,7 @@ void BImage::cdgradient(void) {
 
   // Combine tables to create gradient
 
-#ifdef    INTERLACE
   if (! interlaced) {
-#endif // INTERLACE
-
     // normal cdgradient
     for (yt = ytable, y = 0; y < height; y++, yt += 3) {
       for (xt = xtable, x = 0; x < width; x++) {
@@ -1718,8 +1605,6 @@ void BImage::cdgradient(void) {
         *(pb++) = *(xt++) + *(yt + 2);
       }
     }
-
-#ifdef    INTERLACE
   } else {
     // faked interlacing effect
     unsigned char channel, channel2;
@@ -1760,686 +1645,4 @@ void BImage::cdgradient(void) {
       }
     }
   }
-#endif // INTERLACE
-}
-
-
-BImageControl::BImageControl(BaseDisplay &dpy, ScreenInfo &scrn, Bool _dither,
-                             int _cpc, unsigned long cache_timeout,
-                             unsigned long cmax) : basedisplay(dpy),
-screeninfo(scrn)
-{
-  setDither(_dither);
-  setColorsPerChannel(_cpc);
-
-  cache_max = cmax;
-#ifdef    TIMEDCACHE
-  if (cache_timeout) {
-    timer = new BTimer(basedisplay, *this);
-    timer->setTimeout(cache_timeout);
-    timer->start();
-  } else
-    timer = (BTimer *) 0;
-#endif // TIMEDCACHE
-
-  colors = (XColor *) 0;
-  ncolors = 0;
-
-  grad_xbuffer = grad_ybuffer = (unsigned int *) 0;
-  grad_buffer_width = grad_buffer_height = 0;
-
-  sqrt_table = (unsigned long *) 0;
-
-  screen_depth = screeninfo.getDepth();
-  window = screeninfo.getRootWindow();
-  screen_number = screeninfo.getScreenNumber();
-
-  int count;
-  XPixmapFormatValues *pmv = XListPixmapFormats(basedisplay.getXDisplay(),
-                                                &count);
-  colormap = screeninfo.getColormap();
-
-  if (pmv) {
-    bits_per_pixel = 0;
-    for (int i = 0; i < count; i++)
-      if (pmv[i].depth == screen_depth) {
-        bits_per_pixel = pmv[i].bits_per_pixel;
-        break;
-      }
-
-    XFree(pmv);
-  }
-
-  if (bits_per_pixel == 0) bits_per_pixel = screen_depth;
-  if (bits_per_pixel >= 24) setDither(False);
-
-  red_offset = green_offset = blue_offset = 0;
-
-  switch (getVisual()->c_class) {
-  case TrueColor:
-    {
-      int i;
-
-      // compute color tables
-      unsigned long red_mask = getVisual()->red_mask,
-      green_mask = getVisual()->green_mask,
-      blue_mask = getVisual()->blue_mask;
-
-      while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; }
-      while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; }
-      while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; }
-
-      red_bits = 255 / red_mask;
-      green_bits = 255 / green_mask;
-      blue_bits = 255 / blue_mask;
-
-      for (i = 0; i < 256; i++) {
-        red_color_table[i] = i / red_bits;
-        green_color_table[i] = i / green_bits;
-        blue_color_table[i] = i / blue_bits;
-      }
-    }
-
-    break;
-
-  case PseudoColor:
-  case StaticColor:
-    {
-      ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
-
-      if (ncolors > (1 << screen_depth)) {
-        colors_per_channel = (1 << screen_depth) / 3;
-        ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
-      }
-
-      if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
-        fprintf(stderr, i18n(ImageSet, ImageInvalidColormapSize,
-                             "BImageControl::BImageControl: invalid colormap size %d "
-                             "(%d/%d/%d) - reducing"),
-                ncolors, colors_per_channel, colors_per_channel,
-                colors_per_channel);
-
-        colors_per_channel = (1 << screen_depth) / 3;
-      }
-
-      colors = new XColor[ncolors];
-      if (! colors) {
-        fprintf(stderr, i18n(ImageSet,
-                             ImageErrorAllocatingColormap,
-                             "BImageControl::BImageControl: error allocating "
-                             "colormap\n"));
-        exit(1);
-      }
-
-      int i = 0, ii, p, r, g, b,
-
-#ifdef    ORDEREDPSEUDO
-      bits = 256 / colors_per_channel;
-#else // !ORDEREDPSEUDO
-      bits = 255 / (colors_per_channel - 1);
-#endif // ORDEREDPSEUDO
-
-      red_bits = green_bits = blue_bits = bits;
-
-      for (i = 0; i < 256; i++)
-        red_color_table[i] = green_color_table[i] = blue_color_table[i] =
-          i / bits;
-
-      for (r = 0, i = 0; r < colors_per_channel; r++)
-        for (g = 0; g < colors_per_channel; g++)
-          for (b = 0; b < colors_per_channel; b++, i++) {
-            colors[i].red = (r * 0xffff) / (colors_per_channel - 1);
-            colors[i].green = (g * 0xffff) / (colors_per_channel - 1);
-            colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);;
-            colors[i].flags = DoRed|DoGreen|DoBlue;
-          }
-
-      basedisplay.grab();
-
-      for (i = 0; i < ncolors; i++)
-        if (! XAllocColor(basedisplay.getXDisplay(), colormap, &colors[i])) {
-          fprintf(stderr, i18n(ImageSet, ImageColorAllocFail,
-                               "couldn't alloc color %i %i %i\n"),
-                  colors[i].red, colors[i].green, colors[i].blue);
-          colors[i].flags = 0;
-        } else
-          colors[i].flags = DoRed|DoGreen|DoBlue;
-
-        basedisplay.ungrab();
-
-        XColor icolors[256];
-        int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth));
-
-        for (i = 0; i < incolors; i++)
-          icolors[i].pixel = i;
-
-        XQueryColors(basedisplay.getXDisplay(), colormap, icolors, incolors);
-        for (i = 0; i < ncolors; i++) {
-          if (! colors[i].flags) {
-            unsigned long chk = 0xffffffff, pixel, close = 0;
-
-            p = 2;
-            while (p--) {
-              for (ii = 0; ii < incolors; ii++) {
-                r = (colors[i].red - icolors[i].red) >> 8;
-                g = (colors[i].green - icolors[i].green) >> 8;
-                b = (colors[i].blue - icolors[i].blue) >> 8;
-                pixel = (r * r) + (g * g) + (b * b);
-
-                if (pixel < chk) {
-                  chk = pixel;
-                  close = ii;
-                }
-
-                colors[i].red = icolors[close].red;
-                colors[i].green = icolors[close].green;
-                colors[i].blue = icolors[close].blue;
-
-                if (XAllocColor(basedisplay.getXDisplay(), colormap,
-                                &colors[i])) {
-                  colors[i].flags = DoRed|DoGreen|DoBlue;
-                  break;
-                }
-              }
-            }
-          }
-        }
-
-        break;
-    }
-
-  case GrayScale:
-  case StaticGray:
-    {
-
-      if (getVisual()->c_class == StaticGray) {
-        ncolors = 1 << screen_depth;
-      } else {
-        ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
-
-        if (ncolors > (1 << screen_depth)) {
-          colors_per_channel = (1 << screen_depth) / 3;
-          ncolors =
-            colors_per_channel * colors_per_channel * colors_per_channel;
-        }
-      }
-
-      if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
-        fprintf(stderr,        i18n(ImageSet, ImageInvalidColormapSize,
-                             "BImageControl::BImageControl: invalid colormap size %d "
-                             "(%d/%d/%d) - reducing"),
-                ncolors, colors_per_channel, colors_per_channel,
-                colors_per_channel);
-
-        colors_per_channel = (1 << screen_depth) / 3;
-      }
-
-      colors = new XColor[ncolors];
-      if (! colors) {
-        fprintf(stderr, i18n(ImageSet,
-                             ImageErrorAllocatingColormap,
-                             "BImageControl::BImageControl: error allocating "
-                             "colormap\n"));
-        exit(1);
-      }
-
-      int i = 0, ii, p, bits = 255 / (colors_per_channel - 1);
-      red_bits = green_bits = blue_bits = bits;
-
-      for (i = 0; i < 256; i++)
-        red_color_table[i] = green_color_table[i] = blue_color_table[i] =
-          i / bits;
-
-      basedisplay.grab();
-      for (i = 0; i < ncolors; i++) {
-        colors[i].red = (i * 0xffff) / (colors_per_channel - 1);
-        colors[i].green = (i * 0xffff) / (colors_per_channel - 1);
-        colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);;
-        colors[i].flags = DoRed|DoGreen|DoBlue;
-
-        if (! XAllocColor(basedisplay.getXDisplay(), colormap,
-                          &colors[i])) {
-          fprintf(stderr, i18n(ImageSet, ImageColorAllocFail,
-                               "couldn't alloc color %i %i %i\n"),
-                  colors[i].red, colors[i].green, colors[i].blue);
-          colors[i].flags = 0;
-        } else
-          colors[i].flags = DoRed|DoGreen|DoBlue;
-      }
-
-      basedisplay.ungrab();
-
-      XColor icolors[256];
-      int incolors = (((1 << screen_depth) > 256) ? 256 :
-                      (1 << screen_depth));
-
-      for (i = 0; i < incolors; i++)
-        icolors[i].pixel = i;
-
-      XQueryColors(basedisplay.getXDisplay(), colormap, icolors, incolors);
-      for (i = 0; i < ncolors; i++) {
-        if (! colors[i].flags) {
-          unsigned long chk = 0xffffffff, pixel, close = 0;
-
-          p = 2;
-          while (p--) {
-            for (ii = 0; ii < incolors; ii++) {
-              int r = (colors[i].red - icolors[i].red) >> 8;
-              int g = (colors[i].green - icolors[i].green) >> 8;
-              int b = (colors[i].blue - icolors[i].blue) >> 8;
-              pixel = (r * r) + (g * g) + (b * b);
-
-              if (pixel < chk) {
-                chk = pixel;
-                close = ii;
-              }
-
-              colors[i].red = icolors[close].red;
-              colors[i].green = icolors[close].green;
-              colors[i].blue = icolors[close].blue;
-
-              if (XAllocColor(basedisplay.getXDisplay(), colormap,
-                              &colors[i])) {
-                colors[i].flags = DoRed|DoGreen|DoBlue;
-                break;
-              }
-            }
-          }
-        }
-      }
-
-      break;
-    }
-
-  default:
-    fprintf(stderr, i18n(ImageSet, ImageUnsupVisual,
-                         "BImageControl::BImageControl: unsupported visual %d\n"),
-            getVisual()->c_class);
-    exit(1);
-  }
-}
-
-
-BImageControl::~BImageControl(void) {
-  if (sqrt_table) {
-    delete [] sqrt_table;
-  }
-
-  if (grad_xbuffer) {
-    delete [] grad_xbuffer;
-  }
-
-  if (grad_ybuffer) {
-    delete [] grad_ybuffer;
-  }
-
-  if (colors) {
-    unsigned long *pixels = new unsigned long [ncolors];
-
-    int i;
-    for (i = 0; i < ncolors; i++)
-      *(pixels + i) = (*(colors + i)).pixel;
-
-    XFreeColors(basedisplay.getXDisplay(), colormap, pixels, ncolors, 0);
-
-    delete [] colors;
-  }
-
-  if (!cache.empty()) {
-    int i, n = cache.size();
-    fprintf(stderr, i18n(ImageSet, ImagePixmapRelease,
-                         "BImageContol::~BImageControl: pixmap cache - "
-                         "releasing %d pixmaps\n"), n);
-
-    for (i = 0; i < n; i++) {
-      Cache *tmp = cache.front();
-      XFreePixmap(basedisplay.getXDisplay(), tmp->pixmap);
-      cache.remove(tmp);
-      delete tmp;
-    }
-
-#ifdef    TIMEDCACHE
-    if (timer) {
-      timer->stop();
-      delete timer;
-    }
-#endif // TIMEDCACHE
-  }
-}
-
-
-Pixmap BImageControl::searchCache(unsigned int width, unsigned int height,
-                                  unsigned long texture,
-                                  BColor *c1, BColor *c2) {
-  if (!cache.empty()) {
-
-    CacheList::iterator it;
-    for (it = cache.begin(); it != cache.end(); ++it) {
-      Cache *tmp = *it;
-      if ((tmp->width == width) && (tmp->height == height) &&
-          (tmp->texture == texture) && (tmp->pixel1 == c1->getPixel()))
-        if (texture & BImage_Gradient) {
-          if (tmp->pixel2 == c2->getPixel()) {
-            tmp->count++;
-            return tmp->pixmap;
-          }
-        } else {
-          tmp->count++;
-          return tmp->pixmap;
-        }
-    }
-  }
-
-  return None;
-}
-
-
-Pixmap BImageControl::renderImage(unsigned int width, unsigned int height,
-                                  BTexture *texture) {
-  if (texture->getTexture() & BImage_ParentRelative) return ParentRelative;
-
-  Pixmap pixmap = searchCache(width, height, texture->getTexture(),
-                              texture->getColor(), texture->getColorTo());
-  if (pixmap) return pixmap;
-
-  BImage image(*this, width, height);
-  pixmap = image.render(texture);
-
-  if (pixmap) {
-    Cache *tmp = new Cache;
-
-    tmp->pixmap = pixmap;
-    tmp->width = width;
-    tmp->height = height;
-    tmp->count = 1;
-    tmp->texture = texture->getTexture();
-    tmp->pixel1 = texture->getColor()->getPixel();
-
-    if (texture->getTexture() & BImage_Gradient)
-      tmp->pixel2 = texture->getColorTo()->getPixel();
-    else
-      tmp->pixel2 = 0l;
-
-    cache.push_back(tmp);
-
-    if ((unsigned) cache.size() > cache_max) {
-#ifdef    DEBUG
-      fprintf(stderr, i18n(ImageSet, ImagePixmapCacheLarge,
-                           "BImageControl::renderImage: cache is large, "
-                           "forcing cleanout\n"));
-#endif // DEBUG
-
-      timeout();
-    }
-
-    return pixmap;
-  }
-
-  return None;
-}
-
-
-void BImageControl::removeImage(Pixmap pixmap) {
-  if (pixmap) {
-    CacheList::iterator it;
-    for (it = cache.begin(); it != cache.end(); ++it) {
-      Cache *tmp = *it;
-      if (tmp->pixmap == pixmap) {
-        if (tmp->count) {
-          tmp->count--;
-
-#ifdef    TIMEDCACHE
-          if (! timer) timeout();
-#else // !TIMEDCACHE
-          if (! tmp->count) timeout();
-#endif // TIMEDCACHE
-        }
-
-        return;
-      }
-    }
-  }
-}
-
-
-unsigned long BImageControl::getColor(const char *colorname,
-                                      unsigned char *r, unsigned char *g,
-                                      unsigned char *b)
-{
-  XColor color;
-  color.pixel = 0;
-
-  if (! XParseColor(basedisplay.getXDisplay(), colormap, colorname, &color))
-    fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n",
-            colorname);
-  else if (! XAllocColor(basedisplay.getXDisplay(), colormap, &color))
-    fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n",
-            colorname);
-
-  if (color.red == 65535) *r = 0xff;
-  else *r = (unsigned char) (color.red / 0xff);
-  if (color.green == 65535) *g = 0xff;
-  else *g = (unsigned char) (color.green / 0xff);
-  if (color.blue == 65535) *b = 0xff;
-  else *b = (unsigned char) (color.blue / 0xff);
-
-  return color.pixel;
-}
-
-
-unsigned long BImageControl::getColor(const char *colorname) {
-  XColor color;
-  color.pixel = 0;
-
-  if (! XParseColor(basedisplay.getXDisplay(), colormap, colorname, &color))
-    fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n",
-            colorname);
-  else if (! XAllocColor(basedisplay.getXDisplay(), colormap, &color))
-    fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n",
-            colorname);
-
-  return color.pixel;
-}
-
-
-void BImageControl::getColorTables(unsigned char **rmt, unsigned char **gmt,
-                                   unsigned char **bmt,
-                                   int *roff, int *goff, int *boff,
-                                   int *rbit, int *gbit, int *bbit) {
-  if (rmt) *rmt = red_color_table;
-  if (gmt) *gmt = green_color_table;
-  if (bmt) *bmt = blue_color_table;
-
-  if (roff) *roff = red_offset;
-  if (goff) *goff = green_offset;
-  if (boff) *boff = blue_offset;
-
-  if (rbit) *rbit = red_bits;
-  if (gbit) *gbit = green_bits;
-  if (bbit) *bbit = blue_bits;
-}
-
-
-void BImageControl::getXColorTable(XColor **c, int *n) {
-  if (c) *c = colors;
-  if (n) *n = ncolors;
-}
-
-
-void BImageControl::getGradientBuffers(unsigned int w,
-                                       unsigned int h,
-                                       unsigned int **xbuf,
-                                       unsigned int **ybuf)
-{
-  if (w > grad_buffer_width) {
-    if (grad_xbuffer) {
-      delete [] grad_xbuffer;
-    }
-
-    grad_buffer_width = w;
-
-    grad_xbuffer = new unsigned int[grad_buffer_width * 3];
-  }
-
-  if (h > grad_buffer_height) {
-    if (grad_ybuffer) {
-      delete [] grad_ybuffer;
-    }
-
-    grad_buffer_height = h;
-
-    grad_ybuffer = new unsigned int[grad_buffer_height * 3];
-  }
-
-  *xbuf = grad_xbuffer;
-  *ybuf = grad_ybuffer;
-}
-
-
-void BImageControl::installRootColormap(void) {
-  basedisplay.grab();
-
-  Bool install = True;
-  int i = 0, ncmap = 0;
-  Colormap *cmaps =
-    XListInstalledColormaps(basedisplay.getXDisplay(), window, &ncmap);
-
-  if (cmaps) {
-    for (i = 0; i < ncmap; i++)
-      if (*(cmaps + i) == colormap)
-        install = False;
-
-    if (install)
-      XInstallColormap(basedisplay.getXDisplay(), colormap);
-
-    XFree(cmaps);
-  }
-
-  basedisplay.ungrab();
-}
-
-
-void BImageControl::setColorsPerChannel(int cpc) {
-  if (cpc < 2) cpc = 2;
-  if (cpc > 6) cpc = 6;
-
-  colors_per_channel = cpc;
-}
-
-
-unsigned long BImageControl::getSqrt(unsigned int x) {
-  if (! sqrt_table) {
-    // build sqrt table for use with elliptic gradient
-
-    sqrt_table = new unsigned long[(256 * 256 * 2) + 1];
-    int i = 0;
-
-    for (; i < (256 * 256 * 2); i++)
-      *(sqrt_table + i) = bsqrt(i);
-  }
-
-  return (*(sqrt_table + x));
-}
-
-
-void BImageControl::parseTexture(BTexture *texture, const char *t) {
-  if ((! texture) || (! t)) return;
-
-  int t_len = strlen(t) + 1, i;
-  char *ts = new char[t_len];
-  if (! ts) return;
-
-  // convert to lower case
-  for (i = 0; i < t_len; i++)
-    *(ts + i) = tolower(*(t + i));
-
-  if (strstr(ts, "parentrelative")) {
-    texture->setTexture(BImage_ParentRelative);
-  } else {
-    texture->setTexture(0);
-
-    if (strstr(ts, "solid"))
-      texture->addTexture(BImage_Solid);
-    else if (strstr(ts, "gradient")) {
-      texture->addTexture(BImage_Gradient);
-      if (strstr(ts, "crossdiagonal"))
-        texture->addTexture(BImage_CrossDiagonal);
-      else if (strstr(ts, "rectangle"))
-        texture->addTexture(BImage_Rectangle);
-      else if (strstr(ts, "pyramid"))
-        texture->addTexture(BImage_Pyramid);
-      else if (strstr(ts, "pipecross"))
-        texture->addTexture(BImage_PipeCross);
-      else if (strstr(ts, "elliptic"))
-        texture->addTexture(BImage_Elliptic);
-      else if (strstr(ts, "diagonal"))
-        texture->addTexture(BImage_Diagonal);
-      else if (strstr(ts, "horizontal"))
-        texture->addTexture(BImage_Horizontal);
-      else if (strstr(ts, "vertical"))
-        texture->addTexture(BImage_Vertical);
-      else
-        texture->addTexture(BImage_Diagonal);
-    } else
-      texture->addTexture(BImage_Solid);
-
-    if (strstr(ts, "raised"))
-      texture->addTexture(BImage_Raised);
-    else if (strstr(ts, "sunken"))
-      texture->addTexture(BImage_Sunken);
-    else if (strstr(ts, "flat"))
-      texture->addTexture(BImage_Flat);
-    else
-      texture->addTexture(BImage_Raised);
-
-    if (! (texture->getTexture() & BImage_Flat))
-      if (strstr(ts, "bevel2"))
-        texture->addTexture(BImage_Bevel2);
-      else
-        texture->addTexture(BImage_Bevel1);
-
-#ifdef    INTERLACE
-    if (strstr(ts, "interlaced"))
-      texture->addTexture(BImage_Interlaced);
-#endif // INTERLACE
-  }
-
-  delete [] ts;
-}
-
-
-void BImageControl::parseColor(BColor *color, const char *c) {
-  if (! color) return;
-
-  if (color->isAllocated()) {
-    unsigned long pixel = color->getPixel();
-
-    XFreeColors(basedisplay.getXDisplay(), colormap, &pixel, 1, 0);
-
-    color->setPixel(0l);
-    color->setRGB(0, 0, 0);
-    color->setAllocated(False);
-  }
-
-  if (c) {
-    unsigned char r, g, b;
-
-    color->setPixel(getColor(c, &r, &g, &b));
-    color->setRGB(r, g, b);
-    color->setAllocated(True);
-  }
-}
-
-
-void BImageControl::timeout(void) {
-  CacheList::iterator it;
-  for (it = cache.begin(); it != cache.end(); ) {
-    Cache *tmp = *it;
-    ++it;       // move on to the next item before this one is removed
-    if (tmp->count <= 0) {
-      XFreePixmap(basedisplay.getXDisplay(), tmp->pixmap);
-      cache.remove(tmp);
-      delete tmp;
-    } 
-  }
 }
diff --git a/src/Image.h b/src/Image.h
deleted file mode 100644 (file)
index e342128..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-// Image.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Image_hh
-#define   __Image_hh
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#include "Timer.h"
-#include <list>
-
-class ScreenInfo;
-class BImage;
-class BImageControl;
-
-
-// bevel options
-#define BImage_Flat            (1l<<1)
-#define BImage_Sunken          (1l<<2)
-#define BImage_Raised          (1l<<3)
-
-// textures
-#define BImage_Solid           (1l<<4)
-#define BImage_Gradient                (1l<<5)
-
-// gradients
-#define BImage_Horizontal      (1l<<6)
-#define BImage_Vertical                (1l<<7)
-#define BImage_Diagonal                (1l<<8)
-#define BImage_CrossDiagonal   (1l<<9)
-#define BImage_Rectangle       (1l<<10)
-#define BImage_Pyramid         (1l<<11)
-#define BImage_PipeCross       (1l<<12)
-#define BImage_Elliptic                (1l<<13)
-
-// bevel types
-#define BImage_Bevel1          (1l<<14)
-#define BImage_Bevel2          (1l<<15)
-
-// inverted image
-#define BImage_Invert          (1l<<16)
-
-// parent relative image
-#define BImage_ParentRelative   (1l<<17)
-
-#ifdef    INTERLACE
-// fake interlaced image
-#  define BImage_Interlaced    (1l<<18)
-#endif // INTERLACE
-
-class BColor {
-private:
-  int allocated;
-  unsigned char red, green, blue;
-  unsigned long pixel;
-
-public:
-  BColor(char r = 0, char g = 0, char b = 0)
-    { red = r; green = g; blue = b; pixel = 0; allocated = 0; }
-
-  inline const int &isAllocated(void) const { return allocated; }
-
-  inline const unsigned char &getRed(void) const { return red; }
-  inline const unsigned char &getGreen(void) const { return green; }
-  inline const unsigned char &getBlue(void) const { return blue; }
-
-  inline const unsigned long &getPixel(void) const { return pixel; }
-
-  inline void setAllocated(int a) { allocated = a; }
-  inline void setRGB(char r, char g, char b) { red = r; green = g; blue = b; }
-  inline void setPixel(unsigned long p) { pixel = p; }
-};
-
-
-class BTexture {
-private:
-  BColor color, colorTo, hiColor, loColor;
-  unsigned long texture;
-
-public:
-  BTexture(void) { texture = 0; }
-
-  inline BColor *getColor(void) { return &color; }
-  inline BColor *getColorTo(void) { return &colorTo; }
-  inline BColor *getHiColor(void) { return &hiColor; }
-  inline BColor *getLoColor(void) { return &loColor; }
-
-  inline const unsigned long &getTexture(void) const { return texture; }
-
-  inline void setTexture(unsigned long t) { texture = t; }
-  inline void addTexture(unsigned long t) { texture |= t; }
-};
-
-
-class BImage {
-private:
-  BImageControl &control;
-
-#ifdef    INTERLACE
-  Bool interlaced;
-#endif // INTERLACE
-
-  XColor *colors;
-
-  BColor *from, *to;
-  int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits,
-    ncolors, cpc, cpccpc;
-  unsigned char *red, *green, *blue, *red_table, *green_table, *blue_table;
-  unsigned int width, height, *xtable, *ytable;
-
-
-protected:
-  Pixmap renderPixmap(void);
-
-  XImage *renderXImage(void);
-
-  void invert(void);
-  void bevel1(void);
-  void bevel2(void);
-  void dgradient(void);
-  void egradient(void);
-  void hgradient(void);
-  void pgradient(void);
-  void rgradient(void);
-  void vgradient(void);
-  void cdgradient(void);
-  void pcgradient(void);
-
-
-public:
-  BImage(BImageControl &, unsigned int, unsigned int);
-  ~BImage(void);
-
-  Pixmap render(BTexture *);
-  Pixmap render_solid(BTexture *);
-  Pixmap render_gradient(BTexture *);
-};
-
-
-class BImageControl : public TimeoutHandler {
-private:
-  Bool dither;
-  BaseDisplay &basedisplay;
-  ScreenInfo &screeninfo;
-#ifdef    TIMEDCACHE
-  BTimer *timer;
-#endif // TIMEDCACHE
-
-  Colormap colormap;
-
-  Window window;
-  XColor *colors;
-  int colors_per_channel, ncolors, screen_number, screen_depth,
-    bits_per_pixel, red_offset, green_offset, blue_offset,
-    red_bits, green_bits, blue_bits;
-  unsigned char red_color_table[256], green_color_table[256],
-    blue_color_table[256];
-  unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width,
-    grad_buffer_height;
-  unsigned long *sqrt_table, cache_max;
-
-  typedef struct Cache {
-    Pixmap pixmap;
-
-    unsigned int count, width, height;
-    unsigned long pixel1, pixel2, texture;
-  } Cache;
-
-  typedef std::list<Cache*> CacheList;
-  CacheList cache;
-
-
-protected:
-  Pixmap searchCache(unsigned int, unsigned int, unsigned long, BColor *,
-                     BColor *);
-
-
-public:
-  BImageControl(BaseDisplay &, ScreenInfo &, Bool = False, int = 4,
-                unsigned long = 300000l, unsigned long = 200l);
-  virtual ~BImageControl(void);
-
-  inline BaseDisplay &getBaseDisplay(void) { return basedisplay; }
-
-  inline const Bool &doDither(void) { return dither; }
-
-  inline ScreenInfo &getScreenInfo(void) { return screeninfo; }
-
-  inline const Window &getDrawable(void) const { return window; }
-
-  inline Visual *getVisual(void) const { return screeninfo.getVisual(); }
-
-  inline const int &getBitsPerPixel(void) const { return bits_per_pixel; }
-  inline const int &getDepth(void) const { return screen_depth; }
-  inline const int &getColorsPerChannel(void) const
-    { return colors_per_channel; }
-
-  unsigned long getColor(const char *);
-  unsigned long getColor(const char *, unsigned char *, unsigned char *,
-                         unsigned char *);
-  unsigned long getSqrt(unsigned int);
-
-  Pixmap renderImage(unsigned int, unsigned int, BTexture *);
-
-  void installRootColormap(void);
-  void removeImage(Pixmap);
-  void getColorTables(unsigned char **, unsigned char **, unsigned char **,
-                      int *, int *, int *, int *, int *, int *);
-  void getXColorTable(XColor **, int *);
-  void getGradientBuffers(unsigned int, unsigned int,
-                          unsigned int **, unsigned int **);
-  void setDither(Bool d) { dither = d; }
-  void setColorsPerChannel(int);
-  void parseTexture(BTexture *, const char *);
-  void parseColor(BColor *, const char * = 0);
-
-  virtual void timeout(void);
-};
-
-
-#endif // __Image_hh
-
diff --git a/src/Image.hh b/src/Image.hh
new file mode 100644 (file)
index 0000000..4d72bc1
--- /dev/null
@@ -0,0 +1,179 @@
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Image.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef   __Image_hh
+#define   __Image_hh
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+}
+
+#include <list>
+
+#include "Timer.hh"
+#include "BaseDisplay.hh"
+#include "Color.hh"
+
+class BImageControl;
+class BTexture;
+class BImageCache;
+
+class BImage {
+private:
+  BImageControl *control;
+  bool interlaced;
+  XColor *colors;
+
+  BColor from, to;
+  int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits,
+    ncolors, cpc, cpccpc;
+  unsigned char *red, *green, *blue, *red_table, *green_table, *blue_table;
+  unsigned int width, height, *xtable, *ytable;
+
+  void TrueColorDither(unsigned int bit_depth, int bytes_per_line,
+                      unsigned char *pixel_data);
+  void PseudoColorDither(int bytes_per_line, unsigned char *pixel_data);
+#ifdef ORDEREDPSEUDO
+  void OrderedPseudoColorDither(int bytes_per_line, unsigned char *pixel_data);
+#endif
+
+  Pixmap renderPixmap(void);
+
+  XImage *renderXImage(void);
+
+  void invert(void);
+  void bevel1(void);
+  void bevel2(void);
+  void dgradient(void);
+  void egradient(void);
+  void hgradient(void);
+  void pgradient(void);
+  void rgradient(void);
+  void vgradient(void);
+  void cdgradient(void);
+  void pcgradient(void);
+
+
+public:
+  BImage(BImageControl *c, unsigned int w, unsigned int h);
+  ~BImage(void);
+
+  Pixmap render(const BTexture &texture);
+  Pixmap render_solid(const BTexture &texture);
+  Pixmap render_gradient(const BTexture &texture);
+
+  // static methods for the builtin cache
+  static unsigned long maximumCacheSize(void);
+  static void setMaximumCacheSize(const unsigned long cache_max);
+
+  static unsigned long cacheTimeout(void);
+  static void setCacheTimeout(const unsigned long cache_timeout);
+
+private:
+  // global image cache
+  static BImageCache *imagecache;
+};
+
+
+class BImageControl : public TimeoutHandler {
+public:
+  struct CachedImage {
+    Pixmap pixmap;
+
+    unsigned int count, width, height;
+    unsigned long pixel1, pixel2, texture;
+  };
+
+  BImageControl(BaseDisplay *dpy, const ScreenInfo *scrn,
+                bool _dither= False, int _cpc = 4,
+                unsigned long cache_timeout = 300000l,
+                unsigned long cmax = 200l);
+  virtual ~BImageControl(void);
+
+  inline BaseDisplay *getBaseDisplay(void) const { return basedisplay; }
+
+  inline bool doDither(void) { return dither; }
+
+  inline const ScreenInfo *getScreenInfo(void) { return screeninfo; }
+
+  inline Window getDrawable(void) const { return window; }
+
+  inline Visual *getVisual(void) { return screeninfo->getVisual(); }
+
+  inline int getBitsPerPixel(void) const { return bits_per_pixel; }
+  inline int getDepth(void) const { return screen_depth; }
+  inline int getColorsPerChannel(void) const
+    { return colors_per_channel; }
+
+  unsigned long getSqrt(unsigned int x);
+
+  Pixmap renderImage(unsigned int width, unsigned int height,
+                     const BTexture &texture);
+
+  void installRootColormap(void);
+  void removeImage(Pixmap pixmap);
+  void getColorTables(unsigned char **rmt, unsigned char **gmt,
+                      unsigned char **bmt,
+                      int *roff, int *goff, int *boff,
+                      int *rbit, int *gbit, int *bbit);
+  void getXColorTable(XColor **c, int *n);
+  void getGradientBuffers(unsigned int w, unsigned int h,
+                          unsigned int **xbuf, unsigned int **ybuf);
+  void setDither(bool d) { dither = d; }
+  void setColorsPerChannel(int cpc);
+
+  virtual void timeout(void);
+
+private:
+  bool dither;
+  BaseDisplay *basedisplay;
+  const ScreenInfo *screeninfo;
+#ifdef    TIMEDCACHE
+  BTimer *timer;
+#endif // TIMEDCACHE
+
+  Colormap colormap;
+
+  Window window;
+  XColor *colors;
+  int colors_per_channel, ncolors, screen_number, screen_depth,
+    bits_per_pixel, red_offset, green_offset, blue_offset,
+    red_bits, green_bits, blue_bits;
+  unsigned char red_color_table[256], green_color_table[256],
+    blue_color_table[256];
+  unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width,
+    grad_buffer_height;
+  unsigned long *sqrt_table, cache_max;
+
+  typedef std::list<CachedImage> CacheContainer;
+  CacheContainer cache;
+
+  Pixmap searchCache(const unsigned int width, const unsigned int height,
+                     const unsigned long texture,
+                     const BColor &c1, const BColor &c2);
+};
+
+
+#endif // __Image_hh
+
diff --git a/src/ImageControl.cc b/src/ImageControl.cc
new file mode 100644 (file)
index 0000000..eed9773
--- /dev/null
@@ -0,0 +1,604 @@
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// ImageControl.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifdef    HAVE_CONFIG_H
+#  include "../config.h"
+#endif // HAVE_CONFIG_H
+
+extern "C" {
+#ifdef    HAVE_STDIO_H
+#  include <stdio.h>
+#endif // HAVE_STDIO_H
+
+#ifdef    HAVE_CTYPE_H
+#  include <ctype.h>
+#endif // HAVE_CTYPE_H
+
+#include <X11/Xlib.h>
+}
+
+#include <algorithm>
+
+#include "blackbox.hh"
+#include "i18n.hh"
+#include "BaseDisplay.hh"
+#include "Color.hh"
+#include "Image.hh"
+#include "Texture.hh"
+
+static unsigned long bsqrt(unsigned long x) {
+  if (x <= 0) return 0;
+  if (x == 1) return 1;
+
+  unsigned long r = x >> 1;
+  unsigned long q;
+
+  while (1) {
+    q = x / r;
+    if (q >= r) return r;
+    r = (r + q) >> 1;
+  }
+}
+
+BImageControl *ctrl = 0;
+
+BImageControl::BImageControl(BaseDisplay *dpy, const ScreenInfo *scrn,
+                             bool _dither, int _cpc,
+                             unsigned long cache_timeout,
+                             unsigned long cmax)
+{
+  if (! ctrl) ctrl = this;
+
+  basedisplay = dpy;
+  screeninfo = scrn;
+  setDither(_dither);
+  setColorsPerChannel(_cpc);
+
+  cache_max = cmax;
+#ifdef    TIMEDCACHE
+  if (cache_timeout) {
+    timer = new BTimer(basedisplay, this);
+    timer->setTimeout(cache_timeout);
+    timer->start();
+  } else {
+    timer = (BTimer *) 0;
+  }
+#endif // TIMEDCACHE
+
+  colors = (XColor *) 0;
+  ncolors = 0;
+
+  grad_xbuffer = grad_ybuffer = (unsigned int *) 0;
+  grad_buffer_width = grad_buffer_height = 0;
+
+  sqrt_table = (unsigned long *) 0;
+
+  screen_depth = screeninfo->getDepth();
+  window = screeninfo->getRootWindow();
+  screen_number = screeninfo->getScreenNumber();
+  colormap = screeninfo->getColormap();
+
+  int count;
+  XPixmapFormatValues *pmv = XListPixmapFormats(basedisplay->getXDisplay(),
+                                                &count);
+  if (pmv) {
+    bits_per_pixel = 0;
+    for (int i = 0; i < count; i++)
+      if (pmv[i].depth == screen_depth) {
+       bits_per_pixel = pmv[i].bits_per_pixel;
+       break;
+      }
+
+    XFree(pmv);
+  }
+
+  if (bits_per_pixel == 0) bits_per_pixel = screen_depth;
+  if (bits_per_pixel >= 24) setDither(False);
+
+  red_offset = green_offset = blue_offset = 0;
+
+  switch (getVisual()->c_class) {
+  case TrueColor: {
+    int i;
+
+    // compute color tables
+    unsigned long red_mask = getVisual()->red_mask,
+      green_mask = getVisual()->green_mask,
+      blue_mask = getVisual()->blue_mask;
+
+    while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; }
+    while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; }
+    while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; }
+
+    red_bits = 255 / red_mask;
+    green_bits = 255 / green_mask;
+    blue_bits = 255 / blue_mask;
+
+    for (i = 0; i < 256; i++) {
+      red_color_table[i] = i / red_bits;
+      green_color_table[i] = i / green_bits;
+      blue_color_table[i] = i / blue_bits;
+    }
+    break;
+  }
+
+  case PseudoColor:
+  case StaticColor: {
+    ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
+
+    if (ncolors > (1 << screen_depth)) {
+      colors_per_channel = (1 << screen_depth) / 3;
+      ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
+    }
+
+    if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
+      fprintf(stderr,
+             i18n(ImageSet, ImageInvalidColormapSize,
+                   "BImageControl::BImageControl: invalid colormap size %d "
+                   "(%d/%d/%d) - reducing"),
+             ncolors, colors_per_channel, colors_per_channel,
+             colors_per_channel);
+
+      colors_per_channel = (1 << screen_depth) / 3;
+    }
+
+    colors = new XColor[ncolors];
+    if (! colors) {
+      fprintf(stderr, i18n(ImageSet, ImageErrorAllocatingColormap,
+                           "BImageControl::BImageControl: error allocating "
+                           "colormap\n"));
+      exit(1);
+    }
+
+    int i = 0, ii, p, r, g, b,
+
+#ifdef ORDEREDPSEUDO
+      bits = 256 / colors_per_channel;
+#else // !ORDEREDPSEUDO
+    bits = 255 / (colors_per_channel - 1);
+#endif // ORDEREDPSEUDO
+
+    red_bits = green_bits = blue_bits = bits;
+
+    for (i = 0; i < 256; i++)
+      red_color_table[i] = green_color_table[i] = blue_color_table[i] =
+       i / bits;
+
+    for (r = 0, i = 0; r < colors_per_channel; r++)
+      for (g = 0; g < colors_per_channel; g++)
+       for (b = 0; b < colors_per_channel; b++, i++) {
+         colors[i].red = (r * 0xffff) / (colors_per_channel - 1);
+         colors[i].green = (g * 0xffff) / (colors_per_channel - 1);
+         colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);;
+         colors[i].flags = DoRed|DoGreen|DoBlue;
+       }
+
+    for (i = 0; i < ncolors; i++) {
+      if (! XAllocColor(basedisplay->getXDisplay(), colormap, &colors[i])) {
+       fprintf(stderr, i18n(ImageSet, ImageColorAllocFail,
+                             "couldn't alloc color %i %i %i\n"),
+               colors[i].red, colors[i].green, colors[i].blue);
+       colors[i].flags = 0;
+      } else {
+       colors[i].flags = DoRed|DoGreen|DoBlue;
+      }
+    }
+
+    XColor icolors[256];
+    int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth));
+
+    for (i = 0; i < incolors; i++)
+      icolors[i].pixel = i;
+
+    XQueryColors(basedisplay->getXDisplay(), colormap, icolors, incolors);
+    for (i = 0; i < ncolors; i++) {
+      if (! colors[i].flags) {
+       unsigned long chk = 0xffffffff, pixel, close = 0;
+
+       p = 2;
+       while (p--) {
+         for (ii = 0; ii < incolors; ii++) {
+           r = (colors[i].red - icolors[i].red) >> 8;
+           g = (colors[i].green - icolors[i].green) >> 8;
+           b = (colors[i].blue - icolors[i].blue) >> 8;
+           pixel = (r * r) + (g * g) + (b * b);
+
+           if (pixel < chk) {
+             chk = pixel;
+             close = ii;
+           }
+
+           colors[i].red = icolors[close].red;
+           colors[i].green = icolors[close].green;
+           colors[i].blue = icolors[close].blue;
+
+           if (XAllocColor(basedisplay->getXDisplay(), colormap,
+                           &colors[i])) {
+             colors[i].flags = DoRed|DoGreen|DoBlue;
+             break;
+           }
+         }
+       }
+      }
+    }
+
+    break;
+  }
+
+  case GrayScale:
+  case StaticGray: {
+    if (getVisual()->c_class == StaticGray) {
+      ncolors = 1 << screen_depth;
+    } else {
+      ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
+
+      if (ncolors > (1 << screen_depth)) {
+       colors_per_channel = (1 << screen_depth) / 3;
+       ncolors =
+         colors_per_channel * colors_per_channel * colors_per_channel;
+      }
+    }
+
+    if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
+      fprintf(stderr,
+              i18n(ImageSet, ImageInvalidColormapSize,
+                  "BImageControl::BImageControl: invalid colormap size %d "
+                   "(%d/%d/%d) - reducing"),
+             ncolors, colors_per_channel, colors_per_channel,
+             colors_per_channel);
+
+      colors_per_channel = (1 << screen_depth) / 3;
+    }
+
+    colors = new XColor[ncolors];
+    if (! colors) {
+      fprintf(stderr,
+              i18n(ImageSet, ImageErrorAllocatingColormap,
+                 "BImageControl::BImageControl: error allocating colormap\n"));
+      exit(1);
+    }
+
+    int i = 0, ii, p, bits = 255 / (colors_per_channel - 1);
+    red_bits = green_bits = blue_bits = bits;
+
+    for (i = 0; i < 256; i++)
+      red_color_table[i] = green_color_table[i] = blue_color_table[i] =
+       i / bits;
+
+    for (i = 0; i < ncolors; i++) {
+      colors[i].red = (i * 0xffff) / (colors_per_channel - 1);
+      colors[i].green = (i * 0xffff) / (colors_per_channel - 1);
+      colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);;
+      colors[i].flags = DoRed|DoGreen|DoBlue;
+
+      if (! XAllocColor(basedisplay->getXDisplay(), colormap,
+                       &colors[i])) {
+       fprintf(stderr, i18n(ImageSet, ImageColorAllocFail,
+                            "couldn't alloc color %i %i %i\n"),
+               colors[i].red, colors[i].green, colors[i].blue);
+       colors[i].flags = 0;
+      } else {
+       colors[i].flags = DoRed|DoGreen|DoBlue;
+      }
+    }
+
+    XColor icolors[256];
+    int incolors = (((1 << screen_depth) > 256) ? 256 :
+                   (1 << screen_depth));
+
+    for (i = 0; i < incolors; i++)
+      icolors[i].pixel = i;
+
+    XQueryColors(basedisplay->getXDisplay(), colormap, icolors, incolors);
+    for (i = 0; i < ncolors; i++) {
+      if (! colors[i].flags) {
+       unsigned long chk = 0xffffffff, pixel, close = 0;
+
+       p = 2;
+       while (p--) {
+         for (ii = 0; ii < incolors; ii++) {
+           int r = (colors[i].red - icolors[i].red) >> 8;
+           int g = (colors[i].green - icolors[i].green) >> 8;
+           int b = (colors[i].blue - icolors[i].blue) >> 8;
+           pixel = (r * r) + (g * g) + (b * b);
+
+           if (pixel < chk) {
+             chk = pixel;
+             close = ii;
+           }
+
+           colors[i].red = icolors[close].red;
+           colors[i].green = icolors[close].green;
+           colors[i].blue = icolors[close].blue;
+
+           if (XAllocColor(basedisplay->getXDisplay(), colormap,
+                           &colors[i])) {
+             colors[i].flags = DoRed|DoGreen|DoBlue;
+             break;
+           }
+         }
+       }
+      }
+    }
+
+    break;
+  }
+
+  default:
+    fprintf(stderr,
+            i18n(ImageSet, ImageUnsupVisual,
+                 "BImageControl::BImageControl: unsupported visual %d\n"),
+           getVisual()->c_class);
+    exit(1);
+  }
+}
+
+
+BImageControl::~BImageControl(void) {
+  delete [] sqrt_table;
+
+  delete [] grad_xbuffer;
+
+  delete [] grad_ybuffer;
+
+  if (colors) {
+    unsigned long *pixels = new unsigned long [ncolors];
+
+    int i;
+    for (i = 0; i < ncolors; i++)
+      *(pixels + i) = (*(colors + i)).pixel;
+
+    XFreeColors(basedisplay->getXDisplay(), colormap, pixels, ncolors, 0);
+
+    delete [] colors;
+  }
+
+  if (!cache.empty()) {
+    //#ifdef DEBUG
+    fprintf(stderr, i18n(ImageSet, ImagePixmapRelease,
+                        "BImageContol::~BImageControl: pixmap cache - "
+                        "releasing %d pixmaps\n"), cache.size());
+    //#endif
+    CacheContainer::iterator it = cache.begin();
+    const CacheContainer::iterator end = cache.end();
+    for (; it != end; ++it) {
+      XFreePixmap(basedisplay->getXDisplay(), (*it).pixmap);
+    }
+  }
+#ifdef    TIMEDCACHE
+  if (timer) {
+    timer->stop();
+    delete timer;
+  }
+#endif // TIMEDCACHE
+}
+
+
+Pixmap BImageControl::searchCache(const unsigned int width,
+                                  const unsigned int height,
+                                  const unsigned long texture,
+                                  const BColor &c1, const BColor &c2) {
+  if (cache.empty())
+    return None;
+
+  CacheContainer::iterator it = cache.begin();
+  const CacheContainer::iterator end = cache.end();
+  for (; it != end; ++it) {
+    CachedImage& tmp = *it;
+    if ((tmp.width == width) && (tmp.height == height) &&
+        (tmp.texture == texture) && (tmp.pixel1 == c1.pixel()))
+      if (texture & BTexture::Gradient) {
+        if (tmp.pixel2 == c2.pixel()) {
+          tmp.count++;
+          return tmp.pixmap;
+        }
+      } else {
+        tmp.count++;
+        return tmp.pixmap;
+      }
+  }
+  return None;
+}
+
+
+Pixmap BImageControl::renderImage(unsigned int width, unsigned int height,
+                                  const BTexture &texture) {
+  if (texture.texture() & BTexture::Parent_Relative) return ParentRelative;
+
+  Pixmap pixmap = searchCache(width, height, texture.texture(),
+                             texture.color(), texture.colorTo());
+  if (pixmap) return pixmap;
+
+  BImage image(this, width, height);
+  pixmap = image.render(texture);
+
+  if (!pixmap)
+    return None;
+
+  CachedImage tmp;
+
+  tmp.pixmap = pixmap;
+  tmp.width = width;
+  tmp.height = height;
+  tmp.count = 1;
+  tmp.texture = texture.texture();
+  tmp.pixel1 = texture.color().pixel();
+
+  if (texture.texture() & BTexture::Gradient)
+    tmp.pixel2 = texture.colorTo().pixel();
+  else
+    tmp.pixel2 = 0l;
+
+  cache.push_back(tmp);
+
+  if (cache.size() > cache_max) {
+#ifdef    DEBUG
+    fprintf(stderr, i18n(ImageSet, ImagePixmapCacheLarge,
+                        "BImageControl::renderImage: cache is large, "
+                        "forcing cleanout\n"));
+#endif // DEBUG
+
+    timeout();
+  }
+
+  return pixmap;
+}
+
+
+void BImageControl::removeImage(Pixmap pixmap) {
+  if (!pixmap)
+    return;
+
+  CacheContainer::iterator it = cache.begin();
+  const CacheContainer::iterator end = cache.end();
+  for (; it != end; ++it) {
+    CachedImage &tmp = *it;
+    if (tmp.pixmap == pixmap && tmp.count > 0)
+      tmp.count--;
+  }
+
+#ifdef    TIMEDCACHE
+  if (! timer)
+#endif // TIMEDCACHE
+    timeout();
+}
+
+
+void BImageControl::getColorTables(unsigned char **rmt, unsigned char **gmt,
+                                  unsigned char **bmt,
+                                  int *roff, int *goff, int *boff,
+                                   int *rbit, int *gbit, int *bbit) {
+  if (rmt) *rmt = red_color_table;
+  if (gmt) *gmt = green_color_table;
+  if (bmt) *bmt = blue_color_table;
+
+  if (roff) *roff = red_offset;
+  if (goff) *goff = green_offset;
+  if (boff) *boff = blue_offset;
+
+  if (rbit) *rbit = red_bits;
+  if (gbit) *gbit = green_bits;
+  if (bbit) *bbit = blue_bits;
+}
+
+
+void BImageControl::getXColorTable(XColor **c, int *n) {
+  if (c) *c = colors;
+  if (n) *n = ncolors;
+}
+
+
+void BImageControl::getGradientBuffers(unsigned int w,
+                                      unsigned int h,
+                                      unsigned int **xbuf,
+                                      unsigned int **ybuf)
+{
+  if (w > grad_buffer_width) {
+    if (grad_xbuffer) {
+      delete [] grad_xbuffer;
+    }
+
+    grad_buffer_width = w;
+
+    grad_xbuffer = new unsigned int[grad_buffer_width * 3];
+  }
+
+  if (h > grad_buffer_height) {
+    if (grad_ybuffer) {
+      delete [] grad_ybuffer;
+    }
+
+    grad_buffer_height = h;
+
+    grad_ybuffer = new unsigned int[grad_buffer_height * 3];
+  }
+
+  *xbuf = grad_xbuffer;
+  *ybuf = grad_ybuffer;
+}
+
+
+void BImageControl::installRootColormap(void) {
+  int ncmap = 0;
+  Colormap *cmaps =
+    XListInstalledColormaps(basedisplay->getXDisplay(), window, &ncmap);
+
+  if (cmaps) {
+    bool install = True;
+    for (int i = 0; i < ncmap; i++)
+      if (*(cmaps + i) == colormap)
+       install = False;
+
+    if (install)
+      XInstallColormap(basedisplay->getXDisplay(), colormap);
+
+    XFree(cmaps);
+  }
+}
+
+
+void BImageControl::setColorsPerChannel(int cpc) {
+  if (cpc < 2) cpc = 2;
+  if (cpc > 6) cpc = 6;
+
+  colors_per_channel = cpc;
+}
+
+
+unsigned long BImageControl::getSqrt(unsigned int x) {
+  if (! sqrt_table) {
+    // build sqrt table for use with elliptic gradient
+
+    sqrt_table = new unsigned long[(256 * 256 * 2) + 1];
+
+    for (int i = 0; i < (256 * 256 * 2); i++)
+      *(sqrt_table + i) = bsqrt(i);
+  }
+
+  return (*(sqrt_table + x));
+}
+
+
+struct ZeroRefCheck {
+  inline bool operator()(const BImageControl::CachedImage &image) const {
+    return (image.count == 0);
+  }
+};
+
+struct CacheCleaner {
+  Display *display;
+  ZeroRefCheck ref_check;
+  CacheCleaner(Display *d): display(d) {}
+  inline void operator()(const BImageControl::CachedImage& image) const {
+    if (ref_check(image))
+      XFreePixmap(display, image.pixmap);
+  }
+};
+
+
+void BImageControl::timeout(void) {
+  CacheCleaner cleaner(basedisplay->getXDisplay());
+  std::for_each(cache.begin(), cache.end(), cleaner);
+  cache.remove_if(cleaner.ref_check);
+}
+
index 2f695aa6c779fd0f4c6fb61367d95f10432132ac..8cccea6110ba787434231f7b18556e220391d2a5 100644 (file)
@@ -1,4 +1,4 @@
-# src/Makefile.am for Openbox
+# src/Makefile.am for Blackbox - an X11 Window manager
 # Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # DEALINGS IN THE SOFTWARE.
 
 DEFAULT_MENU=$(pkgdatadir)/menu
-DEFAULT_STYLE=$(pkgdatadir)/styles/steelblue
+DEFAULT_STYLE=$(pkgdatadir)/styles/Results
 
-CPPFLAGS= @CPPFLAGS@ @SHAPE@ @SLIT@ @INTERLACE@ @ORDEREDPSEUDO@ \
-@DEBUG@ @NEWWMSPEC@ @NLS@ @TIMEDCACHE@ @CLOBBER@ \
+CPPFLAGS= @CPPFLAGS@ @SHAPE@ @ORDEREDPSEUDO@ \
+@DEBUG@ @NLS@ @TIMEDCACHE@ @SLIT@ @CLOBBER@ \
 -DLOCALEPATH=\"$(pkgdatadir)/nls\" \
 -DDEFAULTMENU=\"$(DEFAULT_MENU)\" \
 -DDEFAULTSTYLE=\"$(DEFAULT_STYLE)\"
 
-bin_PROGRAMS= openbox
+bin_PROGRAMS= blackbox
 
-openbox_SOURCES= BaseDisplay.cc Basemenu.cc Clientmenu.cc Configmenu.cc Geometry.cc Iconmenu.cc Image.cc Netizen.cc Resource.cc Rootmenu.cc Screen.cc Slit.cc Timer.cc Toolbar.cc Window.cc Windowmenu.cc Workspace.cc Workspacemenu.cc XAtom.cc openbox.cc bsd-snprintf.c i18n.cc main.cc
+blackbox_SOURCES= BaseDisplay.cc Basemenu.cc Clientmenu.cc Color.cc Configmenu.cc GCCache.cc Iconmenu.cc Image.cc ImageControl.cc Netizen.cc Rootmenu.cc Screen.cc Slit.cc Texture.cc Timer.cc Toolbar.cc Util.cc Window.cc Windowmenu.cc Workspace.cc Workspacemenu.cc blackbox.cc i18n.cc main.cc
 
 MAINTAINERCLEANFILES= Makefile.in
 
@@ -39,74 +39,87 @@ distclean-local:
 
 # local dependencies
 
-BaseDisplay.o: BaseDisplay.cc i18n.h BaseDisplay.h \
- Timer.h
-Basemenu.o: Basemenu.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Iconmenu.h Basemenu.h \
- Windowmenu.h Slit.h Screen.h Configmenu.h Netizen.h Rootmenu.h \
- Workspace.h Workspacemenu.h Resource.h
-Clientmenu.o: Clientmenu.cc openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \
- Clientmenu.h Workspace.h Screen.h Configmenu.h Netizen.h \
- Rootmenu.h Workspacemenu.h Resource.h Geometry.h
-Configmenu.o: Configmenu.cc i18n.h Configmenu.h Basemenu.h \
- Screen.h BaseDisplay.h Timer.h Iconmenu.h Netizen.h \
- Rootmenu.h Workspace.h Workspacemenu.h openbox.h Image.h \
- Window.h Windowmenu.h Slit.h Toolbar.h Resource.h Geometry.h
-Geometry.o: Geometry.cc Geometry.h
-Icon.o: Iconmenu.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \
- Screen.h Configmenu.h Netizen.h Rootmenu.h Workspace.h \
- Workspacemenu.h Toolbar.h Resource.h Geometry.h
-Image.o: Image.cc i18n.h BaseDisplay.h Timer.h \
- Image.h
-Netizen.o: Netizen.cc Netizen.h BaseDisplay.h Timer.h \
- Screen.h Configmenu.h Basemenu.h openbox.h Image.h Window.h \
- Iconmenu.h Windowmenu.h Slit.h Rootmenu.h Workspace.h \
- Workspacemenu.h Resource.h Geometry.h
-Resource.o: Resource.cc Resource.h Util.h
-Rootmenu.o: Rootmenu.cc openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \
- Rootmenu.h Screen.h Configmenu.h Netizen.h Workspace.h \
- Workspacemenu.h Resource.h Geometry.h
-Screen.o: Screen.cc i18n.h bsd-snprintf.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h \
- Windowmenu.h Slit.h Clientmenu.h Workspace.h Screen.h Configmenu.h \
- Netizen.h Rootmenu.h Workspacemenu.h Toolbar.h Resource.h Geometry.h
-Slit.o: Slit.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \
- Screen.h Configmenu.h Netizen.h Rootmenu.h Workspace.h \
- Workspacemenu.h Toolbar.h Resource.h Geometry.h
-Timer.o: Timer.cc BaseDisplay.h Timer.h
-Toolbar.o: Toolbar.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \
- Clientmenu.h Workspace.h Rootmenu.h Screen.h Configmenu.h \
- Netizen.h Workspacemenu.h Toolbar.h Resource.h Geometry.h
-XAtom.o: XAtom.cc XAtom.h Geometry.h Util.h
-Window.o: Window.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \
- Screen.h Configmenu.h Netizen.h Rootmenu.h Workspace.h \
- Workspacemenu.h Toolbar.h Resource.h Geometry.h
-Windowmenu.o: Windowmenu.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h \
- Windowmenu.h Slit.h Screen.h Configmenu.h Netizen.h Rootmenu.h \
- Workspace.h Workspacemenu.h Resource.h Geometry.h
-Workspace.o: Workspace.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h \
- Windowmenu.h Slit.h Clientmenu.h Workspace.h Screen.h \
- Configmenu.h Netizen.h Rootmenu.h Workspacemenu.h Toolbar.h Resource.h \
- Geometry.h Geometry.h Util.h
-Workspacemenu.o: Workspacemenu.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h \
- Windowmenu.h Slit.h Screen.h Configmenu.h Netizen.h Rootmenu.h \
- Workspace.h Workspacemenu.h Toolbar.h Resource.h Geometry.h
-openbox.o: openbox.cc i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h \
- Windowmenu.h Slit.h Clientmenu.h Workspace.h Rootmenu.h \
- Screen.h Configmenu.h Netizen.h Workspacemenu.h Toolbar.h Resource.h \
- Geometry.h Util.h
-bsd-snprintf.o: bsd-snprintf.c bsd-snprintf.h
-i18n.o: i18n.cc i18n.h
-main.o: main.cc ../version.h i18n.h openbox.h BaseDisplay.h \
- Timer.h Image.h Window.h Iconmenu.h Basemenu.h \
- Windowmenu.h Slit.h Resource.h Geometry.h
+BaseDisplay.o: BaseDisplay.cc ../config.h i18n.hh \
+ ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh GCCache.hh Color.hh \
+ Util.hh
+Basemenu.o: Basemenu.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ blackbox.hh BaseDisplay.hh Timer.hh Basemenu.hh GCCache.hh Color.hh \
+ Image.hh Screen.hh Texture.hh Util.hh Configmenu.hh Iconmenu.hh \
+ Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh
+Clientmenu.o: Clientmenu.cc ../config.h blackbox.hh i18n.hh \
+ ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh Clientmenu.hh \
+ Basemenu.hh Screen.hh Color.hh Texture.hh Util.hh Configmenu.hh \
+ Iconmenu.hh Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh \
+ Window.hh Windowmenu.hh
+Color.o: Color.cc ../config.h Color.hh BaseDisplay.hh Timer.hh
+Configmenu.o: Configmenu.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ Configmenu.hh Basemenu.hh Image.hh Timer.hh BaseDisplay.hh Color.hh \
+ Toolbar.hh Screen.hh Texture.hh Util.hh Iconmenu.hh Netizen.hh \
+ Rootmenu.hh Workspace.hh Workspacemenu.hh blackbox.hh Window.hh \
+ Windowmenu.hh
+GCCache.o: GCCache.cc ../config.h GCCache.hh BaseDisplay.hh Timer.hh \
+ Color.hh Util.hh
+Iconmenu.o: Iconmenu.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ Iconmenu.hh Basemenu.hh Screen.hh Color.hh Texture.hh Util.hh \
+ Configmenu.hh Netizen.hh Rootmenu.hh Timer.hh Workspace.hh \
+ Workspacemenu.hh blackbox.hh BaseDisplay.hh Window.hh Windowmenu.hh
+Image.o: Image.cc ../config.h blackbox.hh i18n.hh \
+ ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh GCCache.hh Color.hh \
+ Image.hh Texture.hh Util.hh
+ImageControl.o: ImageControl.cc ../config.h blackbox.hh i18n.hh \
+ ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh Color.hh Image.hh \
+ Texture.hh Util.hh
+Netizen.o: Netizen.cc ../config.h Netizen.hh Screen.hh Color.hh \
+ Texture.hh Util.hh Configmenu.hh Basemenu.hh Iconmenu.hh Rootmenu.hh \
+ Timer.hh Workspace.hh Workspacemenu.hh blackbox.hh i18n.hh \
+ ../nls/blackbox-nls.hh BaseDisplay.hh
+Rootmenu.o: Rootmenu.cc ../config.h blackbox.hh i18n.hh \
+ ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh Rootmenu.hh \
+ Basemenu.hh Screen.hh Color.hh Texture.hh Util.hh Configmenu.hh \
+ Iconmenu.hh Netizen.hh Workspace.hh Workspacemenu.hh
+Screen.o: Screen.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ blackbox.hh BaseDisplay.hh Timer.hh Clientmenu.hh Basemenu.hh \
+ GCCache.hh Color.hh Iconmenu.hh Image.hh Screen.hh Texture.hh Util.hh \
+ Configmenu.hh Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh \
+ Slit.hh Toolbar.hh Window.hh Windowmenu.hh
+Slit.o: Slit.cc ../config.h i18n.hh ../nls/blackbox-nls.hh blackbox.hh \
+ BaseDisplay.hh Timer.hh Image.hh Color.hh Screen.hh Texture.hh \
+ Util.hh Configmenu.hh Basemenu.hh Iconmenu.hh Netizen.hh Rootmenu.hh \
+ Workspace.hh Workspacemenu.hh Slit.hh Toolbar.hh
+Texture.o: Texture.cc ../config.h Texture.hh Color.hh Util.hh \
+ BaseDisplay.hh Timer.hh Image.hh Screen.hh Configmenu.hh Basemenu.hh \
+ Iconmenu.hh Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh \
+ blackbox.hh i18n.hh ../nls/blackbox-nls.hh
+Timer.o: Timer.cc ../config.h BaseDisplay.hh Timer.hh Util.hh
+Toolbar.o: Toolbar.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ blackbox.hh BaseDisplay.hh Timer.hh Clientmenu.hh Basemenu.hh \
+ GCCache.hh Color.hh Iconmenu.hh Image.hh Rootmenu.hh Screen.hh \
+ Texture.hh Util.hh Configmenu.hh Netizen.hh Workspace.hh \
+ Workspacemenu.hh Toolbar.hh Window.hh Windowmenu.hh Slit.hh
+Util.o: Util.cc ../config.h Util.hh
+Window.o: Window.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ blackbox.hh BaseDisplay.hh Timer.hh GCCache.hh Color.hh Iconmenu.hh \
+ Basemenu.hh Image.hh Screen.hh Texture.hh Util.hh Configmenu.hh \
+ Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh Toolbar.hh \
+ Window.hh Windowmenu.hh Slit.hh
+Windowmenu.o: Windowmenu.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ blackbox.hh BaseDisplay.hh Timer.hh Screen.hh Color.hh Texture.hh \
+ Util.hh Configmenu.hh Basemenu.hh Iconmenu.hh Netizen.hh Rootmenu.hh \
+ Workspace.hh Workspacemenu.hh Window.hh Windowmenu.hh
+Workspace.o: Workspace.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ blackbox.hh BaseDisplay.hh Timer.hh Clientmenu.hh Basemenu.hh \
+ Netizen.hh Screen.hh Color.hh Texture.hh Util.hh Configmenu.hh \
+ Iconmenu.hh Rootmenu.hh Workspace.hh Workspacemenu.hh Toolbar.hh \
+ Window.hh Windowmenu.hh
+Workspacemenu.o: Workspacemenu.cc ../config.h i18n.hh \
+ ../nls/blackbox-nls.hh blackbox.hh BaseDisplay.hh Timer.hh Screen.hh \
+ Color.hh Texture.hh Util.hh Configmenu.hh Basemenu.hh Iconmenu.hh \
+ Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh Toolbar.hh
+blackbox.o: blackbox.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \
+ blackbox.hh BaseDisplay.hh Timer.hh Basemenu.hh Clientmenu.hh \
+ GCCache.hh Color.hh Image.hh Rootmenu.hh Screen.hh Texture.hh Util.hh \
+ Configmenu.hh Iconmenu.hh Netizen.hh Workspace.hh Workspacemenu.hh \
+ Slit.hh Toolbar.hh Window.hh Windowmenu.hh
+i18n.o: i18n.cc ../config.h i18n.hh ../nls/blackbox-nls.hh
+main.o: main.cc ../version.h ../config.h i18n.hh \
+ ../nls/blackbox-nls.hh blackbox.hh BaseDisplay.hh Timer.hh
index 6fbb99acc33eae58ecbe50f37b5e390f5d16c2fa..6d73be95e8cd269dfe762ef895a17d9b0a83e404 100644 (file)
@@ -1,4 +1,5 @@
-// Netizen.cc for Openbox
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Netizen.cc for Blackbox - An X11 Window Manager
 // Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "Netizen.h"
-#include "Screen.h"
+#include "Netizen.hh"
+#include "Screen.hh"
+
+Netizen::Netizen(BScreen *scr, Window win) {
+  screen = scr;
+  blackbox = scr->getBlackbox();
+  window = win;
 
-Netizen::Netizen(BScreen &scr, Window win) :basedisplay(scr.getBaseDisplay()),
-  screen(scr), window(win)
-{
   event.type = ClientMessage;
-  event.xclient.message_type = basedisplay.getOpenboxStructureMessagesAtom();
-  event.xclient.display = basedisplay.getXDisplay();
+  event.xclient.message_type =
+    blackbox->getBlackboxStructureMessagesAtom();
+  event.xclient.display = blackbox->getXDisplay();
   event.xclient.window = window;
   event.xclient.format = 32;
-  event.xclient.data.l[0] = basedisplay.getOpenboxNotifyStartupAtom();
+  event.xclient.data.l[0] = blackbox->getBlackboxNotifyStartupAtom();
   event.xclient.data.l[1] = event.xclient.data.l[2] =
     event.xclient.data.l[3] = event.xclient.data.l[4] = 0l;
 
-  XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event);
+  XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event);
 }
 
 
 void Netizen::sendWorkspaceCount(void) {
-  event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWorkspaceCountAtom();
-  event.xclient.data.l[1] = screen.getWorkspaceCount();
+  event.xclient.data.l[0] =
+    blackbox->getBlackboxNotifyWorkspaceCountAtom();
+  event.xclient.data.l[1] = screen->getWorkspaceCount();
 
-  XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event);
+  XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event);
 }
 
 
 void Netizen::sendCurrentWorkspace(void) {
-  event.xclient.data.l[0] = basedisplay.getOpenboxNotifyCurrentWorkspaceAtom();
-  event.xclient.data.l[1] = screen.getCurrentWorkspaceID();
+  event.xclient.data.l[0] =
+    blackbox->getBlackboxNotifyCurrentWorkspaceAtom();
+  event.xclient.data.l[1] = screen->getCurrentWorkspaceID();
 
-  XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event);
+  XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event);
 }
 
 
 void Netizen::sendWindowFocus(Window w) {
-  event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowFocusAtom();
+  event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowFocusAtom();
   event.xclient.data.l[1] = w;
 
-  XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event);
+  XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event);
 }
 
 
 void Netizen::sendWindowAdd(Window w, unsigned long p) {
-  event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowAddAtom();
+  event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowAddAtom();
   event.xclient.data.l[1] = w;
   event.xclient.data.l[2] = p;
 
-  XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event);
+  XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event);
 
   event.xclient.data.l[2] = 0l;
 }
 
 
 void Netizen::sendWindowDel(Window w) {
-  event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowDelAtom();
+  event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowDelAtom();
   event.xclient.data.l[1] = w;
 
-  XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event);
+  XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event);
 }
 
 
 void Netizen::sendWindowRaise(Window w) {
-  event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowRaiseAtom();
+  event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowRaiseAtom();
   event.xclient.data.l[1] = w;
 
-  XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event);
+  XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event);
 }
 
 
 void Netizen::sendWindowLower(Window w) {
-  event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowLowerAtom();
+  event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowLowerAtom();
   event.xclient.data.l[1] = w;
 
-  XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event);
+  XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event);
 }
 
 
 void Netizen::sendConfigNotify(XEvent *e) {
-  XSendEvent(basedisplay.getXDisplay(), window, False,
+  XSendEvent(blackbox->getXDisplay(), window, False,
              StructureNotifyMask, e);
 }
similarity index 86%
rename from src/Netizen.h
rename to src/Netizen.hh
index 9de223d774d6a96fac7e5c0c6ecc626fbb5cf30c..2f7cbda2bfaea56d3a7433a5ff078ae47a1f2ac7 100644 (file)
@@ -1,4 +1,5 @@
-// Netizen.h for Openbox
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Netizen.hh for Blackbox - An X11 Window Manager
 // Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 #ifndef   __Netizen_hh
 #define   __Netizen_hh
 
+extern "C" {
 #include <X11/Xlib.h>
+}
 
 // forward declaration
-class BaseDisplay;
+class Blackbox;
 class BScreen;
 class Netizen;
 
 class Netizen {
 private:
-  BaseDisplay &basedisplay;
-  BScreen &screen;
+  Blackbox *blackbox;
+  BScreen *screen;
   Window window;
   XEvent event;
 
-protected:
-
 public:
-  Netizen(BScreen &, Window);
+  Netizen(BScreen *, Window);
 
-  inline const Window &getWindowID(void) const { return window; }
+  inline Window getWindowID(void) const { return window; }
 
   void sendWorkspaceCount(void);
   void sendCurrentWorkspace(void);
diff --git a/src/Resource.cc b/src/Resource.cc
deleted file mode 100644 (file)
index 2a678f8..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-// Resource.cc for Openbox
-// Copyright (c) 2002 - 2002 Ben Jansens (ben@orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#include "Resource.h"
-#include "Util.h"
-
-#ifdef    HAVE_CONFIG_H
-#  include "../config.h"
-#endif // HAVE_CONFIG_H
-
-#ifdef    HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif // HAVE_STDLIB_H
-
-#ifdef    HAVE_STDIO_H
-#  include <stdio.h>
-#endif // HAVE_STDIO_H
-
-bool Resource::m_initialized = false;
-
-Resource::Resource(const std::string &file) {
-  setFile(file);
-  m_modified = false;
-  m_database = NULL;
-  m_autosave = true;
-  if (!m_initialized) {
-    XrmInitialize();
-    m_initialized = true;
-  }
-}
-
-Resource::Resource() {
-  m_modified = false;
-  m_database = NULL;
-  m_autosave = true;
-  if (!m_initialized) {
-    XrmInitialize();
-    m_initialized = true;
-  }
-}
-
-Resource::~Resource() {
-  if (m_database != NULL)
-    XrmDestroyDatabase(m_database);
-}
-
-void Resource::setFile(const std::string &file) {
-  m_file = file;
-}
-
-void Resource::setAutoSave(bool autosave) {
-  m_autosave = autosave;
-}
-
-void Resource::save() {
-  ASSERT(m_database != NULL);
-  XrmPutFileDatabase(m_database, m_file.c_str());
-  m_modified = false;
-}
-
-bool Resource::load() {
-  if (m_database != NULL)
-    XrmDestroyDatabase(m_database);
-  m_modified = false;
-  if (NULL == (m_database = XrmGetFileDatabase(m_file.c_str())))
-    return false;
-  return true;
-}
-
-void Resource::create() {
-  if (m_database != NULL)
-    XrmDestroyDatabase(m_database);
-  m_modified = false;
-  ASSERT(NULL != (m_database = XrmGetStringDatabase("")));
-}
-
-void Resource::setValue(const std::string &rname, bool value) {
-  ASSERT(m_database != NULL);
-
-  const char *val = (value ? "True" : "False");
-  std::string rc_string = rname + ": " + val;
-  XrmPutLineResource(&m_database, rc_string.c_str());
-
-  m_modified = true;
-  if (m_autosave)
-    save();
-}
-
-void Resource::setValue(const std::string &rname, int value) {
-  setValue(rname, (long)value);
-}
-
-void Resource::setValue(const std::string &rname, long value) {
-  ASSERT(m_database != NULL);
-  
-  char val[11];
-  sprintf(val, "%ld", value);
-  std::string rc_string = rname + ": " + val;
-  XrmPutLineResource(&m_database, rc_string.c_str());
-
-  m_modified = true;
-  if (m_autosave)
-    save();
-}
-
-void Resource::setValue(const std::string &rname, const char *value) {
-  ASSERT(m_database != NULL);
-  ASSERT(value != NULL);
-  
-  std::string rc_string = rname + ": " + value;
-  XrmPutLineResource(&m_database, rc_string.c_str());
-
-  m_modified = true;
-  if (m_autosave)
-    save();
-}
-
-void Resource::setValue(const std::string &rname, const std::string &value) {
-  ASSERT(m_database != NULL);
-  
-  std::string rc_string = rname + ": " + value;
-  XrmPutLineResource(&m_database, rc_string.c_str());
-
-  m_modified = true;
-  if (m_autosave)
-    save();
-}
-
-bool Resource::getValue(const std::string &rname, const std::string &rclass,
-                          bool &value) const {
-  ASSERT(rclass.c_str() != NULL);
-  ASSERT(m_database != NULL);
-  
-  char *rettype;
-  XrmValue retvalue;
-  if (0 == XrmGetResource(m_database, rname.c_str(), rclass.c_str(), 
-                          &rettype, &retvalue) || retvalue.addr == NULL)
-    return false;
-  std::string val = retvalue.addr;
-  if (0 == strncasecmp(val.c_str(), "true", val.length()))
-    value = true;
-  else
-    value = false;
-  return true;
-}
-
-bool Resource::getValue(const std::string &rname, const std::string &rclass,
-                          long &value) const {
-  ASSERT(m_database != NULL);
-  
-  char *rettype;
-  XrmValue retvalue;
-  if (0 == XrmGetResource(m_database, rname.c_str(), rclass.c_str(), 
-                          &rettype, &retvalue) || retvalue.addr == NULL)
-    return false;
-  char *end;
-  value = strtol(retvalue.addr, &end, 10);
-  if (end == retvalue.addr)
-    return false;
-  return true;
-}
-
-bool Resource::getValue(const std::string &rname, const std::string &rclass,
-                          std::string &value) const {
-  ASSERT(m_database != NULL);
-  
-  char *rettype;
-  XrmValue retvalue;
-  if (0 == XrmGetResource(m_database, rname.c_str(), rclass.c_str(), 
-                          &rettype, &retvalue) || retvalue.addr == NULL)
-    return false;
-  value = retvalue.addr;
-  return true;
-}
diff --git a/src/Resource.h b/src/Resource.h
deleted file mode 100644 (file)
index e75b871..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// Resource.h for Openbox
-// Copyright (c) 2002 - 2002 Ben Jansens (ben@orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Resource_hh
-#define   __Resource_hh
-
-#include <string>
-
-#include <X11/Xlib.h>
-#include <X11/Xresource.h>
-
-class Resource {
-public:
-  explicit Resource(const std::string &file);
-  Resource();
-  virtual ~Resource();
-
-  inline const std::string &file() const {
-    return static_cast<const std::string &>(m_file);
-  }
-  void setFile(const std::string &file);
-
-  // defaults to true!
-  inline bool autoSave() const {
-    return m_autosave;
-  }
-  void setAutoSave(bool);
-
-  inline bool isModified() const {
-    return m_modified;
-  }
-
-  void save();
-  bool load();
-  void create();
-
-  void setValue(const std::string &rname, bool value);
-  void setValue(const std::string &rname, int value);
-  void setValue(const std::string &rname, long value);
-  void setValue(const std::string &rname, const std::string &value);
-  void setValue(const std::string &rname, const char *value);
-
-  bool getValue(const std::string &rname, const std::string &rclass,
-                bool &value) const;
-  bool getValue(const std::string &rname, const std::string &rclass,
-                long &value) const;
-  bool getValue(const std::string &rname, const std::string &rclass,
-                std::string &value) const;
-
-private:
-  static bool m_initialized;
-  std::string m_file;
-  bool m_modified;
-  bool m_autosave;
-  XrmDatabase m_database;
-};
-
-#endif // __Resource_hh
index 4728f5075b8a02095b27f05a10de34fea0caeb12..3fbc844c6fb0e67b71e9b9535fe01e7fcbe589b1 100644 (file)
@@ -1,5 +1,6 @@
-// Rootmenu.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Rootmenu.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "openbox.h"
-#include "Rootmenu.h"
-#include "Screen.h"
-
+extern "C" {
 #ifdef    HAVE_STDIO_H
 #  include <stdio.h>
 #endif // HAVE_STDIO_H
 
-#ifdef    HAVE_STDLIB_H
+#ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif // HAVE_STDLIB_H
 
-#ifdef    HAVE_STRING_H
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
 
 #ifdef    HAVE_SYS_PARAM_H
 #  include <sys/param.h>
 #endif // HAVE_SYS_PARAM_H
+}
 
-#ifndef   MAXPATHLEN
-#define   MAXPATHLEN 255
-#endif // MAXPATHLEN
+#include "blackbox.hh"
+#include "Rootmenu.hh"
+#include "Screen.hh"
+#include "Util.hh"
 
 
-Rootmenu::Rootmenu(BScreen &scrn) : Basemenu(scrn), openbox(scrn.getOpenbox()),
-  screen(scrn)  
-{
-}
+Rootmenu::Rootmenu(BScreen *scrn) : Basemenu(scrn) { }
 
 
-void Rootmenu::itemSelected(int button, int index) {
+void Rootmenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
@@ -72,44 +63,33 @@ void Rootmenu::itemSelected(int button, int index) {
 
   switch (item->function()) {
   case BScreen::Execute:
-    if (item->exec()) {
-#ifndef    __EMX__
-      char displaystring[MAXPATHLEN];
-      sprintf(displaystring, "DISPLAY=%s",
-             DisplayString(screen.getBaseDisplay().getXDisplay()));
-      sprintf(displaystring + strlen(displaystring) - 1, "%d",
-             screen.getScreenNumber());
-
-      bexec(item->exec(), displaystring);
-#else //   __EMX__
-      spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", item->exec(), NULL);
-#endif // !__EMX__
-    }
+    if (item->exec())
+      bexec(item->exec(), getScreen()->displayString());
     break;
 
   case BScreen::Restart:
-    openbox.restart();
+    getScreen()->getBlackbox()->restart();
     break;
 
   case BScreen::RestartOther:
     if (item->exec())
-      openbox.restart(item->exec());
+      getScreen()->getBlackbox()->restart(item->exec());
     break;
 
   case BScreen::Exit:
-    openbox.shutdown();
+    getScreen()->getBlackbox()->shutdown();
     break;
 
   case BScreen::SetStyle:
     if (item->exec())
-      openbox.setStyleFilename(item->exec());
+      getScreen()->getBlackbox()->saveStyleFilename(item->exec());
 
   case BScreen::Reconfigure:
-    openbox.reconfigure();
+    getScreen()->getBlackbox()->reconfigure();
     return;
   }
 
-  if (! (screen.getRootmenu()->isTorn() || isTorn()) &&
+  if (! (getScreen()->getRootmenu()->isTorn() || isTorn()) &&
       item->function() != BScreen::Reconfigure &&
       item->function() != BScreen::SetStyle)
     hide();
similarity index 79%
rename from src/Rootmenu.h
rename to src/Rootmenu.hh
index 63597d336a650677df8c97e2b481499bb88209ad..e436397d5526e4d50fad1dbe08717b89bec5fd4a 100644 (file)
@@ -1,5 +1,6 @@
-// Rootmenu.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Rootmenu.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 #define   __Rootmenu_hh
 
 // forward declarations
-class Rootmenu;
-
-class Openbox;
 class BScreen;
 
-#include "Basemenu.h"
+#include "Basemenu.hh"
 
 
 class Rootmenu : public Basemenu {
 private:
-  Openbox &openbox;
-  BScreen &screen;
-
+  Rootmenu(const Rootmenu&);
+  Rootmenu& operator=(const Rootmenu&);
 
 protected:
-  virtual void itemSelected(int, int);
-
+  virtual void itemSelected(int button, unsigned int index);
 
 public:
-  Rootmenu(BScreen &);
+  Rootmenu(BScreen *scrn);
 };
 
 
index 2225e2cee73a4dd92c19611dfa23aa043c0509d5..2844d874eb8bf1e29c289d776ef51b4d47c85541 100644 (file)
@@ -1,5 +1,6 @@
-// Screen.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Screen.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
+extern "C" {
 #include <X11/Xatom.h>
 #include <X11/keysym.h>
 
-#include "i18n.h"
-#include "openbox.h"
-#include "Clientmenu.h"
-#include "Iconmenu.h"
-#include "Image.h"
-#include "Screen.h"
-
-#ifdef    SLIT
-#include "Slit.h"
-#endif // SLIT
-
-#include "Rootmenu.h"
-#include "Toolbar.h"
-#include "Window.h"
-#include "Workspace.h"
-#include "Workspacemenu.h"
-#include "Util.h"
-
-#ifdef    HAVE_STDLIB_H
+// for strcasestr()
+#ifndef _GNU_SOURCE
+#  define   _GNU_SOURCE
+#endif // _GNU_SOURCE
+
+#ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif // HAVE_STDLIB_H
 
-#ifdef    HAVE_STRING_H
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
 
-#ifdef    HAVE_SYS_TYPES_H
-#  include <sys/types.h>
-#endif // HAVE_SYS_TYPES_H
-
 #ifdef    HAVE_CTYPE_H
 #  include <ctype.h>
 #endif // HAVE_CTYPE_H
 
+#ifdef    HAVE_UNISTD_H
+#  include <sys/types.h>
+#  include <unistd.h>
+#endif // HAVE_UNISTD_H
+
 #ifdef    HAVE_DIRENT_H
 #  include <dirent.h>
 #endif // HAVE_DIRENT_H
 #  include <locale.h>
 #endif // HAVE_LOCALE_H
 
-#ifdef    HAVE_UNISTD_H
-#  include <sys/types.h>
-#  include <unistd.h>
-#endif // HAVE_UNISTD_H
-
 #ifdef    HAVE_SYS_STAT_H
 #  include <sys/stat.h>
 #endif // HAVE_SYS_STAT_H
 #ifdef    HAVE_STDARG_H
 #  include <stdarg.h>
 #endif // HAVE_STDARG_H
+}
 
-#ifndef    HAVE_SNPRINTF
-#  include "bsd-snprintf.h"
-#endif // !HAVE_SNPRINTF
-
-#ifndef   MAXPATHLEN
-#define   MAXPATHLEN 255
-#endif // MAXPATHLEN
+#include <algorithm>
+#include <functional>
+using std::string;
+
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "Clientmenu.hh"
+#include "GCCache.hh"
+#include "Iconmenu.hh"
+#include "Image.hh"
+#include "Screen.hh"
+#include "Slit.hh"
+#include "Rootmenu.hh"
+#include "Toolbar.hh"
+#include "Util.hh"
+#include "Window.hh"
+#include "Workspace.hh"
+#include "Workspacemenu.hh"
 
 #ifndef   FONT_ELEMENT_SIZE
 #define   FONT_ELEMENT_SIZE 50
 #endif // FONT_ELEMENT_SIZE
 
-#include <strstream>
-#include <string>
-#include <algorithm>
-#include <functional>
-using std::ends;
 
-static Bool running = True;
+static bool running = True;
 
 static int anotherWMRunning(Display *display, XErrorEvent *) {
   fprintf(stderr, i18n(ScreenSet, ScreenAnotherWMRunning,
-                       "BScreen::BScreen: an error occured while querying the X server.\n"
-                       "  another window manager already running on display %s.\n"),
+          "BScreen::BScreen: an error occured while querying the X server.\n"
+          "  another window manager already running on display %s.\n"),
           DisplayString(display));
 
   running = False;
@@ -119,86 +105,16 @@ static int anotherWMRunning(Display *display, XErrorEvent *) {
   return(-1);
 }
 
-struct dcmp {
-  bool operator()(const char *one, const char *two) const {
-    return (strcmp(one, two) < 0) ? True : False;
-  }
-};
-
-#ifndef    HAVE_STRCASESTR
-static const char * strcasestr(const char *str, const char *ptn) {
-  const char *s2, *p2;
-  for( ; *str; str++) {
-    for(s2=str,p2=ptn; ; s2++,p2++) {
-      if (!*p2) return str;
-      if (toupper(*s2) != toupper(*p2)) break;
-    }
-  }
-  return NULL;
-}
-#endif // HAVE_STRCASESTR
-
-static const char *getFontElement(const char *pattern, char *buf, int bufsiz, ...) {
-  const char *p, *v;
-  char *p2;
-  va_list va;
-
-  va_start(va, bufsiz);
-  buf[bufsiz-1] = 0;
-  buf[bufsiz-2] = '*';
-  while((v = va_arg(va, char *)) != NULL) {
-    p = strcasestr(pattern, v);
-    if (p) {
-      strncpy(buf, p+1, bufsiz-2);
-      p2 = strchr(buf, '-');
-      if (p2) *p2=0;
-      va_end(va);
-      return p;
-    }
-  }
-  va_end(va);
-  strncpy(buf, "*", bufsiz);
-  return NULL;
-}
-
-static const char *getFontSize(const char *pattern, int *size) {
-  const char *p;
-  const char *p2=NULL;
-  int n=0;
-
-  for (p=pattern; 1; p++) {
-    if (!*p) {
-      if (p2!=NULL && n>1 && n<72) {
-        *size = n; return p2+1;
-      } else {
-        *size = 16; return NULL;
-      }
-    } else if (*p=='-') {
-      if (n>1 && n<72 && p2!=NULL) {
-        *size = n;
-        return p2+1;
-      }
-      p2=p; n=0;
-    } else if (*p>='0' && *p<='9' && p2!=NULL) {
-      n *= 10;
-      n += *p-'0';
-    } else {
-      p2=NULL; n=0;
-    }
-  }
-}
 
+BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) {
+  blackbox = bb;
 
-BScreen::BScreen(Openbox &ob, int scrn, Resource &conf) : ScreenInfo(ob, scrn),
-openbox(ob), config(conf)
-{
   event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
-    SubstructureRedirectMask | KeyPressMask | KeyReleaseMask |
-    ButtonPressMask | ButtonReleaseMask;
+    SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask;
 
   XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning);
-  XSelectInput(getBaseDisplay().getXDisplay(), getRootWindow(), event_mask);
-  XSync(getBaseDisplay().getXDisplay(), False);
+  XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask);
+  XSync(getBaseDisplay()->getXDisplay(), False);
   XSetErrorHandler((XErrorHandler) old);
 
   managed = running;
@@ -211,131 +127,51 @@ openbox(ob), config(conf)
           getDepth());
 
   rootmenu = 0;
+  resource.stylerc = 0;
 
   resource.mstyle.t_fontset = resource.mstyle.f_fontset =
-    resource.tstyle.fontset = resource.wstyle.fontset = NULL;
+    resource.tstyle.fontset = resource.wstyle.fontset = (XFontSet) 0;
   resource.mstyle.t_font = resource.mstyle.f_font = resource.tstyle.font =
-    resource.wstyle.font = NULL;
-  resource.root_command = NULL;
-#ifdef    HAVE_STRFTIME
-  resource.strftime_format = NULL;
-#endif // HAVE_STRFTIME
-
-#ifdef   SLIT
-  slit = NULL;
-#endif // SLIT
-  toolbar = NULL;
-  current_workspace = (Workspace *) 0;
+    resource.wstyle.font = (XFontStruct *) 0;
 
 #ifdef    HAVE_GETPID
   pid_t bpid = getpid();
 
-  XChangeProperty(getBaseDisplay().getXDisplay(), getRootWindow(),
-                  openbox.getOpenboxPidAtom(), XA_CARDINAL,
+  XChangeProperty(blackbox->getXDisplay(), getRootWindow(),
+                  blackbox->getBlackboxPidAtom(), XA_CARDINAL,
                   sizeof(pid_t) * 8, PropModeReplace,
                   (unsigned char *) &bpid, 1);
 #endif // HAVE_GETPID
 
-  XDefineCursor(getBaseDisplay().getXDisplay(), getRootWindow(),
-                openbox.getSessionCursor());
+  XDefineCursor(blackbox->getXDisplay(), getRootWindow(),
+                blackbox->getSessionCursor());
+
+  // start off full screen, top left.
+  usableArea.setSize(getWidth(), getHeight());
 
   image_control =
-    new BImageControl(openbox, *this, True, openbox.getColorsPerChannel(),
-                      openbox.getCacheLife(), openbox.getCacheMax());
+    new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(),
+                      blackbox->getCacheLife(), blackbox->getCacheMax());
   image_control->installRootColormap();
   root_colormap_installed = True;
 
-  load();       // load config options from Resources
+  blackbox->load_rc(this);
+
+  image_control->setDither(resource.image_dither);
+
   LoadStyle();
 
   XGCValues gcv;
   unsigned long gc_value_mask = GCForeground;
   if (! i18n.multibyte()) gc_value_mask |= GCFont;
 
-  gcv.foreground = WhitePixel(getBaseDisplay().getXDisplay(),
-                              getScreenNumber())
-    ^ BlackPixel(getBaseDisplay().getXDisplay(),
-                 getScreenNumber());
+  gcv.foreground = WhitePixel(blackbox->getXDisplay(), getScreenNumber())
+    ^ BlackPixel(blackbox->getXDisplay(), getScreenNumber());
   gcv.function = GXxor;
   gcv.subwindow_mode = IncludeInferiors;
-  opGC = XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
+  opGC = XCreateGC(blackbox->getXDisplay(), getRootWindow(),
                    GCForeground | GCFunction | GCSubwindowMode, &gcv);
 
-  gcv.foreground = resource.wstyle.l_text_focus.getPixel();
-  if (resource.wstyle.font)
-    gcv.font = resource.wstyle.font->fid;
-  resource.wstyle.l_text_focus_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.wstyle.l_text_unfocus.getPixel();
-  if (resource.wstyle.font)
-    gcv.font = resource.wstyle.font->fid;
-  resource.wstyle.l_text_unfocus_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.wstyle.b_pic_focus.getPixel();
-  resource.wstyle.b_pic_focus_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              GCForeground, &gcv);
-
-  gcv.foreground = resource.wstyle.b_pic_unfocus.getPixel();
-  resource.wstyle.b_pic_unfocus_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              GCForeground, &gcv);
-
-  gcv.foreground = resource.mstyle.t_text.getPixel();
-  if (resource.mstyle.t_font)
-    gcv.font = resource.mstyle.t_font->fid;
-  resource.mstyle.t_text_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.mstyle.f_text.getPixel();
-  if (resource.mstyle.f_font)
-    gcv.font = resource.mstyle.f_font->fid;
-  resource.mstyle.f_text_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.mstyle.h_text.getPixel();
-  resource.mstyle.h_text_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.mstyle.d_text.getPixel();
-  resource.mstyle.d_text_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.mstyle.hilite.getColor()->getPixel();
-  resource.mstyle.hilite_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.tstyle.l_text.getPixel();
-  if (resource.tstyle.font)
-    gcv.font = resource.tstyle.font->fid;
-  resource.tstyle.l_text_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.tstyle.w_text.getPixel();
-  resource.tstyle.w_text_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.tstyle.c_text.getPixel();
-  resource.tstyle.c_text_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
-  gcv.foreground = resource.tstyle.b_pic.getPixel();
-  resource.tstyle.b_pic_gc =
-    XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
-              gc_value_mask, &gcv);
-
   const char *s =  i18n(ScreenSet, ScreenPositionLength,
                         "0: 0000 x 0: 0000");
   int l = strlen(s);
@@ -358,134 +194,107 @@ openbox(ob), config(conf)
 
   XSetWindowAttributes attrib;
   unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder;
-  attrib.border_pixel = getBorderColor()->getPixel();
+  attrib.border_pixel = getBorderColor()->pixel();
   attrib.colormap = getColormap();
   attrib.save_under = True;
 
-  geom_window =
-    XCreateWindow(getBaseDisplay().getXDisplay(), getRootWindow(),
-                  0, 0, geom_w, geom_h, resource.border_width, getDepth(),
-                  InputOutput, getVisual(), mask, &attrib);
+  geom_window = XCreateWindow(blackbox->getXDisplay(), getRootWindow(),
+                              0, 0, geom_w, geom_h, resource.border_width,
+                              getDepth(), InputOutput, getVisual(),
+                              mask, &attrib);
   geom_visible = False;
 
-  if (resource.wstyle.l_focus.getTexture() & BImage_ParentRelative) {
-    if (resource.wstyle.t_focus.getTexture() ==
-        (BImage_Flat | BImage_Solid)) {
-      geom_pixmap = None;
-      XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
-                           resource.wstyle.t_focus.getColor()->getPixel());
-    } else {
-      geom_pixmap = image_control->renderImage(geom_w, geom_h,
-                                               &resource.wstyle.t_focus);
-      XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
-                                 geom_window, geom_pixmap);
-    }
-  } else {
-    if (resource.wstyle.l_focus.getTexture() ==
-        (BImage_Flat | BImage_Solid)) {
-      geom_pixmap = None;
-      XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
-                           resource.wstyle.l_focus.getColor()->getPixel());
-    } else {
-      geom_pixmap = image_control->renderImage(geom_w, geom_h,
-                                               &resource.wstyle.l_focus);
-      XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
-                                 geom_window, geom_pixmap);
-    }
-  }
+  BTexture* texture = &(resource.wstyle.l_focus);
+  geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
+  if (! geom_pixmap)
+    XSetWindowBackground(blackbox->getXDisplay(), geom_window,
+                         texture->color().pixel());
+  else
+    XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                               geom_window, geom_pixmap);
 
-  workspacemenu = new Workspacemenu(*this);
-  iconmenu = new Iconmenu(*this);
-  configmenu = new Configmenu(*this);
+  workspacemenu = new Workspacemenu(this);
+  iconmenu = new Iconmenu(this);
+  configmenu = new Configmenu(this);
 
-  Workspace *wkspc = NULL;
+  Workspace *wkspc = (Workspace *) 0;
   if (resource.workspaces != 0) {
-    for (int i = 0; i < resource.workspaces; ++i) {
-      wkspc = new Workspace(*this, workspacesList.size());
+    for (unsigned int i = 0; i < resource.workspaces; ++i) {
+      wkspc = new Workspace(this, workspacesList.size());
       workspacesList.push_back(wkspc);
       workspacemenu->insert(wkspc->getName(), wkspc->getMenu());
     }
   } else {
-    setWorkspaceCount(1);
-    wkspc = new Workspace(*this, workspacesList.size());
+    wkspc = new Workspace(this, workspacesList.size());
     workspacesList.push_back(wkspc);
     workspacemenu->insert(wkspc->getName(), wkspc->getMenu());
   }
-  saveWorkspaceNames();
 
-  workspacemenu->insert(i18n(IconSet, IconIcons, "Icons"),
-                        iconmenu);
+  workspacemenu->insert(i18n(IconSet, IconIcons, "Icons"), iconmenu);
   workspacemenu->update();
 
   current_workspace = workspacesList.front();
   workspacemenu->setItemSelected(2, True);
 
-  toolbar = new Toolbar(*this, config);
+  toolbar = new Toolbar(this);
 
-#ifdef    SLIT
-  slit = new Slit(*this, config);
-#endif // SLIT
+  slit = new Slit(this);
 
   InitMenu();
 
   raiseWindows(0, 0);
   rootmenu->update();
 
+  updateAvailableArea();
+
   changeWorkspaceID(0);
 
-  int i;
-  unsigned int nchild;
+  unsigned int i, j, nchild;
   Window r, p, *children;
-  XQueryTree(getBaseDisplay().getXDisplay(), getRootWindow(), &r, &p,
+  XQueryTree(blackbox->getXDisplay(), getRootWindow(), &r, &p,
              &children, &nchild);
 
   // preen the window list of all icon windows... for better dockapp support
-  for (i = 0; i < (int) nchild; i++) {
+  for (i = 0; i < nchild; i++) {
     if (children[i] == None) continue;
 
-    XWMHints *wmhints = XGetWMHints(getBaseDisplay().getXDisplay(),
+    XWMHints *wmhints = XGetWMHints(blackbox->getXDisplay(),
                                     children[i]);
 
     if (wmhints) {
       if ((wmhints->flags & IconWindowHint) &&
-          (wmhints->icon_window != children[i]))
-        for (int j = 0; j < (int) nchild; j++)
+          (wmhints->icon_window != children[i])) {
+        for (j = 0; j < nchild; j++) {
           if (children[j] == wmhints->icon_window) {
             children[j] = None;
-
             break;
           }
+        }
+      }
 
       XFree(wmhints);
     }
   }
 
   // manage shown windows
-  for (i = 0; i < (int) nchild; ++i) {
-    if (children[i] == None || (! openbox.validateWindow(children[i])))
+  for (i = 0; i < nchild; ++i) {
+    if (children[i] == None || (! blackbox->validateWindow(children[i])))
       continue;
 
     XWindowAttributes attrib;
-    if (XGetWindowAttributes(getBaseDisplay().getXDisplay(), children[i],
-                             &attrib)) {
+    if (XGetWindowAttributes(blackbox->getXDisplay(), children[i], &attrib)) {
       if (attrib.override_redirect) continue;
 
       if (attrib.map_state != IsUnmapped) {
-        new OpenboxWindow(openbox, children[i], this);
-
-        OpenboxWindow *win = openbox.searchWindow(children[i]);
-        if (win) {
-          XMapRequestEvent mre;
-          mre.window = children[i];
-          win->restoreAttributes();
-          win->mapRequestEvent(&mre);
-        }
+        manageWindow(children[i]);
       }
     }
   }
 
   XFree(children);
-  XFlush(getBaseDisplay().getXDisplay());
+
+  // call this again just in case a window we found updates the Strut list
+  updateAvailableArea();
 }
 
 
@@ -496,1798 +305,830 @@ BScreen::~BScreen(void) {
     image_control->removeImage(geom_pixmap);
 
   if (geom_window != None)
-    XDestroyWindow(getBaseDisplay().getXDisplay(), geom_window);
-
-  removeWorkspaceNames();
+    XDestroyWindow(blackbox->getXDisplay(), geom_window);
 
   std::for_each(workspacesList.begin(), workspacesList.end(),
                 PointerAssassin());
+
   std::for_each(iconList.begin(), iconList.end(), PointerAssassin());
-  std::for_each(netizenList.begin(), netizenList.end(), PointerAssassin());
 
-#ifdef    HAVE_STRFTIME
-  if (resource.strftime_format)
-    delete [] resource.strftime_format;
-#endif // HAVE_STRFTIME
+  std::for_each(netizenList.begin(), netizenList.end(), PointerAssassin());
 
   delete rootmenu;
   delete workspacemenu;
   delete iconmenu;
   delete configmenu;
-
-#ifdef    SLIT
   delete slit;
-#endif // SLIT
-
   delete toolbar;
   delete image_control;
 
   if (resource.wstyle.fontset)
-    XFreeFontSet(getBaseDisplay().getXDisplay(), resource.wstyle.fontset);
+    XFreeFontSet(blackbox->getXDisplay(), resource.wstyle.fontset);
   if (resource.mstyle.t_fontset)
-    XFreeFontSet(getBaseDisplay().getXDisplay(), resource.mstyle.t_fontset);
+    XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.t_fontset);
   if (resource.mstyle.f_fontset)
-    XFreeFontSet(getBaseDisplay().getXDisplay(), resource.mstyle.f_fontset);
+    XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.f_fontset);
   if (resource.tstyle.fontset)
-    XFreeFontSet(getBaseDisplay().getXDisplay(), resource.tstyle.fontset);
+    XFreeFontSet(blackbox->getXDisplay(), resource.tstyle.fontset);
 
   if (resource.wstyle.font)
-    XFreeFont(getBaseDisplay().getXDisplay(), resource.wstyle.font);
+    XFreeFont(blackbox->getXDisplay(), resource.wstyle.font);
   if (resource.mstyle.t_font)
-    XFreeFont(getBaseDisplay().getXDisplay(), resource.mstyle.t_font);
+    XFreeFont(blackbox->getXDisplay(), resource.mstyle.t_font);
   if (resource.mstyle.f_font)
-    XFreeFont(getBaseDisplay().getXDisplay(), resource.mstyle.f_font);
+    XFreeFont(blackbox->getXDisplay(), resource.mstyle.f_font);
   if (resource.tstyle.font)
-    XFreeFont(getBaseDisplay().getXDisplay(), resource.tstyle.font);
-  if (resource.root_command != NULL)
-    delete [] resource.root_command;
-
-  XFreeGC(getBaseDisplay().getXDisplay(), opGC);
-
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.wstyle.l_text_focus_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.wstyle.l_text_unfocus_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.wstyle.b_pic_focus_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.wstyle.b_pic_unfocus_gc);
-
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.mstyle.t_text_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.mstyle.f_text_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.mstyle.h_text_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.mstyle.d_text_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.mstyle.hilite_gc);
-
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.tstyle.l_text_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.tstyle.w_text_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.tstyle.c_text_gc);
-  XFreeGC(getBaseDisplay().getXDisplay(),
-          resource.tstyle.b_pic_gc);
+    XFreeFont(blackbox->getXDisplay(), resource.tstyle.font);
+
+  XFreeGC(blackbox->getXDisplay(), opGC);
 }
 
 
-Rect BScreen::availableArea() const {
-  // the following code is temporary and will be taken care of by Screen in the
-  // future (with the NETWM 'strut')
-  Rect space(0, 0, size().w(), size().h());
-  if (!resource.full_max) {
-#ifdef    SLIT
-    int slit_x = slit->autoHide() ? slit->hiddenOrigin().x() : slit->area().x(),
-    slit_y = slit->autoHide() ? slit->hiddenOrigin().y() : slit->area().y();
-    unsigned int tbarh = resource.hide_toolbar ? 0 :
-      toolbar->getExposedHeight() + resource.border_width * 2;
-    bool tbartop;
-    switch (toolbar->placement()) {
-    case Toolbar::TopLeft:
-    case Toolbar::TopCenter:
-    case Toolbar::TopRight:
-      tbartop = true;
-      break;
-    case Toolbar::BottomLeft:
-    case Toolbar::BottomCenter:
-    case Toolbar::BottomRight:
-      tbartop = false;
-      break;
-    default:
-      ASSERT(false);      // unhandled placement
-    }
-    if ((slit->direction() == Slit::Horizontal &&
-         (slit->placement() == Slit::TopLeft ||
-          slit->placement() == Slit::TopRight)) ||
-        slit->placement() == Slit::TopCenter) {
-      // exclude top
-      if (tbartop && slit_y + slit->area().h() < tbarh) {
-        space.setY(space.y() + tbarh);
-        space.setH(space.h() - tbarh);
-      } else {
-        space.setY(space.y() + (slit_y + slit->area().h() +
-                                resource.border_width * 2));
-        space.setH(space.h() - (slit_y + slit->area().h() +
-                                resource.border_width * 2));
-        if (!tbartop)
-          space.setH(space.h() - tbarh);
-      }
-    } else if ((slit->direction() == Slit::Vertical &&
-                (slit->placement() == Slit::TopRight ||
-                 slit->placement() == Slit::BottomRight)) ||
-               slit->placement() == Slit::CenterRight) {
-      // exclude right
-      space.setW(space.w() - (size().w() - slit_x));
-      if (tbartop)
-        space.setY(space.y() + tbarh);
-      space.setH(space.h() - tbarh);
-    } else if ((slit->direction() == Slit::Horizontal &&
-                (slit->placement() == Slit::BottomLeft ||
-                 slit->placement() == Slit::BottomRight)) ||
-               slit->placement() == Slit::BottomCenter) {
-      // exclude bottom
-      if (!tbartop && (size().h() - slit_y) < tbarh) {
-        space.setH(space.h() - tbarh);
-      } else {
-        space.setH(space.h() - (size().h() - slit_y));
-        if (tbartop) {
-          space.setY(space.y() + tbarh);
-          space.setH(space.h() - tbarh);
-        }
-      }
-    } else {// if ((slit->direction() == Slit::Vertical &&
-      //      (slit->placement() == Slit::TopLeft ||
-      //       slit->placement() == Slit::BottomLeft)) ||
-      //     slit->placement() == Slit::CenterLeft)
-      // exclude left
-      space.setX(slit_x + slit->area().w() +
-                 resource.border_width * 2);
-      space.setW(space.w() - (slit_x + slit->area().w() +
-                              resource.border_width * 2));
-      if (tbartop)
-        space.setY(space.y() + tbarh);
-      space.setH(space.h() - tbarh);
-    }
-#else // !SLIT
-    int tbarh = resource.hide_toolbar ? 0 :
-      toolbar->getExposedHeight() + resource.border_width * 2;
-    switch (toolbar->placement()) {
-    case Toolbar::TopLeft:
-    case Toolbar::TopCenter:
-    case Toolbar::TopRight:
-      space.setY(toolbar->getExposedHeight());
-      space.setH(space.h() - toolbar->getExposedHeight());
-      break;
-    case Toolbar::BottomLeft:
-    case Toolbar::BottomCenter:
-    case Toolbar::BottomRight:
-      space.setH(space.h() - tbarh);
-      break;
-    default:
-      ASSERT(false);      // unhandled placement
-    }
-#endif // SLIT
-  }
-  return space;
+void BScreen::removeWorkspaceNames(void) {
+  workspaceNames.clear();
 }
 
 
-void BScreen::readDatabaseTexture(const char *rname, const char *rclass,
-                                  BTexture *texture,
-                                  unsigned long default_pixel)
-{
-  std::string s;
+void BScreen::reconfigure(void) {
+  LoadStyle();
 
-  if (resource.styleconfig.getValue(rname, rclass, s))
-    image_control->parseTexture(texture, s.c_str());
-  else
-    texture->setTexture(BImage_Solid | BImage_Flat);
-
-  if (texture->getTexture() & BImage_Solid) {
-    int clen = strlen(rclass) + 32, nlen = strlen(rname) + 32;
-
-    char *colorclass = new char[clen], *colorname = new char[nlen];
-
-    sprintf(colorclass, "%s.Color", rclass);
-    sprintf(colorname,  "%s.color", rname);
-
-    readDatabaseColor(colorname, colorclass, texture->getColor(),
-                      default_pixel);
-
-#ifdef    INTERLACE
-    sprintf(colorclass, "%s.ColorTo", rclass);
-    sprintf(colorname,  "%s.colorTo", rname);
-
-    readDatabaseColor(colorname, colorclass, texture->getColorTo(),
-                      default_pixel);
-#endif // INTERLACE
-
-    delete [] colorclass;
-    delete [] colorname;
-
-    if ((! texture->getColor()->isAllocated()) ||
-        (texture->getTexture() & BImage_Flat))
-      return;
-
-    XColor xcol;
-
-    xcol.red = (unsigned int) (texture->getColor()->getRed() +
-                               (texture->getColor()->getRed() >> 1));
-    if (xcol.red >= 0xff) xcol.red = 0xffff;
-    else xcol.red *= 0xff;
-    xcol.green = (unsigned int) (texture->getColor()->getGreen() +
-                                 (texture->getColor()->getGreen() >> 1));
-    if (xcol.green >= 0xff) xcol.green = 0xffff;
-    else xcol.green *= 0xff;
-    xcol.blue = (unsigned int) (texture->getColor()->getBlue() +
-                                (texture->getColor()->getBlue() >> 1));
-    if (xcol.blue >= 0xff) xcol.blue = 0xffff;
-    else xcol.blue *= 0xff;
-
-    if (! XAllocColor(getBaseDisplay().getXDisplay(),
-                      getColormap(), &xcol))
-      xcol.pixel = 0;
-
-    texture->getHiColor()->setPixel(xcol.pixel);
-
-    xcol.red =
-      (unsigned int) ((texture->getColor()->getRed() >> 2) +
-                      (texture->getColor()->getRed() >> 1)) * 0xff;
-    xcol.green =
-      (unsigned int) ((texture->getColor()->getGreen() >> 2) +
-                      (texture->getColor()->getGreen() >> 1)) * 0xff;
-    xcol.blue =
-      (unsigned int) ((texture->getColor()->getBlue() >> 2) +
-                      (texture->getColor()->getBlue() >> 1)) * 0xff;
-
-    if (! XAllocColor(getBaseDisplay().getXDisplay(),
-                      getColormap(), &xcol))
-      xcol.pixel = 0;
-
-    texture->getLoColor()->setPixel(xcol.pixel);
-  } else if (texture->getTexture() & BImage_Gradient) {
-    int clen = strlen(rclass) + 10, nlen = strlen(rname) + 10;
-
-    char *colorclass = new char[clen], *colorname = new char[nlen],
-    *colortoclass = new char[clen], *colortoname = new char[nlen];
-
-    sprintf(colorclass, "%s.Color", rclass);
-    sprintf(colorname,  "%s.color", rname);
-
-    sprintf(colortoclass, "%s.ColorTo", rclass);
-    sprintf(colortoname,  "%s.colorTo", rname);
-
-    readDatabaseColor(colorname, colorclass, texture->getColor(),
-                      default_pixel);
-    readDatabaseColor(colortoname, colortoclass, texture->getColorTo(),
-                      default_pixel);
-
-    delete [] colorclass;
-    delete [] colorname;
-    delete [] colortoclass;
-    delete [] colortoname;
-  }
-}
+  XGCValues gcv;
+  unsigned long gc_value_mask = GCForeground;
+  if (! i18n.multibyte()) gc_value_mask |= GCFont;
 
+  gcv.foreground = WhitePixel(blackbox->getXDisplay(),
+                              getScreenNumber());
+  gcv.function = GXinvert;
+  gcv.subwindow_mode = IncludeInferiors;
+  XChangeGC(blackbox->getXDisplay(), opGC,
+            GCForeground | GCFunction | GCSubwindowMode, &gcv);
 
-void BScreen::readDatabaseColor(const char *rname, const  char *rclass,
-                                BColor *color, unsigned long default_pixel)
-{
-  std::string s;
+  const char *s = i18n(ScreenSet, ScreenPositionLength,
+                       "0: 0000 x 0: 0000");
+  int l = strlen(s);
 
-  if (resource.styleconfig.getValue(rname, rclass, s))
-    image_control->parseColor(color, s.c_str());
-  else {
-    // parsing with no color std::string just deallocates the color, if it has
-    // been previously allocated
-    image_control->parseColor(color);
-    color->setPixel(default_pixel);
+  if (i18n.multibyte()) {
+    XRectangle ink, logical;
+    XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical);
+    geom_w = logical.width;
+
+    geom_h = resource.wstyle.fontset_extents->max_ink_extent.height;
+  } else {
+    geom_w = XTextWidth(resource.wstyle.font, s, l);
+
+    geom_h = resource.wstyle.font->ascent + resource.wstyle.font->descent;
   }
-}
 
+  geom_w += (resource.bevel_width * 2);
+  geom_h += (resource.bevel_width * 2);
+
+  BTexture* texture = &(resource.wstyle.l_focus);
+  geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap);
+  if (! geom_pixmap)
+    XSetWindowBackground(blackbox->getXDisplay(), geom_window,
+                         texture->color().pixel());
+  else
+    XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                               geom_window, geom_pixmap);
+
+  XSetWindowBorderWidth(blackbox->getXDisplay(), geom_window,
+                        resource.border_width);
+  XSetWindowBorder(blackbox->getXDisplay(), geom_window,
+                   resource.border_color.pixel());
 
-void BScreen::readDatabaseFontSet(const char *rname, const char *rclass,
-                                  XFontSet *fontset) {
-  if (! fontset) return;
+  workspacemenu->reconfigure();
+  iconmenu->reconfigure();
 
-  static char *defaultFont = "fixed";
-  bool load_default = false;
-  std::string s;
+  int remember_sub = rootmenu->getCurrentSubmenu();
+  InitMenu();
+  raiseWindows(0, 0);
+  rootmenu->reconfigure();
+  rootmenu->drawSubmenu(remember_sub);
 
-  if (*fontset)
-    XFreeFontSet(getBaseDisplay().getXDisplay(), *fontset);
+  configmenu->reconfigure();
 
-  if (resource.styleconfig.getValue(rname, rclass, s)) {
-    if (! (*fontset = createFontSet(s.c_str())))
-      load_default = true;
-  } else
-    load_default = true;
+  toolbar->reconfigure();
 
-  if (load_default) {
-    *fontset = createFontSet(defaultFont);
+  slit->reconfigure();
 
-    if (! *fontset) {
-      fprintf(stderr, i18n(ScreenSet, ScreenDefaultFontLoadFail,
-                           "BScreen::LoadStyle(): couldn't load default font.\n"));
-      exit(2);
-    }
+  std::for_each(workspacesList.begin(), workspacesList.end(),
+                std::mem_fun(&Workspace::reconfigure));
+
+  BlackboxWindowList::iterator iit = iconList.begin();
+  for (; iit != iconList.end(); ++iit) {
+    BlackboxWindow *bw = *iit;
+    if (bw->validateClient())
+      bw->reconfigure();
   }
+
+  image_control->timeout();
 }
 
 
-void BScreen::readDatabaseFont(const char *rname, const char *rclass,
-                               XFontStruct **font) {
-  if (! font) return;
+void BScreen::rereadMenu(void) {
+  InitMenu();
+  raiseWindows(0, 0);
 
-  static char *defaultFont = "fixed";
-  bool load_default = false;
-  std::string s;
+  rootmenu->reconfigure();
+}
 
-  if (*font)
-    XFreeFont(getBaseDisplay().getXDisplay(), *font);
 
-  if (resource.styleconfig.getValue(rname, rclass, s)) {
-    if ((*font = XLoadQueryFont(getBaseDisplay().getXDisplay(),
-                                s.c_str())) == NULL) {
-      fprintf(stderr, i18n(ScreenSet, ScreenFontLoadFail,
-                           "BScreen::LoadStyle(): couldn't load font '%s'\n"),
-              s.c_str());
-      load_default = true;
-    }
-  } else
-    load_default = true;
+void BScreen::LoadStyle(void) {
+  resource.stylerc = XrmGetFileDatabase(blackbox->getStyleFilename());
+  if (! resource.stylerc)
+    resource.stylerc = XrmGetFileDatabase(DEFAULTSTYLE);
 
-  if (load_default) {
-    if ((*font = XLoadQueryFont(getBaseDisplay().getXDisplay(),
-                                defaultFont)) == NULL) {
-      fprintf(stderr, i18n(ScreenSet, ScreenDefaultFontLoadFail,
-                           "BScreen::LoadStyle(): couldn't load default font.\n"));
-      exit(2);
-    }
-  }
-}
+  XrmValue value;
+  char *value_type;
 
+  // load fonts/fontsets
+  if (resource.wstyle.fontset)
+    XFreeFontSet(blackbox->getXDisplay(), resource.wstyle.fontset);
+  if (resource.tstyle.fontset)
+    XFreeFontSet(blackbox->getXDisplay(), resource.tstyle.fontset);
+  if (resource.mstyle.f_fontset)
+    XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.f_fontset);
+  if (resource.mstyle.t_fontset)
+    XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.t_fontset);
+  resource.wstyle.fontset = 0;
+  resource.tstyle.fontset = 0;
+  resource.mstyle.f_fontset = 0;
+  resource.mstyle.t_fontset = 0;
+  if (resource.wstyle.font)
+    XFreeFont(blackbox->getXDisplay(), resource.wstyle.font);
+  if (resource.tstyle.font)
+    XFreeFont(blackbox->getXDisplay(), resource.tstyle.font);
+  if (resource.mstyle.f_font)
+    XFreeFont(blackbox->getXDisplay(), resource.mstyle.f_font);
+  if (resource.mstyle.t_font)
+    XFreeFont(blackbox->getXDisplay(), resource.mstyle.t_font);
+  resource.wstyle.font = 0;
+  resource.tstyle.font = 0;
+  resource.mstyle.f_font = 0;
+  resource.mstyle.t_font = 0;
 
-XFontSet BScreen::createFontSet(const char *fontname) {
-  XFontSet fs;
-  char **missing, *def = "-";
-  int nmissing, pixel_size = 0, buf_size = 0;
-  char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE];
+  if (i18n.multibyte()) {
+    resource.wstyle.fontset =
+      readDatabaseFontSet("window.font", "Window.Font");
+    resource.tstyle.fontset =
+      readDatabaseFontSet("toolbar.font", "Toolbar.Font");
+    resource.mstyle.t_fontset =
+      readDatabaseFontSet("menu.title.font", "Menu.Title.Font");
+    resource.mstyle.f_fontset =
+      readDatabaseFontSet("menu.frame.font", "Menu.Frame.Font");
+
+    resource.mstyle.t_fontset_extents =
+      XExtentsOfFontSet(resource.mstyle.t_fontset);
+    resource.mstyle.f_fontset_extents =
+      XExtentsOfFontSet(resource.mstyle.f_fontset);
+    resource.tstyle.fontset_extents =
+      XExtentsOfFontSet(resource.tstyle.fontset);
+    resource.wstyle.fontset_extents =
+      XExtentsOfFontSet(resource.wstyle.fontset);
+  } else {
+    resource.wstyle.font =
+      readDatabaseFont("window.font", "Window.Font");
+    resource.tstyle.font =
+      readDatabaseFont("toolbar.font", "Toolbar.Font");
+    resource.mstyle.t_font =
+      readDatabaseFont("menu.title.font", "Menu.Title.Font");
+    resource.mstyle.f_font =
+      readDatabaseFont("menu.frame.font", "Menu.Frame.Font");
+  }
 
-  fs = XCreateFontSet(getBaseDisplay().getXDisplay(),
-                      fontname, &missing, &nmissing, &def);
-  if (fs && (! nmissing)) return fs;
+  // load window config
+  resource.wstyle.t_focus =
+    readDatabaseTexture("window.title.focus", "Window.Title.Focus", "white");
+  resource.wstyle.t_unfocus =
+    readDatabaseTexture("window.title.unfocus",
+                        "Window.Title.Unfocus", "black");
+  resource.wstyle.l_focus =
+    readDatabaseTexture("window.label.focus", "Window.Label.Focus", "white" );
+  resource.wstyle.l_unfocus =
+    readDatabaseTexture("window.label.unfocus", "Window.Label.Unfocus",
+                        "black");
+  resource.wstyle.h_focus =
+    readDatabaseTexture("window.handle.focus", "Window.Handle.Focus", "white");
+  resource.wstyle.h_unfocus =
+    readDatabaseTexture("window.handle.unfocus",
+                        "Window.Handle.Unfocus", "black");
+  resource.wstyle.g_focus =
+    readDatabaseTexture("window.grip.focus", "Window.Grip.Focus", "white");
+  resource.wstyle.g_unfocus =
+    readDatabaseTexture("window.grip.unfocus", "Window.Grip.Unfocus", "black");
+  resource.wstyle.b_focus =
+    readDatabaseTexture("window.button.focus", "Window.Button.Focus", "white");
+  resource.wstyle.b_unfocus =
+    readDatabaseTexture("window.button.unfocus",
+                        "Window.Button.Unfocus", "black");
+  resource.wstyle.b_pressed =
+    readDatabaseTexture("window.button.pressed",
+                        "Window.Button.Pressed", "black");
+  resource.wstyle.f_focus =
+    readDatabaseColor("window.frame.focusColor",
+                      "Window.Frame.FocusColor", "white");
+  resource.wstyle.f_unfocus =
+    readDatabaseColor("window.frame.unfocusColor",
+                      "Window.Frame.UnfocusColor", "black");
+  resource.wstyle.l_text_focus =
+    readDatabaseColor("window.label.focus.textColor",
+                      "Window.Label.Focus.TextColor", "black");
+  resource.wstyle.l_text_unfocus =
+    readDatabaseColor("window.label.unfocus.textColor",
+                      "Window.Label.Unfocus.TextColor", "white");
+  resource.wstyle.b_pic_focus =
+    readDatabaseColor("window.button.focus.picColor",
+                      "Window.Button.Focus.PicColor", "black");
+  resource.wstyle.b_pic_unfocus =
+    readDatabaseColor("window.button.unfocus.picColor",
+                      "Window.Button.Unfocus.PicColor", "white");
+
+  resource.wstyle.justify = LeftJustify;
+  if (XrmGetResource(resource.stylerc, "window.justify", "Window.Justify",
+                     &value_type, &value)) {
+    if (strstr(value.addr, "right") || strstr(value.addr, "Right"))
+      resource.wstyle.justify = RightJustify;
+    else if (strstr(value.addr, "center") || strstr(value.addr, "Center"))
+      resource.wstyle.justify = CenterJustify;
+  }
 
-#ifdef    HAVE_SETLOCALE
-  if (! fs) {
-    if (nmissing) XFreeStringList(missing);
+  // load toolbar config
+  resource.tstyle.toolbar =
+    readDatabaseTexture("toolbar", "Toolbar", "black");
+  resource.tstyle.label =
+    readDatabaseTexture("toolbar.label", "Toolbar.Label", "black");
+  resource.tstyle.window =
+    readDatabaseTexture("toolbar.windowLabel", "Toolbar.WindowLabel", "black");
+  resource.tstyle.button =
+    readDatabaseTexture("toolbar.button", "Toolbar.Button", "white");
+  resource.tstyle.pressed =
+    readDatabaseTexture("toolbar.button.pressed",
+                        "Toolbar.Button.Pressed", "black");
+  resource.tstyle.clock =
+    readDatabaseTexture("toolbar.clock", "Toolbar.Clock", "black");
+  resource.tstyle.l_text =
+    readDatabaseColor("toolbar.label.textColor",
+                      "Toolbar.Label.TextColor", "white");
+  resource.tstyle.w_text =
+    readDatabaseColor("toolbar.windowLabel.textColor",
+                      "Toolbar.WindowLabel.TextColor", "white");
+  resource.tstyle.c_text =
+    readDatabaseColor("toolbar.clock.textColor",
+                      "Toolbar.Clock.TextColor", "white");
+  resource.tstyle.b_pic =
+    readDatabaseColor("toolbar.button.picColor",
+                      "Toolbar.Button.PicColor", "black");
+
+  resource.tstyle.justify = LeftJustify;
+  if (XrmGetResource(resource.stylerc, "toolbar.justify",
+                     "Toolbar.Justify", &value_type, &value)) {
+    if (strstr(value.addr, "right") || strstr(value.addr, "Right"))
+      resource.tstyle.justify = RightJustify;
+    else if (strstr(value.addr, "center") || strstr(value.addr, "Center"))
+      resource.tstyle.justify = CenterJustify;
+  }
 
-    setlocale(LC_CTYPE, "C");
-    fs = XCreateFontSet(getBaseDisplay().getXDisplay(), fontname,
-                        &missing, &nmissing, &def);
-    setlocale(LC_CTYPE, "");
+  // load menu config
+  resource.mstyle.title =
+    readDatabaseTexture("menu.title", "Menu.Title", "white");
+  resource.mstyle.frame =
+    readDatabaseTexture("menu.frame", "Menu.Frame", "black");
+  resource.mstyle.hilite =
+    readDatabaseTexture("menu.hilite", "Menu.Hilite", "white");
+  resource.mstyle.t_text =
+    readDatabaseColor("menu.title.textColor", "Menu.Title.TextColor", "black");
+  resource.mstyle.f_text =
+    readDatabaseColor("menu.frame.textColor", "Menu.Frame.TextColor", "white");
+  resource.mstyle.d_text =
+    readDatabaseColor("menu.frame.disableColor",
+                      "Menu.Frame.DisableColor", "black");
+  resource.mstyle.h_text =
+    readDatabaseColor("menu.hilite.textColor",
+                      "Menu.Hilite.TextColor", "black");
+
+  resource.mstyle.t_justify = LeftJustify;
+  if (XrmGetResource(resource.stylerc, "menu.title.justify",
+                     "Menu.Title.Justify",
+                     &value_type, &value)) {
+    if (strstr(value.addr, "right") || strstr(value.addr, "Right"))
+      resource.mstyle.t_justify = RightJustify;
+    else if (strstr(value.addr, "center") || strstr(value.addr, "Center"))
+      resource.mstyle.t_justify = CenterJustify;
   }
-#endif // HAVE_SETLOCALE
 
-  if (fs) {
-    XFontStruct **fontstructs;
-    char **fontnames;
-    XFontsOfFontSet(fs, &fontstructs, &fontnames);
-    fontname = fontnames[0];
+  resource.mstyle.f_justify = LeftJustify;
+  if (XrmGetResource(resource.stylerc, "menu.frame.justify",
+                     "Menu.Frame.Justify",
+                     &value_type, &value)) {
+    if (strstr(value.addr, "right") || strstr(value.addr, "Right"))
+      resource.mstyle.f_justify = RightJustify;
+    else if (strstr(value.addr, "center") || strstr(value.addr, "Center"))
+      resource.mstyle.f_justify = CenterJustify;
   }
 
-  getFontElement(fontname, weight, FONT_ELEMENT_SIZE,
-                 "-medium-", "-bold-", "-demibold-", "-regular-", NULL);
-  getFontElement(fontname, slant, FONT_ELEMENT_SIZE,
-                 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL);
-  getFontSize(fontname, &pixel_size);
+  resource.mstyle.bullet = Basemenu::Triangle;
+  if (XrmGetResource(resource.stylerc, "menu.bullet", "Menu.Bullet",
+                     &value_type, &value)) {
+    if (! strncasecmp(value.addr, "empty", value.size))
+      resource.mstyle.bullet = Basemenu::Empty;
+    else if (! strncasecmp(value.addr, "square", value.size))
+      resource.mstyle.bullet = Basemenu::Square;
+    else if (! strncasecmp(value.addr, "diamond", value.size))
+      resource.mstyle.bullet = Basemenu::Diamond;
+  }
 
-  if (! strcmp(weight, "*")) strncpy(weight, "medium", FONT_ELEMENT_SIZE);
-  if (! strcmp(slant, "*")) strncpy(slant, "r", FONT_ELEMENT_SIZE);
-  if (pixel_size < 3) pixel_size = 3;
-  else if (pixel_size > 97) pixel_size = 97;
+  resource.mstyle.bullet_pos = Basemenu::Left;
+  if (XrmGetResource(resource.stylerc, "menu.bullet.position",
+                     "Menu.Bullet.Position", &value_type, &value)) {
+    if (! strncasecmp(value.addr, "right", value.size))
+      resource.mstyle.bullet_pos = Basemenu::Right;
+  }
 
-  buf_size = strlen(fontname) + (FONT_ELEMENT_SIZE * 2) + 64;
-  char *pattern2 = new char[buf_size];
-  snprintf(pattern2, buf_size - 1,
-           "%s,"
-           "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
-           "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
-           fontname, weight, slant, pixel_size, pixel_size);
-  fontname = pattern2;
+  resource.border_color =
+    readDatabaseColor("borderColor", "BorderColor", "black");
 
-  if (nmissing) XFreeStringList(missing);
-  if (fs) XFreeFontSet(getBaseDisplay().getXDisplay(), fs);
+  unsigned int uint_value;
 
-  fs = XCreateFontSet(getBaseDisplay().getXDisplay(), fontname,
-                      &missing, &nmissing, &def);
-  delete [] pattern2;
+  // load bevel, border and handle widths
+  resource.handle_width = 6;
+  if (XrmGetResource(resource.stylerc, "handleWidth", "HandleWidth",
+                     &value_type, &value) &&
+      sscanf(value.addr, "%u", &uint_value) == 1 &&
+      uint_value <= (getWidth() / 2) && uint_value != 0) {
+    resource.handle_width = uint_value;
+  }
 
-  return fs;
-}
+  resource.border_width = 1;
+  if (XrmGetResource(resource.stylerc, "borderWidth", "BorderWidth",
+                     &value_type, &value) &&
+      sscanf(value.addr, "%u", &uint_value) == 1) {
+    resource.border_width = uint_value;
+  }
 
+  resource.bevel_width = 3;
+  if (XrmGetResource(resource.stylerc, "bevelWidth", "BevelWidth",
+                     &value_type, &value) &&
+      sscanf(value.addr, "%u", &uint_value) == 1 &&
+      uint_value <= (getWidth() / 2) && uint_value != 0) {
+    resource.bevel_width = uint_value;
+  }
 
-void BScreen::setSloppyFocus(bool b) {
-  resource.sloppy_focus = b;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".focusModel" << ends;
-  config.setValue(s.str(),
-                  (resource.sloppy_focus ?
-                   (resource.auto_raise ? "AutoRaiseSloppyFocus" : "SloppyFocus")
-                   : "ClickToFocus"));
-  s.rdbuf()->freeze(0);
-}
+  resource.frame_width = resource.bevel_width;
+  if (XrmGetResource(resource.stylerc, "frameWidth", "FrameWidth",
+                     &value_type, &value) &&
+      sscanf(value.addr, "%u", &uint_value) == 1 &&
+      uint_value <= (getWidth() / 2)) {
+    resource.frame_width = uint_value;
+  }
 
+  if (XrmGetResource(resource.stylerc, "rootCommand", "RootCommand",
+                     &value_type, &value)) {
+    bexec(value.addr, displayString());
+  }
 
-void BScreen::setAutoRaise(bool a) {
-  resource.auto_raise = a;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".focusModel" << ends;
-  config.setValue(s.str(),
-                  (resource.sloppy_focus ?
-                   (resource.auto_raise ? "AutoRaiseSloppyFocus" : "SloppyFocus")
-                   : "ClickToFocus"));
-  s.rdbuf()->freeze(0);
+  XrmDestroyDatabase(resource.stylerc);
 }
 
 
-void BScreen::setImageDither(bool d, bool reconfig) {
-  image_control->setDither(d);
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".imageDither" << ends;
-  config.setValue(s.str(), imageDither());
-  if (reconfig)
-    reconfigure();
-  s.rdbuf()->freeze(0);
-}
+void BScreen::addIcon(BlackboxWindow *w) {
+  if (! w) return;
 
+  w->setWorkspace(BSENTINEL);
+  w->setWindowNumber(iconList.size());
 
-void BScreen::setOpaqueMove(bool o) {
-  resource.opaque_move = o;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".opaqueMove" << ends;
-  config.setValue(s.str(), resource.opaque_move);
-  s.rdbuf()->freeze(0);
+  iconList.push_back(w);
+
+  const char* title = w->getIconTitle();
+  iconmenu->insert(title);
+  iconmenu->update();
 }
 
 
-void BScreen::setFullMax(bool f) {
-  resource.full_max = f;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".fullMaximization" << ends;
-  config.setValue(s.str(), resource.full_max);
-  s.rdbuf()->freeze(0);
-}
+void BScreen::removeIcon(BlackboxWindow *w) {
+  if (! w) return;
 
+  iconList.remove(w);
 
-void BScreen::setFocusNew(bool f) {
-  resource.focus_new = f;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".focusNewWindows" << ends;
-  config.setValue(s.str(), resource.focus_new);
-  s.rdbuf()->freeze(0);
+  iconmenu->remove(w->getWindowNumber());
+  iconmenu->update();
+
+  BlackboxWindowList::iterator it = iconList.begin(),
+    end = iconList.end();
+  for (int i = 0; it != end; ++it)
+    (*it)->setWindowNumber(i++);
 }
 
 
-void BScreen::setFocusLast(bool f) {
-  resource.focus_last = f;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".focusLastWindow" << ends;
-  config.setValue(s.str(), resource.focus_last);
-  s.rdbuf()->freeze(0);
+BlackboxWindow *BScreen::getIcon(unsigned int index) {
+  if (index < iconList.size()) {
+    BlackboxWindowList::iterator it = iconList.begin();
+    for (; index > 0; --index, ++it) ; /* increment to index */
+    return *it;
+  }
+
+  return (BlackboxWindow *) 0;
 }
 
 
-void BScreen::setWindowZones(int z) {
-  resource.zones = z;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".windowZones" << ends;
-  config.setValue(s.str(), resource.zones);
-  s.rdbuf()->freeze(0);
-}
+unsigned int BScreen::addWorkspace(void) {
+  Workspace *wkspc = new Workspace(this, workspacesList.size());
+  workspacesList.push_back(wkspc);
 
+  workspacemenu->insert(wkspc->getName(), wkspc->getMenu(),
+                        wkspc->getID() + 2);
+  workspacemenu->update();
 
-void BScreen::setWorkspaceCount(int w) {
-  resource.workspaces = w;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".workspaces" << ends;
-  config.setValue(s.str(), resource.workspaces);
-  s.rdbuf()->freeze(0);
-}
+  toolbar->reconfigure();
 
+  updateNetizenWorkspaceCount();
 
-void BScreen::setPlacementPolicy(int p) {
-  resource.placement_policy = p;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".windowPlacement" << ends;
-  const char *placement;
-  switch (resource.placement_policy) {
-  case CascadePlacement: placement = "CascadePlacement"; break;
-  case BestFitPlacement: placement = "BestFitPlacement"; break;
-  case ColSmartPlacement: placement = "ColSmartPlacement"; break;
-  case UnderMousePlacement: placement = "UnderMousePlacement"; break;
-  case ClickMousePlacement: placement = "ClickMousePlacement"; break;
-  default:
-  case RowSmartPlacement: placement = "RowSmartPlacement"; break;
-  }
-  config.setValue(s.str(), placement);
-  s.rdbuf()->freeze(0);
+  return workspacesList.size();
 }
 
 
-void BScreen::setEdgeSnapThreshold(int t) {
-  resource.edge_snap_threshold = t;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".edgeSnapThreshold" << ends;
-  config.setValue(s.str(), resource.edge_snap_threshold);
-  s.rdbuf()->freeze(0);
-}
+unsigned int BScreen::removeLastWorkspace(void) {
+  if (workspacesList.size() == 1)
+    return 1;
 
+  Workspace *wkspc = workspacesList.back();
 
-void BScreen::setRowPlacementDirection(int d) {
-  resource.row_direction = d;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".rowPlacementDirection" << ends;
-  config.setValue(s.str(),
-                  resource.row_direction == LeftRight ?
-                  "LeftToRight" : "RightToLeft");
-  s.rdbuf()->freeze(0);
-}
+  if (current_workspace->getID() == wkspc->getID())
+    changeWorkspaceID(current_workspace->getID() - 1);
 
+  wkspc->removeAll();
 
-void BScreen::setColPlacementDirection(int d) {
-  resource.col_direction = d;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".colPlacementDirection" << ends;
-  config.setValue(s.str(),
-                  resource.col_direction == TopBottom ?
-                  "TopToBottom" : "BottomToTop");
-  s.rdbuf()->freeze(0);
-}
+  workspacemenu->remove(wkspc->getID() + 2);
+  workspacemenu->update();
 
+  workspacesList.pop_back();
+  delete wkspc;
 
-void BScreen::setRootCommand(const char *cmd) {
-  if (resource.root_command != NULL)
-    delete [] resource.root_command;
-  if (cmd != NULL)
-    resource.root_command = bstrdup(cmd);
-  else
-    resource.root_command = NULL;
-  // this doesn't save to the Resources config because it can't be changed
-  // inside Openbox, and this way we dont add an empty command which would over-
-  // ride the styles command when none has been specified
-}
+  toolbar->reconfigure();
 
+  updateNetizenWorkspaceCount();
 
-#ifdef    HAVE_STRFTIME
-void BScreen::setStrftimeFormat(const char *f) {
-  if (resource.strftime_format != NULL)
-    delete [] resource.strftime_format;
-
-  resource.strftime_format = bstrdup(f);
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".strftimeFormat" << ends;
-  config.setValue(s.str(), resource.strftime_format);
-  s.rdbuf()->freeze(0);
+  return workspacesList.size();
 }
 
-#else // !HAVE_STRFTIME
 
-void BScreen::setDateFormat(int f) {
-  resource.date_format = f;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".dateFormat" << ends;
-  config.setValue(s.str(), resource.date_format == B_EuropeanDate ?
-                  "European" : "American");
-  s.rdbuf()->freeze(0);
-}
+void BScreen::changeWorkspaceID(unsigned int id) {
+  if (! current_workspace) return;
 
+  if (id != current_workspace->getID()) {
+    current_workspace->hideAll();
 
-void BScreen::setClock24Hour(Bool c) {
-  resource.clock24hour = c;
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".clockFormat" << ends;
-  config.setValue(s.str(), resource.clock24hour ? 24 : 12);
-  s.rdbuf()->freeze(0);
-}
-#endif // HAVE_STRFTIME
+    workspacemenu->setItemSelected(current_workspace->getID() + 2, False);
 
+    if (blackbox->getFocusedWindow() &&
+        blackbox->getFocusedWindow()->getScreen() == this &&
+        (! blackbox->getFocusedWindow()->isStuck())) {
+      current_workspace->setLastFocusedWindow(blackbox->getFocusedWindow());
+      blackbox->setFocusedWindow((BlackboxWindow *) 0);
+    }
 
-void BScreen::setHideToolbar(bool b) {
-  resource.hide_toolbar = b;
-  if (resource.hide_toolbar)
-    getToolbar()->unMapToolbar();
-  else
-    getToolbar()->mapToolbar();
-  std::ostrstream s;
-  s << "session.screen" << getScreenNumber() << ".hideToolbar" << ends;
-  config.setValue(s.str(), resource.hide_toolbar ? "True" : "False");
-  s.rdbuf()->freeze(0);
-}
+    current_workspace = getWorkspace(id);
 
+    workspacemenu->setItemSelected(current_workspace->getID() + 2, True);
+    toolbar->redrawWorkspaceLabel(True);
 
-void BScreen::saveWorkspaceNames() {
-  std::ostrstream rc, names;
+    current_workspace->showAll();
 
-  wkspList::iterator it;
-  wkspList::iterator last = workspacesList.end() - 1;
-  for (it = workspacesList.begin(); it != workspacesList.end(); ++it) {
-    names << (*it)->getName();
-    if (it != last)
-      names << ",";
+    if (resource.focus_last && current_workspace->getLastFocusedWindow()) {
+      XSync(blackbox->getXDisplay(), False);
+      current_workspace->getLastFocusedWindow()->setInputFocus();
+    }
   }
-  names << ends;
 
-  rc << "session.screen" << getScreenNumber() << ".workspaceNames" << ends;
-  config.setValue(rc.str(), names.str());
-  rc.rdbuf()->freeze(0);
-  names.rdbuf()->freeze(0);
+  updateNetizenCurrentWorkspace();
 }
 
-void BScreen::save() {
-  setSloppyFocus(resource.sloppy_focus);
-  setAutoRaise(resource.auto_raise);
-  setImageDither(imageDither(), false);
-  setOpaqueMove(resource.opaque_move);
-  setFullMax(resource.full_max);
-  setFocusNew(resource.focus_new);
-  setFocusLast(resource.focus_last);
-  setWindowZones(resource.zones);
-  setWorkspaceCount(resource.workspaces);
-  setPlacementPolicy(resource.placement_policy);
-  setEdgeSnapThreshold(resource.edge_snap_threshold);
-  setRowPlacementDirection(resource.row_direction);
-  setColPlacementDirection(resource.col_direction);
-  setRootCommand(resource.root_command);
-#ifdef    HAVE_STRFTIME
-  // it deletes the current value before setting the new one, so we have to
-  // duplicate the current value.
-  std::string s = resource.strftime_format;
-  setStrftimeFormat(s.c_str()); 
-#else // !HAVE_STRFTIME
-  setDateFormat(resource.date_format);
-  setClock24Hour(resource.clock24hour);
-#endif // HAVE_STRFTIME
-  setHideToolbar(resource.hide_toolbar);
-
-  toolbar->save();
-#ifdef    SLIT
-  slit->save();
-#endif // SLIT
-}
-
-
-void BScreen::load() {
-  std::ostrstream rscreen, rname, rclass;
-  std::string s;
-  bool b;
-  long l;
-  rscreen << "session.screen" << getScreenNumber() << '.' << ends;
-
-  rname << rscreen.str() << "hideToolbar" << ends;
-  rclass << rscreen.str() << "HideToolbar" << ends;
-  if (config.getValue(rname.str(), rclass.str(), b))
-    resource.hide_toolbar = b;
-  else
-    resource.hide_toolbar = false;
-  Toolbar *t = getToolbar();
-  if (t != NULL) {
-    if (resource.hide_toolbar)
-      t->unMapToolbar();
-    else
-      t->mapToolbar();
-  }
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "fullMaximization" << ends;
-  rclass << rscreen.str() << "FullMaximization" << ends;
-  if (config.getValue(rname.str(), rclass.str(), b))
-    resource.full_max = b;
-  else
-    resource.full_max = false;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "focusNewWindows" << ends;
-  rclass << rscreen.str() << "FocusNewWindows" << ends;
-  if (config.getValue(rname.str(), rclass.str(), b))
-    resource.focus_new = b;
-  else
-    resource.focus_new = false;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "focusLastWindow" << ends;
-  rclass << rscreen.str() << "FocusLastWindow" << ends;
-  if (config.getValue(rname.str(), rclass.str(), b))
-    resource.focus_last = b;
-  else
-    resource.focus_last = false;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "rowPlacementDirection" << ends;
-  rclass << rscreen.str() << "RowPlacementDirection" << ends;
-  if (config.getValue(rname.str(), rclass.str(), s)) {
-    if (0 == strncasecmp(s.c_str(), "RightToLeft", s.length()))
-      resource.row_direction = RightLeft;
-    else //if (0 == strncasecmp(s.c_str(), "LeftToRight", s.length()))
-      resource.row_direction = LeftRight;
-  } else
-    resource.row_direction = LeftRight;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "colPlacementDirection" << ends;
-  rclass << rscreen.str() << "ColPlacementDirection" << ends;
-  if (config.getValue(rname.str(), rclass.str(), s)) {
-    if (0 == strncasecmp(s.c_str(), "BottomToTop", s.length()))
-      resource.col_direction = BottomTop;
-    else //if (0 == strncasecmp(s.c_str(), "TopToBottom", s.length()))
-      resource.col_direction = TopBottom;
-  } else
-    resource.col_direction = TopBottom;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "workspaces" << ends;
-  rclass << rscreen.str() << "Workspaces" << ends;
-  if (config.getValue(rname.str(), rclass.str(), l)) {
-    resource.workspaces = l;
-  }  else
-    resource.workspaces = 1;
-
-  removeWorkspaceNames();
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "workspaceNames" << ends;
-  rclass << rscreen.str() << "WorkspaceNames" << ends;
-  if (config.getValue(rname.str(), rclass.str(), s)) {
-    std::string::const_iterator it = s.begin(), end = s.end();
-    while(1) {
-      std::string::const_iterator tmp = it;// current string.begin()
-      it = std::find(tmp, end, ',');       // look for comma between tmp and end
-      std::string name(tmp, it);           // name = s[tmp:it]
-      addWorkspaceName(name.c_str());
-      if (it == end)
-        break;
-      ++it;
-    }
-  }
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "focusModel" << ends;
-  rclass << rscreen.str() << "FocusModel" << ends;
-  if (config.getValue(rname.str(), rclass.str(), s)) {
-    if (0 == strncasecmp(s.c_str(), "ClickToFocus", s.length())) {
-      resource.auto_raise = false;
-      resource.sloppy_focus = false;
-    } else if (0 == strncasecmp(s.c_str(), "AutoRaiseSloppyFocus",
-                                s.length())) {
-      resource.sloppy_focus = true;
-      resource.auto_raise = true;
-    } else { //if (0 == strncasecmp(s.c_str(), "SloppyFocus", s.length())) {
-      resource.sloppy_focus = true;
-      resource.auto_raise = false;
-    }
-    } else {
-      resource.sloppy_focus = true;
-      resource.auto_raise = false;
-    }
-
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "windowZones" << ends;
-    rclass << rscreen.str() << "WindowZones" << ends;
-    if (config.getValue(rname.str(), rclass.str(), l))
-      resource.zones = (l == 1 || l == 2 || l == 4) ? l : 1;
-    else
-      resource.zones = 4;
-
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "windowPlacement" << ends;
-    rclass << rscreen.str() << "WindowPlacement" << ends;
-    if (config.getValue(rname.str(), rclass.str(), s)) {
-      if (0 == strncasecmp(s.c_str(), "RowSmartPlacement", s.length()))
-        resource.placement_policy = RowSmartPlacement;
-      else if (0 == strncasecmp(s.c_str(), "ColSmartPlacement", s.length()))
-        resource.placement_policy = ColSmartPlacement;
-      else if (0 == strncasecmp(s.c_str(), "BestFitPlacement", s.length()))
-        resource.placement_policy = BestFitPlacement;
-      else if (0 == strncasecmp(s.c_str(), "UnderMousePlacement", s.length()))
-        resource.placement_policy = UnderMousePlacement;
-      else if (0 == strncasecmp(s.c_str(), "ClickMousePlacement", s.length()))
-        resource.placement_policy = ClickMousePlacement;
-      else //if (0 == strncasecmp(s.c_str(), "CascadePlacement", s.length()))
-        resource.placement_policy = CascadePlacement;
-    } else
-      resource.placement_policy = CascadePlacement;
-
-#ifdef    HAVE_STRFTIME
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "strftimeFormat" << ends;
-    rclass << rscreen.str() << "StrftimeFormat" << ends;
-
-    if (resource.strftime_format != NULL)
-      delete [] resource.strftime_format;
-
-    if (config.getValue(rname.str(), rclass.str(), s))
-      resource.strftime_format = bstrdup(s.c_str());
-    else
-      resource.strftime_format = bstrdup("%I:%M %p");
-#else // !HAVE_STRFTIME
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "dateFormat" << ends;
-    rclass << rscreen.str() << "DateFormat" << ends;
-    if (config.getValue(rname.str(), rclass.str(), s)) {
-      if (strncasecmp(s.c_str(), "European", s.length()))
-        resource.date_format = B_EuropeanDate;
-      else //if (strncasecmp(s.c_str(), "American", s.length()))
-        resource.date_format = B_AmericanDate;
-    } else
-      resource.date_format = B_AmericanDate;
-
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "clockFormat" << ends;
-    rclass << rscreen.str() << "ClockFormat" << ends;
-    if (config.getValue(rname.str(), rclass.str(), l)) {
-      if (clock == 24)
-        resource.clock24hour = true;
-      else if (clock == 12)
-        resource.clock24hour =  false;
-    } else
-      resource.clock24hour =  false;
-#endif // HAVE_STRFTIME
-
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "edgeSnapThreshold" << ends;
-    rclass << rscreen.str() << "EdgeSnapThreshold" << ends;
-    if (config.getValue(rname.str(), rclass.str(), l))
-      resource.edge_snap_threshold = l;
-    else
-      resource.edge_snap_threshold = 4;
-
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "imageDither" << ends;
-    rclass << rscreen.str() << "ImageDither" << ends;
-    if (config.getValue(rname.str(), rclass.str(), b))
-      image_control->setDither(b);
-    else
-      image_control->setDither(true);
-
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "rootCommand" << ends;
-    rclass << rscreen.str() << "RootCommand" << ends;
-
-    if (resource.root_command != NULL)
-      delete [] resource.root_command;
-
-    if (config.getValue(rname.str(), rclass.str(), s))
-      resource.root_command = bstrdup(s.c_str());
-    else
-      resource.root_command = NULL;
-
-    rname.seekp(0); rclass.seekp(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-    rname << rscreen.str() << "opaqueMove" << ends;
-    rclass << rscreen.str() << "OpaqueMove" << ends;
-    if (config.getValue(rname.str(), rclass.str(), b))
-      resource.opaque_move = b;
-    else
-      resource.opaque_move = false;
-
-    rscreen.rdbuf()->freeze(0);
-    rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  }
-
-  void BScreen::reconfigure(void) {
-    load();
-    toolbar->load();
-#ifdef    SLIT
-    slit->load();
-#endif // SLIT
-    LoadStyle();
-
-    XGCValues gcv;
-    unsigned long gc_value_mask = GCForeground;
-    if (! i18n.multibyte()) gc_value_mask |= GCFont;
-
-    gcv.foreground = WhitePixel(getBaseDisplay().getXDisplay(),
-                                getScreenNumber());
-    gcv.function = GXinvert;
-    gcv.subwindow_mode = IncludeInferiors;
-    XChangeGC(getBaseDisplay().getXDisplay(), opGC,
-              GCForeground | GCFunction | GCSubwindowMode, &gcv);
-
-    gcv.foreground = resource.wstyle.l_text_focus.getPixel();
-    if (resource.wstyle.font)
-      gcv.font = resource.wstyle.font->fid;
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.l_text_focus_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.wstyle.l_text_unfocus.getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.l_text_unfocus_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.wstyle.b_pic_focus.getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.b_pic_focus_gc,
-              GCForeground, &gcv);
-
-    gcv.foreground = resource.wstyle.b_pic_unfocus.getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.b_pic_unfocus_gc,
-              GCForeground, &gcv);
-
-    gcv.foreground = resource.mstyle.t_text.getPixel();
-    if (resource.mstyle.t_font)
-      gcv.font = resource.mstyle.t_font->fid;
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.t_text_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.mstyle.f_text.getPixel();
-    if (resource.mstyle.f_font)
-      gcv.font = resource.mstyle.f_font->fid;
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.f_text_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.mstyle.h_text.getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.h_text_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.mstyle.d_text.getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.d_text_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.mstyle.hilite.getColor()->getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.hilite_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.tstyle.l_text.getPixel();
-    if (resource.tstyle.font)
-      gcv.font = resource.tstyle.font->fid;
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.l_text_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.tstyle.w_text.getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.w_text_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.tstyle.c_text.getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.c_text_gc,
-              gc_value_mask, &gcv);
-
-    gcv.foreground = resource.tstyle.b_pic.getPixel();
-    XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.b_pic_gc,
-              gc_value_mask, &gcv);
-
-    const char *s = i18n(ScreenSet, ScreenPositionLength,
-                         "0: 0000 x 0: 0000");
-    int l = strlen(s);
-
-    if (i18n.multibyte()) {
-      XRectangle ink, logical;
-      XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical);
-      geom_w = logical.width;
-
-      geom_h = resource.wstyle.fontset_extents->max_ink_extent.height;
-    } else {
-      geom_w = XTextWidth(resource.wstyle.font, s, l);
 
-      geom_h = resource.wstyle.font->ascent +
-        resource.wstyle.font->descent; 
-    }
-
-    geom_w += (resource.bevel_width * 2);
-    geom_h += (resource.bevel_width * 2);
+void BScreen::manageWindow(Window w) {
+  new BlackboxWindow(blackbox, w, this);
 
-    Pixmap tmp = geom_pixmap;
-    if (resource.wstyle.l_focus.getTexture() & BImage_ParentRelative) {
-      if (resource.wstyle.t_focus.getTexture() ==
-          (BImage_Flat | BImage_Solid)) {
-        geom_pixmap = None;
-        XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
-                             resource.wstyle.t_focus.getColor()->getPixel());
-      } else {
-        geom_pixmap = image_control->renderImage(geom_w, geom_h,
-                                                 &resource.wstyle.t_focus);
-        XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
-                                   geom_window, geom_pixmap);
-      }
-    } else {
-      if (resource.wstyle.l_focus.getTexture() ==
-          (BImage_Flat | BImage_Solid)) {
-        geom_pixmap = None;
-        XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
-                             resource.wstyle.l_focus.getColor()->getPixel());
-      } else {
-        geom_pixmap = image_control->renderImage(geom_w, geom_h,
-                                                 &resource.wstyle.l_focus);
-        XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
-                                   geom_window, geom_pixmap);
-      }
-    }
-    if (tmp) image_control->removeImage(tmp);
-
-    XSetWindowBorderWidth(getBaseDisplay().getXDisplay(), geom_window,
-                          resource.border_width);
-    XSetWindowBorder(getBaseDisplay().getXDisplay(), geom_window,
-                     resource.border_color.getPixel());
-
-    workspacemenu->reconfigure();
-    iconmenu->reconfigure();
-
-    {
-      int remember_sub = rootmenu->getCurrentSubmenu();
-      InitMenu();
-      raiseWindows(0, 0);
-      rootmenu->reconfigure();
-      rootmenu->drawSubmenu(remember_sub);
-    }
+  BlackboxWindow *win = blackbox->searchWindow(w);
+  if (! win)
+    return;
 
-    configmenu->reconfigure();
+  windowList.push_back(win);
 
-    toolbar->reconfigure();
+  XMapRequestEvent mre;
+  mre.window = w;
+  win->restoreAttributes();
+  win->mapRequestEvent(&mre);
+}
 
-#ifdef    SLIT
-    slit->reconfigure();
-#endif // SLIT
 
-    std::for_each(workspacesList.begin(), workspacesList.end(),
-                  std::mem_fun(&Workspace::reconfigure));
+void BScreen::unmanageWindow(BlackboxWindow *w, bool remap) {
+  w->restore(remap);
 
-    for (winList::iterator it = iconList.begin(); it != iconList.end(); ++it)
-      if ((*it)->validateClient())
-        (*it)->reconfigure();
+  if (w->getWorkspaceNumber() != BSENTINEL &&
+      w->getWindowNumber() != BSENTINEL)
+    getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
+  else if (w->isIconic())
+    removeIcon(w);
 
-    image_control->timeout();
-  }
+  windowList.remove(w);
 
+  if (blackbox->getFocusedWindow() == w)
+    blackbox->setFocusedWindow((BlackboxWindow *) 0);
 
-  void BScreen::rereadMenu(void) {
-    InitMenu();
-    raiseWindows(0, 0);
+  removeNetizen(w->getClientWindow());
 
-    rootmenu->reconfigure();
-  }
+  delete w;
+}
 
 
-  void BScreen::removeWorkspaceNames(void) {
-    workspaceNames.clear();
-  }
+void BScreen::addNetizen(Netizen *n) {
+  netizenList.push_back(n);
 
+  n->sendWorkspaceCount();
+  n->sendCurrentWorkspace();
 
-  void BScreen::LoadStyle(void) {
-    Resource &conf = resource.styleconfig;
+  WorkspaceList::iterator it = workspacesList.begin();
+  const WorkspaceList::iterator end = workspacesList.end();
+  for (; it != end; ++it)
+    (*it)->sendWindowList(*n);
 
-    const char *sfile = openbox.getStyleFilename();
-    bool loaded = false;
-    if (sfile != NULL) {
-      conf.setFile(sfile);
-      loaded = conf.load();
-    }
-    if (!loaded) {
-      conf.setFile(DEFAULTSTYLE);
-      if (!conf.load()) {
-        fprintf(stderr, i18n(ScreenSet, ScreenDefaultStyleLoadFail,
-                             "BScreen::LoadStyle(): couldn't load "
-                             "default style.\n"));
-        exit(2);
-      }
-    }
+  Window f = ((blackbox->getFocusedWindow()) ?
+              blackbox->getFocusedWindow()->getClientWindow() : None);
+  n->sendWindowFocus(f);
+}
 
-    std::string s;
-    long l;
-
-    // load fonts/fontsets
-
-    if (i18n.multibyte()) {
-      readDatabaseFontSet("window.font", "Window.Font",
-                          &resource.wstyle.fontset);
-      readDatabaseFontSet("toolbar.font", "Toolbar.Font",
-                          &resource.tstyle.fontset);
-      readDatabaseFontSet("menu.title.font", "Menu.Title.Font",
-                          &resource.mstyle.t_fontset);
-      readDatabaseFontSet("menu.frame.font", "Menu.Frame.Font",
-                          &resource.mstyle.f_fontset);
-
-      resource.mstyle.t_fontset_extents =
-        XExtentsOfFontSet(resource.mstyle.t_fontset);
-      resource.mstyle.f_fontset_extents =
-        XExtentsOfFontSet(resource.mstyle.f_fontset);
-      resource.tstyle.fontset_extents =
-        XExtentsOfFontSet(resource.tstyle.fontset);
-      resource.wstyle.fontset_extents =
-        XExtentsOfFontSet(resource.wstyle.fontset);
-    } else {
-      readDatabaseFont("window.font", "Window.Font",
-                       &resource.wstyle.font);
-      readDatabaseFont("menu.title.font", "Menu.Title.Font",
-                       &resource.mstyle.t_font);
-      readDatabaseFont("menu.frame.font", "Menu.Frame.Font",
-                       &resource.mstyle.f_font);
-      readDatabaseFont("toolbar.font", "Toolbar.Font",
-                       &resource.tstyle.font);
-    }
 
-    // load window config
-    readDatabaseTexture("window.title.focus", "Window.Title.Focus",
-                        &resource.wstyle.t_focus,
-                        WhitePixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.title.unfocus", "Window.Title.Unfocus",
-                        &resource.wstyle.t_unfocus,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.label.focus", "Window.Label.Focus",
-                        &resource.wstyle.l_focus,
-                        WhitePixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.label.unfocus", "Window.Label.Unfocus",
-                        &resource.wstyle.l_unfocus,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.handle.focus", "Window.Handle.Focus",
-                        &resource.wstyle.h_focus,
-                        WhitePixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.handle.unfocus", "Window.Handle.Unfocus",
-                        &resource.wstyle.h_unfocus,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.grip.focus", "Window.Grip.Focus",
-                        &resource.wstyle.g_focus,
-                        WhitePixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.grip.unfocus", "Window.Grip.Unfocus",
-                        &resource.wstyle.g_unfocus,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.button.focus", "Window.Button.Focus",
-                        &resource.wstyle.b_focus,
-                        WhitePixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.button.unfocus", "Window.Button.Unfocus",
-                        &resource.wstyle.b_unfocus,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("window.button.pressed", "Window.Button.Pressed",
-                        &resource.wstyle.b_pressed,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseColor("window.frame.focusColor",
-                      "Window.Frame.FocusColor",
-                      &resource.wstyle.f_focus,
-                      WhitePixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("window.frame.unfocusColor",
-                      "Window.Frame.UnfocusColor",
-                      &resource.wstyle.f_unfocus,
-                      BlackPixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("window.label.focus.textColor",
-                      "Window.Label.Focus.TextColor",
-                      &resource.wstyle.l_text_focus,
-                      BlackPixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("window.label.unfocus.textColor",
-                      "Window.Label.Unfocus.TextColor",
-                      &resource.wstyle.l_text_unfocus,
-                      WhitePixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("window.button.focus.picColor",
-                      "Window.Button.Focus.PicColor",
-                      &resource.wstyle.b_pic_focus,
-                      BlackPixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("window.button.unfocus.picColor",
-                      "Window.Button.Unfocus.PicColor",
-                      &resource.wstyle.b_pic_unfocus,
-                      WhitePixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-
-    if (conf.getValue("window.justify", "Window.Justify", s)) {
-      if (0 == strncasecmp(s.c_str(), "right", s.length()))
-        resource.wstyle.justify = BScreen::RightJustify;
-      else if (0 == strncasecmp(s.c_str(), "center", s.length()))
-        resource.wstyle.justify = BScreen::CenterJustify;
-      else
-        resource.wstyle.justify = BScreen::LeftJustify;
-    } else
-      resource.wstyle.justify = BScreen::LeftJustify;
-
-    // load toolbar config
-    readDatabaseTexture("toolbar", "Toolbar",
-                        &resource.tstyle.toolbar,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("toolbar.label", "Toolbar.Label",
-                        &resource.tstyle.label,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("toolbar.windowLabel", "Toolbar.WindowLabel",
-                        &resource.tstyle.window,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("toolbar.button", "Toolbar.Button",
-                        &resource.tstyle.button,
-                        WhitePixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("toolbar.button.pressed", "Toolbar.Button.Pressed",
-                        &resource.tstyle.pressed,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("toolbar.clock", "Toolbar.Clock",
-                        &resource.tstyle.clock,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseColor("toolbar.label.textColor", "Toolbar.Label.TextColor",
-                      &resource.tstyle.l_text,
-                      WhitePixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("toolbar.windowLabel.textColor",
-                      "Toolbar.WindowLabel.TextColor",
-                      &resource.tstyle.w_text,
-                      WhitePixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("toolbar.clock.textColor", "Toolbar.Clock.TextColor",
-                      &resource.tstyle.c_text,
-                      WhitePixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("toolbar.button.picColor", "Toolbar.Button.PicColor",
-                      &resource.tstyle.b_pic,
-                      BlackPixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-
-    if (conf.getValue("toolbar.justify", "Toolbar.Justify", s)) {
-      if (0 == strncasecmp(s.c_str(), "right", s.length()))
-        resource.tstyle.justify = BScreen::RightJustify;
-      else if (0 == strncasecmp(s.c_str(), "center", s.length()))
-        resource.tstyle.justify = BScreen::CenterJustify;
-      else
-        resource.tstyle.justify = BScreen::LeftJustify;
-    } else
-      resource.tstyle.justify = BScreen::LeftJustify;
-
-    // load menu config
-    readDatabaseTexture("menu.title", "Menu.Title",
-                        &resource.mstyle.title,
-                        WhitePixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("menu.frame", "Menu.Frame",
-                        &resource.mstyle.frame,
-                        BlackPixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseTexture("menu.hilite", "Menu.Hilite",
-                        &resource.mstyle.hilite,
-                        WhitePixel(getBaseDisplay().getXDisplay(),
-                                   getScreenNumber()));
-    readDatabaseColor("menu.title.textColor", "Menu.Title.TextColor",
-                      &resource.mstyle.t_text,
-                      BlackPixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("menu.frame.textColor", "Menu.Frame.TextColor",
-                      &resource.mstyle.f_text,
-                      WhitePixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("menu.frame.disableColor", "Menu.Frame.DisableColor",
-                      &resource.mstyle.d_text,
-                      BlackPixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-    readDatabaseColor("menu.hilite.textColor", "Menu.Hilite.TextColor",
-                      &resource.mstyle.h_text,
-                      BlackPixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-
-    if (conf.getValue("menu.title.justify", "Menu.Title.Justify", s)) {
-      if (0 == strncasecmp(s.c_str(), "right", s.length()))
-        resource.mstyle.t_justify = BScreen::RightJustify;
-      else if (0 == strncasecmp(s.c_str(), "center", s.length()))
-        resource.mstyle.t_justify = BScreen::CenterJustify;
-      else
-        resource.mstyle.t_justify = BScreen::LeftJustify;
-    } else
-      resource.mstyle.t_justify = BScreen::LeftJustify;
-
-    if (conf.getValue("menu.frame.justify", "Menu.Frame.Justify", s)) {
-      if (0 == strncasecmp(s.c_str(), "right", s.length()))
-        resource.mstyle.f_justify = BScreen::RightJustify;
-      else if (0 == strncasecmp(s.c_str(), "center", s.length()))
-        resource.mstyle.f_justify = BScreen::CenterJustify;
-      else
-        resource.mstyle.f_justify = BScreen::LeftJustify;
-    } else
-      resource.mstyle.f_justify = BScreen::LeftJustify;
-
-    if (conf.getValue("menu.bullet", "Menu.Bullet", s)) {
-      if (0 == strncasecmp(s.c_str(), "empty", s.length()))
-        resource.mstyle.bullet = Basemenu::Empty;
-      else if (0 == strncasecmp(s.c_str(), "square", s.length()))
-        resource.mstyle.bullet = Basemenu::Square;
-      else if (0 == strncasecmp(s.c_str(), "diamond", s.length()))
-        resource.mstyle.bullet = Basemenu::Diamond;
-      else
-        resource.mstyle.bullet = Basemenu::Triangle;
-    } else
-      resource.mstyle.bullet = Basemenu::Triangle;
-
-    if (conf.getValue("menu.bullet.position", "Menu.Bullet.Position", s)) {
-      if (0 == strncasecmp(s.c_str(), "right", s.length()))
-        resource.mstyle.bullet_pos = Basemenu::Right;
-      else
-        resource.mstyle.bullet_pos = Basemenu::Left;
-    } else
-      resource.mstyle.bullet_pos = Basemenu::Left;
-
-    readDatabaseColor("borderColor", "BorderColor", &resource.border_color,
-                      BlackPixel(getBaseDisplay().getXDisplay(),
-                                 getScreenNumber()));
-
-    // load bevel, border and handle widths
-    if (conf.getValue("handleWidth", "HandleWidth", l)) {
-      if (l <= (signed)size().w() / 2 && l != 0)
-        resource.handle_width = l;
-      else
-        resource.handle_width = 6;
-    } else
-      resource.handle_width = 6;
-
-    if (conf.getValue("borderWidth", "BorderWidth", l))
-      resource.border_width = l;
-    else
-      resource.border_width = 1;
-
-    if (conf.getValue("bevelWidth", "BevelWidth", l)) {
-      if (l <= (signed)size().w() / 2 && l != 0)
-        resource.bevel_width = l;
-      else
-        resource.bevel_width = 3;
-    } else
-      resource.bevel_width = 3;
-
-    if (conf.getValue("frameWidth", "FrameWidth", l)) {
-      if (l <= (signed)size().w() / 2)
-        resource.frame_width = l;
-      else
-        resource.frame_width = resource.bevel_width;
-    } else
-      resource.frame_width = resource.bevel_width;
-
-    const char *cmd = resource.root_command;
-    if (cmd != NULL || conf.getValue("rootCommand", "RootCommand", s)) {
-      if (cmd == NULL)
-        cmd = s.c_str(); // not specified by the screen, so use the one from the
-      // style file
-#ifndef    __EMX__
-      char displaystring[MAXPATHLEN];
-      sprintf(displaystring, "DISPLAY=%s",
-              DisplayString(getBaseDisplay().getXDisplay()));
-      sprintf(displaystring + strlen(displaystring) - 1, "%d",
-              getScreenNumber());
-
-      bexec(cmd, displaystring);
-#else //   __EMX__
-      spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", cmd, NULL);
-#endif // !__EMX__
+void BScreen::removeNetizen(Window w) {
+  NetizenList::iterator it = netizenList.begin();
+  for (; it != netizenList.end(); ++it) {
+    if ((*it)->getWindowID() == w) {
+      delete *it;
+      netizenList.erase(it);
+      break;
     }
   }
+}
 
 
-  void BScreen::addIcon(OpenboxWindow *w) {
-    if (! w) return;
-
-    w->setWorkspace(-1);
-    w->setWindowNumber(iconList.size());
-
-    iconList.push_back(w);
-
-    iconmenu->insert((const char **) w->getIconTitle());
-    iconmenu->update();
-  }
-
-
-  void BScreen::removeIcon(OpenboxWindow *w) {
-    if (! w) return;
-
-    iconList.remove(w);
-
-    iconmenu->remove(w->getWindowNumber());
-    iconmenu->update();
-
-    winList::iterator it = iconList.begin();
-    for (int i = 0; it != iconList.end(); ++it, ++i)
-      (*it)->setWindowNumber(i);
-  }
-
-
-  OpenboxWindow *BScreen::getIcon(int index) {
-    if (index < 0 || index >= (signed)iconList.size())
-      return (OpenboxWindow *) 0;
-
-    winList::iterator it = iconList.begin();
-    for (; index > 0; --index, ++it);     // increment to index
-    return *it;
-  }
+void BScreen::updateNetizenCurrentWorkspace(void) {
+  std::for_each(netizenList.begin(), netizenList.end(),
+                std::mem_fun(&Netizen::sendCurrentWorkspace));
+}
 
 
-  int BScreen::addWorkspace(void) {
-    Workspace *wkspc = new Workspace(*this, workspacesList.size());
-    workspacesList.push_back(wkspc);
-    setWorkspaceCount(workspaceCount()+1);
-    saveWorkspaceNames();
+void BScreen::updateNetizenWorkspaceCount(void) {
+  std::for_each(netizenList.begin(), netizenList.end(),
+                std::mem_fun(&Netizen::sendWorkspaceCount));
+}
 
-    workspacemenu->insert(wkspc->getName(), wkspc->getMenu(),
-                          wkspc->getWorkspaceID() + 2);
-    workspacemenu->update();
 
-    toolbar->reconfigure();
+void BScreen::updateNetizenWindowFocus(void) {
+  Window f = ((blackbox->getFocusedWindow()) ?
+              blackbox->getFocusedWindow()->getClientWindow() : None);
+  NetizenList::iterator it = netizenList.begin();
+  for (; it != netizenList.end(); ++it)
+    (*it)->sendWindowFocus(f);
+}
 
-    updateNetizenWorkspaceCount();
 
-    return workspacesList.size();
+void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
+  NetizenList::iterator it = netizenList.begin();
+  for (; it != netizenList.end(); ++it) {
+    (*it)->sendWindowAdd(w, p);
   }
+}
 
 
-  int BScreen::removeLastWorkspace(void) {
-    if (workspacesList.size() == 1)
-      return 0;
-
-    Workspace *wkspc = workspacesList.back();
-
-    if (current_workspace->getWorkspaceID() == wkspc->getWorkspaceID())
-      changeWorkspaceID(current_workspace->getWorkspaceID() - 1);
-
-    wkspc->removeAll();
-
-    workspacemenu->remove(wkspc->getWorkspaceID() + 2);
-    workspacemenu->update();
-
-    workspacesList.pop_back();
-    delete wkspc;
-
-    setWorkspaceCount(workspaceCount()-1);
-    saveWorkspaceNames();
-
-    toolbar->reconfigure();
+void BScreen::updateNetizenWindowDel(Window w) {
+  NetizenList::iterator it = netizenList.begin();
+  for (; it != netizenList.end(); ++it)
+    (*it)->sendWindowDel(w);
+}
 
-    updateNetizenWorkspaceCount();
-
-    return workspacesList.size();
-  }
 
+void BScreen::updateNetizenWindowRaise(Window w) {
+  NetizenList::iterator it = netizenList.begin();
+  for (; it != netizenList.end(); ++it)
+    (*it)->sendWindowRaise(w);
+}
 
-  void BScreen::changeWorkspaceID(int id) {
-    if (! current_workspace) return;
 
-    if (id != current_workspace->getWorkspaceID()) {
-      current_workspace->hideAll();
+void BScreen::updateNetizenWindowLower(Window w) {
+  NetizenList::iterator it = netizenList.begin();
+  for (; it != netizenList.end(); ++it)
+    (*it)->sendWindowLower(w);
+}
 
-      workspacemenu->setItemSelected(current_workspace->getWorkspaceID() + 2,
-                                     False);
 
-    OpenboxWindow *fw = openbox.focusedWindow();
-    if (fw && fw->getScreen() == this)
-      openbox.focusWindow(0);
+void BScreen::updateNetizenConfigNotify(XEvent *e) {
+  NetizenList::iterator it = netizenList.begin();
+  for (; it != netizenList.end(); ++it)
+    (*it)->sendConfigNotify(e);
+}
 
-      current_workspace = getWorkspace(id);
 
-      workspacemenu->setItemSelected(current_workspace->getWorkspaceID() + 2,
-                                     True);
-      toolbar->redrawWorkspaceLabel(True);
+void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) {
+  // XXX: why 13??
+  Window *session_stack = new
+    Window[(num + workspacesList.size() + rootmenuList.size() + 13)];
+  unsigned int i = 0, k = num;
 
-      current_workspace->showAll();
+  XRaiseWindow(blackbox->getXDisplay(), iconmenu->getWindowID());
+  *(session_stack + i++) = iconmenu->getWindowID();
 
-      if (resource.focus_last && current_workspace->lastFocusedWindow()) {
-        XSync(openbox.getXDisplay(), False);
-        current_workspace->lastFocusedWindow()->setInputFocus();
-      }
-    }
+  WorkspaceList::iterator wit = workspacesList.begin();
+  const WorkspaceList::iterator w_end = workspacesList.end();
+  for (; wit != w_end; ++wit)
+    *(session_stack + i++) = (*wit)->getMenu()->getWindowID();
 
-    updateNetizenCurrentWorkspace();
-  }
+  *(session_stack + i++) = workspacemenu->getWindowID();
 
+  *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID();
+  *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID();
+  *(session_stack + i++) = configmenu->getWindowID();
 
-  void BScreen::addNetizen(Netizen *n) {
-    netizenList.push_back(n);
+  *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID();
+  *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID();
+  *(session_stack + i++) = slit->getMenu()->getWindowID();
 
-    n->sendWorkspaceCount();
-    n->sendCurrentWorkspace();
+  *(session_stack + i++) =
+    toolbar->getMenu()->getPlacementmenu()->getWindowID();
+  *(session_stack + i++) = toolbar->getMenu()->getWindowID();
 
-    wkspList::iterator it;
-    for (it = workspacesList.begin(); it != workspacesList.end(); ++it) {
-      for (int i = 0; i < (*it)->getCount(); i++)
-        n->sendWindowAdd((*it)->getWindow(i)->getClientWindow(),
-                         (*it)->getWorkspaceID());
-    }
+  RootmenuList::iterator rit = rootmenuList.begin();
+  for (; rit != rootmenuList.end(); ++rit)
+    *(session_stack + i++) = (*rit)->getWindowID();
+  *(session_stack + i++) = rootmenu->getWindowID();
 
-    Window f = ((openbox.focusedWindow()) ?
-                openbox.focusedWindow()->getClientWindow() : None);
-    n->sendWindowFocus(f);
-  }
+  if (toolbar->isOnTop())
+    *(session_stack + i++) = toolbar->getWindowID();
 
+  if (slit->isOnTop())
+    *(session_stack + i++) = slit->getWindowID();
 
-  void BScreen::removeNetizen(Window w) {
-    netList::iterator it;
+  while (k--)
+    *(session_stack + i++) = *(workspace_stack + k);
 
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      if ((*it)->getWindowID() == w) {
-        Netizen *tmp = *it;
-        netizenList.erase(it);
-        delete tmp;
-        break;
-      }
-  }
+  XRestackWindows(blackbox->getXDisplay(), session_stack, i);
 
+  delete [] session_stack;
+}
 
-  void BScreen::updateNetizenCurrentWorkspace(void) {
-    netList::iterator it;
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      (*it)->sendCurrentWorkspace();
-  }
 
+#ifdef    HAVE_STRFTIME
+void BScreen::saveStrftimeFormat(const string& format) {
+  resource.strftime_format = format;
+}
+#endif // HAVE_STRFTIME
 
-  void BScreen::updateNetizenWorkspaceCount(void) {
-    netList::iterator it;
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      (*it)->sendWorkspaceCount();
-  }
 
+void BScreen::addWorkspaceName(const string& name) {
+  workspaceNames.push_back(name);
+}
 
-  void BScreen::updateNetizenWindowFocus(void) {
-    Window f = ((openbox.focusedWindow()) ?
-                openbox.focusedWindow()->getClientWindow() : None);
-    netList::iterator it;
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      (*it)->sendWindowFocus(f);
-  }
 
+/*
+ * I would love to kill this function and the accompanying workspaceNames
+ * list.  However, we have a chicken and egg situation.  The names are read
+ * in during load_rc() which happens before the workspaces are created.
+ * The current solution is to read the names into a list, then use the list
+ * later for constructing the workspaces.  It is only used during initial
+ * BScreen creation.
+ */
+const string BScreen::getNameOfWorkspace(unsigned int id) {
+  if (id < workspaceNames.size())
+    return workspaceNames[id];
+  return string("");
+}
 
-  void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
-    netList::iterator it;
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      (*it)->sendWindowAdd(w, p);
-  }
 
+void BScreen::reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id,
+                                bool ignore_sticky) {
+  if (! w) return;
 
-  void BScreen::updateNetizenWindowDel(Window w) {
-    netList::iterator it;
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      (*it)->sendWindowDel(w);
-  }
+  if (wkspc_id == BSENTINEL)
+    wkspc_id = current_workspace->getID();
 
+  if (w->getWorkspaceNumber() == wkspc_id)
+    return;
 
-  void BScreen::updateNetizenWindowRaise(Window w) {
-    netList::iterator it;
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      (*it)->sendWindowRaise(w);
+  if (w->isIconic()) {
+    removeIcon(w);
+    getWorkspace(wkspc_id)->addWindow(w);
+  } else if (ignore_sticky || ! w->isStuck()) {
+    getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
+    getWorkspace(wkspc_id)->addWindow(w);
   }
+}
 
 
-  void BScreen::updateNetizenWindowLower(Window w) {
-    netList::iterator it;
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      (*it)->sendWindowLower(w);
+void BScreen::propagateWindowName(const BlackboxWindow *bw) {
+  if (bw->isIconic()) {
+    iconmenu->changeItemLabel(bw->getWindowNumber(), bw->getIconTitle());
+    iconmenu->update();
   }
+  else {
+    Clientmenu *clientmenu = getWorkspace(bw->getWorkspaceNumber())->getMenu();
+    clientmenu->changeItemLabel(bw->getWindowNumber(), bw->getTitle());
+    clientmenu->update();
 
-
-  void BScreen::updateNetizenConfigNotify(XEvent *e) {
-    netList::iterator it;
-    for (it = netizenList.begin(); it != netizenList.end(); ++it)
-      (*it)->sendConfigNotify(e);
+    if (blackbox->getFocusedWindow() == bw)
+      toolbar->redrawWindowLabel(True);
   }
+}
 
 
-  void BScreen::raiseWindows(Window *workspace_stack, int num) {
-    Window *session_stack = new
-      Window[(num + workspacesList.size() + rootmenuList.size() + 13)];
-    int i = 0, k = num;
-
-    XRaiseWindow(getBaseDisplay().getXDisplay(), iconmenu->getWindowID());
-    *(session_stack + i++) = iconmenu->getWindowID();
-
-    wkspList::iterator it;
-    for (it = workspacesList.begin(); it != workspacesList.end(); ++it)
-      *(session_stack + i++) = (*it)->getMenu()->getWindowID();
-
-    *(session_stack + i++) = workspacemenu->getWindowID();
-
-    *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID();
-    *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID();
-    *(session_stack + i++) = configmenu->getWindowID();
-
-#ifdef    SLIT
-    *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID();
-    *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID();
-    *(session_stack + i++) = slit->getMenu()->getWindowID();
-#endif // SLIT
-
-    *(session_stack + i++) =
-      toolbar->getMenu()->getPlacementmenu()->getWindowID();
-    *(session_stack + i++) = toolbar->getMenu()->getWindowID();
-
-    menuList::iterator rit;
-    for (rit = rootmenuList.begin(); rit != rootmenuList.end(); ++rit)
-      *(session_stack + i++) = (*rit)->getWindowID();
-    *(session_stack + i++) = rootmenu->getWindowID();
-
-    if (toolbar->onTop())
-      *(session_stack + i++) = toolbar->getWindowID();
-
-#ifdef    SLIT
-    if (slit->onTop())
-      *(session_stack + i++) = slit->getWindowID();
-#endif // SLIT
-
-    while (k--)
-      *(session_stack + i++) = *(workspace_stack + k);
-
-    XRestackWindows(getBaseDisplay().getXDisplay(), session_stack, i);
+void BScreen::nextFocus(void) {
+  BlackboxWindow *focused = blackbox->getFocusedWindow(),
+    *next = focused;
 
-    delete [] session_stack;
+  if (focused) {
+    // if window is not on this screen, ignore it
+    if (focused->getScreen()->getScreenNumber() != getScreenNumber())
+      focused = (BlackboxWindow*) 0;
   }
 
+  if (focused && current_workspace->getCount() > 1) {
+    // next is the next window to recieve focus, current is a place holder
+    BlackboxWindow *current;
+    do {
+      current = next;
+      next = current_workspace->getNextWindowInList(current);
+    } while(!next->setInputFocus() && next != focused);
 
-  void BScreen::addWorkspaceName(const char *name) {
-    workspaceNames.push_back(name);
-  }
-
+    if (next != focused)
+      current_workspace->raiseWindow(next);
+  } else if (current_workspace->getCount() >= 1) {
+    next = current_workspace->getTopWindowOnStack();
 
-  const char *BScreen::getNameOfWorkspace(int id) {
-    if (id < 0 || id >= (signed)workspaceNames.size())
-      return (const char *) 0;
-    return workspaceNames[id].c_str();
+    current_workspace->raiseWindow(next);
+    next->setInputFocus();
   }
+}
 
 
-  void BScreen::reassociateWindow(OpenboxWindow *w, int wkspc_id, Bool ignore_sticky) {
-    if (! w) return;
-
-    if (wkspc_id == -1)
-      wkspc_id = current_workspace->getWorkspaceID();
-
-    if (w->getWorkspaceNumber() == wkspc_id)
-      return;
+void BScreen::prevFocus(void) {
+  BlackboxWindow *focused = blackbox->getFocusedWindow(),
+    *next = focused;
 
-    if (w->isIconic()) {
-      removeIcon(w);
-      getWorkspace(wkspc_id)->addWindow(w);
-    } else if (ignore_sticky || ! w->isStuck()) {
-      getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
-      getWorkspace(wkspc_id)->addWindow(w);
-    }
+  if (focused) {
+    // if window is not on this screen, ignore it
+    if (focused->getScreen()->getScreenNumber() != getScreenNumber())
+      focused = (BlackboxWindow*) 0;
   }
 
+  if (focused && current_workspace->getCount() > 1) {
+    // next is the next window to recieve focus, current is a place holder
+    BlackboxWindow *current;
+    do {
+      current = next;
+      next = current_workspace->getPrevWindowInList(current);
+    } while(!next->setInputFocus() && next != focused);
 
-  void BScreen::nextFocus(void) {
-    Bool have_focused = False;
-    int focused_window_number = -1;
-    OpenboxWindow *next;
-
-    if (openbox.focusedWindow()) {
-      if (openbox.focusedWindow()->getScreen()->getScreenNumber() ==
-          getScreenNumber()) {
-        have_focused = True;
-        focused_window_number = openbox.focusedWindow()->getWindowNumber();
-      }
-    }
-
-    if ((getCurrentWorkspace()->getCount() > 1) && have_focused) {
-      int next_window_number = focused_window_number;
-      do {
-        if ((++next_window_number) >= getCurrentWorkspace()->getCount())
-          next_window_number = 0;
-
-        next = getCurrentWorkspace()->getWindow(next_window_number);
-      } while ((! next->setInputFocus()) && (next_window_number !=
-                                             focused_window_number));
-
-      if (next_window_number != focused_window_number)
-        getCurrentWorkspace()->raiseWindow(next);
-    } else if (getCurrentWorkspace()->getCount() >= 1) {
-      next = current_workspace->getWindow(0);
-
+    if (next != focused)
       current_workspace->raiseWindow(next);
-      next->setInputFocus();
-    }
-  }
-
+  } else if (current_workspace->getCount() >= 1) {
+    next = current_workspace->getTopWindowOnStack();
 
-  void BScreen::prevFocus(void) {
-    Bool have_focused = False;
-    int focused_window_number = -1;
-    OpenboxWindow *prev;
-
-    if (openbox.focusedWindow()) {
-      if (openbox.focusedWindow()->getScreen()->getScreenNumber() ==
-          getScreenNumber()) {
-        have_focused = True;
-        focused_window_number = openbox.focusedWindow()->getWindowNumber();
-      }
-    }
-
-    if ((getCurrentWorkspace()->getCount() > 1) && have_focused) {
-      int prev_window_number = focused_window_number;
-      do {
-        if ((--prev_window_number) < 0)
-          prev_window_number = getCurrentWorkspace()->getCount() - 1;
+    current_workspace->raiseWindow(next);
+    next->setInputFocus();
+  }
+}
 
-        prev = getCurrentWorkspace()->getWindow(prev_window_number);
-      } while ((! prev->setInputFocus()) && (prev_window_number !=
-                                             focused_window_number));
 
-      if (prev_window_number != focused_window_number)
-        getCurrentWorkspace()->raiseWindow(prev);
-    } else if (getCurrentWorkspace()->getCount() >= 1) {
-      prev = current_workspace->getWindow(0);
+void BScreen::raiseFocus(void) {
+  BlackboxWindow *focused = blackbox->getFocusedWindow();
+  if (! focused)
+    return;
 
-      current_workspace->raiseWindow(prev);
-      prev->setInputFocus();
-    }
+  // if on this Screen, raise it
+  if (focused->getScreen()->getScreenNumber() == getScreenNumber()) {
+    Workspace *workspace = getWorkspace(focused->getWorkspaceNumber());
+    workspace->raiseWindow(focused);
   }
+}
 
 
-  void BScreen::raiseFocus(void) {
-    Bool have_focused = False;
-    int focused_window_number = -1;
+void BScreen::InitMenu(void) {
+  if (rootmenu) {
+    rootmenuList.clear();
 
-    if (openbox.focusedWindow()) {
-      if (openbox.focusedWindow()->getScreen()->getScreenNumber() ==
-          getScreenNumber()) {
-        have_focused = True;
-        focused_window_number = openbox.focusedWindow()->getWindowNumber();
-      }
-    }
-
-    if ((getCurrentWorkspace()->getCount() > 1) && have_focused)
-      getWorkspace(openbox.focusedWindow()->getWorkspaceNumber())->
-        raiseWindow(openbox.focusedWindow());
+    while (rootmenu->getCount())
+      rootmenu->remove(0);
+  } else {
+    rootmenu = new Rootmenu(this);
   }
+  bool defaultMenu = True;
 
+  if (blackbox->getMenuFilename()) {
+    FILE *menu_file = fopen(blackbox->getMenuFilename(), "r");
 
-  void BScreen::InitMenu(void) {
-    if (rootmenu) {
-      rootmenuList.clear();
-      while (rootmenu->getCount())
-        rootmenu->remove(0);
+    if (!menu_file) {
+      perror(blackbox->getMenuFilename());
     } else {
-      rootmenu = new Rootmenu(*this);
-    }
-    bool defaultMenu = true;
-
-    FILE *menu_file;
-    const char *menu_filename = openbox.getMenuFilename();
-
-    if (!(menu_file = fopen(menu_filename, "r"))) {
-      perror(menu_filename);
-      menu_filename = (char *) 0;
-    }
-    if (menu_filename == (char *) 0) {
-      // opening the menu file failed, try the DEFAULTMENU
-      menu_filename = DEFAULTMENU;
-      if (!(menu_file = fopen(menu_filename, "r"))) {
-        perror(menu_filename);
-        menu_filename = (char *) 0;
-      }
-    }
-
-    if (menu_filename) { 
       if (feof(menu_file)) {
         fprintf(stderr, i18n(ScreenSet, ScreenEmptyMenuFile,
-                             "%s: Empty menu file"), menu_filename);
-        menu_filename = (char *) 0;
+                             "%s: Empty menu file"),
+                blackbox->getMenuFilename());
       } else {
-        // successsfully opened a menu file
         char line[1024], label[1024];
         memset(line, 0, 1024);
         memset(label, 0, 1024);
@@ -2296,7 +1137,6 @@ void BScreen::load() {
           if (line[0] != '#') {
             int i, key = 0, index = -1, len = strlen(line);
 
-            key = 0;
             for (i = 0; i < len; i++) {
               if (line[i] == '[') index = 0;
               else if (line[i] == ']') break;
@@ -2305,7 +1145,7 @@ void BScreen::load() {
                   key += tolower(line[i]);
             }
 
-            if (key == 517) {
+            if (key == 517) { // [begin]
               index = -1;
               for (i = index; i < len; i++) {
                 if (line[i] == '(') index = 0;
@@ -2321,8 +1161,6 @@ void BScreen::load() {
 
               rootmenu->setLabel(label);
               defaultMenu = parseMenuFile(menu_file, rootmenu);
-              if (!defaultMenu)
-                openbox.addMenuTimestamp(menu_filename);
               break;
             }
           }
@@ -2330,504 +1168,815 @@ void BScreen::load() {
       }
       fclose(menu_file);
     }
+  }
 
-    if (defaultMenu) {
-      rootmenu->setInternalMenu();
-      rootmenu->insert(i18n(ScreenSet, Screenxterm, "xterm"),
-                       BScreen::Execute,
-                       i18n(ScreenSet, Screenxterm, "xterm"));
-      rootmenu->insert(i18n(ScreenSet, ScreenRestart, "Restart"),
-                       BScreen::Restart);
-      rootmenu->insert(i18n(ScreenSet, ScreenExit, "Exit"),
-                       BScreen::Exit);
-    }
+  if (defaultMenu) {
+    rootmenu->setInternalMenu();
+    rootmenu->insert(i18n(ScreenSet, Screenxterm, "xterm"),
+                     BScreen::Execute,
+                     i18n(ScreenSet, Screenxterm, "xterm"));
+    rootmenu->insert(i18n(ScreenSet, ScreenRestart, "Restart"),
+                     BScreen::Restart);
+    rootmenu->insert(i18n(ScreenSet, ScreenExit, "Exit"),
+                     BScreen::Exit);
+    rootmenu->setLabel(i18n(BasemenuSet, BasemenuBlackboxMenu,
+                            "Blackbox Menu"));
+  } else {
+    blackbox->saveMenuFilename(blackbox->getMenuFilename());
   }
+}
+
+
+bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) {
+  char line[1024], label[1024], command[1024];
 
+  while (! feof(file)) {
+    memset(line, 0, 1024);
+    memset(label, 0, 1024);
+    memset(command, 0, 1024);
 
-  Bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) {
-    char line[1024], label[1024], command[1024];
-
-    while (! feof(file)) {
-      memset(line, 0, 1024);
-      memset(label, 0, 1024);
-      memset(command, 0, 1024);
-
-      if (fgets(line, 1024, file)) {
-        if (line[0] != '#') {
-          register int i, key = 0, parse = 0, index = -1,
-          line_length = strlen(line),
-          label_length = 0, command_length = 0;
-
-          // determine the keyword
-          key = 0;
-          for (i = 0; i < line_length; i++) {
-            if (line[i] == '[') parse = 1;
-            else if (line[i] == ']') break;
-            else if (line[i] != ' ')
-              if (parse)
-                key += tolower(line[i]);
+    if (fgets(line, 1024, file)) {
+      if (line[0] != '#') {
+        int i, key = 0, parse = 0, index = -1, line_length = strlen(line);
+
+        // determine the keyword
+        for (i = 0; i < line_length; i++) {
+          if (line[i] == '[') parse = 1;
+          else if (line[i] == ']') break;
+          else if (line[i] != ' ')
+            if (parse)
+              key += tolower(line[i]);
+        }
+
+        // get the label enclosed in ()'s
+        parse = 0;
+
+        for (i = 0; i < line_length; i++) {
+          if (line[i] == '(') {
+            index = 0;
+            parse = 1;
+          } else if (line[i] == ')') break;
+          else if (index++ >= 0) {
+            if (line[i] == '\\' && i < line_length - 1) i++;
+            label[index - 1] = line[i];
           }
+        }
 
-          // get the label enclosed in ()'s
-          parse = 0;
-
-          for (i = 0; i < line_length; i++) {
-            if (line[i] == '(') {
-              index = 0;
-              parse = 1;
-            } else if (line[i] == ')') break;
-            else if (index++ >= 0) {
-              if (line[i] == '\\' && i < line_length - 1) i++;
-              label[index - 1] = line[i];
-            }
+        if (parse) {
+          label[index] = '\0';
+        } else {
+          label[0] = '\0';
+        }
+
+        // get the command enclosed in {}'s
+        parse = 0;
+        index = -1;
+        for (i = 0; i < line_length; i++) {
+          if (line[i] == '{') {
+            index = 0;
+            parse = 1;
+          } else if (line[i] == '}') break;
+          else if (index++ >= 0) {
+            if (line[i] == '\\' && i < line_length - 1) i++;
+            command[index - 1] = line[i];
           }
+        }
+
+        if (parse) {
+          command[index] = '\0';
+        } else {
+          command[0] = '\0';
+        }
+
+        switch (key) {
+        case 311: // end
+          return ((menu->getCount() == 0) ? True : False);
 
-          if (parse) {
-            label[index] = '\0';
-            label_length = index;
-          } else {
+          break;
+
+        case 333: // nop
+          if (! *label)
             label[0] = '\0';
-            label_length = 0;
+          menu->insert(label);
+
+          break;
+
+        case 421: // exec
+          if ((! *label) && (! *command)) {
+            fprintf(stderr, i18n(ScreenSet, ScreenEXECError,
+                                 "BScreen::parseMenuFile: [exec] error, "
+                                 "no menu label and/or command defined\n"));
+            continue;
           }
 
-          // get the command enclosed in {}'s
-          parse = 0;
-          index = -1;
-          for (i = 0; i < line_length; i++) {
-            if (line[i] == '{') {
-              index = 0;
-              parse = 1;
-            } else if (line[i] == '}') break;
-            else if (index++ >= 0) {
-              if (line[i] == '\\' && i < line_length - 1) i++;
-              command[index - 1] = line[i];
-            }
+          menu->insert(label, BScreen::Execute, command);
+
+          break;
+
+        case 442: // exit
+          if (! *label) {
+            fprintf(stderr, i18n(ScreenSet, ScreenEXITError,
+                                 "BScreen::parseMenuFile: [exit] error, "
+                                 "no menu label defined\n"));
+            continue;
           }
 
-          if (parse) {
-            command[index] = '\0';
-            command_length = index;
-          } else {
-            command[0] = '\0';
-            command_length = 0;
+          menu->insert(label, BScreen::Exit);
+
+          break;
+
+        case 561: // style
+          {
+            if ((! *label) || (! *command)) {
+              fprintf(stderr,
+                      i18n(ScreenSet, ScreenSTYLEError,
+                           "BScreen::parseMenuFile: [style] error, "
+                           "no menu label and/or filename defined\n"));
+              continue;
+            }
+
+            string style = expandTilde(command);
+
+            menu->insert(label, BScreen::SetStyle, style.c_str());
           }
 
-          switch (key) {
-          case 311: //end
-            return ((menu->getCount() == 0) ? True : False);
+          break;
 
-            break;
+        case 630: // config
+          if (! *label) {
+            fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError,
+                                 "BScreen::parseMenufile: [config] error, "
+                                 "no label defined"));
+            continue;
+          }
 
-          case 333: // nop
-            menu->insert(label);
+          menu->insert(label, configmenu);
 
-            break;
+          break;
 
-          case 421: // exec
-            if ((! *label) && (! *command)) {
-              fprintf(stderr, i18n(ScreenSet, ScreenEXECError,
-                                   "BScreen::parseMenuFile: [exec] error, "
-                                   "no menu label and/or command defined\n"));
+        case 740: // include
+          {
+            if (! *label) {
+              fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError,
+                                   "BScreen::parseMenuFile: [include] error, "
+                                   "no filename defined\n"));
               continue;
             }
 
-            menu->insert(label, BScreen::Execute, command);
+            string newfile = expandTilde(label);
+            FILE *submenufile = fopen(newfile.c_str(), "r");
 
-            break;
+            if (submenufile) {
+              struct stat buf;
+              if (fstat(fileno(submenufile), &buf) ||
+                  (! S_ISREG(buf.st_mode))) {
+                fprintf(stderr,
+                        i18n(ScreenSet, ScreenINCLUDEErrorReg,
+                             "BScreen::parseMenuFile: [include] error: "
+                             "'%s' is not a regular file\n"), newfile.c_str());
+                break;
+              }
+
+              if (! feof(submenufile)) {
+                if (! parseMenuFile(submenufile, menu))
+                  blackbox->saveMenuFilename(newfile);
+
+                fclose(submenufile);
+              }
+            } else {
+              perror(newfile.c_str());
+            }
+          }
 
-          case 442: // exit
+          break;
+
+        case 767: // submenu
+          {
             if (! *label) {
-              fprintf(stderr, i18n(ScreenSet, ScreenEXITError,
-                                   "BScreen::parseMenuFile: [exit] error, "
+              fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError,
+                                   "BScreen::parseMenuFile: [submenu] error, "
                                    "no menu label defined\n"));
               continue;
             }
 
-            menu->insert(label, BScreen::Exit);
+            Rootmenu *submenu = new Rootmenu(this);
 
-            break;
+            if (*command)
+              submenu->setLabel(command);
+            else
+              submenu->setLabel(label);
 
-          case 561: // style
-            {
-              if ((! *label) || (! *command)) {
-                fprintf(stderr, i18n(ScreenSet, ScreenSTYLEError,
-                                     "BScreen::parseMenuFile: [style] error, "
-                                     "no menu label and/or filename defined\n"));
-                continue;
-              }
+            parseMenuFile(file, submenu);
+            submenu->update();
+            menu->insert(label, submenu);
+            rootmenuList.push_back(submenu);
+          }
 
-              char style[MAXPATHLEN];
+          break;
 
-              // perform shell style ~ home directory expansion
-              char *homedir = 0;
-              int homedir_len = 0;
-              if (*command == '~' && *(command + 1) == '/') {
-                homedir = getenv("HOME");
-                homedir_len = strlen(homedir);
-              }
+        case 773: // restart
+          {
+            if (! *label) {
+              fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError,
+                                   "BScreen::parseMenuFile: [restart] error, "
+                                   "no menu label defined\n"));
+              continue;
+            }
 
-              if (homedir && homedir_len != 0) {
-                strncpy(style, homedir, homedir_len);
+            if (*command)
+              menu->insert(label, BScreen::RestartOther, command);
+            else
+              menu->insert(label, BScreen::Restart);
+          }
 
-                strncpy(style + homedir_len, command + 1,
-                        command_length - 1);
-                *(style + command_length + homedir_len - 1) = '\0';
-              } else {
-                strncpy(style, command, command_length);
-                *(style + command_length) = '\0';
-              }
+          break;
 
-              menu->insert(label, BScreen::SetStyle, style);
+        case 845: // reconfig
+          {
+            if (! *label) {
+              fprintf(stderr,
+                      i18n(ScreenSet, ScreenRECONFIGError,
+                           "BScreen::parseMenuFile: [reconfig] error, "
+                           "no menu label defined\n"));
+              continue;
             }
 
-            break;
+            menu->insert(label, BScreen::Reconfigure);
+          }
 
-          case 630: // config
-            if (! *label) {
-              fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError,
-                                   "BScreen::parseMenufile: [config] error, "
-                                   "no label defined"));
+          break;
+
+        case 995: // stylesdir
+        case 1113: // stylesmenu
+          {
+            bool newmenu = ((key == 1113) ? True : False);
+
+            if ((! *label) || ((! *command) && newmenu)) {
+              fprintf(stderr,
+                      i18n(ScreenSet, ScreenSTYLESDIRError,
+                           "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
+                           " error, no directory defined\n"));
               continue;
             }
 
-            menu->insert(label, configmenu);
+            char *directory = ((newmenu) ? command : label);
 
-            break;
+            string stylesdir = expandTilde(directory);
 
-          case 740: // include
-            {
-              if (! *label) {
-                fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError,
-                                     "BScreen::parseMenuFile: [include] error, "
-                                     "no filename defined\n"));
-                continue;
-              }
+            struct stat statbuf;
 
-              char newfile[MAXPATHLEN];
+            if (! stat(stylesdir.c_str(), &statbuf)) {
+              if (S_ISDIR(statbuf.st_mode)) {
+                Rootmenu *stylesmenu;
 
-              // perform shell style ~ home directory expansion
-              char *homedir = 0;
-              int homedir_len = 0;
-              if (*label == '~' && *(label + 1) == '/') {
-                homedir = getenv("HOME");
-                homedir_len = strlen(homedir);
-              }
+                if (newmenu)
+                  stylesmenu = new Rootmenu(this);
+                else
+                  stylesmenu = menu;
+
+                DIR *d = opendir(stylesdir.c_str());
+                struct dirent *p;
+                std::vector<string> ls;
+
+                while((p = readdir(d)))
+                  ls.push_back(p->d_name);
+
+                closedir(d);
 
-              if (homedir && homedir_len != 0) {
-                strncpy(newfile, homedir, homedir_len);
+                std::sort(ls.begin(), ls.end());
 
-                strncpy(newfile + homedir_len, label + 1,
-                        label_length - 1);
-                *(newfile + label_length + homedir_len - 1) = '\0';
+                std::vector<string>::iterator it = ls.begin(),
+                  end = ls.end();
+                for (; it != end; ++it) {
+                  const string& fname = *it;
+
+                  if (fname[fname.size()-1] == '~')
+                    continue;
+
+                  string style = stylesdir;
+                  style += '/';
+                  style += fname;
+
+                  if ((! stat(style.c_str(), &statbuf)) &&
+                      S_ISREG(statbuf.st_mode))
+                    stylesmenu->insert(fname, BScreen::SetStyle, style);
+                }
+
+                stylesmenu->update();
+
+                if (newmenu) {
+                  stylesmenu->setLabel(label);
+                  menu->insert(label, stylesmenu);
+                  rootmenuList.push_back(stylesmenu);
+                }
+
+                blackbox->saveMenuFilename(stylesdir);
               } else {
-                strncpy(newfile, label, label_length);
-                *(newfile + label_length) = '\0';
+                fprintf(stderr,
+                        i18n(ScreenSet, ScreenSTYLESDIRErrorNotDir,
+                             "BScreen::parseMenuFile:"
+                             " [stylesdir/stylesmenu] error, %s is not a"
+                             " directory\n"), stylesdir.c_str());
               }
+            } else {
+              fprintf(stderr,
+                      i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist,
+                           "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
+                           " error, %s does not exist\n"), stylesdir.c_str());
+            }
+            break;
+          }
 
-              if (newfile) {
-                FILE *submenufile = fopen(newfile, "r");
-
-                if (submenufile) {
-                  struct stat buf;
-                  if (fstat(fileno(submenufile), &buf) ||
-                      (! S_ISREG(buf.st_mode))) {
-                    fprintf(stderr,
-                            i18n(ScreenSet, ScreenINCLUDEErrorReg,
-                                 "BScreen::parseMenuFile: [include] error: "
-                                 "'%s' is not a regular file\n"), newfile);
-                    break;
-                  }
-
-                  if (! feof(submenufile)) {
-                    if (!parseMenuFile(submenufile, menu))
-                      openbox.addMenuTimestamp(newfile);
-                    fclose(submenufile);
-                  }
-                } else
-                  perror(newfile);
-              }
+        case 1090: // workspaces
+          {
+            if (! *label) {
+              fprintf(stderr,
+                      i18n(ScreenSet, ScreenWORKSPACESError,
+                           "BScreen:parseMenuFile: [workspaces] error, "
+                           "no menu label defined\n"));
+              continue;
             }
 
+            menu->insert(label, workspacemenu);
+
             break;
+          }
+        }
+      }
+    }
+  }
 
-          case 767: // submenu
-            {
-              if (! *label) {
-                fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError,
-                                     "BScreen::parseMenuFile: [submenu] error, "
-                                     "no menu label defined\n"));
-                continue;
-              }
+  return ((menu->getCount() == 0) ? True : False);
+}
 
-              Rootmenu *submenu = new Rootmenu(*this);
 
-              if (*command)
-                submenu->setLabel(command);
-              else
-                submenu->setLabel(label);
+void BScreen::shutdown(void) {
+  XSelectInput(blackbox->getXDisplay(), getRootWindow(), NoEventMask);
+  XSync(blackbox->getXDisplay(), False);
 
-              parseMenuFile(file, submenu);
-              submenu->update();
-              menu->insert(label, submenu);
-              rootmenuList.push_back(submenu);
-            }
+  while(! windowList.empty())
+    unmanageWindow(windowList.front(), True);
 
-            break;
+  slit->shutdown();
+}
 
-          case 773: // restart
-            {
-              if (! *label) {
-                fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError,
-                                     "BScreen::parseMenuFile: [restart] error, "
-                                     "no menu label defined\n"));
-                continue;
-              }
 
-              if (*command)
-                menu->insert(label, BScreen::RestartOther, command);
-              else
-                menu->insert(label, BScreen::Restart);
-            }
+void BScreen::showPosition(int x, int y) {
+  if (! geom_visible) {
+    XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
+                      (getWidth() - geom_w) / 2,
+                      (getHeight() - geom_h) / 2, geom_w, geom_h);
+    XMapWindow(blackbox->getXDisplay(), geom_window);
+    XRaiseWindow(blackbox->getXDisplay(), geom_window);
 
-            break;
+    geom_visible = True;
+  }
 
-          case 845: // reconfig
-            {
-              if (! *label) {
-                fprintf(stderr, i18n(ScreenSet, ScreenRECONFIGError,
-                                     "BScreen::parseMenuFile: [reconfig] error, "
-                                     "no menu label defined\n"));
-                continue;
-              }
+  char label[1024];
 
-              menu->insert(label, BScreen::Reconfigure);
-            }
+  sprintf(label, i18n(ScreenSet, ScreenPositionFormat,
+                      "X: %4d x Y: %4d"), x, y);
 
-            break;
+  XClearWindow(blackbox->getXDisplay(), geom_window);
 
-          case 995: // stylesdir
-          case 1113: // stylesmenu
-            {
-              Bool newmenu = ((key == 1113) ? True : False);
+  BPen pen(resource.wstyle.l_text_focus, resource.wstyle.font);
+  if (i18n.multibyte()) {
+    XmbDrawString(blackbox->getXDisplay(), geom_window,
+                  resource.wstyle.fontset, pen.gc(),
+                  resource.bevel_width, resource.bevel_width -
+                  resource.wstyle.fontset_extents->max_ink_extent.y,
+                  label, strlen(label));
+  } else {
+    XDrawString(blackbox->getXDisplay(), geom_window,
+                pen.gc(), resource.bevel_width,
+                resource.wstyle.font->ascent + resource.bevel_width,
+                label, strlen(label));
+  }
+}
 
-              if ((! *label) || ((! *command) && newmenu)) {
-                fprintf(stderr,
-                        i18n(ScreenSet, ScreenSTYLESDIRError,
-                             "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
-                             " error, no directory defined\n"));
-                continue;
-              }
 
-              char stylesdir[MAXPATHLEN];
+void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
+  if (! geom_visible) {
+    XMoveResizeWindow(blackbox->getXDisplay(), geom_window,
+                      (getWidth() - geom_w) / 2,
+                      (getHeight() - geom_h) / 2, geom_w, geom_h);
+    XMapWindow(blackbox->getXDisplay(), geom_window);
+    XRaiseWindow(blackbox->getXDisplay(), geom_window);
 
-              char *directory = ((newmenu) ? command : label);
-              int directory_length = ((newmenu) ? command_length : label_length);
+    geom_visible = True;
+  }
 
-              // perform shell style ~ home directory expansion
-              char *homedir = 0;
-              int homedir_len = 0;
+  char label[1024];
 
-              if (*directory == '~' && *(directory + 1) == '/') {
-                homedir = getenv("HOME");
-                homedir_len = strlen(homedir);
-              }
+  sprintf(label, i18n(ScreenSet, ScreenGeometryFormat,
+                      "W: %4d x H: %4d"), gx, gy);
 
-              if (homedir && homedir_len != 0) {
-                strncpy(stylesdir, homedir, homedir_len);
+  XClearWindow(blackbox->getXDisplay(), geom_window);
 
-                strncpy(stylesdir + homedir_len, directory + 1,
-                        directory_length - 1);
-                *(stylesdir + directory_length + homedir_len - 1) = '\0';
-              } else {
-                strncpy(stylesdir, directory, directory_length);
-                *(stylesdir + directory_length) = '\0';
-              }
+  BPen pen(resource.wstyle.l_text_focus, resource.wstyle.font);
+  if (i18n.multibyte()) {
+    XmbDrawString(blackbox->getXDisplay(), geom_window,
+                  resource.wstyle.fontset, pen.gc(),
+                  resource.bevel_width, resource.bevel_width -
+                  resource.wstyle.fontset_extents->max_ink_extent.y,
+                  label, strlen(label));
+  } else {
+    XDrawString(blackbox->getXDisplay(), geom_window,
+                pen.gc(), resource.bevel_width,
+                resource.wstyle.font->ascent +
+                resource.bevel_width, label, strlen(label));
+  }
+}
 
-              struct stat statbuf;
 
-              if (! stat(stylesdir, &statbuf)) {
-                if (S_ISDIR(statbuf.st_mode)) {
-                  Rootmenu *stylesmenu;
+void BScreen::hideGeometry(void) {
+  if (geom_visible) {
+    XUnmapWindow(blackbox->getXDisplay(), geom_window);
+    geom_visible = False;
+  }
+}
 
-                  if (newmenu)
-                    stylesmenu = new Rootmenu(*this);
-                  else
-                    stylesmenu = menu;
 
-                  DIR *d = opendir(stylesdir);
-                  int entries = 0;
-                  struct dirent *p;
+void BScreen::addStrut(Strut *strut) {
+  strutList.push_back(strut);
+}
 
-                  // get the total number of directory entries
-                  while ((p = readdir(d))) entries++;
-                  rewinddir(d);
 
-                  char **ls = new char* [entries];
-                  int index = 0;
-                  while ((p = readdir(d)))
-                    ls[index++] = bstrdup(p->d_name);
+void BScreen::removeStrut(Strut *strut) {
+  strutList.remove(strut);
+}
 
-                  closedir(d);
 
-                  std::sort(ls, ls + entries, dcmp());
+const Rect& BScreen::availableArea(void) const {
+  if (doFullMax())
+    return getRect(); // return the full screen
+  return usableArea;
+}
 
-                  int n, slen = strlen(stylesdir);
-                  for (n = 0; n < entries; n++) {
-                    if (ls[n][strlen(ls[n])-1] != '~') {
-                      int nlen = strlen(ls[n]);
-                      char style[MAXPATHLEN + 1];
 
-                      strncpy(style, stylesdir, slen);
-                      *(style + slen) = '/';
-                      strncpy(style + slen + 1, ls[n], nlen + 1);
+void BScreen::updateAvailableArea(void) {
+  Rect old_area = usableArea;
+  usableArea = getRect(); // reset to full screen
+
+  /* these values represent offsets from the screen edge
+   * we look for the biggest offset on each edge and then apply them
+   * all at once
+   * do not be confused by the similarity to the names of Rect's members
+   */
+  unsigned int current_left = 0, current_right = 0, current_top = 0,
+    current_bottom = 0;
+
+  StrutList::const_iterator it = strutList.begin(), end = strutList.end();
+
+  for(; it != end; ++it) {
+    Strut *strut = *it;
+    if (strut->left > current_left)
+      current_left = strut->left;
+    if (strut->top > current_top)
+      current_top = strut->top;
+    if (strut->right > current_right)
+      current_right = strut->right;
+    if (strut->bottom > current_bottom)
+      current_bottom = strut->bottom;
+  }
 
-                      if ((! stat(style, &statbuf)) && S_ISREG(statbuf.st_mode))
-                        stylesmenu->insert(ls[n], BScreen::SetStyle, style);
-                    }
+  usableArea.setPos(current_left, current_top);
+  usableArea.setSize(usableArea.width() - (current_left + current_right),
+                     usableArea.height() - (current_top + current_bottom));
 
-                    delete [] ls[n];
-                  }
+  if (old_area != usableArea) {
+    BlackboxWindowList::iterator it = windowList.begin(),
+      end = windowList.end();
+    for (; it != end; ++it)
+      if ((*it)->isMaximized()) (*it)->remaximize();
+  }
+}
 
-                  delete [] ls;
 
-                  stylesmenu->update();
+Workspace* BScreen::getWorkspace(unsigned int index) {
+  assert(index < workspacesList.size());
+  return workspacesList[index];
+}
 
-                  if (newmenu) {
-                    stylesmenu->setLabel(label);
-                    menu->insert(label, stylesmenu);
-                    rootmenuList.push_back(stylesmenu);
-                  }
-                  openbox.addMenuTimestamp(stylesdir);
-                } else {
-                  fprintf(stderr, i18n(ScreenSet,
-                                       ScreenSTYLESDIRErrorNotDir,
-                                       "BScreen::parseMenuFile:"
-                                       " [stylesdir/stylesmenu] error, %s is not a"
-                                       " directory\n"), stylesdir);
-                }
-              } else {
-                fprintf(stderr,
-                        i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist,
-                             "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
-                             " error, %s does not exist\n"), stylesdir);
-              }
 
-              break;
-            }
+void BScreen::buttonPressEvent(XButtonEvent *xbutton) {
+  if (xbutton->button == 1) {
+    if (! isRootColormapInstalled())
+      image_control->installRootColormap();
 
-          case 1090: // workspaces
-            {
-              if (! *label) {
-                fprintf(stderr,
-                        i18n(ScreenSet, ScreenWORKSPACESError,
-                             "BScreen:parseMenuFile: [workspaces] error, "
-                             "no menu label defined\n"));
-                continue;
-              }
+    if (workspacemenu->isVisible())
+      workspacemenu->hide();
 
-              menu->insert(label, workspacemenu);
+    if (rootmenu->isVisible())
+      rootmenu->hide();
+  } else if (xbutton->button == 2) {
+    int mx = xbutton->x_root - (workspacemenu->getWidth() / 2);
+    int my = xbutton->y_root - (workspacemenu->getTitleHeight() / 2);
 
-              break;
-            }
-          }
-        }
-      }
+    if (mx < 0) mx = 0;
+    if (my < 0) my = 0;
+
+    if (mx + workspacemenu->getWidth() > getWidth())
+      mx = getWidth() - workspacemenu->getWidth() - getBorderWidth();
+
+    if (my + workspacemenu->getHeight() > getHeight())
+      my = getHeight() - workspacemenu->getHeight() - getBorderWidth();
+
+    workspacemenu->move(mx, my);
+
+    if (! workspacemenu->isVisible()) {
+      workspacemenu->removeParent();
+      workspacemenu->show();
     }
+  } else if (xbutton->button == 3) {
+    int mx = xbutton->x_root - (rootmenu->getWidth() / 2);
+    int my = xbutton->y_root - (rootmenu->getTitleHeight() / 2);
+
+    if (mx < 0) mx = 0;
+    if (my < 0) my = 0;
 
-    return ((menu->getCount() == 0) ? True : False);
+    if (mx + rootmenu->getWidth() > getWidth())
+      mx = getWidth() - rootmenu->getWidth() - getBorderWidth();
+
+    if (my + rootmenu->getHeight() > getHeight())
+      my = getHeight() - rootmenu->getHeight() - getBorderWidth();
+
+    rootmenu->move(mx, my);
+
+    if (! rootmenu->isVisible()) {
+      blackbox->checkMenu();
+      rootmenu->show();
+    }
   }
+}
+
 
+void BScreen::toggleFocusModel(FocusModel model) {
+  if (model == SloppyFocus) {
+    saveSloppyFocus(True);
+  } else {
+    saveSloppyFocus(False);
+    saveAutoRaise(False);
+    saveClickRaise(False);
+  }
 
-  void BScreen::shutdown(void) {
-    openbox.grab();
+  updateFocusModel();
+}
 
-    XSelectInput(getBaseDisplay().getXDisplay(), getRootWindow(), NoEventMask);
-    XSync(getBaseDisplay().getXDisplay(), False);
 
-    std::for_each(workspacesList.begin(), workspacesList.end(),
-                  std::mem_fun(&Workspace::shutdown));
+void BScreen::updateFocusModel()
+{
+  std::for_each(workspacesList.begin(), workspacesList.end(),
+                std::mem_fun(&Workspace::updateFocusModel));
+}
 
-    while (!iconList.empty())
-      iconList.front()->restore();
 
-#ifdef    SLIT
-    slit->shutdown();
-#endif // SLIT
+BTexture BScreen::readDatabaseTexture(const string &rname,
+                                      const string &rclass,
+                                      const string &default_color) {
+  BTexture texture;
+  XrmValue value;
+  char *value_type;
 
-    openbox.ungrab();
+  if (XrmGetResource(resource.stylerc, rname.c_str(), rclass.c_str(),
+                     &value_type, &value))
+    texture = BTexture(value.addr);
+  else
+    texture.setTexture(BTexture::Solid | BTexture::Flat);
+
+  // associate this texture with this screen
+  texture.setDisplay(getBaseDisplay(), getScreenNumber());
+  texture.setImageControl(image_control);
+
+  if (texture.texture() & BTexture::Solid) {
+    texture.setColor(readDatabaseColor(rname + ".color",
+                                       rclass + ".Color",
+                                       default_color));
+    texture.setColorTo(readDatabaseColor(rname + ".colorTo",
+                                         rclass + ".ColorTo",
+                                         default_color));
+  } else if (texture.texture() & BTexture::Gradient) {
+    texture.setColor(readDatabaseColor(rname + ".color",
+                                       rclass + ".Color",
+                                       default_color));
+    texture.setColorTo(readDatabaseColor(rname + ".colorTo",
+                                         rclass + ".ColorTo",
+                                         default_color));
   }
 
+  return texture;
+}
+
+
+BColor BScreen::readDatabaseColor(const string &rname, const string &rclass,
+                                 const string &default_color) {
+  BColor color;
+  XrmValue value;
+  char *value_type;
+  if (XrmGetResource(resource.stylerc, rname.c_str(), rclass.c_str(),
+                     &value_type, &value))
+    color = BColor(value.addr, getBaseDisplay(), getScreenNumber());
+  else
+    color = BColor(default_color, getBaseDisplay(), getScreenNumber());
+  return color;
+}
+
 
-  void BScreen::showPosition(int x, int y) {
-    if (! geom_visible) {
-      XMoveResizeWindow(getBaseDisplay().getXDisplay(), geom_window,
-                        (size().w() - geom_w) / 2,
-                        (size().h() - geom_h) / 2, geom_w, geom_h);
-      XMapWindow(getBaseDisplay().getXDisplay(), geom_window);
-      XRaiseWindow(getBaseDisplay().getXDisplay(), geom_window);
+XFontSet BScreen::readDatabaseFontSet(const string &rname,
+                                      const string &rclass) {
+  char *defaultFont = "fixed";
 
-      geom_visible = True;
+  bool load_default = True;
+  XrmValue value;
+  char *value_type;
+  XFontSet fontset = 0;
+  if (XrmGetResource(resource.stylerc, rname.c_str(), rclass.c_str(),
+                     &value_type, &value) &&
+      (fontset = createFontSet(value.addr))) {
+    load_default = False;
+  }
+
+  if (load_default) {
+    fontset = createFontSet(defaultFont);
+
+    if (! fontset) {
+      fprintf(stderr,
+              i18n(ScreenSet, ScreenDefaultFontLoadFail,
+                   "BScreen::setCurrentStyle(): couldn't load default font.\n"));
+      exit(2);
     }
+  }
+
+  return fontset;
+}
 
-    char label[1024];
 
-    sprintf(label, i18n(ScreenSet, ScreenPositionFormat,
-                        "X: %4d x Y: %4d"), x, y);
+XFontStruct *BScreen::readDatabaseFont(const string &rname,
+                                       const string &rclass) {
+  char *defaultFont = "fixed";
 
-    XClearWindow(getBaseDisplay().getXDisplay(), geom_window);
+  bool load_default = False;
+  XrmValue value;
+  char *value_type;
+  XFontStruct *font = 0;
+  if (XrmGetResource(resource.stylerc, rname.c_str(), rclass.c_str(),
+                     &value_type, &value)) {
+    if ((font = XLoadQueryFont(blackbox->getXDisplay(), value.addr)) == NULL) {
+      fprintf(stderr,
+              i18n(ScreenSet, ScreenFontLoadFail,
+                   "BScreen::setCurrentStyle(): couldn't load font '%s'\n"),
+              value.addr);
 
-    if (i18n.multibyte()) {
-      XmbDrawString(getBaseDisplay().getXDisplay(), geom_window,
-                    resource.wstyle.fontset, resource.wstyle.l_text_focus_gc,
-                    resource.bevel_width, resource.bevel_width -
-                    resource.wstyle.fontset_extents->max_ink_extent.y,
-                    label, strlen(label));
-    } else {
-      XDrawString(getBaseDisplay().getXDisplay(), geom_window,
-                  resource.wstyle.l_text_focus_gc,
-                  resource.bevel_width,
-                  resource.wstyle.font->ascent +
-                  resource.bevel_width, label, strlen(label));
+      load_default = True;
     }
+  } else {
+    load_default = True;
   }
 
+  if (load_default) {
+    font = XLoadQueryFont(blackbox->getXDisplay(), defaultFont);
+    if (font == NULL) {
+      fprintf(stderr,
+              i18n(ScreenSet, ScreenDefaultFontLoadFail,
+                   "BScreen::setCurrentStyle(): couldn't load default font.\n"));
+      exit(2);
+    }
+  }
+
+  return font;
+}
 
-  void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
-    if (! geom_visible) {
-      XMoveResizeWindow(getBaseDisplay().getXDisplay(), geom_window,
-                        (size().w() - geom_w) / 2,
-                        (size().h() - geom_h) / 2, geom_w, geom_h);
-      XMapWindow(getBaseDisplay().getXDisplay(), geom_window);
-      XRaiseWindow(getBaseDisplay().getXDisplay(), geom_window);
 
-      geom_visible = True;
+#ifndef    HAVE_STRCASESTR
+static const char * strcasestr(const char *str, const char *ptn) {
+  const char *s2, *p2;
+  for(; *str; str++) {
+    for(s2=str,p2=ptn; ; s2++,p2++) {
+      if (!*p2) return str;
+      if (toupper(*s2) != toupper(*p2)) break;
     }
+  }
+  return NULL;
+}
+#endif // HAVE_STRCASESTR
 
-    char label[1024];
 
-    sprintf(label, i18n(ScreenSet, ScreenGeometryFormat,
-                        "W: %4d x H: %4d"), gx, gy);
+static const char *getFontElement(const char *pattern, char *buf,
+                                  int bufsiz, ...) {
+  const char *p, *v;
+  char *p2;
+  va_list va;
+
+  va_start(va, bufsiz);
+  buf[bufsiz-1] = 0;
+  buf[bufsiz-2] = '*';
+  while((v = va_arg(va, char *)) != NULL) {
+    p = strcasestr(pattern, v);
+    if (p) {
+      strncpy(buf, p+1, bufsiz-2);
+      p2 = strchr(buf, '-');
+      if (p2) *p2=0;
+      va_end(va);
+      return p;
+    }
+  }
+  va_end(va);
+  strncpy(buf, "*", bufsiz);
+  return NULL;
+}
 
-    XClearWindow(getBaseDisplay().getXDisplay(), geom_window);
 
-    if (i18n.multibyte()) {
-      XmbDrawString(getBaseDisplay().getXDisplay(), geom_window,
-                    resource.wstyle.fontset, resource.wstyle.l_text_focus_gc,
-                    resource.bevel_width, resource.bevel_width -
-                    resource.wstyle.fontset_extents->max_ink_extent.y,
-                    label, strlen(label));
+static const char *getFontSize(const char *pattern, int *size) {
+  const char *p;
+  const char *p2=NULL;
+  int n=0;
+
+  for (p=pattern; 1; p++) {
+    if (!*p) {
+      if (p2!=NULL && n>1 && n<72) {
+        *size = n; return p2+1;
+      } else {
+        *size = 16; return NULL;
+      }
+    } else if (*p=='-') {
+      if (n>1 && n<72 && p2!=NULL) {
+        *size = n;
+        return p2+1;
+      }
+      p2=p; n=0;
+    } else if (*p>='0' && *p<='9' && p2!=NULL) {
+      n *= 10;
+      n += *p-'0';
     } else {
-      XDrawString(getBaseDisplay().getXDisplay(), geom_window,
-                  resource.wstyle.l_text_focus_gc,
-                  resource.bevel_width,
-                  resource.wstyle.font->ascent +
-                  resource.bevel_width, label, strlen(label));
+      p2=NULL; n=0;
     }
   }
+}
 
-  void BScreen::hideGeometry(void) {
-    if (geom_visible) {
-      XUnmapWindow(getBaseDisplay().getXDisplay(), geom_window);
-      geom_visible = False;
-    }
+
+XFontSet BScreen::createFontSet(const string &fontname) {
+  XFontSet fs;
+  char **missing, *def = "-";
+  int nmissing, pixel_size = 0, buf_size = 0;
+  char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE];
+
+  fs = XCreateFontSet(blackbox->getXDisplay(),
+                      fontname.c_str(), &missing, &nmissing, &def);
+  if (fs && (! nmissing))
+    return fs;
+
+  const char *nfontname = fontname.c_str();
+#ifdef    HAVE_SETLOCALE
+  if (! fs) {
+    if (nmissing) XFreeStringList(missing);
+
+    setlocale(LC_CTYPE, "C");
+    fs = XCreateFontSet(blackbox->getXDisplay(), fontname.c_str(),
+                        &missing, &nmissing, &def);
+    setlocale(LC_CTYPE, "");
   }
+#endif // HAVE_SETLOCALE
+
+  if (fs) {
+    XFontStruct **fontstructs;
+    char **fontnames;
+    XFontsOfFontSet(fs, &fontstructs, &fontnames);
+    nfontname = fontnames[0];
+  }
+
+  getFontElement(nfontname, weight, FONT_ELEMENT_SIZE,
+                 "-medium-", "-bold-", "-demibold-", "-regular-", NULL);
+  getFontElement(nfontname, slant, FONT_ELEMENT_SIZE,
+                 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL);
+  getFontSize(nfontname, &pixel_size);
+
+  if (! strcmp(weight, "*"))
+    strncpy(weight, "medium", FONT_ELEMENT_SIZE);
+  if (! strcmp(slant, "*"))
+    strncpy(slant, "r", FONT_ELEMENT_SIZE);
+  if (pixel_size < 3)
+    pixel_size = 3;
+  else if (pixel_size > 97)
+    pixel_size = 97;
+
+  buf_size = strlen(nfontname) + (FONT_ELEMENT_SIZE * 2) + 64;
+  char *pattern2 = new char[buf_size];
+  sprintf(pattern2,
+           "%s,"
+           "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
+           "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
+           nfontname, weight, slant, pixel_size, pixel_size);
+  nfontname = pattern2;
+
+  if (nmissing)
+    XFreeStringList(missing);
+  if (fs)
+    XFreeFontSet(blackbox->getXDisplay(), fs);
+
+  fs = XCreateFontSet(blackbox->getXDisplay(), nfontname, &missing,
+                      &nmissing, &def);
+
+  delete [] pattern2;
+
+  return fs;
+}
diff --git a/src/Screen.h b/src/Screen.h
deleted file mode 100644 (file)
index 24baba1..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-// Screen.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Screen_hh
-#define   __Screen_hh
-
-#include <X11/Xlib.h>
-#include <X11/Xresource.h>
-
-#ifdef    TIME_WITH_SYS_TIME
-#  include <sys/time.h>
-#  include <time.h>
-#else // !TIME_WITH_SYS_TIME
-#  ifdef    HAVE_SYS_TIME_H
-#    include <sys/time.h>
-#  else // !HAVE_SYS_TIME_H
-#    include <time.h>
-#  endif // HAVE_SYS_TIME_H
-#endif // TIME_WITH_SYS_TIME
-
-#include "BaseDisplay.h"
-#include "Configmenu.h"
-#include "Iconmenu.h"
-#include "Netizen.h"
-#include "Rootmenu.h"
-#include "Timer.h"
-#include "Workspace.h"
-#include "Workspacemenu.h"
-#include "openbox.h"
-#ifdef    SLIT
-#  include "Slit.h"
-#endif // SLIT
-#include "Image.h"
-#include "Resource.h"
-#include "Util.h"
-
-#include <list>
-#include <vector>
-
-// forward declaration
-class BScreen;
-
-struct WindowStyle {
-  BColor f_focus, f_unfocus, l_text_focus, l_text_unfocus, b_pic_focus,
-    b_pic_unfocus;
-  BTexture t_focus, t_unfocus, l_focus, l_unfocus, h_focus, h_unfocus,
-    b_focus, b_unfocus, b_pressed, g_focus, g_unfocus;
-  GC l_text_focus_gc, l_text_unfocus_gc, b_pic_focus_gc, b_pic_unfocus_gc;
-
-  XFontSet fontset;
-  XFontSetExtents *fontset_extents;
-  XFontStruct *font;
-  
-  int justify;
-};
-
-struct ToolbarStyle {
-  BColor l_text, w_text, c_text, b_pic;
-  BTexture toolbar, label, window, button, pressed, clock;
-  GC l_text_gc, w_text_gc, c_text_gc, b_pic_gc;
-
-  XFontSet fontset;
-  XFontSetExtents *fontset_extents;
-  XFontStruct *font;
-  
-  int justify;
-};
-
-struct MenuStyle {
-  BColor t_text, f_text, h_text, d_text;
-  BTexture title, frame, hilite;
-  GC t_text_gc, f_text_gc, h_text_gc, d_text_gc, hilite_gc;
-
-  XFontSet t_fontset, f_fontset;
-  XFontSetExtents *t_fontset_extents, *f_fontset_extents;
-  XFontStruct *t_font, *f_font;
-
-  int t_justify, f_justify, bullet, bullet_pos;
-};
-
-
-class BScreen : public ScreenInfo {
-private:
-  Bool root_colormap_installed, managed, geom_visible;
-  GC opGC;
-  Pixmap geom_pixmap;
-  Window geom_window;
-
-  Openbox &openbox;
-  Resource &config;
-  BImageControl *image_control;
-  Configmenu *configmenu;
-  Iconmenu *iconmenu;
-  Rootmenu *rootmenu;
-
-  typedef std::list<Rootmenu *> menuList;
-  menuList rootmenuList;
-  typedef std::list<Netizen *> netList;
-  netList netizenList;
-  typedef std::list<OpenboxWindow *> winList;
-  winList iconList;     // winList is declared in Workspace.h
-
-#ifdef    SLIT
-  Slit *slit;
-#endif // SLIT
-
-  Toolbar *toolbar;
-  Workspace *current_workspace;
-  Workspacemenu *workspacemenu;
-
-  unsigned int geom_w, geom_h;
-  unsigned long event_mask;
-
-  typedef std::vector<std::string> wkspNameList;
-  wkspNameList workspaceNames;
-  typedef std::vector<Workspace *> wkspList;
-  wkspList workspacesList;
-
-  struct resource {
-    WindowStyle wstyle;
-    ToolbarStyle tstyle;
-    MenuStyle mstyle;
-
-    bool sloppy_focus, auto_raise, auto_edge_balance, focus_last,
-      ordered_dither, opaque_move, hide_toolbar, full_max, focus_new;
-    BColor border_color;
-    Resource styleconfig;
-
-    int workspaces, placement_policy, edge_snap_threshold, row_direction,
-      col_direction;
-
-    unsigned int handle_width, bevel_width, frame_width, border_width;
-    int zones; // number of zones to be used when alt-resizing a window
-
-#ifdef    HAVE_STRFTIME
-    char *strftime_format;
-#else // !HAVE_STRFTIME
-    bool clock24hour;
-    int date_format;
-#endif // HAVE_STRFTIME
-
-    char *root_command;
-  } resource;
-
-
-protected:
-  Bool parseMenuFile(FILE *, Rootmenu *);
-
-  void readDatabaseTexture(const char *, const char *, BTexture *,
-                           unsigned long);
-  void readDatabaseColor(const char *, const char *, BColor *, unsigned long);
-
-  void readDatabaseFontSet(const char *, const char *, XFontSet *);
-  XFontSet createFontSet(const char *);
-  void readDatabaseFont(const char *, const char *, XFontStruct **);
-
-  void InitMenu();
-  void LoadStyle();
-
-
-public:
-  BScreen(Openbox &, int, Resource &);
-  ~BScreen();
-
-  inline const Bool &isScreenManaged() const { return managed; }
-  inline const GC &getOpGC() const { return opGC; }
-
-  inline Openbox &getOpenbox() { return openbox; }
-  inline BColor *getBorderColor() { return &resource.border_color; }
-  inline BImageControl *getImageControl() { return image_control; }
-  inline Rootmenu *getRootmenu() { return rootmenu; }
-
-#ifdef   SLIT
-  inline Slit *getSlit() { return slit; }
-#endif // SLIT
-
-  inline Toolbar *getToolbar() { return toolbar; }
-
-  Rect availableArea() const;
-  
-  inline Workspace *getWorkspace(unsigned int w) {
-    ASSERT(w < workspacesList.size());
-    return workspacesList[w];
-  }
-  inline Workspace *getCurrentWorkspace() { return current_workspace; }
-
-  inline Workspacemenu *getWorkspacemenu() { return workspacemenu; }
-  
-  inline void iconUpdate() { iconmenu->update(); }
-
-  inline const unsigned int &getHandleWidth() const
-  { return resource.handle_width; }
-  inline const unsigned int &getBevelWidth() const
-  { return resource.bevel_width; }
-  inline const unsigned int &getFrameWidth() const
-  { return resource.frame_width; }
-  inline const unsigned int &getBorderWidth() const
-  { return resource.border_width; }
-
-  inline const int getCurrentWorkspaceID()
-  { return current_workspace->getWorkspaceID(); }
-  inline const int getWorkspaceCount() { return workspacesList.size(); }
-  inline const int getIconCount() { return iconList.size(); }
-
-  inline const Bool &isRootColormapInstalled() const
-    { return root_colormap_installed; }
-  inline void setRootColormapInstalled(Bool r) { root_colormap_installed = r; }
-  
-  inline bool sloppyFocus() const { return resource.sloppy_focus; }
-  void setSloppyFocus(bool s);
-  
-  inline bool autoRaise() const { return resource.auto_raise; }
-  void setAutoRaise(bool a);
-  
-  inline bool imageDither() const { return image_control->doDither(); }
-  void setImageDither(bool d, bool reconfig = true);
-  
-  inline bool orderedDither() const { return resource.ordered_dither; }
-  
-  inline bool opaqueMove() const { return resource.opaque_move; }
-  void setOpaqueMove(bool o);
-  
-  inline bool fullMax() const { return resource.full_max; }
-  void setFullMax(bool f);
-  
-  inline bool focusNew() const { return resource.focus_new; }
-  void setFocusNew(bool f);
-  
-  inline bool focusLast() const { return resource.focus_last; }
-  void setFocusLast(bool f);
-  
-  inline int getWindowZones() const { return resource.zones; }
-  void setWindowZones(int z);
-  
-  inline int workspaceCount() const { return resource.workspaces; }
-  void setWorkspaceCount(int w);
-
-  inline int placementPolicy() const { return resource.placement_policy; }
-  void setPlacementPolicy(int p);
-
-  inline int edgeSnapThreshold() const { return resource.edge_snap_threshold; }
-  void setEdgeSnapThreshold(int t);
-  
-  inline int rowPlacementDirection() const { return resource.row_direction; }
-  void setRowPlacementDirection(int d);
-  
-  inline int colPlacementDirection() const { return resource.col_direction; }
-  void setColPlacementDirection(int d);
-  
-  inline char *rootCommand() const { return resource.root_command; }
-  inline void setRootCommand(const char *cmd);
-  
-#ifdef    HAVE_STRFTIME
-  inline char *strftimeFormat() { return resource.strftime_format; }
-  void setStrftimeFormat(const char *);
-#else // !HAVE_STRFTIME
-  inline int dateFormat() { return resource.date_format; }
-  void setDateFormat(int f);
-  inline bool clock24Hour() { return resource.clock24hour; }
-  void setClock24Hour(Bool c);
-#endif // HAVE_STRFTIME
-
-  inline bool hideToolbar() const { return resource.hide_toolbar; }
-  void setHideToolbar(bool);
-
-  inline WindowStyle *getWindowStyle() { return &resource.wstyle; }
-  inline MenuStyle *getMenuStyle() { return &resource.mstyle; }
-  inline ToolbarStyle *getToolbarStyle() { return &resource.tstyle; }
-
-  OpenboxWindow *getIcon(int);
-
-  int addWorkspace();
-  int removeLastWorkspace();
-
-  void removeWorkspaceNames();
-  void addWorkspaceName(const char *);
-  void saveWorkspaceNames();
-  void addNetizen(Netizen *);
-  void removeNetizen(Window);
-  void addIcon(OpenboxWindow *);
-  void removeIcon(OpenboxWindow *);
-  const char *getNameOfWorkspace(int);
-  void changeWorkspaceID(int);
-  void raiseWindows(Window *, int);
-  void reassociateWindow(OpenboxWindow *, int, Bool);
-  void prevFocus();
-  void nextFocus();
-  void raiseFocus();
-  void reconfigure();
-  void load();
-  void save();
-  void rereadMenu();
-  void shutdown();
-  void showPosition(int, int);
-  void showGeometry(unsigned int, unsigned int);
-  void hideGeometry();
-  void updateNetizenCurrentWorkspace();
-  void updateNetizenWorkspaceCount();
-  void updateNetizenWindowFocus();
-  void updateNetizenWindowAdd(Window, unsigned long);
-  void updateNetizenWindowDel(Window);
-  void updateNetizenConfigNotify(XEvent *);
-  void updateNetizenWindowRaise(Window);
-  void updateNetizenWindowLower(Window);
-
-  enum { RowSmartPlacement = 1, ColSmartPlacement, CascadePlacement,
-         BestFitPlacement, UnderMousePlacement, ClickMousePlacement,
-         LeftRight, RightLeft, TopBottom, BottomTop };
-  enum { LeftJustify = 1, RightJustify, CenterJustify };
-  enum { RoundBullet = 1, TriangleBullet, SquareBullet, NoBullet };
-  enum { Restart = 1, RestartOther, Exit, Shutdown, Execute, Reconfigure,
-         WindowShade, WindowIconify, WindowMaximize, WindowClose, WindowRaise,
-         WindowLower, WindowStick, WindowKill, SetStyle };
-};
-
-
-#endif // __Screen_hh
diff --git a/src/Screen.hh b/src/Screen.hh
new file mode 100644 (file)
index 0000000..7a75ac6
--- /dev/null
@@ -0,0 +1,372 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Screen.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef   __Screen_hh
+#define   __Screen_hh
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+
+#ifdef    TIME_WITH_SYS_TIME
+#  include <sys/time.h>
+#  include <time.h>
+#else // !TIME_WITH_SYS_TIME
+#  ifdef    HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#  else // !HAVE_SYS_TIME_H
+#    include <time.h>
+#  endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+}
+
+#include <list>
+#include <vector>
+
+#include "Color.hh"
+#include "Texture.hh"
+#include "Configmenu.hh"
+#include "Iconmenu.hh"
+#include "Netizen.hh"
+#include "Rootmenu.hh"
+#include "Timer.hh"
+#include "Workspace.hh"
+#include "Workspacemenu.hh"
+#include "blackbox.hh"
+class Slit; // forward reference
+
+enum TextJustify { LeftJustify = 1, RightJustify, CenterJustify };
+
+struct WindowStyle {
+  BColor f_focus, f_unfocus, l_text_focus, l_text_unfocus, b_pic_focus,
+    b_pic_unfocus;
+  BTexture t_focus, t_unfocus, l_focus, l_unfocus, h_focus, h_unfocus,
+    b_focus, b_unfocus, b_pressed, g_focus, g_unfocus;
+
+  XFontSet fontset;
+  XFontSetExtents *fontset_extents;
+  XFontStruct *font;
+
+  TextJustify justify;
+
+  int doJustify(const char *text, int &start_pos, unsigned int max_length,
+                unsigned int modifier, bool multibyte) const;
+};
+
+struct ToolbarStyle {
+  BColor l_text, w_text, c_text, b_pic;
+  BTexture toolbar, label, window, button, pressed, clock;
+
+  XFontSet fontset;
+  XFontSetExtents *fontset_extents;
+  XFontStruct *font;
+
+  TextJustify justify;
+
+  int doJustify(const char *text, int &start_pos, unsigned int max_length,
+                unsigned int modifier, bool multibyte) const;
+};
+
+struct MenuStyle {
+  BColor t_text, f_text, h_text, d_text;
+  BTexture title, frame, hilite;
+
+  XFontSet t_fontset, f_fontset;
+  XFontSetExtents *t_fontset_extents, *f_fontset_extents;
+  XFontStruct *t_font, *f_font;
+
+  TextJustify t_justify, f_justify;
+  int bullet, bullet_pos;
+};
+
+struct Strut {
+  unsigned int top, bottom, left, right;
+
+  Strut(void): top(0), bottom(0), left(0), right(0) {}
+};
+
+class BScreen : public ScreenInfo {
+private:
+  bool root_colormap_installed, managed, geom_visible;
+  GC opGC;
+  Pixmap geom_pixmap;
+  Window geom_window;
+
+  Blackbox *blackbox;
+  BImageControl *image_control;
+  Configmenu *configmenu;
+  Iconmenu *iconmenu;
+  Rootmenu *rootmenu;
+
+  typedef std::list<Rootmenu*> RootmenuList;
+  RootmenuList rootmenuList;
+
+  typedef std::list<Netizen*> NetizenList;
+  NetizenList netizenList;
+  BlackboxWindowList iconList, windowList;
+
+  Slit *slit;
+  Toolbar *toolbar;
+  Workspace *current_workspace;
+  Workspacemenu *workspacemenu;
+
+  unsigned int geom_w, geom_h;
+  unsigned long event_mask;
+
+  Rect usableArea;
+
+  typedef std::list<Strut*> StrutList;
+  StrutList strutList;
+  typedef std::vector<std::string> WorkspaceNamesList;
+  WorkspaceNamesList workspaceNames;
+  typedef std::vector<Workspace*> WorkspaceList;
+  WorkspaceList workspacesList;
+
+  struct screen_resource {
+    WindowStyle wstyle;
+    ToolbarStyle tstyle;
+    MenuStyle mstyle;
+
+    bool toolbar_on_top, toolbar_auto_hide, sloppy_focus, auto_raise,
+      auto_edge_balance, image_dither, ordered_dither, opaque_move, full_max,
+      focus_new, focus_last, click_raise;
+    BColor border_color;
+    XrmDatabase stylerc;
+
+    unsigned int workspaces;
+    int toolbar_placement, toolbar_width_percent, placement_policy,
+      edge_snap_threshold, row_direction, col_direction;
+
+    bool slit_on_top, slit_auto_hide;
+    int slit_placement, slit_direction;
+
+    unsigned int handle_width, bevel_width, frame_width, border_width;
+
+#ifdef    HAVE_STRFTIME
+    std::string strftime_format;
+#else // !HAVE_STRFTIME
+    bool clock24hour;
+    int date_format;
+#endif // HAVE_STRFTIME
+
+  } resource;
+
+  BScreen(const BScreen&);
+  BScreen& operator=(const BScreen&);
+
+  bool parseMenuFile(FILE *file, Rootmenu *menu);
+
+  BTexture readDatabaseTexture(const std::string &rname,
+                               const std::string &rclass,
+                               const std::string &default_color);
+  BColor readDatabaseColor(const std::string &rname,
+                           const std::string &rclass,
+                           const std::string &default_color);
+  XFontSet readDatabaseFontSet(const std::string &rname,
+                               const std::string &rclass);
+  XFontStruct *readDatabaseFont(const std::string &rname,
+                                const std::string &rclass);
+  XFontSet createFontSet(const std::string &fontname);
+
+  void InitMenu(void);
+  void LoadStyle(void);
+
+
+public:
+  enum { RowSmartPlacement = 1, ColSmartPlacement, CascadePlacement, LeftRight,
+         RightLeft, TopBottom, BottomTop };
+  enum { RoundBullet = 1, TriangleBullet, SquareBullet, NoBullet };
+  enum { Restart = 1, RestartOther, Exit, Shutdown, Execute, Reconfigure,
+         WindowShade, WindowIconify, WindowMaximize, WindowClose, WindowRaise,
+         WindowLower, WindowStick, WindowKill, SetStyle };
+  enum FocusModel { SloppyFocus, ClickToFocus };
+
+  BScreen(Blackbox *bb, unsigned int scrn);
+  ~BScreen(void);
+
+  inline bool isToolbarOnTop(void) const
+  { return resource.toolbar_on_top; }
+  inline bool doToolbarAutoHide(void) const
+  { return resource.toolbar_auto_hide; }
+  inline bool isSloppyFocus(void) const
+  { return resource.sloppy_focus; }
+  inline bool isRootColormapInstalled(void) const
+  { return root_colormap_installed; }
+  inline bool doAutoRaise(void) const { return resource.auto_raise; }
+  inline bool doClickRaise(void) const { return resource.click_raise; }
+  inline bool isScreenManaged(void) const { return managed; }
+  inline bool doImageDither(void) const
+  { return resource.image_dither; }
+  inline bool doOrderedDither(void) const
+  { return resource.ordered_dither; }
+  inline bool doOpaqueMove(void) const { return resource.opaque_move; }
+  inline bool doFullMax(void) const { return resource.full_max; }
+  inline bool doFocusNew(void) const { return resource.focus_new; }
+  inline bool doFocusLast(void) const { return resource.focus_last; }
+
+  inline const GC &getOpGC(void) const { return opGC; }
+
+  inline Blackbox *getBlackbox(void) { return blackbox; }
+  inline BColor *getBorderColor(void) { return &resource.border_color; }
+  inline BImageControl *getImageControl(void) { return image_control; }
+  inline Rootmenu *getRootmenu(void) { return rootmenu; }
+
+  inline bool isSlitOnTop(void) const { return resource.slit_on_top; }
+  inline bool doSlitAutoHide(void) const
+  { return resource.slit_auto_hide; }
+  inline Slit *getSlit(void) { return slit; }
+  inline int getSlitPlacement(void) const
+  { return resource.slit_placement; }
+  inline int getSlitDirection(void) const
+  { return resource.slit_direction; }
+  inline void saveSlitPlacement(int p) { resource.slit_placement = p; }
+  inline void saveSlitDirection(int d) { resource.slit_direction = d; }
+  inline void saveSlitOnTop(bool t)    { resource.slit_on_top = t; }
+  inline void saveSlitAutoHide(bool t) { resource.slit_auto_hide = t; }
+
+  inline Toolbar *getToolbar(void) { return toolbar; }
+
+  Workspace *getWorkspace(unsigned int index);
+
+  inline Workspace *getCurrentWorkspace(void) { return current_workspace; }
+
+  inline Workspacemenu *getWorkspacemenu(void) { return workspacemenu; }
+
+  inline unsigned int getHandleWidth(void) const
+  { return resource.handle_width; }
+  inline unsigned int getBevelWidth(void) const
+  { return resource.bevel_width; }
+  inline unsigned int getFrameWidth(void) const
+  { return resource.frame_width; }
+  inline unsigned int getBorderWidth(void) const
+  { return resource.border_width; }
+
+  inline unsigned int getCurrentWorkspaceID(void)
+  { return current_workspace->getID(); }
+  inline unsigned int getWorkspaceCount(void)
+  { return workspacesList.size(); }
+  inline unsigned int getIconCount(void) { return iconList.size(); }
+  inline unsigned int getNumberOfWorkspaces(void) const
+  { return resource.workspaces; }
+  inline int getToolbarPlacement(void) const
+  { return resource.toolbar_placement; }
+  inline int getToolbarWidthPercent(void) const
+  { return resource.toolbar_width_percent; }
+  inline int getPlacementPolicy(void) const
+  { return resource.placement_policy; }
+  inline int getEdgeSnapThreshold(void) const
+  { return resource.edge_snap_threshold; }
+  inline int getRowPlacementDirection(void) const
+  { return resource.row_direction; }
+  inline int getColPlacementDirection(void) const
+  { return resource.col_direction; }
+
+  inline void setRootColormapInstalled(bool r) { root_colormap_installed = r; }
+  inline void saveSloppyFocus(bool s) { resource.sloppy_focus = s; }
+  inline void saveAutoRaise(bool a) { resource.auto_raise = a; }
+  inline void saveClickRaise(bool c) { resource.click_raise = c; }
+  inline void saveWorkspaces(unsigned int w) { resource.workspaces = w; }
+  inline void saveToolbarOnTop(bool r) { resource.toolbar_on_top = r; }
+  inline void saveToolbarAutoHide(bool r) { resource.toolbar_auto_hide = r; }
+  inline void saveToolbarWidthPercent(int w)
+  { resource.toolbar_width_percent = w; }
+  inline void saveToolbarPlacement(int p) { resource.toolbar_placement = p; }
+  inline void savePlacementPolicy(int p) { resource.placement_policy = p; }
+  inline void saveRowPlacementDirection(int d) { resource.row_direction = d; }
+  inline void saveColPlacementDirection(int d) { resource.col_direction = d; }
+  inline void saveEdgeSnapThreshold(int t)
+  { resource.edge_snap_threshold = t; }
+  inline void saveImageDither(bool d) { resource.image_dither = d; }
+  inline void saveOpaqueMove(bool o) { resource.opaque_move = o; }
+  inline void saveFullMax(bool f) { resource.full_max = f; }
+  inline void saveFocusNew(bool f) { resource.focus_new = f; }
+  inline void saveFocusLast(bool f) { resource.focus_last = f; }
+  inline void iconUpdate(void) { iconmenu->update(); }
+
+#ifdef    HAVE_STRFTIME
+  inline const char *getStrftimeFormat(void)
+  { return resource.strftime_format.c_str(); }
+  void saveStrftimeFormat(const std::string& format);
+#else // !HAVE_STRFTIME
+  inline int getDateFormat(void) { return resource.date_format; }
+  inline void saveDateFormat(int f) { resource.date_format = f; }
+  inline bool isClock24Hour(void) { return resource.clock24hour; }
+  inline void saveClock24Hour(bool c) { resource.clock24hour = c; }
+#endif // HAVE_STRFTIME
+
+  inline WindowStyle *getWindowStyle(void) { return &resource.wstyle; }
+  inline MenuStyle *getMenuStyle(void) { return &resource.mstyle; }
+  inline ToolbarStyle *getToolbarStyle(void) { return &resource.tstyle; }
+
+  BlackboxWindow *getIcon(unsigned int index);
+
+  const Rect& availableArea(void) const;
+  void updateAvailableArea(void);
+  void addStrut(Strut *strut);
+  void removeStrut(Strut *strut);
+
+  unsigned int addWorkspace(void);
+  unsigned int removeLastWorkspace(void);
+  void removeWorkspaceNames(void);
+  void addWorkspaceName(const std::string& name);
+  const std::string getNameOfWorkspace(unsigned int id);
+  void changeWorkspaceID(unsigned int id);
+
+  void addNetizen(Netizen *n);
+  void removeNetizen(Window w);
+
+  void addIcon(BlackboxWindow *w);
+  void removeIcon(BlackboxWindow *w);
+
+  void manageWindow(Window w);
+  void unmanageWindow(BlackboxWindow *w, bool remap);
+  void raiseWindows(Window *workspace_stack, unsigned int num);
+  void reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id,
+                         bool ignore_sticky);
+  void propagateWindowName(const BlackboxWindow *bw);
+  void prevFocus(void);
+  void nextFocus(void);
+  void raiseFocus(void);
+  void reconfigure(void);
+  void toggleFocusModel(FocusModel model);
+  void updateFocusModel(void);
+  void rereadMenu(void);
+  void shutdown(void);
+  void showPosition(int x, int y);
+  void showGeometry(unsigned int gx, unsigned int gy);
+  void hideGeometry(void);
+
+  void buttonPressEvent(XButtonEvent *xbutton);
+
+  void updateNetizenCurrentWorkspace(void);
+  void updateNetizenWorkspaceCount(void);
+  void updateNetizenWindowFocus(void);
+  void updateNetizenWindowAdd(Window w, unsigned long p);
+  void updateNetizenWindowDel(Window w);
+  void updateNetizenConfigNotify(XEvent *e);
+  void updateNetizenWindowRaise(Window w);
+  void updateNetizenWindowLower(Window w);
+};
+
+
+#endif // __Screen_hh
index 0b1993943a4be9f160204c90dac310550d38deca..087674005c27252e594391027dbd64aa0813abae 100644 (file)
@@ -1,5 +1,6 @@
-// Slit.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Slit.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#ifdef    SLIT
-
+extern "C" {
 #include <X11/keysym.h>
+}
+
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "Image.hh"
+#include "Screen.hh"
+#include "Slit.hh"
+#include "Toolbar.hh"
 
-#include "i18n.h"
-#include "openbox.h"
-#include "Image.h"
-#include "Screen.h"
-#include "Slit.h"
-#include "Toolbar.h"
 
-#include <strstream>
-#include <string>
-using std::ends;
+Slit::Slit(BScreen *scr) {
+  screen = scr;
+  blackbox = screen->getBlackbox();
 
-Slit::Slit(BScreen &scr, Resource &conf) : openbox(scr.getOpenbox()),
-screen(scr), config(conf)
-{
-  load();
+  on_top = screen->isSlitOnTop();
+  hidden = do_auto_hide = screen->doSlitAutoHide();
 
-  display = screen.getBaseDisplay().getXDisplay();
+  display = screen->getBaseDisplay()->getXDisplay();
   frame.window = frame.pixmap = None;
 
-  timer = new BTimer(openbox, *this);
-  // the time out is set in ::reconfigure()
-  timer->fireOnce(True);
+  timer = new BTimer(blackbox, this);
+  timer->setTimeout(blackbox->getAutoRaiseDelay());
 
-  slitmenu = new Slitmenu(*this);
+  slitmenu = new Slitmenu(this);
 
   XSetWindowAttributes attrib;
   unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
-    CWColormap | CWOverrideRedirect | CWEventMask;
+                              CWColormap | CWOverrideRedirect | CWEventMask;
   attrib.background_pixmap = None;
   attrib.background_pixel = attrib.border_pixel =
-    screen.getBorderColor()->getPixel();
-  attrib.colormap = screen.getColormap();
+    screen->getBorderColor()->pixel();
+  attrib.colormap = screen->getColormap();
   attrib.override_redirect = True;
   attrib.event_mask = SubstructureRedirectMask | ButtonPressMask |
-    EnterWindowMask | LeaveWindowMask;
+                      EnterWindowMask | LeaveWindowMask;
 
-  frame.area = Rect(0, 0, 1, 1);
+  frame.rect.setSize(1, 1);
 
   frame.window =
-    XCreateWindow(display, screen.getRootWindow(),
-                  frame.area.x(), frame.area.y(),
-                  frame.area.w(), frame.area.h(), screen.getBorderWidth(),
-                  screen.getDepth(), InputOutput, screen.getVisual(),
-                  create_mask, &attrib);
-  openbox.saveSlitSearch(frame.window, this);
+    XCreateWindow(display, screen->getRootWindow(),
+                  frame.rect.x(), frame.rect.y(),
+                  frame.rect.width(), frame.rect.height(),
+                  screen->getBorderWidth(), screen->getDepth(), InputOutput,
+                  screen->getVisual(), create_mask, &attrib);
+  blackbox->saveSlitSearch(frame.window, this);
+
+  screen->addStrut(&strut);
 
   reconfigure();
 }
 
 
-Slit::~Slit() {
-  openbox.grab();
-
-  if (timer->isTiming()) timer->stop();
+Slit::~Slit(void) {
   delete timer;
 
-  clientList.clear();
-
   delete slitmenu;
 
-  screen.getImageControl()->removeImage(frame.pixmap);
+  screen->getImageControl()->removeImage(frame.pixmap);
 
-  openbox.removeSlitSearch(frame.window);
+  blackbox->removeSlitSearch(frame.window);
 
   XDestroyWindow(display, frame.window);
-
-  openbox.ungrab();
 }
 
 
 void Slit::addClient(Window w) {
-  openbox.grab();
-
-  if (openbox.validateWindow(w)) {
-    SlitClient *client = new SlitClient;
-    client->client_window = w;
-
-    XWMHints *wmhints = XGetWMHints(display, w);
-
-    if (wmhints) {
-      if ((wmhints->flags & IconWindowHint) &&
-          (wmhints->icon_window != None)) {
-        XMoveWindow(display, client->client_window, screen.size().w() + 10,
-                    screen.size().h() + 10);
-        XMapWindow(display, client->client_window);
-
-        client->icon_window = wmhints->icon_window;
-        client->window = client->icon_window;
-      } else {
-        client->icon_window = None;
-        client->window = client->client_window;
-      }
+  if (! blackbox->validateWindow(w))
+    return;
+
+  SlitClient *client = new SlitClient;
+  client->client_window = w;
+
+  XWMHints *wmhints = XGetWMHints(display, w);
 
-      XFree(wmhints);
+  if (wmhints) {
+    if ((wmhints->flags & IconWindowHint) &&
+        (wmhints->icon_window != None)) {
+      // some dock apps use separate windows, we need to hide these
+      XMoveWindow(display, client->client_window, screen->getWidth() + 10,
+                  screen->getHeight() + 10);
+      XMapWindow(display, client->client_window);
+
+      client->icon_window = wmhints->icon_window;
+      client->window = client->icon_window;
     } else {
       client->icon_window = None;
       client->window = client->client_window;
     }
 
-    XWindowAttributes attrib;
-    if (XGetWindowAttributes(display, client->window, &attrib)) {
-      client->width = attrib.width;
-      client->height = attrib.height;
-    } else {
-      client->width = client->height = 64;
-    }
-
-    XSetWindowBorderWidth(display, client->window, 0);
+    XFree(wmhints);
+  } else {
+    client->icon_window = None;
+    client->window = client->client_window;
+  }
 
-    XSelectInput(display, frame.window, NoEventMask);
-    XSelectInput(display, client->window, NoEventMask);
+  XWindowAttributes attrib;
+  if (XGetWindowAttributes(display, client->window, &attrib)) {
+    client->rect.setSize(attrib.width, attrib.height);
+  } else {
+    client->rect.setSize(64, 64);
+  }
 
-    XReparentWindow(display, client->window, frame.window, 0, 0);
-    XMapRaised(display, client->window);
-    XChangeSaveSet(display, client->window, SetModeInsert);
+  XSetWindowBorderWidth(display, client->window, 0);
 
-    XSelectInput(display, frame.window, SubstructureRedirectMask |
-                 ButtonPressMask | EnterWindowMask | LeaveWindowMask);
-    XSelectInput(display, client->window, StructureNotifyMask |
-                 SubstructureNotifyMask | EnterWindowMask);
-    XFlush(display);
+  XGrabServer(display);
+  XSelectInput(display, frame.window, NoEventMask);
+  XSelectInput(display, client->window, NoEventMask);
+  XReparentWindow(display, client->window, frame.window, 0, 0);
+  XMapRaised(display, client->window);
+  XChangeSaveSet(display, client->window, SetModeInsert);
+  XSelectInput(display, frame.window, SubstructureRedirectMask |
+               ButtonPressMask | EnterWindowMask | LeaveWindowMask);
+  XSelectInput(display, client->window, StructureNotifyMask |
+               SubstructureNotifyMask | EnterWindowMask);
 
-    clientList.push_back(client);
+  XUngrabServer(display);
 
-    openbox.saveSlitSearch(client->client_window, this);
-    openbox.saveSlitSearch(client->icon_window, this);
-    reconfigure();
-  }
+  clientList.push_back(client);
 
-  openbox.ungrab();
+  blackbox->saveSlitSearch(client->client_window, this);
+  blackbox->saveSlitSearch(client->icon_window, this);
+  reconfigure();
 }
 
 
-void Slit::removeClient(SlitClient *client, Bool remap) {
-  openbox.removeSlitSearch(client->client_window);
-  openbox.removeSlitSearch(client->icon_window);
-
+void Slit::removeClient(SlitClient *client, bool remap) {
+  blackbox->removeSlitSearch(client->client_window);
+  blackbox->removeSlitSearch(client->icon_window);
   clientList.remove(client);
 
-  screen.removeNetizen(client->window);
+  screen->removeNetizen(client->window);
 
-  if (remap && openbox.validateWindow(client->window)) {
+  if (remap && blackbox->validateWindow(client->window)) {
+    XGrabServer(display);
     XSelectInput(display, frame.window, NoEventMask);
     XSelectInput(display, client->window, NoEventMask);
-    XReparentWindow(display, client->window, screen.getRootWindow(),
-                    client->x, client->y);
+    XReparentWindow(display, client->window, screen->getRootWindow(),
+                    client->rect.x(), client->rect.y());
     XChangeSaveSet(display, client->window, SetModeDelete);
     XSelectInput(display, frame.window, SubstructureRedirectMask |
                  ButtonPressMask | EnterWindowMask | LeaveWindowMask);
-    XFlush(display);
+    XUngrabServer(display);
   }
 
   delete client;
@@ -191,287 +176,174 @@ void Slit::removeClient(SlitClient *client, Bool remap) {
 }
 
 
-void Slit::removeClient(Window w, Bool remap) {
-  openbox.grab();
+struct SlitClientMatch {
+  Window window;
+  SlitClientMatch(Window w): window(w) {}
+  inline bool operator()(const Slit::SlitClient* client) const {
+    return (client->window == window);
+  }
+};
 
-  Bool reconf = False;
 
-  slitClientList::iterator it;
-  for (it = clientList.begin(); it != clientList.end(); it++)
-    if ((*it)->window == w) {
-      removeClient(*it, remap);
-      reconf = True;
-      break;
-    }
+void Slit::removeClient(Window w, bool remap) {
+  SlitClientList::iterator it = clientList.begin();
+  const SlitClientList::iterator end = clientList.end();
 
-  if (reconf)
+  it = std::find_if(it, end, SlitClientMatch(w));
+  if (it != end) {
+    removeClient(*it, remap);
     reconfigure();
-
-  openbox.ungrab();
-}
-
-void Slit::setOnTop(bool b) {
-  m_ontop = b;
-  std::ostrstream s;
-  s << "session.screen" << screen.getScreenNumber() << ".slit.onTop" << ends;
-  config.setValue(s.str(), m_ontop ? "True" : "False");
-  s.rdbuf()->freeze(0);
-}
-
-void Slit::setAutoHide(bool b) {
-  m_autohide = b;
-  std::ostrstream s;
-  s << "session.screen" << screen.getScreenNumber() << ".slit.autoHide" << ends;
-  config.setValue(s.str(), m_autohide ? "True" : "False");
-  s.rdbuf()->freeze(0);
-}
-
-void Slit::setPlacement(int p) {
-  m_placement = p;
-  std::ostrstream s;
-  s << "session.screen" << screen.getScreenNumber() << ".slit.placement"
-    << ends;
-  const char *placement;
-  switch (m_placement) {
-  case TopLeft: placement = "TopLeft"; break;
-  case CenterLeft: placement = "CenterLeft"; break;
-  case BottomLeft: placement = "BottomLeft"; break;
-  case TopCenter: placement = "TopCenter"; break;
-  case BottomCenter: placement = "BottomCenter"; break;
-  case TopRight: placement = "TopRight"; break;
-  case BottomRight: placement = "BottomRight"; break;
-  case CenterRight: default: placement = "CenterRight"; break;
   }
-  config.setValue(s.str(), placement);
-  s.rdbuf()->freeze(0);
-}
-
-void Slit::setDirection(int d) {
-  m_direction = d;
-  std::ostrstream s;
-  s << "session.screen" << screen.getScreenNumber() << ".slit.direction"
-    << ends;
-  config.setValue(s.str(),
-                  m_direction == Horizontal ? "Horizontal" : "Vertical");
-  s.rdbuf()->freeze(0);
 }
 
-void Slit::save() {
-  setOnTop(m_ontop);
-  setAutoHide(m_autohide);
-  setPlacement(m_placement);
-  setDirection(m_direction);
-}
-
-void Slit::load() {
-  std::ostrstream rscreen, rname, rclass;
-  std::string s;
-  bool b;
-  rscreen << "session.screen" << screen.getScreenNumber() << '.' << ends;
-
-  rname << rscreen.str() << "slit.placement" << ends;
-  rclass << rscreen.str() << "Slit.Placement" << ends;
-  if (config.getValue(rname.str(), rclass.str(), s)) {
-    if (0 == strncasecmp(s.c_str(), "TopLeft", s.length()))
-      m_placement = TopLeft;
-    else if (0 == strncasecmp(s.c_str(), "CenterLeft", s.length()))
-      m_placement = CenterLeft;
-    else if (0 == strncasecmp(s.c_str(), "BottomLeft", s.length()))
-      m_placement = BottomLeft;
-    else if (0 == strncasecmp(s.c_str(), "TopCenter", s.length()))
-      m_placement = TopCenter;
-    else if (0 == strncasecmp(s.c_str(), "BottomCenter", s.length()))
-      m_placement = BottomCenter;
-    else if (0 == strncasecmp(s.c_str(), "TopRight", s.length()))
-      m_placement = TopRight;
-    else if (0 == strncasecmp(s.c_str(), "BottomRight", s.length()))
-      m_placement = BottomRight;
-    else if (0 == strncasecmp(s.c_str(), "CenterRight", s.length()))
-      m_placement = CenterRight;
-  } else
-    m_placement = CenterRight;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "slit.direction" << ends;
-  rclass << rscreen.str() << "Slit.Direction" << ends;
-  if (config.getValue(rname.str(), rclass.str(), s)) {
-    if (0 == strncasecmp(s.c_str(), "Horizontal", s.length()))
-      m_direction = Horizontal;
-    else if (0 == strncasecmp(s.c_str(), "Vertical", s.length()))
-      m_direction = Vertical;
-  } else
-    m_direction = Vertical;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "slit.onTop" << ends;
-  rclass << rscreen.str() << "Slit.OnTop" << ends;
-  if (config.getValue(rname.str(), rclass.str(), b))
-    m_ontop = b;
-  else
-    m_ontop = false;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "slit.autoHide" << ends;
-  rclass << rscreen.str() << "Slit.AutoHide" << ends;
-  if (config.getValue(rname.str(), rclass.str(), b))
-    m_hidden = m_autohide = b;
-  else
-    m_hidden = m_autohide = false;
-
-  rscreen.rdbuf()->freeze(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-}
 
 void Slit::reconfigure(void) {
-  timer->setTimeout(openbox.getAutoRaiseDelay());
+  SlitClientList::iterator it = clientList.begin();
+  const SlitClientList::iterator end = clientList.end();
+  SlitClient *client;
 
-  frame.area.setSize(0, 0);
-  slitClientList::const_iterator it;
+  unsigned int width = 0, height = 0;
 
-  switch (m_direction) {
+  switch (screen->getSlitDirection()) {
   case Vertical:
-    for (it = clientList.begin(); it != clientList.end(); it++) {
-      frame.area.setH(frame.area.h() + (*it)->height + screen.getBevelWidth());
+    for (; it != end; ++it) {
+      client = *it;
+      height += client->rect.height() + screen->getBevelWidth();
 
-      if (frame.area.w() < (*it)->width)
-        frame.area.setW((*it)->width);
+      if (width < client->rect.width())
+        width = client->rect.width();
     }
 
-    if (frame.area.w() < 1)
-      frame.area.setW(1);
+    if (width < 1)
+      width = 1;
     else
-      frame.area.setW(frame.area.w() + (screen.getBevelWidth() * 2));
+      width += (screen->getBevelWidth() * 2);
 
-    if (frame.area.h() < 1)
-      frame.area.setH(1);
+    if (height < 1)
+      height = 1;
     else
-      frame.area.setH(frame.area.h() + screen.getBevelWidth());
+      height += screen->getBevelWidth();
 
     break;
 
   case Horizontal:
-    for (it = clientList.begin(); it != clientList.end(); it++) {
-      frame.area.setW(frame.area.w() + (*it)->width + screen.getBevelWidth());
+    for (; it != end; ++it) {
+      client = *it;
+      width += client->rect.width() + screen->getBevelWidth();
 
-      if (frame.area.h() < (*it)->height)
-        frame.area.setH((*it)->height);
+      if (height < client->rect.height())
+        height = client->rect.height();
     }
 
-    if (frame.area.w() < 1)
-      frame.area.setW(1);
+    if (width < 1)
+      width = 1;
     else
-      frame.area.setW(frame.area.w() + screen.getBevelWidth());
+      width += screen->getBevelWidth();
 
-    if (frame.area.h() < 1)
-      frame.area.setH(1);
+    if (height < 1)
+      height = 1;
     else
-      frame.area.setH(frame.area.h() + (screen.getBevelWidth() * 2));
+      height += (screen->getBevelWidth() * 2);
 
     break;
   }
+  frame.rect.setSize(width, height);
 
   reposition();
 
-  XSetWindowBorderWidth(display ,frame.window, screen.getBorderWidth());
+  XSetWindowBorderWidth(display ,frame.window, screen->getBorderWidth());
   XSetWindowBorder(display, frame.window,
-                   screen.getBorderColor()->getPixel());
+                   screen->getBorderColor()->pixel());
 
-  if (! clientList.size())
+  if (clientList.empty())
     XUnmapWindow(display, frame.window);
   else
     XMapWindow(display, frame.window);
 
-  Pixmap tmp = frame.pixmap;
-  BImageControl *image_ctrl = screen.getImageControl();
-  BTexture *texture = &(screen.getToolbarStyle()->toolbar);
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-    frame.pixmap = None;
-    XSetWindowBackground(display, frame.window,
-                         texture->getColor()->getPixel());
-  } else {
-    frame.pixmap = image_ctrl->renderImage(frame.area.w(), frame.area.h(),
-                                           texture);
+  BTexture *texture = &(screen->getToolbarStyle()->toolbar);
+  frame.pixmap = texture->render(frame.rect.width(), frame.rect.height(),
+                                 frame.pixmap);
+  if (! frame.pixmap)
+    XSetWindowBackground(display, frame.window, texture->color().pixel());
+  else
     XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap);
-  }
-  if (tmp) image_ctrl->removeImage(tmp);
+
   XClearWindow(display, frame.window);
 
+  it = clientList.begin();
+
   int x, y;
 
-  switch (m_direction) {
+  switch (screen->getSlitDirection()) {
   case Vertical:
     x = 0;
-    y = screen.getBevelWidth();
+    y = screen->getBevelWidth();
 
-    for (it = clientList.begin(); it != clientList.end(); it++) {
-      x = (frame.area.w() - (*it)->width) / 2;
+    for (; it != end; ++it) {
+      client = *it;
+      x = (frame.rect.width() - client->rect.width()) / 2;
 
-      XMoveResizeWindow(display, (*it)->window, x, y,
-                        (*it)->width, (*it)->height);
-      XMapWindow(display, (*it)->window);
+      XMoveResizeWindow(display, client->window, x, y,
+                        client->rect.width(), client->rect.height());
+      XMapWindow(display, client->window);
 
       // for ICCCM compliance
-      (*it)->x = x;
-      (*it)->y = y;
+      client->rect.setPos(x, y);
 
       XEvent event;
       event.type = ConfigureNotify;
 
       event.xconfigure.display = display;
-      event.xconfigure.event = (*it)->window;
-      event.xconfigure.window = (*it)->window;
+      event.xconfigure.event = client->window;
+      event.xconfigure.window = client->window;
       event.xconfigure.x = x;
       event.xconfigure.y = y;
-      event.xconfigure.width = (*it)->width;
-      event.xconfigure.height = (*it)->height;
+      event.xconfigure.width = client->rect.width();
+      event.xconfigure.height = client->rect.height();
       event.xconfigure.border_width = 0;
       event.xconfigure.above = frame.window;
       event.xconfigure.override_redirect = False;
 
-      XSendEvent(display, (*it)->window, False, StructureNotifyMask, &event);
+      XSendEvent(display, client->window, False, StructureNotifyMask, &event);
 
-      y += (*it)->height + screen.getBevelWidth();
+      y += client->rect.height() + screen->getBevelWidth();
     }
 
     break;
 
   case Horizontal:
-    x = screen.getBevelWidth();
+    x = screen->getBevelWidth();
     y = 0;
 
-    for (it = clientList.begin(); it != clientList.end(); it++) {
-      y = (frame.area.h() - (*it)->height) / 2;
+    for (; it != end; ++it) {
+      client = *it;
+      y = (frame.rect.height() - client->rect.height()) / 2;
 
-      XMoveResizeWindow(display, (*it)->window, x, y,
-                        (*it)->width, (*it)->height);
-      XMapWindow(display, (*it)->window);
+      XMoveResizeWindow(display, client->window, x, y,
+                        client->rect.width(), client->rect.height());
+      XMapWindow(display, client->window);
 
       // for ICCCM compliance
-      (*it)->x = x;
-      (*it)->y = y;
+      client->rect.setPos(x, y);
 
       XEvent event;
       event.type = ConfigureNotify;
 
       event.xconfigure.display = display;
-      event.xconfigure.event = (*it)->window;
-      event.xconfigure.window = (*it)->window;
+      event.xconfigure.event = client->window;
+      event.xconfigure.window = client->window;
       event.xconfigure.x = x;
       event.xconfigure.y = y;
-      event.xconfigure.width = (*it)->width;
-      event.xconfigure.height = (*it)->height;
+      event.xconfigure.width = client->rect.width();
+      event.xconfigure.height = client->rect.height();
       event.xconfigure.border_width = 0;
       event.xconfigure.above = frame.window;
       event.xconfigure.override_redirect = False;
 
-      XSendEvent(display, (*it)->window, False, StructureNotifyMask, &event);
+      XSendEvent(display, client->window, False, StructureNotifyMask, &event);
 
-      x += (*it)->width + screen.getBevelWidth();
+      x += client->rect.width() + screen->getBevelWidth();
     }
-
     break;
   }
 
@@ -479,121 +351,195 @@ void Slit::reconfigure(void) {
 }
 
 
+void Slit::updateStrut(void) {
+  strut.top = strut.bottom = strut.left = strut.right = 0;
+
+  if (! clientList.empty()) {
+    switch (screen->getSlitDirection()) {
+    case Vertical:
+      switch (screen->getSlitPlacement()) {
+      case TopCenter:
+        strut.top = getY() + getExposedHeight() +
+                    (screen->getBorderWidth() * 2);
+        break;
+      case BottomCenter:
+        strut.bottom = screen->getHeight() - getY();
+        break;
+      case TopLeft:
+      case CenterLeft:
+      case BottomLeft:
+        strut.left = getExposedWidth() + (screen->getBorderWidth() * 2);
+        break;
+      case TopRight:
+      case CenterRight:
+      case BottomRight:
+        strut.right = getExposedWidth() + (screen->getBorderWidth() * 2);
+        break;
+      }
+      break;
+    case Horizontal:
+      switch (screen->getSlitPlacement()) {
+      case TopCenter:
+      case TopLeft:
+      case TopRight:
+        strut.top = getY() + getExposedHeight() +
+                    (screen->getBorderWidth() * 2);
+        break;
+      case BottomCenter:
+      case BottomLeft:
+      case BottomRight:
+        strut.bottom = screen->getHeight() - getY();
+        break;
+      case CenterLeft:
+        strut.left = getExposedWidth() + (screen->getBorderWidth() * 2);
+        break;
+      case CenterRight:
+        strut.right = getExposedWidth() + (screen->getBorderWidth() * 2);
+        break;
+      }
+      break;
+    }
+  }
+
+  // update area with new Strut info
+  screen->updateAvailableArea();
+}
+
+
 void Slit::reposition(void) {
   // place the slit in the appropriate place
-  switch (m_placement) {
+  switch (screen->getSlitPlacement()) {
   case TopLeft:
-    frame.area.setOrigin(0, 0);
-    if (m_direction == Vertical) {
-      frame.hidden = Point(screen.getBevelWidth() - screen.getBorderWidth()
-                           - frame.area.w(), 0);
+    frame.rect.setPos(0, 0);
+
+    if (screen->getSlitDirection() == Vertical) {
+      frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
+                       - frame.rect.width();
+      frame.y_hidden = 0;
     } else {
-      frame.hidden = Point(0, screen.getBevelWidth() - screen.getBorderWidth()
-                           - frame.area.h());
+      frame.x_hidden = 0;
+      frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
+                       - frame.rect.height();
     }
     break;
 
   case CenterLeft:
-    frame.area.setOrigin(0, (screen.size().h() - frame.area.h()) / 2);
-    frame.hidden = Point(screen.getBevelWidth() - screen.getBorderWidth()
-                         - frame.area.w(), frame.area.y());
+    frame.rect.setPos(0, (screen->getHeight() - frame.rect.height()) / 2);
+
+    frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
+                     - frame.rect.width();
+    frame.y_hidden = frame.rect.y();
     break;
 
   case BottomLeft:
-    frame.area.setOrigin(0, screen.size().h() - frame.area.h()
-                         - (screen.getBorderWidth() * 2));
-    if (m_direction == Vertical)
-      frame.hidden = Point(screen.getBevelWidth() - screen.getBorderWidth()
-                           - frame.area.w(), frame.area.y());
-    else
-      frame.hidden = Point(0, screen.size().h() - screen.getBevelWidth()
-                           - screen.getBorderWidth());
+    frame.rect.setPos(0, (screen->getHeight() - frame.rect.height()
+                          - (screen->getBorderWidth() * 2)));
+
+    if (screen->getSlitDirection() == Vertical) {
+      frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth()
+                       - frame.rect.width();
+      frame.y_hidden = frame.rect.y();
+    } else {
+      frame.x_hidden = 0;
+      frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
+                       - screen->getBorderWidth();
+    }
     break;
 
   case TopCenter:
-    frame.area.setOrigin((screen.size().w() - frame.area.w()) / 2, 0);
-    frame.hidden = Point(frame.area.x(), screen.getBevelWidth()
-                         - screen.getBorderWidth() - frame.area.h());
+    frame.rect.setPos((screen->getWidth() - frame.rect.width()) / 2, 0);
+
+    frame.x_hidden = frame.rect.x();
+    frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
+                     - frame.rect.height();
     break;
 
   case BottomCenter:
-    frame.area.setOrigin((screen.size().w() - frame.area.w()) / 2,
-                         screen.size().h() - frame.area.h()
-                         - (screen.getBorderWidth() * 2));
-    frame.hidden = Point(frame.area.x(), screen.size().h()
-                         - screen.getBevelWidth() - screen.getBorderWidth());
+    frame.rect.setPos((screen->getWidth() - frame.rect.width()) / 2,
+                      (screen->getHeight() - frame.rect.height()
+                       - (screen->getBorderWidth() * 2)));
+    frame.x_hidden = frame.rect.x();
+    frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
+                     - screen->getBorderWidth();
     break;
 
   case TopRight:
-    frame.area.setOrigin(screen.size().w() - frame.area.w()
-                         - (screen.getBorderWidth() * 2), 0);
-    if (m_direction == Vertical)
-      frame.hidden = Point(screen.size().w() - screen.getBevelWidth()
-                           - screen.getBorderWidth(), 0);
-    else
-      frame.hidden = Point(frame.area.x(), screen.getBevelWidth()
-                           - screen.getBorderWidth() - frame.area.h());
+    frame.rect.setPos((screen->getWidth() - frame.rect.width()
+                       - (screen->getBorderWidth() * 2)), 0);
+
+    if (screen->getSlitDirection() == Vertical) {
+      frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
+                       - screen->getBorderWidth();
+      frame.y_hidden = 0;
+    } else {
+      frame.x_hidden = frame.rect.x();
+      frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
+                       - frame.rect.height();
+    }
     break;
 
   case CenterRight:
   default:
-    frame.area.setOrigin(screen.size().w() - frame.area.w()
-                         - (screen.getBorderWidth() * 2),
-                         (screen.size().h() - frame.area.h()) / 2);
-    frame.hidden = Point(screen.size().w() - screen.getBevelWidth()
-                         - screen.getBorderWidth(), frame.area.y());
+    frame.rect.setPos((screen->getWidth() - frame.rect.width()
+                       - (screen->getBorderWidth() * 2)),
+                      (screen->getHeight() - frame.rect.height()) / 2);
+
+    frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
+                     - screen->getBorderWidth();
+    frame.y_hidden = frame.rect.y();
     break;
 
   case BottomRight:
-    frame.area.setOrigin(screen.size().w() - frame.area.w()
-                         - (screen.getBorderWidth() * 2),
-                         screen.size().h() - frame.area.h()
-                         - (screen.getBorderWidth() * 2));
-    if (m_direction == Vertical)
-      frame.hidden = Point(screen.size().w() - screen.getBevelWidth()
-                           - screen.getBorderWidth(), frame.area.y());
-    else
-      frame.hidden = Point(frame.area.x(), screen.size().h() -
-                           screen.getBevelWidth() - screen.getBorderWidth());
+    frame.rect.setPos((screen->getWidth() - frame.rect.width()
+                       - (screen->getBorderWidth() * 2)),
+                      (screen->getHeight() - frame.rect.height()
+                       - (screen->getBorderWidth() * 2)));
+
+    if (screen->getSlitDirection() == Vertical) {
+      frame.x_hidden = screen->getWidth() - screen->getBevelWidth()
+                       - screen->getBorderWidth();
+      frame.y_hidden = frame.rect.y();
+    } else {
+      frame.x_hidden = frame.rect.x();
+      frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
+                       - screen->getBorderWidth();
+    }
     break;
   }
 
-  Toolbar *tbar = screen.getToolbar();
-  int sw = frame.area.w() + (screen.getBorderWidth() * 2),
-  sh = frame.area.h() + (screen.getBorderWidth() * 2),
-  tw = tbar->area().w() + screen.getBorderWidth(),
-  th = tbar->area().h() + screen.getBorderWidth();
-
-  if (tbar->area().x() < frame.area.x() + sw &&
-      tbar->area().x() + tw > frame.area.x() &&
-      tbar->area().y() < frame.area.y() + sh &&
-      tbar->area().y() + th > frame.area.y()) {
-    if (frame.area.y() < th) {
-      frame.area.setY(frame.area.y() + tbar->getExposedHeight());
-      if (m_direction == Vertical)
-        frame.hidden.setY(frame.hidden.y() + tbar->getExposedHeight());
-      else
-        frame.hidden.setY(frame.area.y());
-    } else {
-      frame.area.setY(frame.area.y() - tbar->getExposedHeight());
-      if (m_direction == Vertical)
-        frame.hidden.setY(frame.area.y() - tbar->getExposedHeight());
-      else
-        frame.hidden.setY(frame.area.y());
+  Rect tbar_rect = screen->getToolbar()->getRect();
+  tbar_rect.setSize(tbar_rect.width() + (screen->getBorderWidth() * 2),
+                    tbar_rect.height() + (screen->getBorderWidth() * 2));
+  Rect slit_rect = frame.rect;
+  slit_rect.setSize(slit_rect.width() + (screen->getBorderWidth() * 2),
+                    slit_rect.height() + (screen->getBorderWidth() * 2));
+
+  if (slit_rect.intersects(tbar_rect)) {
+    Toolbar *tbar = screen->getToolbar();
+    frame.y_hidden = frame.rect.y();
+
+    int delta = tbar->getExposedHeight() + (screen->getBorderWidth() * 2);
+    if (frame.rect.bottom() <= tbar_rect.bottom()) {
+      delta = -delta;
     }
+    frame.rect.setY(frame.rect.y() + delta);
+    if (screen->getSlitDirection() == Vertical)
+      frame.y_hidden += delta;
   }
 
-  if (m_hidden)
-    XMoveResizeWindow(display, frame.window, frame.hidden.x(),
-                      frame.hidden.y(), frame.area.w(), frame.area.h());
+  updateStrut();
+
+  if (hidden)
+    XMoveResizeWindow(display, frame.window, frame.x_hidden,
+                      frame.y_hidden, frame.rect.width(), frame.rect.height());
   else
-    XMoveResizeWindow(display, frame.window, frame.area.x(),
-                      frame.area.y(), frame.area.w(), frame.area.h());
+    XMoveResizeWindow(display, frame.window, frame.rect.x(), frame.rect.y(),
+                      frame.rect.width(), frame.rect.height());
 }
 
 
 void Slit::shutdown(void) {
-  while (clientList.size())
+  while (! clientList.empty())
     removeClient(clientList.front());
 }
 
@@ -601,10 +547,10 @@ void Slit::shutdown(void) {
 void Slit::buttonPressEvent(XButtonEvent *e) {
   if (e->window != frame.window) return;
 
-  if (e->button == Button1 && !m_ontop) {
+  if (e->button == Button1 && (! on_top)) {
     Window w[1] = { frame.window };
-    screen.raiseWindows(w, 1);
-  } else if (e->button == Button2 && !m_ontop) {
+    screen->raiseWindows(w, 1);
+  } else if (e->button == Button2 && (! on_top)) {
     XLowerWindow(display, frame.window);
   } else if (e->button == Button3) {
     if (! slitmenu->isVisible()) {
@@ -615,13 +561,13 @@ void Slit::buttonPressEvent(XButtonEvent *e) {
 
       if (x < 0)
         x = 0;
-      else if (x + slitmenu->getWidth() > screen.size().w())
-        x = screen.size().w() - slitmenu->getWidth();
+      else if (x + slitmenu->getWidth() > screen->getWidth())
+        x = screen->getWidth() - slitmenu->getWidth();
 
       if (y < 0)
         y = 0;
-      else if (y + slitmenu->getHeight() > screen.size().h())
-        y = screen.size().h() - slitmenu->getHeight();
+      else if (y + slitmenu->getHeight() > screen->getHeight())
+        y = screen->getHeight() - slitmenu->getHeight();
 
       slitmenu->move(x, y);
       slitmenu->show();
@@ -633,10 +579,10 @@ void Slit::buttonPressEvent(XButtonEvent *e) {
 
 
 void Slit::enterNotifyEvent(XCrossingEvent *) {
-  if (!m_autohide)
+  if (! do_auto_hide)
     return;
 
-  if (m_hidden) {
+  if (hidden) {
     if (! timer->isTiming()) timer->start();
   } else {
     if (timer->isTiming()) timer->stop();
@@ -645,69 +591,84 @@ void Slit::enterNotifyEvent(XCrossingEvent *) {
 
 
 void Slit::leaveNotifyEvent(XCrossingEvent *) {
-  if (!m_autohide)
+  if (! do_auto_hide)
     return;
 
-  if (m_hidden) {
+  if (hidden) {
     if (timer->isTiming()) timer->stop();
   } else if (! slitmenu->isVisible()) {
-    if (!timer->isTiming()) timer->start();
+    if (! timer->isTiming()) timer->start();
   }
 }
 
 
 void Slit::configureRequestEvent(XConfigureRequestEvent *e) {
-  openbox.grab();
-
-  if (openbox.validateWindow(e->window)) {
-    Bool reconf = False;
-    XWindowChanges xwc;
-
-    xwc.x = e->x;
-    xwc.y = e->y;
-    xwc.width = e->width;
-    xwc.height = e->height;
-    xwc.border_width = 0;
-    xwc.sibling = e->above;
-    xwc.stack_mode = e->detail;
-
-    XConfigureWindow(display, e->window, e->value_mask, &xwc);
-
-    slitClientList::iterator it = clientList.begin();
-    for (; it != clientList.end(); it++) {
-      SlitClient *client = *it;
-      if (client->window == e->window)
-        if (client->width != ((unsigned) e->width) ||
-            client->height != ((unsigned) e->height)) {
-          client->width = (unsigned) e->width;
-          client->height = (unsigned) e->height;
-          reconf = True;
-          break;
-        }
-    }
+  if (! blackbox->validateWindow(e->window))
+    return;
+
+  XWindowChanges xwc;
+
+  xwc.x = e->x;
+  xwc.y = e->y;
+  xwc.width = e->width;
+  xwc.height = e->height;
+  xwc.border_width = 0;
+  xwc.sibling = e->above;
+  xwc.stack_mode = e->detail;
+
+  XConfigureWindow(display, e->window, e->value_mask, &xwc);
+
+  SlitClientList::iterator it = clientList.begin();
+  const SlitClientList::iterator end = clientList.end();
+  for (; it != end; ++it) {
+    SlitClient *client = *it;
+    if (client->window == e->window &&
+        (static_cast<signed>(client->rect.width()) != e->width ||
+         static_cast<signed>(client->rect.height()) != e->height)) {
+      client->rect.setSize(e->width, e->height);
 
-    if (reconf)
       reconfigure();
+      return;
+    }
   }
-  openbox.ungrab();
 }
 
 
 void Slit::timeout(void) {
-  m_hidden = !m_hidden;
-  if (m_hidden)
-    XMoveWindow(display, frame.window, frame.hidden.x(), frame.hidden.y());
+  hidden = ! hidden;
+  if (hidden)
+    XMoveWindow(display, frame.window, frame.x_hidden, frame.y_hidden);
   else
-    XMoveWindow(display, frame.window, frame.area.x(), frame.area.y());
+    XMoveWindow(display, frame.window, frame.rect.x(), frame.rect.y());
 }
 
 
-Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen), slit(sl) {
+void Slit::toggleAutoHide(void) {
+  do_auto_hide = (do_auto_hide) ?  False : True;
+
+  updateStrut();
+
+  if (do_auto_hide == False && hidden) {
+    // force the slit to be visible
+    if (timer->isTiming()) timer->stop();
+    timeout();
+  }
+}
+
+
+void Slit::unmapNotifyEvent(XUnmapEvent *e) {
+  removeClient(e->window);
+}
+
+
+Slitmenu::Slitmenu(Slit *sl) : Basemenu(sl->screen) {
+  slit = sl;
+
   setLabel(i18n(SlitSet, SlitSlitTitle, "Slit"));
   setInternalMenu();
 
-  directionmenu = new Directionmenu(*this);
-  placementmenu = new Placementmenu(*this);
+  directionmenu = new Directionmenu(this);
+  placementmenu = new Placementmenu(this);
 
   insert(i18n(CommonSet, CommonDirectionTitle, "Direction"),
          directionmenu);
@@ -718,12 +679,8 @@ Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen), slit(sl) {
 
   update();
 
-  setValues();
-}
-
-void Slitmenu::setValues() {
-  setItemSelected(2, slit.onTop());
-  setItemSelected(3, slit.autoHide());
+  if (slit->isOnTop()) setItemSelected(2, True);
+  if (slit->doAutoHide()) setItemSelected(3, True);
 }
 
 
@@ -733,7 +690,7 @@ Slitmenu::~Slitmenu(void) {
 }
 
 
-void Slitmenu::itemSelected(int button, int index) {
+void Slitmenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
@@ -742,18 +699,16 @@ void Slitmenu::itemSelected(int button, int index) {
 
   switch (item->function()) {
   case 1: { // always on top
-    bool change = ((slit.onTop()) ?  false : true);
-    slit.setOnTop(change);
-    setItemSelected(2, change);
+    slit->on_top = ((slit->isOnTop()) ?  False : True);
+    setItemSelected(2, slit->on_top);
 
-    if (slit.onTop()) slit.screen.raiseWindows((Window *) 0, 0);
+    if (slit->isOnTop()) slit->screen->raiseWindows((Window *) 0, 0);
     break;
   }
 
   case 2: { // auto hide
-    Bool change = ((slit.autoHide()) ?  false : true);
-    slit.setAutoHide(change);
-    setItemSelected(3, change);
+    slit->toggleAutoHide();
+    setItemSelected(3, slit->do_auto_hide);
 
     break;
   }
@@ -763,13 +718,12 @@ void Slitmenu::itemSelected(int button, int index) {
 
 void Slitmenu::internal_hide(void) {
   Basemenu::internal_hide();
-  if (slit.autoHide())
-    slit.timeout();
+  if (slit->doAutoHide())
+    slit->timeout();
 }
 
 
 void Slitmenu::reconfigure(void) {
-  setValues();
   directionmenu->reconfigure();
   placementmenu->reconfigure();
 
@@ -777,43 +731,34 @@ void Slitmenu::reconfigure(void) {
 }
 
 
-Slitmenu::Directionmenu::Directionmenu(Slitmenu &sm)
-  : Basemenu(sm.slit.screen), slitmenu(sm) {
-    setLabel(i18n(SlitSet, SlitSlitDirection, "Slit Direction"));
-    setInternalMenu();
+Slitmenu::Directionmenu::Directionmenu(Slitmenu *sm)
+  : Basemenu(sm->slit->screen) {
 
-    insert(i18n(CommonSet, CommonDirectionHoriz, "Horizontal"),
-           Slit::Horizontal);
-    insert(i18n(CommonSet, CommonDirectionVert, "Vertical"),
-           Slit::Vertical);
-
-    update();
+  setLabel(i18n(SlitSet, SlitSlitDirection, "Slit Direction"));
+  setInternalMenu();
 
-    setValues();
-  }
+  insert(i18n(CommonSet, CommonDirectionHoriz, "Horizontal"),
+         Slit::Horizontal);
+  insert(i18n(CommonSet, CommonDirectionVert, "Vertical"),
+         Slit::Vertical);
 
+  update();
 
-void Slitmenu::Directionmenu::setValues() {
-  if (slitmenu.slit.direction() == Slit::Horizontal)
+  if (getScreen()->getSlitDirection() == Slit::Horizontal)
     setItemSelected(0, True);
   else
     setItemSelected(1, True);
 }
 
-void Slitmenu::Directionmenu::reconfigure() {
-  setValues();
-  Basemenu::reconfigure();
-}
-
 
-void Slitmenu::Directionmenu::itemSelected(int button, int index) {
+void Slitmenu::Directionmenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
   BasemenuItem *item = find(index);
   if (! item) return;
 
-  slitmenu.slit.setDirection(item->function());
+  getScreen()->saveSlitDirection(item->function());
 
   if (item->function() == Slit::Horizontal) {
     setItemSelected(0, True);
@@ -824,52 +769,48 @@ void Slitmenu::Directionmenu::itemSelected(int button, int index) {
   }
 
   hide();
-  slitmenu.slit.reconfigure();
+  getScreen()->getSlit()->reconfigure();
 }
 
 
-Slitmenu::Placementmenu::Placementmenu(Slitmenu &sm)
-  : Basemenu(sm.slit.screen), slitmenu(sm) {
-
-    setLabel(i18n(SlitSet, SlitSlitPlacement, "Slit Placement"));
-    setMinimumSublevels(3);
-    setInternalMenu();
-
-    insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"),
-           Slit::TopLeft);
-    insert(i18n(CommonSet, CommonPlacementCenterLeft, "Center Left"),
-           Slit::CenterLeft);
-    insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
-           Slit::BottomLeft);
-    insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"),
-           Slit::TopCenter);
-    insert("");
-    insert(i18n(CommonSet, CommonPlacementBottomCenter, 
-                "Bottom Center"),
-           Slit::BottomCenter);
-    insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"),
-           Slit::TopRight);
-    insert(i18n(CommonSet, CommonPlacementCenterRight,
-                "Center Right"),
-           Slit::CenterRight);
-    insert(i18n(CommonSet, CommonPlacementBottomRight,
-                "Bottom Right"),
-           Slit::BottomRight);
-
-    update();
-  }
+Slitmenu::Placementmenu::Placementmenu(Slitmenu *sm)
+  : Basemenu(sm->slit->screen) {
+
+  setLabel(i18n(SlitSet, SlitSlitPlacement, "Slit Placement"));
+  setMinimumSublevels(3);
+  setInternalMenu();
+
+  insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"),
+         Slit::TopLeft);
+  insert(i18n(CommonSet, CommonPlacementCenterLeft, "Center Left"),
+         Slit::CenterLeft);
+  insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
+         Slit::BottomLeft);
+  insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"),
+         Slit::TopCenter);
+  insert("");
+  insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"),
+         Slit::BottomCenter);
+  insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"),
+         Slit::TopRight);
+  insert(i18n(CommonSet, CommonPlacementCenterRight, "Center Right"),
+         Slit::CenterRight);
+  insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"),
+         Slit::BottomRight);
+
+  update();
+}
 
 
-void Slitmenu::Placementmenu::itemSelected(int button, int index) {
+void Slitmenu::Placementmenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
   BasemenuItem *item = find(index);
   if (! (item && item->function())) return;
 
-  slitmenu.slit.setPlacement(item->function());
+  getScreen()->saveSlitPlacement(item->function());
   hide();
-  slitmenu.slit.reconfigure();
+  getScreen()->getSlit()->reconfigure();
 }
 
-#endif // SLIT
diff --git a/src/Slit.h b/src/Slit.h
deleted file mode 100644 (file)
index b07d9c6..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-// Slit.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the 
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in 
-// all copies or substantial portions of the Software. 
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
-// DEALINGS IN THE SOFTWARE.
-  
-#ifndef   __Slit_hh
-#define   __Slit_hh
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#include "Basemenu.h"
-#include "Geometry.h"
-#include <list>
-
-// forward declaration
-class Slit;
-class Slitmenu;
-
-class Slitmenu : public Basemenu {
-private: 
-  class Directionmenu : public Basemenu {
-  private:
-    Slitmenu &slitmenu;
-
-  protected:
-    virtual void itemSelected(int, int);
-    virtual void setValues();
-
-  public:
-    Directionmenu(Slitmenu &);
-    void reconfigure();
-  };
-
-  class Placementmenu : public Basemenu {
-  private:
-    Slitmenu &slitmenu;
-
-  protected: 
-    virtual void itemSelected(int, int);
-
-  public:
-    Placementmenu(Slitmenu &);
-  };
-
-  Directionmenu *directionmenu;
-  Placementmenu *placementmenu;
-
-  Slit &slit;
-
-  friend class Directionmenu;
-  friend class Placementmenu;
-  friend class Slit;
-
-
-protected:
-  virtual void itemSelected(int, int);
-  virtual void internal_hide();
-  virtual void setValues();
-
-public:
-  Slitmenu(Slit &);
-  virtual ~Slitmenu();
-
-  inline Basemenu *getDirectionmenu() { return directionmenu; }
-  inline Basemenu *getPlacementmenu() { return placementmenu; }
-
-  void reconfigure();
-};
-
-
-class Slit : public TimeoutHandler {
-private:
-  class SlitClient {
-  public:
-    Window window, client_window, icon_window;
-
-    int x, y;
-    unsigned int width, height;
-  };
-
-  bool m_ontop, m_autohide, m_hidden;
-  int m_direction, m_placement; 
-  Display *display;
-
-  Openbox &openbox;
-  BScreen &screen;
-  Resource &config;
-  BTimer *timer;
-
-  typedef std::list<SlitClient *> slitClientList;
-  slitClientList clientList;
-  Slitmenu *slitmenu;
-
-  struct frame {
-    Pixmap pixmap;
-    Window window;
-
-    Rect area;
-    Point hidden;
-  } frame;
-
-
-  friend class Slitmenu;
-  friend class Slitmenu::Directionmenu;
-  friend class Slitmenu::Placementmenu;
-
-
-public:
-  Slit(BScreen &, Resource &);
-  virtual ~Slit();
-
-  inline Slitmenu *getMenu() { return slitmenu; }
-
-  inline const Window &getWindowID() const { return frame.window; }
-
-  inline const Point &origin() const { return frame.area.origin(); }
-  inline const Size &size() const { return frame.area.size(); }
-  inline const Rect &area() const { return frame.area; }
-  inline const Point &hiddenOrigin() const { return frame.hidden; }
-
-  void addClient(Window);
-  void removeClient(SlitClient *, Bool = True);
-  void removeClient(Window, Bool = True);
-  void reconfigure();
-  void load();
-  void save();
-  void reposition();
-  void shutdown();
-
-  void buttonPressEvent(XButtonEvent *);
-  void enterNotifyEvent(XCrossingEvent *);
-  void leaveNotifyEvent(XCrossingEvent *);
-  void configureRequestEvent(XConfigureRequestEvent *);
-
-  virtual void timeout();
-
-  inline bool isHidden() const { return m_hidden; }
-
-  inline bool onTop() const { return m_ontop; }
-  void setOnTop(bool);
-  
-  inline bool autoHide() const { return m_autohide; }
-  void setAutoHide(bool);
-  
-  inline int placement() const { return m_placement; }
-  void setPlacement(int);
-
-  inline int direction() const { return m_direction; }
-  void setDirection(int);
-
-  enum { Vertical = 1, Horizontal };
-  enum { TopLeft = 1, CenterLeft, BottomLeft, TopCenter, BottomCenter,
-         TopRight, CenterRight, BottomRight };
-};
-
-
-#endif // __Slit_hh
diff --git a/src/Texture.cc b/src/Texture.cc
new file mode 100644 (file)
index 0000000..716522f
--- /dev/null
@@ -0,0 +1,200 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Texture.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
+// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifdef HAVE_CONFIG_H
+#  include "../config.h"
+#endif // HAVE_CONFIG_H
+
+extern "C" {
+#include <stdio.h>
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+}
+
+#include "Texture.hh"
+#include "BaseDisplay.hh"
+#include "Image.hh"
+#include "Screen.hh"
+#include "blackbox.hh"
+
+using std::string;
+
+
+BTexture::BTexture(const BaseDisplay * const _display,
+                   unsigned int _screen, BImageControl* _ctrl)
+  : c(_display, _screen), ct(_display, _screen),
+    lc(_display, _screen), sc(_display, _screen), t(0),
+    dpy(_display), ctrl(_ctrl), scrn(_screen) { }
+
+
+BTexture::BTexture(const string &d, const BaseDisplay * const _display,
+                   unsigned int _screen, BImageControl* _ctrl)
+  : c(_display, _screen), ct(_display, _screen),
+    lc(_display, _screen), sc(_display, _screen), t(0),
+    dpy(_display), ctrl(_ctrl), scrn(_screen) {
+  setDescription(d);
+}
+
+
+void BTexture::setColor(const BColor &cc) {
+  c = cc;
+  c.setDisplay(display(), screen());
+
+  unsigned char r, g, b, rr, gg, bb;
+
+  // calculate the light color
+  r = c.red();
+  g = c.green();
+  b = c.blue();
+  rr = r + (r >> 1);
+  gg = g + (g >> 1);
+  bb = b + (b >> 1);
+  if (rr < r) rr = ~0;
+  if (gg < g) gg = ~0;
+  if (bb < b) bb = ~0;
+  lc = BColor(rr, gg, bb, display(), screen());
+
+  // calculate the shadow color
+  r = c.red();
+  g = c.green();
+  b = c.blue();
+  rr = (r >> 2) + (r >> 1);
+  gg = (g >> 2) + (g >> 1);
+  bb = (b >> 2) + (b >> 1);
+  if (rr > r) rr = 0;
+  if (gg > g) gg = 0;
+  if (bb > b) bb = 0;
+  sc = BColor(rr, gg, bb, display(), screen());
+}
+
+
+void BTexture::setDescription(const string &d) {
+  descr.erase();
+  descr.reserve(d.length());
+
+  string::const_iterator it = d.begin(), end = d.end();
+  for (; it != end; ++it)
+    descr += tolower(*it);
+
+  if (descr.find("parentrelative") != string::npos) {
+    setTexture(BTexture::Parent_Relative);
+  } else {
+    setTexture(0);
+
+    if (descr.find("gradient") != string::npos) {
+      addTexture(BTexture::Gradient);
+      if (descr.find("crossdiagonal") != string::npos)
+        addTexture(BTexture::CrossDiagonal);
+      else if (descr.find("rectangle") != string::npos)
+        addTexture(BTexture::Rectangle);
+      else if (descr.find("pyramid") != string::npos)
+        addTexture(BTexture::Pyramid);
+      else if (descr.find("pipecross") != string::npos)
+        addTexture(BTexture::PipeCross);
+      else if (descr.find("elliptic") != string::npos)
+        addTexture(BTexture::Elliptic);
+      else if (descr.find("diagonal") != string::npos)
+        addTexture(BTexture::Diagonal);
+      else if (descr.find("horizontal") != string::npos)
+        addTexture(BTexture::Horizontal);
+      else if (descr.find("vertical") != string::npos)
+        addTexture(BTexture::Vertical);
+      else
+        addTexture(BTexture::Diagonal);
+    } else {
+      addTexture(BTexture::Solid);
+    }
+
+    if (descr.find("raised") != string::npos)
+      addTexture(BTexture::Raised);
+    else if (descr.find("sunken") != string::npos)
+      addTexture(BTexture::Sunken);
+    else if (descr.find("flat") != string::npos)
+      addTexture(BTexture::Flat);
+    else
+      addTexture(BTexture::Raised);
+
+    if (! (texture() & BTexture::Flat)) {
+      if (descr.find("bevel2") != string::npos)
+        addTexture(BTexture::Bevel2);
+      else
+        addTexture(BTexture::Bevel1);
+    }
+
+    if (descr.find("interlaced") != string::npos)
+      addTexture(BTexture::Interlaced);
+  }
+}
+
+void BTexture::setDisplay(const BaseDisplay * const _display,
+                          const unsigned int _screen) {
+  if (_display == display() && _screen == screen()) {
+    // nothing to do
+    return;
+  }
+
+  dpy = _display;
+  scrn = _screen;
+  c.setDisplay(_display, _screen);
+  ct.setDisplay(_display, _screen);
+  lc.setDisplay(_display, _screen);
+  sc.setDisplay(_display, _screen);
+}
+
+
+BTexture& BTexture::operator=(const BTexture &tt) {
+  c  = tt.c;
+  ct = tt.ct;
+  lc = tt.lc;
+  sc = tt.sc;
+  descr = tt.descr;
+  t  = tt.t;
+  dpy = tt.dpy;
+  scrn = tt.scrn;
+  ctrl = tt.ctrl;
+
+  return *this;
+}
+
+
+Pixmap BTexture::render(const unsigned int width, const unsigned int height,
+                        const Pixmap old) {
+  assert(display() != 0);
+
+  if (texture() == (BTexture::Flat | BTexture::Solid))
+    return None;
+  if (texture() == BTexture::Parent_Relative)
+    return ParentRelative;
+
+  if (screen() == ~(0u))
+    scrn = DefaultScreen(display()->getXDisplay());
+
+  assert(ctrl != 0);
+  Pixmap ret = ctrl->renderImage(width, height, *this);
+
+  if (old)
+    ctrl->removeImage(old);
+
+  return ret;
+}
diff --git a/src/Texture.hh b/src/Texture.hh
new file mode 100644 (file)
index 0000000..1eed2c4
--- /dev/null
@@ -0,0 +1,108 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Texture.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
+// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef TEXTURE_HH
+#define TEXTURE_HH
+
+#include "Color.hh"
+#include "Util.hh"
+class BImageControl;
+
+#include <string>
+
+class BTexture {
+public:
+  enum Type {
+    // bevel options
+    Flat                = (1l<<0),
+    Sunken              = (1l<<1),
+    Raised              = (1l<<2),
+    // textures
+    Solid               = (1l<<3),
+    Gradient            = (1l<<4),
+    // gradients
+    Horizontal          = (1l<<5),
+    Vertical            = (1l<<6),
+    Diagonal            = (1l<<7),
+    CrossDiagonal       = (1l<<8),
+    Rectangle           = (1l<<9),
+    Pyramid             = (1l<<10),
+    PipeCross           = (1l<<11),
+    Elliptic            = (1l<<12),
+    // bevel types
+    Bevel1              = (1l<<13),
+    Bevel2              = (1l<<14),
+    // inverted image
+    Invert              = (1l<<15),
+    // parent relative image
+    Parent_Relative     = (1l<<16),
+    // fake interlaced image
+    Interlaced          = (1l<<17)
+  };
+
+  BTexture(const BaseDisplay * const _display = 0,
+           unsigned int _screen = ~(0u), BImageControl* _ctrl = 0);
+  BTexture(const std::string &_description,
+           const BaseDisplay * const _display = 0,
+           unsigned int _screen = ~(0u), BImageControl* _ctrl = 0);
+
+  void setColor(const BColor &_color);
+  void setColorTo(const BColor &_colorTo) { ct = _colorTo; }
+
+  const BColor &color(void) const { return c; }
+  const BColor &colorTo(void) const { return ct; }
+  const BColor &lightColor(void) const { return lc; }
+  const BColor &shadowColor(void) const { return sc; }
+
+  unsigned long texture(void) const { return t; }
+  void setTexture(const unsigned long _texture) { t  = _texture; }
+  void addTexture(const unsigned long _texture) { t |= _texture; }
+
+  BTexture &operator=(const BTexture &tt);
+  inline bool operator==(const BTexture &tt)
+  { return (c == tt.c && ct == tt.ct && lc == tt.lc &&
+            sc == tt.sc && t == tt.t); }
+  inline bool operator!=(const BTexture &tt)
+  { return (! operator==(tt)); }
+
+  const BaseDisplay *display(void) const { return dpy; }
+  unsigned int screen(void) const { return scrn; }
+  void setDisplay(const BaseDisplay * const _display,
+                  const unsigned int _screen);
+  void setImageControl(BImageControl* _ctrl) { ctrl = _ctrl; }
+  const std::string &description(void) const { return descr; }
+  void setDescription(const std::string &d);
+
+  Pixmap render(const unsigned int width, const unsigned int height,
+                const Pixmap old = 0);
+
+private:
+  BColor c, ct, lc, sc;
+  std::string descr;
+  unsigned long t;
+  const BaseDisplay *dpy;
+  BImageControl *ctrl;
+  unsigned int scrn;
+};
+
+#endif // TEXTURE_HH
index 8cd4714eb00b14bfaeec07ebd06e1d0fe2a673b1..443a7c469ada4f293cdf63d56b0a7d54afbd9904 100644 (file)
@@ -1,5 +1,6 @@
-// Timer.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Timer.cc for Blackbox - An X11 Window Manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#  define _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "BaseDisplay.h"
-#include "Timer.h"
+#include "BaseDisplay.hh"
+#include "Timer.hh"
+#include "Util.hh"
+
+BTimer::BTimer(TimerQueueManager *m, TimeoutHandler *h) {
+  manager = m;
+  handler = h;
 
-BTimer::BTimer(BaseDisplay &d, TimeoutHandler &h) : display(d), handler(h) {
-  once = timing = False;
+  recur = timing = False;
 }
 
+
 BTimer::~BTimer(void) {
   if (timing) stop();
 }
 
+
 void BTimer::setTimeout(long t) {
   _timeout.tv_sec = t / 1000;
-  _timeout.tv_usec = t;
-  _timeout.tv_usec -= (_timeout.tv_sec * 1000);
+  _timeout.tv_usec = t % 1000;
   _timeout.tv_usec *= 1000;
-  if (timing) {
-    display.removeTimer(this);
-    display.addTimer(this);     // reorder the display
-  }
 }
 
-void BTimer::setTimeout(timeval t) {
+
+void BTimer::setTimeout(const timeval &t) {
   _timeout.tv_sec = t.tv_sec;
   _timeout.tv_usec = t.tv_usec;
 }
 
+
 void BTimer::start(void) {
   gettimeofday(&_start, 0);
 
   if (! timing) {
     timing = True;
-    display.addTimer(this);
+    manager->addTimer(this);
   }
 }
 
+
 void BTimer::stop(void) {
-  if (timing) {
-    timing = False;
+  timing = False;
 
-    display.removeTimer(this);
-  }
+  manager->removeTimer(this);
 }
 
+
+void BTimer::halt(void) {
+  timing = False;
+}
+
+
 void BTimer::fireTimeout(void) {
-  handler.timeout();
+  if (handler)
+    handler->timeout();
+}
+
+
+timeval BTimer::timeRemaining(const timeval &tm) const {
+  timeval ret = endpoint();
+
+  ret.tv_sec  -= tm.tv_sec;
+  ret.tv_usec -= tm.tv_usec;
+
+  return normalizeTimeval(ret);
+}
+
+
+timeval BTimer::endpoint(void) const {
+  timeval ret;
+
+  ret.tv_sec = _start.tv_sec + _timeout.tv_sec;
+  ret.tv_usec = _start.tv_usec + _timeout.tv_usec;
+
+  return normalizeTimeval(ret);
+}
+
+
+bool BTimer::shouldFire(const timeval &tm) const {
+  timeval end = endpoint();
+
+  return !((tm.tv_sec < end.tv_sec) ||
+           (tm.tv_sec == end.tv_sec && tm.tv_usec < end.tv_usec));
 }
diff --git a/src/Timer.h b/src/Timer.h
deleted file mode 100644 (file)
index c132b4f..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// Timer.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the 
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in 
-// all copies or substantial portions of the Software. 
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
-// DEALINGS IN THE SOFTWARE.
-  
-#ifndef   __Timer_hh
-#define   __Timer_hh
-
-#ifdef    TIME_WITH_SYS_TIME
-#  include <sys/time.h>
-#  include <time.h> 
-#else // !TIME_WITH_SYS_TIME 
-#  ifdef    HAVE_SYS_TIME_H
-#    include <sys/time.h>
-#  else // !HAVE_SYS_TIME_H
-#    include <time.h>
-#  endif // HAVE_SYS_TIME_H
-#endif // TIME_WITH_SYS_TIME
-
-// forward declaration
-class BTimer;
-class TimeoutHandler;
-class BaseDisplay;
-
-class TimeoutHandler {
-public:
-  virtual void timeout(void) = 0;
-};
-
-class BTimer {
-  friend class BaseDisplay;
-private:
-  BaseDisplay &display;
-  TimeoutHandler &handler;
-  int timing, once;
-
-  timeval _start, _timeout;
-
-protected:
-  void fireTimeout(void);
-
-public:
-  BTimer(BaseDisplay &, TimeoutHandler &);
-  virtual ~BTimer(void);
-
-  inline const int &isTiming(void) const { return timing; } 
-  inline const int &doOnce(void) const { return once; }
-
-  inline const timeval &getTimeout(void) const { return _timeout; }
-  inline const timeval &getStartTime(void) const { return _start; }
-
-  inline void fireOnce(int o) { once = o; }
-
-  void setTimeout(long);
-  void setTimeout(timeval);
-  void start(void);
-  void stop(void);
-};
-
-#endif // __Timer_hh
-
diff --git a/src/Timer.hh b/src/Timer.hh
new file mode 100644 (file)
index 0000000..a4b0401
--- /dev/null
@@ -0,0 +1,131 @@
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Timer.hh for Blackbox - An X11 Window Manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef   _BLACKBOX_Timer_hh
+#define   _BLACKBOX_Timer_hh
+
+extern "C" {
+#ifdef    TIME_WITH_SYS_TIME
+#  include <sys/time.h>
+#  include <time.h>
+#else // !TIME_WITH_SYS_TIME
+#  ifdef    HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#  else // !HAVE_SYS_TIME_H
+#    include <time.h>
+#  endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+}
+
+// forward declaration
+class TimerQueueManager;
+
+class TimeoutHandler {
+public:
+  virtual void timeout(void) = 0;
+};
+
+class BTimer {
+private:
+  TimerQueueManager *manager;
+  TimeoutHandler *handler;
+  bool timing, recur;
+
+  timeval _start, _timeout;
+
+  BTimer(const BTimer&);
+  BTimer& operator=(const BTimer&);
+
+public:
+  BTimer(TimerQueueManager *m, TimeoutHandler *h);
+  virtual ~BTimer(void);
+
+  void fireTimeout(void);
+
+  inline bool isTiming(void) const { return timing; }
+  inline bool isRecurring(void) const { return recur; }
+
+  inline const timeval &getTimeout(void) const { return _timeout; }
+  inline const timeval &getStartTime(void) const { return _start; }
+
+  timeval timeRemaining(const timeval &tm) const;
+  bool shouldFire(const timeval &tm) const;
+  timeval endpoint(void) const;
+
+  inline void recurring(bool b) { recur = b; }
+
+  void setTimeout(long t);
+  void setTimeout(const timeval &t);
+
+  void start(void);  // manager acquires timer
+  void stop(void);   // manager releases timer
+  void halt(void);   // halts the timer
+
+  bool operator<(const BTimer& other) const
+  { return shouldFire(other.endpoint()); }
+};
+
+
+#include <queue>
+#include <algorithm>
+
+template <class _Tp, class _Sequence, class _Compare>
+class _timer_queue: protected std::priority_queue<_Tp, _Sequence, _Compare> {
+public:
+  typedef std::priority_queue<_Tp, _Sequence, _Compare> _Base;
+
+  _timer_queue(void): _Base() {}
+  ~_timer_queue(void) {}
+
+  void release(const _Tp& value) {
+    c.erase(std::remove(c.begin(), c.end(), value), c.end());
+    // after removing the item we need to make the heap again
+    std::make_heap(c.begin(), c.end(), comp);
+  }
+  bool empty(void) const { return _Base::empty(); }
+  size_t size(void) const { return _Base::size(); }
+  void push(const _Tp& value) { _Base::push(value); }
+  void pop(void) { _Base::pop(); }
+  const _Tp& top(void) const { return _Base::top(); }
+private:
+  // no copying!
+  _timer_queue(const _timer_queue&) {}
+  _timer_queue& operator=(const _timer_queue&) {}
+};
+
+struct TimerLessThan {
+  bool operator()(const BTimer* const l, const BTimer* const r) const {
+    return *r < *l;
+  }
+};
+
+#include <deque>
+typedef _timer_queue<BTimer*, std::deque<BTimer*>, TimerLessThan> TimerQueue;
+
+class TimerQueueManager {
+public:
+  virtual void addTimer(BTimer* timer) = 0;
+  virtual void removeTimer(BTimer* timer) = 0;
+};
+
+#endif // _BLACKBOX_Timer_hh
index b0f9d2305c9ee15e0a40df3838252b33d92e1f2b..a51f949cffab1e91ce83e2caca7af334aac1a98a 100644 (file)
@@ -1,5 +1,6 @@
-// Toolbar.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Toolbar.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "i18n.h"
-#include "openbox.h"
-#include "Clientmenu.h"
-#include "Iconmenu.h"
-#include "Rootmenu.h"
-#include "Screen.h"
-#include "Toolbar.h"
-#include "Window.h"
-#include "Workspace.h"
-#include "Workspacemenu.h"
-
+extern "C" {
 #include <X11/keysym.h>
 
-#ifdef    HAVE_STRING_H
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
 
 #  include <time.h>
 # endif // HAVE_SYS_TIME_H
 #endif // TIME_WITH_SYS_TIME
+}
 
-#include <strstream>
 #include <string>
-using std::ends;
+using std::string;
+
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "Clientmenu.hh"
+#include "GCCache.hh"
+#include "Iconmenu.hh"
+#include "Image.hh"
+#include "Rootmenu.hh"
+#include "Screen.hh"
+#include "Toolbar.hh"
+#include "Window.hh"
+#include "Workspace.hh"
+#include "Workspacemenu.hh"
+#include "Slit.hh"
+
+
+static long aMinuteFromNow(void) {
+  timeval now;
+  gettimeofday(&now, 0);
+  return ((60 - (now.tv_sec % 60)) * 1000);
+}
+
 
-Toolbar::Toolbar(BScreen &scrn, Resource &conf) : openbox(scrn.getOpenbox()),
-screen(scrn), config(conf)
-{
-  load();
+Toolbar::Toolbar(BScreen *scrn) {
+  screen = scrn;
+  blackbox = screen->getBlackbox();
 
   // get the clock updating every minute
-  clock_timer = new BTimer(openbox, *this);
-  timeval now;
-  gettimeofday(&now, 0);
-  clock_timer->setTimeout((60 - (now.tv_sec % 60)) * 1000);
+  clock_timer = new BTimer(blackbox, this);
+  clock_timer->setTimeout(aMinuteFromNow());
+  clock_timer->recurring(True);
   clock_timer->start();
+  frame.minute = frame.hour = -1;
 
   hide_handler.toolbar = this;
-  hide_timer = new BTimer(openbox, hide_handler);
-  // the time out is set in ::reconfigure()
-  hide_timer->fireOnce(True);
+  hide_timer = new BTimer(blackbox, &hide_handler);
+  hide_timer->setTimeout(blackbox->getAutoRaiseDelay());
 
-  image_ctrl = screen.getImageControl();
+  on_top = screen->isToolbarOnTop();
+  hidden = do_auto_hide = screen->doToolbarAutoHide();
 
-  m_editing = False;
-  new_workspace_name = (char *) 0;
+  editing = False;
   new_name_pos = 0;
   frame.grab_x = frame.grab_y = 0;
 
-  toolbarmenu = new Toolbarmenu(*this);
+  toolbarmenu = new Toolbarmenu(this);
 
-  display = openbox.getXDisplay();
+  display = blackbox->getXDisplay();
   XSetWindowAttributes attrib;
   unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
-    CWColormap | CWOverrideRedirect | CWEventMask;
+                              CWColormap | CWOverrideRedirect | CWEventMask;
   attrib.background_pixmap = None;
   attrib.background_pixel = attrib.border_pixel =
-    screen.getBorderColor()->getPixel();
-  attrib.colormap = screen.getColormap();
+    screen->getBorderColor()->pixel();
+  attrib.colormap = screen->getColormap();
   attrib.override_redirect = True;
   attrib.event_mask = ButtonPressMask | ButtonReleaseMask |
-    EnterWindowMask | LeaveWindowMask;
+                      EnterWindowMask | LeaveWindowMask;
 
   frame.window =
-    XCreateWindow(display, screen.getRootWindow(), 0, 0, 1, 1, 0,
-                  screen.getDepth(), InputOutput, screen.getVisual(),
+    XCreateWindow(display, screen->getRootWindow(), 0, 0, 1, 1, 0,
+                  screen->getDepth(), InputOutput, screen->getVisual(),
                   create_mask, &attrib);
-  openbox.saveToolbarSearch(frame.window, this);
+  blackbox->saveToolbarSearch(frame.window, this);
 
   attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask |
-    KeyPressMask | EnterWindowMask;
+                      KeyPressMask | EnterWindowMask;
 
   frame.workspace_label =
-    XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
-                  InputOutput, screen.getVisual(), create_mask, &attrib);
-  openbox.saveToolbarSearch(frame.workspace_label, this);
+    XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
+                  InputOutput, screen->getVisual(), create_mask, &attrib);
+  blackbox->saveToolbarSearch(frame.workspace_label, this);
 
   frame.window_label =
-    XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
-                  InputOutput, screen.getVisual(), create_mask, &attrib);
-  openbox.saveToolbarSearch(frame.window_label, this);
+    XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
+                  InputOutput, screen->getVisual(), create_mask, &attrib);
+  blackbox->saveToolbarSearch(frame.window_label, this);
 
   frame.clock =
-    XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
-                  InputOutput, screen.getVisual(), create_mask, &attrib);
-  openbox.saveToolbarSearch(frame.clock, this);
+    XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
+                  InputOutput, screen->getVisual(), create_mask, &attrib);
+  blackbox->saveToolbarSearch(frame.clock, this);
 
   frame.psbutton =
-    XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
-                  InputOutput, screen.getVisual(), create_mask, &attrib);
-  openbox.saveToolbarSearch(frame.psbutton, this);
+    XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
+                  InputOutput, screen->getVisual(), create_mask, &attrib);
+  blackbox->saveToolbarSearch(frame.psbutton, this);
 
   frame.nsbutton =
-    XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
-                  InputOutput, screen.getVisual(), create_mask, &attrib);
-  openbox.saveToolbarSearch(frame.nsbutton, this);
+    XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
+                  InputOutput, screen->getVisual(), create_mask, &attrib);
+  blackbox->saveToolbarSearch(frame.nsbutton, this);
 
   frame.pwbutton =
-    XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
-                  InputOutput, screen.getVisual(), create_mask, &attrib);
-  openbox.saveToolbarSearch(frame.pwbutton, this);
+    XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
+                  InputOutput, screen->getVisual(), create_mask, &attrib);
+  blackbox->saveToolbarSearch(frame.pwbutton, this);
 
   frame.nwbutton =
-    XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(),
-                  InputOutput, screen.getVisual(), create_mask, &attrib);
-  openbox.saveToolbarSearch(frame.nwbutton, this);
+    XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(),
+                  InputOutput, screen->getVisual(), create_mask, &attrib);
+  blackbox->saveToolbarSearch(frame.nwbutton, this);
 
   frame.base = frame.label = frame.wlabel = frame.clk = frame.button =
     frame.pbutton = None;
 
-  reconfigure();
-  mapToolbar();
-}
+  screen->addStrut(&strut);
 
-Rect Toolbar::area() const {
-  int x = ((m_hidden) ? frame.x_hidden : frame.x);
-  int y;
-  if (screen.hideToolbar()) y = screen.size().h();
-  else if (m_hidden) y = frame.y_hidden;
-  else y = frame.y;
-  return Rect(x, y, frame.width, frame.height);
-}
+  reconfigure();
 
-unsigned int Toolbar::getExposedHeight() const {
-  if (screen.hideToolbar()) return 0;
-  else if (m_autohide) return frame.bevel_w;
-  else return frame.height;
+  XMapSubwindows(display, frame.window);
+  XMapWindow(display, frame.window);
 }
 
-void Toolbar::mapToolbar(){
-  if (!screen.hideToolbar()) {
-    //not hidden, so windows should not maximize over the toolbar
-    XMapSubwindows(display, frame.window);
-    XMapWindow(display, frame.window);
-  }
-}
 
-void Toolbar::unMapToolbar(){
-  //hidden so we can maximize over the toolbar
+Toolbar::~Toolbar(void) {
   XUnmapWindow(display, frame.window);
-}
 
-Toolbar::~Toolbar() {
-  unMapToolbar();
-  if (frame.base) image_ctrl->removeImage(frame.base);
-  if (frame.label) image_ctrl->removeImage(frame.label);
-  if (frame.wlabel) image_ctrl->removeImage(frame.wlabel);
-  if (frame.clk) image_ctrl->removeImage(frame.clk);
-  if (frame.button) image_ctrl->removeImage(frame.button);
-  if (frame.pbutton) image_ctrl->removeImage(frame.pbutton);
-
-  openbox.removeToolbarSearch(frame.window);
-  openbox.removeToolbarSearch(frame.workspace_label);
-  openbox.removeToolbarSearch(frame.window_label);
-  openbox.removeToolbarSearch(frame.clock);
-  openbox.removeToolbarSearch(frame.psbutton);
-  openbox.removeToolbarSearch(frame.nsbutton);
-  openbox.removeToolbarSearch(frame.pwbutton);
-  openbox.removeToolbarSearch(frame.nwbutton);
+  if (frame.base) screen->getImageControl()->removeImage(frame.base);
+  if (frame.label) screen->getImageControl()->removeImage(frame.label);
+  if (frame.wlabel) screen->getImageControl()->removeImage(frame.wlabel);
+  if (frame.clk) screen->getImageControl()->removeImage(frame.clk);
+  if (frame.button) screen->getImageControl()->removeImage(frame.button);
+  if (frame.pbutton) screen->getImageControl()->removeImage(frame.pbutton);
+
+  blackbox->removeToolbarSearch(frame.window);
+  blackbox->removeToolbarSearch(frame.workspace_label);
+  blackbox->removeToolbarSearch(frame.window_label);
+  blackbox->removeToolbarSearch(frame.clock);
+  blackbox->removeToolbarSearch(frame.psbutton);
+  blackbox->removeToolbarSearch(frame.nsbutton);
+  blackbox->removeToolbarSearch(frame.pwbutton);
+  blackbox->removeToolbarSearch(frame.nwbutton);
 
   XDestroyWindow(display, frame.workspace_label);
   XDestroyWindow(display, frame.window_label);
@@ -213,1182 +196,939 @@ Toolbar::~Toolbar() {
 }
 
 
-void Toolbar::setOnTop(bool b) {
-  m_ontop = b;
-  std::ostrstream s;
-  s << "session.screen" << screen.getScreenNumber() << ".toolbar.onTop" << ends;
-  config.setValue(s.str(), m_ontop ? "True" : "False");
-  s.rdbuf()->freeze(0);
-}
-
-void Toolbar::setAutoHide(bool b) {
-  m_autohide = b;
-  std::ostrstream s;
-  s << "session.screen" << screen.getScreenNumber() << ".toolbar.autoHide"
-    << ends;
-  config.setValue(s.str(), m_autohide ? "True" : "False");
-  s.rdbuf()->freeze(0);
-}
+void Toolbar::reconfigure(void) {
+  unsigned int height = 0,
+    width = (screen->getWidth() * screen->getToolbarWidthPercent()) / 100;
 
-void Toolbar::setWidthPercent(int w) {
-  m_width_percent = w;
-  std::ostrstream s;
-  s << "session.screen" << screen.getScreenNumber() << ".toolbar.widthPercent"
-    << ends;
-  config.setValue(s.str(), m_width_percent);
-  s.rdbuf()->freeze(0);
-}
-
-void Toolbar::setPlacement(int p) {
-  m_placement = p;
-  std::ostrstream s;
-  s << "session.screen" << screen.getScreenNumber() << ".toolbar.placement"
-    << ends;
-  const char *placement;
-  switch (m_placement) {
-  case TopLeft: placement = "TopLeft"; break;
-  case BottomLeft: placement = "BottomLeft"; break;
-  case TopCenter: placement = "TopCenter"; break;
-  case TopRight: placement = "TopRight"; break;
-  case BottomRight: placement = "BottomRight"; break;
-  case BottomCenter: default: placement = "BottomCenter"; break;
-  }
-  config.setValue(s.str(), placement);
-  s.rdbuf()->freeze(0);
-}
-
-void Toolbar::save() {
-  setOnTop(m_ontop);
-  setAutoHide(m_autohide);
-  setWidthPercent(m_width_percent);
-  setPlacement(m_placement);
-}
-
-void Toolbar::load() {
-  std::ostrstream rscreen, rname, rclass;
-  std::string s;
-  bool b;
-  long l;
-  rscreen << "session.screen" << screen.getScreenNumber() << '.' << ends;
-
-  rname << rscreen.str() << "toolbar.widthPercent" << ends;
-  rclass << rscreen.str() << "Toolbar.WidthPercent" << ends;
-  if (config.getValue(rname.str(), rclass.str(), l) && (l > 0 && l <= 100))
-    m_width_percent = l;
-  else
-    m_width_percent =66;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "toolbar.placement" << ends;
-  rclass << rscreen.str() << "Toolbar.Placement" << ends;
-  if (config.getValue(rname.str(), rclass.str(), s)) {
-    if (0 == strncasecmp(s.c_str(), "TopLeft", s.length()))
-      m_placement = TopLeft;
-    else if (0 == strncasecmp(s.c_str(), "BottomLeft", s.length()))
-      m_placement = BottomLeft;
-    else if (0 == strncasecmp(s.c_str(), "TopCenter", s.length()))
-      m_placement = TopCenter;
-    else if (0 == strncasecmp(s.c_str(), "TopRight", s.length()))
-      m_placement = TopRight;
-    else if ( 0 == strncasecmp(s.c_str(), "BottomRight", s.length()))
-      m_placement = BottomRight;
-    else if ( 0 == strncasecmp(s.c_str(), "BottomCenter", s.length()))
-      m_placement = BottomCenter;
-  } else
-    m_placement = BottomCenter;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "toolbar.onTop" << ends;
-  rclass << rscreen.str() << "Toolbar.OnTop" << ends;
-  if (config.getValue(rname.str(), rclass.str(), b))
-    m_ontop = b;
-  else
-    m_ontop = false;
-
-  rname.seekp(0); rclass.seekp(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-  rname << rscreen.str() << "toolbar.autoHide" << ends;
-  rclass << rscreen.str() << "Toolbar.AutoHide" << ends;
-  if (config.getValue(rname.str(), rclass.str(), b))
-    m_hidden = m_autohide = b;
+  if (i18n.multibyte())
+    height = screen->getToolbarStyle()->fontset_extents->max_ink_extent.height;
   else
-    m_hidden = m_autohide = false;
-
-  rscreen.rdbuf()->freeze(0);
-  rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0);
-}
+    height = screen->getToolbarStyle()->font->ascent +
+      screen->getToolbarStyle()->font->descent;
 
-void Toolbar::reconfigure() {
-  hide_timer->setTimeout(openbox.getAutoRaiseDelay());
+  frame.bevel_w = screen->getBevelWidth();
+  frame.button_w = height;
+  height += 2;
+  frame.label_h = height;
+  height += (frame.bevel_w * 2);
 
-  frame.bevel_w = screen.getBevelWidth();
-  frame.width = screen.size().w() * m_width_percent / 100;
+  frame.rect.setSize(width, height);
 
-  if (i18n.multibyte())
-    frame.height =
-      screen.getToolbarStyle()->fontset_extents->max_ink_extent.height;
-  else
-    frame.height = screen.getToolbarStyle()->font->ascent +
-      screen.getToolbarStyle()->font->descent;
-  frame.button_w = frame.height;
-  frame.height += 2;
-  frame.label_h = frame.height;
-  frame.height += (frame.bevel_w * 2);
-
-  switch (m_placement) {
+  int x, y;
+  switch (screen->getToolbarPlacement()) {
   case TopLeft:
-    frame.x = 0;
-    frame.y = 0;
-    frame.x_hidden = 0;
-    frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth()
-      - frame.height;
-    break;
+  case TopRight:
+  case TopCenter:
+    if (screen->getToolbarPlacement() == TopLeft)
+      x = 0;
+    else if (screen->getToolbarPlacement() == TopRight)
+      x = screen->getWidth() - frame.rect.width()
+        - (screen->getBorderWidth() * 2);
+    else
+      x = (screen->getWidth() - frame.rect.width()) / 2;
 
-  case BottomLeft:
-    frame.x = 0;
-    frame.y = screen.size().h() - frame.height
-      - (screen.getBorderWidth() * 2);
-    frame.x_hidden = 0;
-    frame.y_hidden = screen.size().h() - screen.getBevelWidth()
-      - screen.getBorderWidth();
-    break;
+    y = 0;
 
-  case TopCenter:
-    frame.x = (screen.size().w() - frame.width) / 2;
-    frame.y = 0;
-    frame.x_hidden = frame.x;
-    frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth()
-      - frame.height;
+    frame.x_hidden = x;
+    frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth()
+                     - frame.rect.height();
     break;
 
+  case BottomLeft:
+  case BottomRight:
   case BottomCenter:
   default:
-    frame.x = (screen.size().w() - frame.width) / 2;
-    frame.y = screen.size().h() - frame.height
-      - (screen.getBorderWidth() * 2);
-    frame.x_hidden = frame.x;
-    frame.y_hidden = screen.size().h() - screen.getBevelWidth()
-      - screen.getBorderWidth();
-    break;
+    if (screen->getToolbarPlacement() == BottomLeft)
+      x = 0;
+    else if (screen->getToolbarPlacement() == BottomRight)
+      x = screen->getWidth() - frame.rect.width()
+        - (screen->getBorderWidth() * 2);
+    else
+      x = (screen->getWidth() - frame.rect.width()) / 2;
 
-  case TopRight:
-    frame.x = screen.size().w() - frame.width
-      - (screen.getBorderWidth() * 2);
-    frame.y = 0;
-    frame.x_hidden = frame.x;
-    frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth()
-      - frame.height;
-    break;
+    y = screen->getHeight() - frame.rect.height()
+      - (screen->getBorderWidth() * 2);
 
-  case BottomRight:
-    frame.x = screen.size().w() - frame.width
-      - (screen.getBorderWidth() * 2);
-    frame.y = screen.size().h() - frame.height
-      - (screen.getBorderWidth() * 2);
-    frame.x_hidden = frame.x;
-    frame.y_hidden = screen.size().h() - screen.getBevelWidth()
-      - screen.getBorderWidth();
+    frame.x_hidden = x;
+    frame.y_hidden = screen->getHeight() - screen->getBevelWidth()
+                     - screen->getBorderWidth();
     break;
   }
 
+  frame.rect.setPos(x, y);
+
+  updateStrut();
+
 #ifdef    HAVE_STRFTIME
   time_t ttmp = time(NULL);
-  struct tm *tt = 0;
 
+  frame.clock_w = 0;
   if (ttmp != -1) {
-    tt = localtime(&ttmp);
+    struct tm *tt = localtime(&ttmp);
     if (tt) {
-      char t[1025], *time_string = (char *) 0;
-      int len = strftime(t, 1024, screen.strftimeFormat(), tt);
-      t[len++] = 'A';   // add size to the string for padding
-      t[len++] = 'A';   // add size to the string for padding
-      t[len] = '\0';
-
+      char t[1024];
+      int len = strftime(t, 1024, screen->getStrftimeFormat(), tt);
+      if (len == 0) { // invalid time format found
+        screen->saveStrftimeFormat("%I:%M %p"); // so use the default
+        len = strftime(t, 1024, screen->getStrftimeFormat(), tt);
+      }
+      // find the length of the rendered string and add room for two extra
+      // characters to it.  This allows for variable width output of the fonts
       if (i18n.multibyte()) {
         XRectangle ink, logical;
-        XmbTextExtents(screen.getToolbarStyle()->fontset, t, len, &ink,
-                       &logical);
-        frame.clock_w = logical.width;
-
-        // ben's additional solution to pad some space beside the numbers
-        //frame.clock_w +=
-        //  screen.getToolbarStyle()->fontset_extents->max_logical_extent.width *
-        //  4;
-
-        // brad's solution, which is currently buggy, too big
-        //frame.clock_w =
-        //  screen.getToolbarStyle()->fontset_extents->max_logical_extent.width
-        //  * len;
+        XmbTextExtents(screen->getToolbarStyle()->fontset, t, len,
+                       &ink, &logical);
+        XFontSetExtents* extents = screen->getToolbarStyle()->fontset_extents;
+        frame.clock_w = logical.width +
+          (extents->max_logical_extent.width * 2);
       } else {
-        frame.clock_w = XTextWidth(screen.getToolbarStyle()->font, t, len);
-        // ben's additional solution to pad some space beside the numbers
-        //frame.clock_w += screen.getToolbarStyle()->font->max_bounds.width * 4;
-        // brad's solution again, too big
-        //frame.clock_w = screen.getToolbarStyle()->font->max_bounds.width * len;
+        XFontStruct* font = screen->getToolbarStyle()->font;
+        frame.clock_w = XTextWidth(font, t, len) +
+          ((font->max_bounds.rbearing - font->min_bounds.lbearing) * 2);
       }
-      frame.clock_w += (frame.bevel_w * 4);
-
-      delete [] time_string;
-    } else {
-      frame.clock_w = 0;
     }
-  } else {
-    frame.clock_w = 0;
   }
 #else // !HAVE_STRFTIME
   frame.clock_w =
-    XTextWidth(screen.getToolbarStyle()->font,
-               i18n(ToolbarSet, ToolbarNoStrftimeLength,
-                    "00:00000"),
+    XTextWidth(screen->getToolbarStyle()->font,
+               i18n(ToolbarSet, ToolbarNoStrftimeLength, "00:00000"),
                strlen(i18n(ToolbarSet, ToolbarNoStrftimeLength,
-                           "00:00000"))) + (frame.bevel_w * 4);
+                           "00:00000")));
 #endif // HAVE_STRFTIME
 
-                           int i;
-                           unsigned int w = 0;
-                           frame.workspace_label_w = 0;
-
-                           for (i = 0; i < screen.getWorkspaceCount(); i++) {
-                             if (i18n.multibyte()) {
-                               XRectangle ink, logical;
-                               XmbTextExtents(screen.getToolbarStyle()->fontset,
-                                              screen.getWorkspace(i)->getName(),
-                                              strlen(screen.getWorkspace(i)->getName()),
-                                              &ink, &logical);
-                               w = logical.width;
-                             } else {
-                               w = XTextWidth(screen.getToolbarStyle()->font,
-                                              screen.getWorkspace(i)->getName(),
-                                              strlen(screen.getWorkspace(i)->getName()));
-                             }
-                             w += (frame.bevel_w * 4);
-
-                             if (w > frame.workspace_label_w) frame.workspace_label_w = w;
-                           }
-
-                           if (frame.workspace_label_w < frame.clock_w)
-                             frame.workspace_label_w = frame.clock_w;
-                           else if (frame.workspace_label_w > frame.clock_w)
-                             frame.clock_w = frame.workspace_label_w;
-
-                           frame.window_label_w =
-                             (frame.width - (frame.clock_w + (frame.button_w * 4) +
-                                             frame.workspace_label_w + (frame.bevel_w * 8) + 6));
-
-                           if (m_hidden) {
-                             XMoveResizeWindow(display, frame.window, frame.x_hidden, frame.y_hidden,
-                                               frame.width, frame.height);
-                           } else {
-                             XMoveResizeWindow(display, frame.window, frame.x, frame.y,
-                                               frame.width, frame.height);
-                           }
-
-                           XMoveResizeWindow(display, frame.workspace_label, frame.bevel_w,
-                                             frame.bevel_w, frame.workspace_label_w,
-                                             frame.label_h);
-                           XMoveResizeWindow(display, frame.psbutton, (frame.bevel_w * 2) +
-                                             frame.workspace_label_w + 1, frame.bevel_w + 1,
-                                             frame.button_w, frame.button_w);
-                           XMoveResizeWindow(display ,frame.nsbutton, (frame.bevel_w * 3) +
-                                             frame.workspace_label_w + frame.button_w + 2,
-                                             frame.bevel_w + 1, frame.button_w, frame.button_w);
-                           XMoveResizeWindow(display, frame.window_label, (frame.bevel_w * 4) +
-                                             (frame.button_w * 2) + frame.workspace_label_w + 3,
-                                             frame.bevel_w, frame.window_label_w, frame.label_h);
-                           XMoveResizeWindow(display, frame.pwbutton, (frame.bevel_w * 5) +
-                                             (frame.button_w * 2) + frame.workspace_label_w +
-                                             frame.window_label_w + 4, frame.bevel_w + 1,
-                                             frame.button_w, frame.button_w);
-                           XMoveResizeWindow(display, frame.nwbutton, (frame.bevel_w * 6) +
-                                             (frame.button_w * 3) + frame.workspace_label_w +
-                                             frame.window_label_w + 5, frame.bevel_w + 1,
-                                             frame.button_w, frame.button_w);
-                           XMoveResizeWindow(display, frame.clock, frame.width - frame.clock_w -
-                                             frame.bevel_w, frame.bevel_w, frame.clock_w,
-                                             frame.label_h);
-
-                           Pixmap tmp = frame.base;
-                           BTexture *texture = &(screen.getToolbarStyle()->toolbar);
-                           if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-                             frame.base = None;
-                             XSetWindowBackground(display, frame.window,
-                                                  texture->getColor()->getPixel());
-                           } else {
-                             frame.base =
-                               image_ctrl->renderImage(frame.width, frame.height, texture);
-                             XSetWindowBackgroundPixmap(display, frame.window, frame.base);
-                           }
-                           if (tmp) image_ctrl->removeImage(tmp);
-
-                           tmp = frame.label;
-                           texture = &(screen.getToolbarStyle()->window);
-                           if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-                             frame.label = None;
-                             XSetWindowBackground(display, frame.window_label,
-                                                  texture->getColor()->getPixel());
-                           } else {
-                             frame.label =
-                               image_ctrl->renderImage(frame.window_label_w, frame.label_h, texture);
-                             XSetWindowBackgroundPixmap(display, frame.window_label, frame.label);
-                           }
-                           if (tmp) image_ctrl->removeImage(tmp);
-
-                           tmp = frame.wlabel;
-                           texture = &(screen.getToolbarStyle()->label);
-                           if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-                             frame.wlabel = None;
-                             XSetWindowBackground(display, frame.workspace_label,
-                                                  texture->getColor()->getPixel());
-                           } else {
-                             frame.wlabel =
-                               image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture);
-                             XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
-                           }
-                           if (tmp) image_ctrl->removeImage(tmp);
-
-                           tmp = frame.clk;
-                           texture = &(screen.getToolbarStyle()->clock);
-                           if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-                             frame.clk = None;
-                             XSetWindowBackground(display, frame.clock,
-                                                  texture->getColor()->getPixel());
-                           } else {
-                             frame.clk =
-                               image_ctrl->renderImage(frame.clock_w, frame.label_h, texture);
-                             XSetWindowBackgroundPixmap(display, frame.clock, frame.clk);
-                           }
-                           if (tmp) image_ctrl->removeImage(tmp);
-
-                           tmp = frame.button;
-                           texture = &(screen.getToolbarStyle()->button);
-                           if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-                             frame.button = None;
-
-                             frame.button_pixel = texture->getColor()->getPixel();
-                             XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
-                             XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
-                             XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
-                             XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
-                           } else {
-                             frame.button =
-                               image_ctrl->renderImage(frame.button_w, frame.button_w, texture);
-
-                             XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
-                             XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
-                             XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
-                             XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
-                           }
-                           if (tmp) image_ctrl->removeImage(tmp);
-
-                           tmp = frame.pbutton;
-                           texture = &(screen.getToolbarStyle()->pressed);
-                           if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-                             frame.pbutton = None;
-                             frame.pbutton_pixel = texture->getColor()->getPixel();
-                           } else {
-                             frame.pbutton =
-                               image_ctrl->renderImage(frame.button_w, frame.button_w, texture);
-                           }
-                           if (tmp) image_ctrl->removeImage(tmp);
-
-                           XSetWindowBorder(display, frame.window,
-                                            screen.getBorderColor()->getPixel());
-                           XSetWindowBorderWidth(display, frame.window, screen.getBorderWidth());
-
-                           XClearWindow(display, frame.window);
-                           XClearWindow(display, frame.workspace_label);
-                           XClearWindow(display, frame.window_label);
-                           XClearWindow(display, frame.clock);
-                           XClearWindow(display, frame.psbutton);
-                           XClearWindow(display, frame.nsbutton);
-                           XClearWindow(display, frame.pwbutton);
-                           XClearWindow(display, frame.nwbutton);
-
-                           redrawWindowLabel();
-                           redrawWorkspaceLabel();
-                           redrawPrevWorkspaceButton();
-                           redrawNextWorkspaceButton();
-                           redrawPrevWindowButton();
-                           redrawNextWindowButton();
-                           checkClock(True);
-
-                           toolbarmenu->reconfigure();
+  frame.workspace_label_w = 0;
+
+  for (unsigned int i = 0; i < screen->getWorkspaceCount(); i++) {
+    const string& workspace_name = screen->getWorkspace(i)->getName();
+    if (i18n.multibyte()) {
+      XRectangle ink, logical;
+      XmbTextExtents(screen->getToolbarStyle()->fontset,
+                     workspace_name.c_str(), workspace_name.length(),
+                     &ink, &logical);
+      width = logical.width;
+    } else {
+      width = XTextWidth(screen->getToolbarStyle()->font,
+                     workspace_name.c_str(), workspace_name.length());
+    }
+
+    if (width > frame.workspace_label_w) frame.workspace_label_w = width;
+  }
+
+  frame.workspace_label_w = frame.clock_w =
+    std::max(frame.workspace_label_w, frame.clock_w) + (frame.bevel_w * 4);
+
+  // XXX: where'd the +6 come from?
+  frame.window_label_w =
+    (frame.rect.width() - (frame.clock_w + (frame.button_w * 4) +
+                           frame.workspace_label_w + (frame.bevel_w * 8) + 6));
+
+  if (hidden) {
+    XMoveResizeWindow(display, frame.window, frame.x_hidden, frame.y_hidden,
+                      frame.rect.width(), frame.rect.height());
+  } else {
+    XMoveResizeWindow(display, frame.window, frame.rect.x(), frame.rect.y(),
+                      frame.rect.width(), frame.rect.height());
+  }
+
+  XMoveResizeWindow(display, frame.workspace_label, frame.bevel_w,
+                    frame.bevel_w, frame.workspace_label_w,
+                    frame.label_h);
+  XMoveResizeWindow(display, frame.psbutton,
+                    ((frame.bevel_w * 2) + frame.workspace_label_w + 1),
+                    frame.bevel_w + 1, frame.button_w, frame.button_w);
+  XMoveResizeWindow(display, frame.nsbutton,
+                    ((frame.bevel_w * 3) + frame.workspace_label_w +
+                     frame.button_w + 2), frame.bevel_w + 1, frame.button_w,
+                    frame.button_w);
+  XMoveResizeWindow(display, frame.window_label,
+                    ((frame.bevel_w * 4) + (frame.button_w * 2) +
+                     frame.workspace_label_w + 3), frame.bevel_w,
+                    frame.window_label_w, frame.label_h);
+  XMoveResizeWindow(display, frame.pwbutton,
+                    ((frame.bevel_w * 5) + (frame.button_w * 2) +
+                     frame.workspace_label_w + frame.window_label_w + 4),
+                    frame.bevel_w + 1, frame.button_w, frame.button_w);
+  XMoveResizeWindow(display, frame.nwbutton,
+                    ((frame.bevel_w * 6) + (frame.button_w * 3) +
+                     frame.workspace_label_w + frame.window_label_w + 5),
+                    frame.bevel_w + 1, frame.button_w, frame.button_w);
+  XMoveResizeWindow(display, frame.clock,
+                    frame.rect.width() - frame.clock_w - (frame.bevel_w * 2),
+                    frame.bevel_w, frame.clock_w, frame.label_h);
+
+  ToolbarStyle *style = screen->getToolbarStyle();
+  frame.base = style->toolbar.render(frame.rect.width(), frame.rect.height(),
+                                     frame.base);
+  if (! frame.base)
+    XSetWindowBackground(display, frame.window,
+                         style->toolbar.color().pixel());
+  else
+    XSetWindowBackgroundPixmap(display, frame.window, frame.base);
+
+  frame.label = style->window.render(frame.window_label_w, frame.label_h,
+                                     frame.label);
+  if (! frame.label)
+    XSetWindowBackground(display, frame.window_label,
+                         style->window.color().pixel());
+  else
+    XSetWindowBackgroundPixmap(display, frame.window_label, frame.label);
+
+  frame.wlabel = style->label.render(frame.workspace_label_w, frame.label_h,
+                                frame.wlabel);
+  if (! frame.wlabel)
+    XSetWindowBackground(display, frame.workspace_label,
+                         style->label.color().pixel());
+  else
+    XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
+
+  frame.clk = style->clock.render(frame.clock_w, frame.label_h, frame.clk);
+  if (! frame.clk)
+    XSetWindowBackground(display, frame.clock, style->clock.color().pixel());
+  else
+    XSetWindowBackgroundPixmap(display, frame.clock, frame.clk);
+
+  frame.button = style->button.render(frame.button_w, frame.button_w,
+                                frame.button);
+  if (! frame.button) {
+    frame.button_pixel = style->button.color().pixel();
+    XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
+    XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
+    XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
+    XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
+  } else {
+    XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
+    XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
+    XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
+    XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
+  }
+
+  frame.pbutton = style->pressed.render(frame.button_w, frame.button_w,
+                                        frame.pbutton);
+  if (! frame.pbutton)
+    frame.pbutton_pixel = style->pressed.color().pixel();
+
+  XSetWindowBorder(display, frame.window,
+                   screen->getBorderColor()->pixel());
+  XSetWindowBorderWidth(display, frame.window, screen->getBorderWidth());
+
+  XClearWindow(display, frame.window);
+  XClearWindow(display, frame.workspace_label);
+  XClearWindow(display, frame.window_label);
+  XClearWindow(display, frame.clock);
+  XClearWindow(display, frame.psbutton);
+  XClearWindow(display, frame.nsbutton);
+  XClearWindow(display, frame.pwbutton);
+  XClearWindow(display, frame.nwbutton);
+
+  redrawWindowLabel();
+  redrawWorkspaceLabel();
+  redrawPrevWorkspaceButton();
+  redrawNextWorkspaceButton();
+  redrawPrevWindowButton();
+  redrawNextWindowButton();
+  checkClock(True);
+
+  toolbarmenu->reconfigure();
+}
+
+
+void Toolbar::updateStrut(void) {
+  // left and right are always 0
+  strut.top = strut.bottom = 0;
+
+  switch(screen->getToolbarPlacement()) {
+  case TopLeft:
+  case TopCenter:
+  case TopRight:
+    strut.top = getExposedHeight() + (screen->getBorderWidth() * 2);
+    break;
+  default:
+    strut.bottom = getExposedHeight() + (screen->getBorderWidth() * 2);
+  }
+
+  screen->updateAvailableArea();
 }
 
 
 #ifdef    HAVE_STRFTIME
-void Toolbar::checkClock(Bool redraw) {
+void Toolbar::checkClock(bool redraw) {
 #else // !HAVE_STRFTIME
-  void Toolbar::checkClock(Bool redraw, Bool date) {
+void Toolbar::checkClock(bool redraw, bool date) {
 #endif // HAVE_STRFTIME
-    time_t tmp = 0;
-    struct tm *tt = 0;
-
-    if ((tmp = time(NULL)) != -1) {
-      if (! (tt = localtime(&tmp))) return;
-      if (tt->tm_min != frame.minute || tt->tm_hour != frame.hour) {
-        frame.hour = tt->tm_hour;
-        frame.minute = tt->tm_min;
-        XClearWindow(display, frame.clock);
-        redraw = True;
-      }
+  time_t tmp = 0;
+  struct tm *tt = 0;
+
+  if ((tmp = time(NULL)) != -1) {
+    if (! (tt = localtime(&tmp))) return;
+    if (tt->tm_min != frame.minute || tt->tm_hour != frame.hour) {
+      frame.hour = tt->tm_hour;
+      frame.minute = tt->tm_min;
+      XClearWindow(display, frame.clock);
+      redraw = True;
     }
+  }
 
-    if (redraw) {
+  if (redraw) {
 #ifdef    HAVE_STRFTIME
-      char t[1024];
-      if (! strftime(t, 1024, screen.strftimeFormat(), tt))
-        return;
+    char t[1024];
+    if (! strftime(t, 1024, screen->getStrftimeFormat(), tt))
+      return;
 #else // !HAVE_STRFTIME
-      char t[9];
-      if (date) {
-        // format the date... with special consideration for y2k ;)
-        if (screen.getDateFormat() == Openbox::B_EuropeanDate)
-          sprintf(t, 18n->getMessage(ToolbarSet, ToolbarNoStrftimeDateFormatEu,
-                                     "%02d.%02d.%02d"),
-                  tt->tm_mday, tt->tm_mon + 1,
-                  (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
-        else
-          sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeDateFormat,
-                          "%02d/%02d/%02d"),
-                  tt->tm_mon + 1, tt->tm_mday,
-                  (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
-      } else {
-        if (screen.isClock24Hour())
-          sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat24,
-                          "  %02d:%02d "),
-                  frame.hour, frame.minute);
-        else
-          sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat12,
-                          "%02d:%02d %sm"),
-                  ((frame.hour > 12) ? frame.hour - 12 :
-                   ((frame.hour == 0) ? 12 : frame.hour)), frame.minute,
-                  ((frame.hour >= 12) ?
-                   i18n(ToolbarSet,
-                        ToolbarNoStrftimeTimeFormatP, "p") :
-                   i18n(ToolbarSet,
-                        ToolbarNoStrftimeTimeFormatA, "a")));
-      }
+    char t[9];
+    if (date) {
+      // format the date... with special consideration for y2k ;)
+      if (screen->getDateFormat() == Blackbox::B_EuropeanDate)
+        sprintf(t, 18n(ToolbarSet, ToolbarNoStrftimeDateFormatEu,
+                       "%02d.%02d.%02d"),
+                tt->tm_mday, tt->tm_mon + 1,
+                (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
+      else
+        sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeDateFormat,
+                        "%02d/%02d/%02d"),
+                tt->tm_mon + 1, tt->tm_mday,
+                (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year);
+    } else {
+      if (screen->isClock24Hour())
+        sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat24,
+                        "  %02d:%02d "),
+                frame.hour, frame.minute);
+      else
+        sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat12,
+                        "%02d:%02d %sm"),
+                ((frame.hour > 12) ? frame.hour - 12 :
+                 ((frame.hour == 0) ? 12 : frame.hour)), frame.minute,
+                ((frame.hour >= 12) ?
+                 i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatP, "p") :
+                 i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatA, "a")));
+    }
 #endif // HAVE_STRFTIME
 
-      int dx = (frame.bevel_w * 2), dlen = strlen(t);
-      unsigned int l;
+    ToolbarStyle *style = screen->getToolbarStyle();
 
-      if (i18n.multibyte()) {
-        XRectangle ink, logical;
-        XmbTextExtents(screen.getToolbarStyle()->fontset,
-                       t, dlen, &ink, &logical);
-        l = logical.width;
-      } else {
-        l = XTextWidth(screen.getToolbarStyle()->font, t, dlen);
-      }
+    int pos = frame.bevel_w * 2, // this is modified by doJustify()
+      dlen = style->doJustify(t, pos, frame.clock_w,
+                              frame.bevel_w * 4, i18n.multibyte());
+    BPen pen(style->c_text, style->font);
+    if (i18n.multibyte())
+      XmbDrawString(display, frame.clock, style->fontset, pen.gc(),
+                    pos, (1 - style->fontset_extents->max_ink_extent.y),
+                    t, dlen);
+    else
+      XDrawString(display, frame.clock, pen.gc(), pos,
+                  (style->font->ascent + 1), t, dlen);
+  }
+}
 
-      l += (frame.bevel_w * 4);
-
-      if (l > frame.clock_w) {
-        for (; dlen >= 0; dlen--) {
-          if (i18n.multibyte()) {
-            XRectangle ink, logical;
-            XmbTextExtents(screen.getToolbarStyle()->fontset,
-                           t, dlen, &ink, &logical);
-            l = logical.width;
-          } else {
-            l = XTextWidth(screen.getToolbarStyle()->font, t, dlen);
-          }
-          l+= (frame.bevel_w * 4);
-
-          if (l < frame.clock_w)
-            break;
-        }
-      }
-      switch (screen.getToolbarStyle()->justify) {
-      case BScreen::RightJustify:
-        dx += frame.clock_w - l;
-        break;
-
-      case BScreen::CenterJustify:
-        dx += (frame.clock_w - l) / 2;
-        break;
-      }
 
-      ToolbarStyle *style = screen.getToolbarStyle();
-      if (i18n.multibyte())
-        XmbDrawString(display, frame.clock, style->fontset, style->c_text_gc,
-                      dx, (1 - style->fontset_extents->max_ink_extent.y),
-                      t, dlen);
-      else
-        XDrawString(display, frame.clock, style->c_text_gc, dx,
-                    (style->font->ascent + 1), t, dlen);
-    }
+void Toolbar::redrawWindowLabel(bool redraw) {
+  BlackboxWindow *foc = screen->getBlackbox()->getFocusedWindow();
+  if (! foc) {
+    XClearWindow(display, frame.window_label);
+    return;
   }
 
+  if (redraw)
+    XClearWindow(display, frame.window_label);
 
-  void Toolbar::redrawWindowLabel(Bool redraw) {
-    OpenboxWindow *foc = screen.getOpenbox().focusedWindow();
-    if (foc == (OpenboxWindow *) 0) {
-      XClearWindow(display, frame.window_label);
-    } else {
-      if (redraw)
-        XClearWindow(display, frame.window_label);
+  if (foc->getScreen() != screen) return;
 
-      if (foc->getScreen() != &screen) return;
+  const char *title = foc->getTitle();
+  ToolbarStyle *style = screen->getToolbarStyle();
 
-      int dx = (frame.bevel_w * 2), dlen = strlen(*foc->getTitle());
-      unsigned int l;
+  int pos = frame.bevel_w * 2, // modified by doJustify()
+    dlen = style->doJustify(title, pos, frame.window_label_w,
+                            frame.bevel_w * 4, i18n.multibyte());
+  BPen pen(style->w_text, style->font);
+  if (i18n.multibyte())
+    XmbDrawString(display, frame.window_label, style->fontset, pen.gc(), pos,
+                  (1 - style->fontset_extents->max_ink_extent.y),
+                  title, dlen);
+  else
+    XDrawString(display, frame.window_label, pen.gc(), pos,
+                (style->font->ascent + 1), title, dlen);
+}
 
-      if (i18n.multibyte()) {
-        XRectangle ink, logical;
-        XmbTextExtents(screen.getToolbarStyle()->fontset, *foc->getTitle(),
-                       dlen, &ink, &logical);
-        l = logical.width;
-      } else {
-        l = XTextWidth(screen.getToolbarStyle()->font, *foc->getTitle(), dlen);
-      }
-      l += (frame.bevel_w * 4);
-
-      if (l > frame.window_label_w) {
-        for (; dlen >= 0; dlen--) {
-          if (i18n.multibyte()) {
-            XRectangle ink, logical;
-            XmbTextExtents(screen.getToolbarStyle()->fontset,
-                           *foc->getTitle(), dlen, &ink, &logical);
-            l = logical.width;
-          } else {
-            l = XTextWidth(screen.getToolbarStyle()->font,
-                           *foc->getTitle(), dlen);
-          }
-          l += (frame.bevel_w * 4);
-
-          if (l < frame.window_label_w)
-            break;
-        }
-      }
-      switch (screen.getToolbarStyle()->justify) {
-      case BScreen::RightJustify:
-        dx += frame.window_label_w - l;
-        break;
-
-      case BScreen::CenterJustify:
-        dx += (frame.window_label_w - l) / 2;
-        break;
-      }
 
-      ToolbarStyle *style = screen.getToolbarStyle();
-      if (i18n.multibyte())
-        XmbDrawString(display, frame.window_label, style->fontset,
-                      style->w_text_gc, dx,
-                      (1 - style->fontset_extents->max_ink_extent.y),
-                      *foc->getTitle(), dlen);
-      else
-        XDrawString(display, frame.window_label, style->w_text_gc, dx,
-                    (style->font->ascent + 1), *foc->getTitle(), dlen);
-    }
-  }
+void Toolbar::redrawWorkspaceLabel(bool redraw) {
+  const string& name = screen->getCurrentWorkspace()->getName();
 
+  if (redraw)
+    XClearWindow(display, frame.workspace_label);
 
-  void Toolbar::redrawWorkspaceLabel(Bool redraw) {
-    if (screen.getCurrentWorkspace()->getName()) {
-      if (redraw)
-        XClearWindow(display, frame.workspace_label);
+  ToolbarStyle *style = screen->getToolbarStyle();
 
-      int dx = (frame.bevel_w * 2), dlen =
-        strlen(screen.getCurrentWorkspace()->getName());
-      unsigned int l;
+  int pos = frame.bevel_w * 2,
+    dlen = style->doJustify(name.c_str(), pos, frame.workspace_label_w,
+                            frame.bevel_w * 4, i18n.multibyte());
+  BPen pen(style->l_text, style->font);
+  if (i18n.multibyte())
+    XmbDrawString(display, frame.workspace_label, style->fontset, pen.gc(),
+                  pos, (1 - style->fontset_extents->max_ink_extent.y),
+                  name.c_str(), dlen);
+  else
+    XDrawString(display, frame.workspace_label, pen.gc(), pos,
+                (style->font->ascent + 1),
+                name.c_str(), dlen);
+}
 
-      if (i18n.multibyte()) {
-        XRectangle ink, logical;
-        XmbTextExtents(screen.getToolbarStyle()->fontset,
-                       screen.getCurrentWorkspace()->getName(), dlen,
-                       &ink, &logical);
-        l = logical.width;
-      } else {
-        l = XTextWidth(screen.getToolbarStyle()->font,
-                       screen.getCurrentWorkspace()->getName(), dlen);
-      }
-      l += (frame.bevel_w * 4);
-
-      if (l > frame.workspace_label_w) {
-        for (; dlen >= 0; dlen--) {
-          if (i18n.multibyte()) {
-            XRectangle ink, logical;
-            XmbTextExtents(screen.getToolbarStyle()->fontset,
-                           screen.getCurrentWorkspace()->getName(), dlen,
-                           &ink, &logical);
-            l = logical.width;
-          } else {
-            l = XTextWidth(screen.getWindowStyle()->font,
-                           screen.getCurrentWorkspace()->getName(), dlen);
-          }
-          l += (frame.bevel_w * 4);
-
-          if (l < frame.workspace_label_w)
-            break;
-        }
-      }
-      switch (screen.getToolbarStyle()->justify) {
-      case BScreen::RightJustify:
-        dx += frame.workspace_label_w - l;
-        break;
-
-      case BScreen::CenterJustify:
-        dx += (frame.workspace_label_w - l) / 2;
-        break;
-      }
 
-      ToolbarStyle *style = screen.getToolbarStyle();
-      if (i18n.multibyte())
-        XmbDrawString(display, frame.workspace_label, style->fontset,
-                      style->l_text_gc, dx,
-                      (1 - style->fontset_extents->max_ink_extent.y),
-                      (char *) screen.getCurrentWorkspace()->getName(), dlen);
+void Toolbar::redrawPrevWorkspaceButton(bool pressed, bool redraw) {
+  if (redraw) {
+    if (pressed) {
+      if (frame.pbutton)
+        XSetWindowBackgroundPixmap(display, frame.psbutton, frame.pbutton);
       else
-        XDrawString(display, frame.workspace_label, style->l_text_gc, dx,
-                    (style->font->ascent + 1),
-                    (char *) screen.getCurrentWorkspace()->getName(), dlen);
+        XSetWindowBackground(display, frame.psbutton, frame.pbutton_pixel);
+    } else {
+      if (frame.button)
+        XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
+      else
+        XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
     }
+    XClearWindow(display, frame.psbutton);
   }
 
+  int hh = frame.button_w / 2, hw = frame.button_w / 2;
 
-  void Toolbar::redrawPrevWorkspaceButton(Bool pressed, Bool redraw) {
-    if (redraw) {
-      if (pressed) {
-        if (frame.pbutton)
-          XSetWindowBackgroundPixmap(display, frame.psbutton, frame.pbutton);
-        else
-          XSetWindowBackground(display, frame.psbutton, frame.pbutton_pixel);
-      } else {
-        if (frame.button)
-          XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button);
-        else
-          XSetWindowBackground(display, frame.psbutton, frame.button_pixel);
-      }
-      XClearWindow(display, frame.psbutton);
-    }
-
-    int hh = frame.button_w / 2, hw = frame.button_w / 2;
-
-    XPoint pts[3];
-    pts[0].x = hw - 2; pts[0].y = hh;
-    pts[1].x = 4; pts[1].y = 2;
-    pts[2].x = 0; pts[2].y = -4;
+  XPoint pts[3];
+  pts[0].x = hw - 2; pts[0].y = hh;
+  pts[1].x = 4; pts[1].y = 2;
+  pts[2].x = 0; pts[2].y = -4;
 
-    XFillPolygon(display, frame.psbutton, screen.getToolbarStyle()->b_pic_gc,
-                 pts, 3, Convex, CoordModePrevious);
-  }
+  ToolbarStyle *style = screen->getToolbarStyle();
+  BPen pen(style->b_pic, style->font);
+  XFillPolygon(display, frame.psbutton, pen.gc(),
+               pts, 3, Convex, CoordModePrevious);
+}
 
 
-  void Toolbar::redrawNextWorkspaceButton(Bool pressed, Bool redraw) {
-    if (redraw) {
-      if (pressed) {
-        if (frame.pbutton)
-          XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.pbutton);
-        else
-          XSetWindowBackground(display, frame.nsbutton, frame.pbutton_pixel);
-      } else {
-        if (frame.button)
-          XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
-        else
-          XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
-      }
-      XClearWindow(display, frame.nsbutton);
+void Toolbar::redrawNextWorkspaceButton(bool pressed, bool redraw) {
+  if (redraw) {
+    if (pressed) {
+      if (frame.pbutton)
+        XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.pbutton);
+      else
+        XSetWindowBackground(display, frame.nsbutton, frame.pbutton_pixel);
+    } else {
+      if (frame.button)
+        XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button);
+      else
+        XSetWindowBackground(display, frame.nsbutton, frame.button_pixel);
     }
-
-    int hh = frame.button_w / 2, hw = frame.button_w / 2;
-
-    XPoint pts[3];
-    pts[0].x = hw - 2; pts[0].y = hh - 2;
-    pts[1].x = 4; pts[1].y =  2;
-    pts[2].x = -4; pts[2].y = 2;
-
-    XFillPolygon(display, frame.nsbutton, screen.getToolbarStyle()->b_pic_gc,
-                 pts, 3, Convex, CoordModePrevious);
+    XClearWindow(display, frame.nsbutton);
   }
 
+  int hh = frame.button_w / 2, hw = frame.button_w / 2;
 
-  void Toolbar::redrawPrevWindowButton(Bool pressed, Bool redraw) {
-    if (redraw) {
-      if (pressed) {
-        if (frame.pbutton)
-          XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.pbutton);
-        else
-          XSetWindowBackground(display, frame.pwbutton, frame.pbutton_pixel);
-      } else {
-        if (frame.button)
-          XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
-        else
-          XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
-      }
-      XClearWindow(display, frame.pwbutton);
-    }
+  XPoint pts[3];
+  pts[0].x = hw - 2; pts[0].y = hh - 2;
+  pts[1].x = 4; pts[1].y =  2;
+  pts[2].x = -4; pts[2].y = 2;
 
-    int hh = frame.button_w / 2, hw = frame.button_w / 2;
+  ToolbarStyle *style = screen->getToolbarStyle();
+  BPen pen(style->b_pic, style->font);
+  XFillPolygon(display, frame.nsbutton, pen.gc(),
+               pts, 3, Convex, CoordModePrevious);
+}
 
-    XPoint pts[3];
-    pts[0].x = hw - 2; pts[0].y = hh;
-    pts[1].x = 4; pts[1].y = 2;
-    pts[2].x = 0; pts[2].y = -4;
 
-    XFillPolygon(display, frame.pwbutton, screen.getToolbarStyle()->b_pic_gc,
-                 pts, 3, Convex, CoordModePrevious);
+void Toolbar::redrawPrevWindowButton(bool pressed, bool redraw) {
+  if (redraw) {
+    if (pressed) {
+      if (frame.pbutton)
+        XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.pbutton);
+      else
+        XSetWindowBackground(display, frame.pwbutton, frame.pbutton_pixel);
+    } else {
+      if (frame.button)
+        XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button);
+      else
+        XSetWindowBackground(display, frame.pwbutton, frame.button_pixel);
+    }
+    XClearWindow(display, frame.pwbutton);
   }
 
+  int hh = frame.button_w / 2, hw = frame.button_w / 2;
 
-  void Toolbar::redrawNextWindowButton(Bool pressed, Bool redraw) {
-    if (redraw) {
-      if (pressed) {
-        if (frame.pbutton)
-          XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.pbutton);
-        else
-          XSetWindowBackground(display, frame.nwbutton, frame.pbutton_pixel);
-      } else {
-        if (frame.button)
-          XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
-        else
-          XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
-      }
-      XClearWindow(display, frame.nwbutton);
-    }
+  XPoint pts[3];
+  pts[0].x = hw - 2; pts[0].y = hh;
+  pts[1].x = 4; pts[1].y = 2;
+  pts[2].x = 0; pts[2].y = -4;
 
-    int hh = frame.button_w / 2, hw = frame.button_w / 2;
+  ToolbarStyle *style = screen->getToolbarStyle();
+  BPen pen(style->b_pic, style->font);
+  XFillPolygon(display, frame.pwbutton, pen.gc(),
+               pts, 3, Convex, CoordModePrevious);
+}
 
-    XPoint pts[3];
-    pts[0].x = hw - 2; pts[0].y = hh - 2;
-    pts[1].x = 4; pts[1].y =  2;
-    pts[2].x = -4; pts[2].y = 2;
 
-    XFillPolygon(display, frame.nwbutton, screen.getToolbarStyle()->b_pic_gc,
-                 pts, 3, Convex, CoordModePrevious);
+void Toolbar::redrawNextWindowButton(bool pressed, bool redraw) {
+  if (redraw) {
+    if (pressed) {
+      if (frame.pbutton)
+        XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.pbutton);
+      else
+        XSetWindowBackground(display, frame.nwbutton, frame.pbutton_pixel);
+    } else {
+      if (frame.button)
+        XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button);
+      else
+        XSetWindowBackground(display, frame.nwbutton, frame.button_pixel);
+    }
+    XClearWindow(display, frame.nwbutton);
   }
 
+  int hh = frame.button_w / 2, hw = frame.button_w / 2;
 
-  void Toolbar::edit() {
-    Window window;
-    int foo;
+  XPoint pts[3];
+  pts[0].x = hw - 2; pts[0].y = hh - 2;
+  pts[1].x = 4; pts[1].y =  2;
+  pts[2].x = -4; pts[2].y = 2;
 
-    m_editing = True;
-    if (XGetInputFocus(display, &window, &foo) &&
-        window == frame.workspace_label)
-      return;
+  ToolbarStyle *style = screen->getToolbarStyle();
+  BPen pen(style->b_pic, style->font);
+  XFillPolygon(display, frame.nwbutton, pen.gc(), pts, 3, Convex,
+               CoordModePrevious);
+}
 
-    XSetInputFocus(display, frame.workspace_label,
-                   RevertToPointerRoot, CurrentTime);
-    XClearWindow(display, frame.workspace_label);
 
-    openbox.setNoFocus(True);
-    if (openbox.focusedWindow())
-      openbox.focusedWindow()->setFocusFlag(False);
-
-    XDrawRectangle(display, frame.workspace_label,
-                   screen.getWindowStyle()->l_text_focus_gc,
-                   frame.workspace_label_w / 2, 0, 1,
-                   frame.label_h - 1);
-
-    // change the background of the window to that of an active window label
-    Pixmap tmp = frame.wlabel;
-    BTexture *texture = &(screen.getWindowStyle()->l_focus);
-    if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-      frame.wlabel = None;
-      XSetWindowBackground(display, frame.workspace_label,
-                           texture->getColor()->getPixel());
-    } else {
-      frame.wlabel =
-        image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture);
-      XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
-    }
-    if (tmp) image_ctrl->removeImage(tmp);
-  }
+void Toolbar::edit(void) {
+  Window window;
+  int foo;
+
+  editing = True;
+  XGetInputFocus(display, &window, &foo);
+  if (window == frame.workspace_label)
+    return;
+
+  XSetInputFocus(display, frame.workspace_label,
+                 RevertToPointerRoot, CurrentTime);
+  XClearWindow(display, frame.workspace_label);
+
+  blackbox->setNoFocus(True);
+  if (blackbox->getFocusedWindow())
+    blackbox->getFocusedWindow()->setFocusFlag(False);
+
+  ToolbarStyle *style = screen->getToolbarStyle();
+  BPen pen(style->l_text, style->font);
+  XDrawRectangle(display, frame.workspace_label, pen.gc(),
+                 frame.workspace_label_w / 2, 0, 1,
+                 frame.label_h - 1);
+  // change the background of the window to that of an active window label
+  BTexture *texture = &(screen->getWindowStyle()->l_focus);
+  frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h,
+                                 frame.wlabel);
+  if (! frame.wlabel)
+    XSetWindowBackground(display, frame.workspace_label,
+                         texture->color().pixel());
+  else
+    XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
+}
 
 
-  void Toolbar::buttonPressEvent(XButtonEvent *be) {
-    if (be->button == 1) {
-      if (be->window == frame.psbutton)
-        redrawPrevWorkspaceButton(True, True);
-      else if (be->window == frame.nsbutton)
-        redrawNextWorkspaceButton(True, True);
-      else if (be->window == frame.pwbutton)
-        redrawPrevWindowButton(True, True);
-      else if (be->window == frame.nwbutton)
-        redrawNextWindowButton(True, True);
+void Toolbar::buttonPressEvent(XButtonEvent *be) {
+  if (be->button == 1) {
+    if (be->window == frame.psbutton)
+      redrawPrevWorkspaceButton(True, True);
+    else if (be->window == frame.nsbutton)
+      redrawNextWorkspaceButton(True, True);
+    else if (be->window == frame.pwbutton)
+      redrawPrevWindowButton(True, True);
+    else if (be->window == frame.nwbutton)
+      redrawNextWindowButton(True, True);
 #ifndef   HAVE_STRFTIME
-      else if (be->window == frame.clock) {
-        XClearWindow(display, frame.clock);
-        checkClock(True, True);
-      }
+    else if (be->window == frame.clock) {
+      XClearWindow(display, frame.clock);
+      checkClock(True, True);
+    }
 #endif // HAVE_STRFTIME
-      else if (! m_ontop) {
-        Window w[1] = { frame.window };
-        screen.raiseWindows(w, 1);
-      }
-    } else if (be->button == 2 && (! m_ontop)) {
-      XLowerWindow(display, frame.window);
-    } else if (be->button == 3) {
-      if (! toolbarmenu->isVisible()) {
-        int x, y;
-
-        x = be->x_root - (toolbarmenu->getWidth() / 2);
-        y = be->y_root - (toolbarmenu->getHeight() / 2);
-
-        if (x < 0)
-          x = 0;
-        else if (x + toolbarmenu->getWidth() > screen.size().w())
-          x = screen.size().w() - toolbarmenu->getWidth();
-
-        if (y < 0)
-          y = 0;
-        else if (y + toolbarmenu->getHeight() > screen.size().h())
-          y = screen.size().h() - toolbarmenu->getHeight();
-
-        toolbarmenu->move(x, y);
-        toolbarmenu->show();
-      } else
-        toolbarmenu->hide();
+    else if (! on_top) {
+      Window w[1] = { frame.window };
+      screen->raiseWindows(w, 1);
     }
-  }
+  } else if (be->button == 2 && (! on_top)) {
+    XLowerWindow(display, frame.window);
+  } else if (be->button == 3) {
+    if (toolbarmenu->isVisible()) {
+      toolbarmenu->hide();
+    } else {
+      int x, y;
 
+      x = be->x_root - (toolbarmenu->getWidth() / 2);
+      y = be->y_root - (toolbarmenu->getHeight() / 2);
 
+      if (x < 0)
+        x = 0;
+      else if (x + toolbarmenu->getWidth() > screen->getWidth())
+        x = screen->getWidth() - toolbarmenu->getWidth();
 
-  void Toolbar::buttonReleaseEvent(XButtonEvent *re) {
-    if (re->button == 1) {
-      if (re->window == frame.psbutton) {
-        redrawPrevWorkspaceButton(False, True);
-
-        if (re->x >= 0 && re->x < (signed) frame.button_w &&
-            re->y >= 0 && re->y < (signed) frame.button_w)
-          if (screen.getCurrentWorkspace()->getWorkspaceID() > 0)
-            screen.changeWorkspaceID(screen.getCurrentWorkspace()->
-                                     getWorkspaceID() - 1);
-          else
-            screen.changeWorkspaceID(screen.getWorkspaceCount() - 1);
-      } else if (re->window == frame.nsbutton) {
-        redrawNextWorkspaceButton(False, True);
-
-        if (re->x >= 0 && re->x < (signed) frame.button_w &&
-            re->y >= 0 && re->y < (signed) frame.button_w)
-          if (screen.getCurrentWorkspace()->getWorkspaceID() <
-              screen.getWorkspaceCount() - 1)
-            screen.changeWorkspaceID(screen.getCurrentWorkspace()->
-                                     getWorkspaceID() + 1);
-          else
-            screen.changeWorkspaceID(0);
-      } else if (re->window == frame.pwbutton) {
-        redrawPrevWindowButton(False, True);
-
-        if (re->x >= 0 && re->x < (signed) frame.button_w &&
-            re->y >= 0 && re->y < (signed) frame.button_w)
-          screen.prevFocus();
-      } else if (re->window == frame.nwbutton) {
-        redrawNextWindowButton(False, True);
-
-        if (re->x >= 0 && re->x < (signed) frame.button_w &&
-            re->y >= 0 && re->y < (signed) frame.button_w)
-          screen.nextFocus();
-      } else if (re->window == frame.window_label)
-        screen.raiseFocus();
-#ifndef   HAVE_STRFTIME
-      else if (re->window == frame.clock) {
-        XClearWindow(display, frame.clock);
-        checkClock(True);
-      }
-#endif // HAVE_STRFTIME
+      if (y < 0)
+        y = 0;
+      else if (y + toolbarmenu->getHeight() > screen->getHeight())
+        y = screen->getHeight() - toolbarmenu->getHeight();
+
+      toolbarmenu->move(x, y);
+      toolbarmenu->show();
     }
   }
+}
 
 
-  void Toolbar::enterNotifyEvent(XCrossingEvent *) {
-    if (! m_autohide)
-      return;
 
-    if (m_hidden) {
-      if (! hide_timer->isTiming()) hide_timer->start();
-    } else {
-      if (hide_timer->isTiming()) hide_timer->stop();
+void Toolbar::buttonReleaseEvent(XButtonEvent *re) {
+  if (re->button == 1) {
+    if (re->window == frame.psbutton) {
+      redrawPrevWorkspaceButton(False, True);
+
+      if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
+          re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
+       if (screen->getCurrentWorkspace()->getID() > 0)
+          screen->changeWorkspaceID(screen->getCurrentWorkspace()->
+                                    getID() - 1);
+        else
+          screen->changeWorkspaceID(screen->getWorkspaceCount() - 1);
+    } else if (re->window == frame.nsbutton) {
+      redrawNextWorkspaceButton(False, True);
+
+      if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
+          re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
+        if (screen->getCurrentWorkspace()->getID() <
+            (screen->getWorkspaceCount() - 1))
+          screen->changeWorkspaceID(screen->getCurrentWorkspace()->
+                                    getID() + 1);
+        else
+          screen->changeWorkspaceID(0);
+    } else if (re->window == frame.pwbutton) {
+      redrawPrevWindowButton(False, True);
+
+      if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
+          re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
+        screen->prevFocus();
+    } else if (re->window == frame.nwbutton) {
+      redrawNextWindowButton(False, True);
+
+      if (re->x >= 0 && re->x < static_cast<signed>(frame.button_w) &&
+          re->y >= 0 && re->y < static_cast<signed>(frame.button_w))
+        screen->nextFocus();
+    } else if (re->window == frame.window_label)
+      screen->raiseFocus();
+#ifndef   HAVE_STRFTIME
+    else if (re->window == frame.clock) {
+      XClearWindow(display, frame.clock);
+      checkClock(True);
     }
+#endif // HAVE_STRFTIME
   }
+}
 
-  void Toolbar::leaveNotifyEvent(XCrossingEvent *) {
-    if (! m_autohide)
-      return;
 
-    if (m_hidden) {
-      if (hide_timer->isTiming()) hide_timer->stop();
-    } else if (! toolbarmenu->isVisible()) {
-      if (! hide_timer->isTiming()) hide_timer->start();
-    }
+void Toolbar::enterNotifyEvent(XCrossingEvent *) {
+  if (! do_auto_hide)
+    return;
+
+  if (hidden) {
+    if (! hide_timer->isTiming()) hide_timer->start();
+  } else {
+    if (hide_timer->isTiming()) hide_timer->stop();
   }
+}
 
+void Toolbar::leaveNotifyEvent(XCrossingEvent *) {
+  if (! do_auto_hide)
+    return;
 
-  void Toolbar::exposeEvent(XExposeEvent *ee) {
-    if (ee->window == frame.clock) checkClock(True);
-    else if (ee->window == frame.workspace_label && (! m_editing))
-      redrawWorkspaceLabel();
-    else if (ee->window == frame.window_label) redrawWindowLabel();
-    else if (ee->window == frame.psbutton) redrawPrevWorkspaceButton();
-    else if (ee->window == frame.nsbutton) redrawNextWorkspaceButton();
-    else if (ee->window == frame.pwbutton) redrawPrevWindowButton();
-    else if (ee->window == frame.nwbutton) redrawNextWindowButton();
+  if (hidden) {
+    if (hide_timer->isTiming()) hide_timer->stop();
+  } else if (! toolbarmenu->isVisible()) {
+    if (! hide_timer->isTiming()) hide_timer->start();
   }
+}
 
 
-  void Toolbar::keyPressEvent(XKeyEvent *ke) {
-    if (ke->window == frame.workspace_label && m_editing) {
-      openbox.grab();
+void Toolbar::exposeEvent(XExposeEvent *ee) {
+  if (ee->window == frame.clock) checkClock(True);
+  else if (ee->window == frame.workspace_label && (! editing))
+    redrawWorkspaceLabel();
+  else if (ee->window == frame.window_label) redrawWindowLabel();
+  else if (ee->window == frame.psbutton) redrawPrevWorkspaceButton();
+  else if (ee->window == frame.nsbutton) redrawNextWorkspaceButton();
+  else if (ee->window == frame.pwbutton) redrawPrevWindowButton();
+  else if (ee->window == frame.nwbutton) redrawNextWindowButton();
+}
 
-      if (! new_workspace_name) {
-        new_workspace_name = new char[128];
-        new_name_pos = 0;
 
-        if (! new_workspace_name) return;
-      }
+void Toolbar::keyPressEvent(XKeyEvent *ke) {
+  if (ke->window == frame.workspace_label && editing) {
+    if (new_workspace_name.empty()) {
+      new_name_pos = 0;
+    }
 
-      KeySym ks;
-      char keychar[1];
-      XLookupString(ke, keychar, 1, &ks, 0);
-
-      // either we are told to end with a return or we hit the end of the buffer
-      if (ks == XK_Return || new_name_pos == 127) {
-        *(new_workspace_name + new_name_pos) = 0;
-
-        m_editing = False;
-
-        openbox.setNoFocus(False);
-        if (openbox.focusedWindow()) {
-          openbox.focusedWindow()->setInputFocus();
-          openbox.focusedWindow()->setFocusFlag(True);
-        } else
-          openbox.focusWindow((OpenboxWindow *) 0);
-
-        // check to make sure that new_name[0] != 0... otherwise we have a null
-        // workspace name which causes serious problems, especially for the
-        // Openbox::LoadRC() method.
-        if (*new_workspace_name) {
-          screen.getCurrentWorkspace()->setName(new_workspace_name);
-          screen.getCurrentWorkspace()->getMenu()->hide();
-          screen.getWorkspacemenu()->
-            remove(screen.getCurrentWorkspace()->getWorkspaceID() + 2);
-          screen.getWorkspacemenu()->
-            insert(screen.getCurrentWorkspace()->getName(),
-                   screen.getCurrentWorkspace()->getMenu(),
-                   screen.getCurrentWorkspace()->getWorkspaceID() + 2);
-          screen.getWorkspacemenu()->update();
-        }
+    KeySym ks;
+    char keychar[1];
+    XLookupString(ke, keychar, 1, &ks, 0);
 
-        delete [] new_workspace_name;
-        new_workspace_name = (char *) 0;
-        new_name_pos = 0;
-
-        // reset the background to that of the workspace label (its normal
-        // setting)
-        Pixmap tmp = frame.wlabel;
-        BTexture *texture = &(screen.getToolbarStyle()->label);
-        if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-          frame.wlabel = None;
-          XSetWindowBackground(display, frame.workspace_label,
-                               texture->getColor()->getPixel());
-        } else {
-          frame.wlabel =
-            image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture);
-          XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel);
-        }
-        if (tmp) image_ctrl->removeImage(tmp);
-
-        reconfigure();
-      } else if (! (ks == XK_Shift_L || ks == XK_Shift_R ||
-                    ks == XK_Control_L || ks == XK_Control_R ||
-                    ks == XK_Caps_Lock || ks == XK_Shift_Lock ||
-                    ks == XK_Meta_L || ks == XK_Meta_R ||
-                    ks == XK_Alt_L || ks == XK_Alt_R ||
-                    ks == XK_Super_L || ks == XK_Super_R ||
-                    ks == XK_Hyper_L || ks == XK_Hyper_R)) {
-        if (ks == XK_BackSpace) {
-          if (new_name_pos > 0) {
-            --new_name_pos;
-            *(new_workspace_name + new_name_pos) = '\0';
-          } else {
-            *new_workspace_name = '\0';
-          }
-        } else {
-          *(new_workspace_name + new_name_pos) = *keychar;
-          ++new_name_pos;
-          *(new_workspace_name + new_name_pos) = '\0';
-        }
+    // either we are told to end with a return or we hit 127 chars
+    if (ks == XK_Return || new_name_pos == 127) {
+      editing = False;
 
-        XClearWindow(display, frame.workspace_label);
-        int l = strlen(new_workspace_name), tw, x;
+      blackbox->setNoFocus(False);
+      if (blackbox->getFocusedWindow()) {
+        blackbox->getFocusedWindow()->setInputFocus();
+      } else {
+        blackbox->setFocusedWindow(0);
+      }
 
-        if (i18n.multibyte()) {
-          XRectangle ink, logical;
-          XmbTextExtents(screen.getToolbarStyle()->fontset,
-                         new_workspace_name, l, &ink, &logical);
-          tw = logical.width;
+      Workspace *wkspc = screen->getCurrentWorkspace();
+      wkspc->setName(new_workspace_name);
+      wkspc->getMenu()->hide();
+
+      screen->getWorkspacemenu()->changeItemLabel(wkspc->getID() + 2,
+                                                  wkspc->getName());
+      screen->getWorkspacemenu()->update();
+
+      new_workspace_name.erase();
+      new_name_pos = 0;
+
+      // reset the background to that of the workspace label (its normal
+      // setting)
+      BTexture *texture = &(screen->getToolbarStyle()->label);
+      frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h,
+                                     frame.wlabel);
+      if (! frame.wlabel)
+        XSetWindowBackground(display, frame.workspace_label,
+                             texture->color().pixel());
+      else
+        XSetWindowBackgroundPixmap(display, frame.workspace_label,
+                                   frame.wlabel);
+      reconfigure();
+    } else if (! (ks == XK_Shift_L || ks == XK_Shift_R ||
+                  ks == XK_Control_L || ks == XK_Control_R ||
+                  ks == XK_Caps_Lock || ks == XK_Shift_Lock ||
+                  ks == XK_Meta_L || ks == XK_Meta_R ||
+                  ks == XK_Alt_L || ks == XK_Alt_R ||
+                  ks == XK_Super_L || ks == XK_Super_R ||
+                  ks == XK_Hyper_L || ks == XK_Hyper_R)) {
+      if (ks == XK_BackSpace) {
+        if (new_name_pos > 0) {
+          --new_name_pos;
+          new_workspace_name.erase(new_name_pos);
         } else {
-          tw = XTextWidth(screen.getToolbarStyle()->font,
-                          new_workspace_name, l);
+          new_workspace_name.resize(0);
         }
-        x = (frame.workspace_label_w - tw) / 2;
-
-        if (x < (signed) frame.bevel_w) x = frame.bevel_w;
+      } else {
+        new_workspace_name += (*keychar);
+        ++new_name_pos;
+      }
 
-        WindowStyle *style = screen.getWindowStyle();
-        if (i18n.multibyte())
-          XmbDrawString(display, frame.workspace_label, style->fontset,
-                        style->l_text_focus_gc, x,
-                        (1 - style->fontset_extents->max_ink_extent.y),
-                        new_workspace_name, l);
-        else
-          XDrawString(display, frame.workspace_label, style->l_text_focus_gc, x,
-                      (style->font->ascent + 1),
-                      new_workspace_name, l);
+      XClearWindow(display, frame.workspace_label);
+      unsigned int l = new_workspace_name.length(), tw, x;
 
-        XDrawRectangle(display, frame.workspace_label,
-                       screen.getWindowStyle()->l_text_focus_gc, x + tw, 0, 1,
-                       frame.label_h - 1);
+      if (i18n.multibyte()) {
+        XRectangle ink, logical;
+        XmbTextExtents(screen->getToolbarStyle()->fontset,
+                       new_workspace_name.c_str(), l, &ink, &logical);
+        tw = logical.width;
+      } else {
+        tw = XTextWidth(screen->getToolbarStyle()->font,
+                        new_workspace_name.c_str(), l);
       }
+      x = (frame.workspace_label_w - tw) / 2;
+
+      if (x < frame.bevel_w) x = frame.bevel_w;
 
-      openbox.ungrab();
+      ToolbarStyle *style = screen->getToolbarStyle();
+      BPen pen(style->l_text, style->font);
+      if (i18n.multibyte())
+        XmbDrawString(display, frame.workspace_label, style->fontset,
+                      pen.gc(), x,
+                      (1 - style->fontset_extents->max_ink_extent.y),
+                      new_workspace_name.c_str(), l);
+      else
+        XDrawString(display, frame.workspace_label, pen.gc(), x,
+                    (style->font->ascent + 1),
+                    new_workspace_name.c_str(), l);
+      XDrawRectangle(display, frame.workspace_label, pen.gc(), x + tw, 0, 1,
+                     frame.label_h - 1);
     }
   }
+}
 
 
-  void Toolbar::timeout() {
-    checkClock(True);
+void Toolbar::timeout(void) {
+  checkClock(True);
 
-    timeval now;
-    gettimeofday(&now, 0);
-    clock_timer->setTimeout((60 - (now.tv_sec % 60)) * 1000);
-  }
+  clock_timer->setTimeout(aMinuteFromNow());
+}
 
 
-  void Toolbar::HideHandler::timeout() {
-    toolbar->m_hidden = !toolbar->m_hidden;
-    if (toolbar->m_hidden)
-      XMoveWindow(toolbar->display, toolbar->frame.window,
-                  toolbar->frame.x_hidden, toolbar->frame.y_hidden);
-    else
-      XMoveWindow(toolbar->display, toolbar->frame.window,
-                  toolbar->frame.x, toolbar->frame.y);
+void Toolbar::HideHandler::timeout(void) {
+  toolbar->hidden = ! toolbar->hidden;
+  if (toolbar->hidden)
+    XMoveWindow(toolbar->display, toolbar->frame.window,
+                toolbar->frame.x_hidden, toolbar->frame.y_hidden);
+  else
+    XMoveWindow(toolbar->display, toolbar->frame.window,
+                toolbar->frame.rect.x(), toolbar->frame.rect.y());
+}
+
+
+void Toolbar::toggleAutoHide(void) {
+  do_auto_hide = (do_auto_hide) ?  False : True;
+
+  updateStrut();
+  screen->getSlit()->reposition();
+
+  if (do_auto_hide == False && hidden) {
+    // force the slit to be visible
+    if (hide_timer->isTiming()) hide_timer->stop();
+    hide_handler.timeout();
   }
+}
 
 
-  Toolbarmenu::Toolbarmenu(Toolbar &tb) : Basemenu(tb.screen), toolbar(tb) {
-    setLabel(i18n(ToolbarSet, ToolbarToolbarTitle, "Toolbar"));
-    setInternalMenu();
+Toolbarmenu::Toolbarmenu(Toolbar *tb) : Basemenu(tb->screen) {
+  toolbar = tb;
 
-    placementmenu = new Placementmenu(*this);
+  setLabel(i18n(ToolbarSet, ToolbarToolbarTitle, "Toolbar"));
+  setInternalMenu();
 
-    insert(i18n(CommonSet, CommonPlacementTitle, "Placement"),
-           placementmenu);
-    insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
-    insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2);
-    insert(i18n(ToolbarSet, ToolbarEditWkspcName,
-                "Edit current workspace name"), 3);
+  placementmenu = new Placementmenu(this);
 
-    update();
+  insert(i18n(CommonSet, CommonPlacementTitle, "Placement"),
+         placementmenu);
+  insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1);
+  insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2);
+  insert(i18n(ToolbarSet, ToolbarEditWkspcName,
+              "Edit current workspace name"), 3);
 
-    setValues();
-  }
+  update();
 
-  void Toolbarmenu::setValues() {
-    setItemSelected(1, toolbar.onTop());
-    setItemSelected(2, toolbar.autoHide());
+  if (toolbar->isOnTop()) setItemSelected(1, True);
+  if (toolbar->doAutoHide()) setItemSelected(2, True);
+}
+
+
+Toolbarmenu::~Toolbarmenu(void) {
+  delete placementmenu;
+}
+
+
+void Toolbarmenu::itemSelected(int button, unsigned int index) {
+  if (button != 1)
+    return;
+
+  BasemenuItem *item = find(index);
+  if (! item) return;
+
+  switch (item->function()) {
+  case 1: { // always on top
+    toolbar->on_top = ((toolbar->isOnTop()) ? False : True);;
+    setItemSelected(1, toolbar->on_top);
+
+    if (toolbar->isOnTop()) getScreen()->raiseWindows((Window *) 0, 0);
+    break;
   }
 
+  case 2: { // auto hide
+    toolbar->toggleAutoHide();
+    setItemSelected(2, toolbar->do_auto_hide);
 
-  Toolbarmenu::~Toolbarmenu() {
-    delete placementmenu;
+    break;
   }
 
+  case 3: { // edit current workspace name
+    toolbar->edit();
+    hide();
 
-  void Toolbarmenu::itemSelected(int button, int index) {
-    if (button != 1)
-      return;
+    break;
+  }
+  } // switch
+}
 
-    BasemenuItem *item = find(index);
-    if (! item) return;
 
-    switch (item->function()) {
-    case 1: { // always on top
-      Bool change = ((toolbar.onTop()) ? False : True);
-      toolbar.setOnTop(change);
-      setItemSelected(1, change);
+void Toolbarmenu::internal_hide(void) {
+  Basemenu::internal_hide();
+  if (toolbar->doAutoHide() && ! toolbar->isEditing())
+    toolbar->hide_handler.timeout();
+}
 
-      if (toolbar.onTop()) toolbar.screen.raiseWindows((Window *) 0, 0);
-      break;
-    }
 
-    case 2: { // auto hide
-      Bool change = ((toolbar.autoHide()) ?  False : True);
-      toolbar.setAutoHide(change);
-      setItemSelected(2, change);
+void Toolbarmenu::reconfigure(void) {
+  placementmenu->reconfigure();
 
-#ifdef    SLIT
-      toolbar.screen.getSlit()->reposition();
-#endif // SLIT
-      break;
-    }
+  Basemenu::reconfigure();
+}
 
-    case 3: { // edit current workspace name
-      toolbar.edit();
-      hide();
 
-      break;
-    }
-    } // switch
-  }
+Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu *tm)
+  : Basemenu(tm->toolbar->screen) {
+  setLabel(i18n(ToolbarSet, ToolbarToolbarPlacement, "Toolbar Placement"));
+  setInternalMenu();
+  setMinimumSublevels(3);
+
+  insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"),
+         Toolbar::TopLeft);
+  insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"),
+         Toolbar::BottomLeft);
+  insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"),
+         Toolbar::TopCenter);
+  insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"),
+         Toolbar::BottomCenter);
+  insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"),
+         Toolbar::TopRight);
+  insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"),
+         Toolbar::BottomRight);
+  update();
+}
 
 
-  void Toolbarmenu::internal_hide() {
-    Basemenu::internal_hide();
-    if (toolbar.autoHide() && ! toolbar.isEditing())
-      toolbar.hide_handler.timeout();
-  }
+void Toolbarmenu::Placementmenu::itemSelected(int button, unsigned int index) {
+  if (button != 1)
+    return;
 
+  BasemenuItem *item = find(index);
+  if (! item) return;
 
-  void Toolbarmenu::reconfigure() {
-    setValues();
-    placementmenu->reconfigure();
+  getScreen()->saveToolbarPlacement(item->function());
+  hide();
+  getScreen()->getToolbar()->reconfigure();
 
-    Basemenu::reconfigure();
-  }
+  // reposition the slit as well to make sure it doesn't intersect the
+  // toolbar
+  getScreen()->getSlit()->reposition();
+}
 
 
-  Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu &tm)
-    : Basemenu(tm.toolbar.screen), toolbarmenu(tm) {
-      setLabel(i18n(ToolbarSet, ToolbarToolbarPlacement,
-                    "Toolbar Placement"));
-      setInternalMenu();
-      setMinimumSublevels(3);
-
-      insert(i18n(CommonSet, CommonPlacementTopLeft,
-                  "Top Left"), Toolbar::TopLeft);
-      insert(i18n(CommonSet, CommonPlacementBottomLeft,
-                  "Bottom Left"), Toolbar::BottomLeft);
-      insert(i18n(CommonSet, CommonPlacementTopCenter,
-                  "Top Center"), Toolbar::TopCenter);
-      insert(i18n(CommonSet, CommonPlacementBottomCenter,
-                  "Bottom Center"), Toolbar::BottomCenter);
-      insert(i18n(CommonSet, CommonPlacementTopRight,
-                  "Top Right"), Toolbar::TopRight);
-      insert(i18n(CommonSet, CommonPlacementBottomRight,
-                  "Bottom Right"), Toolbar::BottomRight);
-      update();
-    }
+int ToolbarStyle::doJustify(const char *text, int &start_pos,
+                            unsigned int max_length, unsigned int modifier,
+                            bool multibyte) const {
+  size_t text_len = strlen(text);
+  unsigned int length;
 
-  void Toolbarmenu::Placementmenu::itemSelected(int button, int index) {
-    if (button != 1)
-      return;
+  do {
+    if (multibyte) {
+      XRectangle ink, logical;
+      XmbTextExtents(fontset, text, text_len, &ink, &logical);
+      length = logical.width;
+    } else {
+      length = XTextWidth(font, text, text_len);
+    }
+    length += modifier;
+  } while (length > max_length && text_len-- > 0);
 
-    BasemenuItem *item = find(index);
-    if (! item) return;
+  switch (justify) {
+  case RightJustify:
+    start_pos += max_length - length;
+    break;
 
-    toolbarmenu.toolbar.setPlacement(item->function());
-    hide();
-    toolbarmenu.toolbar.reconfigure();
+  case CenterJustify:
+    start_pos += (max_length - length) / 2;
+    break;
 
-#ifdef    SLIT
-    // reposition the slit as well to make sure it doesn't intersect the
-    // toolbar
-    toolbarmenu.toolbar.screen.getSlit()->reposition();
-#endif // SLIT
+  case LeftJustify:
+  default:
+    break;
   }
+
+  return text_len;
+}
diff --git a/src/Toolbar.h b/src/Toolbar.h
deleted file mode 100644 (file)
index 93d9205..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-// Toolbar.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Toolbar_hh
-#define   __Toolbar_hh
-
-#include <X11/Xlib.h>
-
-#include "Basemenu.h"
-#include "Timer.h"
-#include "Resource.h"
-#include "Screen.h"
-#include "Geometry.h"
-
-// forward declaration
-class Toolbar;
-
-class Toolbarmenu : public Basemenu {
-private:
-  class Placementmenu : public Basemenu {
-  private:
-    Toolbarmenu &toolbarmenu;
-
-  protected:
-    virtual void itemSelected(int, int);
-
-  public:
-    Placementmenu(Toolbarmenu &);
-  };
-
-  Toolbar &toolbar;
-  Placementmenu *placementmenu;
-
-  friend class Placementmenu;
-  friend class Toolbar;
-
-
-protected:
-  virtual void itemSelected(int, int);
-  virtual void internal_hide();
-  virtual void setValues();
-
-public:
-  Toolbarmenu(Toolbar &);
-  ~Toolbarmenu();
-
-  inline Basemenu *getPlacementmenu() { return placementmenu; }
-
-  void reconfigure();
-};
-
-
-class Toolbar : public TimeoutHandler {
-private:
-  bool m_ontop, m_editing, m_hidden, m_autohide;
-  int m_width_percent, m_placement;
-  Display *display;
-
-  struct frame {
-    unsigned long button_pixel, pbutton_pixel;
-    Pixmap base, label, wlabel, clk, button, pbutton;
-    Window window, workspace_label, window_label, clock, psbutton, nsbutton,
-      pwbutton, nwbutton;
-
-    int x, y, x_hidden, y_hidden, hour, minute, grab_x, grab_y;
-    unsigned int width, height, window_label_w, workspace_label_w, clock_w,
-      button_w, bevel_w, label_h;
-  } frame;
-
-  class HideHandler : public TimeoutHandler {
-  public:
-    Toolbar *toolbar;
-    virtual void timeout();
-  } hide_handler;
-
-  Openbox &openbox;
-  BScreen &screen;
-  Resource &config;
-  BImageControl *image_ctrl;
-  BTimer *clock_timer, *hide_timer;
-  Toolbarmenu *toolbarmenu;
-
-  char *new_workspace_name;
-  size_t new_name_pos;
-
-  friend class HideHandler;
-  friend class Toolbarmenu;
-  friend class Toolbarmenu::Placementmenu;
-
-
-public:
-  Toolbar(BScreen &, Resource &);
-  virtual ~Toolbar();
-
-  inline Toolbarmenu *getMenu() { return toolbarmenu; }
-
-  inline const Window &getWindowID() const { return frame.window; }
-
-  //inline unsigned int getWidth() const { return frame.width; }
-  //inline unsigned int getHeight() const { return frame.height; }
-  unsigned int getExposedHeight() const;
-  
-  //int getX() const;
-  //int getY() const;
-
-  Rect area() const;
-  //Size size() const { return area().size(); }
-  //Point origin() const { return area().origin(); }
-  
-  void buttonPressEvent(XButtonEvent *);
-  void buttonReleaseEvent(XButtonEvent *);
-  void enterNotifyEvent(XCrossingEvent *);
-  void leaveNotifyEvent(XCrossingEvent *);
-  void exposeEvent(XExposeEvent *);
-  void keyPressEvent(XKeyEvent *);
-
-  void redrawWindowLabel(Bool = False);
-  void redrawWorkspaceLabel(Bool = False);
-  void redrawPrevWorkspaceButton(Bool = False, Bool = False);
-  void redrawNextWorkspaceButton(Bool = False, Bool = False);
-  void redrawPrevWindowButton(Bool = False, Bool = False);
-  void redrawNextWindowButton(Bool = False, Bool = False);
-  void edit();
-  void reconfigure();
-  void load();
-  void save();
-  void mapToolbar();
-  void unMapToolbar();
-#ifdef    HAVE_STRFTIME
-  void checkClock(Bool = False);
-#else //  HAVE_STRFTIME
-  void checkClock(Bool = False, Bool = False);
-#endif // HAVE_STRFTIME
-
-  virtual void timeout();
-
-  inline bool onTop() const { return m_ontop; }
-  void setOnTop(bool);
-
-  inline bool autoHide() const { return m_autohide; }
-  void setAutoHide(bool);
-  
-  inline int widthPercent() const { return m_width_percent; }
-  void setWidthPercent(int);
-  
-  inline int placement() const { return m_placement; }
-  void setPlacement(int);
-
-  inline bool isEditing() const { return m_editing; }
-  inline bool isHidden() const { return m_hidden; }
-  
-  enum { TopLeft = 1, BottomLeft, TopCenter,
-         BottomCenter, TopRight, BottomRight };
-};
-
-
-#endif // __Toolbar_hh
diff --git a/src/Toolbar.hh b/src/Toolbar.hh
new file mode 100644 (file)
index 0000000..5ec3029
--- /dev/null
@@ -0,0 +1,173 @@
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Toolbar.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef   __Toolbar_hh
+#define   __Toolbar_hh
+
+extern "C" {
+#include <X11/Xlib.h>
+}
+
+#include "Screen.hh"
+#include "Basemenu.hh"
+#include "Timer.hh"
+
+// forward declaration
+class Toolbar;
+
+class Toolbarmenu : public Basemenu {
+private:
+  class Placementmenu : public Basemenu {
+  private:
+    Placementmenu(const Placementmenu&);
+    Placementmenu& operator=(const Placementmenu&);
+
+  protected:
+    virtual void itemSelected(int button, unsigned int index);
+
+  public:
+    Placementmenu(Toolbarmenu *tm);
+  };
+
+  Toolbar *toolbar;
+  Placementmenu *placementmenu;
+
+  friend class Placementmenu;
+  friend class Toolbar;
+
+  Toolbarmenu(const Toolbarmenu&);
+  Toolbarmenu& operator=(const Toolbarmenu&);
+
+protected:
+  virtual void itemSelected(int button, unsigned int index);
+  virtual void internal_hide(void);
+
+public:
+  Toolbarmenu(Toolbar *tb);
+  ~Toolbarmenu(void);
+
+  inline Basemenu *getPlacementmenu(void) { return placementmenu; }
+
+  void reconfigure(void);
+};
+
+
+class Toolbar : public TimeoutHandler {
+private:
+  bool on_top, editing, hidden, do_auto_hide;
+  Display *display;
+
+  struct ToolbarFrame {
+    unsigned long button_pixel, pbutton_pixel;
+    Pixmap base, label, wlabel, clk, button, pbutton;
+    Window window, workspace_label, window_label, clock, psbutton, nsbutton,
+      pwbutton, nwbutton;
+
+    int x_hidden, y_hidden, hour, minute, grab_x, grab_y;
+    unsigned int window_label_w, workspace_label_w, clock_w,
+      button_w, bevel_w, label_h;
+
+    Rect rect;
+  } frame;
+
+  class HideHandler : public TimeoutHandler {
+  public:
+    Toolbar *toolbar;
+
+    virtual void timeout(void);
+  } hide_handler;
+
+  Blackbox *blackbox;
+  BScreen *screen;
+  BTimer *clock_timer, *hide_timer;
+  Toolbarmenu *toolbarmenu;
+  Strut strut;
+
+  std::string new_workspace_name;
+  size_t new_name_pos;
+
+  friend class HideHandler;
+  friend class Toolbarmenu;
+  friend class Toolbarmenu::Placementmenu;
+
+  void redrawPrevWorkspaceButton(bool pressed = False, bool redraw = False);
+  void redrawNextWorkspaceButton(bool pressed = False, bool redraw = False);
+  void redrawPrevWindowButton(bool preseed = False, bool redraw = False);
+  void redrawNextWindowButton(bool preseed = False, bool redraw = False);
+
+  void updateStrut(void);
+
+#ifdef    HAVE_STRFTIME
+  void checkClock(bool redraw = False);
+#else //  HAVE_STRFTIME
+  void checkClock(bool redraw = False, bool date = False);
+#endif // HAVE_STRFTIME
+
+  Toolbar(const Toolbar&);
+  Toolbar& operator=(const Toolbar&);
+
+public:
+  Toolbar(BScreen *scrn);
+  virtual ~Toolbar(void);
+
+  inline Toolbarmenu *getMenu(void) { return toolbarmenu; }
+
+  inline bool isEditing(void) const { return editing; }
+  inline bool isOnTop(void) const { return on_top; }
+  inline bool isHidden(void) const { return hidden; }
+  inline bool doAutoHide(void) const { return do_auto_hide; }
+
+  inline Window getWindowID(void) const { return frame.window; }
+
+  inline const Rect& getRect(void) const { return frame.rect; }
+  inline unsigned int getWidth(void) const { return frame.rect.width(); }
+  inline unsigned int getHeight(void) const { return frame.rect.height(); }
+  inline unsigned int getExposedHeight(void) const
+  { return ((do_auto_hide) ? frame.bevel_w : frame.rect.height()); }
+  inline int getX(void) const
+  { return ((hidden) ? frame.x_hidden : frame.rect.x()); }
+  inline int getY(void) const
+  { return ((hidden) ? frame.y_hidden : frame.rect.y()); }
+
+  void buttonPressEvent(XButtonEvent *be);
+  void buttonReleaseEvent(XButtonEvent *re);
+  void enterNotifyEvent(XCrossingEvent * /*unused*/);
+  void leaveNotifyEvent(XCrossingEvent * /*unused*/);
+  void exposeEvent(XExposeEvent *ee);
+  void keyPressEvent(XKeyEvent *ke);
+
+  void edit(void);
+  void reconfigure(void);
+  void toggleAutoHide(void);
+
+  void redrawWindowLabel(bool redraw = False);
+  void redrawWorkspaceLabel(bool redraw = False);
+
+  virtual void timeout(void);
+
+  enum { TopLeft = 1, BottomLeft, TopCenter,
+         BottomCenter, TopRight, BottomRight };
+};
+
+
+#endif // __Toolbar_hh
index 14e0f32ac1beea3c51b3c363b9b10e26be07b9f0..0300e52bb0ee279e66f3f0611bb3749ff49bc5c0 100644 (file)
@@ -1,8 +1,7 @@
 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-// Util.cc for Openbox
-// Copyright (c) 2002 - 2002 Ben Jansens (ben at orodu.net)
-// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry (shaleh at debian.org)
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
+// Util.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000, 2002 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // copy of this software and associated documentation files (the "Software"),
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-#include "../config.h"
+#ifdef    HAVE_CONFIG_H
+#  include "../config.h"
+#endif // HAVE_CONFIG_H
 
-#ifdef HAVE_SYS_TYPES_H
-#  include <sys/types.h>
+extern "C" {
+#ifdef HAVE_STRING_H
+#include <string.h>
 #endif
-
-#ifdef HAVE_UNISTD_H
-#  include <unistd.h>
-#endif
-
 #ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
+#include <stdlib.h>
 #endif
+#ifdef    TIME_WITH_SYS_TIME
+#  include <sys/time.h>
+#  include <time.h>
+#else // !TIME_WITH_SYS_TIME
+#  ifdef    HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#  else // !HAVE_SYS_TIME_H
+#    include <time.h>
+#  endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif // HAVE_UNISTD_H
+#if defined(HAVE_PROCESS_H) && defined(__EMX__)
+#  include <process.h>
+#endif //   HAVE_PROCESS_H             __EMX__
+}
+
+#include <X11/Xatom.h>
+
+#include <algorithm>
+
+#include "Util.hh"
+
+using std::string;
+
+
+void Rect::setX(int __x) {
+  _x2 += __x - _x1;
+  _x1 = __x;
+}
+
+
+void Rect::setY(int __y)
+{
+  _y2 += __y - _y1;
+  _y1 = __y;
+}
+
+
+void Rect::setPos(int __x, int __y) {
+  _x2 += __x - _x1;
+  _x1 = __x;
+  _y2 += __y - _y1;
+  _y1 = __y;
+}
+
+
+void Rect::setWidth(unsigned int __w) {
+  _x2 = __w + _x1 - 1;
+}
+
+
+void Rect::setHeight(unsigned int __h) {
+  _y2 = __h + _y1 - 1;
+}
+
+
+void Rect::setSize(unsigned int __w, unsigned int __h) {
+  _x2 = __w + _x1 - 1;
+  _y2 = __h + _y1 - 1;
+}
+
+
+void Rect::setRect(int __x, int __y, unsigned int __w, unsigned int __h) {
+  *this = Rect(__x, __y, __w, __h);
+}
+
+
+void Rect::setCoords(int __l, int __t, int __r, int __b) {
+  _x1 = __l;
+  _y1 = __t;
+  _x2 = __r;
+  _y2 = __b;
+}
+
 
+Rect Rect::operator|(const Rect &a) const {
+  Rect b;
 
+  b._x1 = std::min(_x1, a._x1);
+  b._y1 = std::min(_y1, a._y1);
+  b._x2 = std::max(_x2, a._x2);
+  b._y2 = std::max(_y2, a._y2);
+
+  return b;
+}
+
+
+Rect Rect::operator&(const Rect &a) const {
+  Rect b;
+
+  b._x1 = std::max(_x1, a._x1);
+  b._y1 = std::max(_y1, a._y1);
+  b._x2 = std::min(_x2, a._x2);
+  b._y2 = std::min(_y2, a._y2);
+
+  return b;
+}
+
+
+bool Rect::intersects(const Rect &a) const {
+  return std::max(_x1, a._x1) <= std::min(_x2, a._x2) &&
+         std::max(_y1, a._y1) <= std::min(_y2, a._y2);
+}
+
+
+string expandTilde(const string& s) {
+  if (s[0] != '~') return s;
+
+  const char* const home = getenv("HOME");
+  if (home == NULL) return s;
+
+  return string(home + s.substr(s.find('/')));
+}
+
+
+void bexec(const string& command, const string& displaystring) {
 #ifndef    __EMX__
-void bexec(const char *command, char* displaystring) {
   if (! fork()) {
     setsid();
-    putenv(displaystring);
-    execl("/bin/sh", "/bin/sh", "-c", command, NULL);
+    int ret = putenv(const_cast<char *>(displaystring.c_str()));
+    assert(ret != -1);
+    string cmd = "exec ";
+    cmd += command;
+    execl("/bin/sh", "/bin/sh", "-c", cmd.c_str(), NULL);
     exit(0);
   }
-}
+#else //   __EMX__
+  spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", command, NULL);
 #endif // !__EMX__
+}
 
 
-char *bstrdup(const char *s) {
-  const int l = strlen(s) + 1;
-  char *n = new char[l];
-  strncpy(n, s, l);
-  return n;
+#ifndef   HAVE_BASENAME
+string basename (const string& path) {
+  string::size_type slash = path.rfind('/');
+  if (slash == string::npos)
+    return path;
+  return path.substr(slash+1);
 }
+#endif // HAVE_BASENAME
 
 
-#ifndef   HAVE_BASENAME
-char *basename (char *s) {
-  char *save = s;
+string textPropertyToString(Display *display, XTextProperty& text_prop) {
+  string ret;
 
-  while (*s) if (*s++ == '/') save = s;
+  if (text_prop.value && text_prop.nitems > 0) {
+    ret = (char *) text_prop.value;
+    if (text_prop.encoding != XA_STRING) {
+      text_prop.nitems = strlen((char *) text_prop.value);
 
-  return save;
+      char **list;
+      int num;
+      if (XmbTextPropertyToTextList(display, &text_prop,
+                                    &list, &num) == Success &&
+          num > 0 && *list) {
+        ret = *list;
+        XFreeStringList(list);
+      }
+    }
+  }
+
+  return ret;
+}
+
+
+timeval normalizeTimeval(const timeval &tm) {
+  timeval ret = tm;
+
+  while (ret.tv_usec < 0) {
+    if (ret.tv_sec > 0) {
+      --ret.tv_sec;
+      ret.tv_usec += 1000000;
+    } else {
+      ret.tv_usec = 0;
+    }
+  }
+
+  if (ret.tv_usec >= 1000000) {
+    ret.tv_sec += ret.tv_usec / 1000000;
+    ret.tv_usec %= 1000000;
+  }
+
+  if (ret.tv_sec < 0) ret.tv_sec = 0;
+
+  return ret;
 }
-#endif // HAVE_BASENAME
diff --git a/src/Util.h b/src/Util.h
deleted file mode 100644 (file)
index ad45c40..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// Util.h for Openbox
-// Copyright (c) 2002 - 2002 Ben Jansens (ben@orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Util_hh
-#define   __Util_hh
-
-#ifdef     DEBUG
-# include <assert.h>
-# define ASSERT(x) assert(x)
-#else  // !DEBUG
-# define ASSERT(x)
-#endif //  DEBUG
-
-struct PointerAssassin {
-  template<typename T>
-  inline void operator()(const T ptr) const {
-    delete ptr;
-  }
-};
-
-#endif // __Util_hh
diff --git a/src/Util.hh b/src/Util.hh
new file mode 100644 (file)
index 0000000..1536226
--- /dev/null
@@ -0,0 +1,102 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Util.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef _BLACKBOX_UTIL_HH
+#define _BLACKBOX_UTIL_HH
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <string>
+
+class Rect {
+public:
+  inline Rect(void) : _x1(0), _y1(0), _x2(0), _y2(0) { }
+  inline Rect(int __x, int __y, unsigned int __w, unsigned int __h)
+    : _x1(__x), _y1(__y), _x2(__w + __x - 1), _y2(__h + __y - 1) { }
+  inline explicit Rect(const XRectangle& xrect)
+    : _x1(xrect.x), _y1(xrect.y), _x2(xrect.width + xrect.x - 1),
+      _y2(xrect.height + xrect.y - 1) { }
+
+  inline int left(void) const { return _x1; }
+  inline int top(void) const { return _y1; }
+  inline int right(void) const { return _x2; }
+  inline int bottom(void) const { return _y2; }
+
+  inline int x(void) const { return _x1; }
+  inline int y(void) const { return _y1; }
+  void setX(int __x);
+  void setY(int __y);
+  void setPos(int __x, int __y);
+
+  inline unsigned int width(void) const { return _x2 - _x1 + 1; }
+  inline unsigned int height(void) const { return _y2 - _y1 + 1; }
+  void setWidth(unsigned int __w);
+  void setHeight(unsigned int __h);
+  void setSize(unsigned int __w, unsigned int __h);
+
+  void setRect(int __x, int __y, unsigned int __w, unsigned int __h);
+
+  void setCoords(int __l, int __t, int __r, int __b);
+
+  inline bool operator==(const Rect &a)
+  { return _x1 == a._x1 && _y1 == a._y1 && _x2 == a._x2 && _y2 == a._y2; }
+  inline bool operator!=(const Rect &a) { return ! operator==(a); }
+
+  Rect operator|(const Rect &a) const;
+  Rect operator&(const Rect &a) const;
+  inline Rect &operator|=(const Rect &a) { *this = *this | a; return *this; }
+  inline Rect &operator&=(const Rect &a) { *this = *this & a; return *this; }
+
+  inline bool valid(void) const { return _x2 > _x1 && _y2 > _y1; }
+
+  bool intersects(const Rect &a) const;
+
+private:
+  int _x1, _y1, _x2, _y2;
+};
+
+/* XXX: this needs autoconf help */
+const unsigned int BSENTINEL = 65535;
+
+std::string expandTilde(const std::string& s);
+
+void bexec(const std::string& command, const std::string& displaystring);
+
+#ifndef   HAVE_BASENAME
+std::string basename(const std::string& path);
+#endif
+
+std::string textPropertyToString(Display *display, XTextProperty& text_prop);
+
+struct timeval; // forward declare to avoid the header
+timeval normalizeTimeval(const timeval &tm);
+
+struct PointerAssassin {
+  template<typename T>
+  inline void operator()(const T ptr) const {
+    delete ptr;
+  }
+};
+
+#endif
index 342864c9e11d4cbd48208e6555983e4158d3db11..7ca881ac4a7e938fba2d57fcdf98e7b73c1c0006 100644 (file)
@@ -1,7 +1,7 @@
-// Window.cc for Openbox
-// Copyright (c) 2002 - 2002 Ben Jansens (ben at orodu.net)
-// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry (shaleh at debian.org)
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Window.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
+// Copyright (c) 1997 - 2000, 2002 Brad Hughes <bhughes at trolltech.com>
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // copy of this software and associated documentation files (the "Software"),
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
+extern "C" {
 #include <X11/Xatom.h>
 #include <X11/keysym.h>
 
-#ifdef    HAVE_STRING_H
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
 
 #    include <stdio.h>
 #  endif // HAVE_STDIO_H
 #endif // DEBUG
+}
+
+#include <cstdlib>
+
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "GCCache.hh"
+#include "Iconmenu.hh"
+#include "Image.hh"
+#include "Screen.hh"
+#include "Toolbar.hh"
+#include "Util.hh"
+#include "Window.hh"
+#include "Windowmenu.hh"
+#include "Workspace.hh"
+#include "Slit.hh"
 
-#include "i18n.h"
-#include "openbox.h"
-#include "Iconmenu.h"
-#include "Screen.h"
-#include "Toolbar.h"
-#include "Window.h"
-#include "Windowmenu.h"
-#include "Workspace.h"
-#ifdef    SLIT
-#  include "Slit.h"
-#endif // SLIT
-#include "Util.h"
 
 /*
  * Initializes the class with default values/the window's set initial values.
  */
-OpenboxWindow::OpenboxWindow(Openbox &o, Window w, BScreen *s) : openbox(o) {
+BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) {
+  // fprintf(stderr, "BlackboxWindow size: %d bytes\n",
+  // sizeof(BlackboxWindow));
+
 #ifdef    DEBUG
-  fprintf(stderr, i18n(WindowSet, WindowCreating,
-                       "OpenboxWindow::OpenboxWindow(): creating 0x%lx\n"),
-          w);
+  fprintf(stderr, "BlackboxWindow::BlackboxWindow(): creating 0x%lx\n", w);
 #endif // DEBUG
 
+  // set timer to zero... it is initialized properly later, so we check
+  // if timer is zero in the destructor, and assume that the window is not
+  // fully constructed if timer is zero...
+  timer = 0;
+  blackbox = b;
   client.window = w;
-  display = openbox.getXDisplay();
+  screen = s;
+
+  if (! validateClient()) {
+    delete this;
+    return;
+  }
 
-  openbox.grab();
-  if (! validateClient()) return;
+  // set the eventmask early in the game so that we make sure we get
+  // all the events we are interested in
+  XSetWindowAttributes attrib_set;
+  attrib_set.event_mask = PropertyChangeMask | FocusChangeMask |
+                          StructureNotifyMask;
+  attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
+                                     ButtonMotionMask;
+  XChangeWindowAttributes(blackbox->getXDisplay(), client.window,
+                          CWEventMask|CWDontPropagate, &attrib_set);
 
   // fetch client size and placement
   XWindowAttributes wattrib;
-  if ((! XGetWindowAttributes(display, client.window, &wattrib)) ||
+  if ((! XGetWindowAttributes(blackbox->getXDisplay(),
+                              client.window, &wattrib)) ||
       (! wattrib.screen) || wattrib.override_redirect) {
 #ifdef    DEBUG
     fprintf(stderr,
-            i18n(WindowSet, WindowXGetWindowAttributesFail,
-                 "OpenboxWindow::OpenboxWindow(): XGetWindowAttributes "
-                 "failed\n"));
+            "BlackboxWindow::BlackboxWindow(): XGetWindowAttributes failed\n");
 #endif // DEBUG
 
-    openbox.ungrab();
+    delete this;
     return;
   }
 
-  if (s) {
-    screen = s;
-  } else {
-    screen = openbox.searchScreen(RootWindowOfScreen(wattrib.screen));
-    if (! screen) {
-#ifdef    DEBUG
-      fprintf(stderr, i18n(WindowSet, WindowCannotFindScreen,
-                           "OpenboxWindow::OpenboxWindow(): can't find screen\n"
-                           "\tfor root window 0x%lx\n"),
-              RootWindowOfScreen(wattrib.screen));
-#endif // DEBUG
-
-      openbox.ungrab();
-      return;
-    }
-  }
-
   flags.moving = flags.resizing = flags.shaded = flags.visible =
-    flags.iconic = flags.transient = flags.focused =
-    flags.stuck = flags.modal =  flags.send_focus_message =
-    flags.shaped = flags.managed = False;
+    flags.iconic = flags.focused = flags.stuck = flags.modal =
+    flags.send_focus_message = flags.shaped = False;
   flags.maximized = 0;
 
-  openbox_attrib.workspace = workspace_number = window_number = -1;
+  blackbox_attrib.workspace = window_number = BSENTINEL;
 
-  openbox_attrib.flags = openbox_attrib.attrib = openbox_attrib.stack
-    = openbox_attrib.decoration = 0l;
-  openbox_attrib.premax_x = openbox_attrib.premax_y = 0;
-  openbox_attrib.premax_w = openbox_attrib.premax_h = 0;
+  blackbox_attrib.flags = blackbox_attrib.attrib = blackbox_attrib.stack
+    = blackbox_attrib.decoration = 0l;
+  blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0;
+  blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0;
 
+  frame.border_w = 1;
   frame.window = frame.plate = frame.title = frame.handle = None;
   frame.close_button = frame.iconify_button = frame.maximize_button = None;
   frame.right_grip = frame.left_grip = None;
 
+  frame.ulabel_pixel = frame.flabel_pixel = frame.utitle_pixel =
+  frame.ftitle_pixel = frame.uhandle_pixel = frame.fhandle_pixel =
+    frame.ubutton_pixel = frame.fbutton_pixel = frame.pbutton_pixel =
+    frame.uborder_pixel = frame.fborder_pixel = frame.ugrip_pixel =
+    frame.fgrip_pixel = 0;
   frame.utitle = frame.ftitle = frame.uhandle = frame.fhandle = None;
   frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None;
-  frame.pbutton = frame.ugrip = frame.fgrip = None;
+  frame.pbutton = frame.ugrip = frame.fgrip = decorations;
 
-  decorations.titlebar = decorations.border = decorations.handle = True;
-  decorations.iconify = decorations.maximize = decorations.menu = True;
-  functions.resize = functions.move = functions.iconify =
-    functions.maximize = True;
-  functions.close = decorations.close = False;
+  decorations = Decor_Titlebar | Decor_Border | Decor_Handle |
+                Decor_Iconify | Decor_Maximize;
+  functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
 
   client.wm_hint_flags = client.normal_hint_flags = 0;
-  client.transient_for = client.transient = 0;
-  client.title = 0;
-  client.title_len = 0;
-  client.icon_title = 0;
-  client.mwm_hint = (MwmHints *) 0;
-  client.openbox_hint = (OpenboxHints *) 0;
+  client.transient_for = 0;
 
   // get the initial size and location of client window (relative to the
   // _root window_). This position is the reference point used with the
   // window's gravity to find the window's initial position.
-  client.x = wattrib.x;
-  client.y = wattrib.y;
-  client.width = wattrib.width;
-  client.height = wattrib.height;
+  client.rect.setRect(wattrib.x, wattrib.y, wattrib.width, wattrib.height);
   client.old_bw = wattrib.border_width;
 
   windowmenu = 0;
   lastButtonPressTime = 0;
-  image_ctrl = screen->getImageControl();
 
-  timer = new BTimer(openbox, *this);
-  timer->setTimeout(openbox.getAutoRaiseDelay());
-  timer->fireOnce(True);
+  timer = new BTimer(blackbox, this);
+  timer->setTimeout(blackbox->getAutoRaiseDelay());
 
-  getOpenboxHints();
-  if (! client.openbox_hint)
+  if (! getBlackboxHints())
     getMWMHints();
 
   // get size, aspect, minimum/maximum size and other hints set by the
@@ -167,268 +158,170 @@ OpenboxWindow::OpenboxWindow(Openbox &o, Window w, BScreen *s) : openbox(o) {
   getWMHints();
   getWMNormalHints();
 
-#ifdef    SLIT
   if (client.initial_state == WithdrawnState) {
     screen->getSlit()->addClient(client.window);
-    openbox.ungrab();
     delete this;
     return;
   }
-#endif // SLIT
 
-  flags.managed = True;
-  openbox.saveWindowSearch(client.window, this);
+  frame.window = createToplevelWindow();
+  frame.plate = createChildWindow(frame.window);
+  associateClientWindow();
 
-  // determine if this is a transient window
-  Window win;
-  if (XGetTransientForHint(display, client.window, &win)) {
-    if (win && (win != client.window)) {
-      OpenboxWindow *tr;
-      if ((tr = openbox.searchWindow(win))) {
-        while (tr->client.transient) tr = tr->client.transient;
-        client.transient_for = tr;
-        tr->client.transient = this;
-        flags.stuck = client.transient_for->flags.stuck;
-        flags.transient = True;
-      } else if (win == client.window_group) {
-        if ((tr = openbox.searchGroup(win, this))) {
-          while (tr->client.transient) tr = tr->client.transient;
-          client.transient_for = tr;
-          tr->client.transient = this;
-          flags.stuck = client.transient_for->flags.stuck;
-          flags.transient = True;
-        }
-      }
-    }
+  blackbox->saveWindowSearch(frame.window, this);
+  blackbox->saveWindowSearch(frame.plate, this);
+  blackbox->saveWindowSearch(client.window, this);
 
-    if (win == screen->getRootWindow()) flags.modal = True;
-  }
+  // determine if this is a transient window
+  getTransientInfo();
 
   // adjust the window decorations based on transience and window sizes
-  if (flags.transient)
-    decorations.maximize = decorations.handle = functions.maximize = False;
+  if (isTransient()) {
+    decorations &= ~(Decor_Maximize | Decor_Handle);
+    functions &= ~Func_Maximize;
+  }
 
   if ((client.normal_hint_flags & PMinSize) &&
       (client.normal_hint_flags & PMaxSize) &&
       client.max_width <= client.min_width &&
       client.max_height <= client.min_height) {
-    decorations.maximize = decorations.handle =
-      functions.resize = functions.maximize = False;
+    decorations &= ~(Decor_Maximize | Decor_Handle);
+    functions &= ~(Func_Resize | Func_Maximize);
   }
   upsize();
 
-  place_window = true;
-  if (openbox.isStartup() || flags.transient ||
+  bool place_window = True;
+  if (blackbox->isStartup() || isTransient() ||
       client.normal_hint_flags & (PPosition|USPosition)) {
     setGravityOffsets();
 
-    if ((openbox.isStartup()) ||
-        (frame.x >= 0 &&
-         (signed) (frame.y + frame.y_border) >= 0 &&
-         frame.x <= (signed) screen->size().w() &&
-         frame.y <= (signed) screen->size().h()))
-      place_window = false;
-  }
-
-  frame.window = createToplevelWindow(frame.x, frame.y, frame.width,
-                                      frame.height,
-                                      frame.border_w);
-  openbox.saveWindowSearch(frame.window, this);
-
-  frame.plate = createChildWindow(frame.window);
-  openbox.saveWindowSearch(frame.plate, this);
 
-  if (decorations.titlebar) {
-    frame.title = createChildWindow(frame.window);
-    frame.label = createChildWindow(frame.title);
-    openbox.saveWindowSearch(frame.title, this);
-    openbox.saveWindowSearch(frame.label, this);
+    if (blackbox->isStartup() ||
+        client.rect.intersects(screen->availableArea()))
+      place_window = False;
   }
 
-  if (decorations.handle) {
-    frame.handle = createChildWindow(frame.window);
-    openbox.saveWindowSearch(frame.handle, this);
+  if (decorations & Decor_Titlebar)
+    createTitlebar();
 
-    frame.left_grip =
-      createChildWindow(frame.handle, openbox.getLowerLeftAngleCursor());
-    openbox.saveWindowSearch(frame.left_grip, this);
+  if (decorations & Decor_Handle)
+    createHandle();
 
-    frame.right_grip =
-      createChildWindow(frame.handle, openbox.getLowerRightAngleCursor());
-    openbox.saveWindowSearch(frame.right_grip, this);
+#ifdef    SHAPE
+  if (blackbox->hasShapeExtensions() && flags.shaped) {
+    configureShape();
   }
+#endif // SHAPE
 
-  associateClientWindow();
-
-  if (! screen->sloppyFocus())
-    openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
-                       GrabModeSync, GrabModeSync, frame.plate, None);
+  if ((! screen->isSloppyFocus()) || screen->doClickRaise()) {
+    // grab button 1 for changing focus/raising
+    blackbox->grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
+                         GrabModeSync, GrabModeSync, frame.plate, None);
+  }
 
-  openbox.grabButton(Button1, Mod1Mask, frame.window, True,
-                     ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
-                     GrabModeAsync, frame.window, openbox.getMoveCursor());
-  openbox.grabButton(Button2, Mod1Mask, frame.window, True,
-                     ButtonReleaseMask, GrabModeAsync, GrabModeAsync, frame.window, None);
-  openbox.grabButton(Button3, Mod1Mask, frame.window, True,
-                     ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
-                     GrabModeAsync, frame.window, None);
+  blackbox->grabButton(Button1, Mod1Mask, frame.window, True,
+                       ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
+                       GrabModeAsync, frame.window, blackbox->getMoveCursor());
+  blackbox->grabButton(Button2, Mod1Mask, frame.window, True,
+                       ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
+                       frame.window, None);
+  blackbox->grabButton(Button3, Mod1Mask, frame.window, True,
+                       ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
+                       GrabModeAsync, frame.window,
+                       blackbox->getLowerRightAngleCursor());
 
   positionWindows();
-  XRaiseWindow(display, frame.plate);
-  XMapSubwindows(display, frame.plate);
-  if (decorations.titlebar) XMapSubwindows(display, frame.title);
-  XMapSubwindows(display, frame.window);
+  decorate();
 
-  if (decorations.menu)
-    windowmenu = new Windowmenu(*this);
+  if (decorations & Decor_Titlebar)
+    XMapSubwindows(blackbox->getXDisplay(), frame.title);
+  XMapSubwindows(blackbox->getXDisplay(), frame.window);
 
-  decorate();
+  windowmenu = new Windowmenu(this);
 
-  if (workspace_number < 0 || workspace_number >= screen->getWorkspaceCount())
+  if (blackbox_attrib.workspace >= screen->getWorkspaceCount())
     screen->getCurrentWorkspace()->addWindow(this, place_window);
   else
-    screen->getWorkspace(workspace_number)->addWindow(this, place_window);
+    screen->getWorkspace(blackbox_attrib.workspace)->
+      addWindow(this, place_window);
 
-  configure(frame.x, frame.y, frame.width, frame.height);
+  if (! place_window) {
+    // don't need to call configure if we are letting the workspace
+    // place the window
+    configure(frame.rect.x(), frame.rect.y(),
+              frame.rect.width(), frame.rect.height());
+  }
 
   if (flags.shaded) {
     flags.shaded = False;
     shade();
   }
 
-  if (flags.maximized && functions.maximize) {
-    unsigned int button = flags.maximized;
-    flags.maximized = 0;
-    maximize(button);
+  if (flags.maximized && (functions & Func_Maximize)) {
+    remaximize();
   }
 
   setFocusFlag(False);
-
-  openbox.ungrab();
 }
 
 
-OpenboxWindow::~OpenboxWindow(void) {
-  if (flags.moving || flags.resizing) {
-    screen->hideGeometry();
-    XUngrabPointer(display, CurrentTime);
-  }
-
-  if (workspace_number != -1 && window_number != -1) {
-    if (flags.stuck) {
-      // make sure no other workspaces think that we're focused
-      for (int i=0; i < screen->getWorkspaceCount(); i++)
-        screen->getWorkspace(i)->removeWindow(this);
-    } else
-      screen->getWorkspace(workspace_number)->removeWindow(this);
-  } else if (flags.iconic)
-    screen->removeIcon(this);
-
-  if (timer) {
-    if (timer->isTiming()) timer->stop();
-    delete timer;
-  }
-
-  if (windowmenu) delete windowmenu;
-
-  if (client.title)
-    delete [] client.title;
-
-  if (client.icon_title)
-    delete [] client.icon_title;
-
-  if (client.mwm_hint)
-    XFree(client.mwm_hint);
+BlackboxWindow::~BlackboxWindow(void) {
 
-  if (client.openbox_hint)
-    XFree(client.openbox_hint);
-
-  if (client.window_group)
-    openbox.removeGroupSearch(client.window_group);
-
-  if (flags.transient && client.transient_for)
-    client.transient_for->client.transient = client.transient;
-  if (client.transient)
-    client.transient->client.transient_for = client.transient_for;
-
-  if (frame.close_button) {
-    openbox.removeWindowSearch(frame.close_button);
-    XDestroyWindow(display, frame.close_button);
-  }
+#ifdef    DEBUG
+  fprintf(stderr, "BlackboxWindow::~BlackboxWindow: destroying 0x%lx\n",
+          client.window);
+#endif // DEBUG
 
-  if (frame.iconify_button) {
-    openbox.removeWindowSearch(frame.iconify_button);
-    XDestroyWindow(display, frame.iconify_button);
-  }
+  if (! timer) // window not managed...
+    return;
 
-  if (frame.maximize_button) {
-    openbox.removeWindowSearch(frame.maximize_button);
-    XDestroyWindow(display, frame.maximize_button);
+  if (flags.moving || flags.resizing) {
+    screen->hideGeometry();
+    XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
   }
 
-  if (frame.title) {
-    if (frame.ftitle)
-      image_ctrl->removeImage(frame.ftitle);
-
-    if (frame.utitle)
-      image_ctrl->removeImage(frame.utitle);
-
-    if (frame.flabel)
-      image_ctrl->removeImage(frame.flabel);
+  delete timer;
 
-    if( frame.ulabel)
-      image_ctrl->removeImage(frame.ulabel);
+  delete windowmenu;
 
-    openbox.removeWindowSearch(frame.label);
-    openbox.removeWindowSearch(frame.title);
-    XDestroyWindow(display, frame.label);
-    XDestroyWindow(display, frame.title);
+  if (client.window_group) {
+    BWindowGroup *group = blackbox->searchGroup(client.window_group);
+    if (group) group->removeWindow(this);
   }
 
-  if (frame.handle) {
-    if (frame.fhandle)
-      image_ctrl->removeImage(frame.fhandle);
-
-    if (frame.uhandle)
-      image_ctrl->removeImage(frame.uhandle);
-
-    if (frame.fgrip)
-      image_ctrl->removeImage(frame.fgrip);
-
-    if (frame.ugrip)
-      image_ctrl->removeImage(frame.ugrip);
-
-    openbox.removeWindowSearch(frame.handle);
-    openbox.removeWindowSearch(frame.right_grip);
-    openbox.removeWindowSearch(frame.left_grip);
-    XDestroyWindow(display, frame.right_grip);
-    XDestroyWindow(display, frame.left_grip);
-    XDestroyWindow(display, frame.handle);
+  // remove ourselves from our transient_for
+  if (isTransient()) {
+    if (client.transient_for != (BlackboxWindow *) ~0ul) {
+      client.transient_for->client.transientList.remove(this);
+    }
+    client.transient_for = (BlackboxWindow*) 0;
   }
 
-  if (frame.fbutton)
-    image_ctrl->removeImage(frame.fbutton);
+  if (client.transientList.size() > 0) {
+    // reset transient_for for all transients
+    BlackboxWindowList::iterator it, end = client.transientList.end();
+    for (it = client.transientList.begin(); it != end; ++it) {
+      (*it)->client.transient_for = (BlackboxWindow*) 0;
+    }
+  }
 
-  if (frame.ubutton)
-    image_ctrl->removeImage(frame.ubutton);
+  if (frame.title)
+    destroyTitlebar();
 
-  if (frame.pbutton)
-    image_ctrl->removeImage(frame.pbutton);
+  if (frame.handle)
+    destroyHandle();
 
   if (frame.plate) {
-    openbox.removeWindowSearch(frame.plate);
-    XDestroyWindow(display, frame.plate);
+    blackbox->removeWindowSearch(frame.plate);
+    XDestroyWindow(blackbox->getXDisplay(), frame.plate);
   }
 
   if (frame.window) {
-    openbox.removeWindowSearch(frame.window);
-    XDestroyWindow(display, frame.window);
+    blackbox->removeWindowSearch(frame.window);
+    XDestroyWindow(blackbox->getXDisplay(), frame.window);
   }
 
-  if (flags.managed) {
-    openbox.removeWindowSearch(client.window);
-    screen->removeNetizen(client.window);
-  }
+  blackbox->removeWindowSearch(client.window);
 }
 
 
@@ -437,23 +330,20 @@ OpenboxWindow::~OpenboxWindow(void) {
  * width.
  * Returns: the newly created window
  */
-Window OpenboxWindow::createToplevelWindow(int x, int y, unsigned int width,
-                                           unsigned int height,
-                                           unsigned int borderwidth)
-{
+Window BlackboxWindow::createToplevelWindow(void) {
   XSetWindowAttributes attrib_create;
   unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
-    CWOverrideRedirect | CWEventMask;
+                              CWOverrideRedirect | CWEventMask;
 
   attrib_create.background_pixmap = None;
   attrib_create.colormap = screen->getColormap();
   attrib_create.override_redirect = True;
   attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
-    ButtonMotionMask | EnterWindowMask;
+                             ButtonMotionMask | EnterWindowMask;
 
-  return XCreateWindow(display, screen->getRootWindow(), x, y, width, height,
-                       borderwidth, screen->getDepth(), InputOutput,
-                       screen->getVisual(), create_mask,
+  return XCreateWindow(blackbox->getXDisplay(), screen->getRootWindow(),
+                       -1, -1, 1, 1, frame.border_w, screen->getDepth(),
+                       InputOutput, screen->getVisual(), create_mask,
                        &attrib_create);
 }
 
@@ -462,522 +352,470 @@ Window OpenboxWindow::createToplevelWindow(int x, int y, unsigned int width,
  * Creates a child window, and optionally associates a given cursor with
  * the new window.
  */
-Window OpenboxWindow::createChildWindow(Window parent, Cursor cursor) {
+Window BlackboxWindow::createChildWindow(Window parent, Cursor cursor) {
   XSetWindowAttributes attrib_create;
   unsigned long create_mask = CWBackPixmap | CWBorderPixel |
-    CWEventMask;
+                              CWEventMask;
 
   attrib_create.background_pixmap = None;
   attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
-    ButtonMotionMask | ExposureMask |
-    EnterWindowMask | LeaveWindowMask;
+                             ButtonMotionMask | ExposureMask;
 
   if (cursor) {
     create_mask |= CWCursor;
     attrib_create.cursor = cursor;
   }
 
-  return XCreateWindow(display, parent, 0, 0, 1, 1, 0, screen->getDepth(),
-                       InputOutput, screen->getVisual(), create_mask,
-                       &attrib_create);
+  return XCreateWindow(blackbox->getXDisplay(), parent, 0, 0, 1, 1, 0,
+                       screen->getDepth(), InputOutput, screen->getVisual(),
+                       create_mask, &attrib_create);
 }
 
 
-void OpenboxWindow::associateClientWindow(void) {
-  XSetWindowBorderWidth(display, client.window, 0);
+void BlackboxWindow::associateClientWindow(void) {
+  XSetWindowBorderWidth(blackbox->getXDisplay(), client.window, 0);
   getWMName();
   getWMIconName();
 
-  XChangeSaveSet(display, client.window, SetModeInsert);
-  XSetWindowAttributes attrib_set;
+  XChangeSaveSet(blackbox->getXDisplay(), client.window, SetModeInsert);
 
-  XSelectInput(display, frame.plate, NoEventMask);
-  XReparentWindow(display, client.window, frame.plate, 0, 0);
-  XSelectInput(display, frame.plate, SubstructureRedirectMask);
+  XSelectInput(blackbox->getXDisplay(), frame.plate, SubstructureRedirectMask);
 
-  XFlush(display);
+  XGrabServer(blackbox->getXDisplay());
+  XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
+  XReparentWindow(blackbox->getXDisplay(), client.window, frame.plate, 0, 0);
+  XSelectInput(blackbox->getXDisplay(), client.window,
+               PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
+  XUngrabServer(blackbox->getXDisplay());
 
-  attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask |
-    FocusChangeMask;
-  attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
-    ButtonMotionMask;
+  XRaiseWindow(blackbox->getXDisplay(), frame.plate);
+  XMapSubwindows(blackbox->getXDisplay(), frame.plate);
 
-  XChangeWindowAttributes(display, client.window, CWEventMask|CWDontPropagate,
-                          &attrib_set);
 
 #ifdef    SHAPE
-  if (openbox.hasShapeExtensions()) {
-    XShapeSelectInput(display, client.window, ShapeNotifyMask);
+  if (blackbox->hasShapeExtensions()) {
+    XShapeSelectInput(blackbox->getXDisplay(), client.window,
+                      ShapeNotifyMask);
 
+    Bool shaped = False;
     int foo;
     unsigned int ufoo;
 
-    XShapeQueryExtents(display, client.window, &flags.shaped, &foo, &foo,
-                       &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo);
-
-    if (flags.shaped) {
-      XShapeCombineShape(display, frame.window, ShapeBounding,
-                         frame.mwm_border_w, frame.y_border +
-                         frame.mwm_border_w, client.window,
-                         ShapeBounding, ShapeSet);
-
-      int num = 1;
-      XRectangle xrect[2];
-      xrect[0].x = xrect[0].y = 0;
-      xrect[0].width = frame.width;
-      xrect[0].height = frame.y_border;
-
-      if (decorations.handle) {
-        xrect[1].x = 0;
-        xrect[1].y = frame.y_handle;
-        xrect[1].width = frame.width;
-        xrect[1].height = frame.handle_h + frame.border_w;
-        num++;
-      }
-
-      XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
-                              xrect, num, ShapeUnion, Unsorted);
-    }
+    XShapeQueryExtents(blackbox->getXDisplay(), client.window, &shaped,
+                       &foo, &foo, &ufoo, &ufoo, &foo, &foo, &foo,
+                       &ufoo, &ufoo);
+    flags.shaped = shaped;
   }
 #endif // SHAPE
-
-  if (decorations.iconify) createIconifyButton();
-  if (decorations.maximize) createMaximizeButton();
-  if (decorations.close) createCloseButton();
 }
 
 
-void OpenboxWindow::decorate(void) {
-  Pixmap tmp = frame.fbutton;
-  BTexture *texture = &(screen->getWindowStyle()->b_focus);
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-    frame.fbutton = None;
-    frame.fbutton_pixel = texture->getColor()->getPixel();
-  } else {
-    frame.fbutton =
-      image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
-  }
-  if (tmp) image_ctrl->removeImage(tmp);
+void BlackboxWindow::decorate(void) {
+  BTexture* texture;
+
+  texture = &(screen->getWindowStyle()->b_focus);
+  frame.fbutton = texture->render(frame.button_w, frame.button_w,
+                                  frame.fbutton);
+  if (! frame.fbutton)
+    frame.fbutton_pixel = texture->color().pixel();
 
-  tmp = frame.ubutton;
   texture = &(screen->getWindowStyle()->b_unfocus);
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-    frame.ubutton = None;
-    frame.ubutton_pixel = texture->getColor()->getPixel();
-  } else {
-    frame.ubutton =
-      image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
-  }
-  if (tmp) image_ctrl->removeImage(tmp);
+  frame.ubutton = texture->render(frame.button_w, frame.button_w,
+                                  frame.ubutton);
+  if (! frame.ubutton)
+    frame.ubutton_pixel = texture->color().pixel();
 
-  tmp = frame.pbutton;
   texture = &(screen->getWindowStyle()->b_pressed);
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-    frame.pbutton = None;
-    frame.pbutton_pixel = texture->getColor()->getPixel();
-  } else {
-    frame.pbutton =
-      image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
-  }
-  if (tmp) image_ctrl->removeImage(tmp);
+  frame.pbutton = texture->render(frame.button_w, frame.button_w,
+                                  frame.pbutton);
+  if (! frame.pbutton)
+    frame.pbutton_pixel = texture->color().pixel();
 
-  if (decorations.titlebar) {
-    tmp = frame.ftitle;
+  if (decorations & Decor_Titlebar) {
     texture = &(screen->getWindowStyle()->t_focus);
-    if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-      frame.ftitle = None;
-      frame.ftitle_pixel = texture->getColor()->getPixel();
-    } else {
-      frame.ftitle =
-        image_ctrl->renderImage(frame.width, frame.title_h, texture);
-    }
-    if (tmp) image_ctrl->removeImage(tmp);
+    frame.ftitle = texture->render(frame.inside_w, frame.title_h,
+                                   frame.ftitle);
+    if (! frame.ftitle)
+      frame.ftitle_pixel = texture->color().pixel();
 
-    tmp = frame.utitle;
     texture = &(screen->getWindowStyle()->t_unfocus);
-    if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-      frame.utitle = None;
-      frame.utitle_pixel = texture->getColor()->getPixel();
-    } else {
-      frame.utitle =
-        image_ctrl->renderImage(frame.width, frame.title_h, texture);
-    }
-    if (tmp) image_ctrl->removeImage(tmp);
+    frame.utitle = texture->render(frame.inside_w, frame.title_h,
+                                   frame.utitle);
+    if (! frame.utitle)
+      frame.utitle_pixel = texture->color().pixel();
 
-    XSetWindowBorder(display, frame.title,
-                     screen->getBorderColor()->getPixel());
+    XSetWindowBorder(blackbox->getXDisplay(), frame.title,
+                     screen->getBorderColor()->pixel());
 
     decorateLabel();
   }
 
-  if (decorations.border) {
-    frame.fborder_pixel = screen->getWindowStyle()->f_focus.getPixel();
-    frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.getPixel();
-    openbox_attrib.flags |= AttribDecoration;
-    openbox_attrib.decoration = DecorNormal;
+  if (decorations & Decor_Border) {
+    frame.fborder_pixel = screen->getWindowStyle()->f_focus.pixel();
+    frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.pixel();
+    blackbox_attrib.flags |= AttribDecoration;
+    blackbox_attrib.decoration = DecorNormal;
   } else {
-    openbox_attrib.flags |= AttribDecoration;
-    openbox_attrib.decoration = DecorNone;
+    blackbox_attrib.flags |= AttribDecoration;
+    blackbox_attrib.decoration = DecorNone;
   }
 
-  if (decorations.handle) {
-    tmp = frame.fhandle;
+  if (decorations & Decor_Handle) {
     texture = &(screen->getWindowStyle()->h_focus);
-    if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-      frame.fhandle = None;
-      frame.fhandle_pixel = texture->getColor()->getPixel();
-    } else {
-      frame.fhandle =
-        image_ctrl->renderImage(frame.width, frame.handle_h, texture);
-    }
-    if (tmp) image_ctrl->removeImage(tmp);
+    frame.fhandle = texture->render(frame.inside_w, frame.handle_h,
+                                    frame.fhandle);
+    if (! frame.fhandle)
+      frame.fhandle_pixel = texture->color().pixel();
 
-    tmp = frame.uhandle;
     texture = &(screen->getWindowStyle()->h_unfocus);
-    if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-      frame.uhandle = None;
-      frame.uhandle_pixel = texture->getColor()->getPixel();
-    } else {
-      frame.uhandle =
-        image_ctrl->renderImage(frame.width, frame.handle_h, texture);
-    }
-    if (tmp) image_ctrl->removeImage(tmp);
+    frame.uhandle = texture->render(frame.inside_w, frame.handle_h,
+                                    frame.uhandle);
+    if (! frame.uhandle)
+      frame.uhandle_pixel = texture->color().pixel();
 
-    tmp = frame.fgrip;
     texture = &(screen->getWindowStyle()->g_focus);
-    if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-      frame.fgrip = None;
-      frame.fgrip_pixel = texture->getColor()->getPixel();
-    } else {
-      frame.fgrip =
-        image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture);
-    }
-    if (tmp) image_ctrl->removeImage(tmp);
+    frame.fgrip = texture->render(frame.grip_w, frame.handle_h, frame.fgrip);
+    if (! frame.fgrip)
+      frame.fgrip_pixel = texture->color().pixel();
 
-    tmp = frame.ugrip;
     texture = &(screen->getWindowStyle()->g_unfocus);
-    if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-      frame.ugrip = None;
-      frame.ugrip_pixel = texture->getColor()->getPixel();
-    } else {
-      frame.ugrip =
-        image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture);
-    }
-    if (tmp) image_ctrl->removeImage(tmp);
+    frame.ugrip = texture->render(frame.grip_w, frame.handle_h, frame.ugrip);
+    if (! frame.ugrip)
+      frame.ugrip_pixel = texture->color().pixel();
 
-    XSetWindowBorder(display, frame.handle,
-                     screen->getBorderColor()->getPixel());
-    XSetWindowBorder(display, frame.left_grip,
-                     screen->getBorderColor()->getPixel());
-    XSetWindowBorder(display, frame.right_grip,
-                     screen->getBorderColor()->getPixel());
+    XSetWindowBorder(blackbox->getXDisplay(), frame.handle,
+                     screen->getBorderColor()->pixel());
+    XSetWindowBorder(blackbox->getXDisplay(), frame.left_grip,
+                     screen->getBorderColor()->pixel());
+    XSetWindowBorder(blackbox->getXDisplay(), frame.right_grip,
+                     screen->getBorderColor()->pixel());
   }
 
-  XSetWindowBorder(display, frame.window,
-                   screen->getBorderColor()->getPixel());
+  XSetWindowBorder(blackbox->getXDisplay(), frame.window,
+                   screen->getBorderColor()->pixel());
 }
 
 
-void OpenboxWindow::decorateLabel(void) {
-  Pixmap tmp = frame.flabel;
-  BTexture *texture = &(screen->getWindowStyle()->l_focus);
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-    frame.flabel = None;
-    frame.flabel_pixel = texture->getColor()->getPixel();
-  } else {
-    frame.flabel =
-      image_ctrl->renderImage(frame.label_w, frame.label_h, texture);
-  }
-  if (tmp) image_ctrl->removeImage(tmp);
+void BlackboxWindow::decorateLabel(void) {
+  BTexture *texture;
+
+  texture = &(screen->getWindowStyle()->l_focus);
+  frame.flabel = texture->render(frame.label_w, frame.label_h, frame.flabel);
+  if (! frame.flabel)
+    frame.flabel_pixel = texture->color().pixel();
 
-  tmp = frame.ulabel;
   texture = &(screen->getWindowStyle()->l_unfocus);
-  if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
-    frame.ulabel = None;
-    frame.ulabel_pixel = texture->getColor()->getPixel();
-  } else {
-    frame.ulabel =
-      image_ctrl->renderImage(frame.label_w, frame.label_h, texture);
-  }
-  if (tmp) image_ctrl->removeImage(tmp);
+  frame.ulabel = texture->render(frame.label_w, frame.label_h, frame.ulabel);
+  if (! frame.ulabel)
+    frame.ulabel_pixel = texture->color().pixel();
+}
+
+
+void BlackboxWindow::createHandle(void) {
+  frame.handle = createChildWindow(frame.window);
+  blackbox->saveWindowSearch(frame.handle, this);
+
+  frame.left_grip =
+    createChildWindow(frame.handle, blackbox->getLowerLeftAngleCursor());
+  blackbox->saveWindowSearch(frame.left_grip, this);
+
+  frame.right_grip =
+    createChildWindow(frame.handle, blackbox->getLowerRightAngleCursor());
+  blackbox->saveWindowSearch(frame.right_grip, this);
+}
+
+
+void BlackboxWindow::destroyHandle(void) {
+  if (frame.fhandle)
+    screen->getImageControl()->removeImage(frame.fhandle);
+
+  if (frame.uhandle)
+    screen->getImageControl()->removeImage(frame.uhandle);
+
+  if (frame.fgrip)
+    screen->getImageControl()->removeImage(frame.fgrip);
+
+  if (frame.ugrip)
+    screen->getImageControl()->removeImage(frame.ugrip);
+
+  blackbox->removeWindowSearch(frame.left_grip);
+  blackbox->removeWindowSearch(frame.right_grip);
+
+  XDestroyWindow(blackbox->getXDisplay(), frame.left_grip);
+  XDestroyWindow(blackbox->getXDisplay(), frame.right_grip);
+  frame.left_grip = frame.right_grip = None;
+
+  blackbox->removeWindowSearch(frame.handle);
+  XDestroyWindow(blackbox->getXDisplay(), frame.handle);
+  frame.handle = None;
+}
+
+
+void BlackboxWindow::createTitlebar(void) {
+  frame.title = createChildWindow(frame.window);
+  frame.label = createChildWindow(frame.title);
+  blackbox->saveWindowSearch(frame.title, this);
+  blackbox->saveWindowSearch(frame.label, this);
+
+  if (decorations & Decor_Iconify) createIconifyButton();
+  if (decorations & Decor_Maximize) createMaximizeButton();
+  if (decorations & Decor_Close) createCloseButton();
+}
+
+
+void BlackboxWindow::destroyTitlebar(void) {
+  if (frame.close_button)
+    destroyCloseButton();
+
+  if (frame.iconify_button)
+    destroyIconifyButton();
+
+  if (frame.maximize_button)
+    destroyMaximizeButton();
+
+  if (frame.ftitle)
+    screen->getImageControl()->removeImage(frame.ftitle);
+
+  if (frame.utitle)
+    screen->getImageControl()->removeImage(frame.utitle);
+
+  if (frame.flabel)
+    screen->getImageControl()->removeImage(frame.flabel);
+
+  if( frame.ulabel)
+    screen->getImageControl()->removeImage(frame.ulabel);
+
+  if (frame.fbutton)
+    screen->getImageControl()->removeImage(frame.fbutton);
+
+  if (frame.ubutton)
+    screen->getImageControl()->removeImage(frame.ubutton);
+
+  if (frame.pbutton)
+    screen->getImageControl()->removeImage(frame.pbutton);
+
+  blackbox->removeWindowSearch(frame.title);
+  blackbox->removeWindowSearch(frame.label);
+
+  XDestroyWindow(blackbox->getXDisplay(), frame.label);
+  XDestroyWindow(blackbox->getXDisplay(), frame.title);
+  frame.title = frame.label = None;
 }
 
 
-void OpenboxWindow::createCloseButton(void) {
-  if (decorations.close && frame.title != None) {
+void BlackboxWindow::createCloseButton(void) {
+  if (frame.title != None) {
     frame.close_button = createChildWindow(frame.title);
-    openbox.saveWindowSearch(frame.close_button, this);
+    blackbox->saveWindowSearch(frame.close_button, this);
   }
 }
 
 
-void OpenboxWindow::createIconifyButton(void) {
-  if (decorations.iconify && frame.title != None) {
+void BlackboxWindow::destroyCloseButton(void) {
+  blackbox->removeWindowSearch(frame.close_button);
+  XDestroyWindow(blackbox->getXDisplay(), frame.close_button);
+  frame.close_button = None;
+}
+
+
+void BlackboxWindow::createIconifyButton(void) {
+  if (frame.title != None) {
     frame.iconify_button = createChildWindow(frame.title);
-    openbox.saveWindowSearch(frame.iconify_button, this);
+    blackbox->saveWindowSearch(frame.iconify_button, this);
   }
 }
 
 
-void OpenboxWindow::createMaximizeButton(void) {
-  if (decorations.maximize && frame.title != None) {
+void BlackboxWindow::destroyIconifyButton(void) {
+  blackbox->removeWindowSearch(frame.iconify_button);
+  XDestroyWindow(blackbox->getXDisplay(), frame.iconify_button);
+  frame.iconify_button = None;
+}
+
+
+void BlackboxWindow::createMaximizeButton(void) {
+  if (frame.title != None) {
     frame.maximize_button = createChildWindow(frame.title);
-    openbox.saveWindowSearch(frame.maximize_button, this);
-  }
-}
-
-
-void OpenboxWindow::positionButtons() {
-  const char *format = openbox.getTitleBarLayout();
-  const unsigned int bw = frame.bevel_w + 1;
-  const unsigned int by = frame.bevel_w + 1;
-  unsigned int bx = frame.bevel_w + 1;
-  unsigned int bcount = strlen(format) - 1;
-
-  if (!decorations.close)
-    bcount--;
-  if (!decorations.maximize)
-    bcount--;
-  if (!decorations.iconify)
-    bcount--;
-  frame.label_w = frame.width - bx * 2 - (frame.button_w + bw) * bcount;
-
-  bool hasclose, hasiconify, hasmaximize;
-  hasclose = hasiconify = hasmaximize = false;
-
-  for (int i = 0; format[i] != '\0' && i < 4; i++) {
-    switch(format[i]) {
-    case 'C':
-      if (decorations.close) {
-        if (frame.close_button == None)
-          createCloseButton();
-        XMoveResizeWindow(display, frame.close_button, bx, by,
-                          frame.button_w, frame.button_h);
-        XMapWindow(display, frame.close_button);
-        XClearWindow(display, frame.close_button);
-        bx += frame.button_w + bw;
-        hasclose = true;
-      }
-      break;
-    case 'I':
-      if (decorations.iconify) {
-        if (frame.iconify_button == None)
-          createIconifyButton();
-        XMoveResizeWindow(display, frame.iconify_button, bx, by,
-                          frame.button_w, frame.button_h);
-        XMapWindow(display, frame.iconify_button);
-        XClearWindow(display, frame.iconify_button);
-        bx += frame.button_w + bw;
-        hasiconify = true;
-      }
-      break;
-    case 'M':
-      if (decorations.maximize) {
-        if (frame.maximize_button == None)
-          createMaximizeButton();
-        XMoveResizeWindow(display, frame.maximize_button, bx, by,
-                          frame.button_w, frame.button_h);
-        XMapWindow(display, frame.maximize_button);
-        XClearWindow(display, frame.maximize_button);
-        bx += frame.button_w + bw;
-        hasmaximize = true;
-      }
-      break;
-    case 'L':
-      XMoveResizeWindow(display, frame.label, bx, by - 1,
-                        frame.label_w, frame.label_h);
-      bx += frame.label_w + bw;
-      break;
-    }
+    blackbox->saveWindowSearch(frame.maximize_button, this);
   }
+}
+
 
-  if (!hasclose && frame.close_button) {
-    openbox.removeWindowSearch(frame.close_button);
-    XDestroyWindow(display, frame.close_button);
-    frame.close_button = None;
+void BlackboxWindow::destroyMaximizeButton(void) {
+  blackbox->removeWindowSearch(frame.maximize_button);
+  XDestroyWindow(blackbox->getXDisplay(), frame.maximize_button);
+  frame.maximize_button = None;
+}
+
+
+void BlackboxWindow::positionButtons(bool redecorate_label) {
+  unsigned int bw = frame.button_w + frame.bevel_w + 1,
+    by = frame.bevel_w + 1, lx = by, lw = frame.inside_w - by;
+
+  if (decorations & Decor_Iconify) {
+    if (frame.iconify_button == None) createIconifyButton();
+
+    XMoveResizeWindow(blackbox->getXDisplay(), frame.iconify_button, by, by,
+                      frame.button_w, frame.button_w);
+    XMapWindow(blackbox->getXDisplay(), frame.iconify_button);
+    XClearWindow(blackbox->getXDisplay(), frame.iconify_button);
+
+    lx += bw;
+    lw -= bw;
+  } else if (frame.iconify_button) {
+    destroyIconifyButton();
   }
-  if (!hasiconify && frame.iconify_button) {
-    openbox.removeWindowSearch(frame.iconify_button);
-    XDestroyWindow(display, frame.iconify_button);
-    frame.iconify_button = None;
+  int bx = frame.inside_w - bw;
+
+  if (decorations & Decor_Close) {
+    if (frame.close_button == None) createCloseButton();
+
+    XMoveResizeWindow(blackbox->getXDisplay(), frame.close_button, bx, by,
+                      frame.button_w, frame.button_w);
+    XMapWindow(blackbox->getXDisplay(), frame.close_button);
+    XClearWindow(blackbox->getXDisplay(), frame.close_button);
+
+    bx -= bw;
+    lw -= bw;
+  } else if (frame.close_button) {
+    destroyCloseButton();
   }
-  if (!hasmaximize && frame.iconify_button) {
-    openbox.removeWindowSearch(frame.maximize_button);
-    XDestroyWindow(display, frame.maximize_button);                 
-    frame.maximize_button = None;
+  if (decorations & Decor_Maximize) {
+    if (frame.maximize_button == None) createMaximizeButton();
+
+    XMoveResizeWindow(blackbox->getXDisplay(), frame.maximize_button, bx, by,
+                      frame.button_w, frame.button_w);
+    XMapWindow(blackbox->getXDisplay(), frame.maximize_button);
+    XClearWindow(blackbox->getXDisplay(), frame.maximize_button);
+
+    lw -= bw;
+  } else if (frame.maximize_button) {
+    destroyMaximizeButton();
   }
+  frame.label_w = lw - by;
+  XMoveResizeWindow(blackbox->getXDisplay(), frame.label, lx, frame.bevel_w,
+                    frame.label_w, frame.label_h);
+  if (redecorate_label) decorateLabel();
 
   redrawLabel();
   redrawAllButtons();
 }
 
 
-void OpenboxWindow::reconfigure(void) {
+void BlackboxWindow::reconfigure(void) {
   upsize();
 
-  client.x = frame.x + frame.mwm_border_w + frame.border_w;
-  client.y = frame.y + frame.y_border + frame.mwm_border_w +
-    frame.border_w;
-
-  if (client.title) {
-    if (i18n.multibyte()) {
-      XRectangle ink, logical;
-      XmbTextExtents(screen->getWindowStyle()->fontset,
-                     client.title, client.title_len, &ink, &logical);
-      client.title_text_w = logical.width;
-    } else {
-      client.title_text_w = XTextWidth(screen->getWindowStyle()->font,
-                                       client.title, client.title_len);
-    }
-    client.title_text_w += (frame.bevel_w * 4);
-  }
+  client.rect.setPos(frame.rect.left() + frame.margin.left,
+                     frame.rect.top() + frame.margin.top);
 
   positionWindows();
   decorate();
 
-  XClearWindow(display, frame.window);
+  XClearWindow(blackbox->getXDisplay(), frame.window);
   setFocusFlag(flags.focused);
 
-  configure(frame.x, frame.y, frame.width, frame.height);
-
-  if (! screen->sloppyFocus())
-    openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
-                       GrabModeSync, GrabModeSync, None, None);
-  else
-    openbox.ungrabButton(Button1, 0, frame.plate);
+  configure(frame.rect.x(), frame.rect.y(),
+            frame.rect.width(), frame.rect.height());
 
   if (windowmenu) {
-    windowmenu->move(windowmenu->getX(), frame.y + frame.title_h);
+    windowmenu->move(windowmenu->getX(), frame.rect.y() + frame.title_h);
     windowmenu->reconfigure();
   }
+}
+
 
-  // re-get the timeout delay
-  timer->setTimeout(openbox.getAutoRaiseDelay());
+void BlackboxWindow::updateFocusModel(void) {
+  if ((! screen->isSloppyFocus()) || screen->doClickRaise()) {
+    // grab button 1 for changing focus/raising
+    blackbox->grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
+                         GrabModeSync, GrabModeSync, None, None);
+  } else {
+    blackbox->ungrabButton(Button1, 0, frame.plate);
+  }
 }
 
 
-void OpenboxWindow::positionWindows(void) {
-  XResizeWindow(display, frame.window, frame.width,
-                ((flags.shaded) ? frame.title_h : frame.height));
-  XSetWindowBorderWidth(display, frame.window, frame.border_w);
-  XSetWindowBorderWidth(display, frame.plate, frame.mwm_border_w);
-  XMoveResizeWindow(display, frame.plate, 0, frame.y_border,
-                    client.width, client.height);
-  XMoveResizeWindow(display, client.window, 0, 0, client.width, client.height);
+void BlackboxWindow::positionWindows(void) {
+  XMoveResizeWindow(blackbox->getXDisplay(), frame.window,
+                    frame.rect.x(), frame.rect.y(), frame.inside_w,
+                    (flags.shaded) ? frame.title_h : frame.inside_h);
+  XSetWindowBorderWidth(blackbox->getXDisplay(), frame.window, frame.border_w);
+  XSetWindowBorderWidth(blackbox->getXDisplay(), frame.plate,
+                        frame.mwm_border_w);
+  XMoveResizeWindow(blackbox->getXDisplay(), frame.plate,
+                    frame.margin.left - frame.mwm_border_w - frame.border_w,
+                    frame.margin.top - frame.mwm_border_w - frame.border_w,
+                    client.rect.width(), client.rect.height());
+  XMoveResizeWindow(blackbox->getXDisplay(), client.window,
+                    0, 0, client.rect.width(), client.rect.height());
 
-  if (decorations.titlebar) {
-    XSetWindowBorderWidth(display, frame.title, frame.border_w);
-    XMoveResizeWindow(display, frame.title, -frame.border_w,
-                      -frame.border_w, frame.width, frame.title_h);
+  if (decorations & Decor_Titlebar) {
+    if (frame.title == None) createTitlebar();
+
+    XSetWindowBorderWidth(blackbox->getXDisplay(), frame.title,
+                          frame.border_w);
+    XMoveResizeWindow(blackbox->getXDisplay(), frame.title, -frame.border_w,
+                      -frame.border_w, frame.inside_w, frame.title_h);
 
     positionButtons();
+    XMapSubwindows(blackbox->getXDisplay(), frame.title);
+    XMapWindow(blackbox->getXDisplay(), frame.title);
   } else if (frame.title) {
-    XUnmapWindow(display, frame.title);
-  }
-  if (decorations.handle) {
-    XSetWindowBorderWidth(display, frame.handle, frame.border_w);
-    XSetWindowBorderWidth(display, frame.left_grip, frame.border_w);
-    XSetWindowBorderWidth(display, frame.right_grip, frame.border_w);
-
-    XMoveResizeWindow(display, frame.handle, -frame.border_w,
-                      frame.y_handle - frame.border_w,
-                      frame.width, frame.handle_h);
-    XMoveResizeWindow(display, frame.left_grip, -frame.border_w,
-                      -frame.border_w, frame.grip_w, frame.grip_h);
-    XMoveResizeWindow(display, frame.right_grip,
-                      frame.width - frame.grip_w - frame.border_w,
-                      -frame.border_w, frame.grip_w, frame.grip_h);
-    XMapSubwindows(display, frame.handle);
+    destroyTitlebar();
+  }
+  if (decorations & Decor_Handle) {
+    if (frame.handle == None) createHandle();
+    XSetWindowBorderWidth(blackbox->getXDisplay(), frame.handle,
+                          frame.border_w);
+    XSetWindowBorderWidth(blackbox->getXDisplay(), frame.left_grip,
+                          frame.border_w);
+    XSetWindowBorderWidth(blackbox->getXDisplay(), frame.right_grip,
+                          frame.border_w);
+
+    XMoveResizeWindow(blackbox->getXDisplay(), frame.handle,
+                      -frame.border_w,
+                      frame.rect.height() - frame.margin.bottom +
+                      frame.mwm_border_w - frame.border_w,
+                      frame.inside_w, frame.handle_h);
+    XMoveResizeWindow(blackbox->getXDisplay(), frame.left_grip,
+                      -frame.border_w, -frame.border_w,
+                      frame.grip_w, frame.handle_h);
+    XMoveResizeWindow(blackbox->getXDisplay(), frame.right_grip,
+                      frame.inside_w - frame.grip_w - frame.border_w,
+                      -frame.border_w, frame.grip_w, frame.handle_h);
+    XMapSubwindows(blackbox->getXDisplay(), frame.handle);
+    XMapWindow(blackbox->getXDisplay(), frame.handle);
   } else if (frame.handle) {
-    XUnmapWindow(display, frame.handle);
+    destroyHandle();
   }
 }
 
 
-void OpenboxWindow::getWMName(void) {
-  if (client.title) {
-    delete [] client.title;
-    client.title = (char *) 0;
-  }
-
+void BlackboxWindow::getWMName(void) {
   XTextProperty text_prop;
-  char **list;
-  int num;
-
-  if (XGetWMName(display, client.window, &text_prop)) {
-    if (text_prop.value && text_prop.nitems > 0) {
-      if (text_prop.encoding != XA_STRING) {
-        text_prop.nitems = strlen((char *) text_prop.value);
-
-        if ((XmbTextPropertyToTextList(display, &text_prop,
-                                       &list, &num) == Success) &&
-            (num > 0) && *list) {
-          client.title = bstrdup(*list);
-          XFreeStringList(list);
-        } else {
-          client.title = bstrdup((char *) text_prop.value);
-        }
-      } else {
-        client.title = bstrdup((char *) text_prop.value);
-      }
-      XFree((char *) text_prop.value);
-    } else {
-      client.title = bstrdup(i18n(WindowSet, WindowUnnamed,
-                                  "Unnamed"));
-    }
-  } else {
-    client.title = bstrdup(i18n(WindowSet, WindowUnnamed,
-                                "Unnamed"));
-  }
-  client.title_len = strlen(client.title);
 
-  if (i18n.multibyte()) {
-    XRectangle ink, logical;
-    XmbTextExtents(screen->getWindowStyle()->fontset,
-                   client.title, client.title_len, &ink, &logical);
-    client.title_text_w = logical.width;
+  if (XGetWMName(blackbox->getXDisplay(), client.window, &text_prop)) {
+    client.title = textPropertyToString(blackbox->getXDisplay(), text_prop);
+    if (client.title.empty())
+      client.title = i18n(WindowSet, WindowUnnamed, "Unnamed");
+    XFree((char *) text_prop.value);
   } else {
-    client.title_len = strlen(client.title);
-    client.title_text_w = XTextWidth(screen->getWindowStyle()->font,
-                                     client.title, client.title_len);
+    client.title = i18n(WindowSet, WindowUnnamed, "Unnamed");
   }
-
-  client.title_text_w += (frame.bevel_w * 4);
 }
 
 
-void OpenboxWindow::getWMIconName(void) {
-  if (client.icon_title) {
-    delete [] client.icon_title;
-    client.icon_title = (char *) 0;
-  }
-
+void BlackboxWindow::getWMIconName(void) {
   XTextProperty text_prop;
-  char **list;
-  int num;
-
-  if (XGetWMIconName(display, client.window, &text_prop)) {
-    if (text_prop.value && text_prop.nitems > 0) {
-      if (text_prop.encoding != XA_STRING) {
-        text_prop.nitems = strlen((char *) text_prop.value);
-
-        if ((XmbTextPropertyToTextList(display, &text_prop,
-                                       &list, &num) == Success) &&
-            (num > 0) && *list) {
-          client.icon_title = bstrdup(*list);
-          XFreeStringList(list);
-        } else {
-          client.icon_title = bstrdup((char *) text_prop.value);
-        }
-      } else {
-        client.icon_title = bstrdup((char *) text_prop.value);
-      }
-      XFree((char *) text_prop.value);
-    } else {
-      client.icon_title = bstrdup(client.title);
-    }
+
+  if (XGetWMIconName(blackbox->getXDisplay(), client.window, &text_prop)) {
+    client.icon_title =
+      textPropertyToString(blackbox->getXDisplay(), text_prop);
+    if (client.icon_title.empty())
+      client.icon_title = client.title;
+    XFree((char *) text_prop.value);
   } else {
-    client.icon_title = bstrdup(client.title);
+    client.icon_title = client.title;
   }
 }
 
@@ -989,18 +827,20 @@ void OpenboxWindow::getWMIconName(void) {
  * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
  * this.
  */
-void OpenboxWindow::getWMProtocols(void) {
+void BlackboxWindow::getWMProtocols(void) {
   Atom *proto;
   int num_return = 0;
 
-  if (XGetWMProtocols(display, client.window, &proto, &num_return)) {
+  if (XGetWMProtocols(blackbox->getXDisplay(), client.window,
+                      &proto, &num_return)) {
     for (int i = 0; i < num_return; ++i) {
-      if (proto[i] == openbox.getWMDeleteAtom())
-        functions.close = decorations.close = True;
-      else if (proto[i] == openbox.getWMTakeFocusAtom())
+      if (proto[i] == blackbox->getWMDeleteAtom()) {
+        decorations |= Decor_Close;
+        functions |= Func_Close;
+      } else if (proto[i] == blackbox->getWMTakeFocusAtom())
         flags.send_focus_message = True;
-      else if (proto[i] == openbox.getOpenboxStructureMessagesAtom())
-        screen->addNetizen(new Netizen(*screen, client.window));
+      else if (proto[i] == blackbox->getBlackboxStructureMessagesAtom())
+        screen->addNetizen(new Netizen(screen, client.window));
     }
 
     XFree(proto);
@@ -1012,46 +852,48 @@ void OpenboxWindow::getWMProtocols(void) {
  * Gets the value of the WM_HINTS property.
  * If the property is not set, then use a set of default values.
  */
-void OpenboxWindow::getWMHints(void) {
-  XWMHints *wmhint = XGetWMHints(display, client.window);
+void BlackboxWindow::getWMHints(void) {
+  focus_mode = F_Passive;
+  client.initial_state = NormalState;
+
+  // remove from current window group
+  if (client.window_group) {
+    BWindowGroup *group = blackbox->searchGroup(client.window_group);
+    if (group) group->removeWindow(this);
+  }
+  client.window_group = None;
+
+  XWMHints *wmhint = XGetWMHints(blackbox->getXDisplay(), client.window);
   if (! wmhint) {
-    flags.visible = True;
-    flags.iconic = False;
-    focus_mode = F_Passive;
-    client.window_group = None;
-    client.initial_state = NormalState;
     return;
   }
-  client.wm_hint_flags = wmhint->flags;
+
   if (wmhint->flags & InputHint) {
     if (wmhint->input == True) {
       if (flags.send_focus_message)
         focus_mode = F_LocallyActive;
-      else
-        focus_mode = F_Passive;
     } else {
       if (flags.send_focus_message)
         focus_mode = F_GloballyActive;
       else
         focus_mode = F_NoInput;
     }
-  } else {
-    focus_mode = F_Passive;
   }
 
   if (wmhint->flags & StateHint)
     client.initial_state = wmhint->initial_state;
-  else
-    client.initial_state = NormalState;
 
   if (wmhint->flags & WindowGroupHint) {
-    if (! client.window_group) {
-      client.window_group = wmhint->window_group;
-      openbox.saveGroupSearch(client.window_group, this);
-    }
-  } else {
-    client.window_group = None;
+    client.window_group = wmhint->window_group;
+
+    // add window to the appropriate group
+    BWindowGroup *group = blackbox->searchGroup(client.window_group);
+    if (! group) // no group found, create it!
+      group = new BWindowGroup(blackbox, client.window_group);
+    group->addWindow(this);
   }
+
+  client.wm_hint_flags = wmhint->flags;
   XFree(wmhint);
 }
 
@@ -1060,20 +902,23 @@ void OpenboxWindow::getWMHints(void) {
  * Gets the value of the WM_NORMAL_HINTS property.
  * If the property is not set, then use a set of default values.
  */
-void OpenboxWindow::getWMNormalHints(void) {
+void BlackboxWindow::getWMNormalHints(void) {
   long icccm_mask;
   XSizeHints sizehint;
 
+  const Rect& screen_area = screen->availableArea();
+
   client.min_width = client.min_height =
-    client.base_width = client.base_height =
     client.width_inc = client.height_inc = 1;
-  client.max_width = screen->size().w();
-  client.max_height = screen->size().h();
+  client.base_width = client.base_height = 0;
+  client.max_width = screen_area.width();
+  client.max_height = screen_area.height();
   client.min_aspect_x = client.min_aspect_y =
     client.max_aspect_x = client.max_aspect_y = 1;
   client.win_gravity = NorthWestGravity;
 
-  if (! XGetWMNormalHints(display, client.window, &sizehint, &icccm_mask))
+  if (! XGetWMNormalHints(blackbox->getXDisplay(), client.window,
+                          &sizehint, &icccm_mask))
     return;
 
   client.normal_hint_flags = sizehint.flags;
@@ -1114,641 +959,728 @@ void OpenboxWindow::getWMNormalHints(void) {
  * Gets the MWM hints for the class' contained window.
  * This is used while initializing the window to its first state, and not
  * thereafter.
- * Returns: true if the MWM hints are successfully retreived and applied; false
- * if they are not.
+ * Returns: true if the MWM hints are successfully retreived and applied;
+ * false if they are not.
  */
-void OpenboxWindow::getMWMHints(void) {
+void BlackboxWindow::getMWMHints(void) {
   int format;
   Atom atom_return;
   unsigned long num, len;
+  MwmHints *mwm_hint = 0;
 
-  int ret = XGetWindowProperty(display, client.window,
-                               openbox.getMotifWMHintsAtom(), 0,
+  int ret = XGetWindowProperty(blackbox->getXDisplay(), client.window,
+                               blackbox->getMotifWMHintsAtom(), 0,
                                PropMwmHintsElements, False,
-                               openbox.getMotifWMHintsAtom(), &atom_return,
+                               blackbox->getMotifWMHintsAtom(), &atom_return,
                                &format, &num, &len,
-                               (unsigned char **) &client.mwm_hint);
+                               (unsigned char **) &mwm_hint);
 
-  if (ret != Success || !client.mwm_hint || num != PropMwmHintsElements)
+  if (ret != Success || ! mwm_hint || num != PropMwmHintsElements)
     return;
 
-  if (client.mwm_hint->flags & MwmHintsDecorations) {
-    if (client.mwm_hint->decorations & MwmDecorAll) {
-      decorations.titlebar = decorations.handle = decorations.border =
-        decorations.iconify = decorations.maximize =
-        decorations.close = decorations.menu = True;
+  if (mwm_hint->flags & MwmHintsDecorations) {
+    if (mwm_hint->decorations & MwmDecorAll) {
+      decorations = Decor_Titlebar | Decor_Handle | Decor_Border |
+                    Decor_Iconify | Decor_Maximize | Decor_Close;
     } else {
-      decorations.titlebar = decorations.handle = decorations.border =
-        decorations.iconify = decorations.maximize =
-        decorations.close = decorations.menu = False;
-
-      if (client.mwm_hint->decorations & MwmDecorBorder)
-        decorations.border = True;
-      if (client.mwm_hint->decorations & MwmDecorHandle)
-        decorations.handle = True;
-      if (client.mwm_hint->decorations & MwmDecorTitle)
-        decorations.titlebar = True;
-      if (client.mwm_hint->decorations & MwmDecorMenu)
-        decorations.menu = True;
-      if (client.mwm_hint->decorations & MwmDecorIconify)
-        decorations.iconify = True;
-      if (client.mwm_hint->decorations & MwmDecorMaximize)
-        decorations.maximize = True;
+      decorations = 0;
+
+      if (mwm_hint->decorations & MwmDecorBorder)
+        decorations |= Decor_Border;
+      if (mwm_hint->decorations & MwmDecorHandle)
+        decorations |= Decor_Handle;
+      if (mwm_hint->decorations & MwmDecorTitle)
+        decorations |= Decor_Titlebar;
+      if (mwm_hint->decorations & MwmDecorIconify)
+        decorations |= Decor_Iconify;
+      if (mwm_hint->decorations & MwmDecorMaximize)
+        decorations |= Decor_Maximize;
     }
   }
 
-  if (client.mwm_hint->flags & MwmHintsFunctions) {
-    if (client.mwm_hint->functions & MwmFuncAll) {
-      functions.resize = functions.move = functions.iconify =
-        functions.maximize = functions.close = True;
+  if (mwm_hint->flags & MwmHintsFunctions) {
+    if (mwm_hint->functions & MwmFuncAll) {
+      functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize |
+                  Func_Close;
     } else {
-      functions.resize = functions.move = functions.iconify =
-        functions.maximize = functions.close = False;
-
-      if (client.mwm_hint->functions & MwmFuncResize)
-        functions.resize = True;
-      if (client.mwm_hint->functions & MwmFuncMove)
-        functions.move = True;
-      if (client.mwm_hint->functions & MwmFuncIconify)
-        functions.iconify = True;
-      if (client.mwm_hint->functions & MwmFuncMaximize)
-        functions.maximize = True;
-      if (client.mwm_hint->functions & MwmFuncClose)
-        functions.close = True;
+      functions = 0;
+
+      if (mwm_hint->functions & MwmFuncResize)
+        functions |= Func_Resize;
+      if (mwm_hint->functions & MwmFuncMove)
+        functions |= Func_Move;
+      if (mwm_hint->functions & MwmFuncIconify)
+        functions |= Func_Iconify;
+      if (mwm_hint->functions & MwmFuncMaximize)
+        functions |= Func_Maximize;
+      if (mwm_hint->functions & MwmFuncClose)
+        functions |= Func_Close;
     }
   }
+  XFree(mwm_hint);
 }
 
 
 /*
- * Gets the openbox hints from the class' contained window.
+ * Gets the blackbox hints from the class' contained window.
  * This is used while initializing the window to its first state, and not
  * thereafter.
  * Returns: true if the hints are successfully retreived and applied; false if
  * they are not.
  */
-void OpenboxWindow::getOpenboxHints(void) {
+bool BlackboxWindow::getBlackboxHints(void) {
   int format;
   Atom atom_return;
   unsigned long num, len;
+  BlackboxHints *blackbox_hint = 0;
 
-  int ret = XGetWindowProperty(display, client.window,
-                               openbox.getOpenboxHintsAtom(), 0,
-                               PropOpenboxHintsElements, False,
-                               openbox.getOpenboxHintsAtom(), &atom_return,
+  int ret = XGetWindowProperty(blackbox->getXDisplay(), client.window,
+                               blackbox->getBlackboxHintsAtom(), 0,
+                               PropBlackboxHintsElements, False,
+                               blackbox->getBlackboxHintsAtom(), &atom_return,
                                &format, &num, &len,
-                               (unsigned char **) &client.openbox_hint);
-  if (ret != Success || !client.openbox_hint ||
-      num != PropOpenboxHintsElements)
-    return;
+                               (unsigned char **) &blackbox_hint);
+  if (ret != Success || ! blackbox_hint || num != PropBlackboxHintsElements)
+    return False;
 
-  if (client.openbox_hint->flags & AttribShaded)
-    flags.shaded = (client.openbox_hint->attrib & AttribShaded);
+  if (blackbox_hint->flags & AttribShaded)
+    flags.shaded = (blackbox_hint->attrib & AttribShaded);
 
-  if ((client.openbox_hint->flags & AttribMaxHoriz) &&
-      (client.openbox_hint->flags & AttribMaxVert))
-    flags.maximized = (client.openbox_hint->attrib &
+  if ((blackbox_hint->flags & AttribMaxHoriz) &&
+      (blackbox_hint->flags & AttribMaxVert))
+    flags.maximized = (blackbox_hint->attrib &
                        (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
-  else if (client.openbox_hint->flags & AttribMaxVert)
-    flags.maximized = (client.openbox_hint->attrib & AttribMaxVert) ? 2 : 0;
-  else if (client.openbox_hint->flags & AttribMaxHoriz)
-    flags.maximized = (client.openbox_hint->attrib & AttribMaxHoriz) ? 3 : 0;
+  else if (blackbox_hint->flags & AttribMaxVert)
+    flags.maximized = (blackbox_hint->attrib & AttribMaxVert) ? 2 : 0;
+  else if (blackbox_hint->flags & AttribMaxHoriz)
+    flags.maximized = (blackbox_hint->attrib & AttribMaxHoriz) ? 3 : 0;
 
-  if (client.openbox_hint->flags & AttribOmnipresent)
-    flags.stuck = (client.openbox_hint->attrib & AttribOmnipresent);
+  if (blackbox_hint->flags & AttribOmnipresent)
+    flags.stuck = (blackbox_hint->attrib & AttribOmnipresent);
 
-  if (client.openbox_hint->flags & AttribWorkspace)
-    workspace_number = client.openbox_hint->workspace;
+  if (blackbox_hint->flags & AttribWorkspace)
+    blackbox_attrib.workspace = blackbox_hint->workspace;
 
-  // if (client.openbox_hint->flags & AttribStack)
-  //   don't yet have always on top/bottom for openbox yet... working
+  // if (blackbox_hint->flags & AttribStack)
+  //   don't yet have always on top/bottom for blackbox yet... working
   //   on that
 
-  if (client.openbox_hint->flags & AttribDecoration) {
-    switch (client.openbox_hint->decoration) {
+  if (blackbox_hint->flags & AttribDecoration) {
+    switch (blackbox_hint->decoration) {
     case DecorNone:
-      decorations.titlebar = decorations.border = decorations.handle =
-        decorations.iconify = decorations.maximize =
-        decorations.menu = False;
-      functions.resize = functions.move = functions.iconify =
-        functions.maximize = False;
+      // clear all decorations except close
+      decorations &= Decor_Close;
+      // clear all functions except close
+      functions &= Func_Close;
 
       break;
 
     case DecorTiny:
-      decorations.titlebar = decorations.iconify = decorations.menu =
-        functions.move = functions.iconify = True;
-      decorations.border = decorations.handle = decorations.maximize =
-        functions.resize = functions.maximize = False;
+      decorations |= Decor_Titlebar | Decor_Iconify;
+      decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize);
+      functions |= Func_Move | Func_Iconify;
+      functions &= ~(Func_Resize | Func_Maximize);
 
       break;
 
     case DecorTool:
-      decorations.titlebar = decorations.menu = functions.move = True;
-      decorations.iconify = decorations.border = decorations.handle =
-        decorations.maximize = functions.resize = functions.maximize =
-        functions.iconify = False;
+      decorations |= Decor_Titlebar;
+      decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle);
+      functions |= Func_Move;
+      functions &= ~(Func_Resize | Func_Maximize | Func_Iconify);
 
       break;
 
     case DecorNormal:
     default:
-      decorations.titlebar = decorations.border = decorations.handle =
-        decorations.iconify = decorations.maximize =
-        decorations.menu = True;
-      functions.resize = functions.move = functions.iconify =
-        functions.maximize = True;
+      decorations |= Decor_Titlebar | Decor_Border | Decor_Handle |
+                     Decor_Iconify | Decor_Maximize;
+      functions |= Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
 
       break;
     }
 
     reconfigure();
   }
+  XFree(blackbox_hint);
+  return True;
+}
+
+
+void BlackboxWindow::getTransientInfo(void) {
+  if (client.transient_for &&
+      client.transient_for != (BlackboxWindow *) ~0ul) {
+    // the transient for hint was removed, so we need to tell our
+    // previous transient_for that we are going away
+    client.transient_for->client.transientList.remove(this);
+  }
+
+  // we have no transient_for until we find a new one
+  client.transient_for = 0;
+
+  Window trans_for;
+  if (!XGetTransientForHint(blackbox->getXDisplay(), client.window,
+                            &trans_for)) {
+    // transient_for hint not set
+    return;
+  }
+
+  if (trans_for == client.window) {
+    // wierd client... treat this window as a normal window
+    return;
+  }
+
+  if (trans_for == None || trans_for == screen->getRootWindow()) {
+    // this is an undocumented interpretation of the ICCCM. a transient
+    // associated with None/Root/itself is assumed to be a modal root
+    // transient.  we don't support the concept of a global transient,
+    // so we just associate this transient with nothing, and perhaps
+    // we will add support later for global modality.
+    client.transient_for = (BlackboxWindow *) ~0ul;
+    flags.modal = True;
+    return;
+  }
+
+  client.transient_for = blackbox->searchWindow(trans_for);
+  if (! client.transient_for &&
+      client.window_group && trans_for == client.window_group) {
+    // no direct transient_for, perhaps this is a group transient?
+    BWindowGroup *group = blackbox->searchGroup(client.window_group);
+    if (group) client.transient_for = group->find(screen);
+  }
+
+  if (! client.transient_for || client.transient_for == this) {
+    // no transient_for found, or we have a wierd client that wants to be
+    // a transient for itself, so we treat this window as a normal window
+    client.transient_for = (BlackboxWindow*) 0;
+    return;
+  }
+
+  // register ourselves with our new transient_for
+  client.transient_for->client.transientList.push_back(this);
+  flags.stuck = client.transient_for->flags.stuck;
+}
+
+
+BlackboxWindow *BlackboxWindow::getTransientFor(void) const {
+  if (client.transient_for &&
+      client.transient_for != (BlackboxWindow*) ~0ul)
+    return client.transient_for;
+  return 0;
 }
 
 
-void OpenboxWindow::configure(int dx, int dy,
-                              unsigned int dw, unsigned int dh) {
-  Bool send_event = (frame.x != dx || frame.y != dy);
+void BlackboxWindow::configure(int dx, int dy,
+                               unsigned int dw, unsigned int dh) {
+  bool send_event = (frame.rect.x() != dx || frame.rect.y() != dy);
 
-  if ((dw != frame.width) || (dh != frame.height)) {
-    if ((((signed) frame.width) + dx) < 0) dx = 0;
-    if ((((signed) frame.height) + dy) < 0) dy = 0;
+  if ((dw != frame.rect.width()) || (dh != frame.rect.height())) {
+    frame.rect.setRect(dx, dy, dw, dh);
+    frame.inside_w = frame.rect.width() - (frame.border_w * 2);
+    frame.inside_h = frame.rect.height() - (frame.border_w * 2);
 
-    frame.x = dx;
-    frame.y = dy;
-    frame.width = dw;
-    frame.height = dh;
+    if (frame.rect.right() <= 0 || frame.rect.bottom() <= 0)
+      frame.rect.setPos(0, 0);
 
-    downsize();
+    client.rect.setCoords(frame.rect.left() + frame.margin.left,
+                          frame.rect.top() + frame.margin.top,
+                          frame.rect.right() - frame.margin.right,
+                          frame.rect.bottom() - frame.margin.bottom);
 
 #ifdef    SHAPE
-    if (openbox.hasShapeExtensions() && flags.shaped) {
-      XShapeCombineShape(display, frame.window, ShapeBounding,
-                         frame.mwm_border_w, frame.y_border +
-                         frame.mwm_border_w, client.window,
-                         ShapeBounding, ShapeSet);
-
-      int num = 1;
-      XRectangle xrect[2];
-      xrect[0].x = xrect[0].y = 0;
-      xrect[0].width = frame.width;
-      xrect[0].height = frame.y_border;
-
-      if (decorations.handle) {
-        xrect[1].x = 0;
-        xrect[1].y = frame.y_handle;
-        xrect[1].width = frame.width;
-        xrect[1].height = frame.handle_h + frame.border_w;
-        num++;
-      }
-
-      XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
-                              xrect, num, ShapeUnion, Unsorted);
+    if (blackbox->hasShapeExtensions() && flags.shaped) {
+      configureShape();
     }
 #endif // SHAPE
 
-    XMoveWindow(display, frame.window, frame.x, frame.y);
-
-    setFocusFlag(flags.focused);
     positionWindows();
     decorate();
+    setFocusFlag(flags.focused);
+    redrawAllButtons();
   } else {
-    frame.x = dx;
-    frame.y = dy;
+    frame.rect.setPos(dx, dy);
 
-    XMoveWindow(display, frame.window, frame.x, frame.y);
+    XMoveWindow(blackbox->getXDisplay(), frame.window,
+                frame.rect.x(), frame.rect.y());
 
     if (! flags.moving) send_event = True;
   }
 
   if (send_event && ! flags.moving) {
-    client.x = dx + frame.mwm_border_w + frame.border_w;
-    client.y = dy + frame.y_border + frame.mwm_border_w +
-      frame.border_w;
+    client.rect.setPos(frame.rect.left() + frame.margin.left,
+                       frame.rect.top() + frame.margin.top);
 
     XEvent event;
     event.type = ConfigureNotify;
 
-    event.xconfigure.display = display;
+    event.xconfigure.display = blackbox->getXDisplay();
     event.xconfigure.event = client.window;
     event.xconfigure.window = client.window;
-    event.xconfigure.x = client.x;
-    event.xconfigure.y = client.y;
-    event.xconfigure.width = client.width;
-    event.xconfigure.height = client.height;
+    event.xconfigure.x = client.rect.x();
+    event.xconfigure.y = client.rect.y();
+    event.xconfigure.width = client.rect.width();
+    event.xconfigure.height = client.rect.height();
     event.xconfigure.border_width = client.old_bw;
     event.xconfigure.above = frame.window;
     event.xconfigure.override_redirect = False;
 
-    XSendEvent(display, client.window, True, NoEventMask, &event);
+    XSendEvent(blackbox->getXDisplay(), client.window, True,
+               NoEventMask, &event);
 
     screen->updateNetizenConfigNotify(&event);
   }
 }
 
 
-bool OpenboxWindow::setInputFocus(void) {
-  if (((signed) (frame.x + frame.width)) < 0) {
-    if (((signed) (frame.y + frame.y_border)) < 0)
-      configure(frame.border_w, frame.border_w, frame.width, frame.height);
-    else if (frame.y > (signed) screen->size().h())
-      configure(frame.border_w, screen->size().h() - frame.height,
-                frame.width, frame.height);
-    else
-      configure(frame.border_w, frame.y + frame.border_w,
-                frame.width, frame.height);
-  } else if (frame.x > (signed) screen->size().w()) {
-    if (((signed) (frame.y + frame.y_border)) < 0)
-      configure(screen->size().w() - frame.width, frame.border_w,
-                frame.width, frame.height);
-    else if (frame.y > (signed) screen->size().h())
-      configure(screen->size().w() - frame.width,
-                screen->size().h() - frame.height, frame.width, frame.height);
-    else
-      configure(screen->size().w() - frame.width,
-                frame.y + frame.border_w, frame.width, frame.height);
-  }
-
-  openbox.grab();
-  if (! validateClient()) return False;
-
-  bool ret = false;
-
-  if (client.transient && flags.modal) {
-    ret = client.transient->setInputFocus();
-  } else if (! flags.focused) {
-    if (focus_mode == F_LocallyActive || focus_mode == F_Passive) {
-      XSetInputFocus(display, client.window,
-                     RevertToPointerRoot, CurrentTime);
-      openbox.focusWindow(this);
-
-      if (flags.send_focus_message) {
-        XEvent ce;
-        ce.xclient.type = ClientMessage;
-        ce.xclient.message_type = openbox.getWMProtocolsAtom();
-        ce.xclient.display = display;
-        ce.xclient.window = client.window;
-        ce.xclient.format = 32;
-        ce.xclient.data.l[0] = openbox.getWMTakeFocusAtom();
-        ce.xclient.data.l[1] = openbox.getLastTime();
-        ce.xclient.data.l[2] = 0l;
-        ce.xclient.data.l[3] = 0l;
-        ce.xclient.data.l[4] = 0l;
-        XSendEvent(display, client.window, False, NoEventMask, &ce);
-      }
+#ifdef SHAPE
+void BlackboxWindow::configureShape(void) {
+  XShapeCombineShape(blackbox->getXDisplay(), frame.window, ShapeBounding,
+                     frame.margin.left - frame.border_w,
+                     frame.margin.top - frame.border_w,
+                     client.window, ShapeBounding, ShapeSet);
 
-      if (screen->sloppyFocus() && screen->autoRaise())
-        timer->start();
+  int num = 0;
+  XRectangle xrect[2];
 
-      ret = true;
-    }
+  if (decorations & Decor_Titlebar) {
+    xrect[0].x = xrect[0].y = -frame.border_w;
+    xrect[0].width = frame.rect.width();
+    xrect[0].height = frame.title_h + (frame.border_w * 2);
+    ++num;
   }
 
-  openbox.ungrab();
+  if (decorations & Decor_Handle) {
+    xrect[1].x = -frame.border_w;
+    xrect[1].y = frame.rect.height() - frame.margin.bottom +
+                 frame.mwm_border_w - frame.border_w;
+    xrect[1].width = frame.rect.width();
+    xrect[1].height = frame.handle_h + (frame.border_w * 2);
+    ++num;
+  }
 
-  return ret;
+  XShapeCombineRectangles(blackbox->getXDisplay(), frame.window,
+                          ShapeBounding, 0, 0, xrect, num,
+                          ShapeUnion, Unsorted);
 }
+#endif // SHAPE
 
 
-void OpenboxWindow::iconify(void) {
-  if (flags.iconic) return;
+bool BlackboxWindow::setInputFocus(void) {
+  if (flags.focused) return True;
 
-  if (flags.moving)
-    endMove();
+  if (! client.rect.intersects(screen->getRect())) {
+    // client is outside the screen, move it to the center
+    configure((screen->getWidth() - frame.rect.width()) / 2,
+              (screen->getHeight() - frame.rect.height()) / 2,
+              frame.rect.width(), frame.rect.height());
+  }
+
+  if (client.transientList.size() > 0) {
+    // transfer focus to any modal transients
+    BlackboxWindowList::iterator it, end = client.transientList.end();
+    for (it = client.transientList.begin(); it != end; ++it) {
+      if ((*it)->flags.modal) return (*it)->setInputFocus();
+    }
+  }
+
+  bool ret = True;
+  if (focus_mode == F_LocallyActive || focus_mode == F_Passive) {
+    XSetInputFocus(blackbox->getXDisplay(), client.window,
+                   RevertToPointerRoot, CurrentTime);
+
+    blackbox->setFocusedWindow(this);
+  } else {
+    /* we could set the focus to none, since the window doesn't accept focus,
+     * but we shouldn't set focus to nothing since this would surely make
+     * someone angry
+     */
+    ret = False;
+  }
+
+  if (flags.send_focus_message) {
+    XEvent ce;
+    ce.xclient.type = ClientMessage;
+    ce.xclient.message_type = blackbox->getWMProtocolsAtom();
+    ce.xclient.display = blackbox->getXDisplay();
+    ce.xclient.window = client.window;
+    ce.xclient.format = 32;
+    ce.xclient.data.l[0] = blackbox->getWMTakeFocusAtom();
+    ce.xclient.data.l[1] = blackbox->getLastTime();
+    ce.xclient.data.l[2] = 0l;
+    ce.xclient.data.l[3] = 0l;
+    ce.xclient.data.l[4] = 0l;
+    XSendEvent(blackbox->getXDisplay(), client.window, False,
+               NoEventMask, &ce);
+  }
+
+  return ret;
+}
+
+
+void BlackboxWindow::iconify(void) {
+  if (flags.iconic) return;
 
   if (windowmenu) windowmenu->hide();
 
   setState(IconicState);
 
-  XSelectInput(display, client.window, NoEventMask);
-  XUnmapWindow(display, client.window);
-  XSelectInput(display, client.window,
-               PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
-
-  XUnmapWindow(display, frame.window);
+  /*
+   * we don't want this XUnmapWindow call to generate an UnmapNotify event, so
+   * we need to clear the event mask on client.window for a split second.
+   * HOWEVER, since X11 is asynchronous, the window could be destroyed in that
+   * split second, leaving us with a ghost window... so, we need to do this
+   * while the X server is grabbed
+   */
+  XGrabServer(blackbox->getXDisplay());
+  XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
+  XUnmapWindow(blackbox->getXDisplay(), client.window);
+  XSelectInput(blackbox->getXDisplay(), client.window,
+               PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
+  XUngrabServer(blackbox->getXDisplay());
+
+  XUnmapWindow(blackbox->getXDisplay(), frame.window);
   flags.visible = False;
   flags.iconic = True;
 
-  screen->getWorkspace(workspace_number)->removeWindow(this);
+  screen->getWorkspace(blackbox_attrib.workspace)->removeWindow(this);
 
-  if (flags.transient && client.transient_for &&
-      !client.transient_for->flags.iconic) {
-    client.transient_for->iconify();
+  if (isTransient()) {
+    if (client.transient_for != (BlackboxWindow *) ~0ul &&
+        ! client.transient_for->flags.iconic) {
+      // iconify our transient_for
+      client.transient_for->iconify();
+    }
   }
+
   screen->addIcon(this);
 
-  if (client.transient && !client.transient->flags.iconic) {
-    client.transient->iconify();
+  if (client.transientList.size() > 0) {
+    // iconify all transients
+    BlackboxWindowList::iterator it, end = client.transientList.end();
+    for (it = client.transientList.begin(); it != end; ++it) {
+      if (! (*it)->flags.iconic) (*it)->iconify();
+    }
   }
 }
 
 
-void OpenboxWindow::deiconify(bool reassoc, bool raise, bool initial) {
-  if (flags.iconic || reassoc)
-    screen->reassociateWindow(this, -1, False);
-  else if (workspace_number != screen->getCurrentWorkspace()->getWorkspaceID())
-    return;
-
+void BlackboxWindow::show(void) {
   setState(NormalState);
 
-  XSelectInput(display, client.window, NoEventMask);
-  XMapWindow(display, client.window);
-  XSelectInput(display, client.window,
-               PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
+  XMapWindow(blackbox->getXDisplay(), client.window);
+  XMapSubwindows(blackbox->getXDisplay(), frame.window);
+  XMapWindow(blackbox->getXDisplay(), frame.window);
 
-  XMapSubwindows(display, frame.window);
-  XMapWindow(display, frame.window);
+  flags.visible = True;
+  flags.iconic = False;
+}
 
-  // if we're using the click to place placement type, then immediately
-  // after the window is mapped, we need to start interactively moving it
-  if (initial && place_window &&
-      screen->placementPolicy() == BScreen::ClickMousePlacement) {
-    int x, y, rx, ry;
-    Window c, r;
-    unsigned int m;
-    XQueryPointer(openbox.getXDisplay(), screen->getRootWindow(),
-                  &r, &c, &rx, &ry, &x, &y, &m);
-    startMove(rx, ry);
-  }
 
-  if (flags.iconic && screen->focusNew()) setInputFocus();
+void BlackboxWindow::deiconify(bool reassoc, bool raise) {
+  if (flags.iconic || reassoc)
+    screen->reassociateWindow(this, BSENTINEL, False);
+  else if (blackbox_attrib.workspace != screen->getCurrentWorkspace()->getID())
+    return;
 
-  flags.visible = True;
-  flags.iconic = False;
+  show();
 
-  if (reassoc && client.transient) client.transient->deiconify(True, False);
+  // reassociate and deiconify all transients
+  if (reassoc && client.transientList.size() > 0) {
+    BlackboxWindowList::iterator it, end = client.transientList.end();
+    for (it = client.transientList.begin(); it != end; ++it) {
+      (*it)->deiconify(True, False);
+    }
+  }
 
   if (raise)
-    screen->getWorkspace(workspace_number)->raiseWindow(this);
+    screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
 }
 
 
-void OpenboxWindow::close(void) {
+void BlackboxWindow::close(void) {
   XEvent ce;
   ce.xclient.type = ClientMessage;
-  ce.xclient.message_type = openbox.getWMProtocolsAtom();
-  ce.xclient.display = display;
+  ce.xclient.message_type = blackbox->getWMProtocolsAtom();
+  ce.xclient.display = blackbox->getXDisplay();
   ce.xclient.window = client.window;
   ce.xclient.format = 32;
-  ce.xclient.data.l[0] = openbox.getWMDeleteAtom();
+  ce.xclient.data.l[0] = blackbox->getWMDeleteAtom();
   ce.xclient.data.l[1] = CurrentTime;
   ce.xclient.data.l[2] = 0l;
   ce.xclient.data.l[3] = 0l;
   ce.xclient.data.l[4] = 0l;
-  XSendEvent(display, client.window, False, NoEventMask, &ce);
+  XSendEvent(blackbox->getXDisplay(), client.window, False, NoEventMask, &ce);
 }
 
 
-void OpenboxWindow::withdraw(void) {
-  if (flags.moving)
-    endMove();
+void BlackboxWindow::withdraw(void) {
+  setState(current_state);
 
   flags.visible = False;
   flags.iconic = False;
 
-  XUnmapWindow(display, frame.window);
+  XUnmapWindow(blackbox->getXDisplay(), frame.window);
 
-  XSelectInput(display, client.window, NoEventMask);
-  XUnmapWindow(display, client.window);
-  XSelectInput(display, client.window,
-               PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
+  XGrabServer(blackbox->getXDisplay());
+  XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
+  XUnmapWindow(blackbox->getXDisplay(), client.window);
+  XSelectInput(blackbox->getXDisplay(), client.window,
+               PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
+    XUngrabServer(blackbox->getXDisplay());
 
   if (windowmenu) windowmenu->hide();
 }
 
 
-void OpenboxWindow::maximize(unsigned int button) {
-  if (flags.moving)
-    endMove();
-
+void BlackboxWindow::maximize(unsigned int button) {
   // handle case where menu is open then the max button is used instead
   if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
 
   if (flags.maximized) {
     flags.maximized = 0;
 
-    openbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert);
-    openbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert);
+    blackbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert);
+    blackbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert);
 
     // when a resize is begun, maximize(0) is called to clear any maximization
     // flags currently set.  Otherwise it still thinks it is maximized.
     // so we do not need to call configure() because resizing will handle it
     if (!flags.resizing)
-      configure(openbox_attrib.premax_x, openbox_attrib.premax_y,
-                openbox_attrib.premax_w, openbox_attrib.premax_h);
+      configure(blackbox_attrib.premax_x, blackbox_attrib.premax_y,
+                blackbox_attrib.premax_w, blackbox_attrib.premax_h);
 
-    openbox_attrib.premax_x = openbox_attrib.premax_y = 0;
-    openbox_attrib.premax_w = openbox_attrib.premax_h = 0;
+    blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0;
+    blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0;
 
-    redrawMaximizeButton(flags.maximized);
+    redrawAllButtons();
     setState(current_state);
     return;
   }
 
-  openbox_attrib.premax_x = frame.x;
-  openbox_attrib.premax_y = frame.y;
-  openbox_attrib.premax_w = frame.width;
-  openbox_attrib.premax_h = frame.height;
-
-  Rect space = screen->availableArea();
-  unsigned int dw = space.w(),
-  dh = space.h();
-  dw -= frame.border_w * 2;
-  dw -= frame.mwm_border_w * 2;
-  dw -= client.base_width;
+  blackbox_attrib.premax_x = frame.rect.x();
+  blackbox_attrib.premax_y = frame.rect.y();
+  blackbox_attrib.premax_w = frame.rect.width();
+  blackbox_attrib.premax_h = frame.rect.height();
 
-  dh -= frame.border_w * 2;
-  dh -= frame.mwm_border_w * 2;
-  dh -= ((frame.handle_h + frame.border_w) * decorations.handle);
-  dh -= client.base_height;
-  dh -= frame.y_border;
-
-  if (dw < client.min_width) dw = client.min_width;
-  if (dh < client.min_height) dh = client.min_height;
-  if (dw > client.max_width) dw = client.max_width;
-  if (dh > client.max_height) dh = client.max_height;
-
-  dw -= (dw % client.width_inc);
-  dw += client.base_width;
-  dw += frame.mwm_border_w * 2;
-
-  dh -= (dh % client.height_inc);
-  dh += client.base_height;
-  dh += frame.y_border;
-  dh += ((frame.handle_h + frame.border_w) * decorations.handle);
-  dh += frame.mwm_border_w * 2;
-
-  int dx = space.x() + ((space.w() - dw) / 2) - frame.border_w,
-  dy = space.y() + ((space.h() - dh) / 2) - frame.border_w;
+  const Rect &screen_area = screen->availableArea();
+  frame.changing = screen_area;
+  constrain(TopLeft);
 
   switch(button) {
   case 1:
-    openbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert;
-    openbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert;
+    blackbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert;
+    blackbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert;
     break;
 
   case 2:
-    openbox_attrib.flags |= AttribMaxVert;
-    openbox_attrib.attrib |= AttribMaxVert;
+    blackbox_attrib.flags |= AttribMaxVert;
+    blackbox_attrib.attrib |= AttribMaxVert;
 
-    dw = frame.width;
-    dx = frame.x;
+    frame.changing.setX(frame.rect.x());
+    frame.changing.setWidth(frame.rect.width());
     break;
 
   case 3:
-    openbox_attrib.flags |= AttribMaxHoriz;
-    openbox_attrib.attrib |= AttribMaxHoriz;
+    blackbox_attrib.flags |= AttribMaxHoriz;
+    blackbox_attrib.attrib |= AttribMaxHoriz;
 
-    dh = frame.height;
-    dy = frame.y;
+    frame.changing.setY(frame.rect.y());
+    frame.changing.setHeight(frame.rect.height());
     break;
   }
 
   if (flags.shaded) {
-    openbox_attrib.flags ^= AttribShaded;
-    openbox_attrib.attrib ^= AttribShaded;
+    blackbox_attrib.flags ^= AttribShaded;
+    blackbox_attrib.attrib ^= AttribShaded;
     flags.shaded = False;
   }
 
   flags.maximized = button;
 
-  configure(dx, dy, dw, dh);
-  screen->getWorkspace(workspace_number)->raiseWindow(this);
-  redrawMaximizeButton(flags.maximized);
+  configure(frame.changing.x(), frame.changing.y(),
+            frame.changing.width(), frame.changing.height());
+  screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
+  redrawAllButtons();
   setState(current_state);
 }
 
 
-void OpenboxWindow::setWorkspace(int n) {
-  ASSERT(n < screen->getWorkspaceCount());
-  workspace_number = n;
+// re-maximizes the window to take into account availableArea changes
+void BlackboxWindow::remaximize(void) {
+  // save the original dimensions because maximize will wipe them out
+  int premax_x = blackbox_attrib.premax_x,
+    premax_y = blackbox_attrib.premax_y,
+    premax_w = blackbox_attrib.premax_w,
+    premax_h = blackbox_attrib.premax_h;
 
-  openbox_attrib.flags |= AttribWorkspace;
-  openbox_attrib.workspace = workspace_number;
+  unsigned int button = flags.maximized;
+  flags.maximized = 0; // trick maximize() into working
+  maximize(button);
+
+  // restore saved values
+  blackbox_attrib.premax_x = premax_x;
+  blackbox_attrib.premax_y = premax_y;
+  blackbox_attrib.premax_w = premax_w;
+  blackbox_attrib.premax_h = premax_h;
 }
 
 
-void OpenboxWindow::shade(void) {
-  if (!decorations.titlebar)
+void BlackboxWindow::setWorkspace(unsigned int n) {
+  blackbox_attrib.flags |= AttribWorkspace;
+  blackbox_attrib.workspace = n;
+}
+
+
+void BlackboxWindow::shade(void) {
+  if (! (decorations & Decor_Titlebar))
     return;
 
   if (flags.shaded) {
-    XResizeWindow(display, frame.window, frame.width, frame.height);
+    XResizeWindow(blackbox->getXDisplay(), frame.window,
+                  frame.inside_w, frame.inside_h);
     flags.shaded = False;
-    openbox_attrib.flags ^= AttribShaded;
-    openbox_attrib.attrib ^= AttribShaded;
+    blackbox_attrib.flags ^= AttribShaded;
+    blackbox_attrib.attrib ^= AttribShaded;
 
     setState(NormalState);
+
+    // set the frame rect to the normal size
+    frame.rect.setHeight(client.rect.height() + frame.margin.top +
+                         frame.margin.bottom);
   } else {
-    XResizeWindow(display, frame.window, frame.width, frame.title_h);
+    XResizeWindow(blackbox->getXDisplay(), frame.window,
+                  frame.inside_w, frame.title_h);
     flags.shaded = True;
-    openbox_attrib.flags |= AttribShaded;
-    openbox_attrib.attrib |= AttribShaded;
+    blackbox_attrib.flags |= AttribShaded;
+    blackbox_attrib.attrib |= AttribShaded;
 
     setState(IconicState);
+
+    // set the frame rect to the shaded size
+    frame.rect.setHeight(frame.title_h + (frame.border_w * 2));
   }
 }
 
 
-void OpenboxWindow::stick(void) {
+void BlackboxWindow::stick(void) {
   if (flags.stuck) {
-    openbox_attrib.flags ^= AttribOmnipresent;
-    openbox_attrib.attrib ^= AttribOmnipresent;
+    blackbox_attrib.flags ^= AttribOmnipresent;
+    blackbox_attrib.attrib ^= AttribOmnipresent;
 
     flags.stuck = False;
 
     if (! flags.iconic)
-      screen->reassociateWindow(this, -1, True);
+      screen->reassociateWindow(this, BSENTINEL, True);
 
     setState(current_state);
   } else {
     flags.stuck = True;
 
-    openbox_attrib.flags |= AttribOmnipresent;
-    openbox_attrib.attrib |= AttribOmnipresent;
+    blackbox_attrib.flags |= AttribOmnipresent;
+    blackbox_attrib.attrib |= AttribOmnipresent;
 
     setState(current_state);
   }
 }
 
 
-void OpenboxWindow::setFocusFlag(Bool focus) {
+void BlackboxWindow::setFocusFlag(bool focus) {
   flags.focused = focus;
 
-  if (decorations.titlebar) {
+  if (decorations & Decor_Titlebar) {
     if (flags.focused) {
       if (frame.ftitle)
-        XSetWindowBackgroundPixmap(display, frame.title, frame.ftitle);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.title, frame.ftitle);
       else
-        XSetWindowBackground(display, frame.title, frame.ftitle_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.title, frame.ftitle_pixel);
     } else {
       if (frame.utitle)
-        XSetWindowBackgroundPixmap(display, frame.title, frame.utitle);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.title, frame.utitle);
       else
-        XSetWindowBackground(display, frame.title, frame.utitle_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.title, frame.utitle_pixel);
     }
-    XClearWindow(display, frame.title);
+    XClearWindow(blackbox->getXDisplay(), frame.title);
 
     redrawLabel();
     redrawAllButtons();
   }
 
-  if (decorations.handle) {
+  if (decorations & Decor_Handle) {
     if (flags.focused) {
       if (frame.fhandle)
-        XSetWindowBackgroundPixmap(display, frame.handle, frame.fhandle);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.handle, frame.fhandle);
       else
-        XSetWindowBackground(display, frame.handle, frame.fhandle_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.handle, frame.fhandle_pixel);
 
       if (frame.fgrip) {
-        XSetWindowBackgroundPixmap(display, frame.right_grip, frame.fgrip);
-        XSetWindowBackgroundPixmap(display, frame.left_grip, frame.fgrip);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.left_grip, frame.fgrip);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.right_grip, frame.fgrip);
       } else {
-        XSetWindowBackground(display, frame.right_grip, frame.fgrip_pixel);
-        XSetWindowBackground(display, frame.left_grip, frame.fgrip_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.left_grip, frame.fgrip_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.right_grip, frame.fgrip_pixel);
       }
     } else {
       if (frame.uhandle)
-        XSetWindowBackgroundPixmap(display, frame.handle, frame.uhandle);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.handle, frame.uhandle);
       else
-        XSetWindowBackground(display, frame.handle, frame.uhandle_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.handle, frame.uhandle_pixel);
 
       if (frame.ugrip) {
-        XSetWindowBackgroundPixmap(display, frame.right_grip, frame.ugrip);
-        XSetWindowBackgroundPixmap(display, frame.left_grip, frame.ugrip);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.left_grip, frame.ugrip);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.right_grip, frame.ugrip);
       } else {
-        XSetWindowBackground(display, frame.right_grip, frame.ugrip_pixel);
-        XSetWindowBackground(display, frame.left_grip, frame.ugrip_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.left_grip, frame.ugrip_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.right_grip, frame.ugrip_pixel);
       }
     }
-    XClearWindow(display, frame.handle);
-    XClearWindow(display, frame.right_grip);
-    XClearWindow(display, frame.left_grip);
+    XClearWindow(blackbox->getXDisplay(), frame.handle);
+    XClearWindow(blackbox->getXDisplay(), frame.left_grip);
+    XClearWindow(blackbox->getXDisplay(), frame.right_grip);
   }
 
-  if (decorations.border) {
+  if (decorations & Decor_Border) {
     if (flags.focused)
-      XSetWindowBorder(display, frame.plate, frame.fborder_pixel);
+      XSetWindowBorder(blackbox->getXDisplay(),
+                       frame.plate, frame.fborder_pixel);
     else
-      XSetWindowBorder(display, frame.plate, frame.uborder_pixel);
+      XSetWindowBorder(blackbox->getXDisplay(),
+                       frame.plate, frame.uborder_pixel);
   }
 
-  if (screen->sloppyFocus() && screen->autoRaise() && timer->isTiming())
-    timer->stop();
+  if (screen->isSloppyFocus() && screen->doAutoRaise()) {
+    if (isFocused()) timer->start();
+    else timer->stop();
+  }
 
+  if (isFocused())
+    blackbox->setFocusedWindow(this);
 }
 
 
-void OpenboxWindow::installColormap(Bool install) {
-  openbox.grab();
-  if (! validateClient()) return;
-
+void BlackboxWindow::installColormap(bool install) {
   int i = 0, ncmap = 0;
-  Colormap *cmaps = XListInstalledColormaps(display, client.window, &ncmap);
+  Colormap *cmaps = XListInstalledColormaps(blackbox->getXDisplay(),
+                                            client.window, &ncmap);
   XWindowAttributes wattrib;
   if (cmaps) {
-    if (XGetWindowAttributes(display, client.window, &wattrib)) {
+    if (XGetWindowAttributes(blackbox->getXDisplay(),
+                             client.window, &wattrib)) {
       if (install) {
         // install the window's colormap
         for (i = 0; i < ncmap; i++) {
@@ -1758,61 +1690,59 @@ void OpenboxWindow::installColormap(Bool install) {
         }
         // otherwise, install the window's colormap
         if (install)
-          XInstallColormap(display, wattrib.colormap);
+          XInstallColormap(blackbox->getXDisplay(), wattrib.colormap);
       } else {
         // uninstall the window's colormap
         for (i = 0; i < ncmap; i++) {
           if (*(cmaps + i) == wattrib.colormap)
             // we found the colormap to uninstall
-            XUninstallColormap(display, wattrib.colormap);
+            XUninstallColormap(blackbox->getXDisplay(), wattrib.colormap);
         }
       }
     }
 
     XFree(cmaps);
   }
-
-  openbox.ungrab();
 }
 
 
-void OpenboxWindow::setState(unsigned long new_state) {
+void BlackboxWindow::setState(unsigned long new_state) {
   current_state = new_state;
 
   unsigned long state[2];
-  state[0] = (unsigned long) current_state;
-  state[1] = (unsigned long) None;
-  XChangeProperty(display, client.window, openbox.getWMStateAtom(),
-                  openbox.getWMStateAtom(), 32, PropModeReplace,
-                  (unsigned char *) state, 2);
+  state[0] = current_state;
+  state[1] = None;
+  XChangeProperty(blackbox->getXDisplay(), client.window,
+                  blackbox->getWMStateAtom(), blackbox->getWMStateAtom(), 32,
+                  PropModeReplace, (unsigned char *) state, 2);
 
-  XChangeProperty(display, client.window,
-                  openbox.getOpenboxAttributesAtom(),
-                  openbox.getOpenboxAttributesAtom(), 32, PropModeReplace,
-                  (unsigned char *) &openbox_attrib,
-                  PropOpenboxAttributesElements);
+  XChangeProperty(blackbox->getXDisplay(), client.window,
+                  blackbox->getBlackboxAttributesAtom(),
+                  blackbox->getBlackboxAttributesAtom(), 32, PropModeReplace,
+                  (unsigned char *) &blackbox_attrib,
+                  PropBlackboxAttributesElements);
 }
 
 
-Bool OpenboxWindow::getState(void) {
+bool BlackboxWindow::getState(void) {
   current_state = 0;
 
   Atom atom_return;
-  Bool ret = False;
+  bool ret = False;
   int foo;
   unsigned long *state, ulfoo, nitems;
 
-  if ((XGetWindowProperty(display, client.window, openbox.getWMStateAtom(),
-                          0l, 2l, False, openbox.getWMStateAtom(),
+  if ((XGetWindowProperty(blackbox->getXDisplay(), client.window,
+                          blackbox->getWMStateAtom(),
+                          0l, 2l, False, blackbox->getWMStateAtom(),
                           &atom_return, &foo, &nitems, &ulfoo,
                           (unsigned char **) &state) != Success) ||
       (! state)) {
-    openbox.ungrab();
     return False;
   }
 
   if (nitems >= 1) {
-    current_state = (unsigned long) state[0];
+    current_state = static_cast<unsigned long>(state[0]);
 
     ret = True;
   }
@@ -1823,94 +1753,25 @@ Bool OpenboxWindow::getState(void) {
 }
 
 
-void OpenboxWindow::setGravityOffsets(void) {
-  // x coordinates for each gravity type
-  const int x_west = client.x;
-  const int x_east = client.x + client.width - frame.width;
-  const int x_center = client.x + client.width - frame.width/2;
-  // y coordinates for each gravity type
-  const int y_north = client.y;
-  const int y_south = client.y + client.height - frame.height;
-  const int y_center = client.y + client.height - frame.height/2;
-
-  switch (client.win_gravity) {
-  case NorthWestGravity:
-  default:
-    frame.x = x_west;
-    frame.y = y_north;
-    break;
-  case NorthGravity:
-    frame.x = x_center;
-    frame.y = y_north;
-    break;
-  case NorthEastGravity:
-    frame.x = x_east;
-    frame.y = y_north;
-    break;
-  case SouthWestGravity:
-    frame.x = x_west;
-    frame.y = y_south;
-    break;
-  case SouthGravity:
-    frame.x = x_center;
-    frame.y = y_south;
-    break;
-  case SouthEastGravity:
-    frame.x = x_east;
-    frame.y = y_south;
-    break;
-  case WestGravity:
-    frame.x = x_west;
-    frame.y = y_center;
-    break;
-  case EastGravity:
-    frame.x = x_east;
-    frame.y = y_center;
-    break;
-  case CenterGravity:
-    frame.x = x_center;
-    frame.y = y_center;
-    break;
-  case ForgetGravity:
-  case StaticGravity:
-    frame.x = client.x - frame.mwm_border_w + frame.border_w;
-    frame.y = client.y - frame.y_border - frame.mwm_border_w - frame.border_w;
-    break;
-  }
-}
-
-
-void OpenboxWindow::restoreAttributes(void) {
+void BlackboxWindow::restoreAttributes(void) {
   if (! getState()) current_state = NormalState;
 
   Atom atom_return;
   int foo;
   unsigned long ulfoo, nitems;
 
-  OpenboxAttributes *net;
-  int ret = XGetWindowProperty(display, client.window,
-                               openbox.getOpenboxAttributesAtom(), 0l,
-                               PropOpenboxAttributesElements, False,
-                               openbox.getOpenboxAttributesAtom(),
+  BlackboxAttributes *net;
+  int ret = XGetWindowProperty(blackbox->getXDisplay(), client.window,
+                               blackbox->getBlackboxAttributesAtom(), 0l,
+                               PropBlackboxAttributesElements, False,
+                               blackbox->getBlackboxAttributesAtom(),
                                &atom_return, &foo, &nitems, &ulfoo,
                                (unsigned char **) &net);
-  if (ret != Success || !net || nitems != PropOpenboxAttributesElements)
+  if (ret != Success || !net || nitems != PropBlackboxAttributesElements)
     return;
 
-  openbox_attrib.flags = net->flags;
-  openbox_attrib.attrib = net->attrib;
-  openbox_attrib.decoration = net->decoration;
-  openbox_attrib.workspace = net->workspace;
-  openbox_attrib.stack = net->stack;
-  openbox_attrib.premax_x = net->premax_x;
-  openbox_attrib.premax_y = net->premax_y;
-  openbox_attrib.premax_w = net->premax_w;
-  openbox_attrib.premax_h = net->premax_h;
-
-  XFree((void *) net);
-
-  if (openbox_attrib.flags & AttribShaded &&
-      openbox_attrib.attrib & AttribShaded) {
+  if (net->flags & AttribShaded &&
+      net->attrib & AttribShaded) {
     int save_state =
       ((current_state == IconicState) ? NormalState : current_state);
 
@@ -1920,47 +1781,84 @@ void OpenboxWindow::restoreAttributes(void) {
     current_state = save_state;
   }
 
-  if (((int) openbox_attrib.workspace != screen->getCurrentWorkspaceID()) &&
-      ((int) openbox_attrib.workspace < screen->getWorkspaceCount())) {
-    screen->reassociateWindow(this, openbox_attrib.workspace, True);
+  if ((net->workspace != screen->getCurrentWorkspaceID()) &&
+      (net->workspace < screen->getWorkspaceCount())) {
+    screen->reassociateWindow(this, net->workspace, True);
 
     if (current_state == NormalState) current_state = WithdrawnState;
   } else if (current_state == WithdrawnState) {
     current_state = NormalState;
   }
 
-  if (openbox_attrib.flags & AttribOmnipresent &&
-      openbox_attrib.attrib & AttribOmnipresent) {
+  if (net->flags & AttribOmnipresent &&
+      net->attrib & AttribOmnipresent) {
     flags.stuck = False;
     stick();
 
     current_state = NormalState;
   }
 
-  if ((openbox_attrib.flags & AttribMaxHoriz) ||
-      (openbox_attrib.flags & AttribMaxVert)) {
-    int x = openbox_attrib.premax_x, y = openbox_attrib.premax_y;
-    unsigned int w = openbox_attrib.premax_w, h = openbox_attrib.premax_h;
+  if ((net->flags & AttribMaxHoriz) ||
+      (net->flags & AttribMaxVert)) {
+    int x = net->premax_x, y = net->premax_y;
+    unsigned int w = net->premax_w, h = net->premax_h;
     flags.maximized = 0;
 
-    unsigned int m = False;
-    if ((openbox_attrib.flags & AttribMaxHoriz) &&
-        (openbox_attrib.flags & AttribMaxVert))
-      m = (openbox_attrib.attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
-    else if (openbox_attrib.flags & AttribMaxVert)
-      m = (openbox_attrib.attrib & AttribMaxVert) ? 2 : 0;
-    else if (openbox_attrib.flags & AttribMaxHoriz)
-      m = (openbox_attrib.attrib & AttribMaxHoriz) ? 3 : 0;
+    unsigned int m = 0;
+    if ((net->flags & AttribMaxHoriz) &&
+        (net->flags & AttribMaxVert))
+      m = (net->attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
+    else if (net->flags & AttribMaxVert)
+      m = (net->attrib & AttribMaxVert) ? 2 : 0;
+    else if (net->flags & AttribMaxHoriz)
+      m = (net->attrib & AttribMaxHoriz) ? 3 : 0;
 
     if (m) maximize(m);
 
-    openbox_attrib.premax_x = x;
-    openbox_attrib.premax_y = y;
-    openbox_attrib.premax_w = w;
-    openbox_attrib.premax_h = h;
+    blackbox_attrib.premax_x = x;
+    blackbox_attrib.premax_y = y;
+    blackbox_attrib.premax_w = w;
+    blackbox_attrib.premax_h = h;
   }
 
   setState(current_state);
+
+  XFree((void *) net);
+}
+
+
+/*
+ * Positions the frame according the the client window position and window
+ * gravity.
+ */
+void BlackboxWindow::setGravityOffsets(void) {
+  // x coordinates for each gravity type
+  const int x_west = client.rect.x();
+  const int x_east = client.rect.right() - frame.inside_w + 1;
+  const int x_center = client.rect.right() - (frame.rect.width()/2) + 1;
+  // y coordinates for each gravity type
+  const int y_north = client.rect.y();
+  const int y_south = client.rect.bottom() - frame.inside_h + 1;
+  const int y_center = client.rect.bottom() - (frame.rect.height()/2) + 1;
+
+  switch (client.win_gravity) {
+  default:
+  case NorthWestGravity: frame.rect.setPos(x_west,   y_north);  break;
+  case NorthGravity:     frame.rect.setPos(x_center, y_north);  break;
+  case NorthEastGravity: frame.rect.setPos(x_east,   y_north);  break;
+  case SouthWestGravity: frame.rect.setPos(x_west,   y_south);  break;
+  case SouthGravity:     frame.rect.setPos(x_center, y_south);  break;
+  case SouthEastGravity: frame.rect.setPos(x_east,   y_south);  break;
+  case WestGravity:      frame.rect.setPos(x_west,   y_center); break;
+  case CenterGravity:    frame.rect.setPos(x_center, y_center); break;
+  case EastGravity:      frame.rect.setPos(x_east,   y_center); break;
+
+  case ForgetGravity:
+  case StaticGravity:
+    frame.rect.setPos(client.rect.x() - frame.margin.left,
+                      client.rect.y() - frame.margin.top);
+    break;
+  }
 }
 
 
@@ -1968,397 +1866,294 @@ void OpenboxWindow::restoreAttributes(void) {
  * The reverse of the setGravityOffsets function. Uses the frame window's
  * position to find the window's reference point.
  */
-void OpenboxWindow::restoreGravity(void) {
+void BlackboxWindow::restoreGravity(void) {
   // x coordinates for each gravity type
-  const int x_west = frame.x;
-  const int x_east = frame.x + frame.width - client.width;
-  const int x_center = frame.x + (frame.width/2) - client.width;
+  const int x_west = frame.rect.x();
+  const int x_east = frame.rect.x() + frame.inside_w - client.rect.width();
+  const int x_center = frame.rect.x() + (frame.rect.width()/2) -
+                       client.rect.width();
   // y coordinates for each gravity type
-  const int y_north = frame.y;
-  const int y_south = frame.y + frame.height - client.height;
-  const int y_center = frame.y + (frame.height/2) - client.height;
+  const int y_north = frame.rect.y();
+  const int y_south = frame.rect.y() + frame.inside_h - client.rect.height();
+  const int y_center = frame.rect.y() + (frame.rect.height()/2) -
+                       client.rect.height();
 
   switch(client.win_gravity) {
   default:
-  case NorthWestGravity:
-    client.x = x_west;
-    client.y = y_north;
-    break;
-  case NorthGravity:
-    client.x = x_center;
-    client.y = y_north;
-    break;
-  case NorthEastGravity:
-    client.x = x_east;
-    client.y = y_north;
-    break;
-  case SouthWestGravity:
-    client.x = x_west;
-    client.y = y_south;
-    break;
-  case SouthGravity:
-    client.x = x_center;
-    client.y = y_south;
-    break;
-  case SouthEastGravity:
-    client.x = x_east;
-    client.y = y_south;
-    break;
-  case WestGravity:
-    client.x = x_west;
-    client.y = y_center;
-    break;
-  case EastGravity:
-    client.x = x_east;
-    client.y = y_center;
-    break;
-  case CenterGravity:
-    client.x = x_center;
-    client.y = y_center;
-    break;
+  case NorthWestGravity: client.rect.setPos(x_west,   y_north);  break;
+  case NorthGravity:     client.rect.setPos(x_center, y_north);  break;
+  case NorthEastGravity: client.rect.setPos(x_east,   y_north);  break;
+  case SouthWestGravity: client.rect.setPos(x_west,   y_south);  break;
+  case SouthGravity:     client.rect.setPos(x_center, y_south);  break;
+  case SouthEastGravity: client.rect.setPos(x_east,   y_south);  break;
+  case WestGravity:      client.rect.setPos(x_west,   y_center); break;
+  case CenterGravity:    client.rect.setPos(x_center, y_center); break;
+  case EastGravity:      client.rect.setPos(x_east,   y_center); break;
+
   case ForgetGravity:
   case StaticGravity:
-    client.x = frame.x + frame.mwm_border_w + frame.border_w;
-    client.y = frame.y + frame.y_border + frame.mwm_border_w +
-      frame.border_w;
+    client.rect.setPos(frame.rect.left() + frame.margin.left,
+                       frame.rect.top() + frame.margin.top);
     break;
   }
 }
 
 
-void OpenboxWindow::redrawLabel(void) {
-  int dx = frame.bevel_w * 2, dlen = client.title_len;
-  unsigned int l = client.title_text_w;
-
+void BlackboxWindow::redrawLabel(void) {
   if (flags.focused) {
     if (frame.flabel)
-      XSetWindowBackgroundPixmap(display, frame.label, frame.flabel);
+      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                 frame.label, frame.flabel);
     else
-      XSetWindowBackground(display, frame.label, frame.flabel_pixel);
+      XSetWindowBackground(blackbox->getXDisplay(),
+                           frame.label, frame.flabel_pixel);
   } else {
     if (frame.ulabel)
-      XSetWindowBackgroundPixmap(display, frame.label, frame.ulabel);
+      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                 frame.label, frame.ulabel);
     else
-      XSetWindowBackground(display, frame.label, frame.ulabel_pixel);
-  }
-  XClearWindow(display, frame.label);
-
-  if (client.title_text_w > frame.label_w) {
-    for (; dlen >= 0; dlen--) {
-      if (i18n.multibyte()) {
-        XRectangle ink, logical;
-        XmbTextExtents(screen->getWindowStyle()->fontset, client.title, dlen,
-                       &ink, &logical);
-        l = logical.width;
-      } else {
-        l = XTextWidth(screen->getWindowStyle()->font, client.title, dlen);
-      }
-      l += (frame.bevel_w * 4);
-
-      if (l < frame.label_w)
-        break;
-    }
+      XSetWindowBackground(blackbox->getXDisplay(),
+                           frame.label, frame.ulabel_pixel);
   }
+  XClearWindow(blackbox->getXDisplay(), frame.label);
 
-  switch (screen->getWindowStyle()->justify) {
-  case BScreen::RightJustify:
-    dx += frame.label_w - l;
-    break;
+  WindowStyle *style = screen->getWindowStyle();
 
-  case BScreen::CenterJustify:
-    dx += (frame.label_w - l) / 2;
-    break;
-  }
+  int pos = frame.bevel_w * 2,
+    dlen = style->doJustify(client.title.c_str(), pos, frame.label_w,
+                            frame.bevel_w * 4, i18n.multibyte());
 
-  WindowStyle *style = screen->getWindowStyle();
-  GC text_gc = (flags.focused) ? style->l_text_focus_gc :
-    style->l_text_unfocus_gc;
+  BPen pen((flags.focused) ? style->l_text_focus : style->l_text_unfocus,
+           style->font);
   if (i18n.multibyte())
-    XmbDrawString(display, frame.label, style->fontset, text_gc, dx,
+    XmbDrawString(blackbox->getXDisplay(), frame.label, style->fontset,
+                  pen.gc(), pos,
                   (1 - style->fontset_extents->max_ink_extent.y),
-                  client.title, dlen);
+                  client.title.c_str(), dlen);
   else
-    XDrawString(display, frame.label, text_gc, dx,
-                (style->font->ascent + 1), client.title, dlen);
+    XDrawString(blackbox->getXDisplay(), frame.label, pen.gc(), pos,
+                (style->font->ascent + 1), client.title.c_str(), dlen);
 }
 
 
-void OpenboxWindow::redrawAllButtons(void) {
+void BlackboxWindow::redrawAllButtons(void) {
   if (frame.iconify_button) redrawIconifyButton(False);
   if (frame.maximize_button) redrawMaximizeButton(flags.maximized);
   if (frame.close_button) redrawCloseButton(False);
 }
 
 
-void OpenboxWindow::redrawIconifyButton(Bool pressed) {
+void BlackboxWindow::redrawIconifyButton(bool pressed) {
   if (! pressed) {
     if (flags.focused) {
       if (frame.fbutton)
-        XSetWindowBackgroundPixmap(display, frame.iconify_button,
-                                   frame.fbutton);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.iconify_button, frame.fbutton);
       else
-        XSetWindowBackground(display, frame.iconify_button,
-                             frame.fbutton_pixel);
+        XSetWindowBackground(blackbox->getXDisplay(),
+                             frame.iconify_button, frame.fbutton_pixel);
     } else {
       if (frame.ubutton)
-        XSetWindowBackgroundPixmap(display, frame.iconify_button,
-                                   frame.ubutton);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.iconify_button, frame.ubutton);
       else
-        XSetWindowBackground(display, frame.iconify_button,
+        XSetWindowBackground(blackbox->getXDisplay(), frame.iconify_button,
                              frame.ubutton_pixel);
     }
   } else {
     if (frame.pbutton)
-      XSetWindowBackgroundPixmap(display, frame.iconify_button, frame.pbutton);
+      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                 frame.iconify_button, frame.pbutton);
     else
-      XSetWindowBackground(display, frame.iconify_button, frame.pbutton_pixel);
+      XSetWindowBackground(blackbox->getXDisplay(),
+                           frame.iconify_button, frame.pbutton_pixel);
   }
-  XClearWindow(display, frame.iconify_button);
+  XClearWindow(blackbox->getXDisplay(), frame.iconify_button);
 
-  XDrawRectangle(display, frame.iconify_button,
-                 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
-                  screen->getWindowStyle()->b_pic_unfocus_gc),
-                 2, (frame.button_h - 5), (frame.button_w - 5), 2);
+  BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
+           screen->getWindowStyle()->b_pic_unfocus);
+  XDrawRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(),
+                 2, (frame.button_w - 5), (frame.button_w - 5), 2);
 }
 
 
-void OpenboxWindow::redrawMaximizeButton(Bool pressed) {
+void BlackboxWindow::redrawMaximizeButton(bool pressed) {
   if (! pressed) {
     if (flags.focused) {
       if (frame.fbutton)
-        XSetWindowBackgroundPixmap(display, frame.maximize_button,
-                                   frame.fbutton);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.maximize_button, frame.fbutton);
       else
-        XSetWindowBackground(display, frame.maximize_button,
+        XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
                              frame.fbutton_pixel);
     } else {
       if (frame.ubutton)
-        XSetWindowBackgroundPixmap(display, frame.maximize_button,
-                                   frame.ubutton);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.maximize_button, frame.ubutton);
       else
-        XSetWindowBackground(display, frame.maximize_button,
+        XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
                              frame.ubutton_pixel);
     }
   } else {
     if (frame.pbutton)
-      XSetWindowBackgroundPixmap(display, frame.maximize_button,
-                                 frame.pbutton);
+      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                 frame.maximize_button, frame.pbutton);
     else
-      XSetWindowBackground(display, frame.maximize_button,
+      XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
                            frame.pbutton_pixel);
   }
-  XClearWindow(display, frame.maximize_button);
+  XClearWindow(blackbox->getXDisplay(), frame.maximize_button);
 
-  XDrawRectangle(display, frame.maximize_button,
-                 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
-                  screen->getWindowStyle()->b_pic_unfocus_gc),
-                 2, 2, (frame.button_w - 5), (frame.button_h - 5));
-  XDrawLine(display, frame.maximize_button,
-            ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
-             screen->getWindowStyle()->b_pic_unfocus_gc),
+  BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
+           screen->getWindowStyle()->b_pic_unfocus);
+  XDrawRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
+                 2, 2, (frame.button_w - 5), (frame.button_w - 5));
+  XDrawLine(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
             2, 3, (frame.button_w - 3), 3);
 }
 
 
-void OpenboxWindow::redrawCloseButton(Bool pressed) {
+void BlackboxWindow::redrawCloseButton(bool pressed) {
   if (! pressed) {
     if (flags.focused) {
       if (frame.fbutton)
-        XSetWindowBackgroundPixmap(display, frame.close_button,
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button,
                                    frame.fbutton);
       else
-        XSetWindowBackground(display, frame.close_button,
+        XSetWindowBackground(blackbox->getXDisplay(), frame.close_button,
                              frame.fbutton_pixel);
     } else {
       if (frame.ubutton)
-        XSetWindowBackgroundPixmap(display, frame.close_button,
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button,
                                    frame.ubutton);
       else
-        XSetWindowBackground(display, frame.close_button,
+        XSetWindowBackground(blackbox->getXDisplay(), frame.close_button,
                              frame.ubutton_pixel);
     }
   } else {
     if (frame.pbutton)
-      XSetWindowBackgroundPixmap(display, frame.close_button, frame.pbutton);
+      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                 frame.close_button, frame.pbutton);
     else
-      XSetWindowBackground(display, frame.close_button, frame.pbutton_pixel);
+      XSetWindowBackground(blackbox->getXDisplay(),
+                           frame.close_button, frame.pbutton_pixel);
   }
-  XClearWindow(display, frame.close_button);
+  XClearWindow(blackbox->getXDisplay(), frame.close_button);
 
-  XDrawLine(display, frame.close_button,
-            ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
-             screen->getWindowStyle()->b_pic_unfocus_gc), 2, 2,
-            (frame.button_w - 3), (frame.button_h - 3));
-  XDrawLine(display, frame.close_button,
-            ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
-             screen->getWindowStyle()->b_pic_unfocus_gc), 2,
-            (frame.button_h - 3),
-            (frame.button_w - 3), 2);
+  BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
+           screen->getWindowStyle()->b_pic_unfocus);
+  XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
+            2, 2, (frame.button_w - 3), (frame.button_w - 3));
+  XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
+            2, (frame.button_w - 3), (frame.button_w - 3), 2);
 }
 
 
-void OpenboxWindow::mapRequestEvent(XMapRequestEvent *re) {
-  if (re->window == client.window) {
+void BlackboxWindow::mapRequestEvent(XMapRequestEvent *re) {
+  if (re->window != client.window)
+    return;
+
 #ifdef    DEBUG
-    fprintf(stderr, i18n(WindowSet, WindowMapRequest,
-                         "OpenboxWindow::mapRequestEvent() for 0x%lx\n"),
-            client.window);
+  fprintf(stderr, "BlackboxWindow::mapRequestEvent() for 0x%lx\n",
+          client.window);
 #endif // DEBUG
 
-    openbox.grab();
-    if (! validateClient()) return;
-
-    Bool get_state_ret = getState();
-    if (! (get_state_ret && openbox.isStartup())) {
-      if ((client.wm_hint_flags & StateHint) &&
-          (! (current_state == NormalState || current_state == IconicState)))
-        current_state = client.initial_state;
-      else
-        current_state = NormalState;
-    } else if (flags.iconic) {
+  bool get_state_ret = getState();
+  if (! (get_state_ret && blackbox->isStartup())) {
+    if ((client.wm_hint_flags & StateHint) &&
+        (! (current_state == NormalState || current_state == IconicState)))
+      current_state = client.initial_state;
+    else
       current_state = NormalState;
-    }
-
-    switch (current_state) {
-    case IconicState:
-      iconify();
-      break;
-
-    case WithdrawnState:
-      withdraw();
-      break;
-
-    case NormalState:
-    case InactiveState:
-    case ZoomState:
-    default:
-      deiconify(False, True, True);     // specify that we're initializing the
-      // window
-      break;
-    }
-
-    openbox.ungrab();
+  } else if (flags.iconic) {
+    current_state = NormalState;
   }
-}
-
 
-void OpenboxWindow::mapNotifyEvent(XMapEvent *ne) {
-  if ((ne->window == client.window) && (! ne->override_redirect)
-      && (flags.visible)) {
-    openbox.grab();
-    if (! validateClient()) return;
+  switch (current_state) {
+  case IconicState:
+    iconify();
+    break;
 
-    setState(NormalState);
+  case WithdrawnState:
+    withdraw();
+    break;
 
-    if (flags.transient || screen->focusNew())
+  case NormalState:
+  case InactiveState:
+  case ZoomState:
+  default:
+    show();
+    screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
+    if (! blackbox->isStartup() && (isTransient() || screen->doFocusNew())) {
+      XSync(blackbox->getXDisplay(), False); // make sure the frame is mapped..
       setInputFocus();
-    else
-      setFocusFlag(False);
-
-    flags.visible = True;
-    flags.iconic = False;
-
-    openbox.ungrab();
+    }
+    break;
   }
 }
 
 
-void OpenboxWindow::unmapNotifyEvent(XUnmapEvent *ue) {
-  if (ue->window == client.window) {
+void BlackboxWindow::unmapNotifyEvent(XUnmapEvent *ue) {
+  if (ue->window != client.window)
+    return;
+
 #ifdef    DEBUG
-    fprintf(stderr, i18n(WindowSet, WindowUnmapNotify,
-                         "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"),
-            client.window);
+  fprintf(stderr, "BlackboxWindow::unmapNotifyEvent() for 0x%lx\n",
+          client.window);
 #endif // DEBUG
 
-    openbox.grab();
-    if (! validateClient()) return;
-
-    if (flags.moving)
-      endMove();
-
-    XChangeSaveSet(display, client.window, SetModeDelete);
-    XSelectInput(display, client.window, NoEventMask);
+  screen->unmanageWindow(this, False);
+}
 
-    XDeleteProperty(display, client.window, openbox.getWMStateAtom());
-    XDeleteProperty(display, client.window,
-                    openbox.getOpenboxAttributesAtom());
 
-    XUnmapWindow(display, frame.window);
-    XUnmapWindow(display, client.window);
+void BlackboxWindow::destroyNotifyEvent(XDestroyWindowEvent *de) {
+  if (de->window != client.window)
+    return;
 
-    XEvent dummy;
-    if (! XCheckTypedWindowEvent(display, client.window, ReparentNotify,
-                                 &dummy)) {
 #ifdef    DEBUG
-      fprintf(stderr, i18n(WindowSet, WindowUnmapNotifyReparent,
-                           "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to "
-                           "root.\n"), client.window);
+  fprintf(stderr, "BlackboxWindow::destroyNotifyEvent() for 0x%lx\n",
+          client.window);
 #endif // DEBUG
 
-      restoreGravity();
-      XReparentWindow(display, client.window, screen->getRootWindow(),
-                      client.x, client.y);
-    }
-
-    XFlush(display);
-
-    openbox.ungrab();
-
-    delete this;
-  }
+  screen->unmanageWindow(this, False);
 }
 
 
-void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent *de) {
-  if (de->window == client.window) {
-    if (flags.moving)
-      endMove();
-    XUnmapWindow(display, frame.window);
+void BlackboxWindow::reparentNotifyEvent(XReparentEvent *re) {
+  if (re->window != client.window || re->parent == frame.plate)
+    return;
+
+#ifdef    DEBUG
+  fprintf(stderr, "BlackboxWindow::reparentNotifyEvent(): reparent 0x%lx to "
+          "0x%lx.\n", client.window, re->parent);
+#endif // DEBUG
 
-    delete this;
-  }
+  XEvent ev;
+  ev.xreparent = *re;
+  XPutBackEvent(blackbox->getXDisplay(), &ev);
+  screen->unmanageWindow(this, True);
 }
 
 
-void OpenboxWindow::propertyNotifyEvent(Atom atom) {
-  openbox.grab();
-  if (! validateClient()) return;
-
+void BlackboxWindow::propertyNotifyEvent(Atom atom) {
   switch(atom) {
   case XA_WM_CLASS:
   case XA_WM_CLIENT_MACHINE:
   case XA_WM_COMMAND:
     break;
 
-  case XA_WM_TRANSIENT_FOR:
+  case XA_WM_TRANSIENT_FOR: {
     // determine if this is a transient window
-    Window win;
-    if (XGetTransientForHint(display, client.window, &win)) {
-      if (win && (win != client.window)) {
-        if ((client.transient_for = openbox.searchWindow(win))) {
-          client.transient_for->client.transient = this;
-          flags.stuck = client.transient_for->flags.stuck;
-          flags.transient = True;
-        } else if (win == client.window_group) {
-          //jr This doesn't look quite right...
-          if ((client.transient_for = openbox.searchGroup(win, this))) {
-            client.transient_for->client.transient = this;
-            flags.stuck = client.transient_for->flags.stuck;
-            flags.transient = True;
-          }
-        }
-      }
-
-      if (win == screen->getRootWindow()) flags.modal = True;
-    }
+    getTransientInfo();
 
     // adjust the window decorations based on transience
-    if (flags.transient)
-      decorations.maximize = decorations.handle = functions.maximize = False;
+    if (isTransient()) {
+      decorations &= ~(Decor_Maximize | Decor_Handle);
+      functions &= ~Func_Maximize;
+    }
 
     reconfigure();
-
+  }
     break;
 
   case XA_WM_HINTS:
@@ -2367,18 +2162,16 @@ void OpenboxWindow::propertyNotifyEvent(Atom atom) {
 
   case XA_WM_ICON_NAME:
     getWMIconName();
-    if (flags.iconic) screen->iconUpdate();
+    if (flags.iconic) screen->propagateWindowName(this);
     break;
 
   case XA_WM_NAME:
     getWMName();
 
-    if (decorations.titlebar)
+    if (decorations & Decor_Titlebar)
       redrawLabel();
 
-    if (! flags.iconic)
-      screen->getWorkspace(workspace_number)->update();
-
+    screen->propagateWindowName(this);
     break;
 
   case XA_WM_NORMAL_HINTS: {
@@ -2387,35 +2180,34 @@ void OpenboxWindow::propertyNotifyEvent(Atom atom) {
     if ((client.normal_hint_flags & PMinSize) &&
         (client.normal_hint_flags & PMaxSize)) {
       if (client.max_width <= client.min_width &&
-          client.max_height <= client.min_height)
-        decorations.maximize = decorations.handle =
-          functions.resize = functions.maximize = False;
-      else
-        decorations.maximize = decorations.handle =
-          functions.resize = functions.maximize = True;
+          client.max_height <= client.min_height) {
+        decorations &= ~(Decor_Maximize | Decor_Handle);
+        functions &= ~(Func_Resize | Func_Maximize);
+      } else {
+        decorations |= Decor_Maximize | Decor_Handle;
+        functions |= Func_Resize | Func_Maximize;
+      }
     }
 
-    int x = frame.x, y = frame.y;
-    unsigned int w = frame.width, h = frame.height;
+    Rect old_rect = frame.rect;
 
     upsize();
 
-    if ((x != frame.x) || (y != frame.y) ||
-        (w != frame.width) || (h != frame.height))
+    if (old_rect != frame.rect)
       reconfigure();
 
     break;
   }
 
   default:
-    if (atom == openbox.getWMProtocolsAtom()) {
+    if (atom == blackbox->getWMProtocolsAtom()) {
       getWMProtocols();
 
-      if (decorations.close && (! frame.close_button)) {
+      if ((decorations & Decor_Close) && (! frame.close_button)) {
         createCloseButton();
-        if (decorations.titlebar) {
-          positionButtons();
-          decorateLabel();
+        if (decorations & Decor_Titlebar) {
+          positionButtons(True);
+          XMapSubwindows(blackbox->getXDisplay(), frame.title);
         }
         if (windowmenu) windowmenu->reconfigure();
       }
@@ -2423,13 +2215,11 @@ void OpenboxWindow::propertyNotifyEvent(Atom atom) {
 
     break;
   }
-
-  openbox.ungrab();
 }
 
 
-void OpenboxWindow::exposeEvent(XExposeEvent *ee) {
-  if (frame.label == ee->window && decorations.titlebar)
+void BlackboxWindow::exposeEvent(XExposeEvent *ee) {
+  if (frame.label == ee->window && (decorations & Decor_Titlebar))
     redrawLabel();
   else if (frame.close_button == ee->window)
     redrawCloseButton(False);
@@ -2440,623 +2230,444 @@ void OpenboxWindow::exposeEvent(XExposeEvent *ee) {
 }
 
 
-void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent *cr) {
-  if (cr->window == client.window) {
-    openbox.grab();
-    if (! validateClient()) return;
+void BlackboxWindow::configureRequestEvent(XConfigureRequestEvent *cr) {
+  if (cr->window != client.window || flags.iconic)
+    return;
 
-    int cx = frame.x, cy = frame.y;
-    unsigned int cw = frame.width, ch = frame.height;
+  int cx = frame.rect.x(), cy = frame.rect.y();
+  unsigned int cw = frame.rect.width(), ch = frame.rect.height();
 
-    if (cr->value_mask & CWBorderWidth)
-      client.old_bw = cr->border_width;
+  if (cr->value_mask & CWBorderWidth)
+    client.old_bw = cr->border_width;
 
-    if (cr->value_mask & CWX)
-      cx = cr->x - frame.mwm_border_w - frame.border_w;
+  if (cr->value_mask & CWX)
+    cx = cr->x - frame.margin.left;
 
-    if (cr->value_mask & CWY)
-      cy = cr->y - frame.y_border - frame.mwm_border_w -
-        frame.border_w;
+  if (cr->value_mask & CWY)
+    cy = cr->y - frame.margin.top;
 
-    if (cr->value_mask & CWWidth)
-      cw = cr->width + (frame.mwm_border_w * 2);
+  if (cr->value_mask & CWWidth)
+    cw = cr->width + frame.margin.left + frame.margin.right;
 
-    if (cr->value_mask & CWHeight)
-      ch = cr->height + frame.y_border + (frame.mwm_border_w * 2) +
-        (frame.border_w * decorations.handle) + frame.handle_h;
+  if (cr->value_mask & CWHeight)
+    ch = cr->height + frame.margin.top + frame.margin.bottom;
 
-    if (frame.x != cx || frame.y != cy ||
-        frame.width != cw || frame.height != ch)
-      configure(cx, cy, cw, ch);
+  if (frame.rect != Rect(cx, cy, cw, ch))
+    configure(cx, cy, cw, ch);
 
-    if (cr->value_mask & CWStackMode) {
-      switch (cr->detail) {
-      case Above:
-      case TopIf:
-      default:
-        if (flags.iconic) deiconify();
-        screen->getWorkspace(workspace_number)->raiseWindow(this);
-        break;
+  if (cr->value_mask & CWStackMode) {
+    switch (cr->detail) {
+    case Below:
+    case BottomIf:
+      screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this);
+      break;
 
-      case Below:
-      case BottomIf:
-        if (flags.iconic) deiconify();
-        screen->getWorkspace(workspace_number)->lowerWindow(this);
-        break;
-      }
+    case Above:
+    case TopIf:
+    default:
+      screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
+      break;
     }
-
-    openbox.ungrab();
   }
 }
 
 
-void OpenboxWindow::buttonPressEvent(XButtonEvent *be) {
-  openbox.grab();
-  if (! validateClient())
-    return;
+void BlackboxWindow::buttonPressEvent(XButtonEvent *be) {
+  if (frame.maximize_button == be->window) {
+    redrawMaximizeButton(True);
+  } else if (be->button == 1 || (be->button == 3 && be->state == Mod1Mask)) {
+    if (! flags.focused)
+      setInputFocus();
 
-  int stack_change = 1; // < 0 means to lower the window
-  // > 0 means to raise the window
-  // 0 means to leave it where it is
-
-  // alt + left/right click begins interactively moving/resizing the window
-  // when the mouse is moved
-  if (be->state == Mod1Mask && (be->button == 1 || be->button == 3)) {
-    if (be->button == 3) {
-      if (screen->getWindowZones() == 4 &&
-          be->y < (signed) frame.height / 2) {
-        resize_zone = ZoneTop;
-      } else {
-        resize_zone = ZoneBottom;
-      }
-      if (screen->getWindowZones() >= 2 &&
-          be->x < (signed) frame.width / 2) {
-        resize_zone |= ZoneLeft;
-      } else {
-        resize_zone |= ZoneRight;
-      }
-    }
-    // control + left click on the titlebar shades the window
-  } else if (be->state == ControlMask && be->button == 1) {
-    if (be->window == frame.title ||
-        be->window == frame.label)
-      shade();
-    // left click
-  } else if (be->state == 0 && be->button == 1) {
-    if (windowmenu && windowmenu->isVisible())
-      windowmenu->hide();
-
-    if (be->window == frame.maximize_button) {
-      redrawMaximizeButton(True);
-    } else if (be->window == frame.iconify_button) {
+    if (frame.iconify_button == be->window) {
       redrawIconifyButton(True);
-    } else if (be->window == frame.close_button) {
+    } else if (frame.close_button == be->window) {
       redrawCloseButton(True);
-    } else if (be->window == frame.plate) {
-      XAllowEvents(display, ReplayPointer, be->time);
-    } else if (be->window == frame.title ||
-               be->window == frame.label) {
-      // shade the window when the titlebar is double clicked
-      if ( (be->time - lastButtonPressTime) <=
-          openbox.getDoubleClickInterval()) {
-        lastButtonPressTime = 0;
-        shade();
-      } else {
-        lastButtonPressTime = be->time;
-      }
-      // clicking and dragging on the titlebar moves the window, so on a click
-      // we need to save the coords of the click in case the user drags
-      frame.grab_x = be->x_root - frame.x - frame.border_w;
-      frame.grab_y = be->y_root - frame.y - frame.border_w;
-    } else if (be->window == frame.handle ||
-               be->window == frame.left_grip ||
-               be->window == frame.right_grip ||
-               be->window == frame.window) {
-      // clicking and dragging on the window's frame moves the window, so on a
-      // click we need to save the coords of the click in case the user drags
-      frame.grab_x = be->x_root - frame.x - frame.border_w;
-      frame.grab_y = be->y_root - frame.y - frame.border_w;
-      if (be->window == frame.left_grip)
-        resize_zone = ZoneBottom | ZoneLeft;
-      else if (be->window == frame.right_grip)
-        resize_zone = ZoneBottom | ZoneRight;
-    }
-    // middle click
-  } else if (be->state == 0 && be->button == 2) {
-    if (be->window == frame.maximize_button) {
-      redrawMaximizeButton(True);
-      // a middle click anywhere on the window's frame except for on the buttons
-      // will lower the window
-    } else if (! (be->window == frame.iconify_button ||
-                  be->window == frame.close_button) ) {
-      stack_change = -1;
-    }
-    // right click
-  } else if (be->state == 0 && be->button == 3) {
-    if (be->window == frame.maximize_button) {
-      redrawMaximizeButton(True);
-      // a right click on the window's frame will show or hide the window's
-      // windowmenu
-    } else if (be->window == frame.title ||
-               be->window == frame.label ||
-               be->window == frame.handle ||
-               be->window == frame.window) {
-      int mx, my;
-      if (windowmenu) {
-        if (windowmenu->isVisible()) {
-          windowmenu->hide();
+    } else if (frame.plate == be->window) {
+      if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
+
+      screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
+
+      XAllowEvents(blackbox->getXDisplay(), ReplayPointer, be->time);
+    } else {
+      if (frame.title == be->window || frame.label == be->window) {
+        if (((be->time - lastButtonPressTime) <=
+             blackbox->getDoubleClickInterval()) ||
+            (be->state & ControlMask)) {
+          lastButtonPressTime = 0;
+          shade();
         } else {
-          // get the coords for the menu
-          mx = be->x_root - windowmenu->getWidth() / 2;
-          if (be->window == frame.title || be->window == frame.label) {
-            my = frame.y + frame.title_h;
-          } else if (be->window == frame.handle) {
-            my = frame.y + frame.y_handle - windowmenu->getHeight();
-          } else { // (be->window == frame.window)
-            if (be->y <= (signed) frame.bevel_w) {
-              my = frame.y + frame.y_border;
-            } else {
-              my = be->y_root - (windowmenu->getHeight() / 2);
-            }
-          }
-
-          if (mx > (signed) (frame.x + frame.width -
-                             windowmenu->getWidth())) {
-            mx = frame.x + frame.width - windowmenu->getWidth();
-          } else if (mx < frame.x) {
-            mx = frame.x;
-          }
-
-          if (my > (signed) (frame.y + frame.y_handle -
-                             windowmenu->getHeight())) {
-            my = frame.y + frame.y_handle - windowmenu->getHeight();
-          } else if (my < (signed) (frame.y +
-                                    ((decorations.titlebar) ? frame.title_h : frame.y_border))) {
-            my = frame.y +
-              ((decorations.titlebar) ? frame.title_h : frame.y_border);
-          }
-
-          windowmenu->move(mx, my);
-          windowmenu->show();
-          XRaiseWindow(display, windowmenu->getWindowID());
-          XRaiseWindow(display, windowmenu->getSendToMenu()->getWindowID());
-          stack_change = 0;  // dont raise the window overtop of the menu
+          lastButtonPressTime = be->time;
         }
       }
-    }
-    // mouse wheel up
-  } else if (be->state == 0 && be->button == 4) {
-    if ((be->window == frame.label ||
-         be->window == frame.title) &&
-        !flags.shaded)
-      shade();
-    // mouse wheel down
-  } else if (be->state == 0 && be->button == 5) {
-    if ((be->window == frame.label ||
-         be->window == frame.title) &&
-        flags.shaded)
-      shade();
-  }
-
-  if (! (flags.focused || screen->sloppyFocus()) ) {
-    setInputFocus();  // any click focus' the window in 'click to focus'
-  }
-  if (stack_change < 0) {
-    screen->getWorkspace(workspace_number)->lowerWindow(this);
-  } else if (stack_change > 0) {
-    screen->getWorkspace(workspace_number)->raiseWindow(this);
-  }
-
-  openbox.ungrab();
-}
 
+      frame.grab_x = be->x_root - frame.rect.x() - frame.border_w;
+      frame.grab_y = be->y_root - frame.rect.y() - frame.border_w;
 
-void OpenboxWindow::buttonReleaseEvent(XButtonEvent *re) {
-  openbox.grab();
-  if (! validateClient())
-    return;
+      if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
 
-  // alt + middle button released
-  if (re->state == (Mod1Mask & Button2Mask) && re->button == 2) {
-    if (re->window == frame.window) {
-      XUngrabPointer(display, CurrentTime); // why? i dont know
-    }
-    // left button released
-  } else if (re->button == 1) {
-    if (re->window == frame.maximize_button) {
-      if (re->state == Button1Mask && // only the left button was depressed
-          (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
-          (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
-        maximize(re->button);
-      } else {
-        redrawMaximizeButton(False);
-      }
-    } else if (re->window == frame.iconify_button) {
-      if (re->state == Button1Mask && // only the left button was depressed
-          (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
-          (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
-        iconify();
-      } else {
-        redrawIconifyButton(False);
-      }
-    } else if (re->window == frame.close_button) {
-      if (re->state == Button1Mask && // only the left button was depressed
-          (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
-          (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
-        close();
-      }
-      //we should always redraw the close button. some applications
-      //eg. acroread don't honour the close.
-      redrawCloseButton(False);
+      screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
     }
-    // middle button released
-  } else if (re->button == 2) {
-    if (re->window == frame.maximize_button) {
-      if (re->state == Button2Mask && // only the middle button was depressed
-          (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
-          (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
-        maximize(re->button);
-      } else {
-        redrawMaximizeButton(False);
-      }
+  } else if (be->button == 2 && (be->window != frame.iconify_button) &&
+             (be->window != frame.close_button)) {
+    screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this);
+  } else if (windowmenu && be->button == 3 &&
+             (frame.title == be->window || frame.label == be->window ||
+              frame.handle == be->window || frame.window == be->window)) {
+    int mx = 0, my = 0;
+
+    if (frame.title == be->window || frame.label == be->window) {
+      mx = be->x_root - (windowmenu->getWidth() / 2);
+      my = frame.rect.y() + frame.title_h + frame.border_w;
+    } else if (frame.handle == be->window) {
+      mx = be->x_root - (windowmenu->getWidth() / 2);
+      my = frame.rect.bottom() - frame.handle_h - (frame.border_w * 3) -
+           windowmenu->getHeight();
+    } else {
+      mx = be->x_root - (windowmenu->getWidth() / 2);
+
+      if (be->y <= static_cast<signed>(frame.bevel_w))
+        my = frame.rect.y() + frame.title_h;
+      else
+        my = be->y_root - (windowmenu->getHeight() / 2);
     }
-    // right button released
-  } else if (re->button == 3) {
-    if (re->window == frame.maximize_button) {
-      if (re->state == Button3Mask && // only the right button was depressed
-          (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
-          (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
-        maximize(re->button);
+
+    // snap the window menu into a corner if necessary - we check the
+    // position of the menu with the coordinates of the client to
+    // make the comparisions easier.
+    // ### this needs some work!
+    if (mx > client.rect.right() -
+        static_cast<signed>(windowmenu->getWidth()))
+      mx = frame.rect.right() - windowmenu->getWidth() - frame.border_w + 1;
+    if (mx < client.rect.left())
+      mx = frame.rect.x();
+
+    if (my > client.rect.bottom() -
+        static_cast<signed>(windowmenu->getHeight()))
+      my = frame.rect.bottom() - windowmenu->getHeight() - frame.border_w + 1;
+    if (my < client.rect.top())
+      my = frame.rect.y() + ((decorations & Decor_Titlebar) ?
+                             frame.title_h : 0);
+
+    if (windowmenu) {
+      if (! windowmenu->isVisible()) {
+        windowmenu->move(mx, my);
+        windowmenu->show();
+        XRaiseWindow(blackbox->getXDisplay(), windowmenu->getWindowID());
+        XRaiseWindow(blackbox->getXDisplay(),
+                     windowmenu->getSendToMenu()->getWindowID());
       } else {
-        redrawMaximizeButton(False);
+        windowmenu->hide();
       }
     }
   }
-
-  // when the window is being interactively moved, a button release stops the
-  // move where it is
-  if (flags.moving) {
-    endMove();
-    // when the window is being interactively resized, a button release stops the
-    // resizing
-  } else if (flags.resizing) {
-    flags.resizing = False;
-    XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
-                   frame.resize_x, frame.resize_y,
-                   frame.resize_w - 1, frame.resize_h - 1);
-    screen->hideGeometry();
-    if (resize_zone & ZoneLeft) {
-      left_fixsize();
-    } else {  // when resizing with "Alt+Button3", the resize is the same as if
-      // done with the right grip (the right side of the window is what
-      // moves)
-      right_fixsize();
-    }
-    // unset maximized state when resized after fully maximized
-    if (flags.maximized == 1) {
-      maximize(0);
-    }
-    configure(frame.resize_x, frame.resize_y,
-              frame.resize_w - (frame.border_w * 2),
-              frame.resize_h - (frame.border_w * 2));
-    openbox.ungrab();
-    XUngrabPointer(display, CurrentTime);
-    resize_zone = 0;
-  }
-
-  openbox.ungrab();
 }
 
 
-void OpenboxWindow::startMove(int x, int y) {
-  ASSERT(!flags.moving);
-
-  // make sure only one window is moving at a time
-  OpenboxWindow *w = openbox.getMaskedWindow();
-  if (w != (OpenboxWindow *) 0 && w->flags.moving)
-    w->endMove();
-
-  XGrabPointer(display, frame.window, False, PointerMotionMask |
-               ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
-               None, openbox.getMoveCursor(), CurrentTime);
-
-  if (windowmenu && windowmenu->isVisible())
-    windowmenu->hide();
-
-  flags.moving = True;
-
-  openbox.maskWindowEvents(client.window, this);
+void BlackboxWindow::buttonReleaseEvent(XButtonEvent *re) {
+  if (re->window == frame.maximize_button) {
+    if ((re->x >= 0 && re->x <= static_cast<signed>(frame.button_w)) &&
+        (re->y >= 0 && re->y <= static_cast<signed>(frame.button_w))) {
+      maximize(re->button);
+    } else {
+      redrawMaximizeButton(flags.maximized);
+    }
+  } else if (re->window == frame.iconify_button) {
+    if ((re->x >= 0 && re->x <= static_cast<signed>(frame.button_w)) &&
+        (re->y >= 0 && re->y <= static_cast<signed>(frame.button_w))) {
+      iconify();
+    } else {
+      redrawIconifyButton(False);
+    }
+  } else if (re->window == frame.close_button) {
+    if ((re->x >= 0 && re->x <= static_cast<signed>(frame.button_w)) &&
+        (re->y >= 0 && re->y <= static_cast<signed>(frame.button_w)))
+      close();
+    redrawCloseButton(False);
+  } else if (flags.moving) {
+    flags.moving = False;
+
+    if (! screen->doOpaqueMove()) {
+      /* when drawing the rubber band, we need to make sure we only draw inside
+       * the frame... frame.changing_* contain the new coords for the window,
+       * so we need to subtract 1 from changing_w/changing_h every where we
+       * draw the rubber band (for both moving and resizing)
+       */
+      XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
+                     screen->getOpGC(), frame.changing.x(), frame.changing.y(),
+                     frame.changing.width() - 1, frame.changing.height() - 1);
+      XUngrabServer(blackbox->getXDisplay());
+
+      configure(frame.changing.x(), frame.changing.y(),
+                frame.changing.width(), frame.changing.height());
+    } else {
+      configure(frame.rect.x(), frame.rect.y(),
+                frame.rect.width(), frame.rect.height());
+    }
+    screen->hideGeometry();
+    XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
+  } else if (flags.resizing) {
+    XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
+                   screen->getOpGC(), frame.changing.x(), frame.changing.y(),
+                   frame.changing.width() - 1, frame.changing.height() - 1);
+    XUngrabServer(blackbox->getXDisplay());
 
-  if (! screen->opaqueMove()) {
-    openbox.grab();
+    screen->hideGeometry();
 
-    frame.move_x = frame.x;
-    frame.move_y = frame.y;
-    frame.resize_w = frame.width + (frame.border_w * 2);
-    frame.resize_h = ((flags.shaded) ? frame.title_h : frame.height) +
-      (frame.border_w * 2);
+    constrain((re->window == frame.left_grip) ? TopRight : TopLeft);
 
-    screen->showPosition(frame.x, frame.y);
+    // unset maximized state when resized after fully maximized
+    if (flags.maximized == 1)
+      maximize(0);
+    flags.resizing = False;
+    configure(frame.changing.x(), frame.changing.y(),
+              frame.changing.width(), frame.changing.height());
 
-    XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
-                   frame.move_x, frame.move_y,
-                   frame.resize_w - 1, frame.resize_h - 1);
+    XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
+  } else if (re->window == frame.window) {
+    if (re->button == 2 && re->state == Mod1Mask)
+      XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
   }
-  frame.grab_x = x - frame.x - frame.border_w;
-  frame.grab_y = y - frame.y - frame.border_w;
 }
 
 
-void OpenboxWindow::doMove(int x, int y) {
-  ASSERT(flags.moving);
-
-  int dx = x - frame.grab_x, dy = y - frame.grab_y;
-
-  dx -= frame.border_w;
-  dy -= frame.border_w;
-
-  int snap_distance = screen->edgeSnapThreshold();
-  // width/height of the snapping window
-  unsigned int snap_w = frame.width + (frame.border_w * 2);
-  unsigned int snap_h = area().h() + (frame.border_w * 2);
-  if (snap_distance) {
-    int drx = screen->size().w() - (dx + snap_w);
-
-    if (dx < drx && (dx > 0 && dx < snap_distance) ||
-        (dx < 0 && dx > -snap_distance) )
-      dx = 0;
-    else if ( (drx > 0 && drx < snap_distance) ||
-             (drx < 0 && drx > -snap_distance) )
-      dx = screen->size().w() - snap_w;
-
-    int dtty, dbby, dty, dby;
-    switch (screen->getToolbar()->placement()) {
-    case Toolbar::TopLeft:
-    case Toolbar::TopCenter:
-    case Toolbar::TopRight:
-      dtty = screen->getToolbar()->getExposedHeight() +
-        frame.border_w;
-      dbby = screen->size().h();
-      break;
-
-    default:
-      dtty = 0;
-      dbby = screen->getToolbar()->area().y();
-      break;
-    }
-
-    dty = dy - dtty;
-    dby = dbby - (dy + snap_h);
-
-    if ( (dy > 0 && dty < snap_distance) ||
-        (dy < 0 && dty > -snap_distance) )
-      dy = dtty;
-    else if ( (dby > 0 && dby < snap_distance) ||
-             (dby < 0 && dby > -snap_distance) )
-      dy = dbby - snap_h;
-  }
-
-  if (screen->opaqueMove()) {
-    configure(dx, dy, frame.width, frame.height);
-  } else {
-    XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
-                   frame.move_x, frame.move_y, frame.resize_w - 1,
-                   frame.resize_h - 1);
-
-    frame.move_x = dx;
-    frame.move_y = dy;
-
-    XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
-                   frame.move_x, frame.move_y, frame.resize_w - 1,
-                   frame.resize_h - 1);
-  }
-
-  screen->showPosition(dx, dy);
-}
+void BlackboxWindow::motionNotifyEvent(XMotionEvent *me) {
+  if (!flags.resizing && (me->state & Button1Mask) &&
+      (functions & Func_Move) &&
+      (frame.title == me->window || frame.label == me->window ||
+       frame.handle == me->window || frame.window == me->window)) {
+    if (! flags.moving) {
+      XGrabPointer(blackbox->getXDisplay(), me->window, False,
+                   Button1MotionMask | ButtonReleaseMask,
+                   GrabModeAsync, GrabModeAsync,
+                   None, blackbox->getMoveCursor(), CurrentTime);
 
+      if (windowmenu && windowmenu->isVisible())
+        windowmenu->hide();
 
-void OpenboxWindow::endMove() {
-  ASSERT(flags.moving);
+      flags.moving = True;
 
-  flags.moving = False;
+      if (! screen->doOpaqueMove()) {
+        XGrabServer(blackbox->getXDisplay());
 
-  openbox.maskWindowEvents(0, (OpenboxWindow *) 0);
-  if (!screen->opaqueMove()) {
-    XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
-                   frame.move_x, frame.move_y, frame.resize_w - 1,
-                   frame.resize_h - 1);
+        frame.changing = frame.rect;
+        screen->showPosition(frame.changing.x(), frame.changing.y());
 
-    configure(frame.move_x, frame.move_y, frame.width, frame.height);
-    openbox.ungrab();
-  } else {
-    configure(frame.x, frame.y, frame.width, frame.height);
-  }
-  screen->hideGeometry();
-  XUngrabPointer(display, CurrentTime);
-  // if there are any left over motions from the move, drop them now cuz they
-  // cause problems
-  XEvent e;
-  while (XCheckTypedWindowEvent(display, frame.window, MotionNotify, &e));
-}
+        XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
+                       screen->getOpGC(),
+                       frame.changing.x(),
+                       frame.changing.y(),
+                       frame.changing.width() - 1,
+                       frame.changing.height() - 1);
+      }
+    } else {
+      int dx = me->x_root - frame.grab_x, dy = me->y_root - frame.grab_y;
+      dx -= frame.border_w;
+      dy -= frame.border_w;
+
+      const int snap_distance = screen->getEdgeSnapThreshold();
+
+      if (snap_distance) {
+        Rect srect = screen->availableArea();
+        // window corners
+        const int wleft = dx,
+                 wright = dx + frame.rect.width() - 1,
+                   wtop = dy,
+                wbottom = dy + frame.rect.height() - 1;
+
+        int dleft = std::abs(wleft - srect.left()),
+           dright = std::abs(wright - srect.right()),
+             dtop = std::abs(wtop - srect.top()),
+          dbottom = std::abs(wbottom - srect.bottom());
+
+        // snap left?
+        if (dleft < snap_distance && dleft < dright)
+          dx = srect.left();
+        // snap right?
+        else if (dright < snap_distance && dright < dleft)
+          dx = srect.right() - frame.rect.width() + 1;
+
+        // snap top?
+        if (dtop < snap_distance && dtop < dbottom)
+          dy = srect.top();
+        // snap bottom?
+        else if (dbottom < snap_distance && dbottom < dtop)
+          dy = srect.bottom() - frame.rect.height() + 1;
+
+        srect = screen->getRect(); // now get the full screen
+
+        dleft = std::abs(wleft - srect.left()),
+        dright = std::abs(wright - srect.right()),
+        dtop = std::abs(wtop - srect.top()),
+        dbottom = std::abs(wbottom - srect.bottom());
+
+        // snap left?
+        if (dleft < snap_distance && dleft < dright)
+          dx = srect.left();
+        // snap right?
+        else if (dright < snap_distance && dright < dleft)
+          dx = srect.right() - frame.rect.width() + 1;
+
+        // snap top?
+        if (dtop < snap_distance && dtop < dbottom)
+          dy = srect.top();
+        // snap bottom?
+        else if (dbottom < snap_distance && dbottom < dtop)
+          dy = srect.bottom() - frame.rect.height() + 1;
+      }
 
+      if (screen->doOpaqueMove()) {
+        configure(dx, dy, frame.rect.width(), frame.rect.height());
+      } else {
+        XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
+                       screen->getOpGC(),
+                       frame.changing.x(),
+                       frame.changing.y(),
+                       frame.changing.width() - 1,
+                       frame.changing.height() - 1);
+
+        frame.changing.setPos(dx, dy);
+
+        XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
+                       screen->getOpGC(),
+                       frame.changing.x(),
+                       frame.changing.y(),
+                       frame.changing.width() - 1,
+                       frame.changing.height() - 1);
+      }
 
-void OpenboxWindow::motionNotifyEvent(XMotionEvent *me) {
-  if (flags.moving)
-    doMove(me->x_root, me->y_root);
-  else if (!flags.resizing && (me->state & Button1Mask) && functions.move &&
-           (frame.title == me->window || frame.label == me->window ||
-            frame.handle == me->window || frame.window == me->window))
-    startMove(me->x_root, me->y_root);
-  else if (functions.resize &&
-           (((me->state & Button1Mask) && (me->window == frame.right_grip ||
-                                           me->window == frame.left_grip)) ||
-            (me->state == (Mod1Mask | Button3Mask) &&
-             me->window == frame.window))) {
-    Bool left = resize_zone & ZoneLeft;
+      screen->showPosition(dx, dy);
+    }
+  } else if ((functions & Func_Resize) &&
+             (((me->state & Button1Mask) &&
+               (me->window == frame.right_grip ||
+                me->window == frame.left_grip)) ||
+              (me->state & (Mod1Mask | Button3Mask) &&
+               me->window == frame.window))) {
+    bool left = (me->window == frame.left_grip);
 
     if (! flags.resizing) {
-      Cursor cursor;
-      if (resize_zone & ZoneTop)
-        cursor = (resize_zone & ZoneLeft) ?
-          openbox.getUpperLeftAngleCursor() :
-          openbox.getUpperRightAngleCursor();
-      else
-        cursor = (resize_zone & ZoneLeft) ?
-          openbox.getLowerLeftAngleCursor() :
-          openbox.getLowerRightAngleCursor();
-      XGrabPointer(display, me->window, False, ButtonMotionMask |
-                   ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None,
-                   cursor, CurrentTime);
+      XGrabServer(blackbox->getXDisplay());
+      XGrabPointer(blackbox->getXDisplay(), me->window, False,
+                   ButtonMotionMask | ButtonReleaseMask,
+                   GrabModeAsync, GrabModeAsync, None,
+                   ((left) ? blackbox->getLowerLeftAngleCursor() :
+                    blackbox->getLowerRightAngleCursor()),
+                   CurrentTime);
 
       flags.resizing = True;
 
-      openbox.grab();
+      int gw, gh;
+      frame.grab_x = me->x;
+      frame.grab_y = me->y;
+      frame.changing = frame.rect;
 
-      int gx, gy;
-      if (resize_zone & ZoneRight)
-        frame.grab_x = me->x - screen->getBorderWidth();
-      else
-        frame.grab_x = me->x + screen->getBorderWidth();
-      if (resize_zone & ZoneTop)
-        frame.grab_y = me->y + screen->getBorderWidth() * 2;
-      else
-        frame.grab_y = me->y - screen->getBorderWidth() * 2;
-      frame.resize_x = frame.x;
-      frame.resize_y = frame.y;
-      frame.resize_w = frame.width + (frame.border_w * 2);
-      frame.resize_h = frame.height + (frame.border_w * 2);
-
-      if (left)
-        left_fixsize(&gx, &gy);
-      else
-        right_fixsize(&gx, &gy);
+      constrain((left) ? TopRight : TopLeft, &gw, &gh);
 
-      screen->showGeometry(gx, gy);
+      XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
+                     screen->getOpGC(), frame.changing.x(), frame.changing.y(),
+                     frame.changing.width() - 1, frame.changing.height() - 1);
 
-      XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
-                     frame.resize_x, frame.resize_y,
-                     frame.resize_w - 1, frame.resize_h - 1);
+      screen->showGeometry(gw, gh);
     } else {
-      XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
-                     frame.resize_x, frame.resize_y,
-                     frame.resize_w - 1, frame.resize_h - 1);
+      XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
+                     screen->getOpGC(), frame.changing.x(), frame.changing.y(),
+                     frame.changing.width() - 1, frame.changing.height() - 1);
 
-      int gx, gy;
+      int gw, gh;
 
-      if (resize_zone & ZoneTop)
-        frame.resize_h = frame.height - (me->y - frame.grab_y);
-      else
-        frame.resize_h = frame.height + (me->y - frame.grab_y);
-      if (frame.resize_h < 1) frame.resize_h = 1;
+      Corner anchor;
 
       if (left) {
-        frame.resize_x = me->x_root - frame.grab_x;
-        if (frame.resize_x > (signed) (frame.x + frame.width))
-          frame.resize_x = frame.resize_x + frame.width - 1;
-
-        left_fixsize(&gx, &gy);
+        anchor = TopRight;
+        frame.changing.setCoords(me->x_root - frame.grab_x, frame.rect.top(),
+                                 frame.rect.right(), frame.rect.bottom());
+        frame.changing.setHeight(frame.rect.height() + (me->y - frame.grab_y));
       } else {
-        frame.resize_w = frame.width + (me->x - frame.grab_x);
-        if (frame.resize_w < 1) frame.resize_w = 1;
-
-        right_fixsize(&gx, &gy);
+        anchor = TopLeft;
+        frame.changing.setSize(frame.rect.width() + (me->x - frame.grab_x),
+                               frame.rect.height() + (me->y - frame.grab_y));
       }
 
-      XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
-                     frame.resize_x, frame.resize_y,
-                     frame.resize_w - 1, frame.resize_h - 1);
+      constrain(anchor, &gw, &gh);
+
+      XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
+                     screen->getOpGC(), frame.changing.x(), frame.changing.y(),
+                     frame.changing.width() - 1, frame.changing.height() - 1);
 
-      screen->showGeometry(gx, gy);
+      screen->showGeometry(gw, gh);
     }
   }
 }
 
 
 #ifdef    SHAPE
-void OpenboxWindow::shapeEvent(XShapeEvent *) {
-  if (openbox.hasShapeExtensions()) {
-    if (flags.shaped) {
-      openbox.grab();
-      if (! validateClient()) return;
-      XShapeCombineShape(display, frame.window, ShapeBounding,
-                         frame.mwm_border_w, frame.y_border +
-                         frame.mwm_border_w, client.window,
-                         ShapeBounding, ShapeSet);
-
-      int num = 1;
-      XRectangle xrect[2];
-      xrect[0].x = xrect[0].y = 0;
-      xrect[0].width = frame.width;
-      xrect[0].height = frame.y_border;
-
-      if (decorations.handle) {
-        xrect[1].x = 0;
-        xrect[1].y = frame.y_handle;
-        xrect[1].width = frame.width;
-        xrect[1].height = frame.handle_h + frame.border_w;
-        num++;
-      }
-
-      XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
-                              xrect, num, ShapeUnion, Unsorted);
-      openbox.ungrab();
-    }
+void BlackboxWindow::shapeEvent(XShapeEvent *) {
+  if (blackbox->hasShapeExtensions() && flags.shaped) {
+    configureShape();
   }
 }
 #endif // SHAPE
 
 
-bool OpenboxWindow::validateClient(void) {
-  XSync(display, False);
+bool BlackboxWindow::validateClient(void) {
+  XSync(blackbox->getXDisplay(), False);
 
   XEvent e;
-  if (XCheckTypedWindowEvent(display, client.window, DestroyNotify, &e) ||
-      XCheckTypedWindowEvent(display, client.window, UnmapNotify, &e)) {
-    XPutBackEvent(display, &e);
-    openbox.ungrab();
+  if (XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window,
+                             DestroyNotify, &e) ||
+      XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window,
+                             UnmapNotify, &e)) {
+    XPutBackEvent(blackbox->getXDisplay(), &e);
 
-    return false;
+    return False;
   }
 
-  return true;
+  return True;
 }
 
 
-void OpenboxWindow::restore(void) {
-  XChangeSaveSet(display, client.window, SetModeDelete);
-  XSelectInput(display, client.window, NoEventMask);
+void BlackboxWindow::restore(bool remap) {
+  XChangeSaveSet(blackbox->getXDisplay(), client.window, SetModeDelete);
+  XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
+  XSelectInput(blackbox->getXDisplay(), frame.plate, NoEventMask);
 
   restoreGravity();
 
-  XUnmapWindow(display, frame.window);
-  XUnmapWindow(display, client.window);
+  XUnmapWindow(blackbox->getXDisplay(), frame.window);
+  XUnmapWindow(blackbox->getXDisplay(), client.window);
 
-  XSetWindowBorderWidth(display, client.window, client.old_bw);
-  XReparentWindow(display, client.window, screen->getRootWindow(),
-                  client.x, client.y);
-  XMapWindow(display, client.window);
+  XSetWindowBorderWidth(blackbox->getXDisplay(), client.window, client.old_bw);
 
-  XFlush(display);
+  XEvent ev;
+  if (! XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window,
+                               ReparentNotify, &ev)) {
+    // according to the ICCCM - if the client doesn't reparent to
+    // root, then we have to do it for them
+    XReparentWindow(blackbox->getXDisplay(), client.window,
+                    screen->getRootWindow(),
+                    client.rect.x(), client.rect.y());
+  }
 
-  delete this;
+  if (remap) XMapWindow(blackbox->getXDisplay(), client.window);
 }
 
 
-void OpenboxWindow::timeout(void) {
-  screen->getWorkspace(workspace_number)->raiseWindow(this);
+// timer for autoraise
+void BlackboxWindow::timeout(void) {
+  screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
 }
 
 
-void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) {
+void BlackboxWindow::changeBlackboxHints(BlackboxHints *net) {
   if ((net->flags & AttribShaded) &&
-      ((openbox_attrib.attrib & AttribShaded) !=
+      ((blackbox_attrib.attrib & AttribShaded) !=
        (net->attrib & AttribShaded)))
     shade();
 
   if (flags.visible && // watch out for requests when we can not be seen
       (net->flags & (AttribMaxVert | AttribMaxHoriz)) &&
-      ((openbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) !=
+      ((blackbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) !=
        (net->attrib & (AttribMaxVert | AttribMaxHoriz)))) {
     if (flags.maximized) {
       maximize(0);
@@ -3075,53 +2686,53 @@ void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) {
   }
 
   if ((net->flags & AttribOmnipresent) &&
-      ((openbox_attrib.attrib & AttribOmnipresent) !=
+      ((blackbox_attrib.attrib & AttribOmnipresent) !=
        (net->attrib & AttribOmnipresent)))
     stick();
 
   if ((net->flags & AttribWorkspace) &&
-      (workspace_number != (signed) net->workspace)) {
+      (blackbox_attrib.workspace != net->workspace)) {
     screen->reassociateWindow(this, net->workspace, True);
 
-    if (screen->getCurrentWorkspaceID() != (signed) net->workspace) withdraw();
-    else deiconify();
+    if (screen->getCurrentWorkspaceID() != net->workspace) {
+      withdraw();
+    } else {
+      show();
+      screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
+    }
   }
 
   if (net->flags & AttribDecoration) {
     switch (net->decoration) {
     case DecorNone:
-      decorations.titlebar = decorations.border = decorations.handle =
-        decorations.iconify = decorations.maximize = decorations.menu = False;
+      // clear all decorations except close
+      decorations &= Decor_Close;
 
       break;
 
     default:
     case DecorNormal:
-      decorations.titlebar = decorations.iconify = decorations.menu =
-        decorations.border = True;
-      decorations.handle = (functions.resize && !flags.transient);
-      decorations.maximize = functions.maximize;
+      decorations |= Decor_Titlebar | Decor_Handle | Decor_Border |
+                     Decor_Iconify | Decor_Maximize;
 
       break;
 
     case DecorTiny:
-      decorations.titlebar = decorations.iconify = decorations.menu = True;
-      decorations.border = decorations.border = decorations.handle = False;
-      decorations.maximize = functions.maximize;
+      decorations |= Decor_Titlebar | Decor_Iconify;
+      decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize);
 
       break;
 
     case DecorTool:
-      decorations.titlebar = decorations.menu = True;
-      decorations.iconify = decorations.border = False;
-      decorations.handle = (functions.resize && !flags.transient);
-      decorations.maximize = functions.maximize;
+      decorations |= Decor_Titlebar;
+      decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle);
+      functions |= Func_Move;
 
       break;
     }
     if (frame.window) {
-      XMapSubwindows(display, frame.window);
-      XMapWindow(display, frame.window);
+      XMapSubwindows(blackbox->getXDisplay(), frame.window);
+      XMapWindow(blackbox->getXDisplay(), frame.window);
     }
 
     reconfigure();
@@ -3134,14 +2745,14 @@ void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) {
  * Set the sizes of all components of the window frame
  * (the window decorations).
  * These values are based upon the current style settings and the client
- * window's dimentions.
+ * window's dimensions.
  */
-void OpenboxWindow::upsize(void) {
+void BlackboxWindow::upsize(void) {
   frame.bevel_w = screen->getBevelWidth();
 
-  if (decorations.border) {
+  if (decorations & Decor_Border) {
     frame.border_w = screen->getBorderWidth();
-    if (!flags.transient)
+    if (!isTransient())
       frame.mwm_border_w = screen->getFrameWidth();
     else
       frame.mwm_border_w = 0;
@@ -3149,7 +2760,7 @@ void OpenboxWindow::upsize(void) {
     frame.mwm_border_w = frame.border_w = 0;
   }
 
-  if (decorations.titlebar) {
+  if (decorations & Decor_Titlebar) {
     // the height of the titlebar is based upon the height of the font being
     // used to display the window's title
     WindowStyle *style = screen->getWindowStyle();
@@ -3161,115 +2772,187 @@ void OpenboxWindow::upsize(void) {
                        (frame.bevel_w * 2) + 2);
 
     frame.label_h = frame.title_h - (frame.bevel_w * 2);
-    frame.button_w = frame.button_h = (frame.label_h - 2);
-    frame.y_border = frame.title_h + frame.border_w;
+    frame.button_w = (frame.label_h - 2);
+
+    // set the top frame margin
+    frame.margin.top = frame.border_w + frame.title_h +
+                       frame.border_w + frame.mwm_border_w;
   } else {
     frame.title_h = 0;
     frame.label_h = 0;
-    frame.button_w = frame.button_h = 0;
-    frame.y_border = 0;
+    frame.button_w = 0;
+
+    // set the top frame margin
+    frame.margin.top = frame.border_w + frame.mwm_border_w;
   }
 
-  frame.border_h = client.height + frame.mwm_border_w * 2;
+  // set the left/right frame margin
+  frame.margin.left = frame.margin.right = frame.border_w + frame.mwm_border_w;
 
-  if (decorations.handle) {
-    frame.y_handle = frame.y_border + frame.border_h + frame.border_w;
+  if (decorations & Decor_Handle) {
     frame.grip_w = frame.button_w * 2;
-    frame.grip_h = frame.handle_h = screen->getHandleWidth();
+    frame.handle_h = screen->getHandleWidth();
+
+    // set the bottom frame margin
+    frame.margin.bottom = frame.border_w + frame.handle_h +
+                          frame.border_w + frame.mwm_border_w;
   } else {
-    frame.y_handle = frame.y_border + frame.border_h;
     frame.handle_h = 0;
-    frame.grip_w = frame.grip_h = 0;
+    frame.grip_w = 0;
+
+    // set the bottom frame margin
+    frame.margin.bottom = frame.border_w + frame.mwm_border_w;
   }
 
-  frame.width = client.width + (frame.mwm_border_w * 2);
-  frame.height = frame.y_handle + frame.handle_h;
+  // set the frame rect
+  frame.rect.setSize(client.rect.width() + frame.margin.left +
+                     frame.margin.right,
+                     client.rect.height() + frame.margin.top +
+                     frame.margin.bottom);
+  frame.inside_w = frame.rect.width() - (frame.border_w * 2);
+  frame.inside_h = frame.rect.height() - (frame.border_w * 2);
 }
 
 
 /*
- * Set the size and position of the client window.
- * These values are based upon the current style settings and the frame
- * window's dimensions.
+ * Calculate the size of the client window and constrain it to the
+ * size specified by the size hints of the client window.
+ *
+ * The logical width and height are placed into pw and ph, if they
+ * are non-zero.  Logical size refers to the users perception of
+ * the window size (for example an xterm has resizes in cells, not in
+ * pixels).
+ *
+ * The physical geometry is placed into frame.changing_{x,y,width,height}.
+ * Physical geometry refers to the geometry of the window in pixels.
  */
-void OpenboxWindow::downsize(void) {
-  frame.y_handle = frame.height - frame.handle_h;
-  frame.border_h = frame.y_handle - frame.y_border -
-    (decorations.handle ? frame.border_w : 0);
+void BlackboxWindow::constrain(Corner anchor, int *pw, int *ph) {
+  // frame.changing represents the requested frame size, we need to
+  // strip the frame margin off and constrain the client size
+  frame.changing.setCoords(frame.changing.left() + frame.margin.left,
+                           frame.changing.top() + frame.margin.top,
+                           frame.changing.right() - frame.margin.right,
+                           frame.changing.bottom() - frame.margin.bottom);
+
+  int dw = frame.changing.width(), dh = frame.changing.height(),
+    base_width = (client.base_width) ? client.base_width : client.min_width,
+    base_height = (client.base_height) ? client.base_height :
+                                         client.min_height;
+
+  // constrain
+  if (dw < static_cast<signed>(client.min_width)) dw = client.min_width;
+  if (dh < static_cast<signed>(client.min_height)) dh = client.min_height;
+  if (dw > static_cast<signed>(client.max_width)) dw = client.max_width;
+  if (dh > static_cast<signed>(client.max_height)) dh = client.max_height;
+
+  dw -= base_width;
+  dw /= client.width_inc;
+  dh -= base_height;
+  dh /= client.height_inc;
+
+  if (pw) *pw = dw;
+  if (ph) *ph = dh;
+
+  dw *= client.width_inc;
+  dw += base_width;
+  dh *= client.height_inc;
+  dh += base_height;
+
+  frame.changing.setSize(dw, dh);
+
+  // add the frame margin back onto frame.changing
+  frame.changing.setCoords(frame.changing.left() - frame.margin.left,
+                           frame.changing.top() - frame.margin.top,
+                           frame.changing.right() + frame.margin.right,
+                           frame.changing.bottom() + frame.margin.bottom);
+
+  // move frame.changing to the specified anchor
+  switch (anchor) {
+  case TopLeft:
+    // nothing to do
+    break;
 
-  client.x = frame.x + frame.mwm_border_w + frame.border_w;
-  client.y = frame.y + frame.y_border + frame.mwm_border_w + frame.border_w;
+  case TopRight:
+    int dx = frame.rect.right() - frame.changing.right();
+    frame.changing.setPos(frame.changing.x() + dx, frame.changing.y());
+    break;
+  }
+}
 
-  client.width = frame.width - (frame.mwm_border_w * 2);
-  client.height = frame.height - frame.y_border - (frame.mwm_border_w * 2)
-    - frame.handle_h - (decorations.handle ? frame.border_w : 0);
 
-  frame.y_handle = frame.border_h + frame.y_border + frame.border_w;
-}
+int WindowStyle::doJustify(const char *text, int &start_pos,
+                           unsigned int max_length, unsigned int modifier,
+                           bool multibyte) const {
+  size_t text_len = strlen(text);
+  unsigned int length;
 
+  do {
+    if (multibyte) {
+      XRectangle ink, logical;
+      XmbTextExtents(fontset, text, text_len, &ink, &logical);
+      length = logical.width;
+    } else {
+      length = XTextWidth(font, text, text_len);
+    }
+    length += modifier;
+  } while (length > max_length && text_len-- > 0);
 
-void OpenboxWindow::right_fixsize(int *gx, int *gy) {
-  // calculate the size of the client window and conform it to the
-  // size specified by the size hints of the client window...
-  int dx = 1 + frame.resize_w - client.base_width - (frame.mwm_border_w * 2) -
-    (frame.border_w * 2) + (client.width_inc / 2);
-  int dy = 1 + frame.resize_h - frame.y_border - client.base_height -
-    frame.handle_h - (frame.border_w * 3) - (frame.mwm_border_w * 2)
-    + (client.height_inc / 2);
+  switch (justify) {
+  case RightJustify:
+    start_pos += max_length - length;
+    break;
 
-  if (dx < (signed) client.min_width) dx = client.min_width;
-  if (dy < (signed) client.min_height) dy = client.min_height;
-  if ((unsigned) dx > client.max_width) dx = client.max_width;
-  if ((unsigned) dy > client.max_height) dy = client.max_height;
+  case CenterJustify:
+    start_pos += (max_length - length) / 2;
+    break;
 
-  dx /= client.width_inc;
-  dy /= client.height_inc;
+  case LeftJustify:
+  default:
+    break;
+  }
 
-  if (gx) *gx = dx;
-  if (gy) *gy = dy;
+  return text_len;
+}
 
-  dx = (dx * client.width_inc) + client.base_width;
-  dy = (dy * client.height_inc) + client.base_height;
 
-  frame.resize_w = dx + (frame.mwm_border_w * 2) + (frame.border_w * 2) - 1;
-  frame.resize_h = dy + frame.y_border + frame.handle_h +
-    (frame.mwm_border_w * 2) +  (frame.border_w * 3) - 1;
-  if (resize_zone & ZoneTop)
-    frame.resize_y = frame.y + frame.height - frame.resize_h +
-      screen->getBorderWidth() * 2;
+BWindowGroup::BWindowGroup(Blackbox *b, Window _group)
+  : blackbox(b), group(_group) {
+  // watch for destroy notify on the group window
+  XSelectInput(blackbox->getXDisplay(), group, StructureNotifyMask);
+  blackbox->saveGroupSearch(group, this);
 }
 
 
-void OpenboxWindow::left_fixsize(int *gx, int *gy) {
-  // calculate the size of the client window and conform it to the
-  // size specified by the size hints of the client window...
-  int dx = 1 + frame.x + frame.width - frame.resize_x - client.base_width -
-    (frame.mwm_border_w * 2) + (client.width_inc / 2);
-  int dy = 1 + frame.resize_h - frame.y_border - client.base_height -
-    frame.handle_h - (frame.border_w * 3) - (frame.mwm_border_w * 2)
-    + (client.height_inc / 2);
+BWindowGroup::~BWindowGroup(void) {
+  blackbox->removeGroupSearch(group);
+}
+
 
-  if (dx < (signed) client.min_width) dx = client.min_width;
-  if (dy < (signed) client.min_height) dy = client.min_height;
-  if ((unsigned) dx > client.max_width) dx = client.max_width;
-  if ((unsigned) dy > client.max_height) dy = client.max_height;
+BlackboxWindow *
+BWindowGroup::find(BScreen *screen, bool allow_transients) const {
+  BlackboxWindow *ret = blackbox->getFocusedWindow();
 
-  dx /= client.width_inc;
-  dy /= client.height_inc;
+  // does the focus window match (or any transient_fors)?
+  while (ret) {
+    if (ret->getScreen() == screen && ret->getGroupWindow() == group) {
+      if (ret->isTransient() && allow_transients) break;
+      else if (! ret->isTransient()) break;
+    }
 
-  if (gx) *gx = dx;
-  if (gy) *gy = dy;
+    ret = ret->getTransientFor();
+  }
 
-  dx = (dx * client.width_inc) + client.base_width;
-  dy = (dy * client.height_inc) + client.base_height;
+  if (ret) return ret;
 
-  frame.resize_w = dx + (frame.mwm_border_w * 2) + (frame.border_w * 2) - 1;
-  frame.resize_x = frame.x + frame.width - frame.resize_w +
-    (frame.border_w * 2);
-  frame.resize_h = dy + frame.y_border + frame.handle_h +
-    (frame.mwm_border_w * 2) + (frame.border_w * 3) - 1;
-  if (resize_zone & ZoneTop)
-    frame.resize_y = frame.y + frame.height - frame.resize_h +
-      screen->getBorderWidth() * 2;
+  // the focus window didn't match, look in the group's window list
+  BlackboxWindowList::const_iterator it, end = windowList.end();
+  for (it = windowList.begin(); it != end; ++it) {
+    ret = *it;
+    if (ret->getScreen() == screen && ret->getGroupWindow() == group) {
+      if (ret->isTransient() && allow_transients) break;
+      else if (! ret->isTransient()) break;
+    }
+  }
 
+  return ret;
 }
diff --git a/src/Window.h b/src/Window.h
deleted file mode 100644 (file)
index b91a41f..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-// Window.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Window_hh
-#define   __Window_hh
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#ifdef    SHAPE
-#  include <X11/extensions/shape.h>
-#endif // SHAPE
-
-#include "BaseDisplay.h"
-#include "Timer.h"
-#include "Windowmenu.h"
-#include "Geometry.h"
-
-// forward declaration
-class OpenboxWindow;
-
-#define MwmHintsFunctions     (1l << 0)
-#define MwmHintsDecorations   (1l << 1)
-
-#define MwmFuncAll            (1l << 0)
-#define MwmFuncResize         (1l << 1)
-#define MwmFuncMove           (1l << 2)
-#define MwmFuncIconify        (1l << 3)
-#define MwmFuncMaximize       (1l << 4)
-#define MwmFuncClose          (1l << 5)
-
-#define MwmDecorAll           (1l << 0)
-#define MwmDecorBorder        (1l << 1)
-#define MwmDecorHandle        (1l << 2)
-#define MwmDecorTitle         (1l << 3)
-#define MwmDecorMenu          (1l << 4)
-#define MwmDecorIconify       (1l << 5)
-#define MwmDecorMaximize      (1l << 6)
-
-// this structure only contains 3 elements... the Motif 2.0 structure contains
-// 5... we only need the first 3... so that is all we will define
-typedef struct MwmHints {
-  unsigned long flags, functions, decorations;
-} MwmHints;
-
-#define PropMwmHintsElements  3
-
-
-class OpenboxWindow : public TimeoutHandler {
-private:
-  BImageControl *image_ctrl;
-  Openbox &openbox;
-  BScreen *screen;
-  Display *display;
-  BTimer *timer;
-  OpenboxAttributes openbox_attrib;
-
-  Time lastButtonPressTime;  // used for double clicks, when were we clicked
-  Windowmenu *windowmenu;
-
-  int window_number, workspace_number;
-  unsigned long current_state;
-  bool place_window;         // place the window ourselves when mapped
-
-  enum FocusMode { F_NoInput = 0, F_Passive,
-                  F_LocallyActive, F_GloballyActive };
-  FocusMode focus_mode;
-
-  enum ResizeZones {
-    ZoneTop     = 1 << 0,
-    ZoneBottom  = 1 << 1,
-    ZoneLeft    = 1 << 2,
-    ZoneRight   = 1 << 3
-  };
-  unsigned int resize_zone;     // bitmask of ResizeZones values
-
-  struct _flags {
-    Bool moving,             // is moving?
-      resizing,              // is resizing?
-      shaded,                // is shaded?
-      visible,               // is visible?
-      iconic,                // is iconified?
-      transient,             // is a transient window?
-      focused,               // has focus?
-      stuck,                 // is omnipresent
-      modal,                 // is modal? (must be dismissed to continue)
-      send_focus_message,    // should we send focus messages to our client?
-      shaped,                // does the frame use the shape extension?
-      managed;               // under openbox's control?
-                             // maximize is special, the number corresponds
-                             // with a mouse button
-                             // if 0, not maximized
-    unsigned int maximized;  // 1 = HorizVert, 2 = Vertical, 3 = Horizontal
-  } flags;
-
-  struct _client {
-    OpenboxWindow *transient_for,   // which window are we a transient for?
-      *transient;                   // which window is our transient?
-
-    Window window,                  // the client's window
-      window_group;                 // the client's window group
-
-    char *title, *icon_title;
-    size_t title_len;               // strlen(title)
-
-    int x, y,
-      old_bw;                       // client's borderwidth
-
-    unsigned int width, height,
-      title_text_w,                 // width as rendered in the current font
-      min_width, min_height,        // can not be resized smaller
-      max_width, max_height,        // can not be resized larger
-      width_inc, height_inc,        // increment step
-      min_aspect_x, min_aspect_y,   // minimum aspect ratio
-      max_aspect_x, max_aspect_y,   // maximum aspect ratio
-      base_width, base_height,
-      win_gravity;
-
-    unsigned long initial_state, normal_hint_flags, wm_hint_flags;
-
-    MwmHints *mwm_hint;
-    OpenboxHints *openbox_hint;
-  } client;
-
-  struct _functions {
-    Bool resize, move, iconify, maximize, close;
-  } functions;
-
-  /*
-   * client window = the application's window
-   * frame window = the window drawn around the outside of the client window
-   *                by the window manager which contains items like the
-   *                titlebar and close button
-   * title = the titlebar drawn above the client window, it displays the
-   *         window's name and any buttons for interacting with the window,
-   *         such as iconify, maximize, and close
-   * label = the window in the titlebar where the title is drawn
-   * buttons = maximize, iconify, close
-   * handle = the bar drawn at the bottom of the window, which contains the
-   *          left and right grips used for resizing the window
-   * grips = the smaller reactangles in the handle, one of each side of it.
-   *         When clicked and dragged, these resize the window interactively
-   * border = the line drawn around the outside edge of the frame window,
-   *          between the title, the bordered client window, and the handle.
-   *          Also drawn between the grips and the handle
-   */
-
-  /*
-   * what decorations do we have?
-   * this is based on the type of the client window as well as user input
-   * the menu is not really decor, but it goes hand in hand with the decor
-   */
-  struct _decorations {
-    Bool titlebar, handle, border, iconify, maximize, close, menu;
-  } decorations;
-
-  struct _frame {
-    // u -> unfocused, f -> has focus
-    unsigned long ulabel_pixel, flabel_pixel, utitle_pixel,
-      ftitle_pixel, uhandle_pixel, fhandle_pixel, ubutton_pixel,
-      fbutton_pixel, pbutton_pixel, uborder_pixel, fborder_pixel,
-      ugrip_pixel, fgrip_pixel;
-    Pixmap ulabel, flabel, utitle, ftitle, uhandle, fhandle,
-      ubutton, fbutton, pbutton, ugrip, fgrip;
-
-    Window window,       // the frame
-      plate,             // holds the client
-      title,
-      label,
-      handle,
-      close_button, iconify_button, maximize_button,
-      right_grip, left_grip;
-
-
-    unsigned int resize_w, resize_h;
-    int resize_x, resize_y,    // size and location of box drawn while resizing
-      move_x, move_y;          // location of box drawn while moving
-
-    int x, y,
-      grab_x, grab_y,          // where was the window when it was grabbed?
-      y_border, y_handle;      // where within frame is the border and handle
-
-    unsigned int width, height, title_h, label_w, label_h, handle_h,
-      button_w, button_h, grip_w, grip_h, mwm_border_w, border_h, border_w,
-      bevel_w;
-  } frame;
-
-protected:
-  Bool getState();
-  Window createToplevelWindow(int x, int y, unsigned int width,
-                             unsigned int height, unsigned int borderwidth);
-  Window createChildWindow(Window parent, Cursor = None);
-
-  void getWMName();
-  void getWMIconName();
-  void getWMNormalHints();
-  void getWMProtocols();
-  void getWMHints();
-  void getMWMHints();
-  void getOpenboxHints();
-  void setNetWMAttributes();
-  void associateClientWindow();
-  void decorate();
-  void decorateLabel();
-  void positionButtons();
-  void positionWindows();
-  void createCloseButton();
-  void createIconifyButton();
-  void createMaximizeButton();
-  void redrawLabel();
-  void redrawAllButtons();
-  void redrawCloseButton(Bool);
-  void redrawIconifyButton(Bool);
-  void redrawMaximizeButton(Bool);
-  void restoreGravity();
-  void setGravityOffsets();
-  void setState(unsigned long);
-  void upsize();
-  void downsize();
-  void right_fixsize(int *gx = 0, int *gy = 0);
-  void left_fixsize(int *gx = 0, int *gy = 0);
-  void doMove(int x, int y);
-
-
-public:
-  OpenboxWindow(Openbox &b, Window w, BScreen *s = (BScreen *) 0);
-  virtual ~OpenboxWindow();
-
-  inline Bool isTransient() const { return flags.transient; }
-  inline Bool isFocused() const { return flags.focused; }
-  inline Bool isVisible() const { return flags.visible; }
-  inline Bool isIconic() const { return flags.iconic; }
-  inline Bool isShaded() const { return flags.shaded; }
-  inline Bool isMaximized() const { return flags.maximized; }
-  inline Bool isMaximizedFull() const { return flags.maximized == 1; }
-  inline Bool isStuck() const { return flags.stuck; }
-  inline Bool isIconifiable() const { return functions.iconify; }
-  inline Bool isMaximizable() const { return functions.maximize; }
-  inline Bool isResizable() const { return functions.resize; }
-  inline Bool isClosable() const { return functions.close; }
-
-  inline Bool hasTitlebar() const { return decorations.titlebar; }
-  inline Bool hasTransient() const
-  { return ((client.transient) ? True : False); }
-
-  inline OpenboxWindow *getTransient() { return client.transient; }
-  inline OpenboxWindow *getTransientFor() { return client.transient_for; }
-
-  inline BScreen *getScreen() { return screen; }
-
-  inline const Window &getFrameWindow() const { return frame.window; }
-  inline const Window &getClientWindow() const { return client.window; }
-
-  inline Windowmenu * getWindowmenu() { return windowmenu; }
-
-  inline char **getTitle() { return &client.title; }
-  inline char **getIconTitle() { return &client.icon_title; }
-  //inline const int &getXFrame() const { return frame.x; }
-  //inline const int &getYFrame() const { return frame.y; }
-  //inline const int &getXClient() const { return client.x; }
-  //inline const int &getYClient() const { return client.y; }
-  inline const int &getWorkspaceNumber() const { return workspace_number; }
-  inline const int &getWindowNumber() const { return window_number; }
-
-  //inline const unsigned int &getWidth() const { return frame.width; }
-  //inline const unsigned int &getHeight() const {
-  //  if (!flags.shaded)
-  //    return frame.height;
-  //  else
-  //    return frame.title_h;
-  //}
-  //inline const unsigned int &getClientHeight() const
-  //{ return client.height; }
-  //inline const unsigned int &getClientWidth() const
-  //{ return client.width; }
-  inline const unsigned int &getTitleHeight() const
-  { return frame.title_h; }
-
-  //inline const Point origin() const {
-  //  return Point(frame.x, frame.y);
-  //}
-  //inline const Point clientOrigin() const {
-  //  return Point(client.x, client.y);
-  //}
-  //inline const Size size() const {
-  //  return Size(frame.width, flags.shaded ? frame.title_h : frame.height);
-  //}
-  //inline const Size clientSize() const {
-  //  return Size(client.width, client.height);
-  //}
-  inline const Rect area() const {
-    return Rect(frame.x, frame.y, frame.width,
-                flags.shaded ? frame.title_h : frame.height);
-  }
-  inline const Rect clientArea() const {
-    return Rect(client.x, client.y, client.width, client.height);
-  }
-  
-  inline void setWindowNumber(int n) { window_number = n; }
-  
-  bool validateClient();
-  bool setInputFocus();
-
-  void setFocusFlag(Bool);
-  void iconify();
-  void deiconify(bool reassoc = true, bool raise = true, bool initial = false);
-  void close();
-  void withdraw();
-  void maximize(unsigned int button);
-  void shade();
-  void stick();
-  void unstick();
-  void reconfigure();
-  void installColormap(Bool);
-  void restore();
-  void configure(int dx, int dy, unsigned int dw, unsigned int dh);
-  void setWorkspace(int n);
-  void changeOpenboxHints(OpenboxHints *);
-  void restoreAttributes();
-
-  void startMove(int x, int y);
-  void endMove();
-  
-  void buttonPressEvent(XButtonEvent *);
-  void buttonReleaseEvent(XButtonEvent *);
-  void motionNotifyEvent(XMotionEvent *);
-  void destroyNotifyEvent(XDestroyWindowEvent *);
-  void mapRequestEvent(XMapRequestEvent *);
-  void mapNotifyEvent(XMapEvent *);
-  void unmapNotifyEvent(XUnmapEvent *);
-  void propertyNotifyEvent(Atom);
-  void exposeEvent(XExposeEvent *);
-  void configureRequestEvent(XConfigureRequestEvent *);
-
-#ifdef    SHAPE
-  void shapeEvent(XShapeEvent *);
-#endif // SHAPE
-
-  virtual void timeout();
-};
-
-
-#endif // __Window_hh
diff --git a/src/Window.hh b/src/Window.hh
new file mode 100644 (file)
index 0000000..9bed279
--- /dev/null
@@ -0,0 +1,363 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Window.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef   __Window_hh
+#define   __Window_hh
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#ifdef    SHAPE
+#  include <X11/extensions/shape.h>
+#endif // SHAPE
+}
+
+#include <string>
+
+#include "BaseDisplay.hh"
+#include "Timer.hh"
+#include "Util.hh"
+#include "Windowmenu.hh"
+
+#define MwmHintsFunctions     (1l << 0)
+#define MwmHintsDecorations   (1l << 1)
+
+#define MwmFuncAll            (1l << 0)
+#define MwmFuncResize         (1l << 1)
+#define MwmFuncMove           (1l << 2)
+#define MwmFuncIconify        (1l << 3)
+#define MwmFuncMaximize       (1l << 4)
+#define MwmFuncClose          (1l << 5)
+
+#define MwmDecorAll           (1l << 0)
+#define MwmDecorBorder        (1l << 1)
+#define MwmDecorHandle        (1l << 2)
+#define MwmDecorTitle         (1l << 3)
+#define MwmDecorMenu          (1l << 4) // not used
+#define MwmDecorIconify       (1l << 5)
+#define MwmDecorMaximize      (1l << 6)
+
+// this structure only contains 3 elements... the Motif 2.0 structure contains
+// 5... we only need the first 3... so that is all we will define
+typedef struct MwmHints {
+  unsigned long flags, functions, decorations;
+} MwmHints;
+
+#define PropMwmHintsElements  3
+
+class BWindowGroup {
+private:
+  Blackbox *blackbox;
+  Window group;
+  BlackboxWindowList windowList;
+
+public:
+  BWindowGroup(Blackbox *b, Window _group);
+  ~BWindowGroup(void);
+
+  inline Window groupWindow(void) const { return group; }
+
+  inline bool empty(void) const { return windowList.empty(); }
+
+  void addWindow(BlackboxWindow *w) { windowList.push_back(w); }
+  void removeWindow(BlackboxWindow *w) { windowList.remove(w); }
+
+  /*
+    find a window on the specified screen. the focused window (if any) is
+    checked first, otherwise the first matching window found is returned.
+    transients are returned only if allow_transients is True.
+  */
+  BlackboxWindow *find(BScreen *screen, bool allow_transients = False) const;
+};
+
+
+class BlackboxWindow : public TimeoutHandler {
+public:
+  enum Function { Func_Resize   = (1l << 0),
+                  Func_Move     = (1l << 1),
+                  Func_Iconify  = (1l << 2),
+                  Func_Maximize = (1l << 3),
+                  Func_Close    = (1l << 4) };
+  typedef unsigned int FunctionFlags;
+
+  enum Decoration { Decor_Titlebar = (1l << 0),
+                    Decor_Handle   = (1l << 1),
+                    Decor_Border   = (1l << 2),
+                    Decor_Iconify  = (1l << 3),
+                    Decor_Maximize = (1l << 4),
+                    Decor_Close    = (1l << 5) };
+  typedef unsigned int DecorationFlags;
+
+private:
+  Blackbox *blackbox;
+  BScreen *screen;
+  BTimer *timer;
+  BlackboxAttributes blackbox_attrib;
+
+  Time lastButtonPressTime;  // used for double clicks, when were we clicked
+  Windowmenu *windowmenu;
+
+  unsigned int window_number;
+  unsigned long current_state;
+
+  enum FocusMode { F_NoInput = 0, F_Passive,
+                   F_LocallyActive, F_GloballyActive };
+  FocusMode focus_mode;
+
+  struct _flags {
+    bool moving,             // is moving?
+      resizing,              // is resizing?
+      shaded,                // is shaded?
+      visible,               // is visible?
+      iconic,                // is iconified?
+      focused,               // has focus?
+      stuck,                 // is omnipresent
+      modal,                 // is modal? (must be dismissed to continue)
+      send_focus_message,    // should we send focus messages to our client?
+      shaped;                // does the frame use the shape extension?
+    unsigned int maximized;  // maximize is special, the number corresponds
+                             // with a mouse button
+                             // if 0, not maximized
+                             // 1 = HorizVert, 2 = Vertical, 3 = Horizontal
+  } flags;
+
+  struct _client {
+    Window window,                  // the client's window
+      window_group;
+    BlackboxWindow *transient_for;  // which window are we a transient for?
+    BlackboxWindowList transientList; // which windows are our transients?
+
+    std::string title, icon_title;
+
+    Rect rect;
+
+    int old_bw;                       // client's borderwidth
+
+    unsigned int
+      min_width, min_height,        // can not be resized smaller
+      max_width, max_height,        // can not be resized larger
+      width_inc, height_inc,        // increment step
+      min_aspect_x, min_aspect_y,   // minimum aspect ratio
+      max_aspect_x, max_aspect_y,   // maximum aspect ratio
+      base_width, base_height,
+      win_gravity;
+
+    unsigned long initial_state, normal_hint_flags, wm_hint_flags;
+  } client;
+
+  FunctionFlags functions;
+  /*
+   * what decorations do we have?
+   * this is based on the type of the client window as well as user input
+   * the menu is not really decor, but it goes hand in hand with the decor
+   */
+  DecorationFlags decorations;
+
+  /*
+   * client window = the application's window
+   * frame window = the window drawn around the outside of the client window
+   *                by the window manager which contains items like the
+   *                titlebar and close button
+   * title = the titlebar drawn above the client window, it displays the
+   *         window's name and any buttons for interacting with the window,
+   *         such as iconify, maximize, and close
+   * label = the window in the titlebar where the title is drawn
+   * buttons = maximize, iconify, close
+   * handle = the bar drawn at the bottom of the window, which contains the
+   *          left and right grips used for resizing the window
+   * grips = the smaller reactangles in the handle, one of each side of it.
+   *         When clicked and dragged, these resize the window interactively
+   * border = the line drawn around the outside edge of the frame window,
+   *          between the title, the bordered client window, and the handle.
+   *          Also drawn between the grips and the handle
+   */
+
+  struct _frame {
+    // u -> unfocused, f -> has focus
+    unsigned long ulabel_pixel, flabel_pixel, utitle_pixel,
+      ftitle_pixel, uhandle_pixel, fhandle_pixel, ubutton_pixel,
+      fbutton_pixel, pbutton_pixel, uborder_pixel, fborder_pixel,
+      ugrip_pixel, fgrip_pixel;
+    Pixmap ulabel, flabel, utitle, ftitle, uhandle, fhandle,
+      ubutton, fbutton, pbutton, ugrip, fgrip;
+
+    Window window,       // the frame
+      plate,             // holds the client
+      title,
+      label,
+      handle,
+      close_button, iconify_button, maximize_button,
+      right_grip, left_grip;
+
+    /*
+     * size and location of the box drawn while the window dimensions or
+     * location is being changed, ie. resized or moved
+     */
+    Rect changing;
+
+    Rect rect;                  // frame geometry
+    Strut margin;               // margins between the frame and client
+
+    int grab_x, grab_y;         // where was the window when it was grabbed?
+
+    unsigned int inside_w, inside_h, // window w/h without border_w
+      title_h, label_w, label_h, handle_h,
+      button_w, grip_w, mwm_border_w, border_w,
+      bevel_w;
+  } frame;
+
+  BlackboxWindow(const BlackboxWindow&);
+  BlackboxWindow& operator=(const BlackboxWindow&);
+
+  bool getState(void);
+  Window createToplevelWindow();
+  Window createChildWindow(Window parent, Cursor = None);
+
+  void getWMName(void);
+  void getWMIconName(void);
+  void getWMNormalHints(void);
+  void getWMProtocols(void);
+  void getWMHints(void);
+  void getMWMHints(void);
+  bool getBlackboxHints(void);
+  void getTransientInfo(void);
+  void setNetWMAttributes(void);
+  void associateClientWindow(void);
+  void decorate(void);
+  void decorateLabel(void);
+  void positionButtons(bool redecorate_label = False);
+  void positionWindows(void);
+  void createHandle(void);
+  void destroyHandle(void);
+  void createTitlebar(void);
+  void destroyTitlebar(void);
+  void createCloseButton(void);
+  void destroyCloseButton(void);
+  void createIconifyButton(void);
+  void destroyIconifyButton(void);
+  void createMaximizeButton(void);
+  void destroyMaximizeButton(void);
+  void redrawLabel(void);
+  void redrawAllButtons(void);
+  void redrawCloseButton(bool pressed);
+  void redrawIconifyButton(bool pressed);
+  void redrawMaximizeButton(bool pressed);
+  void restoreGravity(void);
+  void setGravityOffsets(void);
+  void setState(unsigned long new_state);
+  void upsize(void);
+
+  enum Corner { TopLeft, TopRight };
+  void constrain(Corner anchor, int *pw = 0, int *ph = 0);
+
+public:
+  BlackboxWindow(Blackbox *b, Window w, BScreen *s);
+  virtual ~BlackboxWindow(void);
+
+  inline bool isTransient(void) const { return client.transient_for != 0; }
+  inline bool isFocused(void) const { return flags.focused; }
+  inline bool isVisible(void) const { return flags.visible; }
+  inline bool isIconic(void) const { return flags.iconic; }
+  inline bool isShaded(void) const { return flags.shaded; }
+  inline bool isMaximized(void) const { return flags.maximized; }
+  inline bool isStuck(void) const { return flags.stuck; }
+  inline bool isIconifiable(void) const { return functions & Func_Iconify; }
+  inline bool isMaximizable(void) const { return functions & Func_Maximize; }
+  inline bool isResizable(void) const { return functions & Func_Resize; }
+  inline bool isClosable(void) const { return functions & Func_Close; }
+
+  inline bool hasTitlebar(void) const { return decorations & Decor_Titlebar; }
+
+  inline const BlackboxWindowList &getTransients(void) const
+  { return client.transientList; }
+  BlackboxWindow *getTransientFor(void) const;
+
+  inline BScreen *getScreen(void) { return screen; }
+
+  inline Window getFrameWindow(void) const { return frame.window; }
+  inline Window getClientWindow(void) const { return client.window; }
+  inline Window getGroupWindow(void) const { return client.window_group; }
+
+  inline Windowmenu * getWindowmenu(void) { return windowmenu; }
+
+  inline const char *getTitle(void) const
+  { return client.title.c_str(); }
+  inline const char *getIconTitle(void) const
+  { return client.icon_title.c_str(); }
+
+  inline unsigned int getWorkspaceNumber(void) const
+  { return blackbox_attrib.workspace; }
+  inline unsigned int getWindowNumber(void) const { return window_number; }
+
+  inline const Rect &frameRect(void) const { return frame.rect; }
+  inline const Rect &clientRect(void) const { return client.rect; }
+
+  inline unsigned int getTitleHeight(void) const
+  { return frame.title_h; }
+
+  inline void setWindowNumber(int n) { window_number = n; }
+
+  bool validateClient(void);
+  bool setInputFocus(void);
+
+  void setFocusFlag(bool focus);
+  void iconify(void);
+  void deiconify(bool reassoc = True, bool raise = True);
+  void show(void);
+  void close(void);
+  void withdraw(void);
+  void maximize(unsigned int button);
+  void remaximize(void);
+  void shade(void);
+  void stick(void);
+  void unstick(void);
+  void reconfigure(void);
+  void updateFocusModel(void);
+  void installColormap(bool install);
+  void restore(bool remap);
+  void configure(int dx, int dy, unsigned int dw, unsigned int dh);
+  void setWorkspace(unsigned int n);
+  void changeBlackboxHints(BlackboxHints *net);
+  void restoreAttributes(void);
+
+  void buttonPressEvent(XButtonEvent *be);
+  void buttonReleaseEvent(XButtonEvent *re);
+  void motionNotifyEvent(XMotionEvent *me);
+  void destroyNotifyEvent(XDestroyWindowEvent */*unused*/);
+  void mapRequestEvent(XMapRequestEvent *mre);
+  void unmapNotifyEvent(XUnmapEvent */*unused*/);
+  void reparentNotifyEvent(XReparentEvent */*unused*/);
+  void propertyNotifyEvent(Atom atom);
+  void exposeEvent(XExposeEvent *ee);
+  void configureRequestEvent(XConfigureRequestEvent *cr);
+
+#ifdef    SHAPE
+  void configureShape(void);
+  void shapeEvent(XShapeEvent * /*unused*/);
+#endif // SHAPE
+
+  virtual void timeout(void);
+};
+
+
+#endif // __Window_hh
index 6f216e5c90395846c7c1ba51057d3c590cb872e7..f274a047e3cc38e121503bd305154b48d29dac3a 100644 (file)
@@ -1,5 +1,6 @@
-// Windowmenu.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Windowmenu.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "i18n.h"
-#include "openbox.h"
-#include "Screen.h"
-#include "Window.h"
-#include "Windowmenu.h"
-#include "Workspace.h"
-
-#ifdef    HAVE_STRING_H
+extern "C" {
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
+}
 
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "Screen.hh"
+#include "Window.hh"
+#include "Windowmenu.hh"
+#include "Workspace.hh"
 
-Windowmenu::Windowmenu(OpenboxWindow &win) : Basemenu(*win.getScreen()),
-window(win), screen(*win.getScreen())
-{
+
+Windowmenu::Windowmenu(BlackboxWindow *win) : Basemenu(win->getScreen()) {
+  window = win;
 
   setTitleVisibility(False);
   setMovable(False);
   setInternalMenu();
 
-  sendToMenu = new SendtoWorkspacemenu(*this);
+  sendToMenu = new SendtoWorkspacemenu(this);
   insert(i18n(WindowmenuSet, WindowmenuSendTo, "Send To ..."),
          sendToMenu);
   insert(i18n(WindowmenuSet, WindowmenuShade, "Shade"),
@@ -72,10 +68,10 @@ window(win), screen(*win.getScreen())
 
   update();
 
-  setItemEnabled(1, window.hasTitlebar());
-  setItemEnabled(2, window.isIconifiable());
-  setItemEnabled(3, window.isMaximizable());
-  setItemEnabled(8, window.isClosable());
+  setItemEnabled(1, window->hasTitlebar());
+  setItemEnabled(2, window->isIconifiable());
+  setItemEnabled(3, window->isMaximizable());
+  setItemEnabled(8, window->isClosable());
 }
 
 
@@ -85,71 +81,64 @@ Windowmenu::~Windowmenu(void) {
 
 
 void Windowmenu::show(void) {
-  if (isItemEnabled(1)) setItemSelected(1, window.isShaded());
-  if (isItemEnabled(3)) setItemSelected(3, window.isMaximized());
-  if (isItemEnabled(6)) setItemSelected(6, window.isStuck());
+  if (isItemEnabled(1)) setItemSelected(1, window->isShaded());
+  if (isItemEnabled(3)) setItemSelected(3, window->isMaximized());
+  if (isItemEnabled(6)) setItemSelected(6, window->isStuck());
 
   Basemenu::show();
 }
 
 
-void Windowmenu::itemSelected(int button, int index) {
+void Windowmenu::itemSelected(int button, unsigned int index) {
   BasemenuItem *item = find(index);
 
-  /* Added by Scott Moynes, April 8, 2002
-     Ignore the middle button for every item except the maximize
-     button in the window menu. Maximize needs it for
-     horizontal/vertical maximize, however, for the others it is
-     inconsistent with the rest of the window behaviour.
-     */
-  if(button != 2) {
-    hide();
-    switch (item->function()) {
-    case BScreen::WindowShade:
-      window.shade();
-      break;
-
-    case BScreen::WindowIconify:
-      window.iconify();
-      break;
-
-    case BScreen::WindowMaximize:
-      window.maximize((unsigned int) button);
-      break;
-
-    case BScreen::WindowClose:
-      window.close();
-      break;
-
-    case BScreen::WindowRaise:
-      screen.getWorkspace(window.getWorkspaceNumber())->raiseWindow(&window);
-      break;
-
-    case BScreen::WindowLower:
-      screen.getWorkspace(window.getWorkspaceNumber())->lowerWindow(&window);
-      break;
-
-    case BScreen::WindowStick:
-      window.stick();
-      break;
-
-    case BScreen::WindowKill:
-      XKillClient(screen.getBaseDisplay().getXDisplay(),
-                  window.getClientWindow());
-      break;
-    }
-  } else if (item->function() == BScreen::WindowMaximize) {
-    hide();
-    window.maximize((unsigned int) button);
+  hide();
+  switch (item->function()) {
+  case BScreen::WindowShade:
+    window->shade();
+    break;
+
+  case BScreen::WindowIconify:
+    window->iconify();
+    break;
+
+  case BScreen::WindowMaximize:
+    window->maximize(button);
+    break;
+
+  case BScreen::WindowClose:
+    window->close();
+    break;
+
+  case BScreen::WindowRaise: {
+    Workspace *wkspc = getScreen()->getWorkspace(window->getWorkspaceNumber());
+    wkspc->raiseWindow(window);
+  }
+    break;
+
+  case BScreen::WindowLower: {
+    Workspace *wkspc = getScreen()->getWorkspace(window->getWorkspaceNumber());
+    wkspc->lowerWindow(window);
+  }
+    break;
+
+  case BScreen::WindowStick:
+    window->stick();
+    break;
+
+  case BScreen::WindowKill:
+    XKillClient(getScreen()->getBaseDisplay()->getXDisplay(),
+                window->getClientWindow());
+    break;
   }
 }
 
 
 void Windowmenu::reconfigure(void) {
-  setItemEnabled(1, window.hasTitlebar());
-  setItemEnabled(2, window.isIconifiable());
-  setItemEnabled(3, window.isMaximizable());
-  setItemEnabled(8, window.isClosable());
+  setItemEnabled(1, window->hasTitlebar());
+  setItemEnabled(2, window->isIconifiable());
+  setItemEnabled(3, window->isMaximizable());
+  setItemEnabled(8, window->isClosable());
 
   sendToMenu->reconfigure();
 
@@ -157,39 +146,51 @@ void Windowmenu::reconfigure(void) {
 }
 
 
-Windowmenu::SendtoWorkspacemenu::SendtoWorkspacemenu(Windowmenu &w)
-  : Basemenu(w.screen), windowmenu(w) {
-    setTitleVisibility(False);
-    setMovable(False);
-    setInternalMenu();
-    update();
-  }
+Windowmenu::SendtoWorkspacemenu::SendtoWorkspacemenu(Windowmenu *w)
+  : Basemenu(w->getScreen()) {
 
+  window = w->window;
 
-void Windowmenu::SendtoWorkspacemenu::itemSelected(int button, int index) {
+  setTitleVisibility(False);
+  setMovable(False);
+  setInternalMenu();
+  update();
+}
+
+
+void Windowmenu::SendtoWorkspacemenu::itemSelected(int button,
+                                                   unsigned int index) {
   if (button > 2) return;
 
-  if (index <= windowmenu.screen.getWorkspaceCount()) {
-    if (index == windowmenu.screen.getCurrentWorkspaceID()) return;
-    if (windowmenu.window.isStuck()) windowmenu.window.stick();
+  if (index <= getScreen()->getWorkspaceCount()) {
+    if (index == getScreen()->getCurrentWorkspaceID()) return;
+    if (window->isStuck()) window->stick();
 
-    if (button == 1) windowmenu.window.withdraw();
-    windowmenu.screen.reassociateWindow(&(windowmenu.window), index, True);
-    if (button == 2) windowmenu.screen.changeWorkspaceID(index);
+    if (button == 1) window->withdraw();
+    getScreen()->reassociateWindow(window, index, True);
+    if (button == 2) getScreen()->changeWorkspaceID(index);
   }
   hide();
 }
 
 
 void Windowmenu::SendtoWorkspacemenu::update(void) {
-  int i, r = getCount();
-
-  if (r != 0)
-    for (i = 0; i < r; ++i)
+  unsigned int i, r = getCount(),
+    workspace_count = getScreen()->getWorkspaceCount();
+  if (r > workspace_count) {
+    for (i = r; i < workspace_count; ++i)
       remove(0);
+    r = getCount();
+  }
 
-  for (i = 0; i < windowmenu.screen.getWorkspaceCount(); ++i)
-    insert(windowmenu.screen.getWorkspace(i)->getName());
+  for (i = 0; i < workspace_count; ++i) {
+    if (r < workspace_count) {
+      insert(getScreen()->getWorkspace(i)->getName());
+      ++r;
+    } else {
+      changeItemLabel(i, getScreen()->getWorkspace(i)->getName());
+    }
+  }
 
   Basemenu::update();
 }
diff --git a/src/Windowmenu.h b/src/Windowmenu.h
deleted file mode 100644 (file)
index d892abc..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// Windowmenu.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Windowmenu_hh
-#define   __Windowmenu_hh
-
-#include "Basemenu.h"
-
-// forward declaration
-class Windowmenu;
-class SendtoWorkspaceMenu;
-
-class Openbox;
-class OpenboxWindow;
-class Toolbar;
-
-class Windowmenu : public Basemenu {
-private:
-  OpenboxWindow &window;
-  BScreen &screen;
-
-  class SendtoWorkspacemenu : public Basemenu {
-  private:
-    Windowmenu &windowmenu;
-
-  protected:
-    virtual void itemSelected(int, int);
-
-  public:
-    SendtoWorkspacemenu(Windowmenu &);
-
-    void update(void);
-
-    virtual void show(void);
-  };
-
-  SendtoWorkspacemenu *sendToMenu;
-
-  friend class SendtoWorkspacemenu;
-
-
-protected:
-  virtual void itemSelected(int, int);
-
-
-public:
-  Windowmenu(OpenboxWindow &);
-  virtual ~Windowmenu(void);
-
-  inline Basemenu *getSendToMenu(void) { return (Basemenu *) sendToMenu; }
-
-  void reconfigure(void);
-  void setClosable(void);
-
-  virtual void show(void);
-};
-
-
-#endif // __Windowmenu_hh
index 47ad3827f2ec2ea55053f088308c1f6c301f5549..3ef99ea749d054ac3e1016b17e9808af9517dd0e 100644 (file)
@@ -1,6 +1,6 @@
-// Workspace.cc for Openbox
-// Copyright (c) 2002 - 2002 Ben Jansens (ben@orodu.net)
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Workspace.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
 #ifdef    HAVE_STDIO_H
 #  include <stdio.h>
 #endif // HAVE_STDIO_H
 
-#ifdef    HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif // HAVE_STDLIB_H
-
-#ifdef    HAVE_STRING_H
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
+}
 
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
+#include <functional>
+#include <string>
 
-#include "i18n.h"
-#include "openbox.h"
-#include "Clientmenu.h"
-#include "Screen.h"
-#include "Toolbar.h"
-#include "Window.h"
-#include "Workspace.h"
-#include "Windowmenu.h"
-#include "Geometry.h"
-#include "Util.h"
-
-#include <algorithm>
-#include <vector>
-typedef std::vector<Rect> rectList;
+using std::string;
 
-Workspace::Workspace(BScreen &scrn, int i) : screen(scrn) {
-  cascade_x = cascade_y = 0;
-  _focused = _last = (OpenboxWindow *) 0;
-  id = i;
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "Clientmenu.hh"
+#include "Netizen.hh"
+#include "Screen.hh"
+#include "Toolbar.hh"
+#include "Util.hh"
+#include "Window.hh"
+#include "Workspace.hh"
+#include "Windowmenu.hh"
 
-  clientmenu = new Clientmenu(*this);
 
-  name = (char *) 0;
-  setName(screen.getNameOfWorkspace(id));
-}
+Workspace::Workspace(BScreen *scrn, unsigned int i) {
+  screen = scrn;
 
+  cascade_x = cascade_y = 32;
 
-Workspace::~Workspace(void) {
-  delete clientmenu;
+  id = i;
 
-  if (name)
-    delete [] name;
+  clientmenu = new Clientmenu(this);
+
+  lastfocus = (BlackboxWindow *) 0;
+
+  setName(screen->getNameOfWorkspace(id));
 }
 
 
-int Workspace::addWindow(OpenboxWindow *w, bool place) {
-  if (! w) return -1;
+void Workspace::addWindow(BlackboxWindow *w, bool place) {
+  assert(w != 0);
 
-  if (place) placeWindow(*w);
+  if (place) placeWindow(w);
 
   w->setWorkspace(id);
-  w->setWindowNumber(_windows.size());
+  w->setWindowNumber(windowList.size());
 
-  _zorder.push_front(w);
-  _windows.push_back(w);
+  stackingList.push_front(w);
+  windowList.push_back(w);
 
-  clientmenu->insert((const char **) w->getTitle());
+  clientmenu->insert(w->getTitle());
   clientmenu->update();
 
-  screen.updateNetizenWindowAdd(w->getClientWindow(), id);
+  screen->updateNetizenWindowAdd(w->getClientWindow(), id);
 
   raiseWindow(w);
-
-  return w->getWindowNumber();
 }
 
 
-int Workspace::removeWindow(OpenboxWindow *w) {
-  if (! w) return -1;
+unsigned int Workspace::removeWindow(BlackboxWindow *w) {
+  assert(w != 0);
 
-  winVect::iterator winit = std::find(_windows.begin(), _windows.end(), w);
+  stackingList.remove(w);
 
-  if (winit == _windows.end()) {
-    if (w == _last)
-      _last = (OpenboxWindow *) 0;
-    if (w == _focused)
-      _focused = (OpenboxWindow *) 0;
-    return _windows.size();
+  if (w->isFocused() && ! screen->getBlackbox()->doShutdown()) {
+    BlackboxWindow *newfocus = 0;
+    if (w->isTransient())
+      newfocus = w->getTransientFor();
+    if (! newfocus && ! stackingList.empty())
+      newfocus = stackingList.front();
+    if (! newfocus || ! newfocus->setInputFocus())
+      screen->getBlackbox()->setFocusedWindow(0);
   }
-  
-  _zorder.remove(w);
-
-  if (w == _last)
-    _last = (OpenboxWindow *) 0;
-  if (w == _focused) {
-    OpenboxWindow *fw = (OpenboxWindow *) 0;
-    if (w->isTransient() && w->getTransientFor() &&
-        w->getTransientFor()->isVisible())
-      fw = w->getTransientFor();
-    else if (screen.sloppyFocus())             // sloppy focus
-      fw = (OpenboxWindow *) 0;
-    else if (!_zorder.empty())                 // click focus
-      fw = _zorder.front();
-
-    if (!(fw != (OpenboxWindow *) 0 && fw->setInputFocus()))
-      screen.getOpenbox().focusWindow(0);
-  }
-  
-  _windows.erase(winit);
+
+  if (lastfocus == w)
+    lastfocus = (BlackboxWindow *) 0;
+
+  windowList.remove(w);
   clientmenu->remove(w->getWindowNumber());
   clientmenu->update();
 
-  screen.updateNetizenWindowDel(w->getClientWindow());
+  screen->updateNetizenWindowDel(w->getClientWindow());
 
-  winVect::iterator it = _windows.begin();
-  for (int i=0; it != _windows.end(); ++it, ++i)
+  BlackboxWindowList::iterator it = windowList.begin();
+  const BlackboxWindowList::iterator end = windowList.end();
+  unsigned int i = 0;
+  for (; it != end; ++it, ++i)
     (*it)->setWindowNumber(i);
 
-  return _windows.size();
-}
-
+  if (i == 0)
+    cascade_x = cascade_y = 32;
 
-void Workspace::focusWindow(OpenboxWindow *win) {
-  if (_focused != (OpenboxWindow *) 0)
-    clientmenu->setItemSelected(_focused->getWindowNumber(), false);
-  _focused = win;
-  // make sure the focused window belongs to this workspace before highlighting
-  // it in the menu (sticky windows arent in this workspace's menu).
-  if (_focused != (OpenboxWindow *) 0 && _focused->getWorkspaceNumber() == id)
-    clientmenu->setItemSelected(_focused->getWindowNumber(), true);
-  if (win != (OpenboxWindow *) 0)
-    _last = win;
+  return i;
 }
 
 
 void Workspace::showAll(void) {
-  winList::iterator it;
-  for (it = _zorder.begin(); it != _zorder.end(); ++it)
-    (*it)->deiconify(false, false);
+  std::for_each(stackingList.begin(), stackingList.end(),
+                std::mem_fun(&BlackboxWindow::show));
 }
 
 
 void Workspace::hideAll(void) {
-  winList::reverse_iterator it;
-  for (it = _zorder.rbegin(); it != _zorder.rend(); ++it)
-    if (!(*it)->isStuck())
-      (*it)->withdraw();
-}
+  // withdraw in reverse order to minimize the number of Expose events
 
+  BlackboxWindowList lst(stackingList.rbegin(), stackingList.rend());
 
-void Workspace::removeAll(void) {
-  winVect::iterator it;
-  for (it = _windows.begin(); it != _windows.end(); ++it)
-    (*it)->iconify();
+  BlackboxWindowList::iterator it = lst.begin();
+  const BlackboxWindowList::iterator end = lst.end();
+  for (; it != end; ++it) {
+    BlackboxWindow *bw = *it;
+    if (! bw->isStuck())
+      bw->withdraw();
+  }
 }
 
 
-void Workspace::raiseWindow(OpenboxWindow *w) {
-  OpenboxWindow *win = (OpenboxWindow *) 0, *bottom = w;
+void Workspace::removeAll(void) {
+  while (! windowList.empty())
+    windowList.front()->iconify();
+}
 
-  while (bottom->isTransient() && bottom->getTransientFor())
-    bottom = bottom->getTransientFor();
 
-  int i = 1;
-  win = bottom;
-  while (win->hasTransient() && win->getTransient()) {
-    win = win->getTransient();
+/*
+ * returns the number of transients for win, plus the number of transients
+ * associated with each transient of win
+ */
+static int countTransients(const BlackboxWindow * const win) {
+  int ret = win->getTransients().size();
+  if (ret > 0) {
+    BlackboxWindowList::const_iterator it, end = win->getTransients().end();
+    for (it = win->getTransients().begin(); it != end; ++it) {
+      ret += countTransients(*it);
+    }
+  }
+  return ret;
+}
+
+
+/*
+ * puts the transients of win into the stack. windows are stacked above
+ * the window before it in the stackvector being iterated, meaning
+ * stack[0] is on bottom, stack[1] is above stack[0], stack[2] is above
+ * stack[1], etc...
+ */
+void Workspace::raiseTransients(const BlackboxWindow * const win,
+                                StackVector::iterator &stack) {
+  if (win->getTransients().size() == 0) return; // nothing to do
+
+  // put win's transients in the stack
+  BlackboxWindowList::const_iterator it, end = win->getTransients().end();
+  for (it = win->getTransients().begin(); it != end; ++it) {
+    *stack++ = (*it)->getFrameWindow();
+    screen->updateNetizenWindowRaise((*it)->getClientWindow());
+
+    if (! (*it)->isIconic()) {
+      Workspace *wkspc = screen->getWorkspace((*it)->getWorkspaceNumber());
+      wkspc->stackingList.remove((*it));
+      wkspc->stackingList.push_front((*it));
+    }
+  }
 
-    i++;
+  // put transients of win's transients in the stack
+  for (it = win->getTransients().begin(); it != end; ++it) {
+    raiseTransients(*it, stack);
   }
+}
 
-  Window *nstack = new Window[i], *curr = nstack;
-  Workspace *wkspc;
 
-  win = bottom;
-  while (true) {
-    *(curr++) = win->getFrameWindow();
-    screen.updateNetizenWindowRaise(win->getClientWindow());
+void Workspace::lowerTransients(const BlackboxWindow * const win,
+                                StackVector::iterator &stack) {
+  if (win->getTransients().size() == 0) return; // nothing to do
 
-    if (! win->isIconic()) {
-      wkspc = screen.getWorkspace(win->getWorkspaceNumber());
-      wkspc->_zorder.remove(win);
-      wkspc->_zorder.push_front(win);
-    }
+  // put transients of win's transients in the stack
+  BlackboxWindowList::const_reverse_iterator it,
+    end = win->getTransients().rend();
+  for (it = win->getTransients().rbegin(); it != end; ++it) {
+    lowerTransients(*it, stack);
+  }
 
-    if (! win->hasTransient() || ! win->getTransient())
-      break;
+  // put win's transients in the stack
+  for (it = win->getTransients().rbegin(); it != end; ++it) {
+    *stack++ = (*it)->getFrameWindow();
+    screen->updateNetizenWindowLower((*it)->getClientWindow());
 
-    win = win->getTransient();
+    if (! (*it)->isIconic()) {
+      Workspace *wkspc = screen->getWorkspace((*it)->getWorkspaceNumber());
+      wkspc->stackingList.remove((*it));
+      wkspc->stackingList.push_back((*it));
+    }
   }
 
-  screen.raiseWindows(nstack, i);
-
-  delete [] nstack;
 }
 
 
-void Workspace::lowerWindow(OpenboxWindow *w) {
-  OpenboxWindow *win = (OpenboxWindow *) 0, *bottom = w;
+void Workspace::raiseWindow(BlackboxWindow *w) {
+  BlackboxWindow *win = w;
+
+  // walk up the transient_for's to the window that is not a transient
+  while (win->isTransient()) {
+    if (! win->getTransientFor()) break;
+    win = win->getTransientFor();
+  }
 
-  while (bottom->isTransient() && bottom->getTransientFor())
-    bottom = bottom->getTransientFor();
+  // get the total window count (win and all transients)
+  unsigned int i = 1 + countTransients(win);
 
-  int i = 1;
-  win = bottom;
-  while (win->hasTransient() && win->getTransient()) {
-    win = win->getTransient();
+  // stack the window with all transients above
+  StackVector stack_vector(i);
+  StackVector::iterator stack = stack_vector.begin();
 
-    i++;
+  *(stack++) = win->getFrameWindow();
+  screen->updateNetizenWindowRaise(win->getClientWindow());
+  if (! win->isIconic()) {
+    Workspace *wkspc = screen->getWorkspace(win->getWorkspaceNumber());
+    wkspc->stackingList.remove(win);
+    wkspc->stackingList.push_front(win);
   }
 
-  Window *nstack = new Window[i], *curr = nstack;
-  Workspace *wkspc;
+  raiseTransients(win, stack);
 
-  while (true) {
-    *(curr++) = win->getFrameWindow();
-    screen.updateNetizenWindowLower(win->getClientWindow());
+  screen->raiseWindows(&stack_vector[0], stack_vector.size());
+}
 
-    if (! win->isIconic()) {
-      wkspc = screen.getWorkspace(win->getWorkspaceNumber());
-      wkspc->_zorder.remove(win);
-      wkspc->_zorder.push_back(win);
-    }
 
-    if (! win->getTransientFor())
-      break;
+void Workspace::lowerWindow(BlackboxWindow *w) {
+  BlackboxWindow *win = w;
 
+  // walk up the transient_for's to the window that is not a transient
+  while (win->isTransient()) {
+    if (! win->getTransientFor()) break;
     win = win->getTransientFor();
   }
 
-  screen.getOpenbox().grab();
+  // get the total window count (win and all transients)
+  unsigned int i = 1 + countTransients(win);
+
+  // stack the window with all transients above
+  StackVector stack_vector(i);
+  StackVector::iterator stack = stack_vector.begin();
 
-  XLowerWindow(screen.getBaseDisplay().getXDisplay(), *nstack);
-  XRestackWindows(screen.getBaseDisplay().getXDisplay(), nstack, i);
+  lowerTransients(win, stack);
 
-  screen.getOpenbox().ungrab();
+  *(stack++) = win->getFrameWindow();
+  screen->updateNetizenWindowLower(win->getClientWindow());
+  if (! win->isIconic()) {
+    Workspace *wkspc = screen->getWorkspace(win->getWorkspaceNumber());
+    wkspc->stackingList.remove(win);
+    wkspc->stackingList.push_back(win);
+  }
 
-  delete [] nstack;
+  XLowerWindow(screen->getBaseDisplay()->getXDisplay(), stack_vector.front());
+  XRestackWindows(screen->getBaseDisplay()->getXDisplay(),
+                  &stack_vector[0], stack_vector.size());
 }
 
 
 void Workspace::reconfigure(void) {
   clientmenu->reconfigure();
+  std::for_each(windowList.begin(), windowList.end(),
+                std::mem_fun(&BlackboxWindow::reconfigure));
+}
+
 
-  winVect::iterator it;
-  for (it = _windows.begin(); it != _windows.end(); ++it)
-    if ((*it)->validateClient())
-      (*it)->reconfigure();
+void Workspace::updateFocusModel(void) {
+  std::for_each(windowList.begin(), windowList.end(),
+                std::mem_fun(&BlackboxWindow::updateFocusModel));
 }
 
 
-OpenboxWindow *Workspace::getWindow(int index) {
-  if ((index >= 0) && (index < (signed)_windows.size()))
-    return _windows[index];
-  else
-    return (OpenboxWindow *) 0;
+BlackboxWindow *Workspace::getWindow(unsigned int index) {
+  if (index < windowList.size()) {
+    BlackboxWindowList::iterator it = windowList.begin();
+    for(; index > 0; --index, ++it); /* increment to index */
+    return *it;
+  }
+  return 0;
 }
 
 
-int Workspace::getCount(void) {
-  return (signed)_windows.size();
+BlackboxWindow*
+Workspace::getNextWindowInList(BlackboxWindow *w) {
+  BlackboxWindowList::iterator it = std::find(windowList.begin(),
+                                              windowList.end(),
+                                              w);
+  assert(it != windowList.end());   // window must be in list
+  ++it;                             // next window
+  if (it == windowList.end())
+    return windowList.front();      // if we walked off the end, wrap around
+
+  return *it;
 }
 
 
-void Workspace::update(void) {
-  clientmenu->update();
-  screen.getToolbar()->redrawWindowLabel(true);
+BlackboxWindow* Workspace::getPrevWindowInList(BlackboxWindow *w) {
+  BlackboxWindowList::iterator it = std::find(windowList.begin(),
+                                              windowList.end(),
+                                              w);
+  assert(it != windowList.end()); // window must be in list
+  if (it == windowList.begin())
+    return windowList.back();     // if we walked of the front, wrap around
+
+  return *(--it);
 }
 
 
-bool Workspace::isCurrent(void) {
-  return (id == screen.getCurrentWorkspaceID());
+BlackboxWindow* Workspace::getTopWindowOnStack(void) const {
+  return stackingList.front();
 }
 
 
-void Workspace::setCurrent(void) {
-  screen.changeWorkspaceID(id);
+void Workspace::sendWindowList(Netizen &n) {
+  BlackboxWindowList::iterator it = windowList.begin(),
+    end = windowList.end();
+  for(; it != end; ++it)
+    n.sendWindowAdd((*it)->getClientWindow(), getID());
+}
+
+
+unsigned int Workspace::getCount(void) const {
+  return windowList.size();
+}
+
+
+bool Workspace::isCurrent(void) const {
+  return (id == screen->getCurrentWorkspaceID());
 }
 
 
-void Workspace::setName(const char *new_name) {
-  if (name)
-    delete [] name;
+bool Workspace::isLastWindow(const BlackboxWindow* const w) const {
+  return (w == windowList.back());
+}
+
+void Workspace::setCurrent(void) {
+  screen->changeWorkspaceID(id);
+}
+
 
-  if (new_name) {
-    name = bstrdup(new_name);
+void Workspace::setName(const string& new_name) {
+  if (! new_name.empty()) {
+    name = new_name;
   } else {
-    name = new char[128];
-    sprintf(name, i18n(WorkspaceSet, WorkspaceDefaultNameFormat,
-                       "Workspace %d"), id + 1);
+    string tmp =i18n(WorkspaceSet, WorkspaceDefaultNameFormat, "Workspace %d");
+    assert(tmp.length() < 32);
+    char default_name[32];
+    sprintf(default_name, tmp.c_str(), id + 1);
+    name = default_name;
   }
 
   clientmenu->setLabel(name);
   clientmenu->update();
-  screen.saveWorkspaceNames();
 }
 
 
-void Workspace::shutdown(void) {
-  while (!_windows.empty())
-    _windows[0]->restore();
-}
+/*
+ * Calculate free space available for window placement.
+ */
+typedef std::vector<Rect> rectList;
 
 static rectList calcSpace(const Rect &win, const rectList &spaces) {
+  Rect isect, extra;
   rectList result;
-  rectList::const_iterator siter;
-  for(siter=spaces.begin(); siter!=spaces.end(); ++siter) {
-    if(win.Intersect(*siter)) {
-      //Check for space to the left of the window
-      if(win.x() > siter->x())
-        result.push_back(Rect(siter->x(), siter->y(),
-                              win.x() - siter->x() - 1,
-                              siter->h()));
-      //Check for space above the window
-      if(win.y() > siter->y())
-        result.push_back(Rect(siter->x(), siter->y(),
-                              siter->w(),
-                              win.y() - siter->y() - 1));
-      //Check for space to the right of the window
-      if((win.x()+win.w()) <
-         (siter->x()+siter->w()))
-        result.push_back(Rect(win.x() + win.w() + 1,
-                              siter->y(),
-                              siter->x() + siter->w() -
-                              win.x() - win.w() - 1,
-                              siter->h()));
-      //Check for space below the window
-      if((win.y()+win.h()) <
-         (siter->y()+siter->h()))
-        result.push_back(Rect(siter->x(),
-                              win.y() + win.h() + 1,
-                              siter->w(),
-                              siter->y() + siter->h()-
-                              win.y() - win.h() - 1));
+  rectList::const_iterator siter, end = spaces.end();
+  for (siter = spaces.begin(); siter != end; ++siter) {
+    const Rect &curr = *siter;
 
+    if(! win.intersects(curr)) {
+      result.push_back(curr);
+      continue;
     }
-    else
-      result.push_back(*siter);
+
+    /* Use an intersection of win and curr to determine the space around
+     * curr that we can use.
+     *
+     * NOTE: the spaces calculated can overlap.
+     */
+    isect = curr & win;
+
+    // left
+    extra.setCoords(curr.left(), curr.top(),
+                    isect.left() - 1, curr.bottom());
+    if (extra.valid()) result.push_back(extra);
+
+    // top
+    extra.setCoords(curr.left(), curr.top(),
+                    curr.right(), isect.top() - 1);
+    if (extra.valid()) result.push_back(extra);
+
+    // right
+    extra.setCoords(isect.right() + 1, curr.top(),
+                    curr.right(), curr.bottom());
+    if (extra.valid()) result.push_back(extra);
+
+    // bottom
+    extra.setCoords(curr.left(), isect.bottom() + 1,
+                    curr.right(), curr.bottom());
+    if (extra.valid()) result.push_back(extra);
   }
   return result;
 }
 
-bool rowRLBT(const Rect &first, const Rect &second){
-  if (first.y()+first.h()==second.y()+second.h())
-    return first.x()+first.w()>second.x()+second.w();
-  return first.y()+first.h()>second.y()+second.h();
+
+static bool rowRLBT(const Rect &first, const Rect &second) {
+  if (first.bottom() == second.bottom())
+    return first.right() > second.right();
+  return first.bottom() > second.bottom();
 }
 
-bool rowRLTB(const Rect &first, const Rect &second){
-  if (first.y()==second.y())
-    return first.x()+first.w()>second.x()+second.w();
-  return first.y()<second.y();
+static bool rowRLTB(const Rect &first, const Rect &second) {
+  if (first.y() == second.y())
+    return first.right() > second.right();
+  return first.y() < second.y();
 }
 
-bool rowLRBT(const Rect &first, const Rect &second){
-  if (first.y()+first.h()==second.y()+second.h())
-    return first.x()<second.x();
-  return first.y()+first.h()>second.y()+second.h();
+static bool rowLRBT(const Rect &first, const Rect &second) {
+  if (first.bottom() == second.bottom())
+    return first.x() < second.x();
+  return first.bottom() > second.bottom();
 }
 
-bool rowLRTB(const Rect &first, const Rect &second){
-  if (first.y()==second.y())
-    return first.x()<second.x();
-  return first.y()<second.y();
+static bool rowLRTB(const Rect &first, const Rect &second) {
+  if (first.y() == second.y())
+    return first.x() < second.x();
+  return first.y() < second.y();
 }
 
-bool colLRTB(const Rect &first, const Rect &second){
-  if (first.x()==second.x())
-    return first.y()<second.y();
-  return first.x()<second.x();
+static bool colLRTB(const Rect &first, const Rect &second) {
+  if (first.x() == second.x())
+    return first.y() < second.y();
+  return first.x() < second.x();
 }
 
-bool colLRBT(const Rect &first, const Rect &second){
-  if (first.x()==second.x())
-    return first.y()+first.h()>second.y()+second.h();
-  return first.x()<second.x();
+static bool colLRBT(const Rect &first, const Rect &second) {
+  if (first.x() == second.x())
+    return first.bottom() > second.bottom();
+  return first.x() < second.x();
 }
 
-bool colRLTB(const Rect &first, const Rect &second){
-  if (first.x()+first.w()==second.x()+second.w())
-    return first.y()<second.y();
-  return first.x()+first.w()>second.x()+second.w();
+static bool colRLTB(const Rect &first, const Rect &second) {
+  if (first.right() == second.right())
+    return first.y() < second.y();
+  return first.right() > second.right();
 }
 
-bool colRLBT(const Rect &first, const Rect &second){
-  if (first.x()+first.w()==second.x()+second.w())
-    return first.y()+first.h()>second.y()+second.h();
-  return first.x()+first.w()>second.x()+second.w();
+static bool colRLBT(const Rect &first, const Rect &second) {
+  if (first.right() == second.right())
+    return first.bottom() > second.bottom();
+  return first.right() > second.right();
 }
 
 
-//BestFitPlacement finds the smallest free space that fits the window
-//to be placed. It currentl ignores whether placement is right to left or top
-//to bottom.
-Point *Workspace::bestFitPlacement(const Size &win_size, const Rect &space) {
-  const Rect *best;
+bool Workspace::smartPlacement(Rect& win, const Rect& availableArea) {
   rectList spaces;
-  rectList::const_iterator siter;
-  spaces.push_back(space); //initially the entire screen is free
+  spaces.push_back(availableArea); //initially the entire screen is free
 
   //Find Free Spaces
-  winVect::iterator it;
-  for (it = _windows.begin(); it != _windows.end(); ++it)
-    spaces = calcSpace((*it)->area().Inflate(screen.getBorderWidth() * 4),
-                       spaces);
-
-  //Find first space that fits the window
-  best = NULL;
-  for (siter=spaces.begin(); siter!=spaces.end(); ++siter) {
-    if ((siter->w() >= win_size.w()) && (siter->h() >= win_size.h())) {
-      if (best==NULL)
-        best = &*siter;
-      else if(siter->w()*siter->h()<best->h()*best->w())
-        best = &*siter;
-    }
+  BlackboxWindowList::iterator wit = windowList.begin(),
+                               end = windowList.end();
+  Rect tmp;
+  for (; wit != end; ++wit) {
+    const BlackboxWindow* const curr = *wit;
+    tmp.setRect(curr->frameRect().x(), curr->frameRect().y(),
+                curr->frameRect().width() + screen->getBorderWidth(),
+                curr->frameRect().height() + screen->getBorderWidth());
+
+    spaces = calcSpace(tmp, spaces);
   }
-  if (best != NULL) {
-    Point *pt = new Point(best->origin());
-    if (screen.colPlacementDirection() != BScreen::TopBottom)
-      pt->setY(pt->y() + (best->h() - win_size.h()));
-    if (screen.rowPlacementDirection() != BScreen::LeftRight)
-      pt->setX(pt->x() + (best->w() - win_size.w()));
-    return pt;
-  } else
-    return NULL; //fall back to cascade
-}
-
-Point *Workspace::underMousePlacement(const Size &win_size, const Rect &space) {
-  Point *pt;
-
-  int x, y, rx, ry;
-  Window c, r;
-  unsigned int m;
-  XQueryPointer(screen.getOpenbox().getXDisplay(), screen.getRootWindow(),
-                &r, &c, &rx, &ry, &x, &y, &m);
-  pt = new Point(rx - win_size.w() / 2, ry - win_size.h() / 2);
-
-  if (pt->x() < space.x())
-    pt->setX(space.x());
-  if (pt->y() < space.y())
-    pt->setY(space.y());
-  if (pt->x() + win_size.w() > space.x() + space.w())
-    pt->setX(space.x() + space.w() - win_size.w());
-  if (pt->y() + win_size.h() > space.y() + space.h())
-    pt->setY(space.y() + space.h() - win_size.h());
-  return pt;
-}
-
-Point *Workspace::rowSmartPlacement(const Size &win_size, const Rect &space) {
-  const Rect *best;
-  rectList spaces;
 
-  rectList::const_iterator siter;
-  spaces.push_back(space); //initially the entire screen is free
+  if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) {
+    if(screen->getRowPlacementDirection() == BScreen::LeftRight) {
+      if(screen->getColPlacementDirection() == BScreen::TopBottom)
+        sort(spaces.begin(), spaces.end(), rowLRTB);
+      else
+        sort(spaces.begin(), spaces.end(), rowLRBT);
+    } else {
+      if(screen->getColPlacementDirection() == BScreen::TopBottom)
+        sort(spaces.begin(), spaces.end(), rowRLTB);
+      else
+        sort(spaces.begin(), spaces.end(), rowRLBT);
+    }
+  } else {
+    if(screen->getColPlacementDirection() == BScreen::TopBottom) {
+      if(screen->getRowPlacementDirection() == BScreen::LeftRight)
+        sort(spaces.begin(), spaces.end(), colLRTB);
+      else
+        sort(spaces.begin(), spaces.end(), colRLTB);
+    } else {
+      if(screen->getRowPlacementDirection() == BScreen::LeftRight)
+        sort(spaces.begin(), spaces.end(), colLRBT);
+      else
+        sort(spaces.begin(), spaces.end(), colRLBT);
+    }
+  }
 
-  //Find Free Spaces
-  winVect::iterator it;
-  for (it = _windows.begin(); it != _windows.end(); ++it)
-    spaces = calcSpace((*it)->area().Inflate(screen.getBorderWidth() * 4),
-                       spaces);
-  //Sort spaces by preference
-  if(screen.rowPlacementDirection() == BScreen::RightLeft)
-    if(screen.colPlacementDirection() == BScreen::TopBottom)
-      sort(spaces.begin(),spaces.end(),rowRLTB);
-    else
-      sort(spaces.begin(),spaces.end(),rowRLBT);
-  else
-    if(screen.colPlacementDirection() == BScreen::TopBottom)
-      sort(spaces.begin(),spaces.end(),rowLRTB);
-    else
-      sort(spaces.begin(),spaces.end(),rowLRBT);
-  best = NULL;
-  for (siter=spaces.begin(); siter!=spaces.end(); ++siter)
-    if ((siter->w() >= win_size.w()) && (siter->h() >= win_size.h())) {
-      best = &*siter;
+  rectList::const_iterator sit = spaces.begin(), spaces_end = spaces.end();
+  for(; sit != spaces_end; ++sit) {
+    if (sit->width() >= win.width() && sit->height() >= win.height())
       break;
-    }
+  }
 
-  if (best != NULL) {
-    Point *pt = new Point(best->origin());
-    if (screen.colPlacementDirection() != BScreen::TopBottom)
-      pt->setY(best->y() + best->h() - win_size.h());
-    if (screen.rowPlacementDirection() != BScreen::LeftRight)
-      pt->setX(best->x()+best->w()-win_size.w());
-    return pt;
-  } else
-    return NULL; //fall back to cascade
-}
+  if (sit == spaces_end)
+    return False;
 
-Point *Workspace::colSmartPlacement(const Size &win_size, const Rect &space) {
-  const Rect *best;
-  rectList spaces;
+  //set new position based on the empty space found
+  const Rect& where = *sit;
+  win.setX(where.x());
+  win.setY(where.y());
+
+  // adjust the location() based on left/right and top/bottom placement
+  if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) {
+    if (screen->getRowPlacementDirection() == BScreen::RightLeft)
+      win.setX(where.right() - win.width());
+    if (screen->getColPlacementDirection() == BScreen::BottomTop)
+      win.setY(where.bottom() - win.height());
+  } else {
+    if (screen->getColPlacementDirection() == BScreen::BottomTop)
+      win.setY(win.y() + where.height() - win.height());
+    if (screen->getRowPlacementDirection() == BScreen::RightLeft)
+      win.setX(win.x() + where.width() - win.width());
+  }
+  return True;
+}
 
-  rectList::const_iterator siter;
-  spaces.push_back(space); //initially the entire screen is free
 
-  //Find Free Spaces
-  winVect::iterator it;
-  for (it = _windows.begin(); it != _windows.end(); ++it)
-    spaces = calcSpace((*it)->area().Inflate(screen.getBorderWidth() * 4),
-                       spaces);
-  //Sort spaces by user preference
-  if(screen.colPlacementDirection() == BScreen::TopBottom)
-    if(screen.rowPlacementDirection() == BScreen::LeftRight)
-      sort(spaces.begin(),spaces.end(),colLRTB);
-    else
-      sort(spaces.begin(),spaces.end(),colRLTB);
-  else
-    if(screen.rowPlacementDirection() == BScreen::LeftRight)
-      sort(spaces.begin(),spaces.end(),colLRBT);
-    else
-      sort(spaces.begin(),spaces.end(),colRLBT);
-
-  //Find first space that fits the window
-  best = NULL;
-  for (siter=spaces.begin(); siter!=spaces.end(); ++siter)
-    if ((siter->w() >= win_size.w()) && (siter->h() >= win_size.h())) {
-      best = &*siter;
-      break;
-    }
+bool Workspace::cascadePlacement(Rect &win, const Rect &availableArea) {
+  if ((cascade_x > static_cast<signed>(availableArea.width() / 2)) ||
+      (cascade_y > static_cast<signed>(availableArea.height() / 2)))
+    cascade_x = cascade_y = 32;
 
-  if (best != NULL) {
-    Point *pt = new Point(best->origin());
-    if (screen.colPlacementDirection() != BScreen::TopBottom)
-      pt->setY(pt->y() + (best->h() - win_size.h()));
-    if (screen.rowPlacementDirection() != BScreen::LeftRight)
-      pt->setX(pt->x() + (best->w() - win_size.w()));
-    return pt;
-  } else
-    return NULL; //fall back to cascade
-}
-
-
-Point *const Workspace::cascadePlacement(const OpenboxWindow &win,
-                                         const Rect &space) {
-  if ((cascade_x + win.area().w() + screen.getBorderWidth() * 2 >
-       (space.x() + space.w())) ||
-      (cascade_y + win.area().h() + screen.getBorderWidth() * 2 >
-       (space.y() + space.h())))
-    cascade_x = cascade_y = 0;
-  if (cascade_x < space.x() || cascade_y < space.y()) {
-    cascade_x = space.x();
-    cascade_y = space.y();
+  if (cascade_x == 32) {
+    cascade_x += availableArea.x();
+    cascade_y += availableArea.y();
   }
 
-  Point *p = new Point(cascade_x, cascade_y);
-  cascade_x += win.getTitleHeight();
-  cascade_y += win.getTitleHeight();
-  return p;
+  win.setPos(cascade_x, cascade_y);
+
+  return True;
 }
 
 
-void Workspace::placeWindow(OpenboxWindow &win) {
-  Rect space = screen.availableArea();
-  const Size window_size(win.area().w()+screen.getBorderWidth() * 2,
-                         win.area().h()+screen.getBorderWidth() * 2);
-  Point *place = NULL;
+void Workspace::placeWindow(BlackboxWindow *win) {
+  Rect availableArea(screen->availableArea()),
+    new_win(availableArea.x(), availableArea.y(),
+            win->frameRect().width(), win->frameRect().height());
+  bool placed = False;
 
-  switch (screen.placementPolicy()) {
-  case BScreen::BestFitPlacement:
-    place = bestFitPlacement(window_size, space);
-    break;
+  switch (screen->getPlacementPolicy()) {
   case BScreen::RowSmartPlacement:
-    place = rowSmartPlacement(window_size, space);
-    break;
   case BScreen::ColSmartPlacement:
-    place = colSmartPlacement(window_size, space);
-    break;
-  case BScreen::UnderMousePlacement:
-  case BScreen::ClickMousePlacement:
-    place = underMousePlacement(window_size, space);
+    placed = smartPlacement(new_win, availableArea);
     break;
+  default:
+    break; // handled below
   } // switch
 
-  if (place == NULL)
-    place = cascadePlacement(win, space);
-
-  ASSERT(place != NULL);  
-  if (place->x() + window_size.w() > (signed) space.x() + space.w())
-    place->setX(((signed) space.x() + space.w() - window_size.w()) / 2);
-  if (place->y() + window_size.h() > (signed) space.y() + space.h())
-    place->setY(((signed) space.y() + space.h() - window_size.h()) / 2);
+  if (placed == False) {
+    cascadePlacement(new_win, availableArea);
+    cascade_x += win->getTitleHeight() + (screen->getBorderWidth() * 2);
+    cascade_y += win->getTitleHeight() + (screen->getBorderWidth() * 2);
+  }
 
-  win.configure(place->x(), place->y(), win.area().w(), win.area().h());
-  delete place;
+  if (new_win.right() > availableArea.right())
+    new_win.setX(availableArea.left());
+  if (new_win.bottom() > availableArea.bottom())
+    new_win.setY(availableArea.top());
+  win->configure(new_win.x(), new_win.y(), new_win.width(), new_win.height());
 }
diff --git a/src/Workspace.h b/src/Workspace.h
deleted file mode 100644 (file)
index 146e1d6..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// Workspace.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __Workspace_hh
-#define   __Workspace_hh
-
-#include <X11/Xlib.h>
-
-#include <vector>
-#include <list>
-
-class BScreen;
-class Clientmenu;
-class Workspace;
-class OpenboxWindow;
-class Size;
-class Rect;
-
-class Workspace {
-private:
-  BScreen &screen;
-  Clientmenu *clientmenu;
-
-  typedef std::vector<OpenboxWindow *> winVect;
-  winVect _windows;
-  typedef std::list<OpenboxWindow *> winList;
-  winList _zorder;
-
-  char *name;
-  int id, cascade_x, cascade_y;
-
-  OpenboxWindow *_focused, *_last;      // last is the same as focused except
-                                        // that when focus is removed from all
-                                        // windows on the workspace, last doesnt
-                                        // change to NULL
-
-protected:
-  void placeWindow(OpenboxWindow &);
-  Point *bestFitPlacement(const Size &win_size, const Rect &space);
-  Point *underMousePlacement(const Size &win_size, const Rect &space);
-  Point *rowSmartPlacement(const Size &win_size, const Rect &space);
-  Point *colSmartPlacement(const Size &win_size, const Rect &space);
-  Point *const cascadePlacement(const OpenboxWindow &window, const Rect &space);
-
-public:
-  Workspace(BScreen &, int = 0);
-  ~Workspace(void);
-
-  inline BScreen &getScreen(void) { return screen; }
-  inline Clientmenu *getMenu(void) { return clientmenu; }
-  inline const char *getName(void) const { return name; }
-  inline int getWorkspaceID(void) const { return id; }
-  inline OpenboxWindow *focusedWindow() { return _focused; }
-  inline OpenboxWindow *lastFocusedWindow() { return _last; }
-  void focusWindow(OpenboxWindow *win);
-  OpenboxWindow *getWindow(int);
-  bool isCurrent(void);
-  int addWindow(OpenboxWindow *, bool = false);
-  int removeWindow(OpenboxWindow *);
-  int getCount(void);
-  void showAll(void);
-  void hideAll(void);
-  void removeAll(void);
-  void raiseWindow(OpenboxWindow *);
-  void lowerWindow(OpenboxWindow *);
-  void reconfigure();
-  void update();
-  void setCurrent(void);
-  void setName(const char *);
-  void shutdown(void);
-};
-
-
-#endif // __Workspace_hh
-
diff --git a/src/Workspace.hh b/src/Workspace.hh
new file mode 100644 (file)
index 0000000..652e8ce
--- /dev/null
@@ -0,0 +1,109 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// Workspace.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef   __Workspace_hh
+#define   __Workspace_hh
+
+extern "C" {
+#include <X11/Xlib.h>
+}
+
+#include <list>
+#include <string>
+#include <vector>
+
+class BScreen;
+class Clientmenu;
+class Workspace;
+class BlackboxWindow;
+class Netizen;
+
+typedef std::list<BlackboxWindow*> BlackboxWindowList;
+typedef std::vector<Window> StackVector;
+
+class Workspace {
+private:
+  BScreen *screen;
+  BlackboxWindow *lastfocus;
+  Clientmenu *clientmenu;
+
+  BlackboxWindowList stackingList, windowList;
+
+  std::string name;
+  unsigned int id;
+  int cascade_x, cascade_y;
+
+  Workspace(const Workspace&);
+  Workspace& operator=(const Workspace&);
+
+  void raiseTransients(const BlackboxWindow * const win,
+                       StackVector::iterator &stack);
+  void lowerTransients(const BlackboxWindow * const win,
+                       StackVector::iterator &stack);
+
+  void placeWindow(BlackboxWindow *win);
+  bool cascadePlacement(Rect& win, const Rect& availableArea);
+  bool smartPlacement(Rect& win, const Rect& availableArea);
+
+public:
+  Workspace(BScreen *scrn, unsigned int i = 0);
+
+  inline BScreen *getScreen(void) { return screen; }
+
+  inline BlackboxWindow *getLastFocusedWindow(void) { return lastfocus; }
+
+  inline Clientmenu *getMenu(void) { return clientmenu; }
+
+  inline const std::string& getName(void) const { return name; }
+
+  inline unsigned int getID(void) const { return id; }
+
+  inline void setLastFocusedWindow(BlackboxWindow *w) { lastfocus = w; }
+
+  BlackboxWindow* getWindow(unsigned int index);
+  BlackboxWindow* getNextWindowInList(BlackboxWindow *w);
+  BlackboxWindow* getPrevWindowInList(BlackboxWindow *w);
+  BlackboxWindow* getTopWindowOnStack(void) const;
+  void sendWindowList(Netizen &n);
+
+  bool isCurrent(void) const;
+  bool isLastWindow(const BlackboxWindow* w) const;
+
+  void addWindow(BlackboxWindow *w, bool place = False);
+  unsigned int removeWindow(BlackboxWindow *w);
+  unsigned int getCount(void) const;
+
+  void showAll(void);
+  void hideAll(void);
+  void removeAll(void);
+  void raiseWindow(BlackboxWindow *w);
+  void lowerWindow(BlackboxWindow *w);
+  void reconfigure(void);
+  void updateFocusModel(void);
+  void setCurrent(void);
+  void setName(const std::string& new_name);
+};
+
+
+#endif // __Workspace_hh
+
index a97bdfefe829925a777a2c4ad587040923bdb501..a63251ab00c879a55e8e9423b2c81ac2a85613be 100644 (file)
@@ -1,5 +1,6 @@
-// Workspacemenu.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// Workspacemenu.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
-#include "i18n.h"
-#include "openbox.h"
-#include "Screen.h"
-#include "Toolbar.h"
-#include "Workspacemenu.h"
-#include "Workspace.h"
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "Screen.hh"
+#include "Toolbar.hh"
+#include "Workspacemenu.hh"
+#include "Workspace.hh"
 
 
-Workspacemenu::Workspacemenu(BScreen &scrn) : Basemenu(scrn), screen(scrn) {
+Workspacemenu::Workspacemenu(BScreen *scrn) : Basemenu(scrn) {
   setInternalMenu();
 
-  setLabel(i18n(WorkspacemenuSet, WorkspacemenuWorkspacesTitle,
-                "Workspaces"));
-  insert(i18n(WorkspacemenuSet, WorkspacemenuNewWorkspace,
-              "New Workspace"));
-  insert(i18n(WorkspacemenuSet, WorkspacemenuRemoveLast,
-              "Remove Last"));
+  setLabel(i18n(WorkspacemenuSet, WorkspacemenuWorkspacesTitle, "Workspaces"));
+  insert(i18n(WorkspacemenuSet, WorkspacemenuNewWorkspace, "New Workspace"));
+  insert(i18n(WorkspacemenuSet, WorkspacemenuRemoveLast, "Remove Last"));
 }
 
 
-void Workspacemenu::itemSelected(int button, int index) {
+void Workspacemenu::itemSelected(int button, unsigned int index) {
   if (button != 1)
     return;
 
-  if (index == 0)
-    screen.addWorkspace();
-  else if (index == 1)
-    screen.removeLastWorkspace();
-  else if ((screen.getCurrentWorkspace()->getWorkspaceID() !=
-            (index - 2)) && ((index - 2) < screen.getWorkspaceCount()))
-    screen.changeWorkspaceID(index - 2);
-
-  if (! (screen.getWorkspacemenu()->isTorn() || isTorn()))
+  if (index == 0) {
+    getScreen()->addWorkspace();
+  } else if (index == 1) {
+    getScreen()->removeLastWorkspace();
+  } else {
+    index -= 2;
+    const Workspace* const wkspc = getScreen()->getCurrentWorkspace();
+    if (wkspc->getID() != index && index < getScreen()->getWorkspaceCount())
+      getScreen()->changeWorkspaceID(index);
+  }
+  if (! (getScreen()->getWorkspacemenu()->isTorn() || isTorn()))
     hide();
 }
similarity index 78%
rename from src/Workspacemenu.h
rename to src/Workspacemenu.hh
index fa25814ec5a4cda999cf4f57a1e439424eb662fa..28052a9fe899c2a80226524f05bf26094a9efc4e 100644 (file)
@@ -1,5 +1,6 @@
-// WorkspaceMenu.h for Openbox - an X11 Window manager
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// WorkspaceMenu.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
@@ -23,7 +24,7 @@
 #ifndef   __Workspacemenu_hh
 #define   __Workspacemenu_hh
 
-#include "Basemenu.h"
+#include "Basemenu.hh"
 
 // forward declaration
 class Workspacemenu;
@@ -31,13 +32,14 @@ class Toolbar;
 
 class Workspacemenu : public Basemenu {
 private:
-  BScreen &screen;
+  Workspacemenu(const Workspacemenu&);
+  Workspacemenu& operator=(const Workspacemenu&);
 
 protected:
-  virtual void itemSelected(int, int);
+  virtual void itemSelected(int button, unsigned int index);
 
 public:
-  Workspacemenu(BScreen &);
+  Workspacemenu(BScreen *scrn);
 };
 
 
diff --git a/src/XAtom.cc b/src/XAtom.cc
deleted file mode 100644 (file)
index 9e59012..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-// XAtom.cc for Openbox
-// Copyright (c) 2002 - 2002 Ben Jansens (xor at orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#include "XAtom.h"
-#include "openbox.h"
-#include "Screen.h"
-#include "Util.h"
-
-XAtom::XAtom(Openbox &ob) {
-  _display = ob.getXDisplay();
-
-#ifdef    HAVE_GETPID
-  openbox_pid = getAtom("_BLACKBOX_PID");
-#endif // HAVE_GETPID
-
-  wm_colormap_windows = getAtom("WM_COLORMAP_WINDOWS");
-  wm_protocols = getAtom("WM_PROTOCOLS");
-  wm_state = getAtom("WM_STATE");
-  wm_change_state = getAtom("WM_CHANGE_STATE");
-  wm_delete_window = getAtom("WM_DELETE_WINDOW");
-  wm_take_focus = getAtom("WM_TAKE_FOCUS");
-  motif_wm_hints = getAtom("_MOTIF_WM_HINTS");
-  openbox_hints = getAtom("_BLACKBOX_HINTS");
-  openbox_attributes = getAtom("_BLACKBOX_ATTRIBUTES");
-  openbox_change_attributes = getAtom("_BLACKBOX_CHANGE_ATTRIBUTES");
-
-  openbox_structure_messages = getAtom("_BLACKBOX_STRUCTURE_MESSAGES");
-  openbox_notify_startup = getAtom("_BLACKBOX_NOTIFY_STARTUP");
-  openbox_notify_window_add = getAtom("_BLACKBOX_NOTIFY_WINDOW_ADD");
-  openbox_notify_window_del = getAtom("_BLACKBOX_NOTIFY_WINDOW_DEL");
-  openbox_notify_current_workspace =
-    getAtom("_BLACKBOX_NOTIFY_CURRENT_WORKSPACE");
-  openbox_notify_workspace_count = getAtom("_BLACKBOX_NOTIFY_WORKSPACE_COUNT");
-  openbox_notify_window_focus = getAtom("_BLACKBOX_NOTIFY_WINDOW_FOCUS");
-  openbox_notify_window_raise = getAtom("_BLACKBOX_NOTIFY_WINDOW_RAISE");
-  openbox_notify_window_lower = getAtom("_BLACKBOX_NOTIFY_WINDOW_LOWER");
-  
-  openbox_change_workspace = getAtom("_BLACKBOX_CHANGE_WORKSPACE");
-  openbox_change_window_focus = getAtom("_BLACKBOX_CHANGE_WINDOW_FOCUS");
-  openbox_cycle_window_focus = getAtom("_BLACKBOX_CYCLE_WINDOW_FOCUS");
-
-  net_supported = getAtom("_NET_SUPPORTED");
-  net_client_list = getAtom("_NET_CLIENT_LIST");
-  net_client_list_stacking = getAtom("_NET_CLIENT_LIST_STACKING");
-  net_number_of_desktops = getAtom("_NET_NUMBER_OF_DESKTOPS");
-  net_desktop_geometry = getAtom("_NET_DESKTOP_GEOMETRY");
-  net_desktop_viewport = getAtom("_NET_DESKTOP_VIEWPORT");
-  net_current_desktop = getAtom("_NET_CURRENT_DESKTOP");
-  net_desktop_names = getAtom("_NET_DESKTOP_NAMES");
-  net_active_window = getAtom("_NET_ACTIVE_WINDOW");
-  net_workarea = getAtom("_NET_WORKAREA");
-  net_supporting_wm_check = getAtom("_NET_SUPPORTING_WM_CHECK");
-  net_virtual_roots = getAtom("_NET_VIRTUAL_ROOTS");
-
-  net_close_window = getAtom("_NET_CLOSE_WINDOW");
-  net_wm_moveresize = getAtom("_NET_WM_MOVERESIZE");
-
-  net_properties = getAtom("_NET_PROPERTIES");
-  net_wm_name = getAtom("_NET_WM_NAME");
-  net_wm_desktop = getAtom("_NET_WM_DESKTOP");
-  net_wm_window_type = getAtom("_NET_WM_WINDOW_TYPE");
-  net_wm_state = getAtom("_NET_WM_STATE");
-  net_wm_strut = getAtom("_NET_WM_STRUT");
-  net_wm_icon_geometry = getAtom("_NET_WM_ICON_GEOMETRY");
-  net_wm_icon = getAtom("_NET_WM_ICON");
-  net_wm_pid = getAtom("_NET_WM_PID");
-  net_wm_handled_icons = getAtom("_NET_WM_HANDLED_ICONS");
-
-  net_wm_ping = getAtom("_NET_WM_PING");
-
-  for (unsigned int s = 0, c = ob.managedScreenCount(); s < c; ++s)
-    setSupported( static_cast<ScreenInfo*>(ob.getScreen(s)) );
-}
-
-
-/*
- * clean up the class' members
- */
-XAtom::~XAtom() {
-  while (!_support_windows.empty()) {
-    // make sure we aren't fucking with this somewhere
-    ASSERT(_support_windows.back() != None);
-    XDestroyWindow(_display, _support_windows.back());
-    _support_windows.pop_back();
-  }
-}
-
-
-/*
- * Returns an atom from the Xserver, creating it if necessary.
- */
-Atom XAtom::getAtom(const char *name) const {
-  return XInternAtom(_display, name, False);
-}
-
-
-/*
- * Sets which atoms are supported for NETWM, by Openbox, on the root window.
- */
-void XAtom::setSupported(const ScreenInfo *screen) {
-  // create the netwm support window
-  Window w = XCreateSimpleWindow(_display, screen->getRootWindow(),
-                                 0, 0, 1, 1, 0, 0, 0);
-  ASSERT(w != None);
-  _support_windows.push_back(w);
-  
-  // we don't support any yet..
-}
-  
-
-/*
- * Internal setValue used by all typed setValue functions.
- * Sets a window property on a window, optionally appending to the existing
- * value.
- */
-void XAtom::setValue(Window win, Atom atom, Atom type, unsigned char* data,
-                     int size, int nelements, bool append) const {
-  ASSERT(win != None); ASSERT(atom != None); ASSERT(type != None);
-  ASSERT(data != (unsigned char *) 0);
-  ASSERT(size == 8 || size == 16 || size == 32);
-  ASSERT(nelements > 0);
-  XChangeProperty(_display, win, atom, type, size,
-                  (append ? PropModeAppend : PropModeReplace),
-                  data, nelements);                  
-}
-
-
-/*
- * Set a 32-bit CARDINAL property value on a window.
- */
-void XAtom::setCardValue(Window win, Atom atom, long value) const {
-  setValue(win, atom, XA_CARDINAL, reinterpret_cast<unsigned char*>(&value),
-           32, 1, false);
-}
-
-
-/*
- * Set an Atom property value on a window.
- */
-void XAtom::setAtomValue(Window win, Atom atom, Atom value) const {
-  setValue(win, atom, XA_ATOM, reinterpret_cast<unsigned char*>(&value),
-           32, 1, false);
-}
-
-
-/*
- * Set a Window property value on a window.
- */
-void XAtom::setWindowValue(Window win, Atom atom, Window value) const {
-  setValue(win, atom, XA_WINDOW, reinterpret_cast<unsigned char*>(&value),
-           32, 1, false);
-}
-
-
-/*
- * Set a Pixmap property value on a window.
- */
-void XAtom::setPixmapValue(Window win, Atom atom, Pixmap value) const {
-  setValue(win, atom, XA_PIXMAP, reinterpret_cast<unsigned char*>(&value),
-           32, 1, false);
-}
-
-
-/*
- * Set a string property value on a window.
- */
-void XAtom::setStringValue(Window win, Atom atom,
-                           const std::string &value) const {
-  setValue(win, atom, XA_STRING,
-           const_cast<unsigned char*>
-           (reinterpret_cast<const unsigned char*>(value.c_str())),
-           8, value.size(), false);
-}
-
-
-/*
- * Add elements to a 32-bit CARDINAL property value on a window.
- */
-void XAtom::addCardValue(Window win, Atom atom, long value) const {
-  setValue(win, atom, XA_CARDINAL, reinterpret_cast<unsigned char*>(&value),
-           32, 1, true);
-}
-
-
-/*
- * Add elements to an Atom property value on a window.
- */
-void XAtom::addAtomValue(Window win, Atom atom, Atom value) const {
-  setValue(win, atom, XA_ATOM, reinterpret_cast<unsigned char*>(&value),
-           32, 1, true);
-}
-
-
-/*
- * Add elements to a Window property value on a window.
- */
-void XAtom::addWindowValue(Window win, Atom atom, Window value) const {
-  setValue(win, atom, XA_WINDOW, reinterpret_cast<unsigned char*>(&value),
-           32, 1, true);
-}
-
-
-/*
- * Add elements to a Pixmap property value on a window.
- */
-void XAtom::addPixmapValue(Window win, Atom atom, Pixmap value) const {
-  setValue(win, atom, XA_PIXMAP, reinterpret_cast<unsigned char*>(&value),
-           32, 1, true);
-}
-
-
-/*
- * Add characters to a string property value on a window.
- */
-void XAtom::addStringValue(Window win, Atom atom,
-                           const std::string &value) const {
-  setValue(win, atom, XA_STRING,
-           const_cast<unsigned char*>
-           (reinterpret_cast<const unsigned char *>
-            (value.c_str())),
-           8, value.size(), true);
-} 
-
-
-/*
- * Internal getValue function used by all of the typed getValue functions.
- * Gets an property's value from a window.
- * Returns true if the property was successfully retrieved; false if the
- * property did not exist on the window, or has a different type/size format
- * than the user tried to retrieve.
- */
-bool XAtom::getValue(Window win, Atom atom, Atom type, unsigned long *nelements,
-                     unsigned char **value, int size) const {
-  unsigned char *c_val;        // value alloc'd with c malloc
-  Atom ret_type;
-  int ret_size;
-  unsigned long ret_bytes;
-  XGetWindowProperty(_display, win, atom, 0l, 1l, False, AnyPropertyType,
-                     &ret_type, &ret_size, nelements, &ret_bytes,
-                     &c_val); // try get the first element
-  if (ret_type == None)
-    // the property does not exist on the window
-    return false;
-  if (ret_type != type || ret_size != size) {
-    // wrong data in property
-    XFree(c_val);
-    return false;
-  }
-  // the data is correct, now, is there more than 1 element?
-  if (ret_bytes == 0) {
-    // we got the whole property's value
-    *value = new unsigned char[*nelements * size/8 + 1];
-    memcpy(*value, c_val, *nelements * size/8 + 1);
-    XFree(c_val);
-    return true;    
-  }
-  // get the entire property since it is larger than one long
-  free(c_val);
-  // the number of longs that need to be retreived to get the property's entire
-  // value. The last + 1 is the first long that we retrieved above.
-  const int remain = (ret_bytes - 1)/sizeof(long) + 1 + 1;
-  XGetWindowProperty(_display, win, atom, 0l, remain, False, type, &ret_type,
-                     &ret_size, nelements, &ret_bytes, &c_val);
-  ASSERT(ret_bytes == 0);
-  *value = new unsigned char[*nelements * size/8 + 1];
-  memcpy(*value, c_val, *nelements * size/8 + 1);
-  XFree(c_val);
-  return true;    
-}
-
-
-/*
- * Gets a 32-bit Cardinal property's value from a window.
- */
-bool XAtom::getCardValue(Window win, Atom atom, unsigned long *nelements,
-                     long **value) const {
-  return XAtom::getValue(win, atom, XA_CARDINAL, nelements,
-                  reinterpret_cast<unsigned char **>(value), 32);
-}
-
-
-/*
- * Gets an Atom property's value from a window.
- */
-bool XAtom::getAtomValue(Window win, Atom atom, unsigned long *nelements,
-                     Atom **value) const {
-  return XAtom::getValue(win, atom, XA_ATOM, nelements,
-                  reinterpret_cast<unsigned char **>(value), 32);
-}
-
-
-/*
- * Gets an Window property's value from a window.
- */
-bool XAtom::getWindowValue(Window win, Atom atom, unsigned long *nelements,
-                     Window **value) const {
-  return XAtom::getValue(win, atom, XA_WINDOW, nelements,
-                  reinterpret_cast<unsigned char **>(value), 32);
-}
-
-
-/*
- * Gets an Pixmap property's value from a window.
- */
-bool XAtom::getPixmapValue(Window win, Atom atom, unsigned long *nelements,
-                     Pixmap **value) const {
-  return XAtom::getValue(win, atom, XA_PIXMAP, nelements,
-                  reinterpret_cast<unsigned char **>(value), 32);
-}
-
-
-/*
- * Gets an string property's value from a window.
- */
-bool XAtom::getStringValue(Window win, Atom atom, std::string &value) const {
-  unsigned char *data;
-  unsigned long nelements;
-  bool ret = XAtom::getValue(win, atom, XA_STRING, &nelements, &data, 8);
-  if (ret)
-    value = reinterpret_cast<char*>(data);
-  return ret;
-}
-
-
-/*
- * Removes a property entirely from a window.
- */
-void XAtom::eraseValue(Window win, Atom atom) const {
-  XDeleteProperty(_display, win, atom);
-}
diff --git a/src/XAtom.h b/src/XAtom.h
deleted file mode 100644 (file)
index 03292b5..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-// XAtom.h for Openbox
-// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __XAtom_h
-#define   __XAtom_h
-
-#include "../config.h"
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <vector>
-#include <string>
-
-class Openbox;
-class ScreenInfo;
-
-class XAtom {
-  typedef std::vector<Window> SupportWindows;
-  
-  Display              *_display;
-  // windows used to specify support for NETWM
-  SupportWindows        _support_windows; 
-
-  Atom 
-#ifdef    HAVE_GETPID
-    openbox_pid,
-#endif // HAVE_GETPID
-
-    // window hints
-    wm_colormap_windows,
-    wm_protocols,
-    wm_state,
-    wm_delete_window,
-    wm_take_focus,
-    wm_change_state,
-    motif_wm_hints,
-    openbox_attributes,
-    openbox_change_attributes,
-    openbox_hints,
-
-    // blackbox-protocol atoms (wm -> client)
-    openbox_structure_messages,
-    openbox_notify_startup,
-    openbox_notify_window_add,
-    openbox_notify_window_del,
-    openbox_notify_window_focus,
-    openbox_notify_current_workspace,
-    openbox_notify_workspace_count,
-    openbox_notify_window_raise,
-    openbox_notify_window_lower,
-    // blackbox-protocol atoms (client -> wm)
-    openbox_change_workspace,
-    openbox_change_window_focus,
-    openbox_cycle_window_focus,
-
-    // NETWM atoms
-    // root window properties
-    net_supported,
-    net_client_list,
-    net_client_list_stacking,
-    net_number_of_desktops,
-    net_desktop_geometry,
-    net_desktop_viewport,
-    net_current_desktop,
-    net_desktop_names,
-    net_active_window,
-    net_workarea,
-    net_supporting_wm_check,
-    net_virtual_roots,
-    // root window messages
-    net_close_window,
-    net_wm_moveresize,
-    // application window properties
-    net_properties,
-    net_wm_name,
-    net_wm_desktop,
-    net_wm_window_type,
-    net_wm_state,
-    net_wm_strut,
-    net_wm_icon_geometry,
-    net_wm_icon,
-    net_wm_pid,
-    net_wm_handled_icons,
-    // application protocols
-    net_wm_ping;
-
-  Atom getAtom(const char *name) const;
-  void setSupported(const ScreenInfo *screen);
-
-  void setValue(Window win, Atom atom, Atom type, unsigned char *data,
-                int size, int nelements, bool append) const;
-  bool getValue(Window win, Atom atom, Atom type, unsigned long *nelements,
-                unsigned char **value, int size) const;
-
-  // no copying!!
-  XAtom(const XAtom &);
-  XAtom& operator=(const XAtom&);
-
-public:
-  XAtom(Openbox &ob);
-  virtual ~XAtom();
-
-  void setCardValue(Window win, Atom atom, long value) const; // 32-bit CARDINAL
-  void setAtomValue(Window win, Atom atom, Atom value) const;
-  void setWindowValue(Window win, Atom atom, Window value) const;
-  void setPixmapValue(Window win, Atom atom, Pixmap value) const;
-  void setStringValue(Window win, Atom atom, const std::string &value) const;
-  
-  void addCardValue(Window win, Atom atom, long value) const; // 32-bit CARDINAL
-  void addAtomValue(Window win, Atom atom, Atom value) const;
-  void addWindowValue(Window win, Atom atom, Window value) const;
-  void addPixmapValue(Window win, Atom atom, Pixmap value) const;
-  void addStringValue(Window win, Atom atom, const std::string &value) const;
-
-  // the 'value' is allocated inside the function and
-  // delete [] value needs to be called when you are done with it.
-  // teh 'value' array returned is null terminated, and has 'nelements'
-  // elements in it plus the null.
-  bool getCardValue(Window win, Atom atom, unsigned long *nelements,
-                long **value) const; // 32-bit CARDINAL
-  bool getAtomValue(Window win, Atom atom, unsigned long *nelements,
-                Atom **value) const;
-  bool getWindowValue(Window win, Atom atom, unsigned long *nelements,
-                Window **value) const;
-  bool getPixmapValue(Window win, Atom atom, unsigned long *nelements,
-                Pixmap **value) const;
-  bool getStringValue(Window win, Atom atom, std::string &value) const;
-  
-  void eraseValue(Window win, Atom atom) const;
-  
-#ifdef    HAVE_GETPID
-  inline Atom openboxPid() const { return openbox_pid; }
-#endif // HAVE_GETPID
-
-  inline Atom wmChangeState() const { return wm_change_state; }
-  inline Atom wmState() const { return wm_state; }
-  inline Atom wmDelete() const { return wm_delete_window; }
-  inline Atom wmProtocols() const { return wm_protocols; }
-  inline Atom wmTakeFocus() const { return wm_take_focus; }
-  inline Atom wmColormap() const { return wm_colormap_windows; }
-  inline Atom motifWMHints() const { return motif_wm_hints; }
-
-  // this atom is for normal app->WM hints about decorations, stacking,
-  // starting workspace etc...
-  inline Atom openboxHints() const { return openbox_hints;}
-
-  // these atoms are for normal app->WM interaction beyond the scope of the
-  // ICCCM...
-  inline Atom openboxAttributes() const { return openbox_attributes; }
-  inline Atom openboxChangeAttributes() const
-  { return openbox_change_attributes; }
-
-  // these atoms are for window->WM interaction, with more control and
-  // information on window "structure"... common examples are
-  // notifying apps when windows are raised/lowered... when the user changes
-  // workspaces... i.e. "pager talk"
-  inline Atom openboxStructureMessages() const
-  { return openbox_structure_messages; }
-
-  inline Atom openboxNotifyStartup() const
-  { return openbox_notify_startup; }
-  inline Atom openboxNotifyWindowAdd() const
-  { return openbox_notify_window_add; }
-  inline Atom openboxNotifyWindowDel() const
-  { return openbox_notify_window_del; }
-  inline Atom openboxNotifyWindowFocus() const
-  { return openbox_notify_window_focus; }
-  inline Atom openboxNotifyCurrentWorkspace() const
-  { return openbox_notify_current_workspace; }
-  inline Atom openboxNotifyWorkspaceCount() const
-  { return openbox_notify_workspace_count; }
-  inline Atom openboxNotifyWindowRaise() const
-  { return openbox_notify_window_raise; }
-  inline Atom openboxNotifyWindowLower() const
-  { return openbox_notify_window_lower; }
-
-  // atoms to change that request changes to the desktop environment during
-  // runtime... these messages can be sent by any client... as the sending
-  // client window id is not included in the ClientMessage event...
-  inline Atom openboxChangeWorkspace() const
-  { return openbox_change_workspace; }
-  inline Atom openboxChangeWindowFocus() const
-  { return openbox_change_window_focus; }
-  inline Atom openboxCycleWindowFocus() const
-  { return openbox_cycle_window_focus; }
-
-  // root window properties
-  inline Atom netClientList() const { return net_client_list; }
-  inline Atom netClientListStacking() const { return net_client_list_stacking; }
-  inline Atom netNumberOfDesktops() const { return net_number_of_desktops; }
-  inline Atom netDesktopGeometry() const { return net_desktop_geometry; }
-  inline Atom netDesktopViewport() const { return net_desktop_viewport; }
-  inline Atom netCurrentDesktop() const { return net_current_desktop; }
-  inline Atom netDesktopNames() const { return net_desktop_names; }
-  inline Atom netActiveWindow() const { return net_active_window; }
-  inline Atom netWorkarea() const { return net_workarea; }
-  inline Atom netSupportingWMCheck() const { return net_supporting_wm_check; }
-  inline Atom netVirtualRoots() const { return net_virtual_roots; }
-
-  // root window messages
-  inline Atom netCloseWindow() const { return net_close_window; }
-  inline Atom netWMMoveResize() const { return net_wm_moveresize; }
-
-  // application window properties
-  inline Atom netProperties() const { return net_properties; }
-  inline Atom netWMName() const { return net_wm_name; }
-  inline Atom netWMDesktop() const { return net_wm_desktop; }
-  inline Atom netWMWindowType() const { return net_wm_window_type; }
-  inline Atom netWMState() const { return net_wm_state; }
-  inline Atom netWMStrut() const { return net_wm_strut; }
-  inline Atom netWMIconGeometry() const { return net_wm_icon_geometry; }
-  inline Atom netWMIcon() const { return net_wm_icon; }
-  inline Atom netWMPid() const { return net_wm_pid; }
-  inline Atom netWMHandledIcons() const { return net_wm_handled_icons; }
-
-  // application protocols
-  inline Atom netWMPing() const { return net_wm_ping; }
-};
-
-#endif // __XAtom_h
diff --git a/src/XDisplay.cc b/src/XDisplay.cc
deleted file mode 100644 (file)
index 1addb2d..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-// XDisplay.cc for Openbox
-// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifdef HAVE_CONFIG_H
-# include "../config.h"
-#endif
-
-#ifdef HAVE_UNNISTD_H
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-#ifdef SHAPE
-# include <X11/extensions/shape.h>
-#endif
-
-#include "XDisplay.h"
-#include "Util.h"
-#include <iostream>
-#include <algorithm>
-
-using std::cerr;
-using std::endl;
-
-std::string XDisplay::_app_name;
-Window      XDisplay::_last_bad_window = None;
-  
-/*
- * X error handler to handle all X errors while the application is
- * running.
- */
-int XDisplay::errorHandler(Display *d, XErrorEvent *e) {
-#ifdef DEBUG
-  char errtxt[128];
-  XGetErrorText(d, e->error_code, errtxt, sizeof(errtxt)/sizeof(char));
-  cerr << _app_name.c_str() << ": X error: " << 
-    errtxt << "(" << e->error_code << ") opcodes " <<
-    e->request_code << "/" << e->minor_code << endl;
-  cerr.flags(std::ios_base::hex);
-  cerr << "  resource 0x" << e->resourceid << endl;
-  cerr.flags(std::ios_base::dec);
-#endif
-  
-  if (e->error_code == BadWindow)
-    _last_bad_window = e->resourceid;
-  
-  return False;
-}
-
-
-XDisplay::XDisplay(const std::string &application_name, const char *dpyname) {
-  _app_name = application_name;
-  _grabs = 0;
-  _hasshape = false;
-  
-  _display = XOpenDisplay(dpyname);
-  if (_display == NULL) {
-    cerr << "Could not open display. Connection to X server failed.\n";
-    ::exit(2);
-  }
-  if (-1 == fcntl(ConnectionNumber(_display), F_SETFD, 1)) {
-    cerr << "Could not mark display connection as close-on-exec.\n";
-    ::exit(2);
-  }
-  _name = XDisplayName(dpyname);
-
-  XSetErrorHandler(errorHandler);
-
-#ifdef    SHAPE
-  int waste;
-  _hasshape = XShapeQueryExtension(_display, &_shape_event_base, &waste);
-#endif // SHAPE
-
-#ifndef NOCLOBBER
-  getLockModifiers();
-#endif
-}
-
-
-XDisplay::~XDisplay() {
-  std::for_each(_screens.begin(), _screens.end(), PointerAssassin());
-  XCloseDisplay(_display);
-}
-
-
-/*
- * Grab the X server
- */
-void XDisplay::grab() {
-  if (_grabs++ == 0)
-    XGrabServer(_display);
-}
-
-
-/*
- * Release the X server from a grab
- */
-void XDisplay::ungrab() {
-  if (--_grabs == 0)
-    XUngrabServer(_display);
-}
-
-
-/*
- * Gets the next event on the queue from the X server.
- * 
- * Returns: true if e contains a new event; false if there is no event to be
- *          returned.
- */
-bool XDisplay::nextEvent(XEvent &e) {
-  if(!XPending(_display))
-    return false;
-  XNextEvent(_display, &e);
-  if (_last_bad_window != None) {
-    if (e.xany.window == _last_bad_window) {
-      cerr << "XDisplay::nextEvent(): Removing event for bad window from " <<
-        "event queue\n";
-      return false;
-    } else
-      _last_bad_window = None;
-  }
-  return true;
-}
-
-
-int XDisplay::connectionNumber() const {
-  return ConnectionNumber(_display);
-}
-
-
-/*
- * Creates a font cursor in the X server and returns it.
- */
-Cursor createCursor(unsigned int shape) const {
-  return XCreateFontCursor(_display, shape);
-}
-
-
-#ifndef   NOCLOBBER
-void XDisplay::getLockModifers() {
-  NumLockMask = ScrollLockMask = 0;
-
-  const XModifierKeymap* const modmap = XGetModifierMapping(display);
-  if (modmap && modmap->max_keypermod > 0) {
-    const int mask_table[] = {
-      ShiftMask, LockMask, ControlMask, Mod1Mask,
-      Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
-    };
-    const size_t size = (sizeof(mask_table) / sizeof(mask_table[0])) *
-      modmap->max_keypermod;
-    // get the values of the keyboard lock modifiers
-    // Note: Caps lock is not retrieved the same way as Scroll and Num lock
-    // since it doesn't need to be.
-    const KeyCode num_lock_code = XKeysymToKeycode(display, XK_Num_Lock);
-    const KeyCode scroll_lock_code = XKeysymToKeycode(display, XK_Scroll_Lock);
-
-    for (size_t cnt = 0; cnt < size; ++cnt) {
-      if (! modmap->modifiermap[cnt]) continue;
-
-      if (num_lock_code == modmap->modifiermap[cnt])
-        NumLockMask = mask_table[cnt / modmap->max_keypermod];
-      if (scroll_lock_code == modmap->modifiermap[cnt])
-        ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
-    }
-  }
-
-  MaskList[0] = 0;
-  MaskList[1] = LockMask;
-  MaskList[2] = NumLockMask;
-  MaskList[3] = ScrollLockMask;
-  MaskList[4] = LockMask | NumLockMask;
-  MaskList[5] = NumLockMask  | ScrollLockMask;
-  MaskList[6] = LockMask | ScrollLockMask;
-  MaskList[7] = LockMask | NumLockMask | ScrollLockMask;
-
-  if (modmap) XFreeModifiermap(const_cast<XModifierKeymap*>(modmap));
-}
-#endif // NOCLOBBER
-  
-unsigned int XDisplay::stripModifiers(const unsigned int state) const {
-#ifndef NOCLOBBER
-  return state &= ~(NumLockMask() | ScrollLockMask | LockMask);
-#else
-  return state &= ~LockMask;
-#endif
-}
-
-
-/*
- * Verifies that a window has not requested to be destroyed/unmapped, so
- * if it is a valid window or not.
- * Returns: true if the window is valid; false if it is no longer valid.
- */
-bool XDisplay::validateWindow(Window window) {
-  XEvent event;
-  if (XCheckTypedWindowEvent(_display, window, DestroyNotify, &event)) {
-    XPutBackEvent(display, &event);
-    return false;
-  }
-  return true;
-}
-
-
-/*
- * Grabs a button, but also grabs the button in every possible combination with
- * the keyboard lock keys, so that they do not cancel out the event.
- */
-void BaseDisplay::grabButton(unsigned int button, unsigned int modifiers,
-                             Window grab_window, Bool owner_events,
-                             unsigned int event_mask, int pointer_mode,
-                             int keybaord_mode, Window confine_to,
-                             Cursor cursor) const
-{
-#ifndef   NOCLOBBER
-  for (size_t cnt = 0; cnt < 8; ++cnt)
-    XGrabButton(_display, button, modifiers | MaskList[cnt], grab_window,
-                owner_events, event_mask, pointer_mode, keybaord_mode,
-                confine_to, cursor);
-#else  // NOCLOBBER
-  XGrabButton(_display, button, modifiers, grab_window,
-              owner_events, event_mask, pointer_mode, keybaord_mode,
-              confine_to, cursor);
-#endif // NOCLOBBER
-}
-
-
-/*
- * Releases the grab on a button, and ungrabs all possible combinations of the
- * keyboard lock keys.
- */
-void BaseDisplay::ungrabButton(unsigned int button, unsigned int modifiers,
-                               Window grab_window) const {
-#ifndef   NOCLOBBER
-  for (size_t cnt = 0; cnt < 8; ++cnt)
-    XUngrabButton(display, button, modifiers | MaskList[cnt], grab_window);
-#else  // NOCLOBBER
-  XUngrabButton(display, button, modifiers, grab_window);
-#endif // NOCLOBBER
-}
diff --git a/src/XDisplay.h b/src/XDisplay.h
deleted file mode 100644 (file)
index 3c4230b..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// XDisplay.h for Openbox
-// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __XDisplay_h
-#define   __XDisplay_h
-
-#include <X11/Xlib.h>
-#include <string>
-#include <vector>
-#include "XAtom.h"
-#include "XScreen.h"
-
-class XDisplay {
-  friend XAtom::XAtom(const XDisplay *);
-  friend XScreen::XScreen(const XDisplay *, const unsigned int);
-
-private:
-  Display       *_display;
-  std::string    _name;
-  unsigned int   _grabs;
-  bool           _hasshape;
-  int            _shape_event_base;
-
-#ifndef   NOCLOBBER
-  // the server's values for the lock key modifiers
-  void getLockModifiers();
-  unsigned int MaskList[8];
-  // the masks of the modifiers which are ignored in button events.
-  int NumLockMask, ScrollLockMask;
-#endif // NOCLOBBER
-
-  
-  // X error handling
-  static int errorHandler(Display *d, XErrorEvent *e);
-  static std::string _app_name;
-  static Window _last_bad_window;
-
-  // no copying!!
-  XDisplay(const XDisplay &);
-  XDisplay& operator=(const XDisplay&);
-  
-protected:
-  virtual void process_event(XEvent *) = 0;
-
-public:
-  XDisplay(const std::string &application_name, const char *dpyname = 0);
-  virtual ~XDisplay();
-
-  inline virtual unsigned int screenCount() const
-  { return ScreenCount(_display); }
-  
-  inline bool hasShape() const { return _hasshape; }
-  inline int shapeEventBase() const { return _shape_event_base; }
-
-  //inline Display *display() const { return _display; }
-
-  inline std::string applicationName() const { return _app_name; }
-  inline std::string name() const { return _name; }
-  
-  void grab();
-  void ungrab();
-
-  bool nextEvent(XEvent &e);
-
-  int connectionNumber() const;
-
-  Cursor createCursor(unsigned int shape) const;
-
-  unsigned int stripModifiers(const unsigned int state) const;
-
-  // these belong in Xwindow
-  const bool validateWindow(Window);
-  void grabButton(unsigned int, unsigned int, Window, Bool, unsigned int, int,
-      int, Window, Cursor) const;
-  void ungrabButton(unsigned int button, unsigned int modifiers,
-      Window grab_window) const;
-};
-
-#endif // _XDisplay_h
diff --git a/src/XScreen.cc b/src/XScreen.cc
deleted file mode 100644 (file)
index 5ae8bec..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// XScreen.cc for Openbox
-// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#include <X11/Xutil.h>
-#include "XScreen.h"
-#include "XDisplay.h"
-#include "Geometry.h"
-
-XScreen::XScreen(const XDisplay *display, const unsigned int number) {
-  _display = display->_display;
-  _number = number;
-
-  _root = RootWindow(_display, _number);
-  _size = Size(WidthOfScreen(ScreenOfDisplay(_display, _number)),
-               HeightOfScreen(ScreenOfDisplay(_display, _number)));
-  setColorData();
-}
-
-
-XScreen::~XScreen() {
-}
-
-  
-/*
- * This sets up the _depth, _visual, and _colormap properties.
- */
-void XScreen::setColorData() {
-  _depth = DefaultDepth(_display, _number);
-  _visual = (Visual *) 0;
-
-  // search for a TrueColor Visual. If we can't find one, use the default
-  // visual for the screen
-  XVisualInfo vinfo_template, *vinfo_return;
-  int vinfo_nitems;
-
-  vinfo_template.screen = _number;
-  vinfo_template.c_class = TrueColor;
-
-  vinfo_return = XGetVisualInfo(_display, VisualScreenMask | VisualClassMask,
-                                &vinfo_template, &vinfo_nitems);
-  if (vinfo_return && vinfo_nitems > 0) {
-    for (int i = 0; i < vinfo_nitems; i++)
-      if (_depth < (vinfo_return + i)->depth) {
-        _depth = (vinfo_return + i)->depth;
-        _visual = (vinfo_return + i)->visual;
-      }
-    XFree(vinfo_return);
-  }
-  if (_visual)
-    _colormap = XCreateColormap(_display, _root, _visual, AllocNone);
-  else {
-    _visual = DefaultVisual(_display, _number);
-    _colormap = DefaultColormap(_display, _number);
-  }
-}
-
-
-/*
- * Creates a window on screen.
- */
-Window createWindow(Window parent, const Rect &area, int borderw,
-                    unsigned int winclass, unsigned long attrib_mask,
-                    XSetWindowAttributes *attrib) const {
-  return XCreateWindow(_display, parent,
-                       area.x(), area.y(), area.w(), area.h(),
-                       borderw, depth(), winclass, visual(),
-                       attrib_mask, attrib);
-}
diff --git a/src/XScreen.h b/src/XScreen.h
deleted file mode 100644 (file)
index cdfd425..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// XScreen.h for Openbox
-// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __XScreen_h
-#define   __XScreen_h
-
-#include <X11/Xlib.h>
-#include "Geometry.h"
-
-class XDisplay;
-
-class XScreen {
-private:
-  Display        *_display;
-  unsigned int    _number;
-  Visual         *_visual;
-  Window          _root;
-  Colormap        _colormap;
-  int             _depth;
-  Size            _size;
-
-  void setColorData();
-  
-  // no copying!!
-  XScreen(const XScreen &);
-  XScreen& operator=(const XScreen&);
-
-public:
-  XScreen(const XDisplay *display, const unsigned int number);
-  virtual ~XScreen();
-
-  inline Visual *visual() const { return _visual; }
-  inline Window rootWindow() const { return _root; }
-  inline Colormap colormap() const { return _colormap; }
-  inline unsigned int depth() const { return _depth; }
-  inline unsigned int number() const { return _number; }
-  inline const Size &size() const { return _size; }
-
-  Window createWindow(Window parent, const Rect &area, int borderw,
-                      unsigned int winclass,
-                      unsigned long attrib_mask,
-                      XSetWindowAttributes *attrib) const;
-};
-
-#endif // __XScreen_h
diff --git a/src/blackbox.cc b/src/blackbox.cc
new file mode 100644 (file)
index 0000000..4325933
--- /dev/null
@@ -0,0 +1,1680 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// blackbox.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifdef    HAVE_CONFIG_H
+#  include "../config.h"
+#endif // HAVE_CONFIG_H
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xresource.h>
+#include <X11/Xatom.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+
+#ifdef    SHAPE
+#include <X11/extensions/shape.h>
+#endif // SHAPE
+
+#ifdef    HAVE_STDIO_H
+#  include <stdio.h>
+#endif // HAVE_STDIO_H
+
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif // HAVE_STDLIB_H
+
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif // HAVE_STRING_H
+
+#ifdef    HAVE_UNISTD_H
+#  include <sys/types.h>
+#  include <unistd.h>
+#endif // HAVE_UNISTD_H
+
+#ifdef    HAVE_SYS_PARAM_H
+#  include <sys/param.h>
+#endif // HAVE_SYS_PARAM_H
+
+#ifdef    HAVE_SYS_SELECT_H
+#  include <sys/select.h>
+#endif // HAVE_SYS_SELECT_H
+
+#ifdef    HAVE_SIGNAL_H
+#  include <signal.h>
+#endif // HAVE_SIGNAL_H
+
+#ifdef    HAVE_SYS_SIGNAL_H
+#  include <sys/signal.h>
+#endif // HAVE_SYS_SIGNAL_H
+
+#ifdef    HAVE_SYS_STAT_H
+#  include <sys/types.h>
+#  include <sys/stat.h>
+#endif // HAVE_SYS_STAT_H
+
+#ifdef    TIME_WITH_SYS_TIME
+#  include <sys/time.h>
+#  include <time.h>
+#else // !TIME_WITH_SYS_TIME
+#  ifdef    HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#  else // !HAVE_SYS_TIME_H
+#    include <time.h>
+#  endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+
+#ifdef    HAVE_LIBGEN_H
+#  include <libgen.h>
+#endif // HAVE_LIBGEN_H
+}
+
+#include <algorithm>
+#include <string>
+using std::string;
+
+#include "i18n.hh"
+#include "blackbox.hh"
+#include "Basemenu.hh"
+#include "Clientmenu.hh"
+#include "GCCache.hh"
+#include "Image.hh"
+#include "Rootmenu.hh"
+#include "Screen.hh"
+#include "Slit.hh"
+#include "Toolbar.hh"
+#include "Util.hh"
+#include "Window.hh"
+#include "Workspace.hh"
+#include "Workspacemenu.hh"
+
+
+// X event scanner for enter/leave notifies - adapted from twm
+struct scanargs {
+  Window w;
+  bool leave, inferior, enter;
+};
+
+static Bool queueScanner(Display *, XEvent *e, char *args) {
+  scanargs *scan = (scanargs *) args;
+  if ((e->type == LeaveNotify) &&
+      (e->xcrossing.window == scan->w) &&
+      (e->xcrossing.mode == NotifyNormal)) {
+    scan->leave = True;
+    scan->inferior = (e->xcrossing.detail == NotifyInferior);
+  } else if ((e->type == EnterNotify) && (e->xcrossing.mode == NotifyUngrab)) {
+    scan->enter = True;
+  }
+
+  return False;
+}
+
+Blackbox *blackbox;
+
+
+Blackbox::Blackbox(char **m_argv, char *dpy_name, char *rc)
+  : BaseDisplay(m_argv[0], dpy_name) {
+  if (! XSupportsLocale())
+    fprintf(stderr, "X server does not support locale\n");
+
+  if (XSetLocaleModifiers("") == NULL)
+    fprintf(stderr, "cannot set locale modifiers\n");
+
+  ::blackbox = this;
+  argv = m_argv;
+  if (! rc) rc = "~/.blackboxrc";
+  rc_file = expandTilde(rc);
+
+  no_focus = False;
+
+  resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec = 0;
+
+  active_screen = 0;
+  focused_window = (BlackboxWindow *) 0;
+
+  XrmInitialize();
+  load_rc();
+
+  init_icccm();
+
+  cursor.session = XCreateFontCursor(getXDisplay(), XC_left_ptr);
+  cursor.move = XCreateFontCursor(getXDisplay(), XC_fleur);
+  cursor.ll_angle = XCreateFontCursor(getXDisplay(), XC_ll_angle);
+  cursor.lr_angle = XCreateFontCursor(getXDisplay(), XC_lr_angle);
+
+  for (unsigned int i = 0; i < getNumberOfScreens(); i++) {
+    BScreen *screen = new BScreen(this, i);
+
+    if (! screen->isScreenManaged()) {
+      delete screen;
+      continue;
+    }
+
+    screenList.push_back(screen);
+  }
+
+  if (screenList.empty()) {
+    fprintf(stderr,
+            i18n(blackboxSet, blackboxNoManagableScreens,
+              "Blackbox::Blackbox: no managable screens found, aborting.\n"));
+    ::exit(3);
+  }
+
+  // set the screen with mouse to the first managed screen
+  active_screen = screenList.front();
+  setFocusedWindow(0);
+
+  XSynchronize(getXDisplay(), False);
+  XSync(getXDisplay(), False);
+
+  reconfigure_wait = reread_menu_wait = False;
+
+  timer = new BTimer(this, this);
+  timer->setTimeout(0l);
+}
+
+
+Blackbox::~Blackbox(void) {
+  std::for_each(screenList.begin(), screenList.end(), PointerAssassin());
+
+  std::for_each(menuTimestamps.begin(), menuTimestamps.end(),
+                PointerAssassin());
+
+  delete timer;
+}
+
+
+void Blackbox::process_event(XEvent *e) {
+  switch (e->type) {
+  case ButtonPress: {
+    // strip the lock key modifiers
+    e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
+
+    last_time = e->xbutton.time;
+
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Basemenu *menu = (Basemenu *) 0;
+    Slit *slit = (Slit *) 0;
+    Toolbar *tbar = (Toolbar *) 0;
+    BScreen *scrn = (BScreen *) 0;
+
+    if ((win = searchWindow(e->xbutton.window))) {
+      win->buttonPressEvent(&e->xbutton);
+
+      /* XXX: is this sane on low colour desktops? */
+      if (e->xbutton.button == 1)
+        win->installColormap(True);
+    } else if ((menu = searchMenu(e->xbutton.window))) {
+      menu->buttonPressEvent(&e->xbutton);
+    } else if ((slit = searchSlit(e->xbutton.window))) {
+      slit->buttonPressEvent(&e->xbutton);
+    } else if ((tbar = searchToolbar(e->xbutton.window))) {
+      tbar->buttonPressEvent(&e->xbutton);
+    } else if ((scrn = searchScreen(e->xbutton.window))) {
+      scrn->buttonPressEvent(&e->xbutton);
+      if (active_screen != scrn) {
+        active_screen = scrn;
+        // first, set no focus window on the old screen
+        setFocusedWindow(0);
+        // and move focus to this screen
+        setFocusedWindow(0);
+      }
+    }
+    break;
+  }
+
+  case ButtonRelease: {
+    // strip the lock key modifiers
+    e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
+
+    last_time = e->xbutton.time;
+
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Basemenu *menu = (Basemenu *) 0;
+    Toolbar *tbar = (Toolbar *) 0;
+
+    if ((win = searchWindow(e->xbutton.window)))
+      win->buttonReleaseEvent(&e->xbutton);
+    else if ((menu = searchMenu(e->xbutton.window)))
+      menu->buttonReleaseEvent(&e->xbutton);
+    else if ((tbar = searchToolbar(e->xbutton.window)))
+      tbar->buttonReleaseEvent(&e->xbutton);
+
+    break;
+  }
+
+  case ConfigureRequest: {
+    // compress configure requests...
+    XEvent realevent;
+    unsigned int i = 0;
+    while(XCheckTypedWindowEvent(getXDisplay(), e->xconfigurerequest.window,
+                                 ConfigureRequest, &realevent)) {
+      i++;
+    }
+    if ( i > 0 )
+      e = &realevent;
+
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Slit *slit = (Slit *) 0;
+
+    if ((win = searchWindow(e->xconfigurerequest.window))) {
+      win->configureRequestEvent(&e->xconfigurerequest);
+    } else if ((slit = searchSlit(e->xconfigurerequest.window))) {
+      slit->configureRequestEvent(&e->xconfigurerequest);
+    } else {
+      if (validateWindow(e->xconfigurerequest.window)) {
+        XWindowChanges xwc;
+
+        xwc.x = e->xconfigurerequest.x;
+        xwc.y = e->xconfigurerequest.y;
+        xwc.width = e->xconfigurerequest.width;
+        xwc.height = e->xconfigurerequest.height;
+        xwc.border_width = e->xconfigurerequest.border_width;
+        xwc.sibling = e->xconfigurerequest.above;
+        xwc.stack_mode = e->xconfigurerequest.detail;
+
+        XConfigureWindow(getXDisplay(), e->xconfigurerequest.window,
+                         e->xconfigurerequest.value_mask, &xwc);
+      }
+    }
+
+    break;
+  }
+
+  case MapRequest: {
+#ifdef    DEBUG
+    fprintf(stderr, "Blackbox::process_event(): MapRequest for 0x%lx\n",
+            e->xmaprequest.window);
+#endif // DEBUG
+
+    BlackboxWindow *win = searchWindow(e->xmaprequest.window);
+
+    if (! win) {
+      BScreen *screen = searchScreen(e->xmaprequest.parent);
+
+      if (! screen) {
+        /*
+          we got a map request for a window who's parent isn't root. this
+          can happen in only one circumstance:
+
+            a client window unmapped a managed window, and then remapped it
+            somewhere between unmapping the client window and reparenting it
+            to root.
+
+          regardless of how it happens, we need to find the screen that
+          the window is on
+        */
+        XWindowAttributes wattrib;
+        if (! XGetWindowAttributes(getXDisplay(), e->xmaprequest.window,
+                                   &wattrib)) {
+          // failed to get the window attributes, perhaps the window has
+          // now been destroyed?
+          break;
+        }
+
+        screen = searchScreen(wattrib.root);
+        assert(screen != 0); // this should never happen
+      }
+
+      screen->manageWindow(e->xmaprequest.window);
+    }
+
+    break;
+  }
+
+  case UnmapNotify: {
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Slit *slit = (Slit *) 0;
+
+    if ((win = searchWindow(e->xunmap.window))) {
+      win->unmapNotifyEvent(&e->xunmap);
+    } else if ((slit = searchSlit(e->xunmap.window))) {
+      slit->unmapNotifyEvent(&e->xunmap);
+    }
+
+    break;
+  }
+
+  case DestroyNotify: {
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Slit *slit = (Slit *) 0;
+    BWindowGroup *group = (BWindowGroup *) 0;
+
+    if ((win = searchWindow(e->xdestroywindow.window))) {
+      win->destroyNotifyEvent(&e->xdestroywindow);
+    } else if ((slit = searchSlit(e->xdestroywindow.window))) {
+      slit->removeClient(e->xdestroywindow.window, False);
+    } else if ((group = searchGroup(e->xdestroywindow.window))) {
+      delete group;
+    }
+
+    break;
+  }
+
+  case ReparentNotify: {
+    /*
+      this event is quite rare and is usually handled in unmapNotify
+      however, if the window is unmapped when the reparent event occurs
+      the window manager never sees it because an unmap event is not sent
+      to an already unmapped window.
+    */
+    BlackboxWindow *win = searchWindow(e->xreparent.window);
+    if (win) {
+      win->reparentNotifyEvent(&e->xreparent);
+    } else {
+      Slit *slit = searchSlit(e->xreparent.window);
+      if (slit && slit->getWindowID() != e->xreparent.parent)
+        slit->removeClient(e->xreparent.window, True);
+    }
+    break;
+  }
+
+  case MotionNotify: {
+    // motion notify compression...
+    XEvent realevent;
+    unsigned int i = 0;
+    while (XCheckTypedWindowEvent(getXDisplay(), e->xmotion.window,
+                                  MotionNotify, &realevent)) {
+      i++;
+    }
+
+    // if we have compressed some motion events, use the last one
+    if ( i > 0 )
+      e = &realevent;
+
+    // strip the lock key modifiers
+    e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
+
+    last_time = e->xmotion.time;
+
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Basemenu *menu = (Basemenu *) 0;
+
+    if ((win = searchWindow(e->xmotion.window)))
+      win->motionNotifyEvent(&e->xmotion);
+    else if ((menu = searchMenu(e->xmotion.window)))
+      menu->motionNotifyEvent(&e->xmotion);
+
+    break;
+  }
+
+  case PropertyNotify: {
+    last_time = e->xproperty.time;
+
+    if (e->xproperty.state != PropertyDelete) {
+      BlackboxWindow *win = searchWindow(e->xproperty.window);
+
+      if (win)
+        win->propertyNotifyEvent(e->xproperty.atom);
+    }
+
+    break;
+  }
+
+  case EnterNotify: {
+    last_time = e->xcrossing.time;
+
+    BScreen *screen = (BScreen *) 0;
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Basemenu *menu = (Basemenu *) 0;
+    Toolbar *tbar = (Toolbar *) 0;
+    Slit *slit = (Slit *) 0;
+
+    if (e->xcrossing.mode == NotifyGrab) break;
+
+    XEvent dummy;
+    scanargs sa;
+    sa.w = e->xcrossing.window;
+    sa.enter = sa.leave = False;
+    XCheckIfEvent(getXDisplay(), &dummy, queueScanner, (char *) &sa);
+
+    if ((e->xcrossing.window == e->xcrossing.root) &&
+        (screen = searchScreen(e->xcrossing.window))) {
+      screen->getImageControl()->installRootColormap();
+    } else if ((win = searchWindow(e->xcrossing.window))) {
+      if (win->getScreen()->isSloppyFocus() &&
+          (! win->isFocused()) && (! no_focus)) {
+        if (((! sa.leave) || sa.inferior) && win->isVisible()) {
+          if (win->setInputFocus())
+            win->installColormap(True); // XXX: shouldnt we honour no install?
+        }
+      }
+    } else if ((menu = searchMenu(e->xcrossing.window))) {
+      menu->enterNotifyEvent(&e->xcrossing);
+    } else if ((tbar = searchToolbar(e->xcrossing.window))) {
+      tbar->enterNotifyEvent(&e->xcrossing);
+    } else if ((slit = searchSlit(e->xcrossing.window))) {
+      slit->enterNotifyEvent(&e->xcrossing);
+    }
+    break;
+  }
+
+  case LeaveNotify: {
+    last_time = e->xcrossing.time;
+
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Basemenu *menu = (Basemenu *) 0;
+    Toolbar *tbar = (Toolbar *) 0;
+    Slit *slit = (Slit *) 0;
+
+    if ((menu = searchMenu(e->xcrossing.window)))
+      menu->leaveNotifyEvent(&e->xcrossing);
+    else if ((win = searchWindow(e->xcrossing.window)))
+      win->installColormap(False);
+    else if ((tbar = searchToolbar(e->xcrossing.window)))
+      tbar->leaveNotifyEvent(&e->xcrossing);
+    else if ((slit = searchSlit(e->xcrossing.window)))
+      slit->leaveNotifyEvent(&e->xcrossing);
+    break;
+  }
+
+  case Expose: {
+    // compress expose events
+    XEvent realevent;
+    unsigned int i = 0;
+    int ex1, ey1, ex2, ey2;
+    ex1 = e->xexpose.x;
+    ey1 = e->xexpose.y;
+    ex2 = ex1 + e->xexpose.width - 1;
+    ey2 = ey1 + e->xexpose.height - 1;
+    while (XCheckTypedWindowEvent(getXDisplay(), e->xexpose.window,
+                                  Expose, &realevent)) {
+      i++;
+
+      // merge expose area
+      ex1 = std::min(realevent.xexpose.x, ex1);
+      ey1 = std::min(realevent.xexpose.y, ey1);
+      ex2 = std::max(realevent.xexpose.x + realevent.xexpose.width - 1, ex2);
+      ey2 = std::max(realevent.xexpose.y + realevent.xexpose.height - 1, ey2);
+    }
+    if ( i > 0 )
+      e = &realevent;
+
+    // use the merged area
+    e->xexpose.x = ex1;
+    e->xexpose.y = ey1;
+    e->xexpose.width = ex2 - ex1 + 1;
+    e->xexpose.height = ey2 - ey1 + 1;
+
+    BlackboxWindow *win = (BlackboxWindow *) 0;
+    Basemenu *menu = (Basemenu *) 0;
+    Toolbar *tbar = (Toolbar *) 0;
+
+    if ((win = searchWindow(e->xexpose.window)))
+      win->exposeEvent(&e->xexpose);
+    else if ((menu = searchMenu(e->xexpose.window)))
+      menu->exposeEvent(&e->xexpose);
+    else if ((tbar = searchToolbar(e->xexpose.window)))
+      tbar->exposeEvent(&e->xexpose);
+
+    break;
+  }
+
+  case KeyPress: {
+    Toolbar *tbar = searchToolbar(e->xkey.window);
+
+    if (tbar && tbar->isEditing())
+      tbar->keyPressEvent(&e->xkey);
+
+    break;
+  }
+
+  case ColormapNotify: {
+    BScreen *screen = searchScreen(e->xcolormap.window);
+
+    if (screen)
+      screen->setRootColormapInstalled((e->xcolormap.state ==
+                                        ColormapInstalled) ? True : False);
+
+    break;
+  }
+
+  case FocusIn: {
+    if (e->xfocus.detail != NotifyNonlinear) {
+      /*
+        don't process FocusIns when:
+        1. the new focus window isn't an ancestor or inferior of the old
+        focus window (NotifyNonlinear)
+      */
+      break;
+    }
+
+    BlackboxWindow *win = searchWindow(e->xfocus.window);
+    if (win) {
+      if (! win->isFocused())
+        win->setFocusFlag(True);
+
+      /*
+        set the event window to None.  when the FocusOut event handler calls
+        this function recursively, it uses this as an indication that focus
+        has moved to a known window.
+      */
+      e->xfocus.window = None;
+    }
+
+    break;
+  }
+
+  case FocusOut: {
+    if (e->xfocus.detail != NotifyNonlinear) {
+      /*
+        don't process FocusOuts when:
+        2. the new focus window isn't an ancestor or inferior of the old
+        focus window (NotifyNonlinear)
+      */
+      break;
+    }
+
+    BlackboxWindow *win = searchWindow(e->xfocus.window);
+    if (win && win->isFocused()) {
+      /*
+        before we mark "win" as unfocused, we need to verify that focus is
+        going to a known location, is in a known location, or set focus
+        to a known location.
+      */
+
+      XEvent event;
+      // don't check the current focus if FocusOut was generated during a grab
+      bool check_focus = (e->xfocus.mode == NotifyNormal);
+
+      /*
+        First, check if there is a pending FocusIn event waiting.  if there
+        is, process it and determine if focus has moved to another window
+        (the FocusIn event handler sets the window in the event
+        structure to None to indicate this).
+      */
+      if (XCheckTypedEvent(getXDisplay(), FocusIn, &event)) {
+
+        process_event(&event);
+        if (event.xfocus.window == None) {
+          // focus has moved
+          check_focus = False;
+        }
+      }
+
+      if (check_focus) {
+        /*
+          Second, we query the X server for the current input focus.
+          to make sure that we keep a consistent state.
+        */
+        BlackboxWindow *focus;
+        Window w;
+        int revert;
+        XGetInputFocus(getXDisplay(), &w, &revert);
+        focus = searchWindow(w);
+        if (focus) {
+          /*
+            focus got from "win" to "focus" under some very strange
+            circumstances, and we need to make sure that the focus indication
+            is correct.
+          */
+          setFocusedWindow(focus);
+        } else {
+          // we have no idea where focus went... so we set it to somewhere
+          setFocusedWindow(0);
+        }
+      }
+    }
+
+    break;
+  }
+
+  case ClientMessage: {
+    if (e->xclient.format == 32) {
+      if (e->xclient.message_type == getWMChangeStateAtom()) {
+        BlackboxWindow *win = searchWindow(e->xclient.window);
+        if (! win || ! win->validateClient()) return;
+
+        if (e->xclient.data.l[0] == IconicState)
+          win->iconify();
+        if (e->xclient.data.l[0] == NormalState)
+          win->deiconify();
+      } else if(e->xclient.message_type == getBlackboxChangeWorkspaceAtom()) {
+        BScreen *screen = searchScreen(e->xclient.window);
+
+        if (screen && e->xclient.data.l[0] >= 0 &&
+            e->xclient.data.l[0] <
+            static_cast<signed>(screen->getWorkspaceCount()))
+          screen->changeWorkspaceID(e->xclient.data.l[0]);
+      } else if (e->xclient.message_type == getBlackboxChangeWindowFocusAtom()) {
+        BlackboxWindow *win = searchWindow(e->xclient.window);
+
+        if (win && win->isVisible() && win->setInputFocus())
+          win->installColormap(True);
+      } else if (e->xclient.message_type == getBlackboxCycleWindowFocusAtom()) {
+        BScreen *screen = searchScreen(e->xclient.window);
+
+        if (screen) {
+          if (! e->xclient.data.l[0])
+            screen->prevFocus();
+          else
+            screen->nextFocus();
+        }
+      } else if (e->xclient.message_type == getBlackboxChangeAttributesAtom()) {
+        BlackboxWindow *win = searchWindow(e->xclient.window);
+
+        if (win && win->validateClient()) {
+          BlackboxHints net;
+          net.flags = e->xclient.data.l[0];
+          net.attrib = e->xclient.data.l[1];
+          net.workspace = e->xclient.data.l[2];
+          net.stack = e->xclient.data.l[3];
+          net.decoration = e->xclient.data.l[4];
+
+          win->changeBlackboxHints(&net);
+        }
+      }
+    }
+
+    break;
+  }
+
+  case NoExpose:
+  case ConfigureNotify:
+  case MapNotify:
+    break; // not handled, just ignore
+
+  default: {
+#ifdef    SHAPE
+    if (e->type == getShapeEventBase()) {
+      XShapeEvent *shape_event = (XShapeEvent *) e;
+      BlackboxWindow *win = searchWindow(e->xany.window);
+
+      if (win)
+        win->shapeEvent(shape_event);
+    }
+#endif // SHAPE
+  }
+  } // switch
+}
+
+
+bool Blackbox::handleSignal(int sig) {
+  switch (sig) {
+  case SIGHUP:
+    reconfigure();
+    break;
+
+  case SIGUSR1:
+    reload_rc();
+    break;
+
+  case SIGUSR2:
+    rereadMenu();
+    break;
+
+  case SIGPIPE:
+  case SIGSEGV:
+  case SIGFPE:
+  case SIGINT:
+  case SIGTERM:
+    shutdown();
+
+  default:
+    return False;
+  }
+
+  return True;
+}
+
+
+void Blackbox::init_icccm(void) {
+  xa_wm_colormap_windows =
+    XInternAtom(getXDisplay(), "WM_COLORMAP_WINDOWS", False);
+  xa_wm_protocols = XInternAtom(getXDisplay(), "WM_PROTOCOLS", False);
+  xa_wm_state = XInternAtom(getXDisplay(), "WM_STATE", False);
+  xa_wm_change_state = XInternAtom(getXDisplay(), "WM_CHANGE_STATE", False);
+  xa_wm_delete_window = XInternAtom(getXDisplay(), "WM_DELETE_WINDOW", False);
+  xa_wm_take_focus = XInternAtom(getXDisplay(), "WM_TAKE_FOCUS", False);
+  motif_wm_hints = XInternAtom(getXDisplay(), "_MOTIF_WM_HINTS", False);
+
+  blackbox_hints = XInternAtom(getXDisplay(), "_BLACKBOX_HINTS", False);
+  blackbox_attributes =
+    XInternAtom(getXDisplay(), "_BLACKBOX_ATTRIBUTES", False);
+  blackbox_change_attributes =
+    XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_ATTRIBUTES", False);
+  blackbox_structure_messages =
+    XInternAtom(getXDisplay(), "_BLACKBOX_STRUCTURE_MESSAGES", False);
+  blackbox_notify_startup =
+    XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_STARTUP", False);
+  blackbox_notify_window_add =
+    XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_ADD", False);
+  blackbox_notify_window_del =
+    XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_DEL", False);
+  blackbox_notify_current_workspace =
+    XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_CURRENT_WORKSPACE", False);
+  blackbox_notify_workspace_count =
+    XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WORKSPACE_COUNT", False);
+  blackbox_notify_window_focus =
+    XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_FOCUS", False);
+  blackbox_notify_window_raise =
+    XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_RAISE", False);
+  blackbox_notify_window_lower =
+    XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_LOWER", False);
+  blackbox_change_workspace =
+    XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_WORKSPACE", False);
+  blackbox_change_window_focus =
+    XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_WINDOW_FOCUS", False);
+  blackbox_cycle_window_focus =
+    XInternAtom(getXDisplay(), "_BLACKBOX_CYCLE_WINDOW_FOCUS", False);
+
+#ifdef    NEWWMSPEC
+  net_supported = XInternAtom(getXDisplay(), "_NET_SUPPORTED", False);
+  net_client_list = XInternAtom(getXDisplay(), "_NET_CLIENT_LIST", False);
+  net_client_list_stacking =
+    XInternAtom(getXDisplay(), "_NET_CLIENT_LIST_STACKING", False);
+  net_number_of_desktops =
+    XInternAtom(getXDisplay(), "_NET_NUMBER_OF_DESKTOPS", False);
+  net_desktop_geometry =
+    XInternAtom(getXDisplay(), "_NET_DESKTOP_GEOMETRY", False);
+  net_desktop_viewport =
+    XInternAtom(getXDisplay(), "_NET_DESKTOP_VIEWPORT", False);
+  net_current_desktop =
+    XInternAtom(getXDisplay(), "_NET_CURRENT_DESKTOP", False);
+  net_desktop_names = XInternAtom(getXDisplay(), "_NET_DESKTOP_NAMES", False);
+  net_active_window = XInternAtom(getXDisplay(), "_NET_ACTIVE_WINDOW", False);
+  net_workarea = XInternAtom(getXDisplay(), "_NET_WORKAREA", False);
+  net_supporting_wm_check =
+    XInternAtom(getXDisplay(), "_NET_SUPPORTING_WM_CHECK", False);
+  net_virtual_roots = XInternAtom(getXDisplay(), "_NET_VIRTUAL_ROOTS", False);
+  net_close_window = XInternAtom(getXDisplay(), "_NET_CLOSE_WINDOW", False);
+  net_wm_moveresize = XInternAtom(getXDisplay(), "_NET_WM_MOVERESIZE", False);
+  net_properties = XInternAtom(getXDisplay(), "_NET_PROPERTIES", False);
+  net_wm_name = XInternAtom(getXDisplay(), "_NET_WM_NAME", False);
+  net_wm_desktop = XInternAtom(getXDisplay(), "_NET_WM_DESKTOP", False);
+  net_wm_window_type =
+    XInternAtom(getXDisplay(), "_NET_WM_WINDOW_TYPE", False);
+  net_wm_state = XInternAtom(getXDisplay(), "_NET_WM_STATE", False);
+  net_wm_strut = XInternAtom(getXDisplay(), "_NET_WM_STRUT", False);
+  net_wm_icon_geometry =
+    XInternAtom(getXDisplay(), "_NET_WM_ICON_GEOMETRY", False);
+  net_wm_icon = XInternAtom(getXDisplay(), "_NET_WM_ICON", False);
+  net_wm_pid = XInternAtom(getXDisplay(), "_NET_WM_PID", False);
+  net_wm_handled_icons =
+    XInternAtom(getXDisplay(), "_NET_WM_HANDLED_ICONS", False);
+  net_wm_ping = XInternAtom(getXDisplay(), "_NET_WM_PING", False);
+#endif // NEWWMSPEC
+
+#ifdef    HAVE_GETPID
+  blackbox_pid = XInternAtom(getXDisplay(), "_BLACKBOX_PID", False);
+#endif // HAVE_GETPID
+}
+
+
+bool Blackbox::validateWindow(Window window) {
+  XEvent event;
+  if (XCheckTypedWindowEvent(getXDisplay(), window, DestroyNotify, &event)) {
+    XPutBackEvent(getXDisplay(), &event);
+
+    return False;
+  }
+
+  return True;
+}
+
+
+BScreen *Blackbox::searchScreen(Window window) {
+  ScreenList::iterator it = screenList.begin();
+
+  for (; it != screenList.end(); ++it) {
+    BScreen *s = *it;
+    if (s->getRootWindow() == window)
+      return s;
+  }
+
+  return (BScreen *) 0;
+}
+
+
+BlackboxWindow *Blackbox::searchWindow(Window window) {
+  WindowLookup::iterator it = windowSearchList.find(window);
+  if (it != windowSearchList.end())
+    return it->second;
+
+  return (BlackboxWindow*) 0;
+}
+
+
+BWindowGroup *Blackbox::searchGroup(Window window) {
+  GroupLookup::iterator it = groupSearchList.find(window);
+  if (it != groupSearchList.end())
+    return it->second;
+
+  return (BWindowGroup *) 0;
+}
+
+
+Basemenu *Blackbox::searchMenu(Window window) {
+  MenuLookup::iterator it = menuSearchList.find(window);
+  if (it != menuSearchList.end())
+    return it->second;
+
+  return (Basemenu*) 0;
+}
+
+
+Toolbar *Blackbox::searchToolbar(Window window) {
+  ToolbarLookup::iterator it = toolbarSearchList.find(window);
+  if (it != toolbarSearchList.end())
+    return it->second;
+
+  return (Toolbar*) 0;
+}
+
+
+Slit *Blackbox::searchSlit(Window window) {
+  SlitLookup::iterator it = slitSearchList.find(window);
+  if (it != slitSearchList.end())
+    return it->second;
+
+  return (Slit*) 0;
+}
+
+
+void Blackbox::saveWindowSearch(Window window, BlackboxWindow *data) {
+  windowSearchList.insert(WindowLookupPair(window, data));
+}
+
+
+void Blackbox::saveGroupSearch(Window window, BWindowGroup *data) {
+  groupSearchList.insert(GroupLookupPair(window, data));
+}
+
+
+void Blackbox::saveMenuSearch(Window window, Basemenu *data) {
+  menuSearchList.insert(MenuLookupPair(window, data));
+}
+
+
+void Blackbox::saveToolbarSearch(Window window, Toolbar *data) {
+  toolbarSearchList.insert(ToolbarLookupPair(window, data));
+}
+
+
+void Blackbox::saveSlitSearch(Window window, Slit *data) {
+  slitSearchList.insert(SlitLookupPair(window, data));
+}
+
+
+void Blackbox::removeWindowSearch(Window window) {
+  windowSearchList.erase(window);
+}
+
+
+void Blackbox::removeGroupSearch(Window window) {
+  groupSearchList.erase(window);
+}
+
+
+void Blackbox::removeMenuSearch(Window window) {
+  menuSearchList.erase(window);
+}
+
+
+void Blackbox::removeToolbarSearch(Window window) {
+  toolbarSearchList.erase(window);
+}
+
+
+void Blackbox::removeSlitSearch(Window window) {
+  slitSearchList.erase(window);
+}
+
+
+void Blackbox::restart(const char *prog) {
+  shutdown();
+
+  if (prog) {
+    execlp(prog, prog, NULL);
+    perror(prog);
+  }
+
+  // fall back in case the above execlp doesn't work
+  execvp(argv[0], argv);
+  string name = basename(argv[0]);
+  execvp(name.c_str(), argv);
+}
+
+
+void Blackbox::shutdown(void) {
+  BaseDisplay::shutdown();
+
+  XSetInputFocus(getXDisplay(), PointerRoot, None, CurrentTime);
+
+  std::for_each(screenList.begin(), screenList.end(),
+                std::mem_fun(&BScreen::shutdown));
+
+  XSync(getXDisplay(), False);
+
+  save_rc();
+}
+
+
+void Blackbox::save_rc(void) {
+  XrmDatabase new_blackboxrc = (XrmDatabase) 0;
+  char rc_string[1024];
+
+  load_rc();
+
+  sprintf(rc_string, "session.menuFile:  %s", getMenuFilename());
+  XrmPutLineResource(&new_blackboxrc, rc_string);
+
+  sprintf(rc_string, "session.colorsPerChannel:  %d",
+          resource.colors_per_channel);
+  XrmPutLineResource(&new_blackboxrc, rc_string);
+
+  sprintf(rc_string, "session.doubleClickInterval:  %lu",
+          resource.double_click_interval);
+  XrmPutLineResource(&new_blackboxrc, rc_string);
+
+  sprintf(rc_string, "session.autoRaiseDelay:  %lu",
+          ((resource.auto_raise_delay.tv_sec * 1000) +
+           (resource.auto_raise_delay.tv_usec / 1000)));
+  XrmPutLineResource(&new_blackboxrc, rc_string);
+
+  sprintf(rc_string, "session.cacheLife: %lu", resource.cache_life / 60000);
+  XrmPutLineResource(&new_blackboxrc, rc_string);
+
+  sprintf(rc_string, "session.cacheMax: %lu", resource.cache_max);
+  XrmPutLineResource(&new_blackboxrc, rc_string);
+
+  ScreenList::iterator it = screenList.begin();
+  for (; it != screenList.end(); ++it) {
+    BScreen *screen = *it;
+    int screen_number = screen->getScreenNumber();
+
+    char *placement = (char *) 0;
+
+    switch (screen->getSlitPlacement()) {
+    case Slit::TopLeft: placement = "TopLeft"; break;
+    case Slit::CenterLeft: placement = "CenterLeft"; break;
+    case Slit::BottomLeft: placement = "BottomLeft"; break;
+    case Slit::TopCenter: placement = "TopCenter"; break;
+    case Slit::BottomCenter: placement = "BottomCenter"; break;
+    case Slit::TopRight: placement = "TopRight"; break;
+    case Slit::BottomRight: placement = "BottomRight"; break;
+    case Slit::CenterRight: default: placement = "CenterRight"; break;
+    }
+
+    sprintf(rc_string, "session.screen%d.slit.placement: %s", screen_number,
+            placement);
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.slit.direction: %s", screen_number,
+            ((screen->getSlitDirection() == Slit::Horizontal) ? "Horizontal" :
+             "Vertical"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.slit.onTop: %s", screen_number,
+            ((screen->getSlit()->isOnTop()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.slit.autoHide: %s", screen_number,
+            ((screen->getSlit()->doAutoHide()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.opaqueMove: %s",
+            ((screen->doOpaqueMove()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.imageDither: %s",
+            ((screen->getImageControl()->doDither()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.fullMaximization: %s", screen_number,
+            ((screen->doFullMax()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.focusNewWindows: %s", screen_number,
+            ((screen->doFocusNew()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.focusLastWindow: %s", screen_number,
+            ((screen->doFocusLast()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.rowPlacementDirection: %s",
+            screen_number,
+            ((screen->getRowPlacementDirection() == BScreen::LeftRight) ?
+             "LeftToRight" : "RightToLeft"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.colPlacementDirection: %s",
+            screen_number,
+            ((screen->getColPlacementDirection() == BScreen::TopBottom) ?
+             "TopToBottom" : "BottomToTop"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    switch (screen->getPlacementPolicy()) {
+    case BScreen::CascadePlacement:
+      placement = "CascadePlacement";
+      break;
+    case BScreen::ColSmartPlacement:
+      placement = "ColSmartPlacement";
+      break;
+
+    case BScreen::RowSmartPlacement:
+    default:
+      placement = "RowSmartPlacement";
+      break;
+    }
+    sprintf(rc_string, "session.screen%d.windowPlacement:  %s", screen_number,
+            placement);
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    string fmodel;
+    if (screen->isSloppyFocus()) {
+      fmodel = "SloppyFocus";
+      if (screen->doAutoRaise()) fmodel += " AutoRaise";
+      if (screen->doClickRaise()) fmodel += " ClickRaise";
+    } else {
+      fmodel = "ClickToFocus";
+    }
+    sprintf(rc_string, "session.screen%d.focusModel:  %s", screen_number,
+            fmodel.c_str());
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.workspaces:  %d", screen_number,
+            screen->getWorkspaceCount());
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.toolbar.onTop:  %s", screen_number,
+            ((screen->getToolbar()->isOnTop()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.toolbar.autoHide:  %s",
+            screen_number,
+            ((screen->getToolbar()->doAutoHide()) ? "True" : "False"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    switch (screen->getToolbarPlacement()) {
+    case Toolbar::TopLeft: placement = "TopLeft"; break;
+    case Toolbar::BottomLeft: placement = "BottomLeft"; break;
+    case Toolbar::TopCenter: placement = "TopCenter"; break;
+    case Toolbar::TopRight: placement = "TopRight"; break;
+    case Toolbar::BottomRight: placement = "BottomRight"; break;
+    case Toolbar::BottomCenter: default: placement = "BottomCenter"; break;
+    }
+
+    sprintf(rc_string, "session.screen%d.toolbar.placement: %s",
+            screen_number, placement);
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    load_rc(screen);
+
+    // these are static, but may not be saved in the users .blackboxrc,
+    // writing these resources will allow the user to edit them at a later
+    // time... but loading the defaults before saving allows us to rewrite the
+    // users changes...
+
+#ifdef    HAVE_STRFTIME
+    sprintf(rc_string, "session.screen%d.strftimeFormat: %s", screen_number,
+            screen->getStrftimeFormat());
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+#else // !HAVE_STRFTIME
+    sprintf(rc_string, "session.screen%d.dateFormat:  %s", screen_number,
+            ((screen->getDateFormat() == B_EuropeanDate) ?
+             "European" : "American"));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.clockFormat:  %d", screen_number,
+            ((screen->isClock24Hour()) ? 24 : 12));
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+#endif // HAVE_STRFTIME
+
+    sprintf(rc_string, "session.screen%d.edgeSnapThreshold: %d",
+            screen_number, screen->getEdgeSnapThreshold());
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    sprintf(rc_string, "session.screen%d.toolbar.widthPercent:  %d",
+            screen_number, screen->getToolbarWidthPercent());
+    XrmPutLineResource(&new_blackboxrc, rc_string);
+
+    // write out the user's workspace names
+
+    string save_string = screen->getWorkspace(0)->getName();
+    for (unsigned int i = 1; i < screen->getWorkspaceCount(); ++i) {
+      save_string += ',';
+      save_string += screen->getWorkspace(i)->getName();
+    }
+
+    char *resource_string = new char[save_string.length() + 48];
+    sprintf(resource_string, "session.screen%d.workspaceNames:  %s",
+            screen_number, save_string.c_str());
+    XrmPutLineResource(&new_blackboxrc, resource_string);
+
+    delete [] resource_string;
+  }
+
+  XrmDatabase old_blackboxrc = XrmGetFileDatabase(rc_file.c_str());
+
+  XrmMergeDatabases(new_blackboxrc, &old_blackboxrc);
+  XrmPutFileDatabase(old_blackboxrc, rc_file.c_str());
+  XrmDestroyDatabase(old_blackboxrc);
+}
+
+
+void Blackbox::load_rc(void) {
+  XrmDatabase database = (XrmDatabase) 0;
+
+  database = XrmGetFileDatabase(rc_file.c_str());
+
+  XrmValue value;
+  char *value_type;
+  int int_value;
+  unsigned long long_value;
+
+  if (XrmGetResource(database, "session.menuFile", "Session.MenuFile",
+                     &value_type, &value)) {
+    resource.menu_file = expandTilde(value.addr);
+  } else {
+    resource.menu_file = DEFAULTMENU;
+  }
+
+  resource.colors_per_channel = 4;
+  if (XrmGetResource(database, "session.colorsPerChannel",
+                     "Session.ColorsPerChannel", &value_type, &value) &&
+      sscanf(value.addr, "%d", &int_value) == 1) {
+    resource.colors_per_channel = int_value;
+    if (resource.colors_per_channel < 2) resource.colors_per_channel = 2;
+    if (resource.colors_per_channel > 6) resource.colors_per_channel = 6;
+  }
+
+  if (XrmGetResource(database, "session.styleFile", "Session.StyleFile",
+                     &value_type, &value))
+    resource.style_file = expandTilde(value.addr);
+  else
+    resource.style_file = DEFAULTSTYLE;
+
+  resource.double_click_interval = 250;
+  if (XrmGetResource(database, "session.doubleClickInterval",
+                     "Session.DoubleClickInterval", &value_type, &value) &&
+      sscanf(value.addr, "%lu", &long_value) == 1) {
+    resource.double_click_interval = long_value;
+  }
+
+  resource.auto_raise_delay.tv_usec = 400;
+  if (XrmGetResource(database, "session.autoRaiseDelay",
+                     "Session.AutoRaiseDelay", &value_type, &value) &&
+      sscanf(value.addr, "%lu", &long_value) == 1) {
+    resource.auto_raise_delay.tv_usec = long_value;
+  }
+
+  resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec / 1000;
+  resource.auto_raise_delay.tv_usec -=
+    (resource.auto_raise_delay.tv_sec * 1000);
+  resource.auto_raise_delay.tv_usec *= 1000;
+
+  resource.cache_life = 5l;
+  if (XrmGetResource(database, "session.cacheLife", "Session.CacheLife",
+                     &value_type, &value) &&
+      sscanf(value.addr, "%lu", &long_value) == 1) {
+    resource.cache_life = long_value;
+  }
+  resource.cache_life *= 60000;
+
+  resource.cache_max = 200;
+  if (XrmGetResource(database, "session.cacheMax", "Session.CacheMax",
+                     &value_type, &value) &&
+      sscanf(value.addr, "%lu", &long_value) == 1) {
+    resource.cache_max = long_value;
+  }
+}
+
+
+void Blackbox::load_rc(BScreen *screen) {
+  XrmDatabase database = (XrmDatabase) 0;
+
+  database = XrmGetFileDatabase(rc_file.c_str());
+
+  XrmValue value;
+  char *value_type, name_lookup[1024], class_lookup[1024];
+  int screen_number = screen->getScreenNumber();
+  int int_value;
+
+  sprintf(name_lookup,  "session.screen%d.fullMaximization", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.FullMaximization", screen_number);
+  screen->saveFullMax(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "true", value.size)) {
+    screen->saveFullMax(True);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.focusNewWindows", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.FocusNewWindows", screen_number);
+  screen->saveFocusNew(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "true", value.size)) {
+    screen->saveFocusNew(True);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.focusLastWindow", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.focusLastWindow", screen_number);
+  screen->saveFocusLast(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "true", value.size)) {
+    screen->saveFocusLast(True);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.rowPlacementDirection",
+          screen_number);
+  sprintf(class_lookup, "Session.Screen%d.RowPlacementDirection",
+          screen_number);
+  screen->saveRowPlacementDirection(BScreen::LeftRight);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "righttoleft", value.size)) {
+    screen->saveRowPlacementDirection(BScreen::RightLeft);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.colPlacementDirection",
+          screen_number);
+  sprintf(class_lookup, "Session.Screen%d.ColPlacementDirection",
+          screen_number);
+  screen->saveColPlacementDirection(BScreen::TopBottom);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "bottomtotop", value.size)) {
+    screen->saveColPlacementDirection(BScreen::BottomTop);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.workspaces", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Workspaces", screen_number);
+  screen->saveWorkspaces(1);
+  if (XrmGetResource(database, name_lookup, class_lookup,
+                     &value_type, &value) &&
+      sscanf(value.addr, "%d", &int_value) == 1 &&
+      int_value > 0 && int_value < 128) {
+    screen->saveWorkspaces(int_value);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.toolbar.widthPercent",
+          screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Toolbar.WidthPercent",
+          screen_number);
+  screen->saveToolbarWidthPercent(66);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      sscanf(value.addr, "%d", &int_value) == 1 &&
+      int_value > 0 && int_value <= 100) {
+    screen->saveToolbarWidthPercent(int_value);
+  }
+
+  sprintf(name_lookup, "session.screen%d.toolbar.placement", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Toolbar.Placement", screen_number);
+  screen->saveToolbarPlacement(Toolbar::BottomCenter);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value)) {
+    if (! strncasecmp(value.addr, "TopLeft", value.size))
+      screen->saveToolbarPlacement(Toolbar::TopLeft);
+    else if (! strncasecmp(value.addr, "BottomLeft", value.size))
+      screen->saveToolbarPlacement(Toolbar::BottomLeft);
+    else if (! strncasecmp(value.addr, "TopCenter", value.size))
+      screen->saveToolbarPlacement(Toolbar::TopCenter);
+    else if (! strncasecmp(value.addr, "TopRight", value.size))
+      screen->saveToolbarPlacement(Toolbar::TopRight);
+    else if (! strncasecmp(value.addr, "BottomRight", value.size))
+      screen->saveToolbarPlacement(Toolbar::BottomRight);
+  }
+  screen->removeWorkspaceNames();
+
+  sprintf(name_lookup,  "session.screen%d.workspaceNames", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.WorkspaceNames", screen_number);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value)) {
+    string search = value.addr;
+    string::const_iterator it = search.begin(),
+      end = search.end();
+    while (1) {
+      string::const_iterator tmp = it; // current string.begin()
+      it = std::find(tmp, end, ',');   // look for comma between tmp and end
+      screen->addWorkspaceName(string(tmp, it)); // string = search[tmp:it]
+      if (it == end) break;
+      ++it;
+    }
+  }
+
+  sprintf(name_lookup,  "session.screen%d.toolbar.onTop", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Toolbar.OnTop", screen_number);
+  screen->saveToolbarOnTop(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "true", value.size)) {
+    screen->saveToolbarOnTop(True);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.toolbar.autoHide", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Toolbar.autoHide", screen_number);
+  screen->saveToolbarAutoHide(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "true", value.size)) {
+    screen->saveToolbarAutoHide(True);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.focusModel", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.FocusModel", screen_number);
+  screen->saveSloppyFocus(True);
+  screen->saveAutoRaise(False);
+  screen->saveClickRaise(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value)) {
+    string fmodel = value.addr;
+
+    if (fmodel.find("ClickToFocus") != string::npos) {
+      screen->saveSloppyFocus(False);
+    } else {
+      // must be sloppy
+
+      if (fmodel.find("AutoRaise") != string::npos)
+        screen->saveAutoRaise(True);
+      if (fmodel.find("ClickRaise") != string::npos)
+        screen->saveClickRaise(True);
+    }
+  }
+
+  sprintf(name_lookup,  "session.screen%d.windowPlacement", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.WindowPlacement", screen_number);
+  screen->savePlacementPolicy(BScreen::RowSmartPlacement);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value)) {
+    if (! strncasecmp(value.addr, "RowSmartPlacement", value.size))
+      /* pass */;
+    else if (! strncasecmp(value.addr, "ColSmartPlacement", value.size))
+      screen->savePlacementPolicy(BScreen::ColSmartPlacement);
+    else if (! strncasecmp(value.addr, "CascadePlacement", value.size))
+      screen->savePlacementPolicy(BScreen::CascadePlacement);
+  }
+
+  sprintf(name_lookup, "session.screen%d.slit.placement", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Slit.Placement", screen_number);
+  screen->saveSlitPlacement(Slit::CenterRight);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value)) {
+    if (! strncasecmp(value.addr, "TopLeft", value.size))
+      screen->saveSlitPlacement(Slit::TopLeft);
+    else if (! strncasecmp(value.addr, "CenterLeft", value.size))
+      screen->saveSlitPlacement(Slit::CenterLeft);
+    else if (! strncasecmp(value.addr, "BottomLeft", value.size))
+      screen->saveSlitPlacement(Slit::BottomLeft);
+    else if (! strncasecmp(value.addr, "TopCenter", value.size))
+      screen->saveSlitPlacement(Slit::TopCenter);
+    else if (! strncasecmp(value.addr, "BottomCenter", value.size))
+      screen->saveSlitPlacement(Slit::BottomCenter);
+    else if (! strncasecmp(value.addr, "TopRight", value.size))
+      screen->saveSlitPlacement(Slit::TopRight);
+    else if (! strncasecmp(value.addr, "BottomRight", value.size))
+      screen->saveSlitPlacement(Slit::BottomRight);
+  }
+
+  sprintf(name_lookup, "session.screen%d.slit.direction", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Slit.Direction", screen_number);
+  screen->saveSlitDirection(Slit::Vertical);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "Horizontal", value.size)) {
+    screen->saveSlitDirection(Slit::Horizontal);
+  }
+
+  sprintf(name_lookup, "session.screen%d.slit.onTop", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Slit.OnTop", screen_number);
+  screen->saveSlitOnTop(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "True", value.size)) {
+    screen->saveSlitOnTop(True);
+  }
+
+  sprintf(name_lookup, "session.screen%d.slit.autoHide", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.Slit.AutoHide", screen_number);
+  screen->saveSlitAutoHide(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      ! strncasecmp(value.addr, "true", value.size)) {
+    screen->saveSlitAutoHide(True);
+  }
+
+#ifdef    HAVE_STRFTIME
+  sprintf(name_lookup,  "session.screen%d.strftimeFormat", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.StrftimeFormat", screen_number);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value)) {
+    screen->saveStrftimeFormat(value.addr);
+  } else {
+    screen->saveStrftimeFormat("%I:%M %p");
+  }
+#else //  HAVE_STRFTIME
+  sprintf(name_lookup,  "session.screen%d.dateFormat", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.DateFormat", screen_number);
+  screen->saveDateFormat(B_AmericanDate);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value)) {
+    if (! strncasecmp(value.addr, "european", value.size))
+      screen->saveDateFormat(B_EuropeanDate);
+  }
+
+  sprintf(name_lookup,  "session.screen%d.clockFormat", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.ClockFormat", screen_number);
+  screen->saveClock24Hour(False);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      sscanf(value.addr, "%d", &int_value) == 1 && int_value == 24) {
+    screen->saveClock24Hour(True);
+  }
+#endif // HAVE_STRFTIME
+
+  sprintf(name_lookup,  "session.screen%d.edgeSnapThreshold", screen_number);
+  sprintf(class_lookup, "Session.Screen%d.EdgeSnapThreshold", screen_number);
+  if (XrmGetResource(database, name_lookup, class_lookup, &value_type,
+                     &value) &&
+      sscanf(value.addr, "%d", &int_value) == 1) {
+    screen->saveEdgeSnapThreshold(int_value);
+  }
+
+  screen->saveImageDither(True);
+  if (XrmGetResource(database, "session.imageDither", "Session.ImageDither",
+                     &value_type, &value) &&
+      ! strncasecmp("false", value.addr, value.size)) {
+    screen->saveImageDither(False);
+  }
+
+  screen->saveOpaqueMove(False);
+  if (XrmGetResource(database, "session.opaqueMove", "Session.OpaqueMove",
+                     &value_type, &value) &&
+      ! strncasecmp("true", value.addr, value.size)) {
+    screen->saveOpaqueMove(True);
+  }
+
+  XrmDestroyDatabase(database);
+}
+
+
+void Blackbox::reload_rc(void) {
+  load_rc();
+  reconfigure();
+}
+
+
+void Blackbox::reconfigure(void) {
+  reconfigure_wait = True;
+
+  if (! timer->isTiming()) timer->start();
+}
+
+
+void Blackbox::real_reconfigure(void) {
+  XrmDatabase new_blackboxrc = (XrmDatabase) 0;
+  char *style = new char[resource.style_file.length() + 20];
+
+  sprintf(style, "session.styleFile: %s", getStyleFilename());
+  XrmPutLineResource(&new_blackboxrc, style);
+
+  delete [] style;
+
+  XrmDatabase old_blackboxrc = XrmGetFileDatabase(rc_file.c_str());
+
+  XrmMergeDatabases(new_blackboxrc, &old_blackboxrc);
+  XrmPutFileDatabase(old_blackboxrc, rc_file.c_str());
+  if (old_blackboxrc) XrmDestroyDatabase(old_blackboxrc);
+
+  std::for_each(menuTimestamps.begin(), menuTimestamps.end(),
+                PointerAssassin());
+  menuTimestamps.clear();
+
+  gcCache()->purge();
+
+  std::for_each(screenList.begin(), screenList.end(),
+                std::mem_fun(&BScreen::reconfigure));
+}
+
+
+void Blackbox::checkMenu(void) {
+  bool reread = False;
+  MenuTimestampList::iterator it = menuTimestamps.begin();
+  for(; it != menuTimestamps.end(); ++it) {
+    MenuTimestamp *tmp = *it;
+    struct stat buf;
+
+    if (! stat(tmp->filename.c_str(), &buf)) {
+      if (tmp->timestamp != buf.st_ctime)
+        reread = True;
+    } else {
+      reread = True;
+    }
+  }
+
+  if (reread) rereadMenu();
+}
+
+
+void Blackbox::rereadMenu(void) {
+  reread_menu_wait = True;
+
+  if (! timer->isTiming()) timer->start();
+}
+
+
+void Blackbox::real_rereadMenu(void) {
+  std::for_each(menuTimestamps.begin(), menuTimestamps.end(),
+                PointerAssassin());
+  menuTimestamps.clear();
+
+  std::for_each(screenList.begin(), screenList.end(),
+                std::mem_fun(&BScreen::rereadMenu));
+}
+
+
+void Blackbox::saveStyleFilename(const string& filename) {
+  assert(! filename.empty());
+  resource.style_file = filename;
+}
+
+
+void Blackbox::saveMenuFilename(const string& filename) {
+  assert(! filename.empty());
+  bool found = False;
+
+  MenuTimestampList::iterator it = menuTimestamps.begin();
+  for (; it != menuTimestamps.end() && !found; ++it) {
+    if ((*it)->filename == filename) found = True;
+  }
+  if (! found) {
+    struct stat buf;
+
+    if (! stat(filename.c_str(), &buf)) {
+      MenuTimestamp *ts = new MenuTimestamp;
+
+      ts->filename = filename;
+      ts->timestamp = buf.st_ctime;
+
+      menuTimestamps.push_back(ts);
+    }
+  }
+}
+
+
+void Blackbox::timeout(void) {
+  if (reconfigure_wait)
+    real_reconfigure();
+
+  if (reread_menu_wait)
+    real_rereadMenu();
+
+  reconfigure_wait = reread_menu_wait = False;
+}
+
+
+void Blackbox::setFocusedWindow(BlackboxWindow *win) {
+  if (focused_window && focused_window == win) // nothing to do
+    return;
+
+  BScreen *old_screen = 0;
+
+  if (focused_window) {
+    focused_window->setFocusFlag(False);
+    old_screen = focused_window->getScreen();
+  }
+
+  if (win && ! win->isIconic()) {
+    // the active screen is the one with the last focused window...
+    // this will keep focus on this screen no matter where the mouse goes,
+    // so multihead keybindings will continue to work on that screen until the
+    // user focuses a window on a different screen.
+    active_screen = win->getScreen();
+    focused_window = win;
+  } else {
+    focused_window = 0;
+    if (! old_screen) {
+      if (active_screen) {
+        // set input focus to the toolbar of the screen with mouse
+        XSetInputFocus(getXDisplay(),
+                       active_screen->getToolbar()->getWindowID(),
+                       RevertToPointerRoot, CurrentTime);
+      } else {
+        // set input focus to the toolbar of the first managed screen
+        XSetInputFocus(getXDisplay(),
+                       screenList.front()->getToolbar()->getWindowID(),
+                       RevertToPointerRoot, CurrentTime);
+      }
+    } else {
+      // set input focus to the toolbar of the last screen
+      XSetInputFocus(getXDisplay(), old_screen->getToolbar()->getWindowID(),
+                     RevertToPointerRoot, CurrentTime);
+    }
+  }
+
+  if (active_screen && active_screen->isScreenManaged()) {
+    active_screen->getToolbar()->redrawWindowLabel(True);
+    active_screen->updateNetizenWindowFocus();
+  }
+
+  if (old_screen && old_screen != active_screen) {
+    old_screen->getToolbar()->redrawWindowLabel(True);
+    old_screen->updateNetizenWindowFocus();
+  }
+}
diff --git a/src/blackbox.hh b/src/blackbox.hh
new file mode 100644 (file)
index 0000000..b494039
--- /dev/null
@@ -0,0 +1,410 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// blackbox.hh for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
+// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef   __blackbox_hh
+#define   __blackbox_hh
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+
+#ifdef    HAVE_STDIO_H
+# include <stdio.h>
+#endif // HAVE_STDIO_H
+
+#ifdef    TIME_WITH_SYS_TIME
+#  include <sys/time.h>
+#  include <time.h>
+#else // !TIME_WITH_SYS_TIME
+#  ifdef    HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#  else // !HAVE_SYS_TIME_H
+#    include <time.h>
+#  endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+}
+
+#include <list>
+#include <map>
+#include <string>
+
+#include "i18n.hh"
+#include "BaseDisplay.hh"
+#include "Timer.hh"
+
+#define AttribShaded      (1l << 0)
+#define AttribMaxHoriz    (1l << 1)
+#define AttribMaxVert     (1l << 2)
+#define AttribOmnipresent (1l << 3)
+#define AttribWorkspace   (1l << 4)
+#define AttribStack       (1l << 5)
+#define AttribDecoration  (1l << 6)
+
+#define StackTop          (0)
+#define StackNormal       (1)
+#define StackBottom       (2)
+
+#define DecorNone         (0)
+#define DecorNormal       (1)
+#define DecorTiny         (2)
+#define DecorTool         (3)
+
+struct BlackboxHints {
+  unsigned long flags, attrib, workspace, stack, decoration;
+};
+
+struct BlackboxAttributes {
+  unsigned long flags, attrib, workspace, stack, decoration;
+  int premax_x, premax_y;
+  unsigned int premax_w, premax_h;
+};
+
+#define PropBlackboxHintsElements      (5)
+#define PropBlackboxAttributesElements (9)
+
+
+//forward declaration
+class BScreen;
+class Blackbox;
+class BlackboxWindow;
+class BWindowGroup;
+class Basemenu;
+class Toolbar;
+class Slit;
+
+extern I18n i18n;
+
+class Blackbox : public BaseDisplay, public TimeoutHandler {
+private:
+  struct BCursor {
+    Cursor session, move, ll_angle, lr_angle;
+  };
+  BCursor cursor;
+
+  struct MenuTimestamp {
+    std::string filename;
+    time_t timestamp;
+  };
+
+  struct BResource {
+    Time double_click_interval;
+
+    std::string menu_file, style_file;
+    int colors_per_channel;
+    timeval auto_raise_delay;
+    unsigned long cache_life, cache_max;
+  } resource;
+
+  typedef std::map<Window, BlackboxWindow*> WindowLookup;
+  typedef WindowLookup::value_type WindowLookupPair;
+  WindowLookup windowSearchList;
+
+  typedef std::map<Window, BWindowGroup*> GroupLookup;
+  typedef GroupLookup::value_type GroupLookupPair;
+  GroupLookup groupSearchList;
+
+  typedef std::map<Window, Basemenu*> MenuLookup;
+  typedef MenuLookup::value_type MenuLookupPair;
+  MenuLookup menuSearchList;
+
+  typedef std::map<Window, Toolbar*> ToolbarLookup;
+  typedef ToolbarLookup::value_type ToolbarLookupPair;
+  ToolbarLookup toolbarSearchList;
+
+  typedef std::map<Window, Slit*> SlitLookup;
+  typedef SlitLookup::value_type SlitLookupPair;
+  SlitLookup slitSearchList;
+
+  typedef std::list<MenuTimestamp*> MenuTimestampList;
+  MenuTimestampList menuTimestamps;
+
+  typedef std::list<BScreen*> ScreenList;
+  ScreenList screenList;
+
+  BScreen *active_screen;
+  BlackboxWindow *focused_window;
+  BTimer *timer;
+
+  bool no_focus, reconfigure_wait, reread_menu_wait;
+  Time last_time;
+  char **argv;
+  std::string rc_file;
+
+  Atom xa_wm_colormap_windows, xa_wm_protocols, xa_wm_state,
+    xa_wm_delete_window, xa_wm_take_focus, xa_wm_change_state,
+    motif_wm_hints;
+
+  // NETAttributes
+  Atom blackbox_attributes, blackbox_change_attributes, blackbox_hints;
+#ifdef    HAVE_GETPID
+  Atom blackbox_pid;
+#endif // HAVE_GETPID
+
+  // NETStructureMessages
+  Atom blackbox_structure_messages, blackbox_notify_startup,
+    blackbox_notify_window_add, blackbox_notify_window_del,
+    blackbox_notify_window_focus, blackbox_notify_current_workspace,
+    blackbox_notify_workspace_count, blackbox_notify_window_raise,
+    blackbox_notify_window_lower;
+
+  // message_types for client -> wm messages
+  Atom blackbox_change_workspace, blackbox_change_window_focus,
+    blackbox_cycle_window_focus;
+
+#ifdef    NEWWMSPEC
+  // root window properties
+  Atom net_supported, net_client_list, net_client_list_stacking,
+    net_number_of_desktops, net_desktop_geometry, net_desktop_viewport,
+    net_current_desktop, net_desktop_names, net_active_window, net_workarea,
+    net_supporting_wm_check, net_virtual_roots;
+
+  // root window messages
+  Atom net_close_window, net_wm_moveresize;
+
+  // application window properties
+  Atom net_properties, net_wm_name, net_wm_desktop, net_wm_window_type,
+    net_wm_state, net_wm_strut, net_wm_icon_geometry, net_wm_icon, net_wm_pid,
+    net_wm_handled_icons;
+
+  // application protocols
+  Atom net_wm_ping;
+#endif // NEWWMSPEC
+
+  Blackbox(const Blackbox&);
+  Blackbox& operator=(const Blackbox&);
+
+  void load_rc(void);
+  void save_rc(void);
+  void reload_rc(void);
+  void real_rereadMenu(void);
+  void real_reconfigure(void);
+
+  void init_icccm(void);
+
+  virtual void process_event(XEvent *);
+
+
+public:
+  Blackbox(char **m_argv, char *dpy_name = 0, char *rc = 0);
+  virtual ~Blackbox(void);
+
+  Basemenu *searchMenu(Window window);
+  BWindowGroup *searchGroup(Window window);
+  BlackboxWindow *searchWindow(Window window);
+  BScreen *searchScreen(Window window);
+  Toolbar *searchToolbar(Window);
+  Slit *searchSlit(Window);
+
+  void saveMenuSearch(Window window, Basemenu *data);
+  void saveWindowSearch(Window window, BlackboxWindow *data);
+  void saveGroupSearch(Window window, BWindowGroup *data);
+  void saveToolbarSearch(Window window, Toolbar *data);
+  void saveSlitSearch(Window window, Slit *data);
+  void removeMenuSearch(Window window);
+  void removeWindowSearch(Window window);
+  void removeGroupSearch(Window window);
+  void removeToolbarSearch(Window window);
+  void removeSlitSearch(Window window);
+
+  inline BlackboxWindow *getFocusedWindow(void) { return focused_window; }
+
+  inline const Time &getDoubleClickInterval(void) const
+  { return resource.double_click_interval; }
+  inline const Time &getLastTime(void) const { return last_time; }
+
+  inline const char *getStyleFilename(void) const
+    { return resource.style_file.c_str(); }
+  inline const char *getMenuFilename(void) const
+    { return resource.menu_file.c_str(); }
+
+  inline int getColorsPerChannel(void) const
+    { return resource.colors_per_channel; }
+
+  inline const timeval &getAutoRaiseDelay(void) const
+    { return resource.auto_raise_delay; }
+
+  inline unsigned long getCacheLife(void) const
+    { return resource.cache_life; }
+  inline unsigned long getCacheMax(void) const
+    { return resource.cache_max; }
+
+  inline void setNoFocus(bool f) { no_focus = f; }
+
+  inline Cursor getSessionCursor(void) const
+    { return cursor.session; }
+  inline Cursor getMoveCursor(void) const
+    { return cursor.move; }
+  inline Cursor getLowerLeftAngleCursor(void) const
+    { return cursor.ll_angle; }
+  inline Cursor getLowerRightAngleCursor(void) const
+    { return cursor.lr_angle; }
+
+  void setFocusedWindow(BlackboxWindow *w);
+  void shutdown(void);
+  void load_rc(BScreen *screen);
+  void saveStyleFilename(const std::string& filename);
+  void saveMenuFilename(const std::string& filename);
+  void restart(const char *prog = 0);
+  void reconfigure(void);
+  void rereadMenu(void);
+  void checkMenu(void);
+
+  bool validateWindow(Window window);
+
+  virtual bool handleSignal(int sig);
+
+  virtual void timeout(void);
+
+#ifndef   HAVE_STRFTIME
+  enum { B_AmericanDate = 1, B_EuropeanDate };
+#endif // HAVE_STRFTIME
+
+#ifdef    HAVE_GETPID
+  inline Atom getBlackboxPidAtom(void) const { return blackbox_pid; }
+#endif // HAVE_GETPID
+
+  inline Atom getWMChangeStateAtom(void) const
+    { return xa_wm_change_state; }
+  inline Atom getWMStateAtom(void) const
+    { return xa_wm_state; }
+  inline Atom getWMDeleteAtom(void) const
+    { return xa_wm_delete_window; }
+  inline Atom getWMProtocolsAtom(void) const
+    { return xa_wm_protocols; }
+  inline Atom getWMTakeFocusAtom(void) const
+    { return xa_wm_take_focus; }
+  inline Atom getWMColormapAtom(void) const
+    { return xa_wm_colormap_windows; }
+  inline Atom getMotifWMHintsAtom(void) const
+    { return motif_wm_hints; }
+
+  // this atom is for normal app->WM hints about decorations, stacking,
+  // starting workspace etc...
+  inline Atom getBlackboxHintsAtom(void) const
+    { return blackbox_hints;}
+
+  // these atoms are for normal app->WM interaction beyond the scope of the
+  // ICCCM...
+  inline Atom getBlackboxAttributesAtom(void) const
+    { return blackbox_attributes; }
+  inline Atom getBlackboxChangeAttributesAtom(void) const
+    { return blackbox_change_attributes; }
+
+  // these atoms are for window->WM interaction, with more control and
+  // information on window "structure"... common examples are
+  // notifying apps when windows are raised/lowered... when the user changes
+  // workspaces... i.e. "pager talk"
+  inline Atom getBlackboxStructureMessagesAtom(void) const
+    { return blackbox_structure_messages; }
+
+  // *Notify* portions of the NETStructureMessages protocol
+  inline Atom getBlackboxNotifyStartupAtom(void) const
+    { return blackbox_notify_startup; }
+  inline Atom getBlackboxNotifyWindowAddAtom(void) const
+    { return blackbox_notify_window_add; }
+  inline Atom getBlackboxNotifyWindowDelAtom(void) const
+    { return blackbox_notify_window_del; }
+  inline Atom getBlackboxNotifyWindowFocusAtom(void) const
+    { return blackbox_notify_window_focus; }
+  inline Atom getBlackboxNotifyCurrentWorkspaceAtom(void) const
+    { return blackbox_notify_current_workspace; }
+  inline Atom getBlackboxNotifyWorkspaceCountAtom(void) const
+    { return blackbox_notify_workspace_count; }
+  inline Atom getBlackboxNotifyWindowRaiseAtom(void) const
+    { return blackbox_notify_window_raise; }
+  inline Atom getBlackboxNotifyWindowLowerAtom(void) const
+    { return blackbox_notify_window_lower; }
+
+  // atoms to change that request changes to the desktop environment during
+  // runtime... these messages can be sent by any client... as the sending
+  // client window id is not included in the ClientMessage event...
+  inline Atom getBlackboxChangeWorkspaceAtom(void) const
+    { return blackbox_change_workspace; }
+  inline Atom getBlackboxChangeWindowFocusAtom(void) const
+    { return blackbox_change_window_focus; }
+  inline Atom getBlackboxCycleWindowFocusAtom(void) const
+    { return blackbox_cycle_window_focus; }
+
+#ifdef    NEWWMSPEC
+  // root window properties
+  inline Atom getNETSupportedAtom(void) const
+    { return net_supported; }
+  inline Atom getNETClientListAtom(void) const
+    { return net_client_list; }
+  inline Atom getNETClientListStackingAtom(void) const
+    { return net_client_list_stacking; }
+  inline Atom getNETNumberOfDesktopsAtom(void) const
+    { return net_number_of_desktops; }
+  inline Atom getNETDesktopGeometryAtom(void) const
+    { return net_desktop_geometry; }
+  inline Atom getNETDesktopViewportAtom(void) const
+    { return net_desktop_viewport; }
+  inline Atom getNETCurrentDesktopAtom(void) const
+    { return net_current_desktop; }
+  inline Atom getNETDesktopNamesAtom(void) const
+    { return net_desktop_names; }
+  inline Atom getNETActiveWindowAtom(void) const
+    { return net_active_window; }
+  inline Atom getNETWorkareaAtom(void) const
+    { return net_workarea; }
+  inline Atom getNETSupportingWMCheckAtom(void) const
+    { return net_supporting_wm_check; }
+  inline Atom getNETVirtualRootsAtom(void) const
+    { return net_virtual_roots; }
+
+  // root window messages
+  inline Atom getNETCloseWindowAtom(void) const
+    { return net_close_window; }
+  inline Atom getNETWMMoveResizeAtom(void) const
+    { return net_wm_moveresize; }
+
+  // application window properties
+  inline Atom getNETPropertiesAtom(void) const
+    { return net_properties; }
+  inline Atom getNETWMNameAtom(void) const
+    { return net_wm_name; }
+  inline Atom getNETWMDesktopAtom(void) const
+    { return net_wm_desktop; }
+  inline Atom getNETWMWindowTypeAtom(void) const
+    { return net_wm_window_type; }
+  inline Atom getNETWMStateAtom(void) const
+    { return net_wm_state; }
+  inline Atom getNETWMStrutAtom(void) const
+    { return net_wm_strut; }
+  inline Atom getNETWMIconGeometryAtom(void) const
+    { return net_wm_icon_geometry; }
+  inline Atom getNETWMIconAtom(void) const
+    { return net_wm_icon; }
+  inline Atom getNETWMPidAtom(void) const
+    { return net_wm_pid; }
+  inline Atom getNETWMHandledIconsAtom(void) const
+    { return net_wm_handled_icons; }
+
+  // application protocols
+  inline Atom getNETWMPingAtom(void) const
+    { return net_wm_ping; }
+#endif // NEWWMSPEC
+};
+
+
+#endif // __blackbox_hh
diff --git a/src/bsd-snprintf.c b/src/bsd-snprintf.c
deleted file mode 100644 (file)
index 4716ee2..0000000
+++ /dev/null
@@ -1,788 +0,0 @@
-/**************************************************************
- * Original:
- * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
- * A bombproof version of doprnt (dopr) included.
- * Sigh.  This sort of thing is always nasty do deal with.  Note that
- * the version here does not include floating point...
- *
- * snprintf() is used instead of sprintf() as it does limit checks
- * for string length.  This covers a nasty loophole.
- *
- * The other functions are there to prevent NULL pointers from
- * causing nast effects.
- *
- * More Recently:
- *  Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
- *  This was ugly.  It is still ugly.  I opted out of floating point
- *  numbers, but the formatter understands just about everything
- *  from the normal C string format, at least as far as I can tell from
- *  the Solaris 2.5 printf(3S) man page.
- *
- *  Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
- *    Ok, added some minimal floating point support, which means this
- *    probably requires libm on most operating systems.  Don't yet
- *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint()
- *    was pretty badly broken, it just wasn't being exercised in ways
- *    which showed it, so that's been fixed.  Also, formated the code
- *    to mutt conventions, and removed dead code left over from the
- *    original.  Also, there is now a builtin-test, just compile with:
- *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
- *    and run snprintf for results.
- * 
- *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
- *    The PGP code was using unsigned hexadecimal formats. 
- *    Unfortunately, unsigned formats simply didn't work.
- *
- *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
- *    The original code assumed that both snprintf() and vsnprintf() were
- *    missing.  Some systems only have snprintf() but not vsnprintf(), so
- *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
- *
- **************************************************************/
-
-#include "config.h"
-
-#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
-
-#include <string.h>
-# include <ctype.h>
-#include <sys/types.h>
-
-/* Define this as a fall through, HAVE_STDARG_H is probably already set */
-
-#define HAVE_VARARGS_H
-
-/* varargs declarations: */
-
-#if defined(HAVE_STDARG_H)
-# include <stdarg.h>
-# define HAVE_STDARGS    /* let's hope that works everywhere (mj) */
-# define VA_LOCAL_DECL   va_list ap
-# define VA_START(f)     va_start(ap, f)
-# define VA_SHIFT(v,t)  ;   /* no-op for ANSI */
-# define VA_END          va_end(ap)
-#else
-# if defined(HAVE_VARARGS_H)
-#  include <varargs.h>
-#  undef HAVE_STDARGS
-#  define VA_LOCAL_DECL   va_list ap
-#  define VA_START(f)     va_start(ap)      /* f is ignored! */
-#  define VA_SHIFT(v,t) v = va_arg(ap,t)
-#  define VA_END        va_end(ap)
-# else
-/*XX ** NO VARARGS ** XX*/
-# endif
-#endif
-
-/*int snprintf (char *str, size_t count, const char *fmt, ...);*/
-/*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/
-
-static void dopr (char *buffer, size_t maxlen, const char *format, 
-                  va_list args);
-static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
-                   char *value, int flags, int min, int max);
-static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
-                   long value, int base, int min, int max, int flags);
-static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
-                  long double fvalue, int min, int max, int flags);
-static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
-
-/*
- * dopr(): poor man's version of doprintf
- */
-
-/* format read states */
-#define DP_S_DEFAULT 0
-#define DP_S_FLAGS   1
-#define DP_S_MIN     2
-#define DP_S_DOT     3
-#define DP_S_MAX     4
-#define DP_S_MOD     5
-#define DP_S_CONV    6
-#define DP_S_DONE    7
-
-/* format flags - Bits */
-#define DP_F_MINUS     (1 << 0)
-#define DP_F_PLUS      (1 << 1)
-#define DP_F_SPACE     (1 << 2)
-#define DP_F_NUM       (1 << 3)
-#define DP_F_ZERO      (1 << 4)
-#define DP_F_UP        (1 << 5)
-#define DP_F_UNSIGNED  (1 << 6)
-
-/* Conversion Flags */
-#define DP_C_SHORT   1
-#define DP_C_LONG    2
-#define DP_C_LDOUBLE 3
-
-#define char_to_int(p) (p - '0')
-#define MAX(p,q) ((p >= q) ? p : q)
-
-static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
-{
-  char ch;
-  long value;
-  long double fvalue;
-  char *strvalue;
-  int min;
-  int max;
-  int state;
-  int flags;
-  int cflags;
-  size_t currlen;
-  
-  state = DP_S_DEFAULT;
-  currlen = flags = cflags = min = 0;
-  max = -1;
-  ch = *format++;
-
-  while (state != DP_S_DONE)
-  {
-    if ((ch == '\0') || (currlen >= maxlen)) 
-      state = DP_S_DONE;
-
-    switch(state) 
-    {
-    case DP_S_DEFAULT:
-      if (ch == '%') 
-       state = DP_S_FLAGS;
-      else 
-       dopr_outch (buffer, &currlen, maxlen, ch);
-      ch = *format++;
-      break;
-    case DP_S_FLAGS:
-      switch (ch) 
-      {
-      case '-':
-       flags |= DP_F_MINUS;
-        ch = *format++;
-       break;
-      case '+':
-       flags |= DP_F_PLUS;
-        ch = *format++;
-       break;
-      case ' ':
-       flags |= DP_F_SPACE;
-        ch = *format++;
-       break;
-      case '#':
-       flags |= DP_F_NUM;
-        ch = *format++;
-       break;
-      case '0':
-       flags |= DP_F_ZERO;
-        ch = *format++;
-       break;
-      default:
-       state = DP_S_MIN;
-       break;
-      }
-      break;
-    case DP_S_MIN:
-      if (isdigit((unsigned char)ch)) 
-      {
-       min = 10*min + char_to_int (ch);
-       ch = *format++;
-      } 
-      else if (ch == '*') 
-      {
-       min = va_arg (args, int);
-       ch = *format++;
-       state = DP_S_DOT;
-      } 
-      else 
-       state = DP_S_DOT;
-      break;
-    case DP_S_DOT:
-      if (ch == '.') 
-      {
-       state = DP_S_MAX;
-       ch = *format++;
-      } 
-      else 
-       state = DP_S_MOD;
-      break;
-    case DP_S_MAX:
-      if (isdigit((unsigned char)ch)) 
-      {
-       if (max < 0)
-         max = 0;
-       max = 10*max + char_to_int (ch);
-       ch = *format++;
-      } 
-      else if (ch == '*') 
-      {
-       max = va_arg (args, int);
-       ch = *format++;
-       state = DP_S_MOD;
-      } 
-      else 
-       state = DP_S_MOD;
-      break;
-    case DP_S_MOD:
-      /* Currently, we don't support Long Long, bummer */
-      switch (ch) 
-      {
-      case 'h':
-       cflags = DP_C_SHORT;
-       ch = *format++;
-       break;
-      case 'l':
-       cflags = DP_C_LONG;
-       ch = *format++;
-       break;
-      case 'L':
-       cflags = DP_C_LDOUBLE;
-       ch = *format++;
-       break;
-      default:
-       break;
-      }
-      state = DP_S_CONV;
-      break;
-    case DP_S_CONV:
-      switch (ch) 
-      {
-      case 'd':
-      case 'i':
-       if (cflags == DP_C_SHORT) 
-         value = va_arg (args, short int);
-       else if (cflags == DP_C_LONG)
-         value = va_arg (args, long int);
-       else
-         value = va_arg (args, int);
-       fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
-       break;
-      case 'o':
-       flags |= DP_F_UNSIGNED;
-       if (cflags == DP_C_SHORT)
-         value = va_arg (args, unsigned short int);
-       else if (cflags == DP_C_LONG)
-         value = va_arg (args, unsigned long int);
-       else
-         value = va_arg (args, unsigned int);
-       fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
-       break;
-      case 'u':
-       flags |= DP_F_UNSIGNED;
-       if (cflags == DP_C_SHORT)
-         value = va_arg (args, unsigned short int);
-       else if (cflags == DP_C_LONG)
-         value = va_arg (args, unsigned long int);
-       else
-         value = va_arg (args, unsigned int);
-       fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
-       break;
-      case 'X':
-       flags |= DP_F_UP;
-      case 'x':
-       flags |= DP_F_UNSIGNED;
-       if (cflags == DP_C_SHORT)
-         value = va_arg (args, unsigned short int);
-       else if (cflags == DP_C_LONG)
-         value = va_arg (args, unsigned long int);
-       else
-         value = va_arg (args, unsigned int);
-       fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
-       break;
-      case 'f':
-       if (cflags == DP_C_LDOUBLE)
-         fvalue = va_arg (args, long double);
-       else
-         fvalue = va_arg (args, double);
-       /* um, floating point? */
-       fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
-       break;
-      case 'E':
-       flags |= DP_F_UP;
-      case 'e':
-       if (cflags == DP_C_LDOUBLE)
-         fvalue = va_arg (args, long double);
-       else
-         fvalue = va_arg (args, double);
-       break;
-      case 'G':
-       flags |= DP_F_UP;
-      case 'g':
-       if (cflags == DP_C_LDOUBLE)
-         fvalue = va_arg (args, long double);
-       else
-         fvalue = va_arg (args, double);
-       break;
-      case 'c':
-       dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
-       break;
-      case 's':
-       strvalue = va_arg (args, char *);
-       if (max < 0) 
-         max = maxlen; /* ie, no max */
-       fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
-       break;
-      case 'p':
-       strvalue = va_arg (args, void *);
-       fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
-       break;
-      case 'n':
-       if (cflags == DP_C_SHORT) 
-       {
-         short int *num;
-         num = va_arg (args, short int *);
-         *num = currlen;
-        } 
-       else if (cflags == DP_C_LONG) 
-       {
-         long int *num;
-         num = va_arg (args, long int *);
-         *num = currlen;
-        } 
-       else 
-       {
-         int *num;
-         num = va_arg (args, int *);
-         *num = currlen;
-        }
-       break;
-      case '%':
-       dopr_outch (buffer, &currlen, maxlen, ch);
-       break;
-      case 'w':
-       /* not supported yet, treat as next char */
-       ch = *format++;
-       break;
-      default:
-       /* Unknown, skip */
-       break;
-      }
-      ch = *format++;
-      state = DP_S_DEFAULT;
-      flags = cflags = min = 0;
-      max = -1;
-      break;
-    case DP_S_DONE:
-      break;
-    default:
-      /* hmm? */
-      break; /* some picky compilers need this */
-    }
-  }
-  if (currlen < maxlen - 1) 
-    buffer[currlen] = '\0';
-  else 
-    buffer[maxlen - 1] = '\0';
-}
-
-static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
-                   char *value, int flags, int min, int max)
-{
-  int padlen, strln;     /* amount to pad */
-  int cnt = 0;
-  
-  if (value == 0)
-  {
-    value = "<NULL>";
-  }
-
-  for (strln = 0; value[strln]; ++strln); /* strlen */
-  padlen = min - strln;
-  if (padlen < 0) 
-    padlen = 0;
-  if (flags & DP_F_MINUS) 
-    padlen = -padlen; /* Left Justify */
-
-  while ((padlen > 0) && (cnt < max)) 
-  {
-    dopr_outch (buffer, currlen, maxlen, ' ');
-    --padlen;
-    ++cnt;
-  }
-  while (*value && (cnt < max)) 
-  {
-    dopr_outch (buffer, currlen, maxlen, *value++);
-    ++cnt;
-  }
-  while ((padlen < 0) && (cnt < max)) 
-  {
-    dopr_outch (buffer, currlen, maxlen, ' ');
-    ++padlen;
-    ++cnt;
-  }
-}
-
-/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
-
-static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
-                   long value, int base, int min, int max, int flags)
-{
-  int signvalue = 0;
-  unsigned long uvalue;
-  char convert[20];
-  int place = 0;
-  int spadlen = 0; /* amount to space pad */
-  int zpadlen = 0; /* amount to zero pad */
-  int caps = 0;
-  
-  if (max < 0)
-    max = 0;
-
-  uvalue = value;
-
-  if(!(flags & DP_F_UNSIGNED))
-  {
-    if( value < 0 ) {
-      signvalue = '-';
-      uvalue = -value;
-    }
-    else
-      if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
-       signvalue = '+';
-    else
-      if (flags & DP_F_SPACE)
-       signvalue = ' ';
-  }
-  
-  if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
-
-  do {
-    convert[place++] =
-      (caps? "0123456789ABCDEF":"0123456789abcdef")
-      [uvalue % (unsigned)base  ];
-    uvalue = (uvalue / (unsigned)base );
-  } while(uvalue && (place < 20));
-  if (place == 20) place--;
-  convert[place] = 0;
-
-  zpadlen = max - place;
-  spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
-  if (zpadlen < 0) zpadlen = 0;
-  if (spadlen < 0) spadlen = 0;
-  if (flags & DP_F_ZERO)
-  {
-    zpadlen = MAX(zpadlen, spadlen);
-    spadlen = 0;
-  }
-  if (flags & DP_F_MINUS) 
-    spadlen = -spadlen; /* Left Justifty */
-
-#ifdef DEBUG_SNPRINTF
-  dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
-      zpadlen, spadlen, min, max, place));
-#endif
-
-  /* Spaces */
-  while (spadlen > 0) 
-  {
-    dopr_outch (buffer, currlen, maxlen, ' ');
-    --spadlen;
-  }
-
-  /* Sign */
-  if (signvalue) 
-    dopr_outch (buffer, currlen, maxlen, signvalue);
-
-  /* Zeros */
-  if (zpadlen > 0) 
-  {
-    while (zpadlen > 0)
-    {
-      dopr_outch (buffer, currlen, maxlen, '0');
-      --zpadlen;
-    }
-  }
-
-  /* Digits */
-  while (place > 0) 
-    dopr_outch (buffer, currlen, maxlen, convert[--place]);
-  
-  /* Left Justified spaces */
-  while (spadlen < 0) {
-    dopr_outch (buffer, currlen, maxlen, ' ');
-    ++spadlen;
-  }
-}
-
-static long double abs_val (long double value)
-{
-  long double result = value;
-
-  if (value < 0)
-    result = -value;
-
-  return result;
-}
-
-static long double pow10 (int exp)
-{
-  long double result = 1;
-
-  while (exp)
-  {
-    result *= 10;
-    exp--;
-  }
-  
-  return result;
-}
-
-static long round (long double value)
-{
-  long intpart;
-
-  intpart = value;
-  value = value - intpart;
-  if (value >= 0.5)
-    intpart++;
-
-  return intpart;
-}
-
-static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
-                  long double fvalue, int min, int max, int flags)
-{
-  int signvalue = 0;
-  long double ufvalue;
-  char iconvert[20];
-  char fconvert[20];
-  int iplace = 0;
-  int fplace = 0;
-  int padlen = 0; /* amount to pad */
-  int zpadlen = 0; 
-  int caps = 0;
-  long intpart;
-  long fracpart;
-  
-  /* 
-   * AIX manpage says the default is 0, but Solaris says the default
-   * is 6, and sprintf on AIX defaults to 6
-   */
-  if (max < 0)
-    max = 6;
-
-  ufvalue = abs_val (fvalue);
-
-  if (fvalue < 0)
-    signvalue = '-';
-  else
-    if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
-      signvalue = '+';
-    else
-      if (flags & DP_F_SPACE)
-       signvalue = ' ';
-
-#if 0
-  if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
-#endif
-
-  intpart = ufvalue;
-
-  /* 
-   * Sorry, we only support 9 digits past the decimal because of our 
-   * conversion method
-   */
-  if (max > 9)
-    max = 9;
-
-  /* We "cheat" by converting the fractional part to integer by
-   * multiplying by a factor of 10
-   */
-  fracpart = round ((pow10 (max)) * (ufvalue - intpart));
-
-  if (fracpart >= pow10 (max))
-  {
-    intpart++;
-    fracpart -= pow10 (max);
-  }
-
-#ifdef DEBUG_SNPRINTF
-  dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
-#endif
-
-  /* Convert integer part */
-  do {
-    iconvert[iplace++] =
-      (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
-    intpart = (intpart / 10);
-  } while(intpart && (iplace < 20));
-  if (iplace == 20) iplace--;
-  iconvert[iplace] = 0;
-
-  /* Convert fractional part */
-  do {
-    fconvert[fplace++] =
-      (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
-    fracpart = (fracpart / 10);
-  } while(fracpart && (fplace < 20));
-  if (fplace == 20) fplace--;
-  fconvert[fplace] = 0;
-
-  /* -1 for decimal point, another -1 if we are printing a sign */
-  padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 
-  zpadlen = max - fplace;
-  if (zpadlen < 0)
-    zpadlen = 0;
-  if (padlen < 0) 
-    padlen = 0;
-  if (flags & DP_F_MINUS) 
-    padlen = -padlen; /* Left Justifty */
-
-  if ((flags & DP_F_ZERO) && (padlen > 0)) 
-  {
-    if (signvalue) 
-    {
-      dopr_outch (buffer, currlen, maxlen, signvalue);
-      --padlen;
-      signvalue = 0;
-    }
-    while (padlen > 0)
-    {
-      dopr_outch (buffer, currlen, maxlen, '0');
-      --padlen;
-    }
-  }
-  while (padlen > 0)
-  {
-    dopr_outch (buffer, currlen, maxlen, ' ');
-    --padlen;
-  }
-  if (signvalue) 
-    dopr_outch (buffer, currlen, maxlen, signvalue);
-
-  while (iplace > 0) 
-    dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
-
-  /*
-   * Decimal point.  This should probably use locale to find the correct
-   * char to print out.
-   */
-  dopr_outch (buffer, currlen, maxlen, '.');
-
-  while (fplace > 0) 
-    dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
-
-  while (zpadlen > 0)
-  {
-    dopr_outch (buffer, currlen, maxlen, '0');
-    --zpadlen;
-  }
-
-  while (padlen < 0) 
-  {
-    dopr_outch (buffer, currlen, maxlen, ' ');
-    ++padlen;
-  }
-}
-
-static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
-{
-  if (*currlen < maxlen)
-    buffer[(*currlen)++] = c;
-}
-#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
-
-#ifndef HAVE_VSNPRINTF
-int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
-{
-  str[0] = 0;
-  dopr(str, count, fmt, args);
-  return(strlen(str));
-}
-#endif /* !HAVE_VSNPRINTF */
-
-#ifndef HAVE_SNPRINTF
-/* VARARGS3 */
-#ifdef HAVE_STDARGS
-int snprintf (char *str,size_t count,const char *fmt,...)
-#else
-int snprintf (va_alist) va_dcl
-#endif
-{
-#ifndef HAVE_STDARGS
-  char *str;
-  size_t count;
-  char *fmt;
-#endif
-  VA_LOCAL_DECL;
-    
-  VA_START (fmt);
-  VA_SHIFT (str, char *);
-  VA_SHIFT (count, size_t );
-  VA_SHIFT (fmt, char *);
-  (void) vsnprintf(str, count, fmt, ap);
-  VA_END;
-  return(strlen(str));
-}
-
-#ifdef TEST_SNPRINTF
-#ifndef LONG_STRING
-#define LONG_STRING 1024
-#endif
-int main (void)
-{
-  char buf1[LONG_STRING];
-  char buf2[LONG_STRING];
-  char *fp_fmt[] = {
-    "%-1.5f",
-    "%1.5f",
-    "%123.9f",
-    "%10.5f",
-    "% 10.5f",
-    "%+22.9f",
-    "%+4.9f",
-    "%01.3f",
-    "%4f",
-    "%3.1f",
-    "%3.2f",
-    NULL
-  };
-  double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 
-    0.9996, 1.996, 4.136, 0};
-  char *int_fmt[] = {
-    "%-1.5d",
-    "%1.5d",
-    "%123.9d",
-    "%5.5d",
-    "%10.5d",
-    "% 10.5d",
-    "%+22.33d",
-    "%01.3d",
-    "%4d",
-    NULL
-  };
-  long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
-  int x, y;
-  int fail = 0;
-  int num = 0;
-
-  printf ("Testing snprintf format codes against system sprintf...\n");
-
-  for (x = 0; fp_fmt[x] != NULL ; x++)
-    for (y = 0; fp_nums[y] != 0 ; y++)
-    {
-      snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
-      sprintf (buf2, fp_fmt[x], fp_nums[y]);
-      if (strcmp (buf1, buf2))
-      {
-       printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n", 
-           fp_fmt[x], buf1, buf2);
-       fail++;
-      }
-      num++;
-    }
-
-  for (x = 0; int_fmt[x] != NULL ; x++)
-    for (y = 0; int_nums[y] != 0 ; y++)
-    {
-      snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
-      sprintf (buf2, int_fmt[x], int_nums[y]);
-      if (strcmp (buf1, buf2))
-      {
-       printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n", 
-           int_fmt[x], buf1, buf2);
-       fail++;
-      }
-      num++;
-    }
-  printf ("%d tests failed out of %d.\n", fail, num);
-}
-#endif /* SNPRINTF_TEST */
-
-#endif /* !HAVE_SNPRINTF */
diff --git a/src/bsd-snprintf.h b/src/bsd-snprintf.h
deleted file mode 100644 (file)
index ed7a21c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _BSD_SNPRINTF_H
-#define _BSD_SNPRINTF_H
-
-#include "config.h"
-
-#include <sys/types.h> /* For size_t */
-
-#ifndef HAVE_SNPRINTF
-int snprintf(char *str, size_t count, const char *fmt, ...);
-#endif /* !HAVE_SNPRINTF */
-
-#ifndef HAVE_VSNPRINTF
-int vsnprintf(char *str, size_t count, const char *fmt, va_list args);
-#endif /* !HAVE_SNPRINTF */
-
-
-#endif /* _BSD_SNPRINTF_H */
index 718ee4e733474e5b6f43839214042afbeb3a899f..0eb0a9116f069bd2a13e325af74c9f6aebc51db4 100644 (file)
@@ -1,5 +1,5 @@
 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-// i18n.cc for Openbox
+// i18n.cc for Blackbox - an X11 Window manager
 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
@@ -46,11 +46,17 @@ extern "C" {
 }
 
 #include <string>
+using std::string;
 
-#include "i18n.h"
+#include "i18n.hh"
 
-I18n::I18n(const char *catalog) {
-  mb = false;
+
+// the rest of bb source uses True and False from X, so we continue that
+#define True true
+#define False false
+
+I18n::I18n(void) {
+  mb = False;
 #ifdef    HAVE_SETLOCALE
   locale = setlocale(LC_ALL, "");
   if (! locale) {
@@ -61,7 +67,7 @@ I18n::I18n(const char *catalog) {
   } else {
     // MB_CUR_MAX returns the size of a char in the current locale
     if (MB_CUR_MAX > 1)
-      mb = true;
+      mb = True;
     // truncate any encoding off the end of the locale
     char *l = strchr(locale, '@');
     if (l) *l = '\0';
@@ -73,12 +79,10 @@ I18n::I18n(const char *catalog) {
   catalog_fd = (nl_catd) -1;
 #endif
 #endif // HAVE_SETLOCALE
-  if (catalog)
-    openCatalog(catalog);
 }
 
 
-I18n::~I18n() {
+I18n::~I18n(void) {
 #if defined(NLS) && defined(HAVE_CATCLOSE)
   if (catalog_fd != (nl_catd) -1)
     catclose(catalog_fd);
@@ -86,9 +90,9 @@ I18n::~I18n() {
 }
 
 
-#if defined(NLS) && defined(HAVE_CATOPEN)
 void I18n::openCatalog(const char *catalog) {
-  std::string catalog_filename = LOCALEPATH;
+#if defined(NLS) && defined(HAVE_CATOPEN)
+  string catalog_filename = LOCALEPATH;
   catalog_filename += '/';
   catalog_filename += locale;
   catalog_filename += '/';
@@ -102,21 +106,14 @@ void I18n::openCatalog(const char *catalog) {
 
   if (catalog_fd == (nl_catd) -1)
     fprintf(stderr, "failed to open catalog, using default messages\n");
-}
-#else
-void I18n::openCatalog(const char *) {
-}
 #endif // HAVE_CATOPEN
+}
 
-#if   defined(NLS) && defined(HAVE_CATGETS)
 const char* I18n::operator()(int set, int msg, const char *msgString) const {
+#if   defined(NLS) && defined(HAVE_CATGETS)
   if (catalog_fd != (nl_catd) -1)
     return catgets(catalog_fd, set, msg, msgString);
   else
+#endif
     return msgString;
 }
-#else
-const char* I18n::operator()(int, int, const char *msgString) const {
-  return msgString;
-}
-#endif
similarity index 92%
rename from src/i18n.h
rename to src/i18n.hh
index d8d29a4a080533dba2b1a911ebd8fdf6ea6ad9f7..b86d9d80702afeac3867c9a5be7a6bf037171a39 100644 (file)
@@ -1,5 +1,5 @@
 // -*- mode: C++; indent-tabs-mode: nil; -*-
-// i18n.hh for Openbox
+// i18n.hh for Blackbox - an X11 Window manager
 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
@@ -27,7 +27,7 @@
 // always include this just for the #defines
 // this keeps the calls to i18n->getMessage clean, otherwise we have to
 // add ifdefs to every call to getMessage
-#include "../nls/openbox-nls.h"
+#include "../nls/blackbox-nls.hh"
 
 extern "C" {
 #ifdef    HAVE_LOCALE_H
@@ -49,8 +49,8 @@ private:
 #endif
 
 public:
-  I18n(const char *catalog = 0);
-  ~I18n();
+  I18n(void);
+  ~I18n(void);
 
   inline bool multibyte(void) const { return mb; }
 
@@ -58,6 +58,6 @@ public:
   void openCatalog(const char *catalog);
 };
 
-extern I18n i18n;       // located in main.cc
+extern I18n i18n;
 
 #endif // __i18n_h
index 5cf68b421bb74eef3e77894ba8eb8b110e177395..a0edb83f7f70beb1469d684f60e961312ef524a6 100644 (file)
@@ -1,5 +1,6 @@
-// main.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
+// -*- mode: C++; indent-tabs-mode: nil; -*-
+// main.cc for Blackbox - an X11 Window manager
+// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
 #include "../version.h"
 
 #ifdef    HAVE_CONFIG_H
 #  include "../config.h"
 #endif // HAVE_CONFIG_H
 
+extern "C" {
 #ifdef    HAVE_STDIO_H
 #  include <stdio.h>
 #endif // HAVE_STDIO_H
 
-#ifdef    HAVE_STDLIB_H
+#ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif // HAVE_STDLIB_H
 
-#ifdef    HAVE_STRING_H
+#ifdef HAVE_STRING_H
 #  include <string.h>
 #endif // HAVE_STRING_H
 
 #ifdef    HAVE_SYS_PARAM_H
 #  include <sys/param.h>
 #endif // HAVE_SYS_PARAM_H
+}
 
-#ifndef   MAXPATHLEN
-#define   MAXPATHLEN 255
-#endif // MAXPATHLEN
+#include <string>
+using std::string;
 
-#include "openbox.h"
-#include "i18n.h"
+#include "i18n.hh"
+#include "blackbox.hh"
 
-I18n i18n("openbox.cat");
+
+I18n i18n; // initialized in main
 
 static void showHelp(int exitval) {
   // print program usage and command line options
   printf(i18n(mainSet, mainUsage,
-              "Openbox %s : (c) 2002 - 2002 Ben Jansens\n"
-              "\t\t\t  2001 - 2002 Sean 'Shaleh' Perry\n\n"
-              "\t\t\t  1997 - 2000 Brad Hughes\n\n"
+              "Blackbox %s : (c) 2001 - 2002 Sean 'Shaleh' Perry\n"
+              "\t\t\t  1997 - 2000, 2002 Brad Hughes\n\n"
               "  -display <string>\t\tuse display connection.\n"
               "  -rc <string>\t\t\tuse alternate resource file.\n"
-              "  -menu <string>\t\t\tuse alternate menu file.\n"
               "  -version\t\t\tdisplay version and exit.\n"
               "  -help\t\t\t\tdisplay this help text and exit.\n\n"),
-         __openbox_version);
+         __blackbox_version);
 
   // some people have requested that we print out compile options
   // as well
-  fprintf(stdout,i18n(mainSet, mainCompileOptions,
-                      "Compile time options:\n"
-                      "  Debugging:\t\t\t%s\n"
-                      "  Interlacing:\t\t\t%s\n"
-                      "  Shape:\t\t\t%s\n"
-                      "  Slit:\t\t\t\t%s\n"
-                      "  8bpp Ordered Dithering:\t%s\n"
-                      "  Event Clobbering:\t\t%s\n\n"),
+  printf(i18n(mainSet, mainCompileOptions,
+              "Compile time options:\n"
+              "  Debugging:\t\t\t%s\n"
+              "  Shape:\t\t\t%s\n"
+              "  8bpp Ordered Dithering:\t%s\n\n"),
 #ifdef    DEBUG
-          i18n(CommonSet, CommonYes, "yes"),
+         i18n(CommonSet, CommonYes, "yes"),
 #else // !DEBUG
-          i18n(CommonSet, CommonNo, "no"),
+         i18n(CommonSet, CommonNo, "no"),
 #endif // DEBUG
 
-#ifdef    INTERLACE
-          i18n(CommonSet, CommonYes, "yes"),
-#else // !INTERLACE
-          i18n(CommonSet, CommonNo, "no"),
-#endif // INTERLACE
-
 #ifdef    SHAPE
-          i18n(CommonSet, CommonYes, "yes"),
+         i18n(CommonSet, CommonYes, "yes"),
 #else // !SHAPE
-          i18n(CommonSet, CommonNo, "no"),
+         i18n(CommonSet, CommonNo, "no"),
 #endif // SHAPE
 
-#ifdef    SLIT
-          i18n(CommonSet, CommonYes, "yes"),
-#else // !SLIT
-          i18n(CommonSet, CommonNo, "no"),
-#endif // SLIT
-
 #ifdef    ORDEREDPSEUDO
-          i18n(CommonSet, CommonYes, "yes"),
+         i18n(CommonSet, CommonYes, "yes")
 #else // !ORDEREDPSEUDO
-          i18n(CommonSet, CommonNo, "no"),
+         i18n(CommonSet, CommonNo, "no")
 #endif // ORDEREDPSEUDO
+          );
 
-#ifndef   NOCLOBBER
-          i18n(CommonSet, CommonYes, "yes")
-#else // !NOCLOBBER
-            i18n(CommonSet, CommonNo, "no")
-#endif // NOCLOBBER
-            );
-
-          ::exit(exitval);
+  ::exit(exitval);
 }
 
 int main(int argc, char **argv) {
   char *session_display = (char *) 0;
   char *rc_file = (char *) 0;
-  char *menu_file = (char *) 0;
+
+  i18n.openCatalog("blackbox.cat");
 
   for (int i = 1; i < argc; ++i) {
     if (! strcmp(argv[i], "-rc")) {
@@ -136,24 +111,12 @@ int main(int argc, char **argv) {
       if ((++i) >= argc) {
         fprintf(stderr,
                 i18n(mainSet, mainRCRequiresArg,
-                     "error: '-rc' requires and argument\n"));
+                                 "error: '-rc' requires and argument\n"));
 
         ::exit(1);
       }
 
       rc_file = argv[i];
-    } else if (! strcmp(argv[i], "-menu")) {
-      // look for alternative menu file to use
-
-      if ((++i) >= argc) {
-        fprintf(stderr,
-                i18n(mainSet, mainMENURequiresArg,
-                     "error: '-menu' requires and argument\n"));
-
-        ::exit(1);
-      }
-
-      menu_file = argv[i];
     } else if (! strcmp(argv[i], "-display")) {
       // check for -display option... to run on a display other than the one
       // set by the environment variable DISPLAY
@@ -161,27 +124,25 @@ int main(int argc, char **argv) {
       if ((++i) >= argc) {
         fprintf(stderr,
                 i18n(mainSet, mainDISPLAYRequiresArg,
-                     "error: '-display' requires an argument\n"));
+                                 "error: '-display' requires an argument\n"));
 
         ::exit(1);
       }
 
       session_display = argv[i];
-      char dtmp[MAXPATHLEN];
-      sprintf(dtmp, "DISPLAY=%s", session_display);
+      string dtmp = "DISPLAY=";
+      dtmp += session_display;
 
-      if (putenv(dtmp)) {
-        fprintf(stderr,
-                i18n(mainSet, mainWarnDisplaySet,
-                     "warning: couldn't set environment variable 'DISPLAY'\n"));
+      if (putenv(const_cast<char*>(dtmp.c_str()))) {
+        fprintf(stderr, i18n(mainSet, mainWarnDisplaySet,
+                "warning: couldn't set environment variable 'DISPLAY'\n"));
         perror("putenv()");
       }
     } else if (! strcmp(argv[i], "-version")) {
       // print current version string
-      printf("Openbox %s : (c) 2002 - 2002 Ben Jansens\n"
-             "\t\t    2001 - 2002 Sean 'Shaleh' Perry\n"
-             "\t\t    1997 - 2000 Brad Hughes\n",
-             __openbox_version);
+      printf("Blackbox %s : (c) 2001 - 2002 Sean 'Shaleh' Perry\n",
+             "\t\t\t   1997 - 2000 Brad Hughes\n"
+             __blackbox_version);
 
       ::exit(0);
     } else if (! strcmp(argv[i], "-help")) {
@@ -195,8 +156,8 @@ int main(int argc, char **argv) {
   _chdir2(getenv("X11ROOT"));
 #endif // __EMX__
 
-  Openbox openbox(argc, argv, session_display, rc_file, menu_file);
-  openbox.eventLoop();
+  Blackbox blackbox(argv, session_display, rc_file);
+  blackbox.eventLoop();
 
   return(0);
 }
diff --git a/src/openbox.cc b/src/openbox.cc
deleted file mode 100644 (file)
index 6df793a..0000000
+++ /dev/null
@@ -1,1109 +0,0 @@
-// openbox.cc for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-// stupid macros needed to access some functions in version 2 of the GNU C
-// library
-#ifndef   _GNU_SOURCE
-#define   _GNU_SOURCE
-#endif // _GNU_SOURCE
-
-#ifdef    HAVE_CONFIG_H
-#  include "../config.h"
-#endif // HAVE_CONFIG_H
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xresource.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-
-#ifdef    SHAPE
-#include <X11/extensions/shape.h>
-#endif // SHAPE
-
-#include "i18n.h"
-#include "openbox.h"
-#include "Basemenu.h"
-#include "Clientmenu.h"
-#include "Rootmenu.h"
-#include "Screen.h"
-
-#ifdef    SLIT
-#include "Slit.h"
-#endif // SLIT
-
-#include "Toolbar.h"
-#include "Window.h"
-#include "Workspace.h"
-#include "Workspacemenu.h"
-#include "Util.h"
-
-#include <string>
-#include <algorithm>
-
-#ifdef    HAVE_STDIO_H
-#  include <stdio.h>
-#endif // HAVE_STDIO_H
-
-#ifdef    HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif // HAVE_STDLIB_H
-
-#ifdef    HAVE_STRING_H
-#  include <string.h>
-#endif // HAVE_STRING_H
-
-#ifdef    HAVE_UNISTD_H
-#  include <sys/types.h>
-#  include <unistd.h>
-#endif // HAVE_UNISTD_H
-
-#ifdef    HAVE_SYS_PARAM_H
-#  include <sys/param.h>
-#endif // HAVE_SYS_PARAM_H
-
-#ifndef   MAXPATHLEN
-#define   MAXPATHLEN 255
-#endif // MAXPATHLEN
-
-#ifdef    HAVE_SYS_SELECT_H
-#  include <sys/select.h>
-#endif // HAVE_SYS_SELECT_H
-
-#ifdef    HAVE_SIGNAL_H
-#  include <signal.h>
-#endif // HAVE_SIGNAL_H
-
-#ifdef    HAVE_SYS_SIGNAL_H
-#  include <sys/signal.h>
-#endif // HAVE_SYS_SIGNAL_H
-
-#ifdef    HAVE_SYS_STAT_H
-#  include <sys/types.h>
-#  include <sys/stat.h>
-#endif // HAVE_SYS_STAT_H
-
-#ifdef    TIME_WITH_SYS_TIME
-#  include <sys/time.h>
-#  include <time.h>
-#else // !TIME_WITH_SYS_TIME
-#  ifdef    HAVE_SYS_TIME_H
-#    include <sys/time.h>
-#  else // !HAVE_SYS_TIME_H
-#    include <time.h>
-#  endif // HAVE_SYS_TIME_H
-#endif // TIME_WITH_SYS_TIME
-
-#ifdef    HAVE_LIBGEN_H
-#  include <libgen.h>
-#endif // HAVE_LIBGEN_H
-
-#ifndef   HAVE_BASENAME
-static inline char *basename (char *s) {
-  char *save = s;
-
-  while (*s) if (*s++ == '/') save = s;
-
-  return save;
-}
-#endif // HAVE_BASENAME
-
-
-// X event scanner for enter/leave notifies - adapted from twm
-typedef struct scanargs {
-  Window w;
-  Bool leave, inferior, enter;
-} scanargs;
-
-static Bool queueScanner(Display *, XEvent *e, char *args) {
-  if ((e->type == LeaveNotify) &&
-      (e->xcrossing.window == ((scanargs *) args)->w) &&
-      (e->xcrossing.mode == NotifyNormal)) {
-    ((scanargs *) args)->leave = True;
-    ((scanargs *) args)->inferior = (e->xcrossing.detail == NotifyInferior);
-  } else if ((e->type == EnterNotify) &&
-             (e->xcrossing.mode == NotifyUngrab)) {
-    ((scanargs *) args)->enter = True;
-  }
-
-  return False;
-}
-
-Openbox *openbox;
-
-
-Openbox::Openbox(int m_argc, char **m_argv, char *dpy_name, char *rc,
-                 char *menu) : BaseDisplay(m_argv[0], dpy_name) {
-                   grab();
-
-                   if (! XSupportsLocale())
-                     fprintf(stderr, "X server does not support locale\n");
-
-                   if (XSetLocaleModifiers("") == NULL)
-                     fprintf(stderr, "cannot set locale modifiers\n");
-
-                   ::openbox = this;
-                   argc = m_argc;
-                   argv = m_argv;
-                   if (rc == NULL || menu == NULL) {
-                     char *homedir = getenv("HOME");
-                     char *configdir = new char[strlen(homedir) + strlen("/.openbox") + 1];
-                     sprintf(configdir, "%s/.openbox", homedir);
-                     // try to make sure the ~/.openbox directory exists
-                     mkdir(configdir, S_IREAD | S_IWRITE | S_IEXEC |
-                           S_IRGRP | S_IWGRP | S_IXGRP |
-                           S_IROTH | S_IWOTH | S_IXOTH);
-
-
-                     if (rc == NULL) {
-                       rc_file = new char[strlen(configdir) + strlen("/rc") + 1];
-                       sprintf(rc_file, "%s/rc", configdir);
-                     } else
-                       rc_file = bstrdup(rc);
-
-                     if (menu == NULL) {
-                       menu_file = new char[strlen(configdir) + strlen("/menu") + 1];
-                       sprintf(menu_file, "%s/menu", configdir);
-                     } else
-                       menu_file = bstrdup(menu);
-
-                     delete [] configdir;
-                   }
-                   config.setFile(rc_file);
-
-                   no_focus = False;
-
-                   resource.style_file = NULL;
-                   resource.titlebar_layout = NULL;
-                   resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec = 0;
-
-                   current_screen = (BScreen *) 0;
-                   masked_window = (OpenboxWindow *) 0;
-                   masked = None;
-
-                   load();
-
-#ifdef    HAVE_GETPID
-                   openbox_pid = XInternAtom(getXDisplay(), "_BLACKBOX_PID", False);
-#endif // HAVE_GETPID
-
-                   for (unsigned int s = 0; s < numberOfScreens(); s++) {
-                     BScreen *screen = new BScreen(*this, s, config);
-
-                     if (! screen->isScreenManaged()) {
-                       delete screen;
-                       continue;
-                     }
-
-                     screenList.push_back(screen);
-                   }
-
-                   if (screenList.empty()) {
-                     fprintf(stderr,
-                             i18n(openboxSet, openboxNoManagableScreens,
-                                  "Openbox::Openbox: no managable screens found, aborting.\n"));
-                     ::exit(3);
-                   }
-                   current_screen = screenList[0];
-
-                   // save current settings and default values
-                   save();
-
-                   XSynchronize(getXDisplay(), False);
-                   XSync(getXDisplay(), False);
-
-                   reconfigure_wait = reread_menu_wait = False;
-
-                   timer = new BTimer(*this, *this);
-                   timer->setTimeout(0);
-                   timer->fireOnce(True);
-
-                   ungrab();
-
-                   focusWindow(0);
-                 }
-
-
-Openbox::~Openbox() {
-  for_each(screenList.begin(), screenList.end(),
-           PointerAssassin());
-
-  for_each(menuTimestamps.begin(), menuTimestamps.end(),
-           PointerAssassin());
-
-  if (resource.style_file)
-    delete [] resource.style_file;
-
-  if (resource.titlebar_layout)
-    delete [] resource.titlebar_layout;
-
-  delete timer;
-
-  delete [] rc_file;
-  delete [] menu_file;
-}
-
-
-void Openbox::process_event(XEvent *e) {
-  if ((masked == e->xany.window && masked_window) &&
-      (e->type == MotionNotify)) {
-    last_time = e->xmotion.time;
-    masked_window->motionNotifyEvent(&e->xmotion);
-    return;
-  }
-
-  switch (e->type) {
-  case ButtonPress: {
-    // strip the lock key modifiers
-    e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
-
-    last_time = e->xbutton.time;
-
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-    Basemenu *menu = (Basemenu *) 0;
-
-#ifdef    SLIT
-    Slit *slit = (Slit *) 0;
-#endif // SLIT
-
-    Toolbar *tbar = (Toolbar *) 0;
-
-    if ((win = searchWindow(e->xbutton.window))) {
-      win->buttonPressEvent(&e->xbutton);
-
-      if (e->xbutton.button == 1)
-        win->installColormap(True);
-    } else if ((menu = searchMenu(e->xbutton.window))) {
-      menu->buttonPressEvent(&e->xbutton);
-
-#ifdef    SLIT
-    } else if ((slit = searchSlit(e->xbutton.window))) {
-      slit->buttonPressEvent(&e->xbutton);
-#endif // SLIT
-
-    } else if ((tbar = searchToolbar(e->xbutton.window))) {
-      tbar->buttonPressEvent(&e->xbutton);
-    } else {
-      ScreenList::iterator it;
-      for (it = screenList.begin(); it != screenList.end(); ++it) {
-        BScreen *screen = *it;
-        if (e->xbutton.window == screen->getRootWindow()) {
-          if (e->xbutton.button == 1) {
-            if (! screen->isRootColormapInstalled())
-              screen->getImageControl()->installRootColormap();
-
-            if (screen->getWorkspacemenu()->isVisible())
-              screen->getWorkspacemenu()->hide();
-
-            if (screen->getRootmenu()->isVisible())
-              screen->getRootmenu()->hide();
-          } else if (e->xbutton.button == 2) {
-            int mx = e->xbutton.x_root -
-              (screen->getWorkspacemenu()->getWidth() / 2);
-            int my = e->xbutton.y_root -
-              (screen->getWorkspacemenu()->getTitleHeight() / 2);
-
-            if (mx < 0) mx = 0;
-            if (my < 0) my = 0;
-
-            if (mx + screen->getWorkspacemenu()->getWidth() >
-                screen->size().w())
-              mx = screen->size().w() -
-                screen->getWorkspacemenu()->getWidth() -
-                screen->getBorderWidth();
-
-            if (my + screen->getWorkspacemenu()->getHeight() >
-                screen->size().h())
-              my = screen->size().h() -
-                screen->getWorkspacemenu()->getHeight() -
-                screen->getBorderWidth();
-
-            screen->getWorkspacemenu()->move(mx, my);
-
-            if (! screen->getWorkspacemenu()->isVisible()) {
-              screen->getWorkspacemenu()->removeParent();
-              screen->getWorkspacemenu()->show();
-            }
-          } else if (e->xbutton.button == 3) {
-            int mx = e->xbutton.x_root -
-              (screen->getRootmenu()->getWidth() / 2);
-            int my = e->xbutton.y_root -
-              (screen->getRootmenu()->getTitleHeight() / 2);
-
-            if (mx < 0) mx = 0;
-            if (my < 0) my = 0;
-
-            if (mx + screen->getRootmenu()->getWidth() > screen->size().w())
-              mx = screen->size().w() -
-                screen->getRootmenu()->getWidth() -
-                screen->getBorderWidth();
-
-            if (my + screen->getRootmenu()->getHeight() > screen->size().h())
-              my = screen->size().h() -
-                screen->getRootmenu()->getHeight() -
-                screen->getBorderWidth();
-
-            screen->getRootmenu()->move(mx, my);
-
-            if (! screen->getRootmenu()->isVisible()) {
-              checkMenu();
-              screen->getRootmenu()->show();
-            }
-          } else if (e->xbutton.button == 4) {
-            if ((screen->getCurrentWorkspaceID() + 1) >
-                screen->getWorkspaceCount() - 1)
-              screen->changeWorkspaceID(0);
-            else
-              screen->changeWorkspaceID(screen->getCurrentWorkspaceID() + 1);
-          } else if (e->xbutton.button == 5) {
-            if ((screen->getCurrentWorkspaceID() - 1) < 0)
-              screen->changeWorkspaceID(screen->getWorkspaceCount() - 1);
-            else
-              screen->changeWorkspaceID(screen->getCurrentWorkspaceID() - 1);
-          }
-        }
-      }
-    }
-
-    break;
-  }
-
-  case ButtonRelease: {
-    // strip the lock key modifiers
-    e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
-
-    last_time = e->xbutton.time;
-
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-    Basemenu *menu = (Basemenu *) 0;
-    Toolbar *tbar = (Toolbar *) 0;
-
-    if ((win = searchWindow(e->xbutton.window)))
-      win->buttonReleaseEvent(&e->xbutton);
-    else if ((menu = searchMenu(e->xbutton.window)))
-      menu->buttonReleaseEvent(&e->xbutton);
-    else if ((tbar = searchToolbar(e->xbutton.window)))
-      tbar->buttonReleaseEvent(&e->xbutton);
-
-    break;
-  }
-
-  case ConfigureRequest: {
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-
-#ifdef    SLIT
-    Slit *slit = (Slit *) 0;
-#endif // SLIT
-
-    if ((win = searchWindow(e->xconfigurerequest.window))) {
-      win->configureRequestEvent(&e->xconfigurerequest);
-
-#ifdef    SLIT
-    } else if ((slit = searchSlit(e->xconfigurerequest.window))) {
-      slit->configureRequestEvent(&e->xconfigurerequest);
-#endif // SLIT
-
-    } else {
-      grab();
-
-      if (validateWindow(e->xconfigurerequest.window)) {
-        XWindowChanges xwc;
-
-        xwc.x = e->xconfigurerequest.x;
-        xwc.y = e->xconfigurerequest.y;
-        xwc.width = e->xconfigurerequest.width;
-        xwc.height = e->xconfigurerequest.height;
-        xwc.border_width = e->xconfigurerequest.border_width;
-        xwc.sibling = e->xconfigurerequest.above;
-        xwc.stack_mode = e->xconfigurerequest.detail;
-
-        XConfigureWindow(getXDisplay(), e->xconfigurerequest.window,
-                         e->xconfigurerequest.value_mask, &xwc);
-      }
-
-      ungrab();
-    }
-
-    break;
-  }
-
-  case MapRequest: {
-#ifdef    DEBUG
-    fprintf(stderr,
-            i18n(openboxSet, openboxMapRequest,
-                 "Openbox::process_event(): MapRequest for 0x%lx\n"),
-            e->xmaprequest.window);
-#endif // DEBUG
-
-    OpenboxWindow *win = searchWindow(e->xmaprequest.window);
-
-    if (! win)
-      win = new OpenboxWindow(*this, e->xmaprequest.window);
-
-    if ((win = searchWindow(e->xmaprequest.window)))
-      win->mapRequestEvent(&e->xmaprequest);
-
-    break;
-  }
-
-  case MapNotify: {
-    OpenboxWindow *win = searchWindow(e->xmap.window);
-
-    if (win)
-      win->mapNotifyEvent(&e->xmap);
-
-    break;
-  }
-
-  case UnmapNotify: {
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-
-#ifdef    SLIT
-    Slit *slit = (Slit *) 0;
-#endif // SLIT
-
-    if ((win = searchWindow(e->xunmap.window))) {
-      win->unmapNotifyEvent(&e->xunmap);
-#ifdef    SLIT
-    } else if ((slit = searchSlit(e->xunmap.window))) {
-      slit->removeClient(e->xunmap.window);
-#endif // SLIT
-
-    }
-
-    break;
-  }
-
-  case DestroyNotify: {
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-
-#ifdef    SLIT
-    Slit *slit = (Slit *) 0;
-#endif // SLIT
-
-    if ((win = searchWindow(e->xdestroywindow.window))) {
-      win->destroyNotifyEvent(&e->xdestroywindow);
-#ifdef    SLIT
-    } else if ((slit = searchSlit(e->xdestroywindow.window))) {
-      slit->removeClient(e->xdestroywindow.window, False);
-#endif // SLIT
-    }
-
-    break;
-  }
-
-  case MotionNotify: {
-    // strip the lock key modifiers
-    e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask);
-
-    last_time = e->xmotion.time;
-
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-    Basemenu *menu = (Basemenu *) 0;
-
-    if ((win = searchWindow(e->xmotion.window)))
-      win->motionNotifyEvent(&e->xmotion);
-    else if ((menu = searchMenu(e->xmotion.window)))
-      menu->motionNotifyEvent(&e->xmotion);
-
-    break;
-  }
-
-  case PropertyNotify: {
-    last_time = e->xproperty.time;
-
-    if (e->xproperty.state != PropertyDelete) {
-      OpenboxWindow *win = searchWindow(e->xproperty.window);
-
-      if (win)
-        win->propertyNotifyEvent(e->xproperty.atom);
-    }
-
-    break;
-  }
-
-  case EnterNotify: {
-    last_time = e->xcrossing.time;
-
-    BScreen *screen = (BScreen *) 0;
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-    Basemenu *menu = (Basemenu *) 0;
-    Toolbar *tbar = (Toolbar *) 0;
-
-#ifdef    SLIT
-    Slit *slit = (Slit *) 0;
-#endif // SLIT
-
-    if (e->xcrossing.mode == NotifyGrab) break;
-
-    XEvent dummy;
-    scanargs sa;
-    sa.w = e->xcrossing.window;
-    sa.enter = sa.leave = False;
-    XCheckIfEvent(getXDisplay(), &dummy, queueScanner, (char *) &sa);
-
-    if ((e->xcrossing.window == e->xcrossing.root) &&
-        (screen = searchScreen(e->xcrossing.window))) {
-      screen->getImageControl()->installRootColormap();
-    } else if ((win = searchWindow(e->xcrossing.window))) {
-      if (win->getScreen()->sloppyFocus() &&
-          (! win->isFocused()) && (! no_focus)) {
-        grab();
-
-        if (((! sa.leave) || sa.inferior) && win->isVisible() &&
-            win->setInputFocus())
-          win->installColormap(True);
-
-        ungrab();
-      }
-    } else if ((menu = searchMenu(e->xcrossing.window))) {
-      menu->enterNotifyEvent(&e->xcrossing);
-    } else if ((tbar = searchToolbar(e->xcrossing.window))) {
-      tbar->enterNotifyEvent(&e->xcrossing);
-#ifdef    SLIT
-    } else if ((slit = searchSlit(e->xcrossing.window))) {
-      slit->enterNotifyEvent(&e->xcrossing);
-#endif // SLIT
-    }
-    break;
-  }
-
-  case LeaveNotify: {
-    last_time = e->xcrossing.time;
-
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-    Basemenu *menu = (Basemenu *) 0;
-    Toolbar *tbar = (Toolbar *) 0;
-
-#ifdef    SLIT
-    Slit *slit = (Slit *) 0;
-#endif // SLIT
-
-    if ((menu = searchMenu(e->xcrossing.window)))
-      menu->leaveNotifyEvent(&e->xcrossing);
-    else if ((win = searchWindow(e->xcrossing.window)))
-      win->installColormap(False);
-    else if ((tbar = searchToolbar(e->xcrossing.window)))
-      tbar->leaveNotifyEvent(&e->xcrossing);
-#ifdef    SLIT
-    else if ((slit = searchSlit(e->xcrossing.window)))
-      slit->leaveNotifyEvent(&e->xcrossing);
-#endif // SLIT
-
-    break;
-  }
-
-  case Expose: {
-    OpenboxWindow *win = (OpenboxWindow *) 0;
-    Basemenu *menu = (Basemenu *) 0;
-    Toolbar *tbar = (Toolbar *) 0;
-
-    if ((win = searchWindow(e->xexpose.window)))
-      win->exposeEvent(&e->xexpose);
-    else if ((menu = searchMenu(e->xexpose.window)))
-      menu->exposeEvent(&e->xexpose);
-    else if ((tbar = searchToolbar(e->xexpose.window)))
-      tbar->exposeEvent(&e->xexpose);
-
-    break;
-  }
-
-  case KeyPress: {
-    Toolbar *tbar = searchToolbar(e->xkey.window);
-
-    if (tbar && tbar->isEditing())
-      tbar->keyPressEvent(&e->xkey);
-
-    break;
-  }
-
-  case ColormapNotify: {
-    BScreen *screen = searchScreen(e->xcolormap.window);
-
-    if (screen)
-      screen->setRootColormapInstalled((e->xcolormap.state ==
-                                        ColormapInstalled) ? True : False);
-
-    break;
-  }
-
-  case FocusIn: {
-    if (e->xfocus.mode == NotifyUngrab || e->xfocus.detail == NotifyPointer)
-      break;
-
-    OpenboxWindow *win = searchWindow(e->xfocus.window);
-    if (win && !win->isFocused())
-      focusWindow(win);
-
-    break;
-  }
-
-  case FocusOut:
-    break;
-
-  case ClientMessage: {
-    if (e->xclient.format == 32) {
-      if (e->xclient.message_type == getWMChangeStateAtom()) {
-        OpenboxWindow *win = searchWindow(e->xclient.window);
-        if (! win || ! win->validateClient()) return;
-
-        if (e->xclient.data.l[0] == IconicState)
-          win->iconify();
-        if (e->xclient.data.l[0] == NormalState)
-          win->deiconify();
-      } else if (e->xclient.message_type == getOpenboxChangeWorkspaceAtom()) {
-        BScreen *screen = searchScreen(e->xclient.window);
-
-        if (screen && e->xclient.data.l[0] >= 0 &&
-            e->xclient.data.l[0] < screen->getWorkspaceCount())
-          screen->changeWorkspaceID(e->xclient.data.l[0]);
-      } else if (e->xclient.message_type == getOpenboxChangeWindowFocusAtom()) {
-        OpenboxWindow *win = searchWindow(e->xclient.window);
-
-        if (win && win->isVisible() && win->setInputFocus())
-          win->installColormap(True);
-      } else if (e->xclient.message_type == getOpenboxCycleWindowFocusAtom()) {
-        BScreen *screen = searchScreen(e->xclient.window);
-
-        if (screen) {
-          if (! e->xclient.data.l[0])
-            screen->prevFocus();
-          else
-            screen->nextFocus();
-        }
-      } else if (e->xclient.message_type == getOpenboxChangeAttributesAtom()) {
-        OpenboxWindow *win = searchWindow(e->xclient.window);
-
-        if (win && win->validateClient()) {
-          OpenboxHints net;
-          net.flags = e->xclient.data.l[0];
-          net.attrib = e->xclient.data.l[1];
-          net.workspace = e->xclient.data.l[2];
-          net.stack = e->xclient.data.l[3];
-          net.decoration = e->xclient.data.l[4];
-
-          win->changeOpenboxHints(&net);
-        }
-      }
-    }
-
-    break;
-  }
-
-
-  default: {
-#ifdef    SHAPE
-    if (e->type == getShapeEventBase()) {
-      XShapeEvent *shape_event = (XShapeEvent *) e;
-      OpenboxWindow *win = (OpenboxWindow *) 0;
-
-      if ((win = searchWindow(e->xany.window)) ||
-          (shape_event->kind != ShapeBounding))
-        win->shapeEvent(shape_event);
-    }
-#endif // SHAPE
-
-  }
-  } // switch
-}
-
-
-Bool Openbox::handleSignal(int sig) {
-  switch (sig) {
-  case SIGHUP:
-  case SIGUSR1:
-    reconfigure();
-    break;
-
-  case SIGUSR2:
-    rereadMenu();
-    break;
-
-  case SIGPIPE:
-  case SIGSEGV:
-  case SIGFPE:
-  case SIGINT:
-  case SIGTERM:
-    shutdown();
-
-  default:
-    return False;
-  }
-
-  return True;
-}
-
-
-BScreen *Openbox::searchScreen(Window window) {
-  ScreenList::iterator it;
-  for (it = screenList.begin(); it != screenList.end(); ++it)
-    if ((*it)->getRootWindow() == window)
-      return *it;
-  return (BScreen *) 0;
-}
-
-
-OpenboxWindow *Openbox::searchWindow(Window window) {
-  WindowLookup::iterator it = windowSearchList.find(window);
-  if (it == windowSearchList.end())
-    return (OpenboxWindow *) 0;
-  return it->second;
-}
-
-
-OpenboxWindow *Openbox::searchGroup(Window window, OpenboxWindow *win) {
-  WindowLookup::iterator it = groupSearchList.find(window);
-  if (it != groupSearchList.end())
-    if (it->second->getClientWindow() != win->getClientWindow())
-      return win;
-  return (OpenboxWindow *) 0;
-}
-
-
-Basemenu *Openbox::searchMenu(Window window) {
-  MenuLookup::iterator it = menuSearchList.find(window);
-  if (it == menuSearchList.end())
-    return (Basemenu *) 0;
-  return it->second;
-}
-
-
-Toolbar *Openbox::searchToolbar(Window window) {
-  ToolbarLookup::iterator it = toolbarSearchList.find(window);
-  if (it == toolbarSearchList.end())
-    return (Toolbar *) 0;
-  return it->second;
-}
-
-
-#ifdef    SLIT
-Slit *Openbox::searchSlit(Window window) {
-  SlitLookup::iterator it = slitSearchList.find(window);
-  if (it == slitSearchList.end())
-    return (Slit *) 0;
-  return it->second;
-}
-#endif // SLIT
-
-
-void Openbox::saveWindowSearch(Window window, OpenboxWindow *data) {
-  windowSearchList.insert(WindowLookupPair(window, data));
-}
-
-
-void Openbox::saveGroupSearch(Window window, OpenboxWindow *data) {
-  groupSearchList.insert(WindowLookupPair(window, data));
-}
-
-
-void Openbox::saveMenuSearch(Window window, Basemenu *data) {
-  menuSearchList.insert(MenuLookupPair(window, data));
-}
-
-
-void Openbox::saveToolbarSearch(Window window, Toolbar *data) {
-  toolbarSearchList.insert(ToolbarLookupPair(window, data));
-}
-
-
-#ifdef    SLIT
-void Openbox::saveSlitSearch(Window window, Slit *data) {
-  slitSearchList.insert(SlitLookupPair(window, data));
-}
-#endif // SLIT
-
-
-void Openbox::removeWindowSearch(Window window) {
-  windowSearchList.erase(window);
-}
-
-
-void Openbox::removeGroupSearch(Window window) {
-  groupSearchList.erase(window);
-}
-
-
-void Openbox::removeMenuSearch(Window window) {
-  menuSearchList.erase(window);
-}
-
-
-void Openbox::removeToolbarSearch(Window window) {
-  toolbarSearchList.erase(window);
-}
-
-
-#ifdef    SLIT
-void Openbox::removeSlitSearch(Window window) {
-  slitSearchList.erase(window);
-}
-#endif // SLIT
-
-
-void Openbox::restart(const char *prog) {
-  shutdown();
-
-  if (prog) {
-    execlp(prog, prog, NULL);
-    perror(prog);
-  }
-
-  // fall back in case the above execlp doesn't work
-  execvp(argv[0], argv);
-  execvp(basename(argv[0]), argv);
-}
-
-
-void Openbox::shutdown() {
-  BaseDisplay::shutdown();
-
-  std::for_each(screenList.begin(), screenList.end(),
-                std::mem_fun(&BScreen::shutdown));
-
-  focusWindow(0);
-
-  XSync(getXDisplay(), False);
-}
-
-
-void Openbox::save() {
-  config.setAutoSave(false);
-
-  // save all values as they are so that the defaults will be written to the rc
-  // file
-
-  config.setValue("session.colorsPerChannel",
-                  resource.colors_per_channel);
-  config.setValue("session.styleFile", resource.style_file);
-  config.setValue("session.titlebarLayout", resource.titlebar_layout);
-  config.setValue("session.doubleClickInterval",
-                  (long)resource.double_click_interval);
-  config.setValue("session.autoRaiseDelay",
-                  ((resource.auto_raise_delay.tv_sec * 1000) +
-                   (resource.auto_raise_delay.tv_usec / 1000)));
-  config.setValue("session.cacheLife", (long)resource.cache_life / 60000);
-  config.setValue("session.cacheMax", (long)resource.cache_max);
-
-  std::for_each(screenList.begin(), screenList.end(),
-                std::mem_fun(&BScreen::save));
-
-  config.setAutoSave(true);
-  config.save();
-}
-
-void Openbox::load() {
-  if (!config.load())
-    config.create();
-
-  std::string s;
-  long l;
-
-  if (config.getValue("session.colorsPerChannel", "Session.ColorsPerChannel",
-                      l))
-    resource.colors_per_channel = (l < 2 ? 2 : (l > 6 ? 6 : l)); // >= 2, <= 6
-  else
-    resource.colors_per_channel = 4;
-
-  if (resource.style_file)
-    delete [] resource.style_file;
-  if (config.getValue("session.styleFile", "Session.StyleFile", s))
-    resource.style_file = bstrdup(s.c_str());
-  else
-    resource.style_file = bstrdup(DEFAULTSTYLE);
-
-  if (resource.titlebar_layout)
-    delete [] resource.titlebar_layout;
-  if (config.getValue("session.titlebarLayout", "Session.TitlebarLayout", s))
-    resource.titlebar_layout = bstrdup(s.c_str());
-  else
-    resource.titlebar_layout = bstrdup("ILMC");
-
-  if (config.getValue("session.doubleClickInterval",
-                      "Session.DoubleClickInterval", l))
-    resource.double_click_interval = l;
-  else
-    resource.double_click_interval = 250;
-
-  if (config.getValue("session.autoRaiseDelay", "Session.AutoRaiseDelay", l))
-    resource.auto_raise_delay.tv_usec = l;
-  else
-    resource.auto_raise_delay.tv_usec = 400;
-  resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec / 1000;
-  resource.auto_raise_delay.tv_usec -=
-    (resource.auto_raise_delay.tv_sec * 1000);
-  resource.auto_raise_delay.tv_usec *= 1000;
-
-  if (config.getValue("session.cacheLife", "Session.CacheLife", l))
-    resource.cache_life = l;
-  else
-    resource.cache_life = 51;
-  resource.cache_life *= 60000;
-
-  if (config.getValue("session.cacheMax", "Session.CacheMax", l))
-    resource.cache_max = l;
-  else
-    resource.cache_max = 200;
-}
-
-
-void Openbox::reconfigure() {
-  reconfigure_wait = True;
-
-  if (! timer->isTiming()) timer->start();
-}
-
-
-void Openbox::real_reconfigure() {
-  grab();
-
-  load();
-
-  for_each(menuTimestamps.begin(), menuTimestamps.end(),
-           PointerAssassin());
-  menuTimestamps.clear();
-
-  std::for_each(screenList.begin(), screenList.end(),
-                std::mem_fun(&BScreen::reconfigure));
-
-  ungrab();
-}
-
-
-void Openbox::checkMenu() {
-  MenuTimestampList::iterator it;
-  for (it = menuTimestamps.begin(); it != menuTimestamps.end(); ++it) {
-    struct stat buf;
-
-    if (stat((*it)->filename, &buf) || (*it)->timestamp != buf.st_ctime) {
-      rereadMenu();
-      return;
-    }
-  }
-}
-
-
-void Openbox::addMenuTimestamp(const char *filename) {
-  bool found = false;
-
-  MenuTimestampList::iterator it;
-  for (it = menuTimestamps.begin(); it != menuTimestamps.end(); ++it)
-    if (! strcmp((*it)->filename, filename)) {
-      found = true;
-      break;
-    }
-  if (!found) {
-    struct stat buf;
-
-    if (! stat(filename, &buf)) {
-      MenuTimestamp *ts = new MenuTimestamp;
-
-      ts->filename = bstrdup(filename);
-      ts->timestamp = buf.st_ctime;
-
-      menuTimestamps.push_back(ts);
-    }
-  }
-}
-
-void Openbox::rereadMenu() {
-  reread_menu_wait = True;
-
-  if (! timer->isTiming()) timer->start();
-}
-
-
-void Openbox::real_rereadMenu() {
-  std::for_each(menuTimestamps.begin(), menuTimestamps.end(),
-                PointerAssassin());
-  menuTimestamps.clear();
-
-  std::for_each(screenList.begin(), screenList.end(),
-                std::mem_fun(&BScreen::rereadMenu));
-}
-
-
-void Openbox::setStyleFilename(const char *filename) {
-  if (resource.style_file)
-    delete [] resource.style_file;
-
-  resource.style_file = bstrdup(filename);
-  config.setValue("session.styleFile", resource.style_file);
-}
-
-
-void Openbox::timeout() {
-  if (reconfigure_wait)
-    real_reconfigure();
-
-  if (reread_menu_wait)
-    real_rereadMenu();
-
-  reconfigure_wait = reread_menu_wait = False;
-}
-
-
-OpenboxWindow *Openbox::focusedWindow() {
-  Workspace *w;
-  if (current_screen)
-    if ((w = current_screen->getCurrentWorkspace()))
-      return w->focusedWindow();
-  return (OpenboxWindow *) 0;
-}
-
-
-void Openbox::focusWindow(OpenboxWindow *win) {
-  BScreen *old_screen = (BScreen *) 0;
-  Toolbar *old_tbar = (Toolbar *) 0, *tbar = (Toolbar *) 0;
-  Workspace *old_wkspc = (Workspace *) 0, *wkspc = (Workspace *) 0;
-
-  OpenboxWindow *old_win = focusedWindow();
-  if (old_win != (OpenboxWindow *) 0) {
-    old_screen = old_win->getScreen();
-    old_wkspc = old_screen->getWorkspace(old_win->getWorkspaceNumber());
-    old_tbar = old_screen->getToolbar();
-
-    old_win->setFocusFlag(false);
-    old_wkspc->focusWindow((OpenboxWindow *) 0);
-  }
-
-  if (win && !win->isIconic()) {
-    current_screen = win->getScreen();
-    tbar = current_screen->getToolbar();
-    if (win->isStuck())
-      wkspc = current_screen->getCurrentWorkspace();
-    else
-      wkspc = current_screen->getWorkspace(win->getWorkspaceNumber());
-    win->setFocusFlag(true);
-    wkspc->focusWindow(win);
-
-    if (tbar)
-      tbar->redrawWindowLabel(true);
-    current_screen->updateNetizenWindowFocus();
-  } else {
-    XSetInputFocus(getXDisplay(), PointerRoot, None, CurrentTime);
-  }
-
-  if (old_tbar && old_tbar != tbar)
-    old_tbar->redrawWindowLabel(true);
-  if (old_screen && old_screen != current_screen)
-    old_screen->updateNetizenWindowFocus();
-}
diff --git a/src/openbox.h b/src/openbox.h
deleted file mode 100644 (file)
index 009b57f..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-// openbox.h for Openbox
-// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
-// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#ifndef   __openbox_hh
-#define   __openbox_hh
-
-#include <X11/Xlib.h>
-#include <X11/Xresource.h>
-
-#ifdef    HAVE_STDIO_H
-# include <stdio.h>
-#endif // HAVE_STDIO_H
-
-#ifdef    TIME_WITH_SYS_TIME
-#  include <sys/time.h>
-#  include <time.h>
-#else // !TIME_WITH_SYS_TIME
-#  ifdef    HAVE_SYS_TIME_H
-#    include <sys/time.h>
-#  else // !HAVE_SYS_TIME_H
-#    include <time.h>
-#  endif // HAVE_SYS_TIME_H
-#endif // TIME_WITH_SYS_TIME
-
-#include "Resource.h"
-#include "BaseDisplay.h"
-#include "Timer.h"
-
-#include <map>
-#include <list>
-#include <vector>
-
-//forward declaration
-class BScreen;
-class Openbox;
-class BImageControl;
-class OpenboxWindow;
-class Basemenu;
-class Toolbar;
-#ifdef    SLIT
-class Slit;
-#endif // SLIT
-
-template <class Z>
-class DataSearch {
-private:
-  Window window;
-  Z *data;
-
-public:
-  DataSearch(Window w, Z *d): window(w), data(d) {}
-
-  inline const Window &getWindow() const { return window; }
-  inline Z *getData() { return data; }
-};
-
-
-class Openbox : public BaseDisplay, public TimeoutHandler {
-private:
-  typedef struct MenuTimestamp {
-    virtual ~MenuTimestamp() {
-      if (filename != (char *) 0)
-        delete [] filename;
-    }
-    char *filename;
-    time_t timestamp;
-  } MenuTimestamp;
-
-  struct resource {
-    Time double_click_interval;
-
-    char *style_file;
-    char *titlebar_layout;
-    int colors_per_channel;
-    timeval auto_raise_delay;
-    unsigned long cache_life, cache_max;
-  } resource;
-
-  typedef std::map<Window, OpenboxWindow*> WindowLookup;
-  typedef WindowLookup::value_type WindowLookupPair;
-  WindowLookup windowSearchList, groupSearchList;
-  
-  typedef std::map<Window, Basemenu*> MenuLookup;
-  typedef MenuLookup::value_type MenuLookupPair;
-  MenuLookup menuSearchList;
-
-  typedef std::map<Window, Toolbar*> ToolbarLookup;
-  typedef ToolbarLookup::value_type ToolbarLookupPair;
-  ToolbarLookup toolbarSearchList;
-
-#ifdef    SLIT
-  typedef std::map<Window, Slit*> SlitLookup;
-  typedef SlitLookup::value_type SlitLookupPair;
-  SlitLookup slitSearchList; 
-#endif // SLIT
-
-  typedef std::list<MenuTimestamp*> MenuTimestampList;
-  MenuTimestampList menuTimestamps;
-
-  typedef std::vector<BScreen*> ScreenList;
-  ScreenList screenList;
-
-  BScreen *current_screen;
-  OpenboxWindow *masked_window;
-  BTimer *timer;
-
-#ifdef    HAVE_GETPID
-  Atom openbox_pid;
-#endif // HAVE_GETPID
-
-  Bool no_focus, reconfigure_wait, reread_menu_wait;
-  Time last_time;
-  Window masked;
-  char *menu_file, *rc_file, **argv;
-  int argc;
-  Resource config;
-
-
-protected:
-  void load();
-  void save();
-  void real_rereadMenu();
-  void real_reconfigure();
-
-  virtual void process_event(XEvent *);
-
-
-public:
-  Openbox(int, char **, char * = 0, char * = 0, char * = 0);
-  virtual ~Openbox();
-
-#ifdef    HAVE_GETPID
-  inline const Atom &getOpenboxPidAtom() const { return openbox_pid; }
-#endif // HAVE_GETPID
-
-  Basemenu *searchMenu(Window);
-
-  OpenboxWindow *searchGroup(Window, OpenboxWindow *);
-  OpenboxWindow *searchWindow(Window);
-  OpenboxWindow *focusedWindow();
-  void focusWindow(OpenboxWindow *w);
-
-  inline BScreen *getScreen(unsigned int s) {
-    ASSERT(s < screenList.size());
-    return screenList[s];
-  }
-  BScreen *searchScreen(Window);
-  inline unsigned int managedScreenCount() const {
-    return screenList.size();
-  }
-
-  inline Resource &getConfig() {
-    return config;
-  }
-  inline const Time &getDoubleClickInterval() const
-    { return resource.double_click_interval; }
-  inline const Time &getLastTime() const { return last_time; }
-
-  Toolbar *searchToolbar(Window);
-
-  inline const char *getStyleFilename() const
-    { return resource.style_file; }
-  inline const char *getMenuFilename() const
-    { return menu_file; }
-  void addMenuTimestamp(const char *filename);
-
-  inline const int &getColorsPerChannel() const
-    { return resource.colors_per_channel; }
-
-  inline const timeval &getAutoRaiseDelay() const
-    { return resource.auto_raise_delay; }
-
-  inline const char *getTitleBarLayout() const
-    { return resource.titlebar_layout; }
-
-  inline const unsigned long &getCacheLife() const
-    { return resource.cache_life; }
-  inline const unsigned long &getCacheMax() const
-    { return resource.cache_max; }
-
-  inline OpenboxWindow *getMaskedWindow() const
-    { return masked_window; }
-  inline void maskWindowEvents(Window w, OpenboxWindow *bw)
-    { masked = w; masked_window = bw; }
-  inline void setNoFocus(Bool f) { no_focus = f; }
-
-  void shutdown();
-  void setStyleFilename(const char *);
-  void saveMenuSearch(Window, Basemenu *);
-  void saveWindowSearch(Window, OpenboxWindow *);
-  void saveToolbarSearch(Window, Toolbar *);
-  void saveGroupSearch(Window, OpenboxWindow *);
-  void removeMenuSearch(Window);
-  void removeWindowSearch(Window);
-  void removeToolbarSearch(Window);
-  void removeGroupSearch(Window);
-  void restart(const char * = 0);
-  void reconfigure();
-  void rereadMenu();
-  void checkMenu();
-
-  virtual Bool handleSignal(int);
-
-  virtual void timeout();
-
-#ifdef    SLIT
-  Slit *searchSlit(Window);
-
-  void saveSlitSearch(Window, Slit *);
-  void removeSlitSearch(Window);
-#endif // SLIT
-
-#ifndef   HAVE_STRFTIME
-
-  enum { B_AmericanDate = 1, B_EuropeanDate };
-#endif // HAVE_STRFTIME
-};
-
-
-#endif // __openbox_hh
This page took 0.667348 seconds and 4 git commands to generate.