]> Dogcows Code - chaz/openbox/commitdiff
No longer using otk widgets for the frame decorations.
authorDana Jansens <danakj@orodu.net>
Sat, 8 Feb 2003 07:37:22 +0000 (07:37 +0000)
committerDana Jansens <danakj@orodu.net>
Sat, 8 Feb 2003 07:37:22 +0000 (07:37 +0000)
The titlebar no long has any buttons, in preparation for a new button system.
Using otk::Size for sizes, and unsigned ints (*PAIN*) we'll see..

15 files changed:
src/Makefile.am
src/actions.cc
src/backgroundwidget.cc [deleted file]
src/backgroundwidget.hh [deleted file]
src/buttonwidget.cc [deleted file]
src/buttonwidget.hh [deleted file]
src/client.cc
src/client.hh
src/frame.cc
src/frame.hh
src/labelwidget.cc [deleted file]
src/labelwidget.hh [deleted file]
src/openbox.cc
src/screen.cc
src/screen.hh

index bf759d8213dd6cf9711630d5f98390672977bcb4..c1ecf8e7c36c4bf42171c612bafb6adf91784ea3 100644 (file)
@@ -16,11 +16,10 @@ bin_PROGRAMS= openbox3
 openbox3_LDADD=-L../otk -lotk @LIBINTL@
 openbox3_LDFLAGS=-export-dynamic
 openbox3_SOURCES= actions.cc client.cc frame.cc openbox.cc screen.cc \
-                  main.cc backgroundwidget.cc labelwidget.cc \
-                  buttonwidget.cc python.cc bindings.cc
-noinst_HEADERS= actions.hh backgroundwidget.hh bindings.hh buttonwidget.hh \
-                client.hh frame.hh labelwidget.hh openbox.hh python.hh \
-                screen.hh widgetbase.hh gettext.h
+                  main.cc python.cc bindings.cc
+noinst_HEADERS= actions.hh bindings.hh \
+                client.hh frame.hh openbox.hh python.hh \
+                screen.hh
 
 MAINTAINERCLEANFILES= Makefile.in
 
index b557cd33d6603d6017de35a97044bf024726acb2..bb5088e92447e23d9b1da283e90e1f835247a51a 100644 (file)
@@ -5,9 +5,9 @@
 #endif
 
 #include "actions.hh"
-#include "widgetbase.hh"
 #include "openbox.hh"
 #include "client.hh"
+#include "frame.hh"
 #include "screen.hh"
 #include "python.hh"
 #include "bindings.hh"
