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..
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
#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"
{
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);
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);
_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
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
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);
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
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();
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);
+++ /dev/null
-// -*- 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
-}
-
-}
+++ /dev/null
-// -*- 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
+++ /dev/null
-// -*- 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();
-}
-
-}
+++ /dev/null
-// -*- 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
Client::Client(int screen, Window window)
: otk::EventHandler(),
- WidgetBase(WidgetBase::Type_Client),
frame(0), _screen(screen), _window(window)
{
assert(screen >= 0);
_title = _("Unnamed Window");
if (frame)
- frame->setTitle(_title);
+ frame->adjustTitle();
}
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
otk::EventHandler::focusHandler(e);
- frame->focus();
_focused = true;
+ frame->adjustFocus();
openbox->setFocusedClient(this);
}
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;
*/
#include "screen.hh"
-#include "widgetbase.hh"
-#include "otk/point.hh"
#include "otk/strut.hh"
#include "otk/rect.hh"
#include "otk/eventhandler.hh"
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
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.
/*!
/*!
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;
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;
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; }
@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
/*!
#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()
{
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);
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);
}
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
_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());
// 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());
}
}
#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
private:
Client *_client;
- const otk::ScreenInfo *_screen;
//! The size of the frame on each side of the client window
otk::Strut _size;
//! 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();
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
//! 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.
*/
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;
};
}
+++ /dev/null
-// -*- 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.
-}
-
-}
+++ /dev/null
-// -*- 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
#include "otk/property.hh"
#include "otk/util.hh"
#include "otk/rendercolor.hh"
+#include "otk/renderstyle.hh"
extern "C" {
#include <X11/cursorfont.h>
while (waitpid(-1, NULL, WNOHANG) > 0);
otk::RenderColor::initialize();
+ otk::RenderStyle::initialize();
otk::Timer::initialize();
otk::Property::initialize();
_actions = new Actions();
for (it = _screens.begin(); it != end; ++it) {
(*it)->manageExisting();
}
-
+
// grab any keys set up before the screens existed
_bindings->grabKeys(true);
//delete _display;
otk::Timer::destroy();
+ otk::RenderStyle::destroy();
otk::RenderColor::destroy();
}
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);
}
_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);
#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
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
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();
// 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());
}
#include "widgetbase.hh"
-#include "otk/renderstyle.hh"
#include "otk/strut.hh"
#include "otk/rect.hh"
#include "otk/screeninfo.hh"
//! 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;
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