From 17b0266979137ad957a701c7093a14841a8c2091 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sat, 8 Feb 2003 07:37:22 +0000 Subject: [PATCH] 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.. --- src/Makefile.am | 9 +- src/actions.cc | 58 ++-- src/backgroundwidget.cc | 87 ------ src/backgroundwidget.hh | 29 -- src/buttonwidget.cc | 215 -------------- src/buttonwidget.hh | 43 --- src/client.cc | 26 +- src/client.hh | 22 +- src/frame.cc | 643 ++++++++++++++++++++++------------------ src/frame.hh | 146 +++++---- src/labelwidget.cc | 117 -------- src/labelwidget.hh | 42 --- src/openbox.cc | 5 +- src/screen.cc | 48 ++- src/screen.hh | 6 - 15 files changed, 525 insertions(+), 971 deletions(-) delete mode 100644 src/backgroundwidget.cc delete mode 100644 src/backgroundwidget.hh delete mode 100644 src/buttonwidget.cc delete mode 100644 src/buttonwidget.hh delete mode 100644 src/labelwidget.cc delete mode 100644 src/labelwidget.hh diff --git a/src/Makefile.am b/src/Makefile.am index bf759d82..c1ecf8e7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/actions.cc b/src/actions.cc index b557cd33..bb5088e9 100644 --- a/src/actions.cc +++ b/src/actions.cc @@ -5,9 +5,9 @@ #endif #include "actions.hh" -#include "widgetbase.hh" #include "openbox.hh" #include "client.hh" +#include "frame.hh" #include "screen.hh" #include "python.hh" #include "bindings.hh" @@ -72,12 +72,20 @@ void Actions::buttonPressHandler(const XButtonEvent &e) { otk::EventHandler::buttonPressHandler(e); insertPress(e); - - // run the PRESS python hook - WidgetBase *w = dynamic_cast - (openbox->findHandler(e.window)); - if (!w) return; + MouseContext::MC context; + EventHandler *h = openbox->findHandler(e.window); + Frame *f = dynamic_cast(h); + if (f) + context= f->mouseContext(e.window); + else if (dynamic_cast(h)) + context = MouseContext::Window; + else if (dynamic_cast(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 - (openbox->findHandler(e.window)); - if (!w) return; + MouseContext::MC context; + EventHandler *h = openbox->findHandler(e.window); + Frame *f = dynamic_cast(h); + if (f) + context= f->mouseContext(e.window); + else if (dynamic_cast(h)) + context = MouseContext::Window; + else if (dynamic_cast(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(h); + if (f) + context= f->mouseContext(e.window); + else if (dynamic_cast(h)) + context = MouseContext::Window; + else if (dynamic_cast(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 - (openbox->findHandler(e.window)); - if (!w) return; - if (!_dragging) { long threshold; int dx = x_root - _posqueue[0]->pos.x(); @@ -298,7 +322,7 @@ void Actions::motionHandler(const XMotionEvent &e) screen = c->screen(); else screen = otk::display->findScreen(e.root)->screen(); - MouseData data(screen, c, e.time, state, button, w->mcontext(), + MouseData data(screen, c, e.time, state, button, context, MouseAction::Motion, x_root, y_root, _posqueue[0]->pos, _posqueue[0]->clientarea); openbox->bindings()->fireButton(&data); diff --git a/src/backgroundwidget.cc b/src/backgroundwidget.cc deleted file mode 100644 index 4d1a51d0..00000000 --- a/src/backgroundwidget.cc +++ /dev/null @@ -1,87 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif - -#include "backgroundwidget.hh" - -namespace ob { - -BackgroundWidget::BackgroundWidget(otk::Widget *parent, - WidgetBase::WidgetType type) - : otk::Widget(parent), - WidgetBase(type) -{ -} - - -BackgroundWidget::~BackgroundWidget() -{ -} - - -void BackgroundWidget::setTextures() -{ - switch (type()) { - case Type_Titlebar: - if (_focused) - setTexture(_style->titlebarFocusBackground()); - else - setTexture(_style->titlebarUnfocusBackground()); - break; - case Type_Handle: - if (_focused) - setTexture(_style->handleFocusBackground()); - else - setTexture(_style->handleUnfocusBackground()); - break; - case Type_Plate: - if (_focused) - setBorderColor(_style->clientBorderFocusColor()); - else - setBorderColor(_style->clientBorderUnfocusColor()); - break; - default: - assert(false); // there's no other background widgets! - } -} - - -void BackgroundWidget::setStyle(otk::RenderStyle *style) -{ - Widget::setStyle(style); - setTextures(); - switch (type()) { - case Type_Titlebar: - case Type_Handle: - setBorderColor(_style->frameBorderColor()); - break; - case Type_Plate: - break; - default: - assert(false); // there's no other background widgets! - } -} - - -void BackgroundWidget::focus() -{ - otk::Widget::focus(); - setTextures(); -} - - -void BackgroundWidget::unfocus() -{ - otk::Widget::unfocus(); - setTextures(); -} - - -void BackgroundWidget::adjust() -{ - // nothing to adjust here. its done in Frame::adjustSize -} - -} diff --git a/src/backgroundwidget.hh b/src/backgroundwidget.hh deleted file mode 100644 index 640ac45e..00000000 --- a/src/backgroundwidget.hh +++ /dev/null @@ -1,29 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __backgroundwidget_hh -#define __backgroundwidget_hh - -#include "otk/widget.hh" -#include "widgetbase.hh" - -namespace ob { - -class BackgroundWidget : public otk::Widget, public WidgetBase -{ -private: - void setTextures(); - -public: - BackgroundWidget(otk::Widget *parent, WidgetBase::WidgetType type); - virtual ~BackgroundWidget(); - - virtual void setStyle(otk::RenderStyle *style); - - virtual void adjust(); - - virtual void focus(); - virtual void unfocus(); -}; - -} - -#endif // __backgroundwidget_hh diff --git a/src/buttonwidget.cc b/src/buttonwidget.cc deleted file mode 100644 index 810911be..00000000 --- a/src/buttonwidget.cc +++ /dev/null @@ -1,215 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif - -#include "buttonwidget.hh" -#include "client.hh" - -namespace ob { - -ButtonWidget::ButtonWidget(otk::Widget *parent, - WidgetBase::WidgetType type, - Client *client) - : otk::Widget(parent), - WidgetBase(type), - _client(client), - _pressed(false), - _button(0), - _state(false) -{ -} - - -ButtonWidget::~ButtonWidget() -{ -} - - -void ButtonWidget::setTextures() -{ - bool p = _pressed; - - switch (type()) { - case Type_AllDesktopsButton: - if (_client->desktop() == (signed)0xffffffff) - p = true; - break; - case Type_MaximizeButton: - if (_client->maxHorz() || _client->maxVert()) - p = true; - break; - default: - break; - } - - switch (type()) { - case Type_LeftGrip: - case Type_RightGrip: - if (_focused) - setTexture(_style->gripFocusBackground()); - else - setTexture(_style->gripUnfocusBackground()); - break; - case Type_AllDesktopsButton: - case Type_MaximizeButton: - case Type_CloseButton: - case Type_IconifyButton: - if (p) { - if (_focused) - setTexture(_style->buttonPressFocusBackground()); - else - setTexture(_style->buttonPressUnfocusBackground()); - } else { - if (_focused) - setTexture(_style->buttonUnpressFocusBackground()); - else - setTexture(_style->buttonUnpressUnfocusBackground()); - } - break; - default: - assert(false); // there's no other button widgets! - } -} - - -void ButtonWidget::setStyle(otk::RenderStyle *style) -{ - otk::Widget::setStyle(style); - setTextures(); - - switch (type()) { - case Type_LeftGrip: - case Type_RightGrip: - setBorderColor(_style->frameBorderColor()); - break; - case Type_AllDesktopsButton: - case Type_CloseButton: - case Type_MaximizeButton: - case Type_IconifyButton: - break; - default: - assert(false); // there's no other button widgets! - } -} - - -void ButtonWidget::update() -{ - switch (type()) { - case Type_AllDesktopsButton: - if ((_client->desktop() == (signed)0xffffffff) != _state) { - _state = !_state; - setTextures(); - } - break; - case Type_MaximizeButton: - if ((_client->maxHorz() || _client->maxVert()) != _state) { - _state = !_state; - setTextures(); - } - break; - default: - break; - } - - otk::Widget::update(); -} - - -void ButtonWidget::renderForeground() -{ - otk::PixmapMask *pm; - int width; - bool draw = _dirty; - - otk::Widget::renderForeground(); - - if (draw) { - switch (type()) { - case Type_AllDesktopsButton: - pm = _style->alldesktopsMask(); - break; - case Type_CloseButton: - pm = _style->closeMask(); - break; - case Type_MaximizeButton: - pm = _style->maximizeMask(); - break; - case Type_IconifyButton: - pm = _style->iconifyMask(); - break; - case Type_LeftGrip: - case Type_RightGrip: - return; // no drawing - default: - assert(false); // there's no other button widgets! - } - - assert(pm->mask); - if (pm->mask == None) return; // no mask for the button, leave it empty - - width = _rect.width(); - - otk::RenderColor *color = (_focused ? _style->buttonFocusColor() : - _style->buttonUnfocusColor()); - - // set the clip region - int x = (width - pm->w) / 2, y = (width - pm->h) / 2; - XSetClipMask(**otk::display, color->gc(), pm->mask); - XSetClipOrigin(**otk::display, color->gc(), x, y); - - // fill in the clipped region - XFillRectangle(**otk::display, _surface->pixmap(), color->gc(), x, y, - x + pm->w, y + pm->h); - - // unset the clip region - XSetClipMask(**otk::display, color->gc(), None); - XSetClipOrigin(**otk::display, color->gc(), 0, 0); - } -} - - -void ButtonWidget::adjust() -{ - // nothing to adjust. no children. -} - - -void ButtonWidget::focus() -{ - otk::Widget::focus(); - setTextures(); -} - - -void ButtonWidget::unfocus() -{ - otk::Widget::unfocus(); - setTextures(); -} - - -void ButtonWidget::buttonPressHandler(const XButtonEvent &e) -{ - otk::Widget::buttonPressHandler(e); - if (_button) return; - _button = e.button; - _pressed = true; - setTextures(); - update(); -} - - -void ButtonWidget::buttonReleaseHandler(const XButtonEvent &e) -{ - otk::Widget::buttonPressHandler(e); - if (e.button != _button) return; - _button = 0; - _pressed = false; - setTextures(); - update(); -} - -} diff --git a/src/buttonwidget.hh b/src/buttonwidget.hh deleted file mode 100644 index 0d546f73..00000000 --- a/src/buttonwidget.hh +++ /dev/null @@ -1,43 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __buttonwidget_hh -#define __buttonwidget_hh - -#include "widgetbase.hh" -#include "otk/widget.hh" - -namespace ob { - -class Client; - -class ButtonWidget : public otk::Widget, public WidgetBase -{ -private: - void setTextures(); - Client *_client; - bool _pressed; - unsigned int _button; - bool _state; - -public: - ButtonWidget(otk::Widget *parent, WidgetBase::WidgetType type, - Client *client); - virtual ~ButtonWidget(); - - virtual void setStyle(otk::RenderStyle *style); - - virtual void adjust(); - - virtual void update(); - - virtual void renderForeground(); - - virtual void focus(); - virtual void unfocus(); - - virtual void buttonPressHandler(const XButtonEvent &e); - virtual void buttonReleaseHandler(const XButtonEvent &e); -}; - -} - -#endif // __buttonwidget_hh diff --git a/src/client.cc b/src/client.cc index 68653c31..d5be00d0 100644 --- a/src/client.cc +++ b/src/client.cc @@ -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; diff --git a/src/client.hh b/src/client.hh index c17431a5..6e11ed8c 100644 --- a/src/client.hh +++ b/src/client.hh @@ -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 /*! diff --git a/src/frame.cc b/src/frame.cc index 57b338c8..5e9d8520 100644 --- a/src/frame.cc +++ b/src/frame.cc @@ -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 +#include namespace ob { const long Frame::event_mask; -Frame::Frame(Client *client, otk::RenderStyle *style) - : otk::Widget(openbox, style, Horizontal, 0, 1, true), - WidgetBase(WidgetBase::Type_Frame), - _client(client), - _screen(otk::display->screenInfo(client->screen())), - _plate(this, WidgetBase::Type_Plate), - _titlebar(this, WidgetBase::Type_Titlebar), - _button_close(&_titlebar, WidgetBase::Type_CloseButton, client), - _button_iconify(&_titlebar, WidgetBase::Type_IconifyButton, client), - _button_max(&_titlebar, WidgetBase::Type_MaximizeButton, client), - _button_alldesk(&_titlebar, WidgetBase::Type_AllDesktopsButton, client), - _label(&_titlebar, WidgetBase::Type_Label), - _handle(this, WidgetBase::Type_Handle), - _grip_left(&_handle, WidgetBase::Type_LeftGrip, client), - _grip_right(&_handle, WidgetBase::Type_RightGrip, client), - _decorations(client->decorations()) +Window createWindow(const otk::ScreenInfo *info, Window parent, + unsigned long mask, XSetWindowAttributes *attrib) { - assert(client); - assert(style); - - XSelectInput(**otk::display, _window, Frame::event_mask); - - _grip_left.setCursor(openbox->cursors().ll_angle); - _grip_right.setCursor(openbox->cursors().lr_angle); - - _label.setText(_client->title()); + return XCreateWindow(**otk::display, parent, 0, 0, 1, 1, 0, + info->depth(), InputOutput, info->visual(), + mask, attrib); + +} - _style = 0; - setStyle(style); +Frame::Frame(Client *client) + : _client(client), + _visible(false), + _plate(0), + _title(0), + _label(0), + _handle(0), + _lgrip(0), + _rgrip(0), + _buttons(0), + _numbuttons(0), + _titleorder(0), + _frame_sur(0), + _title_sur(0), + _label_sur(0), + _handle_sur(0), + _grip_sur(0), + _buttons_sur(0) +{ + assert(client); - otk::Widget::unfocus(); // stuff starts out appearing focused in otk - - _plate.show(); // the other stuff is shown based on decor settings + XSetWindowAttributes attrib; + unsigned long mask; + const otk::ScreenInfo *info = otk::display->screenInfo(client->screen()); + + // create all of the decor windows (except title bar buttons) + mask = CWOverrideRedirect | CWEventMask; + attrib.event_mask = Frame::event_mask; + attrib.override_redirect = true; + _frame = createWindow(info, info->rootWindow(), mask, &attrib); + + mask = 0; + _plate = createWindow(info, _frame, mask, &attrib); + mask = CWEventMask; + attrib.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | + ExposureMask); + _title = createWindow(info, _frame, mask, &attrib); + _label = createWindow(info, _title, mask, &attrib); + _handle = createWindow(info, _frame, mask, &attrib); + mask |= CWCursor; + attrib.cursor = openbox->cursors().ll_angle; + _lgrip = createWindow(info, _handle, mask, &attrib); + attrib.cursor = openbox->cursors().lr_angle; + _rgrip = createWindow(info, _handle, mask, &attrib); + + // the other stuff is shown based on decor settings + XMapWindow(**otk::display, _plate); + XMapWindow(**otk::display, _lgrip); + XMapWindow(**otk::display, _rgrip); + XMapWindow(**otk::display, _label); + + applyStyle(*otk::RenderStyle::style(_client->screen())); + + // XXX load buttons + _numbuttons = 0; + _buttons = new Window[0]; + _buttons_sur = new otk::Surface*[0]; + _titleorder = new unsigned int[1]; + _titleorder[0] = (unsigned)-1; + + // register all of the windows with the event dispatcher + Window *w = allWindows(); + for (unsigned int i = 0; w[i]; ++i) + openbox->registerHandler(w[i], this); + delete [] w; } - Frame::~Frame() { + // unregister all of the windows with the event dispatcher + Window *w = allWindows(); + for (unsigned int i = 0; w[i]; ++i) + openbox->clearHandler(w[i]); + delete [] w; + + for (unsigned int i = 0; i < _numbuttons; ++i) { + XDestroyWindow(**otk::display, _buttons[i]); + delete _buttons_sur[i]; + } + XDestroyWindow(**otk::display, _rgrip); + XDestroyWindow(**otk::display, _lgrip); + XDestroyWindow(**otk::display, _handle); + XDestroyWindow(**otk::display, _label); + XDestroyWindow(**otk::display, _title); + XDestroyWindow(**otk::display, _frame); + + if (_frame_sur) delete _frame_sur; + if (_title_sur) delete _title_sur; + if (_label_sur) delete _label_sur; + if (_handle_sur) delete _handle_sur; + if (_grip_sur) delete _grip_sur; + + delete [] _buttons; + delete [] _titleorder; + delete [] _buttons_sur; } - -void Frame::setTitle(const otk::ustring &text) +void Frame::show() { - _label.setText(text); - _label.update(); + if (!_visible) { + _visible = true; + XMapWindow(**otk::display, _frame); + } } - -void Frame::setStyle(otk::RenderStyle *style) +void Frame::hide() { - assert(style); - - // if a style was previously set, then 'replace' is true, cause we're - // replacing a style - bool replace = (_style); - - otk::Widget::setStyle(style); - - if (replace) { - // XXX: do shit here whatever - } - - _style = style; - - setBorderColor(_style->frameBorderColor()); - - // if !replace, then adjust() will get called after the client is grabbed! - if (replace) { - // size/position everything - adjustSize(); - adjustPosition(); + if (_visible) { + _visible = false; + XUnmapWindow(**otk::display, _frame); } } +MouseContext::MC Frame::mouseContext(Window win) const +{ + if (win == _frame) return MouseContext::Frame; + if (win == _title || + win == _label) return MouseContext::Titlebar; + if (win == _handle) return MouseContext::Handle; + if (win == _plate) return MouseContext::Window; + if (win == _lgrip || + win == _rgrip) return MouseContext::Grip; + return (MouseContext::MC) -1; +} -void Frame::focus() +Window *Frame::allWindows() const { - otk::Widget::focus(); - update(); + Window *w = new Window[7 + _numbuttons + 1]; + unsigned int i = 0; + w[i++] = _frame; + w[i++] = _plate; + w[i++] = _title; + w[i++] = _label; + w[i++] = _handle; + w[i++] = _lgrip; + w[i++] = _rgrip; + for (unsigned int j = 0; j < _numbuttons; ++j) + w[j + i++] = _buttons[j]; + w[i] = 0; + return w; } +void Frame::applyStyle(const otk::RenderStyle &style) +{ + // set static border colors + XSetWindowBorder(**otk::display, _frame, style.frameBorderColor()->pixel()); + XSetWindowBorder(**otk::display, _title, style.frameBorderColor()->pixel()); + XSetWindowBorder(**otk::display, _handle, style.frameBorderColor()->pixel()); + XSetWindowBorder(**otk::display, _lgrip, style.frameBorderColor()->pixel()); + XSetWindowBorder(**otk::display, _rgrip, style.frameBorderColor()->pixel()); + + // size all the fixed-size elements + geom.font_height = style.labelFont()->height(); + if (geom.font_height < 1) geom.font_height = 1; + geom.button_size = geom.font_height - 2; + if (geom.button_size < 1) geom.button_size = 1; + geom.handle_height = style.handleWidth(); + if (geom.handle_height < 1) geom.handle_height = 1; + geom.bevel = style.bevelWidth(); + + XResizeWindow(**otk::display, _lgrip, geom.grip_width(), geom.handle_height); + XResizeWindow(**otk::display, _rgrip, geom.grip_width(), geom.handle_height); + + for (unsigned int i = 0; i < _numbuttons; ++i) + XResizeWindow(**otk::display, _buttons[i], + geom.button_size, geom.button_size); +} -void Frame::unfocus() +void Frame::styleChanged(const otk::RenderStyle &style) { - otk::Widget::unfocus(); - update(); + applyStyle(style); + + // size/position everything + adjustSize(); + adjustPosition(); } +void Frame::adjustFocus() +{ + // XXX optimizations later... + adjustSize(); +} -void Frame::adjust() +void Frame::adjustTitle() { - // the party all happens in adjustSize + // XXX optimizations later... + adjustSize(); } +static void render(int screen, const otk::Size &size, Window win, + otk::Surface **surface, + const otk::RenderTexture &texture) +{ + otk::Surface *s = new otk::Surface(screen, size); + otk::display->renderControl(screen)->drawBackground(*s, texture); + XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap()); + XClearWindow(**otk::display, win); + if (*surface) delete *surface; + *surface = s; +} void Frame::adjustSize() { - // XXX: only if not overridden or something!!! MORE LOGIC HERE!! - _decorations = _client->decorations(); - - // true/false for whether to show each element of the titlebar - bool tit_i = false, tit_m = false, tit_s = false, tit_c = false; - int width; // the width of the client and its border - int bwidth; // width to make borders - int cbwidth; // width of the inner client border - int fontheight = _style->labelFont()->height(); // height of the font - int butsize = fontheight - 2; // width and height of the titlebar buttons - const int bevel = _style->bevelWidth(); - - if (_decorations & Client::Decor_Border) { - bwidth = _style->frameBorderWidth(); - cbwidth = _style->clientBorderWidth(); - } else - bwidth = cbwidth = 0; + Client::DecorationFlags decorations = _client->decorations(); + const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen()); + + if (decorations & Client::Decor_Border) { + geom.bwidth = style->frameBorderWidth(); + geom.cbwidth = style->clientBorderWidth(); + } else { + geom.bwidth = geom.cbwidth = 0; + } _innersize.left = _innersize.top = _innersize.bottom = _innersize.right = - cbwidth; - width = _client->area().width() + cbwidth * 2; + geom.cbwidth; + geom.width = _client->area().width() + geom.cbwidth * 2; + assert(geom.width > 0); + + // set border widths + XSetWindowBorderWidth(**otk::display, _plate, geom.cbwidth); + XSetWindowBorderWidth(**otk::display, _frame, geom.bwidth); + XSetWindowBorderWidth(**otk::display, _title, geom.bwidth); + XSetWindowBorderWidth(**otk::display, _handle, geom.bwidth); + XSetWindowBorderWidth(**otk::display, _lgrip, geom.bwidth); + XSetWindowBorderWidth(**otk::display, _rgrip, geom.bwidth); + + // position/size and map/unmap all the windows - _plate.setBorderWidth(cbwidth); + if (decorations & Client::Decor_Titlebar) { + XMoveResizeWindow(**otk::display, _title, -geom.bwidth, -geom.bwidth, + geom.width, geom.title_height()); + _innersize.top += geom.title_height() + geom.bwidth; + XMapWindow(**otk::display, _title); - setBorderWidth(bwidth); - _titlebar.setBorderWidth(bwidth); - _grip_left.setBorderWidth(bwidth); - _grip_right.setBorderWidth(bwidth); - _handle.setBorderWidth(bwidth); - - if (_decorations & Client::Decor_Titlebar) { - // set the titlebar size - _titlebar.setGeometry(-bwidth, - -bwidth, - width, - _style->labelFont()->height() + (bevel * 2)); - _innersize.top += _titlebar.height() + bwidth; - - // set the label size - _label.setGeometry(0, bevel, width, fontheight); - // set the buttons sizes - if (_decorations & Client::Decor_Iconify) - _button_iconify.setGeometry(0, bevel + 1, butsize, butsize); - if (_decorations & Client::Decor_Maximize) - _button_max.setGeometry(0, bevel + 1, butsize, butsize); - if (_decorations & Client::Decor_AllDesktops) - _button_alldesk.setGeometry(0, bevel + 1, butsize, butsize); - if (_decorations & Client::Decor_Close) - _button_close.setGeometry(0, bevel + 1, butsize, butsize); - - // separation between titlebar elements - const int sep = bevel + 1; - - otk::ustring layout; - if (!python_get_string("TITLEBAR_LAYOUT", &layout)) - layout = "ILMC"; - - // this code ensures that the string only has one of each possible - // letter, all of the letters are valid, and L exists somewhere in the - // string! - bool tit_l = false; + // layout the title bar elements + layoutTitle(); + } else + XUnmapWindow(**otk::display, _title); + + if (decorations & Client::Decor_Handle) { + geom.handle_y = _innersize.top + _client->area().height() + geom.cbwidth; + XMoveResizeWindow(**otk::display, _handle, -geom.bwidth, geom.handle_y, + geom.width, geom.handle_height); + XMoveWindow(**otk::display, _lgrip, -geom.bwidth, -geom.bwidth); + XMoveWindow(**otk::display, _rgrip, + -geom.bwidth + geom.width - geom.grip_width(), + -geom.bwidth); + _innersize.bottom += geom.handle_height + geom.bwidth; + XMapWindow(**otk::display, _handle); + } else + XUnmapWindow(**otk::display, _handle); - for (std::string::size_type i = 0; i < layout.size(); ++i) { - switch (layout[i]) { - case 'i': - case 'I': - if (!tit_i && (_decorations & Client::Decor_Iconify)) { - tit_i = true; - continue; - } - break; - case 'l': - case 'L': - if (!tit_l) { - tit_l = true; - continue; - } - break; - case 'm': - case 'M': - if (!tit_m && (_decorations & Client::Decor_Maximize)) { - tit_m = true; - continue; - } - break; - case 'd': - case 'D': - if (!tit_s && (_decorations & Client::Decor_AllDesktops)) { - tit_s = true; - continue; - } - break; - case 'c': - case 'C': - if (!tit_c && (_decorations & Client::Decor_Close)) { - tit_c = true; - continue; - } - break; - } - // if we get here then we don't want the letter, kill it - layout.erase(i--, 1); - } - if (!tit_l) - layout += "L"; + XResizeWindow(**otk::display, _frame, geom.width, + (_client->shaded() ? geom.title_height() : + _innersize.top + _innersize.bottom + + _client->area().height())); + + XMoveResizeWindow(**otk::display, _plate, + _innersize.left - geom.cbwidth, + _innersize.top - geom.cbwidth, + _client->area().width(), _client->area().height()); + + _size.left = _innersize.left + geom.bwidth; + _size.right = _innersize.right + geom.bwidth; + _size.top = _innersize.top + geom.bwidth; + _size.bottom = _innersize.bottom + geom.bwidth; + + _area = otk::Rect(_area.position(), otk::Size(_client->area().width() + + _size.left + _size.right, + _client->area().height() + + _size.top + _size.bottom)); + + // render all the elements + int screen = _client->screen(); + bool focus = _client->focused(); + if (decorations & Client::Decor_Titlebar) { + render(screen, otk::Size(geom.width, geom.title_height()), _title, + &_title_sur, *(focus ? style->titlebarFocusBackground() : + style->titlebarUnfocusBackground())); - // the size of the label. this ASSUMES the layout has only buttons other - // that the ONE LABEL!! - // adds an extra sep so that there's a space on either side of the - // titlebar.. note: x = sep, below. - int lwidth = width - sep * 2 - - (butsize + sep) * (layout.size() - 1); - // quick sanity check for really small windows. if this is needed, its - // obviously not going to be displayed right... - // XXX: maybe we should make this look better somehow? constraints? - if (lwidth <= 0) lwidth = 1; - _label.setWidth(lwidth); - - int x = sep; - for (std::string::size_type i = 0, len = layout.size(); i < len; ++i) { - switch (layout[i]) { - case 'i': - case 'I': - _button_iconify.move(x, _button_iconify.rect().y()); - x += _button_iconify.width(); - break; - case 'l': - case 'L': - _label.move(x, _label.rect().y()); - x += _label.width(); - break; - case 'm': - case 'M': - _button_max.move(x, _button_max.rect().y()); - x += _button_max.width(); - break; - case 'd': - case 'D': - _button_alldesk.move(x, _button_alldesk.rect().y()); - x += _button_alldesk.width(); - break; - case 'c': - case 'C': - _button_close.move(x, _button_close.rect().y()); - x += _button_close.width(); - break; - default: - assert(false); // the layout string is invalid! - } - x += sep; - } - } - - if (_decorations & Client::Decor_Handle) { - _handle.setGeometry(-bwidth, - _innersize.top + _client->area().height() + cbwidth, - width, _style->handleWidth()); - _grip_left.setGeometry(-bwidth, - -bwidth, - butsize * 2, - _handle.height()); - _grip_right.setGeometry(((_handle.rect().right() + 1) - - butsize * 2), - -bwidth, - butsize * 2, - _handle.height()); - _innersize.bottom += _handle.height() + bwidth; + renderLabel(); } - - // position/size all the windows - - if (_client->shaded()) - resize(_innersize.left + _innersize.right + _client->area().width(), - _titlebar.height()); - else - resize(_innersize.left + _innersize.right + _client->area().width(), - _innersize.top + _innersize.bottom + _client->area().height()); - - _plate.setGeometry(_innersize.left - cbwidth, _innersize.top - cbwidth, - _client->area().width(), _client->area().height()); - - // map/unmap all the windows - if (_decorations & Client::Decor_Titlebar) { - _label.show(); - if (tit_i) - _button_iconify.show(); - else - _button_iconify.hide(); - if (tit_m) - _button_max.show(); - else - _button_max.hide(); - if (tit_s) - _button_alldesk.show(); - else - _button_alldesk.hide(); - if (tit_c) - _button_close.show(); - else - _button_close.hide(); - _titlebar.show(); - } else { - _titlebar.hide(true); + if (decorations & Client::Decor_Handle) { + render(screen, otk::Size(geom.width, geom.handle_height), _handle, + &_handle_sur, *(focus ? style->handleFocusBackground() : + style->handleUnfocusBackground())); + render(screen, otk::Size(geom.grip_width(), geom.handle_height), _lgrip, + &_grip_sur, *(focus ? style->gripFocusBackground() : + style->gripUnfocusBackground())); + XSetWindowBackgroundPixmap(**otk::display, _rgrip, _grip_sur->pixmap()); + XClearWindow(**otk::display, _rgrip); } - if (_decorations & Client::Decor_Handle) - _handle.show(true); - else - _handle.hide(true); + XSetWindowBorder(**otk::display, _plate, + focus ? style->clientBorderFocusColor()->pixel() : + style->clientBorderUnfocusColor()->pixel()); - _size.left = _innersize.left + bwidth; - _size.right = _innersize.right + bwidth; - _size.top = _innersize.top + bwidth; - _size.bottom = _innersize.bottom + bwidth; - adjustShape(); +} - update(); +void Frame::renderLabel() +{ + const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen()); + const otk::RenderControl *control = + otk::display->renderControl(_client->screen()); + const otk::Font *font = style->labelFont(); + + otk::Surface *s = new otk::Surface(_client->screen(), + otk::Size(geom.label_width, + geom.label_height())); + control->drawBackground(*s, *(_client->focused() ? + style->labelFocusBackground() : + style->labelUnfocusBackground())); + + otk::ustring t = _client->title(); // the actual text to draw + int x = geom.bevel; // x coord for the text + + if ((unsigned)x * 2 > geom.label_width) return; // no room at all + + // find a string that will fit inside the area for text + otk::ustring::size_type text_len = t.size(); + unsigned int length; + unsigned int maxsize = geom.label_width - geom.bevel * 2; + + do { + t.resize(text_len); + length = font->measureString(t); + } while (length > maxsize && text_len-- > 0); + + if (text_len <= 0) return; // won't fit anything + + // justify the text + switch (style->labelTextJustify()) { + case otk::RenderStyle::RightBottomJustify: + x += maxsize - length; + break; + case otk::RenderStyle::CenterJustify: + x += (maxsize - length) / 2; + break; + case otk::RenderStyle::LeftTopJustify: + break; + } + + control->drawString(*s, *font, x, 0, + *(_client->focused() ? style->textFocusColor() : + style->textUnfocusColor()), t); + + XSetWindowBackgroundPixmap(**otk::display, _label, s->pixmap()); + XClearWindow(**otk::display, _label); + if (_label_sur) delete _label_sur; + _label_sur = s; } +void Frame::layoutTitle() +{ + geom.label_width = geom.width - geom.bevel * 2; + if (geom.label_width < 1) geom.label_width = 1; + XMoveResizeWindow(**otk::display, _label, geom.bevel, geom.bevel, + geom.label_width, geom.font_height); +} void Frame::adjustPosition() { @@ -347,25 +398,25 @@ void Frame::adjustPosition() x = _client->area().x(); y = _client->area().y(); clientGravity(x, y); - move(x, y); + XMoveWindow(**otk::display, _frame, x, y); + _area = otk::Rect(otk::Point(x, y), _area.size()); } void Frame::adjustShape() { #ifdef SHAPE - int bwidth = (_decorations & Client::Decor_Border) ? - _style->frameBorderWidth() : 0; + Client::DecorationFlags decorations = _client->decorations(); if (!_client->shaped()) { // clear the shape on the frame window - XShapeCombineMask(**otk::display, _window, ShapeBounding, + XShapeCombineMask(**otk::display, _frame, ShapeBounding, _innersize.left, _innersize.top, None, ShapeSet); } else { // make the frame's shape match the clients - XShapeCombineShape(**otk::display, _window, ShapeBounding, + XShapeCombineShape(**otk::display, _frame, ShapeBounding, _innersize.left, _innersize.top, _client->window(), ShapeBounding, ShapeSet); @@ -373,23 +424,23 @@ void Frame::adjustShape() int num = 0; XRectangle xrect[2]; - if (_decorations & Client::Decor_Titlebar) { - xrect[0].x = _titlebar.rect().x(); - xrect[0].y = _titlebar.rect().y(); - xrect[0].width = _titlebar.width() + bwidth * 2; // XXX: this is useless once the widget handles borders! - xrect[0].height = _titlebar.height() + bwidth * 2; + if (decorations & Client::Decor_Titlebar) { + xrect[0].x = -geom.bevel; + xrect[0].y = -geom.bevel; + xrect[0].width = geom.width + geom.bwidth * 2; + xrect[0].height = geom.title_height() + geom.bwidth * 2; ++num; } - if (_decorations & Client::Decor_Handle) { - xrect[1].x = _handle.rect().x(); - xrect[1].y = _handle.rect().y(); - xrect[1].width = _handle.width() + bwidth * 2; // XXX: this is useless once the widget handles borders! - xrect[1].height = _handle.height() + bwidth * 2; + if (decorations & Client::Decor_Handle) { + xrect[1].x = -geom.bevel; + xrect[1].y = geom.handle_y; + xrect[1].width = geom.width + geom.bwidth * 2; + xrect[1].height = geom.handle_height + geom.bwidth * 2; ++num; } - XShapeCombineRectangles(**otk::display, window(), + XShapeCombineRectangles(**otk::display, _frame, ShapeBounding, 0, 0, xrect, num, ShapeUnion, Unsorted); } @@ -399,15 +450,15 @@ void Frame::adjustShape() void Frame::adjustState() { - _button_alldesk.update(); - _button_max.update(); +// XXX _button_alldesk.update(); +// XXX _button_max.update(); } void Frame::grabClient() { // reparent the client to the frame - XReparentWindow(**otk::display, _client->window(), _plate.window(), 0, 0); + XReparentWindow(**otk::display, _client->window(), _plate, 0, 0); /* When reparenting the client window, it is usually not mapped yet, since this occurs from a MapRequest. However, in the case where Openbox is @@ -420,7 +471,7 @@ void Frame::grabClient() _client->ignore_unmaps += 2; // select the event mask on the client's parent (to receive config/map req's) - XSelectInput(**otk::display, _plate.window(), SubstructureRedirectMask); + XSelectInput(**otk::display, _plate, SubstructureRedirectMask); // map the client so it maps when the frame does XMapWindow(**otk::display, _client->window()); @@ -444,7 +495,7 @@ void Frame::releaseClient() // according to the ICCCM - if the client doesn't reparent itself, then we // will reparent the window to root for them XReparentWindow(**otk::display, _client->window(), - _screen->rootWindow(), + otk::display->screenInfo(_client->screen())->rootWindow(), _client->area().x(), _client->area().y()); } } diff --git a/src/frame.hh b/src/frame.hh index b2cc2d16..c587c112 100644 --- a/src/frame.hh +++ b/src/frame.hh @@ -9,28 +9,43 @@ extern "C" { #include } -#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 namespace ob { +class Client; + +//! Varius geometry settings in the frame decorations +struct FrameGeometry { + unsigned int width; // title and handle + unsigned int font_height; + unsigned int title_height() { return font_height + bevel*2; } + unsigned int label_width; + unsigned int label_height() { return font_height; } + unsigned int handle_height; // static, from the style + int handle_y; + unsigned int button_size; // static, from the style + unsigned grip_width() { return button_size * 2; } + unsigned bevel; // static, from the style + unsigned bwidth; // frame elements' border width + unsigned cbwidth; // client border width +}; + //! Holds and decorates a frame around an Client (client window) /*! The frame is responsible for calling XSelectInput on the client window's new parent with the SubstructureRedirectMask so that structure events for the client are sent to the window manager. */ -class Frame : public otk::Widget, public WidgetBase { +class Frame : public otk::StyleNotify, public otk::EventHandler { public: //! The event mask to grab on frame windows @@ -38,7 +53,6 @@ public: private: Client *_client; - const otk::ScreenInfo *_screen; //! The size of the frame on each side of the client window otk::Strut _size; @@ -46,32 +60,45 @@ private: //! The size of the frame on each side of the client window inside the border otk::Strut _innersize; + //! The position and size of the entire frame (including borders) + otk::Rect _area; + + bool _visible; + // decoration windows - BackgroundWidget _plate; // sits entirely under the client window - BackgroundWidget _titlebar; - ButtonWidget _button_close; - ButtonWidget _button_iconify; - ButtonWidget _button_max; - ButtonWidget _button_alldesk; - LabelWidget _label; - BackgroundWidget _handle; - ButtonWidget _grip_left; - ButtonWidget _grip_right; - - //! The decorations to display on the window. - /*! - This is by default the same value as in the Client::decorations, but it - is duplicated here so that it can be overridden per-window by the user. - */ - Client::DecorationFlags _decorations; + Window _frame; // sits under everything + Window _plate; // sits entirely under the client window + Window _title; // the titlebar + Window _label; // the section of the titlebar which shows the window name + Window _handle; // bottom bar + Window _lgrip; // lefthand resize grab on the handle + Window _rgrip; // righthand resize grab on the handle + Window *_buttons; // all of the titlebar buttons + unsigned int _numbuttons; // number of buttons, size of _buttons array + unsigned int *_titleorder; // order of the buttons and the label (always + // holds '_numbuttons + 1' elements (for the + // label, which is coded as '-1') + + // surfaces for each + otk::Surface *_frame_sur; + otk::Surface *_title_sur; + otk::Surface *_label_sur; + otk::Surface *_handle_sur; + otk::Surface *_grip_sur; + otk::Surface **_buttons_sur; + + FrameGeometry geom; + + void applyStyle(const otk::RenderStyle &style); + void layoutTitle(); + void renderLabel(); public: - //! Constructs an Frame object, and reparents the client to itself + //! Constructs an Frame object for a client /*! - @param client The client window which will be decorated by the new Frame - @param style The style to use to decorate the frame + @param client The client which will be decorated by the new Frame */ - Frame(Client *client, otk::RenderStyle *style); + Frame(Client *client); //! Destroys the Frame object virtual ~Frame(); @@ -79,18 +106,8 @@ public: const otk::Strut& size() const { return _size; } //! Set the style to decorate the frame with - virtual void setStyle(otk::RenderStyle *style); + virtual void styleChanged(const otk::RenderStyle &style); - //! Empty overridden method to prevent automatic alignment of children - virtual void adjust(); - - //! Displays focused decorations - virtual void focus(); - //! Displays unfocused decorations - virtual void unfocus(); - - void setTitle(const otk::ustring &text); - //! Reparents the client window from the root window onto the frame void grabClient(); //! Reparents the client window back to the root window @@ -103,8 +120,10 @@ public: //! Shape the frame window to the client window void adjustShape(); //! Update the frame to match the client's new state (for things like toggle - //! buttons) + //! buttons, focus, and the title) XXX break this up void adjustState(); + void adjustFocus(); + void adjustTitle(); //! Applies gravity to the client's position to find where the frame should //! be positioned. @@ -120,27 +139,32 @@ public: */ void frameGravity(int &x, int &y); - //! Gets the window id of the frame's "plate" subelement - inline Window plate() const { return _plate.window(); } - //! Gets the window id of the frame's "titlebar" subelement - inline Window titlebar() const { return _titlebar.window(); } - //! Gets the window id of the frame's "label" subelement - inline Window label() const { return _label.window(); } - //! Gets the window id of the frame's "close button" subelement - inline Window button_close() const { return _button_close.window(); } - //! Gets the window id of the frame's "iconify button" subelement - inline Window button_iconify() const { return _button_iconify.window(); } - //! Gets the window id of the frame's "maximize button" subelement - inline Window button_max() const { return _button_max.window(); } - //! Gets the window id of the frame's "all desktops button" subelement - inline Window button_alldesk() const { return _button_alldesk.window(); } - //! Gets the window id of the frame's "handle" subelement - inline Window handle() const { return _handle.window(); } - //! Gets the window id of the frame's "left grip" subelement - inline Window grip_left() const { return _grip_left.window(); } - //! Gets the window id of the frame's "right grip" subelement - inline Window grip_right() const { return _grip_right.window(); } + //! The position and size of the frame window + inline const otk::Rect& area() const { return _area; } + + //! Returns if the frame is visible + inline bool visible() const { return _visible; } + + //! Shows the frame + void show(); + //! Hides the frame + void hide(); + + //! Returns the MouseContext for the given window id + /*! + Returns '-1' if no valid mouse context exists in the frame for the given + id. + */ + ob::MouseContext::MC mouseContext(Window win) const; + + //! Gets the window id of the frame's base top-level parent + inline Window window() const { return _frame; } + //! Gets the window id of the client's parent window + inline Window plate() const { return _plate; } + //! Returns a null terminated array of the window ids that make up the + //! frame's decorations. + Window *allWindows() const; }; } diff --git a/src/labelwidget.cc b/src/labelwidget.cc deleted file mode 100644 index 020e8b73..00000000 --- a/src/labelwidget.cc +++ /dev/null @@ -1,117 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif - -#include "otk/screeninfo.hh" -#include "otk/display.hh" -#include "labelwidget.hh" - -namespace ob { - -LabelWidget::LabelWidget(otk::Widget *parent, WidgetBase::WidgetType type) - : otk::Widget(parent), - WidgetBase(type) -{ -} - - -LabelWidget::~LabelWidget() -{ -} - - -void LabelWidget::setText(const otk::ustring &text) -{ - _text = text; - _dirty = true; -} - - -void LabelWidget::setTextures() -{ - if (_focused) { - setTexture(_style->labelFocusBackground()); - _text_color = _style->textFocusColor(); - } else { - setTexture(_style->labelUnfocusBackground()); - _text_color = _style->textUnfocusColor(); - } -} - - -void LabelWidget::setStyle(otk::RenderStyle *style) -{ - otk::Widget::setStyle(style); - setTextures(); - _font = style->labelFont(); - _sidemargin = style->bevelWidth() * 2; - _justify = style->labelTextJustify(); - - assert(_font); -} - - -void LabelWidget::focus() -{ - otk::Widget::focus(); - setTextures(); -} - - -void LabelWidget::unfocus() -{ - otk::Widget::unfocus(); - setTextures(); -} - - -void LabelWidget::renderForeground() -{ - bool draw = _dirty; - - otk::Widget::renderForeground(); - - if (draw) { - otk::ustring t = _text; - int x = _sidemargin; // x coord for the text - - // find a string that will fit inside the area for text - int max_length = width() - _sidemargin * 2; - if (max_length <= 0) { - t = ""; // can't fit anything - } else { - size_t text_len = t.size(); - int length; - - do { - t.resize(text_len); - length = _font->measureString(t); - } while (length > max_length && text_len-- > 0); - - // justify the text - switch (_justify) { - case otk::RenderStyle::RightJustify: - x += max_length - length; - break; - case otk::RenderStyle::CenterJustify: - x += (max_length - length) / 2; - break; - case otk::RenderStyle::LeftJustify: - break; - } - } - - otk::display->renderControl(_screen)->drawString - (*_surface, *_font, x, 0, *_text_color, t); - } -} - - -void LabelWidget::adjust() -{ - // nothing to adjust. no children. -} - -} diff --git a/src/labelwidget.hh b/src/labelwidget.hh deleted file mode 100644 index 81d350c6..00000000 --- a/src/labelwidget.hh +++ /dev/null @@ -1,42 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __oblabelwidget_hh -#define __oblabelwidget_hh - -#include "widgetbase.hh" -#include "otk/widget.hh" -#include "otk/font.hh" -#include "otk/renderstyle.hh" -#include "otk/ustring.hh" - -namespace ob { - -class LabelWidget : public otk::Widget, public WidgetBase -{ -private: - void setTextures(); - const otk::Font *_font; - otk::RenderColor *_text_color; - int _sidemargin; - otk::RenderStyle::TextJustify _justify; - otk::ustring _text; - -public: - LabelWidget(otk::Widget *parent, WidgetBase::WidgetType type); - virtual ~LabelWidget(); - - virtual void setStyle(otk::RenderStyle *style); - - virtual void adjust(); - - virtual void focus(); - virtual void unfocus(); - - virtual void renderForeground(); - - inline const otk::ustring &text() const { return _text; } - void setText(const otk::ustring &text); -}; - -} - -#endif // __oblabelwidget_hh diff --git a/src/openbox.cc b/src/openbox.cc index de7767a2..24b32786 100644 --- a/src/openbox.cc +++ b/src/openbox.cc @@ -15,6 +15,7 @@ #include "otk/property.hh" #include "otk/util.hh" #include "otk/rendercolor.hh" +#include "otk/renderstyle.hh" extern "C" { #include @@ -120,6 +121,7 @@ Openbox::Openbox(int argc, char **argv) while (waitpid(-1, NULL, WNOHANG) > 0); otk::RenderColor::initialize(); + otk::RenderStyle::initialize(); otk::Timer::initialize(); otk::Property::initialize(); _actions = new Actions(); @@ -180,7 +182,7 @@ Openbox::Openbox(int argc, char **argv) for (it = _screens.begin(); it != end; ++it) { (*it)->manageExisting(); } - + // grab any keys set up before the screens existed _bindings->grabKeys(true); @@ -212,6 +214,7 @@ Openbox::~Openbox() //delete _display; otk::Timer::destroy(); + otk::RenderStyle::destroy(); otk::RenderColor::destroy(); } diff --git a/src/screen.cc b/src/screen.cc index 9ff1f2b7..41cc6e4c 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -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()); diff --git a/src/screen.hh b/src/screen.hh index ab0bc25a..db8c26d1 100644 --- a/src/screen.hh +++ b/src/screen.hh @@ -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 -- 2.39.2