@@ -72,12 +72,20 @@ void Actions::buttonPressHandler(const XButtonEvent &e)
 {
   otk::EventHandler::buttonPressHandler(e);
   insertPress(e);
-  
-  // run the PRESS python hook
-  WidgetBase *w = dynamic_cast<WidgetBase*>
-    (openbox->findHandler(e.window));
-  if (!w) return;
 
+  MouseContext::MC context;
+  EventHandler *h = openbox->findHandler(e.window);
+  Frame *f = dynamic_cast<Frame*>(h);
+  if (f)
+    context= f->mouseContext(e.window);
+  else if (dynamic_cast<Client*>(h))
+    context = MouseContext::Window;
+  else if (dynamic_cast<Screen*>(h))
+    context = MouseContext::Root;
+  else
+    return; // not a valid mouse context
+
+  // run the PRESS python hook
   // kill off the Button1Mask etc, only want the modifiers
   unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask |
                                   Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
@@ -87,7 +95,7 @@ void Actions::buttonPressHandler(const XButtonEvent &e)
     screen = c->screen();
   else
     screen = otk::display->findScreen(e.root)->screen();
-  MouseData data(screen, c, e.time, state, e.button, w->mcontext(),
+  MouseData data(screen, c, e.time, state, e.button, context,
                  MouseAction::Press);
   openbox->bindings()->fireButton(&data);
     
@@ -95,7 +103,7 @@ void Actions::buttonPressHandler(const XButtonEvent &e)
 
   _button = e.button;
 
-  if (w->mcontext() == MouseContext::Window) {
+  if (context == MouseContext::Window) {
     /*
       Because of how events are grabbed on the client window, we can't get
       ButtonRelease events, so instead we simply manufacture them here, so that
@@ -113,9 +121,17 @@ void Actions::buttonReleaseHandler(const XButtonEvent &e)
   otk::EventHandler::buttonReleaseHandler(e);
   removePress(e);
   
-  WidgetBase *w = dynamic_cast<WidgetBase*>
-    (openbox->findHandler(e.window));
-  if (!w) return;
+  MouseContext::MC context;
+  EventHandler *h = openbox->findHandler(e.window);
+  Frame *f = dynamic_cast<Frame*>(h);
+  if (f)
+    context= f->mouseContext(e.window);
+  else if (dynamic_cast<Client*>(h))
+    context = MouseContext::Window;
+  else if (dynamic_cast<Screen*>(h))
+    context = MouseContext::Root;
+  else
+    return; // not a valid mouse context
 
   // run the RELEASE python hook
   // kill off the Button1Mask etc, only want the modifiers
@@ -127,7 +143,7 @@ void Actions::buttonReleaseHandler(const XButtonEvent &e)
     screen = c->screen();
   else
     screen = otk::display->findScreen(e.root)->screen();
-  MouseData data(screen, c, e.time, state, e.button, w->mcontext(),
+  MouseData data(screen, c, e.time, state, e.button, context,
                  MouseAction::Release);
   openbox->bindings()->fireButton(&data);
 
@@ -260,6 +276,18 @@ void Actions::motionHandler(const XMotionEvent &e)
 
   if (!e.same_screen) return; // this just gets stupid
 
+  MouseContext::MC context;
+  EventHandler *h = openbox->findHandler(e.window);
+  Frame *f = dynamic_cast<Frame*>(h);
+  if (f)
+    context= f->mouseContext(e.window);
+  else if (dynamic_cast<Client*>(h))
+    context = MouseContext::Window;
+  else if (dynamic_cast<Screen*>(h))
+    context = MouseContext::Root;
+  else
+    return; // not a valid mouse context
+
   int x_root = e.x_root, y_root = e.y_root;
   
   // compress changes to a window into a single change
@@ -269,10 +297,6 @@ void Actions::motionHandler(const XMotionEvent &e)
     y_root = e.y_root;
   }
 
-  WidgetBase *w = dynamic_cast<WidgetBase*>
-    (openbox->findHandler(e.window));
-  if (!w) return;
-
   if (!_dragging) {
     long threshold;
     int dx = x_root - _posqueue[0]->pos.x();
@@ -298,7 +322,7 @@ void Actions::motionHandler(const XMotionEvent &e)
     screen = c->screen();
   else
     screen = otk::display->findScreen(e.root)->screen();
-  MouseData data(screen, c, e.time, state, button, w->mcontext(),
+  MouseData data(screen, c, e.time, state, button, context,
                  MouseAction::Motion, x_root, y_root,
                  _posqueue[0]->pos, _posqueue[0]->clientarea);
   openbox->bindings()->fireButton(&data);
diff --git a/src/backgroundwidget.cc b/src/backgroundwidget.cc
deleted file mode 100644 (file)
index 4d1a51d..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#ifdef HAVE_CONFIG_H
-# include "../config.h"
-#endif
-
-#include "backgroundwidget.hh"
-
-namespace ob {
-
-BackgroundWidget::BackgroundWidget(otk::Widget *parent,
-                                   WidgetBase::WidgetType type)
-  : otk::Widget(parent),
-    WidgetBase(type)
-{
-}
-
-
-BackgroundWidget::~BackgroundWidget()
-{
-}
-
-
-void BackgroundWidget::setTextures()
-{
-  switch (type()) {
-  case Type_Titlebar:
-    if (_focused)
-      setTexture(_style->titlebarFocusBackground());
-    else
-      setTexture(_style->titlebarUnfocusBackground());
-    break;
-  case Type_Handle:
-    if (_focused)
-      setTexture(_style->handleFocusBackground());
-    else
-      setTexture(_style->handleUnfocusBackground());
-    break;
-  case Type_Plate:
-    if (_focused)
-      setBorderColor(_style->clientBorderFocusColor());
-    else
-      setBorderColor(_style->clientBorderUnfocusColor());
-    break;
-  default:
-    assert(false); // there's no other background widgets!
-  }
-}
-
-
-void BackgroundWidget::setStyle(otk::RenderStyle *style)
-{
-  Widget::setStyle(style);
-  setTextures();
-  switch (type()) {
-  case Type_Titlebar:
-  case Type_Handle:
-    setBorderColor(_style->frameBorderColor());
-    break;
-  case Type_Plate:
-    break;
-  default:
-    assert(false); // there's no other background widgets!
-  }
-}
-
-
-void BackgroundWidget::focus()
-{
-  otk::Widget::focus();
-  setTextures();
-}
-
-
-void BackgroundWidget::unfocus()
-{
-  otk::Widget::unfocus();
-  setTextures();
-}
-
-
-void BackgroundWidget::adjust()
-{
-  // nothing to adjust here. its done in Frame::adjustSize
-}
-
-}
diff --git a/src/backgroundwidget.hh b/src/backgroundwidget.hh
deleted file mode 100644 (file)
index 640ac45..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef   __backgroundwidget_hh
-#define   __backgroundwidget_hh
-
-#include "otk/widget.hh"
-#include "widgetbase.hh"
-
-namespace ob {
-
-class BackgroundWidget : public otk::Widget, public WidgetBase
-{
-private:
-  void setTextures();
-  
-public:
-  BackgroundWidget(otk::Widget *parent, WidgetBase::WidgetType type);
-  virtual ~BackgroundWidget();
-
-  virtual void setStyle(otk::RenderStyle *style);
-
-  virtual void adjust();
-
-  virtual void focus();
-  virtual void unfocus();
-};
-
-}
-
-#endif // __backgroundwidget_hh
diff --git a/src/buttonwidget.cc b/src/buttonwidget.cc
deleted file mode 100644 (file)
index 810911b..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#ifdef HAVE_CONFIG_H
-# include "../config.h"
-#endif
-
-#include "buttonwidget.hh"
-#include "client.hh"
-
-namespace ob {
-
-ButtonWidget::ButtonWidget(otk::Widget *parent,
-                           WidgetBase::WidgetType type,
-                           Client *client)
-  : otk::Widget(parent),
-    WidgetBase(type),
-    _client(client),
-    _pressed(false),
-    _button(0),
-    _state(false)
-{
-}
-
-
-ButtonWidget::~ButtonWidget()
-{
-}
-
-
-void ButtonWidget::setTextures()
-{
-  bool p = _pressed;
-
-  switch (type()) {
-  case Type_AllDesktopsButton:
-    if (_client->desktop() == (signed)0xffffffff)
-      p = true;
-    break;
-  case Type_MaximizeButton:
-    if (_client->maxHorz() || _client->maxVert())
-      p = true;
-    break;
-  default:
-    break;
-  }
-  
-  switch (type()) {
-  case Type_LeftGrip:
-  case Type_RightGrip:
-    if (_focused)
-      setTexture(_style->gripFocusBackground());
-    else
-      setTexture(_style->gripUnfocusBackground());
-    break;
-  case Type_AllDesktopsButton:
-  case Type_MaximizeButton:
-  case Type_CloseButton:
-  case Type_IconifyButton:
-    if (p) {
-      if (_focused)
-        setTexture(_style->buttonPressFocusBackground());
-      else
-        setTexture(_style->buttonPressUnfocusBackground());
-    } else {
-      if (_focused)
-        setTexture(_style->buttonUnpressFocusBackground());
-      else
-        setTexture(_style->buttonUnpressUnfocusBackground());
-    }
-    break;
-  default:
-    assert(false); // there's no other button widgets!
-  }
-}
-
-
-void ButtonWidget::setStyle(otk::RenderStyle *style)
-{
-  otk::Widget::setStyle(style);
-  setTextures();
-
-  switch (type()) {
-  case Type_LeftGrip:
-  case Type_RightGrip:
-    setBorderColor(_style->frameBorderColor());
-    break;
-  case Type_AllDesktopsButton:
-  case Type_CloseButton:
-  case Type_MaximizeButton:
-  case Type_IconifyButton:
-    break;
-  default:
-    assert(false); // there's no other button widgets!
-  }
-}
-
-
-void ButtonWidget::update()
-{
-  switch (type()) {
-  case Type_AllDesktopsButton:
-    if ((_client->desktop() == (signed)0xffffffff) != _state) {
-      _state = !_state;
-      setTextures();
-    }
-    break;
-  case Type_MaximizeButton:
-    if ((_client->maxHorz() || _client->maxVert()) != _state) {
-      _state = !_state;
-      setTextures();
-    }
-    break;
-  default:
-    break;
-  }
-  
-  otk::Widget::update();
-}
-
-
-void ButtonWidget::renderForeground()
-{
-  otk::PixmapMask *pm;
-  int width;
-  bool draw = _dirty;
-
-  otk::Widget::renderForeground();
-
-  if (draw) {
-    switch (type()) {
-    case Type_AllDesktopsButton:
-      pm = _style->alldesktopsMask();
-      break;
-    case Type_CloseButton:
-      pm = _style->closeMask();
-      break;
-    case Type_MaximizeButton:
-      pm = _style->maximizeMask();
-      break;
-    case Type_IconifyButton:
-      pm = _style->iconifyMask();
-      break;
-    case Type_LeftGrip:
-    case Type_RightGrip:
-      return; // no drawing
-    default:
-      assert(false); // there's no other button widgets!
-    }
-
-    assert(pm->mask);
-    if (pm->mask == None) return; // no mask for the button, leave it empty
-
-    width = _rect.width();
-
-    otk::RenderColor *color = (_focused ? _style->buttonFocusColor() :
-                               _style->buttonUnfocusColor());
-
-    // set the clip region
-    int x = (width - pm->w) / 2, y = (width - pm->h) / 2;
-    XSetClipMask(**otk::display, color->gc(), pm->mask);
-    XSetClipOrigin(**otk::display, color->gc(), x, y);
-
-    // fill in the clipped region
-    XFillRectangle(**otk::display, _surface->pixmap(), color->gc(), x, y,
-                   x + pm->w, y + pm->h);
-
-    // unset the clip region
-    XSetClipMask(**otk::display, color->gc(), None);
-    XSetClipOrigin(**otk::display, color->gc(), 0, 0);
-  }
-}
-
-
-void ButtonWidget::adjust()
-{
-  // nothing to adjust. no children.
-}
-
-
-void ButtonWidget::focus()
-{
-  otk::Widget::focus();
-  setTextures();
-}
-
-
-void ButtonWidget::unfocus()
-{
-  otk::Widget::unfocus();
-  setTextures();
-}
-
-
-void ButtonWidget::buttonPressHandler(const XButtonEvent &e)
-{
-  otk::Widget::buttonPressHandler(e);
-  if (_button) return;
-  _button = e.button;
-  _pressed = true;
-  setTextures();
-  update();
-}
-
-
-void ButtonWidget::buttonReleaseHandler(const XButtonEvent &e)
-{
-  otk::Widget::buttonPressHandler(e);
-  if (e.button != _button) return;
-  _button = 0;
-  _pressed = false;
-  setTextures();
-  update();
-}
-
-}
diff --git a/src/buttonwidget.hh b/src/buttonwidget.hh
deleted file mode 100644 (file)
index 0d546f7..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef   __buttonwidget_hh
-#define   __buttonwidget_hh
-
-#include "widgetbase.hh"
-#include "otk/widget.hh"
-
-namespace ob {
-
-class Client;
-
-class ButtonWidget : public otk::Widget, public WidgetBase
-{
-private:
-  void setTextures();
-  Client *_client;
-  bool _pressed;
-  unsigned int _button;
-  bool _state;
-  
-public:
-  ButtonWidget(otk::Widget *parent, WidgetBase::WidgetType type,
-               Client *client);
-  virtual ~ButtonWidget();
-
-  virtual void setStyle(otk::RenderStyle *style);
-
-  virtual void adjust();
-
-  virtual void update();
-  
-  virtual void renderForeground();
-  
-  virtual void focus();
-  virtual void unfocus();
-
-  virtual void buttonPressHandler(const XButtonEvent &e);
-  virtual void buttonReleaseHandler(const XButtonEvent &e);
-};
-
-}
-
-#endif // __buttonwidget_hh
index 68653c31f462a8a3e007f466f789fe186102b268..d5be00d01822b8b64f7796180eeea9f0035dfda0 100644 (file)
@@ -29,7 +29,6 @@ namespace ob {
 
 Client::Client(int screen, Window window)
   : otk::EventHandler(),
-    WidgetBase(WidgetBase::Type_Client),
     frame(0), _screen(screen), _window(window)
 {
   assert(screen >= 0);
@@ -581,7 +580,7 @@ void Client::updateTitle()
     _title = _("Unnamed Window");
 
   if (frame)
-    frame->setTitle(_title);
+    frame->adjustTitle();
 }
 
 
@@ -1128,8 +1127,14 @@ void Client::resize(Corner anchor, unsigned int w, unsigned int h)
 void Client::internal_resize(Corner anchor, unsigned int w, unsigned int h,
                              bool user, int x, int y)
 {
-  w -= _base_size.width(); 
-  h -= _base_size.height();
+  if (_base_size.width() < w)
+    w -= _base_size.width();
+  else
+    w = 0;
+  if (_base_size.height() < h)
+    h -= _base_size.height();
+  else
+    h = 0;
 
   if (user) {
     // for interactive resizing. have to move half an increment in each
@@ -1714,8 +1719,8 @@ void Client::focusHandler(const XFocusChangeEvent &e)
   
   otk::EventHandler::focusHandler(e);
 
-  frame->focus();
   _focused = true;
+  frame->adjustFocus();
 
   openbox->setFocusedClient(this);
 }
@@ -1729,26 +1734,29 @@ void Client::unfocusHandler(const XFocusChangeEvent &e)
   
   otk::EventHandler::unfocusHandler(e);
 
-  frame->unfocus();
   _focused = false;
+  frame->adjustFocus();
 
   if (openbox->focusedClient() == this)
     openbox->setFocusedClient(0);
 }
 
 
-void Client::configureRequestHandler(const XConfigureRequestEvent &e)
+void Client::configureRequestHandler(const XConfigureRequestEvent &ec)
 {
 #ifdef    DEBUG
-  printf("ConfigureRequest for 0x%lx\n", e.window);
+  printf("ConfigureRequest for 0x%lx\n", ec.window);
 #endif // DEBUG
   
-  otk::EventHandler::configureRequestHandler(e);
+  otk::EventHandler::configureRequestHandler(ec);
 
   // compress these
+  XConfigureRequestEvent e = ec;
   XEvent ev;
   while (XCheckTypedWindowEvent(**otk::display, window(), ConfigureRequest,
                                 &ev)) {
+    // XXX if this causes bad things.. we can compress config req's with the
+    //     same mask.
     e.value_mask |= ev.xconfigurerequest.value_mask;
     if (ev.xconfigurerequest.value_mask & CWX)
       e.x = ev.xconfigurerequest.x;
index c17431a556fe476fb81b47f190ef7c0c7fe00e90..6e11ed8c27ead0e191ca9b0c8573e8dd797b17fa 100644 (file)
@@ -8,8 +8,6 @@
 */
 
 #include "screen.hh"
-#include "widgetbase.hh"
-#include "otk/point.hh"
 #include "otk/strut.hh"
 #include "otk/rect.hh"
 #include "otk/eventhandler.hh"
@@ -56,7 +54,7 @@ struct MwmHints {
   class' member variables and call whatever is nessary to complete the
   change (such as causing a redraw of the titlebar after the title is changed).
 */
-class Client : public otk::EventHandler, public WidgetBase {
+class Client : public otk::EventHandler {
 public:
 
   //! The frame window which decorates around the client window
@@ -229,7 +227,7 @@ private:
     For example, with xterms, this value it the number of characters being
     displayed in the terminal, instead of the number of pixels.
   */
-  otk::Point   _logical_size;
+  otk::Size   _logical_size;
 
   //! Width of the border on the window.
   /*!
@@ -253,20 +251,20 @@ private:
   /*!
     If the min is > the max, then the window is not resizable
   */
-  otk::Point _min_size;
+  otk::Size _min_size;
   //! The maximum size of the client window
   /*!
     If the min is > the max, then the window is not resizable
   */
-  otk::Point _max_size;
+  otk::Size _max_size;
   //! The size of increments to resize the client window by
-  otk::Point _size_inc;
+  otk::Size _size_inc;
   //! The base size of the client window
   /*!
     This value should be subtracted from the window's actual size when
     displaying its size to the user, or working with its min/max size
   */
-  otk::Point _base_size;
+  otk::Size _base_size;
 
   //! Window decoration and functionality hints
   MwmHints _mwmhints;
@@ -481,8 +479,8 @@ private:
     The x and y coordinates must both be sepcified together, or they will have
     no effect. When they are specified, the anchor is ignored.
   */
-  void internal_resize(Corner anchor, int w, int h, bool user = true,
-                       int x = INT_MIN, int y = INT_MIN);
+  void internal_resize(Corner anchor, unsigned int w, unsigned int h,
+                       bool user = true, int x = INT_MIN, int y = INT_MIN);
 
   //! Attempts to find and return a modal child of this window, recursively.
   Client *findModalChild(Client *skip = 0) const;
@@ -629,7 +627,7 @@ BB    @param window The window id that the Client class should handle
     For example, with xterms, this value it the number of characters being
     displayed in the terminal, instead of the number of pixels.
   */
-  const otk::Point &logicalSize() const { return _logical_size; }
+  const otk::Size &logicalSize() const { return _logical_size; }
 
   //! Returns the position and size of the client relative to the root window
   inline const otk::Rect &area() const { return _area; }
@@ -653,7 +651,7 @@ BB    @param window The window id that the Client class should handle
     @param w The width component of the new size for the client.
     @param h The height component of the new size for the client.
   */
-  void resize(Corner anchor, int w, int h);
+  void resize(Corner anchor, unsigned int w, unsigned int h);
 
   //! Reapplies the maximized state to the window
   /*!
index 57b338c8905743d279fd3579657d3f6359e279d6..5e9d852030fcc2b60f1be52202334d66a2dac867 100644 (file)
@@ -10,336 +10,387 @@ extern "C" {
 #endif // SHAPE
 }
 
-#include "openbox.hh"
 #include "frame.hh"
 #include "client.hh"
-#include "python.hh"
-#include "bindings.hh"
+#include "openbox.hh"
 #include "otk/display.hh"
 
 #include <string>
+#include <cassert>
 
 namespace ob {
 
 const long Frame::event_mask;
 
-Frame::Frame(Client *client, otk::RenderStyle *style)
-  : otk::Widget(openbox, style, Horizontal, 0, 1, true),
-    WidgetBase(WidgetBase::Type_Frame),
-    _client(client),
-    _screen(otk::display->screenInfo(client->screen())),
-    _plate(this, WidgetBase::Type_Plate),
-    _titlebar(this, WidgetBase::Type_Titlebar),
-    _button_close(&_titlebar, WidgetBase::Type_CloseButton, client),
-    _button_iconify(&_titlebar, WidgetBase::Type_IconifyButton, client),
-    _button_max(&_titlebar, WidgetBase::Type_MaximizeButton, client),
-    _button_alldesk(&_titlebar, WidgetBase::Type_AllDesktopsButton, client),
-    _label(&_titlebar, WidgetBase::Type_Label),
-    _handle(this, WidgetBase::Type_Handle),
-    _grip_left(&_handle, WidgetBase::Type_LeftGrip, client),
-    _grip_right(&_handle, WidgetBase::Type_RightGrip, client),
-    _decorations(client->decorations())
+Window createWindow(const otk::ScreenInfo *info, Window parent, 
+                    unsigned long mask, XSetWindowAttributes *attrib)
 {
-  assert(client);
-  assert(style);
-
-  XSelectInput(**otk::display, _window, Frame::event_mask);
-
-  _grip_left.setCursor(openbox->cursors().ll_angle);
-  _grip_right.setCursor(openbox->cursors().lr_angle);
-  
-  _label.setText(_client->title());
+  return XCreateWindow(**otk::display, parent, 0, 0, 1, 1, 0,
+                       info->depth(), InputOutput, info->visual(),
+                       mask, attrib);
+                       
+}
 
-  _style = 0;
-  setStyle(style);
+Frame::Frame(Client *client)
+  : _client(client),
+    _visible(false),
+    _plate(0),
+    _title(0),
+    _label(0),
+    _handle(0),
+    _lgrip(0),
+    _rgrip(0),
+    _buttons(0),
+    _numbuttons(0),
+    _titleorder(0),
+    _frame_sur(0),
+    _title_sur(0),
+    _label_sur(0),
+    _handle_sur(0),
+    _grip_sur(0),
+    _buttons_sur(0)
+{
+  assert(client);
 
-  otk::Widget::unfocus(); // stuff starts out appearing focused in otk
-  
-  _plate.show(); // the other stuff is shown based on decor settings
+  XSetWindowAttributes attrib;
+  unsigned long mask;
+  const otk::ScreenInfo *info = otk::display->screenInfo(client->screen());
+
+  // create all of the decor windows (except title bar buttons)
+  mask = CWOverrideRedirect | CWEventMask;
+  attrib.event_mask = Frame::event_mask;
+  attrib.override_redirect = true;
+  _frame = createWindow(info, info->rootWindow(), mask, &attrib);
+
+  mask = 0;
+  _plate = createWindow(info, _frame, mask, &attrib);
+  mask = CWEventMask;
+  attrib.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
+                       ExposureMask);
+  _title = createWindow(info, _frame, mask, &attrib);
+  _label = createWindow(info, _title, mask, &attrib);
+  _handle = createWindow(info, _frame, mask, &attrib);
+  mask |= CWCursor;
+  attrib.cursor = openbox->cursors().ll_angle;
+  _lgrip = createWindow(info, _handle, mask, &attrib);
+  attrib.cursor = openbox->cursors().lr_angle;
+  _rgrip = createWindow(info, _handle, mask, &attrib);
+
+  // the other stuff is shown based on decor settings
+  XMapWindow(**otk::display, _plate);
+  XMapWindow(**otk::display, _lgrip);
+  XMapWindow(**otk::display, _rgrip);
+  XMapWindow(**otk::display, _label);
+
+  applyStyle(*otk::RenderStyle::style(_client->screen()));
+
+  // XXX load buttons
+  _numbuttons = 0;
+  _buttons = new Window[0];
+  _buttons_sur = new otk::Surface*[0];
+  _titleorder = new unsigned int[1];
+  _titleorder[0] = (unsigned)-1;
+
+  // register all of the windows with the event dispatcher
+  Window *w = allWindows();
+  for (unsigned int i = 0; w[i]; ++i)
+    openbox->registerHandler(w[i], this);
+  delete [] w;
 }
 
-
 Frame::~Frame()
 {
+  // unregister all of the windows with the event dispatcher
+  Window *w = allWindows();
+  for (unsigned int i = 0; w[i]; ++i)
+    openbox->clearHandler(w[i]);
+  delete [] w;
+
+  for (unsigned int i = 0; i < _numbuttons; ++i) {
+    XDestroyWindow(**otk::display, _buttons[i]);
+    delete _buttons_sur[i];
+  }
+  XDestroyWindow(**otk::display, _rgrip);
+  XDestroyWindow(**otk::display, _lgrip);
+  XDestroyWindow(**otk::display, _handle);
+  XDestroyWindow(**otk::display, _label);
+  XDestroyWindow(**otk::display, _title);
+  XDestroyWindow(**otk::display, _frame);
+
+  if (_frame_sur) delete _frame_sur;
+  if (_title_sur) delete _title_sur;
+  if (_label_sur) delete _label_sur;
+  if (_handle_sur) delete _handle_sur;
+  if (_grip_sur) delete _grip_sur;
+
+  delete [] _buttons;
+  delete [] _titleorder;
+  delete [] _buttons_sur;
 }
 
-
-void Frame::setTitle(const otk::ustring &text)
+void Frame::show()
 {
-  _label.setText(text);
-  _label.update();
+  if (!_visible) {
+    _visible = true;
+    XMapWindow(**otk::display, _frame);
+  }
 }
 
-
-void Frame::setStyle(otk::RenderStyle *style)
+void Frame::hide()
 {
-  assert(style);
-
-  // if a style was previously set, then 'replace' is true, cause we're
-  // replacing a style
-  bool replace = (_style);
-
-  otk::Widget::setStyle(style);
-
-  if (replace) {
-    // XXX: do shit here whatever
-  }
-  
-  _style = style;
-
-  setBorderColor(_style->frameBorderColor());
-
-  // if !replace, then adjust() will get called after the client is grabbed!
-  if (replace) {
-    // size/position everything
-    adjustSize();
-    adjustPosition();
+  if (_visible) {
+    _visible = false;
+    XUnmapWindow(**otk::display, _frame);
   }
 }
 
+MouseContext::MC Frame::mouseContext(Window win) const
+{
+  if (win == _frame)  return MouseContext::Frame;
+  if (win == _title ||
+      win == _label)  return MouseContext::Titlebar;
+  if (win == _handle) return MouseContext::Handle;
+  if (win == _plate)  return MouseContext::Window;
+  if (win == _lgrip ||
+      win == _rgrip)  return MouseContext::Grip;
+  return (MouseContext::MC) -1;
+}
 
-void Frame::focus()
+Window *Frame::allWindows() const
 {
-  otk::Widget::focus();
-  update();
+  Window *w = new Window[7 + _numbuttons + 1];
+  unsigned int i = 0;
+  w[i++] = _frame;
+  w[i++] = _plate;
+  w[i++] = _title;
+  w[i++] = _label;
+  w[i++] = _handle;
+  w[i++] = _lgrip;
+  w[i++] = _rgrip;
+  for (unsigned int j = 0; j < _numbuttons; ++j)
+    w[j + i++] = _buttons[j];
+  w[i] = 0;
+  return w;
 }
 
+void Frame::applyStyle(const otk::RenderStyle &style)
+{
+  // set static border colors
+  XSetWindowBorder(**otk::display, _frame, style.frameBorderColor()->pixel());
+  XSetWindowBorder(**otk::display, _title, style.frameBorderColor()->pixel());
+  XSetWindowBorder(**otk::display, _handle, style.frameBorderColor()->pixel());
+  XSetWindowBorder(**otk::display, _lgrip, style.frameBorderColor()->pixel());
+  XSetWindowBorder(**otk::display, _rgrip, style.frameBorderColor()->pixel());
+
+  // size all the fixed-size elements
+  geom.font_height = style.labelFont()->height();
+  if (geom.font_height < 1) geom.font_height = 1;
+  geom.button_size = geom.font_height - 2;
+  if (geom.button_size < 1) geom.button_size = 1;
+  geom.handle_height = style.handleWidth();
+  if (geom.handle_height < 1) geom.handle_height = 1;
+  geom.bevel = style.bevelWidth();
+  
+  XResizeWindow(**otk::display, _lgrip, geom.grip_width(), geom.handle_height);
+  XResizeWindow(**otk::display, _rgrip, geom.grip_width(), geom.handle_height);
+  
+  for (unsigned int i = 0; i < _numbuttons; ++i)
+    XResizeWindow(**otk::display, _buttons[i],
+                  geom.button_size, geom.button_size);
+}
 
-void Frame::unfocus()
+void Frame::styleChanged(const otk::RenderStyle &style)
 {
-  otk::Widget::unfocus();
-  update();
+  applyStyle(style);
+  
+  // size/position everything
+  adjustSize();
+  adjustPosition();
 }
 
+void Frame::adjustFocus()
+{
+  // XXX optimizations later...
+  adjustSize();
+}
 
-void Frame::adjust()
+void Frame::adjustTitle()
 {
-  // the party all happens in adjustSize
+  // XXX optimizations later...
+  adjustSize();
 }
 
+static void render(int screen, const otk::Size &size, Window win,
+                   otk::Surface **surface,
+                   const otk::RenderTexture &texture)
+{
+  otk::Surface *s = new otk::Surface(screen, size);
+  otk::display->renderControl(screen)->drawBackground(*s, texture);
+  XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap());
+  XClearWindow(**otk::display, win);
+  if (*surface) delete *surface;
+  *surface = s;
+}
 
 void Frame::adjustSize()
 {
-  // XXX: only if not overridden or something!!! MORE LOGIC HERE!!
-  _decorations = _client->decorations();
-
-  // true/false for whether to show each element of the titlebar
-  bool tit_i = false, tit_m = false, tit_s = false, tit_c = false;
-  int width;   // the width of the client and its border
-  int bwidth;  // width to make borders
-  int cbwidth; // width of the inner client border
-  int fontheight = _style->labelFont()->height(); // height of the font
-  int butsize = fontheight - 2; // width and height of the titlebar buttons
-  const int bevel = _style->bevelWidth();
-  
-  if (_decorations & Client::Decor_Border) {
-    bwidth = _style->frameBorderWidth();
-    cbwidth = _style->clientBorderWidth();
-  } else
-    bwidth = cbwidth = 0;
+  Client::DecorationFlags decorations = _client->decorations();
+  const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
+
+  if (decorations & Client::Decor_Border) {
+    geom.bwidth = style->frameBorderWidth();
+    geom.cbwidth = style->clientBorderWidth();
+  } else {
+    geom.bwidth = geom.cbwidth = 0;
+  }
   _innersize.left = _innersize.top = _innersize.bottom = _innersize.right =
-    cbwidth;
-  width = _client->area().width() + cbwidth * 2;
+    geom.cbwidth;
+  geom.width = _client->area().width() + geom.cbwidth * 2;
+  assert(geom.width > 0);
+
+  // set border widths
+  XSetWindowBorderWidth(**otk::display, _plate, geom.cbwidth);
+  XSetWindowBorderWidth(**otk::display, _frame, geom.bwidth);
+  XSetWindowBorderWidth(**otk::display, _title, geom.bwidth);
+  XSetWindowBorderWidth(**otk::display, _handle, geom.bwidth);
+  XSetWindowBorderWidth(**otk::display, _lgrip, geom.bwidth);
+  XSetWindowBorderWidth(**otk::display, _rgrip, geom.bwidth);
+  
+  // position/size and map/unmap all the windows
 
-  _plate.setBorderWidth(cbwidth);
+  if (decorations & Client::Decor_Titlebar) {
+    XMoveResizeWindow(**otk::display, _title, -geom.bwidth, -geom.bwidth,
+                      geom.width, geom.title_height());
+    _innersize.top += geom.title_height() + geom.bwidth;
+    XMapWindow(**otk::display, _title);
 
-  setBorderWidth(bwidth);
-  _titlebar.setBorderWidth(bwidth);
-  _grip_left.setBorderWidth(bwidth);
-  _grip_right.setBorderWidth(bwidth);
-  _handle.setBorderWidth(bwidth);
-  
-  if (_decorations & Client::Decor_Titlebar) {
-    // set the titlebar size
-    _titlebar.setGeometry(-bwidth,
-                          -bwidth,
-                          width,
-                          _style->labelFont()->height() + (bevel * 2));
-    _innersize.top += _titlebar.height() + bwidth;
-
-    // set the label size
-    _label.setGeometry(0, bevel, width, fontheight);
-    // set the buttons sizes
-    if (_decorations & Client::Decor_Iconify)
-      _button_iconify.setGeometry(0, bevel + 1, butsize, butsize);
-    if (_decorations & Client::Decor_Maximize)
-      _button_max.setGeometry(0, bevel + 1, butsize, butsize);
-    if (_decorations & Client::Decor_AllDesktops)
-      _button_alldesk.setGeometry(0, bevel + 1, butsize, butsize);
-    if (_decorations & Client::Decor_Close)
-      _button_close.setGeometry(0, bevel + 1, butsize, butsize);
-
-    // separation between titlebar elements
-    const int sep = bevel + 1;
-
-    otk::ustring layout;
-    if (!python_get_string("TITLEBAR_LAYOUT", &layout))
-      layout = "ILMC";
-
-    // this code ensures that the string only has one of each possible
-    // letter, all of the letters are valid, and L exists somewhere in the
-    // string!
-    bool tit_l = false;
+    // layout the title bar elements
+    layoutTitle();
+  } else
+    XUnmapWindow(**otk::display, _title);
+
+  if (decorations & Client::Decor_Handle) {
+    geom.handle_y = _innersize.top + _client->area().height() + geom.cbwidth;
+    XMoveResizeWindow(**otk::display, _handle, -geom.bwidth, geom.handle_y,
+                      geom.width, geom.handle_height);
+    XMoveWindow(**otk::display, _lgrip, -geom.bwidth, -geom.bwidth);
+    XMoveWindow(**otk::display, _rgrip,
+                -geom.bwidth + geom.width - geom.grip_width(),
+                -geom.bwidth);
+    _innersize.bottom += geom.handle_height + geom.bwidth;
+    XMapWindow(**otk::display, _handle);
+  } else
+    XUnmapWindow(**otk::display, _handle);
   
-    for (std::string::size_type i = 0; i < layout.size(); ++i) {
-      switch (layout[i]) {
-      case 'i':
-      case 'I':
-        if (!tit_i && (_decorations & Client::Decor_Iconify)) {
-          tit_i = true;
-          continue;
-        }
-        break;
-      case 'l':
-      case 'L':
-        if (!tit_l) {
-          tit_l = true;
-          continue;
-        }
-        break;
-      case 'm':
-      case 'M':
-        if (!tit_m && (_decorations & Client::Decor_Maximize)) {
-          tit_m = true;
-          continue;
-        }
-        break;
-      case 'd':
-      case 'D':
-        if (!tit_s && (_decorations & Client::Decor_AllDesktops)) {
-          tit_s = true;
-          continue;
-        }
-        break;
-      case 'c':
-      case 'C':
-        if (!tit_c && (_decorations & Client::Decor_Close)) {
-          tit_c = true;
-          continue;
-        }
-        break;
-      }
-      // if we get here then we don't want the letter, kill it
-      layout.erase(i--, 1);
-    }
-    if (!tit_l)
-      layout += "L";
+  XResizeWindow(**otk::display, _frame, geom.width,
+                (_client->shaded() ? geom.title_height() :
+                 _innersize.top + _innersize.bottom +
+                 _client->area().height()));
+
+  XMoveResizeWindow(**otk::display, _plate,
+                    _innersize.left - geom.cbwidth,
+                    _innersize.top - geom.cbwidth,
+                    _client->area().width(), _client->area().height());
+
+  _size.left   = _innersize.left + geom.bwidth;
+  _size.right  = _innersize.right + geom.bwidth;
+  _size.top    = _innersize.top + geom.bwidth;
+  _size.bottom = _innersize.bottom + geom.bwidth;
+
+  _area = otk::Rect(_area.position(), otk::Size(_client->area().width() +
+                                                _size.left + _size.right,
+                                                _client->area().height() +
+                                                _size.top + _size.bottom));
+
+  // render all the elements
+  int screen = _client->screen();
+  bool focus = _client->focused();
+  if (decorations & Client::Decor_Titlebar) {
+    render(screen, otk::Size(geom.width, geom.title_height()), _title,
+           &_title_sur, *(focus ? style->titlebarFocusBackground() :
+                          style->titlebarUnfocusBackground()));
     
-    // the size of the label. this ASSUMES the layout has only buttons other
-    // that the ONE LABEL!!
-    // adds an extra sep so that there's a space on either side of the
-    // titlebar.. note: x = sep, below.
-    int lwidth = width - sep * 2 -
-      (butsize + sep) * (layout.size() - 1);
-    // quick sanity check for really small windows. if this is needed, its
-    // obviously not going to be displayed right...
-    // XXX: maybe we should make this look better somehow? constraints?
-    if (lwidth <= 0) lwidth = 1;
-    _label.setWidth(lwidth);
-
-    int x = sep;
-    for (std::string::size_type i = 0, len = layout.size(); i < len; ++i) {
-      switch (layout[i]) {
-      case 'i':
-      case 'I':
-        _button_iconify.move(x, _button_iconify.rect().y());
-        x += _button_iconify.width();
-        break;
-      case 'l':
-      case 'L':
-        _label.move(x, _label.rect().y());
-        x += _label.width();
-        break;
-      case 'm':
-      case 'M':
-        _button_max.move(x, _button_max.rect().y());
-        x += _button_max.width();
-        break;
-      case 'd':
-      case 'D':
-        _button_alldesk.move(x, _button_alldesk.rect().y());
-        x += _button_alldesk.width();
-        break;
-      case 'c':
-      case 'C':
-        _button_close.move(x, _button_close.rect().y());
-        x += _button_close.width();
-        break;
-      default:
-        assert(false); // the layout string is invalid!
-      }
-      x += sep;
-    }
-  }
-
-  if (_decorations & Client::Decor_Handle) {
-    _handle.setGeometry(-bwidth,
-                        _innersize.top + _client->area().height() + cbwidth,
-                        width, _style->handleWidth());
-    _grip_left.setGeometry(-bwidth,
-                           -bwidth,
-                           butsize * 2,
-                           _handle.height());
-    _grip_right.setGeometry(((_handle.rect().right() + 1) -
-                             butsize * 2),
-                            -bwidth,
-                            butsize * 2,
-                            _handle.height());
-    _innersize.bottom += _handle.height() + bwidth;
+    renderLabel();
   }
-  
 
-  // position/size all the windows
-
-  if (_client->shaded())
-    resize(_innersize.left + _innersize.right + _client->area().width(),
-           _titlebar.height());
-  else
-    resize(_innersize.left + _innersize.right + _client->area().width(),
-           _innersize.top + _innersize.bottom + _client->area().height());
-
-  _plate.setGeometry(_innersize.left - cbwidth, _innersize.top - cbwidth,
-                     _client->area().width(), _client->area().height());
-
-  // map/unmap all the windows
-  if (_decorations & Client::Decor_Titlebar) {
-    _label.show();
-    if (tit_i)
-      _button_iconify.show();
-    else
-      _button_iconify.hide();
-    if (tit_m)
-      _button_max.show();
-    else
-      _button_max.hide();
-    if (tit_s)
-      _button_alldesk.show();
-    else
-      _button_alldesk.hide();
-    if (tit_c)
-      _button_close.show();
-    else
-      _button_close.hide();
-    _titlebar.show();
-  } else {
-    _titlebar.hide(true);
+  if (decorations & Client::Decor_Handle) {
+    render(screen, otk::Size(geom.width, geom.handle_height), _handle,
+           &_handle_sur, *(focus ? style->handleFocusBackground() :
+                           style->handleUnfocusBackground()));
+    render(screen, otk::Size(geom.grip_width(), geom.handle_height), _lgrip,
+           &_grip_sur, *(focus ? style->gripFocusBackground() :
+                         style->gripUnfocusBackground()));
+    XSetWindowBackgroundPixmap(**otk::display, _rgrip, _grip_sur->pixmap());
+    XClearWindow(**otk::display, _rgrip);
   }
 
-  if (_decorations & Client::Decor_Handle)
-    _handle.show(true);
-  else
-    _handle.hide(true);
+  XSetWindowBorder(**otk::display, _plate,
+                   focus ? style->clientBorderFocusColor()->pixel() :
+                   style->clientBorderUnfocusColor()->pixel());
   
-  _size.left   = _innersize.left + bwidth;
-  _size.right  = _innersize.right + bwidth;
-  _size.top    = _innersize.top + bwidth;
-  _size.bottom = _innersize.bottom + bwidth;
-
   adjustShape();
+}
 
-  update();
+void Frame::renderLabel()
+{
+  const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
+  const otk::RenderControl *control =
+    otk::display->renderControl(_client->screen());
+  const otk::Font *font = style->labelFont();
+
+  otk::Surface *s = new otk::Surface(_client->screen(),
+                                     otk::Size(geom.label_width,
+                                               geom.label_height()));
+  control->drawBackground(*s, *(_client->focused() ?
+                                style->labelFocusBackground() :
+                                style->labelUnfocusBackground()));
+
+  otk::ustring t = _client->title(); // the actual text to draw
+  int x = geom.bevel;                // x coord for the text
+
+  if ((unsigned)x * 2 > geom.label_width) return; // no room at all
+
+  // find a string that will fit inside the area for text
+  otk::ustring::size_type text_len = t.size();
+  unsigned int length;
+  unsigned int maxsize = geom.label_width - geom.bevel * 2;
+      
+  do {
+    t.resize(text_len);
+    length = font->measureString(t);
+  } while (length > maxsize && text_len-- > 0);
+
+  if (text_len <= 0) return; // won't fit anything
+
+  // justify the text
+  switch (style->labelTextJustify()) {
+  case otk::RenderStyle::RightBottomJustify:
+    x += maxsize - length;
+    break;
+  case otk::RenderStyle::CenterJustify:
+    x += (maxsize - length) / 2;
+    break;
+  case otk::RenderStyle::LeftTopJustify:
+    break;
+  }
+  control->drawString(*s, *font, x, 0,
+                      *(_client->focused() ? style->textFocusColor() :
+                        style->textUnfocusColor()), t);
+
+  XSetWindowBackgroundPixmap(**otk::display, _label, s->pixmap());
+  XClearWindow(**otk::display, _label);
+  if (_label_sur) delete _label_sur;
+  _label_sur = s;
 }
 
+void Frame::layoutTitle()
+{
+  geom.label_width = geom.width - geom.bevel * 2;
+  if (geom.label_width < 1) geom.label_width = 1;
+  XMoveResizeWindow(**otk::display, _label, geom.bevel, geom.bevel,
+                    geom.label_width, geom.font_height);
+}
 
 void Frame::adjustPosition()
 {
@@ -347,25 +398,25 @@ void Frame::adjustPosition()
   x = _client->area().x();
   y = _client->area().y();
   clientGravity(x, y);
-  move(x, y);
+  XMoveWindow(**otk::display, _frame, x, y);
+  _area = otk::Rect(otk::Point(x, y), _area.size());
 }
 
 
 void Frame::adjustShape()
 {
 #ifdef SHAPE
-  int bwidth = (_decorations & Client::Decor_Border) ?
-    _style->frameBorderWidth() : 0;
+  Client::DecorationFlags decorations = _client->decorations();
   
   if (!_client->shaped()) {
     // clear the shape on the frame window
-    XShapeCombineMask(**otk::display, _window, ShapeBounding,
+    XShapeCombineMask(**otk::display, _frame, ShapeBounding,
                       _innersize.left,
                       _innersize.top,
                       None, ShapeSet);
   } else {
     // make the frame's shape match the clients
-    XShapeCombineShape(**otk::display, _window, ShapeBounding,
+    XShapeCombineShape(**otk::display, _frame, ShapeBounding,
                        _innersize.left,
                        _innersize.top,
                        _client->window(), ShapeBounding, ShapeSet);
@@ -373,23 +424,23 @@ void Frame::adjustShape()
     int num = 0;
     XRectangle xrect[2];
 
-    if (_decorations & Client::Decor_Titlebar) {
-      xrect[0].x = _titlebar.rect().x();
-      xrect[0].y = _titlebar.rect().y();
-      xrect[0].width = _titlebar.width() + bwidth * 2; // XXX: this is useless once the widget handles borders!
-      xrect[0].height = _titlebar.height() + bwidth * 2;
+    if (decorations & Client::Decor_Titlebar) {
+      xrect[0].x = -geom.bevel;
+      xrect[0].y = -geom.bevel;
+      xrect[0].width = geom.width + geom.bwidth * 2;
+      xrect[0].height = geom.title_height() + geom.bwidth * 2;
       ++num;
     }
 
-    if (_decorations & Client::Decor_Handle) {
-      xrect[1].x = _handle.rect().x();
-      xrect[1].y = _handle.rect().y();
-      xrect[1].width = _handle.width() + bwidth * 2; // XXX: this is useless once the widget handles borders!
-      xrect[1].height = _handle.height() + bwidth * 2;
+    if (decorations & Client::Decor_Handle) {
+      xrect[1].x = -geom.bevel;
+      xrect[1].y = geom.handle_y;
+      xrect[1].width = geom.width + geom.bwidth * 2;
+      xrect[1].height = geom.handle_height + geom.bwidth * 2;
       ++num;
     }
 
-    XShapeCombineRectangles(**otk::display, window(),
+    XShapeCombineRectangles(**otk::display, _frame,
                             ShapeBounding, 0, 0, xrect, num,
                             ShapeUnion, Unsorted);
   }
@@ -399,15 +450,15 @@ void Frame::adjustShape()
 
 void Frame::adjustState()
 {
-  _button_alldesk.update();
-  _button_max.update();
+// XXX  _button_alldesk.update();
+// XXX  _button_max.update();
 }
 
 
 void Frame::grabClient()
 {
   // reparent the client to the frame
-  XReparentWindow(**otk::display, _client->window(), _plate.window(), 0, 0);
+  XReparentWindow(**otk::display, _client->window(), _plate, 0, 0);
   /*
     When reparenting the client window, it is usually not mapped yet, since
     this occurs from a MapRequest. However, in the case where Openbox is
@@ -420,7 +471,7 @@ void Frame::grabClient()
     _client->ignore_unmaps += 2;
 
   // select the event mask on the client's parent (to receive config/map req's)
-  XSelectInput(**otk::display, _plate.window(), SubstructureRedirectMask);
+  XSelectInput(**otk::display, _plate, SubstructureRedirectMask);
 
   // map the client so it maps when the frame does
   XMapWindow(**otk::display, _client->window());
@@ -444,7 +495,7 @@ void Frame::releaseClient()
     // according to the ICCCM - if the client doesn't reparent itself, then we
     // will reparent the window to root for them
     XReparentWindow(**otk::display, _client->window(),
-                    _screen->rootWindow(),
+                    otk::display->screenInfo(_client->screen())->rootWindow(),
                     _client->area().x(), _client->area().y());
   }
 }
index b2cc2d16419c153da873adb7f678b2f7ca3c0240..c587c112ad2e863e4758a60f0cf9e72ee9be3a23 100644 (file)
@@ -9,28 +9,43 @@ extern "C" {
 #include <X11/Xlib.h>
 }
 
-#include "client.hh"
-#include "backgroundwidget.hh"
-#include "labelwidget.hh"
-#include "buttonwidget.hh"
+#include "python.hh"
 #include "otk/strut.hh"
 #include "otk/rect.hh"
-#include "otk/screeninfo.hh"
 #include "otk/renderstyle.hh"
-#include "otk/widget.hh"
 #include "otk/ustring.hh"
+#include "otk/surface.hh"
+#include "otk/eventhandler.hh"
 
 #include <string>
 
 namespace ob {
 
+class Client;
+
+//! Varius geometry settings in the frame decorations
+struct FrameGeometry {
+  unsigned int width; // title and handle
+  unsigned int font_height;
+  unsigned int title_height() { return font_height + bevel*2; }
+  unsigned int label_width;
+  unsigned int label_height() { return font_height; }
+  unsigned int handle_height; // static, from the style
+  int handle_y;
+  unsigned int button_size;   // static, from the style
+  unsigned  grip_width() { return button_size * 2; }
+  unsigned  bevel;         // static, from the style
+  unsigned  bwidth;  // frame elements' border width
+  unsigned  cbwidth; // client border width
+};
+
 //! Holds and decorates a frame around an Client (client window)
 /*!
   The frame is responsible for calling XSelectInput on the client window's new
   parent with the SubstructureRedirectMask so that structure events for the
   client are sent to the window manager.
 */
-class Frame : public otk::Widget, public WidgetBase {
+class Frame : public otk::StyleNotify, public otk::EventHandler {
 public:
 
   //! The event mask to grab on frame windows
@@ -38,7 +53,6 @@ public:
    
 private:
   Client *_client;
-  const otk::ScreenInfo *_screen;
 
   //! The size of the frame on each side of the client window
   otk::Strut _size;
@@ -46,32 +60,45 @@ private:
   //! The size of the frame on each side of the client window inside the border
   otk::Strut _innersize;
 
+  //! The position and size of the entire frame (including borders)
+  otk::Rect _area;
+
+  bool _visible;
+  
   // decoration windows
-  BackgroundWidget  _plate;   // sits entirely under the client window
-  BackgroundWidget  _titlebar;
-  ButtonWidget      _button_close;
-  ButtonWidget      _button_iconify;
-  ButtonWidget      _button_max;
-  ButtonWidget      _button_alldesk;
-  LabelWidget       _label;
-  BackgroundWidget  _handle;
-  ButtonWidget      _grip_left;
-  ButtonWidget      _grip_right;
-
-  //! The decorations to display on the window.
-  /*!
-    This is by default the same value as in the Client::decorations, but it
-    is duplicated here so that it can be overridden per-window by the user.
-  */
-  Client::DecorationFlags _decorations;
+  Window  _frame;   // sits under everything
+  Window  _plate;   // sits entirely under the client window
+  Window  _title;   // the titlebar
+  Window  _label;   // the section of the titlebar which shows the window name
+  Window  _handle;  // bottom bar
+  Window  _lgrip;   // lefthand resize grab on the handle
+  Window  _rgrip;   // righthand resize grab on the handle
+  Window *_buttons; // all of the titlebar buttons
+  unsigned int  _numbuttons; // number of buttons, size of _buttons array
+  unsigned int *_titleorder; // order of the buttons and the label (always
+                             // holds '_numbuttons + 1' elements (for the
+                             // label, which is coded as '-1')
+
+  // surfaces for each 
+  otk::Surface  *_frame_sur;
+  otk::Surface  *_title_sur;
+  otk::Surface  *_label_sur;
+  otk::Surface  *_handle_sur;
+  otk::Surface  *_grip_sur;
+  otk::Surface **_buttons_sur;
+
+  FrameGeometry geom;
+  
+  void applyStyle(const otk::RenderStyle &style);
+  void layoutTitle();
+  void renderLabel();
 
 public:
-  //! Constructs an Frame object, and reparents the client to itself
+  //! Constructs an Frame object for a client
   /*!
-    @param client The client window which will be decorated by the new Frame
-    @param style The style to use to decorate the frame
+    @param client The client which will be decorated by the new Frame
   */
-  Frame(Client *client, otk::RenderStyle *style);
+  Frame(Client *client);
   //! Destroys the Frame object
   virtual ~Frame();
 
@@ -79,18 +106,8 @@ public:
   const otk::Strut& size() const { return _size; }
   
   //! Set the style to decorate the frame with
-  virtual void setStyle(otk::RenderStyle *style);
+  virtual void styleChanged(const otk::RenderStyle &style);
 
-  //! Empty overridden method to prevent automatic alignment of children
-  virtual void adjust();
-  
-  //! Displays focused decorations
-  virtual void focus();
-  //! Displays unfocused decorations
-  virtual void unfocus();
-
-  void setTitle(const otk::ustring &text);
   //! Reparents the client window from the root window onto the frame
   void grabClient();
   //! Reparents the client window back to the root window
@@ -103,8 +120,10 @@ public:
   //! Shape the frame window to the client window
   void adjustShape();
   //! Update the frame to match the client's new state (for things like toggle
-  //! buttons)
+  //! buttons, focus, and the title) XXX break this up
   void adjustState();
+  void adjustFocus();
+  void adjustTitle();
 
   //! Applies gravity to the client's position to find where the frame should
   //! be positioned.
@@ -120,27 +139,32 @@ public:
   */
   void frameGravity(int &x, int &y);
 
-  //! Gets the window id of the frame's "plate" subelement
-  inline Window plate() const { return _plate.window(); }
-  //! Gets the window id of the frame's "titlebar" subelement
-  inline Window titlebar() const { return _titlebar.window(); }
-  //! Gets the window id of the frame's "label" subelement
-  inline Window label() const { return _label.window(); }
-  //! Gets the window id of the frame's "close button" subelement
-  inline Window button_close() const { return _button_close.window(); }
-  //! Gets the window id of the frame's "iconify button" subelement
-  inline Window button_iconify() const { return _button_iconify.window(); }
-  //! Gets the window id of the frame's "maximize button" subelement
-  inline Window button_max() const { return _button_max.window(); }
-  //! Gets the window id of the frame's "all desktops button" subelement
-  inline Window button_alldesk() const { return _button_alldesk.window(); }
-  //! Gets the window id of the frame's "handle" subelement
-  inline Window handle() const { return _handle.window(); }
-  //! Gets the window id of the frame's "left grip" subelement
-  inline Window grip_left() const { return _grip_left.window(); }
-  //! Gets the window id of the frame's "right grip" subelement
-  inline Window grip_right() const { return _grip_right.window(); }
+  //! The position and size of the frame window
+  inline const otk::Rect& area() const { return _area; }
+
+  //! Returns if the frame is visible
+  inline bool visible() const { return _visible; }
+
+  //! Shows the frame
+  void show();
+  //! Hides the frame
+  void hide();
+
+  //! Returns the MouseContext for the given window id
+  /*!
+    Returns '-1' if no valid mouse context exists in the frame for the given
+    id.
+  */
+  ob::MouseContext::MC mouseContext(Window win) const;
+
+  //! Gets the window id of the frame's base top-level parent
+  inline Window window() const { return _frame; }
+  //! Gets the window id of the client's parent window
+  inline Window plate() const { return _plate; }
 
+  //! Returns a null terminated array of the window ids that make up the
+  //! frame's decorations.
+  Window *allWindows() const;
 };
 
 }
diff --git a/src/labelwidget.cc b/src/labelwidget.cc
deleted file mode 100644 (file)
index 020e8b7..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#ifdef HAVE_CONFIG_H
-# include "../config.h"
-#endif
-
-#include "otk/screeninfo.hh"
-#include "otk/display.hh"
-#include "labelwidget.hh"
-
-namespace ob {
-
-LabelWidget::LabelWidget(otk::Widget *parent, WidgetBase::WidgetType type)
-  : otk::Widget(parent),
-    WidgetBase(type)
-{
-}
-
-
-LabelWidget::~LabelWidget()
-{
-}
-
-
-void LabelWidget::setText(const otk::ustring &text)
-{
-  _text = text;
-  _dirty = true;
-}
-
-
-void LabelWidget::setTextures()
-{
-  if (_focused) {
-    setTexture(_style->labelFocusBackground());
-    _text_color = _style->textFocusColor();
-  } else {
-    setTexture(_style->labelUnfocusBackground());
-    _text_color = _style->textUnfocusColor();
-  }
-}
-
-
-void LabelWidget::setStyle(otk::RenderStyle *style)
-{
-  otk::Widget::setStyle(style);
-  setTextures();
-  _font = style->labelFont();
-  _sidemargin = style->bevelWidth() * 2;
-  _justify = style->labelTextJustify();
-
-  assert(_font);
-}
-
-
-void LabelWidget::focus()
-{
-  otk::Widget::focus();
-  setTextures();
-}
-
-
-void LabelWidget::unfocus()
-{
-  otk::Widget::unfocus();
-  setTextures();
-}
-
-
-void LabelWidget::renderForeground()
-{
-  bool draw = _dirty;
-
-  otk::Widget::renderForeground();
-
-  if (draw) {
-    otk::ustring t = _text;
-    int x = _sidemargin;    // x coord for the text
-
-    // find a string that will fit inside the area for text
-    int max_length = width() - _sidemargin * 2;
-    if (max_length <= 0) {
-      t = ""; // can't fit anything
-    } else {
-      size_t text_len = t.size();
-      int length;
-      
-      do {
-        t.resize(text_len);
-        length = _font->measureString(t);
-      } while (length > max_length && text_len-- > 0);
-
-      // justify the text
-      switch (_justify) {
-      case otk::RenderStyle::RightJustify:
-        x += max_length - length;
-        break;
-      case otk::RenderStyle::CenterJustify:
-        x += (max_length - length) / 2;
-        break;
-      case otk::RenderStyle::LeftJustify:
-        break;
-      }
-    }
-
-    otk::display->renderControl(_screen)->drawString
-      (*_surface, *_font, x, 0, *_text_color, t);
-  }
-}
-
-
-void LabelWidget::adjust()
-{
-  // nothing to adjust. no children.
-}
-
-}
diff --git a/src/labelwidget.hh b/src/labelwidget.hh
deleted file mode 100644 (file)
index 81d350c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef   __oblabelwidget_hh
-#define   __oblabelwidget_hh
-
-#include "widgetbase.hh"
-#include "otk/widget.hh"
-#include "otk/font.hh"
-#include "otk/renderstyle.hh"
-#include "otk/ustring.hh"
-
-namespace ob {
-
-class LabelWidget : public otk::Widget, public WidgetBase
-{
-private:
-  void setTextures();
-  const otk::Font *_font;
-  otk::RenderColor *_text_color;
-  int _sidemargin;
-  otk::RenderStyle::TextJustify _justify;
-  otk::ustring _text;
-  
-public:
-  LabelWidget(otk::Widget *parent, WidgetBase::WidgetType type);
-  virtual ~LabelWidget();
-
-  virtual void setStyle(otk::RenderStyle *style);
-
-  virtual void adjust();
-
-  virtual void focus();
-  virtual void unfocus();
-
-  virtual void renderForeground();
-
-  inline const otk::ustring &text() const { return _text; }
-  void setText(const otk::ustring &text);
-};
-
-}
-
-#endif // __oblabelwidget_hh
index de7767a2151c10594c5ad08771385f464667c63f..24b3278615bed12dfec0a3679567e103c6d0607e 100644 (file)
@@ -15,6 +15,7 @@
 #include "otk/property.hh"
 #include "otk/util.hh"
 #include "otk/rendercolor.hh"
+#include "otk/renderstyle.hh"
 
 extern "C" {
 #include <X11/cursorfont.h>
@@ -120,6 +121,7 @@ Openbox::Openbox(int argc, char **argv)
   while (waitpid(-1, NULL, WNOHANG) > 0);
 
   otk::RenderColor::initialize();
+  otk::RenderStyle::initialize();
   otk::Timer::initialize();
   otk::Property::initialize();
   _actions = new Actions();
@@ -180,7 +182,7 @@ Openbox::Openbox(int argc, char **argv)
   for (it = _screens.begin(); it != end; ++it) {
     (*it)->manageExisting();
   }
+  
   // grab any keys set up before the screens existed
   _bindings->grabKeys(true);
 
@@ -212,6 +214,7 @@ Openbox::~Openbox()
   //delete _display;
 
   otk::Timer::destroy();
+  otk::RenderStyle::destroy();
   otk::RenderColor::destroy();
 }
 
index 9ff1f2b7a14414ce24adbcb86d943edf8512f2b9..41cc6e4c9a3414d03d5849f573bf0dab7e4dfb05 100644 (file)
@@ -48,8 +48,7 @@ namespace ob {
 
 Screen::Screen(int screen)
   : WidgetBase(WidgetBase::Type_Root),
-    _number(screen),
-    _style(screen, "")
+    _number(screen)
 {
   assert(screen >= 0); assert(screen < ScreenCount(**otk::display));
   _info = otk::display->screenInfo(screen);
@@ -91,14 +90,15 @@ Screen::Screen(int screen)
   }
   _style.load(sconfig);
   */
-  otk::display->renderControl(_number)->drawRoot(*_style.rootColor());
+  otk::display->renderControl(_number)->
+    drawRoot(*otk::RenderStyle::style(_number)->rootColor());
 
   // set up notification of netwm support
   changeSupportedAtoms();
 
   // Set the netwm properties for geometry
-  unsigned long geometry[] = { _info->width(),
-                               _info->height() };
+  unsigned long geometry[] = { _info->size().width(),
+                               _info->size().height() };
   otk::Property::set(_info->rootWindow(),
                      otk::Property::atoms.net_desktop_geometry,
                      otk::Property::atoms.cardinal, geometry, 2);
@@ -237,9 +237,9 @@ void Screen::calcArea()
 #endif // XINERAMA
 */
   
-  _area.setRect(_strut.left, _strut.top,
-                _info->width() - (_strut.left + _strut.right),
-                _info->height() - (_strut.top + _strut.bottom));
+  _area = otk::Rect(_strut.left, _strut.top,
+                    _info->size().width() - (_strut.left + _strut.right),
+                    _info->size().height() - (_strut.top + _strut.bottom));
 
 /*
 #ifdef    XINERAMA
@@ -494,7 +494,7 @@ void Screen::manageWindow(Window window)
   XChangeSaveSet(**otk::display, window, SetModeInsert);
 
   // create the decoration frame for the client window
-  client->frame = new Frame(client, &_style);
+  client->frame = new Frame(client);
   // register the plate for events (map req's)
   // this involves removing itself from the handler list first, since it is
   // auto added to the list, being a widget. we won't get any events on the
@@ -503,17 +503,10 @@ void Screen::manageWindow(Window window)
   openbox->registerHandler(client->frame->plate(), client);
 
   // add to the wm's map
-  openbox->addClient(client->frame->window(), client);
-  openbox->addClient(client->frame->plate(), client);
-  openbox->addClient(client->frame->titlebar(), client);
-  openbox->addClient(client->frame->label(), client);
-  openbox->addClient(client->frame->button_max(), client);
-  openbox->addClient(client->frame->button_iconify(), client);
-  openbox->addClient(client->frame->button_alldesk(), client);
-  openbox->addClient(client->frame->button_close(), client);
-  openbox->addClient(client->frame->handle(), client);
-  openbox->addClient(client->frame->grip_left(), client);
-  openbox->addClient(client->frame->grip_right(), client);
+  Window *w = client->frame->allWindows();
+  for (unsigned int i = 0; w[i]; ++i)
+    openbox->addClient(w[i], client);
+  delete [] w;
 
   // reparent the client to the frame
   client->frame->grabClient();
@@ -573,17 +566,10 @@ void Screen::unmanageWindow(Client *client)
 
   // remove from the wm's map
   openbox->removeClient(client->window());
-  openbox->removeClient(frame->window());
-  openbox->removeClient(frame->plate());
-  openbox->removeClient(frame->titlebar());
-  openbox->removeClient(frame->label());
-  openbox->removeClient(frame->button_max());
-  openbox->removeClient(frame->button_iconify());
-  openbox->removeClient(frame->button_alldesk());
-  openbox->removeClient(frame->button_close());
-  openbox->removeClient(frame->handle());
-  openbox->removeClient(frame->grip_left());
-  openbox->removeClient(frame->grip_right());
+  Window *w = frame->allWindows();
+  for (unsigned int i = 0; w[i]; ++i)
+    openbox->addClient(w[i], client);
+  delete [] w;
   // unregister for handling events
   openbox->clearHandler(client->window());
   
index ab0bc25aea37841c0196fb186a9105ceec4739b1..db8c26d199c7b4d48049d390c4685c95d60f4597 100644 (file)
@@ -11,7 +11,6 @@ extern "C" {
 }
 
 #include "widgetbase.hh"
-#include "otk/renderstyle.hh"
 #include "otk/strut.hh"
 #include "otk/rect.hh"
 #include "otk/screeninfo.hh"
@@ -58,9 +57,6 @@ private:
   //! Information about this screen
   const otk::ScreenInfo *_info;
   
-  //! The style with which to render on the screen
-  otk::RenderStyle _style;
-
   //! Is the root colormap currently installed?
   bool _root_cmap_installed;
 
@@ -146,8 +142,6 @@ public:
   inline bool managed() const { return _managed; }
   //! Returns the area of the screen not reserved by applications' Struts
   inline const otk::Rect &area() const { return _area; }
-  //! Returns the style in use on the screen
-  inline const otk::RenderStyle *style() const { return &_style; }
   //!  An offscreen window which gets focus when nothing else has it
   inline Window focuswindow() const { return _focuswindow; }
   //! Returns the desktop being displayed
This page took 0.081717 seconds and 4 git commands to generate.