X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fframe.cc;h=9e97f2b0594e3d91df4506f8c89b2699144fd52e;hb=73a584981e853f03cbd01930d27d138c6b95707b;hp=17ebdb65f1dd54ff5056beb59f21a488e6ac770e;hpb=74cfb1b4c115cdb4e05aa823b09d2b5ea9d0d690;p=chaz%2Fopenbox diff --git a/src/frame.cc b/src/frame.cc index 17ebdb65..9e97f2b0 100644 --- a/src/frame.cc +++ b/src/frame.cc @@ -1,8 +1,6 @@ // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif +#include "config.h" extern "C" { #ifdef SHAPE @@ -11,9 +9,9 @@ extern "C" { } #include "frame.hh" -#include "client.hh" #include "openbox.hh" #include "otk/display.hh" +#include "otk/surface.hh" #include #include @@ -40,15 +38,27 @@ Frame::Frame(Client *client) _handle(0), _lgrip(0), _rgrip(0), - _buttons(0), - _numbuttons(0), - _titleorder(0), + _max(0), + _desk(0), + _iconify(0), + _icon(0), + _close(0), _frame_sur(0), _title_sur(0), _label_sur(0), _handle_sur(0), _grip_sur(0), - _buttons_sur(0) + _max_sur(0), + _desk_sur(0), + _iconify_sur(0), + _icon_sur(0), + _close_sur(0), + _max_press(false), + _desk_press(false), + _iconify_press(false), + _icon_press(false), + _close_press(false), + _press_button(0) { assert(client); @@ -69,6 +79,11 @@ Frame::Frame(Client *client) ExposureMask); _title = createWindow(info, _frame, mask, &attrib); _label = createWindow(info, _title, mask, &attrib); + _max = createWindow(info, _title, mask, &attrib); + _close = createWindow(info, _title, mask, &attrib); + _desk = createWindow(info, _title, mask, &attrib); + _icon = createWindow(info, _title, mask, &attrib); + _iconify = createWindow(info, _title, mask, &attrib); _handle = createWindow(info, _frame, mask, &attrib); mask |= CWCursor; attrib.cursor = openbox->cursors().ll_angle; @@ -84,12 +99,7 @@ Frame::Frame(Client *client) applyStyle(*otk::RenderStyle::style(_client->screen())); - // XXX load buttons - _numbuttons = 0; - _buttons = new Window[0]; - _buttons_sur = new otk::Surface*[0]; - _titleorder = new int[1]; - _titleorder[0] = -1; + _layout = openbox->screen(_client->screen())->config().titlebar_layout; // register all of the windows with the event dispatcher Window *w = allWindows(); @@ -106,13 +116,14 @@ Frame::~Frame() openbox->clearHandler(w[i]); delete [] w; - for (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, _max); + XDestroyWindow(**otk::display, _icon); + XDestroyWindow(**otk::display, _iconify); + XDestroyWindow(**otk::display, _desk); + XDestroyWindow(**otk::display, _close); XDestroyWindow(**otk::display, _label); XDestroyWindow(**otk::display, _title); XDestroyWindow(**otk::display, _frame); @@ -122,10 +133,11 @@ Frame::~Frame() 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; + if (_max_sur) delete _max_sur; + if (_desk_sur) delete _desk_sur; + if (_iconify_sur) delete _iconify_sur; + if (_icon_sur) delete _icon_sur; + if (_close_sur) delete _close_sur; } void Frame::show() @@ -144,6 +156,60 @@ void Frame::hide() } } +void Frame::buttonPressHandler(const XButtonEvent &e) +{ + if (_press_button) return; + _press_button = e.button; + + if (e.window == _max) { + _max_press = true; + renderMax(); + } + if (e.window == _close) { + _close_press = true; + renderClose(); + } + if (e.window == _desk) { + _desk_press = true; + renderDesk(); + } + if (e.window == _iconify) { + _iconify_press = true; + renderIconify(); + } + if (e.window == _icon) { + _icon_press = true; + renderIcon(); + } +} + +void Frame::buttonReleaseHandler(const XButtonEvent &e) +{ + if (e.button != _press_button) return; + _press_button = 0; + + if (e.window == _max) { + _max_press = false; + renderMax(); + } + if (e.window == _close) { + _close_press = false; + renderClose(); + } + if (e.window == _desk) { + _desk_press = false; + renderDesk(); + } + if (e.window == _iconify) { + _iconify_press = false; + renderIconify(); + } + if (e.window == _icon) { + _icon_press = false; + renderIcon(); + } +} + MouseContext::MC Frame::mouseContext(Window win) const { if (win == _frame) return MouseContext::Frame; @@ -153,12 +219,17 @@ MouseContext::MC Frame::mouseContext(Window win) const if (win == _plate) return MouseContext::Window; if (win == _lgrip || win == _rgrip) return MouseContext::Grip; + if (win == _max) return MouseContext::MaximizeButton; + if (win == _close) return MouseContext::CloseButton; + if (win == _desk) return MouseContext::AllDesktopsButton; + if (win == _iconify)return MouseContext::IconifyButton; + if (win == _icon) return MouseContext::IconButton; return (MouseContext::MC) -1; } Window *Frame::allWindows() const { - Window *w = new Window[7 + _numbuttons + 1]; + Window *w = new Window[12 + 1]; unsigned int i = 0; w[i++] = _frame; w[i++] = _plate; @@ -167,8 +238,11 @@ Window *Frame::allWindows() const w[i++] = _handle; w[i++] = _lgrip; w[i++] = _rgrip; - for (int j = 0; j < _numbuttons; ++j) - w[j + i++] = _buttons[j]; + w[i++] = _max; + w[i++] = _desk; + w[i++] = _close; + w[i++] = _icon; + w[i++] = _iconify; w[i] = 0; return w; } @@ -194,9 +268,11 @@ void Frame::applyStyle(const otk::RenderStyle &style) XResizeWindow(**otk::display, _lgrip, geom.grip_width(), geom.handle_height); XResizeWindow(**otk::display, _rgrip, geom.grip_width(), geom.handle_height); - for (int i = 0; i < _numbuttons; ++i) - XResizeWindow(**otk::display, _buttons[i], - geom.button_size, geom.button_size); + XResizeWindow(**otk::display, _max, geom.button_size, geom.button_size); + XResizeWindow(**otk::display, _close, geom.button_size, geom.button_size); + XResizeWindow(**otk::display, _desk, geom.button_size, geom.button_size); + XResizeWindow(**otk::display, _iconify, geom.button_size, geom.button_size); + XResizeWindow(**otk::display, _icon, geom.button_size, geom.button_size); } void Frame::styleChanged(const otk::RenderStyle &style) @@ -222,22 +298,23 @@ void Frame::adjustTitle() static void render(int screen, const otk::Size &size, Window win, otk::Surface **surface, - const otk::RenderTexture &texture) + const otk::RenderTexture &texture, bool freedata=true) { 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; + if (freedata) s->freePixelData(); *surface = s; } void Frame::adjustSize() { - Client::DecorationFlags decorations = _client->decorations(); + _decorations = _client->decorations(); const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen()); - if (decorations & Client::Decor_Border) { + if (_decorations & Client::Decor_Border) { geom.bwidth = style->frameBorderWidth(); geom.cbwidth = style->clientBorderWidth(); } else { @@ -258,7 +335,7 @@ void Frame::adjustSize() // position/size and map/unmap all the windows - if (decorations & Client::Decor_Titlebar) { + 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; @@ -266,10 +343,15 @@ void Frame::adjustSize() // layout the title bar elements layoutTitle(); - } else + } else { XUnmapWindow(**otk::display, _title); + // make all the titlebar stuff not render + _decorations &= ~(Client::Decor_Icon | Client::Decor_Iconify | + Client::Decor_Maximize | Client::Decor_Close | + Client::Decor_AllDesktops); + } - if (decorations & Client::Decor_Handle) { + 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); @@ -307,15 +389,20 @@ void Frame::adjustSize() // render all the elements int screen = _client->screen(); bool focus = _client->focused(); - if (decorations & Client::Decor_Titlebar) { + if (_decorations & Client::Decor_Titlebar) { render(screen, otk::Size(geom.width, geom.title_height()), _title, &_title_sur, *(focus ? style->titlebarFocusBackground() : - style->titlebarUnfocusBackground())); + style->titlebarUnfocusBackground()), false); renderLabel(); + renderMax(); + renderDesk(); + renderIconify(); + renderIcon(); + renderClose(); } - if (decorations & Client::Decor_Handle) { + if (_decorations & Client::Decor_Handle) { render(screen, otk::Size(geom.width, geom.handle_height), _handle, &_handle_sur, *(focus ? style->handleFocusBackground() : style->handleUnfocusBackground())); @@ -384,15 +471,219 @@ void Frame::renderLabel() XSetWindowBackgroundPixmap(**otk::display, _label, s->pixmap()); XClearWindow(**otk::display, _label); if (_label_sur) delete _label_sur; + s->freePixelData(); _label_sur = s; } +static void renderButton(int screen, bool focus, bool press, Window win, + otk::Surface **sur, int butsize, + const otk::PixmapMask *mask) +{ + const otk::RenderStyle *style = otk::RenderStyle::style(screen); + const otk::RenderControl *control = otk::display->renderControl(screen); + otk::Surface *s = new otk::Surface(screen, otk::Size(butsize, butsize)); + + const otk::RenderTexture *tx = (focus ? + (press ? + style->buttonPressFocusBackground() : + style->buttonUnpressFocusBackground()) : + (press ? + style->buttonPressUnfocusBackground() : + style->buttonUnpressUnfocusBackground())); + const otk::RenderColor *maskcolor = (focus ? + style->buttonFocusColor() : + style->buttonUnfocusColor()); + control->drawBackground(*s, *tx); + control->drawMask(*s, *maskcolor, *mask); + + XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap()); + XClearWindow(**otk::display, win); + if (*sur) delete *sur; + s->freePixelData(); + *sur = s; +} + +void Frame::renderMax() +{ + if (!(_decorations & Client::Decor_Maximize)) return; + bool press = _max_press || _client->maxVert() || _client->maxHorz(); + renderButton(_client->screen(), _client->focused(), press, _max, + &_max_sur, geom.button_size, + otk::RenderStyle::style(_client->screen())->maximizeMask()); +} + +void Frame::renderDesk() +{ + if (!(_decorations & Client::Decor_AllDesktops)) return; + bool press = _desk_press || _client->desktop() == 0xffffffff; + renderButton(_client->screen(), _client->focused(), press, _desk, + &_desk_sur, geom.button_size, + otk::RenderStyle::style(_client->screen())->alldesktopsMask()); +} + +void Frame::renderIconify() +{ + if (!(_decorations & Client::Decor_Iconify)) return; + renderButton(_client->screen(), _client->focused(), _iconify_press, _iconify, + &_iconify_sur, geom.button_size, + otk::RenderStyle::style(_client->screen())->iconifyMask()); +} + +void Frame::renderClose() +{ + if (!(_decorations & Client::Decor_Close)) return; + renderButton(_client->screen(), _client->focused(), _close_press, _close, + &_close_sur, geom.button_size, + otk::RenderStyle::style(_client->screen())->closeMask()); +} + +void Frame::renderIcon() +{ + if (!(_decorations & Client::Decor_Icon)) return; + const int screen = _client->screen(); + const otk::RenderControl *control = otk::display->renderControl(screen); + + otk::Surface *s = new otk::Surface(screen, otk::Size(geom.button_size, + geom.button_size)); + otk::pixel32 *dest = s->pixelData(), *src; + int w = _title_sur->size().width(); + + src = _title_sur->pixelData() + w * (geom.bevel + 1) + geom.icon_x; + + // get the background under the icon button + for (int y = 0; y < geom.button_size; ++y, src += w - geom.button_size) + for (int x = 0; x < geom.button_size; ++x, ++dest, ++src) + *dest = *src; + // draw the icon over it + const Icon *icon = _client->icon(otk::Size(geom.button_size, + geom.button_size)); + control->drawImage(*s, icon->w, icon->h, icon->data); + + XSetWindowBackgroundPixmap(**otk::display, _icon, s->pixmap()); + XClearWindow(**otk::display, _icon); + if (_icon_sur) delete _icon_sur; + _icon_sur = s; +} + void Frame::layoutTitle() { + // figure out whats being shown, and the width of the label geom.label_width = geom.width - geom.bevel * 2; + bool n, d, i, t, m ,c; + n = d = i = t = m = c = false; + for (const char *l = _layout.c_str(); *l; ++l) { + switch (*l) { + case 'n': + case 'N': + if (!(_decorations & Client::Decor_Icon)) break; + n = true; + geom.label_width -= geom.button_size + geom.bevel; + break; + case 'd': + case 'D': + if (!(_decorations & Client::Decor_AllDesktops)) break; + d = true; + geom.label_width -= geom.button_size + geom.bevel; + break; + case 'i': + case 'I': + if (!(_decorations & Client::Decor_Iconify)) break; + i = true; + geom.label_width -= geom.button_size + geom.bevel; + break; + case 't': + case 'T': + t = true; + break; + case 'm': + case 'M': + if (!(_decorations & Client::Decor_Maximize)) break; + m = true; + geom.label_width -= geom.button_size + geom.bevel; + break; + case 'c': + case 'C': + if (!(_decorations & Client::Decor_Close)) break; + c = true; + geom.label_width -= geom.button_size + geom.bevel; + break; + } + } if (geom.label_width < 1) geom.label_width = 1; - XMoveResizeWindow(**otk::display, _label, geom.bevel, geom.bevel, - geom.label_width, geom.font_height); + + XResizeWindow(**otk::display, _label, geom.label_width, geom.font_height); + + if (!n) { + _decorations &= ~Client::Decor_Icon; + XUnmapWindow(**otk::display, _icon); + } + if (!d) { + _decorations &= ~Client::Decor_AllDesktops; + XUnmapWindow(**otk::display, _desk); + } + if (!i) { + _decorations &= ~Client::Decor_Iconify; + XUnmapWindow(**otk::display, _iconify); + } + if (!t) + XUnmapWindow(**otk::display, _label); + if (!m) { + _decorations &= ~Client::Decor_Maximize; + XUnmapWindow(**otk::display, _max); + } + if (!c) { + _decorations &= ~Client::Decor_Close; + XUnmapWindow(**otk::display, _close); + } + + int x = geom.bevel; + for (const char *lc = _layout.c_str(); *lc; ++lc) { + switch (*lc) { + case 'n': + case 'N': + if (!n) break; + geom.icon_x = x; + XMapWindow(**otk::display, _icon); + XMoveWindow(**otk::display, _icon, x, geom.bevel + 1); + x += geom.button_size + geom.bevel; + break; + case 'd': + case 'D': + if (!d) break; + XMapWindow(**otk::display, _desk); + XMoveWindow(**otk::display, _desk, x, geom.bevel + 1); + x += geom.button_size + geom.bevel; + break; + case 'i': + case 'I': + if (!i) break; + XMapWindow(**otk::display, _iconify); + XMoveWindow(**otk::display, _iconify, x, geom.bevel + 1); + x += geom.button_size + geom.bevel; + break; + case 't': + case 'T': + if (!t) break; + XMapWindow(**otk::display, _label); + XMoveWindow(**otk::display, _label, x, geom.bevel); + x += geom.label_width + geom.bevel; + break; + case 'm': + case 'M': + if (!m) break; + XMapWindow(**otk::display, _max); + XMoveWindow(**otk::display, _max, x, geom.bevel + 1); + x += geom.button_size + geom.bevel; + break; + case 'c': + case 'C': + if (!c) break; + XMapWindow(**otk::display, _close); + XMoveWindow(**otk::display, _close, x, geom.bevel + 1); + x += geom.button_size + geom.bevel; + break; + } + } } void Frame::adjustPosition() @@ -409,8 +700,6 @@ void Frame::adjustPosition() void Frame::adjustShape() { #ifdef SHAPE - Client::DecorationFlags decorations = _client->decorations(); - if (!_client->shaped()) { // clear the shape on the frame window XShapeCombineMask(**otk::display, _frame, ShapeBounding, @@ -427,7 +716,7 @@ void Frame::adjustShape() int num = 0; XRectangle xrect[2]; - if (decorations & Client::Decor_Titlebar) { + if (_decorations & Client::Decor_Titlebar) { xrect[0].x = -geom.bevel; xrect[0].y = -geom.bevel; xrect[0].width = geom.width + geom.bwidth * 2; @@ -435,7 +724,7 @@ void Frame::adjustShape() ++num; } - if (decorations & Client::Decor_Handle) { + if (_decorations & Client::Decor_Handle) { xrect[1].x = -geom.bevel; xrect[1].y = geom.handle_y; xrect[1].width = geom.width + geom.bwidth * 2; @@ -450,13 +739,16 @@ void Frame::adjustShape() #endif // SHAPE } - void Frame::adjustState() { -// XXX _button_alldesk.update(); -// XXX _button_max.update(); + renderDesk(); + renderMax(); } +void Frame::adjustIcon() +{ + renderIcon(); +} void Frame::grabClient() {