No longer using otk widgets for the frame decorations.

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..
This commit is contained in:
Dana Jansens 2003-02-08 07:37:22 +00:00
parent 1c97e9fb7b
commit 17b0266979
15 changed files with 539 additions and 985 deletions

View 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

View 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"
@ -73,11 +73,19 @@ 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);

View file

@ -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
}
}

View file

@ -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

View file

@ -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();
}
}

View file

@ -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

View 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;

View 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
/*!

View 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);
return XCreateWindow(**otk::display, parent, 0, 0, 1, 1, 0,
info->depth(), InputOutput, info->visual(),
mask, attrib);
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());
_style = 0;
setStyle(style);
otk::Widget::unfocus(); // stuff starts out appearing focused in otk
_plate.show(); // the other stuff is shown based on decor settings
}
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);
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;
void Frame::setTitle(const otk::ustring &text)
{
_label.setText(text);
_label.update();
}
void Frame::setStyle(otk::RenderStyle *style)
{
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
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);
_style = style;
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;
setBorderColor(_style->frameBorderColor());
delete [] _buttons;
delete [] _titleorder;
delete [] _buttons_sur;
}
// if !replace, then adjust() will get called after the client is grabbed!
if (replace) {
// size/position everything
adjustSize();
adjustPosition();
void Frame::show()
{
if (!_visible) {
_visible = true;
XMapWindow(**otk::display, _frame);
}
}
void Frame::focus()
void Frame::hide()
{
otk::Widget::focus();
update();
if (_visible) {
_visible = false;
XUnmapWindow(**otk::display, _frame);
}
}
void Frame::unfocus()
MouseContext::MC Frame::mouseContext(Window win) const
{
otk::Widget::unfocus();
update();
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::adjust()
Window *Frame::allWindows() const
{
// the party all happens in adjustSize
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::styleChanged(const otk::RenderStyle &style)
{
applyStyle(style);
// size/position everything
adjustSize();
adjustPosition();
}
void Frame::adjustFocus()
{
// XXX optimizations later...
adjustSize();
}
void Frame::adjustTitle()
{
// 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();
Client::DecorationFlags decorations = _client->decorations();
const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
// 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;
_innersize.left = _innersize.top = _innersize.bottom = _innersize.right =
cbwidth;
width = _client->area().width() + cbwidth * 2;
_plate.setBorderWidth(cbwidth);
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;
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";
// 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;
}
// 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();
if (decorations & Client::Decor_Border) {
geom.bwidth = style->frameBorderWidth();
geom.cbwidth = style->clientBorderWidth();
} else {
_titlebar.hide(true);
geom.bwidth = geom.cbwidth = 0;
}
_innersize.left = _innersize.top = _innersize.bottom = _innersize.right =
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
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);
// 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);
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()));
renderLabel();
}
if (_decorations & Client::Decor_Handle)
_handle.show(true);
else
_handle.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);
}
_size.left = _innersize.left + bwidth;
_size.right = _innersize.right + bwidth;
_size.top = _innersize.top + bwidth;
_size.bottom = _innersize.bottom + bwidth;
XSetWindowBorder(**otk::display, _plate,
focus ? style->clientBorderFocusColor()->pixel() :
style->clientBorderUnfocusColor()->pixel());
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());
}
}

View 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;
// 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 position and size of the entire frame (including borders)
otk::Rect _area;
//! 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;
bool _visible;
// decoration windows
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,17 +106,7 @@ public:
const otk::Strut& size() const { return _size; }
//! Set the style to decorate the frame with
virtual void setStyle(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);
virtual void styleChanged(const otk::RenderStyle &style);
//! Reparents the client window from the root window onto the frame
void grabClient();
@ -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;
};
}

View file

@ -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.
}
}

View file

@ -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

View 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();
@ -212,6 +214,7 @@ Openbox::~Openbox()
//delete _display;
otk::Timer::destroy();
otk::RenderStyle::destroy();
otk::RenderColor::destroy();
}

View 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());

View 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