all repos — fluxbox @ 1c2f92a3d2288b1cae9500110a72173506a18072

custom fork of the fluxbox windowmanager

extension of previous big patch. Move a bunch of menu things onto 
background pixmap. Same for textbuttons.
simonb simonb
commit

1c2f92a3d2288b1cae9500110a72173506a18072

parent

b49432be05c6cf748e662e196778463e2190b4c3

M ChangeLogChangeLog

@@ -1,5 +1,19 @@

(Format: Year/Month/Day) Changes for 0.9.13 +*05/04/26: + * Extension of previous patch, pushing various bits of menu items and + text buttons onto the background, and fixing various issues (Simon) + + Incidentally, adds some new theme items (due to backwards + compatibility fix): + - menu.hilite.submenu.pixmap: <Pixmap> + - menu.hilite.selected.pixmap: <Pixmap> + - menu.hilite.unselected.pixmap: <Pixmap> + These are equivalent to the no-.hilite ones, except are shown + when the item is highlighted... + FbTk/... + Menu.hh/cc MenuItem.hh/cc MenuTheme.hh/cc TextButton.hh/cc + FbWindow.hh/cc MenuIcon.hh/cc + FbWinFrame.hh/cc IconButton.hh/cc ToggleMenu.hh Window.cc *05/04/25: * Fixed #1188690, fbrun segfault (Mathias) FbTk/App.cc
M src/ClockTool.ccsrc/ClockTool.cc

@@ -249,6 +249,7 @@ #ifdef HAVE_STRFTIME

if (!strftime(time_string, 255, m_timeformat->c_str(), time_type) || m_button.text() == time_string) return; m_button.setText(time_string); + m_button.parentMoved(); #else // dont have strftime so we have to set it to hour:minut // sprintf(time_string, "%d:%d", ); #endif // HAVE_STRFTIME
M src/FbTk/FbWindow.ccsrc/FbTk/FbWindow.cc

@@ -46,7 +46,7 @@ namespace FbTk {

FbWindow::FbWindow():FbDrawable(), m_parent(0), m_screen_num(0), m_window(0), m_x(0), m_y(0), m_width(0), m_height(0), m_border_width(0), m_depth(0), m_destroy(true), - m_lastbg_pm(0){ + m_lastbg_pm(0), m_renderer(0) { }

@@ -57,7 +57,7 @@ m_x(the_copy.x()), m_y(the_copy.y()),

m_width(the_copy.width()), m_height(the_copy.height()), m_border_width(the_copy.borderWidth()), m_depth(the_copy.depth()), m_destroy(true), - m_lastbg_pm(0) { + m_lastbg_pm(0), m_renderer(the_copy.m_renderer) { the_copy.m_window = 0; }

@@ -75,7 +75,7 @@ m_screen_num(screen_num),

m_destroy(true), m_lastbg_color_set(false), m_lastbg_color(0), - m_lastbg_pm(0) { + m_lastbg_pm(0), m_renderer(0) { create(RootWindow(display(), screen_num), x, y, width, height, eventmask,

@@ -93,7 +93,7 @@ m_screen_num(parent.screenNumber()),

m_destroy(true), m_lastbg_color_set(false), m_lastbg_color(0x42), - m_lastbg_pm(0) { + m_lastbg_pm(0), m_renderer(0) { create(parent.window(), x, y, width, height, eventmask, override_redirect, save_unders, depth, class_type);

@@ -109,7 +109,7 @@ m_width(1), m_height(1),

m_border_width(0), m_depth(0), m_destroy(false), // don't destroy this window - m_lastbg_pm(0) { + m_lastbg_pm(0), m_renderer(0) { setNew(client); }

@@ -166,22 +166,19 @@ Pixmap root = FbPixmap::getRootPixmap(screenNumber());

if (m_transparent->source() != root) m_transparent->setSource(root, screenNumber()); - newbg = XCreatePixmap(display(), window(), width(), height(), depth()); - free_newbg = true; + FbPixmap newpm = FbPixmap(*this, width(), height(), depth()); + free_newbg = true; // newpm gets released to newbg at end of block GC gc = XCreateGC(display(), window(), 0, 0); if (m_lastbg_pm == None && m_lastbg_color_set) { XSetForeground(display(), gc, m_lastbg_color); - XFillRectangle(display(), newbg, gc, 0, 0, width(), height()); + newpm.fillRectangle(gc, 0, 0, width(), height()); } else { // copy from window if no color and no bg... - XCopyArea(display(), (m_lastbg_pm == None)?drawable():m_lastbg_pm, newbg, gc, - 0, 0, - width(), height(), - 0, 0); + newpm.copyArea((m_lastbg_pm == None)?drawable():m_lastbg_pm, gc, 0, 0, 0, 0, width(), height()); } XFreeGC(display(), gc); - m_transparent->setDest(newbg, screenNumber()); + m_transparent->setDest(newpm.drawable(), screenNumber()); // get root position

@@ -202,7 +199,13 @@ // render background image from root pos to our window

m_transparent->render(root_x, root_y, 0, 0, width(), height()); + + // render any foreground items + if (m_renderer) + m_renderer->renderForeground(*this, newpm); + m_transparent->freeDest(); // it's only temporary, don't leave it hanging around + newbg = newpm.release(); } if (newbg != None)

@@ -238,10 +241,14 @@

void FbWindow::clearArea(int x, int y, unsigned int width, unsigned int height, bool exposures) { + // TODO: probably could call renderForeground here (with x,y,w,h) XClearArea(display(), window(), x, y, width, height, exposures); } -void FbWindow::updateTransparent(int the_x, int the_y, unsigned int the_width, unsigned int the_height) { +// If override_is_offset, then dest_override is a pixmap located at the_x, the_y +// with size the_width x the_height in the target window. + +void FbWindow::updateTransparent(int the_x, int the_y, unsigned int the_width, unsigned int the_height, Pixmap dest_override, bool override_is_offset) { #ifdef HAVE_XRENDER if (!m_transparent.get()) return;

@@ -249,12 +256,15 @@

if (width() == 0 || height() == 0) return; - if ((the_width == 0 && the_height == 0 || the_width == width() && the_height == height()) && + if (!dest_override && (the_width == 0 && the_height == 0 || the_width == width() && the_height == height()) && the_x <= 0 && the_y <= 0) { // do the whole thing updateBackground(true); return; } + + if (!dest_override) + dest_override = window(); if (the_width == 0 || the_height == 0) { the_width = width();

@@ -271,8 +281,8 @@ Pixmap root = FbPixmap::getRootPixmap(screenNumber());

if (m_transparent->source() != root) m_transparent->setSource(root, screenNumber()); - if (m_transparent->dest() != window()) - m_transparent->setDest(window(), screenNumber()); + if (m_transparent->dest() != dest_override) + m_transparent->setDest(dest_override, screenNumber()); // get root position

@@ -292,7 +302,7 @@ } // else toplevel window so we already have x, y set

// render background image from root pos to our window m_transparent->render(root_x + the_x, root_y + the_y, - the_x, the_y, + override_is_offset?0:the_x, override_is_offset?0:the_y, the_width, the_height); #endif // HAVE_XRENDER }

@@ -496,12 +506,6 @@ unsigned int opacity = alpha << 24;

changeProperty(m_alphaatom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1l); #endif // HAVE_XRENDER } - -/* -void FbWindow::setBufferPixmap(Pixmap pm) { - m_lastbg_pm = pm; -} -*/ void FbWindow::updateGeometry() { if (m_window == 0)
M src/FbTk/FbWindow.hhsrc/FbTk/FbWindow.hh

@@ -34,6 +34,8 @@ namespace FbTk {

class Color; class Transparent; +class FbPixmap; +class FbWindowRenderer; /// Wrapper for X window /**

@@ -82,7 +84,7 @@ /// @param exposures wheter Expose event should be generated

virtual void clearArea(int x, int y, unsigned int width, unsigned int height, bool exposures = false); - void updateTransparent(int x = -1, int y = -1, unsigned int width = 0, unsigned int height = 0); + void updateTransparent(int x = -1, int y = -1, unsigned int width = 0, unsigned int height = 0, Pixmap dest_override = None, bool override_is_offset = false); void setAlpha(unsigned char alpha);

@@ -182,6 +184,8 @@

// used for composite void setOpaque(unsigned char alpha); + void setRenderer(FbWindowRenderer &renderer) { m_renderer = &renderer; } + protected: /// creates a window with x window client (m_window = client) explicit FbWindow(Window client);

@@ -213,6 +217,8 @@ std::auto_ptr<FbTk::Transparent> m_transparent;

bool m_lastbg_color_set; unsigned long m_lastbg_color; Pixmap m_lastbg_pm; + + FbWindowRenderer *m_renderer; }; bool operator == (Window win, const FbWindow &fbwin);

@@ -235,8 +241,14 @@ Atom m_prop;

unsigned char *m_state; int m_num; int m_mode; +}; +/// Interface class to render FbWindow foregrounds. +class FbWindowRenderer { +public: + virtual void renderForeground(FbWindow &win, FbDrawable &drawable) = 0; }; + } // end namespace FbTk
M src/FbTk/GContext.hhsrc/FbTk/GContext.hh

@@ -131,6 +131,7 @@

void copy(GC gc); void copy(const GContext &gc); + inline GContext &operator = (const GContext &copy_gc) { copy(copy_gc); return *this; } inline GContext &operator = (GC copy_gc) { copy(copy_gc); return *this; } inline GC gc() const { return m_gc; }
M src/FbTk/Menu.ccsrc/FbTk/Menu.cc

@@ -121,9 +121,7 @@ m_which_sbl = -1;

menu.frame_pixmap = menu.title_pixmap = - menu.hilite_pixmap = - menu.sel_pixmap = None; - + menu.hilite_pixmap = None; menu.item_w = menu.frame_h = theme().titleFont().height() + theme().bevelWidth() * 2;

@@ -157,6 +155,7 @@ false, // override redirect

true); // save under evm.add(*this, menu.title); + menu.title.setRenderer(*this); event_mask |= PointerMotionMask; menu.frame = FbTk::FbWindow(menu.window, // parent

@@ -166,6 +165,7 @@ event_mask, // mask

false, // override redirect true); // save under evm.add(*this, menu.frame); + menu.frame.setRenderer(*this); menu.title.raise();

@@ -189,9 +189,6 @@ m_image_ctrl.removeImage(menu.frame_pixmap);

if (menu.hilite_pixmap) m_image_ctrl.removeImage(menu.hilite_pixmap); - - if (menu.sel_pixmap) - m_image_ctrl.removeImage(menu.sel_pixmap); if (s_focused == this) s_focused = 0;

@@ -285,7 +282,7 @@ // we need to do this explicitly on the menu.window

// since it might hide the parent if we use Menu::hide menuitems[old_which_press]->submenu()->internal_hide(); } - drawItem(old_which_press, true); // clear + clearItem(old_which_press); } // restore old in case we changed m_which_press

@@ -306,7 +303,7 @@ }

m_active_index = m_which_press; - drawItem(m_which_press, true); // clear + clearItem(m_which_press); }

@@ -320,7 +317,7 @@ // we need to do this explicitly on the menu.window

// since it might hide the parent if we use Menu::hide menuitems[old_which_press]->submenu()->internal_hide(); } - drawItem(old_which_press, true); // clear + clearItem(old_which_press); } // restore old in case we changed m_which_press m_which_press = old_which_press - 1;

@@ -340,7 +337,7 @@ }

m_active_index = m_which_press; - drawItem(m_which_press, true); // clear + clearItem(m_which_press); }

@@ -370,7 +367,7 @@ if (submenu)

submenu->internal_hide(); m_active_index = -1; - drawItem(m_which_press, true); // clear + //clearItem(m_which_press); m_which_press = -1; // dont select any in this // hide self m_visible = false;

@@ -451,7 +448,36 @@

if (menu.frame.alpha() != alpha()) menu.frame.setAlpha(alpha()); - Pixmap tmp = 0; + Pixmap tmp = menu.hilite_pixmap; + const FbTk::Texture &hilite_tex = theme().hiliteTexture(); + if (!hilite_tex.usePixmap()) { + menu.hilite_pixmap = None; + } else + menu.hilite_pixmap = + m_image_ctrl.renderImage(menu.item_w, theme().itemHeight(), hilite_tex); + if (tmp) + m_image_ctrl.removeImage(tmp); + + + if (!theme().selectedPixmap().pixmap().drawable()) { + int hw = theme().itemHeight() / 2; + m_theme.setSelectedPixmap(m_image_ctrl.renderImage(hw, hw, theme().hiliteTexture())); + + if (!theme().highlightSelectedPixmap().pixmap().drawable()) { + int hw = theme().itemHeight() / 2; + m_theme.setHighlightSelectedPixmap(m_image_ctrl.renderImage(hw, hw, theme().frameTexture())); + } + } + + if (m_title_vis) { + menu.title.moveResize(-menu.title.borderWidth(), -menu.title.borderWidth(), + width() + menu.title.borderWidth(), theme().titleHeight()); + } + + menu.frame.moveResize(0, ((m_title_vis) ? menu.title.y() + menu.title.height() + + menu.title.borderWidth()*2 : 1), + width(), menu.frame_h); + if (m_title_vis && m_need_update) { tmp = menu.title_pixmap; const FbTk::Texture &tex = theme().titleTexture();

@@ -485,46 +511,8 @@ if (tmp)

m_image_ctrl.removeImage(tmp); } - tmp = menu.hilite_pixmap; - const FbTk::Texture &hilite_tex = theme().hiliteTexture(); - if (!hilite_tex.usePixmap()) { - menu.hilite_pixmap = None; - } else - menu.hilite_pixmap = - m_image_ctrl.renderImage(menu.item_w, theme().itemHeight(), hilite_tex); - if (tmp) - m_image_ctrl.removeImage(tmp); - tmp = menu.sel_pixmap; - if (!hilite_tex.usePixmap()) { - menu.sel_pixmap = None; - } else { - int hw = theme().itemHeight() / 2; - menu.sel_pixmap = - m_image_ctrl.renderImage(hw, hw, hilite_tex); - } - if (tmp) - m_image_ctrl.removeImage(tmp); - - - - if (m_title_vis) { - menu.title.moveResize(-menu.title.borderWidth(), -menu.title.borderWidth(), - width() + menu.title.borderWidth(), theme().titleHeight()); - } - - menu.frame.moveResize(0, ((m_title_vis) ? menu.title.y() + menu.title.height() + - menu.title.borderWidth()*2 : 1), - width(), menu.frame_h); - - // if menu m_visible and title m_visible - if (m_title_vis && m_visible) - redrawTitle(); - - if (m_visible && (active_index >= 0 || m_need_update)) { - redrawFrame(); - } - + clearWindow(); m_need_update = false; }

@@ -583,14 +571,18 @@ }

void Menu::clearWindow() { - redrawTitle(); - redrawFrame(); + menu.title.clear(); + menu.frame.clear(); + + // clear foreground bits of frame items + for (unsigned int i = 0; i < menuitems.size(); i++) { + clearItem(i, false); // no clear + } } -void Menu::redrawFrame() { - menu.frame.clear(); +void Menu::redrawFrame(FbDrawable &drawable) { for (unsigned int i = 0; i < menuitems.size(); i++) { - drawItem(i, false); // no clear + drawItem(drawable, i); } }

@@ -606,7 +598,7 @@ // if we have an active index we need to redraw it

// as non active int old = m_active_index; m_active_index = -1; - drawItem(old, true); // clear old area from highlight + clearItem(old); // clear old area from highlight if (shown && shown->menu.window == menu.window) shown = (Menu *) 0;

@@ -638,7 +630,7 @@ drawSubmenu(m_which_sub);

} -void Menu::redrawTitle() { +void Menu::redrawTitle(FbDrawable &drawable) { const char *text = menu.label.c_str(); const FbTk::Font &font = theme().titleFont();

@@ -657,16 +649,9 @@ default:

break; } - if (menu.title.alpha() != alpha()) - menu.title.setAlpha(alpha()); - - FbTk::GContext def_gc(menu.title); - - menu.title.clear(); - // difference between height based on font, and style-set height int height_offset = theme().titleHeight() - (font.height() + 2*theme().bevelWidth()); - font.drawText(menu.title, // drawable + font.drawText(drawable, // drawable screenNumber(), theme().titleTextGC().gc(), // graphic context text, len, // text string with length

@@ -741,7 +726,7 @@ new_y = m_screen_y;

item->submenu()->move(new_x, new_y); if (! m_moving) - drawItem(index); + clearItem(index); if (! item->submenu()->isVisible()) { item->submenu()->show();

@@ -766,99 +751,24 @@ return true;

} -int Menu::drawItem(unsigned int index, bool clear, - int x, int y, unsigned int w, unsigned int h) { +int Menu::drawItem(FbDrawable &drawable, unsigned int index, + bool highlight, bool exclusive_drawable) { + if (index >= menuitems.size() || menuitems.size() == 0 || menu.persub == 0) return 0; - // don't bother if we're not showing - if (!isVisible()) - return 0; - MenuItem *item = menuitems[index]; if (! item) return 0; int sbl = index / menu.persub, i = index - (sbl * menu.persub); int item_x = (sbl * menu.item_w), item_y = (i * theme().itemHeight()); - unsigned int item_w = menu.item_w, item_h = theme().itemHeight(); - int hilite_x = item_x, hilite_y = item_y, hoff_x = 0, hoff_y = 0; - int sel_x = 0, sel_y = 0; - unsigned int hilite_w = menu.item_w, hilite_h = theme().itemHeight(); - unsigned int half_w = theme().itemHeight() / 2, quarter_w = theme().itemHeight() / 4; - bool highlight = (index == m_active_index); - GC gc = - ((highlight || item->isSelected()) ? theme().hiliteTextGC().gc() : - theme().frameTextGC().gc()); - - sel_x = item_x; - - if (theme().bulletPos() == FbTk::RIGHT) - sel_x += (menu.item_w - theme().itemHeight() - theme().bevelWidth()); - - sel_x += quarter_w; - sel_y = item_y + quarter_w; - if (clear) { - frameWindow().clearArea(item_x, item_y, - menu.item_w, theme().itemHeight(), False); - } + if (exclusive_drawable) + item_x = item_y = 0; - if (highlight && (menu.hilite_pixmap != ParentRelative)) { - if (menu.hilite_pixmap) { - menu.frame.copyArea(menu.hilite_pixmap, - theme().hiliteGC().gc(), hoff_x, hoff_y, - item_x, item_y, - item_w, item_h); - } else { - menu.frame.fillRectangle(theme().hiliteGC().gc(), - item_x, item_y, item_w, item_h); - } - menu.frame.updateTransparent(item_x, item_y, item_w, item_h); - } - - //!! - //!! TODO: Move this out to MenuItem - //!! current problem: menu.sel_pixmap needs a image control instance - //!! to be generated :( - //!! - if (item->isToggleItem() && item->isSelected()) { - Display *disp = FbTk::App::instance()->display(); - if (theme().selectedPixmap().pixmap().drawable()) { - - // enable clip mask - XSetClipMask(disp, - gc, - theme().selectedPixmap().mask().drawable()); - XSetClipOrigin(disp, - gc, sel_x, item_y); - // copy bullet pixmap to frame - menu.frame.copyArea(theme().selectedPixmap().pixmap().drawable(), - gc, - 0, 0, - sel_x, item_y, - theme().selectedPixmap().width(), - theme().selectedPixmap().height()); - // disable clip mask - XSetClipMask(disp, - gc, - None); - } else { - if (highlight && menu.sel_pixmap) { - menu.frame.copyArea(menu.sel_pixmap, - theme().hiliteGC().gc(), - 0, 0, - sel_x, sel_y, - half_w, half_w); - } else { - menu.frame.fillRectangle(theme().hiliteGC().gc(), - sel_x, sel_y, half_w, half_w); - } - } - - } - - item->draw(menu.frame, theme(), highlight, + item->draw(drawable, theme(), highlight, + exclusive_drawable, true, // draw fg, draw bg item_x, item_y, menu.item_w, theme().itemHeight());

@@ -955,8 +865,6 @@

if (item->submenu()) { if (!item->submenu()->isVisible()) drawSubmenu(w); - } else { - drawItem(w, true); // clear } } } else {

@@ -978,8 +886,7 @@ if (alpha() < 255) {

// update these since we've (probably) moved menu.title.parentMoved(); menu.frame.parentMoved(); - redrawTitle(); - redrawFrame(); + clearWindow(); } }

@@ -1002,7 +909,7 @@ itemSelected(re.button, w);

} } - drawItem(p, true); // clear + clearItem(p); } } }

@@ -1016,8 +923,8 @@

if (! m_moving) { // if not m_moving: start m_moving operation if (m_parent && (! m_torn)) { - m_parent->drawItem(m_parent->m_which_sub, true); // clear m_parent->m_which_sub = -1; + m_parent->clearItem(m_parent->m_which_sub); // clear } m_moving = m_torn = true;

@@ -1047,10 +954,9 @@ MenuItem *item = menuitems[old];

if (item != 0) { - drawItem(old, true); // clear + clearItem(old); if (item->submenu()) { - if (item->submenu()->isVisible() && !item->submenu()->isTorn()) { // setup hide timer for submenu

@@ -1085,8 +991,8 @@ // if submenu,

// draw item highlighted and // start submenu open delay - drawItem(w, true); // clear - + clearItem(w); + if (theme().menuMode() == MenuTheme::DELAY_OPEN) { // setup show menu timer timeval timeout;

@@ -1102,7 +1008,7 @@ // else normal menu item

// draw highlighted m_submenu_timer.stop(); if (itmp->isEnabled()) { - drawItem(w, true); // clear + clearItem(w); } }

@@ -1112,10 +1018,8 @@

void Menu::exposeEvent(XExposeEvent &ee) { if (ee.window == menu.title) { - redrawTitle(); + menu.title.clearArea(ee.x, ee.y, ee.width, ee.height); } else if (ee.window == menu.frame) { - menu.frame.clearArea(ee.x, ee.y, ee.width, ee.height); - // find where to clear // this is a compilicated algorithm... lets do it step by step... // first... we see in which sub level the expose starts... and how many

@@ -1140,7 +1044,7 @@ Menuitems::iterator it_end = menuitems.end();

for (ii = id; ii <= id_d && it != it_end; ++it, ii++) { int index = ii + (i * menu.persub); // redraw the item - drawItem(index, false); // no clear + clearItem(index); } } }

@@ -1187,7 +1091,7 @@

if (w != m_which_sub && (! tmp->submenu()->isTorn())) { tmp->submenu()->internal_hide(); - drawItem(m_which_sub, true); // clear + clearItem(m_which_sub); // not highlighted anymore m_which_sub = -1; } }

@@ -1198,18 +1102,6 @@ void Menu::leaveNotifyEvent(XCrossingEvent &ce) {

if (menu.frame != ce.window) return; - if (m_which_press != -1 && m_which_sbl != -1 && menuitems.size() > 0) { - int p = (m_which_sbl * menu.persub) + m_which_press; - - drawItem(p, true); // clear - - m_which_sbl = m_which_press = -1; - } - - if (m_shifted) { - // menu.window.move(menu.x, menu.y); - m_shifted = false; - } } void Menu::keyPressEvent(XKeyEvent &event) {

@@ -1282,7 +1174,7 @@ int item = m_which_sbl * menu.persub + m_which_press;

if (!validIndex(item)) return; - drawItem(item, true); // clear + clearItem(item); if (menuitems[item]->submenu() != 0 && !menuitems[item]->submenu()->isVisible()) drawSubmenu(item);

@@ -1311,8 +1203,9 @@ m_need_update = true;

Menuitems::iterator it = menuitems.begin(); Menuitems::iterator it_end = menuitems.end(); - for (; it != it_end; ++it) + for (; it != it_end; ++it) { (*it)->updateTheme(theme()); + } reconfigure(); }

@@ -1322,6 +1215,74 @@ m_screen_x = x;

m_screen_y = y; m_screen_width = w; m_screen_height = h; +} + +// Render the foreground objects of given window onto given pixmap +void Menu::renderForeground(FbWindow &win, FbDrawable &drawable) { + if (&win == &menu.frame) { + redrawFrame(drawable); + } else if (&win == &menu.title) { + redrawTitle(drawable); + } +} + +// clear item clears the item and draws the dynamic bits +// thus sometimes it won't perform the actual clear operation +// nothing in here should be rendered transparently +// (unless you use a caching pixmap, which I think we should avoid) +void Menu::clearItem(int index, bool clear) { + if (!validIndex(index)) + return; + + int sbl = index / menu.persub, i = index - (sbl * menu.persub); + unsigned int item_w = menu.item_w, item_h = theme().itemHeight(); + int item_x = (sbl * item_w), item_y = (i * item_h); + bool highlight = (index == m_active_index); + + if (highlight) { + highlightItem(index); + return; + } else if (clear) + menu.frame.clearArea(item_x, item_y, item_w, item_h); + + MenuItem *item = menuitems[index]; + if (! item) return; + + item->draw(menu.frame, theme(), highlight, + true, false, item_x, item_y, + item_w, item_h); +} + +// Area must have been cleared before calling highlight +void Menu::highlightItem(int index) { + int sbl = index / menu.persub, i = index - (sbl * menu.persub); + unsigned int item_w = menu.item_w, item_h = theme().itemHeight(); + int item_x = (sbl * menu.item_w), item_y = (i * item_h); + + FbPixmap buffer = FbPixmap(menu.frame, item_w, item_h, menu.frame.depth()); + + int hilite_x = item_x, hilite_y = item_y; + if (menu.hilite_pixmap != ParentRelative) { + if (menu.hilite_pixmap) { + buffer.copyArea(menu.hilite_pixmap, + theme().hiliteGC().gc(), 0, 0, + 0, 0, + item_w, item_h); + } else { + buffer.fillRectangle(theme().hiliteGC().gc(), + 0, 0, item_w, item_h); + } + menu.frame.updateTransparent(item_x, item_y, item_w, item_h, buffer.drawable(), true); + } + + + drawItem(buffer, index, true, true); + + menu.frame.copyArea(buffer.drawable(), theme().hiliteGC().gc(), + 0, 0, + item_x, item_y, + item_w, item_h); + } }; // end namespace FbTk
M src/FbTk/Menu.hhsrc/FbTk/Menu.hh

@@ -47,7 +47,7 @@ class MenuItem;

class ImageControl; /// Base class for menus -class Menu: public FbTk::EventHandler, protected FbTk::Observer { +class Menu: public FbTk::EventHandler, FbTk::FbWindowRenderer, protected FbTk::Observer { public: enum Alignment{ ALIGNDONTCARE = 1, ALIGNTOP, ALIGNBOTTOM }; enum { RIGHT = 1, LEFT };

@@ -166,6 +166,8 @@

inline Menu *parent() { return m_parent; } inline const Menu *parent() const { return m_parent; } + void renderForeground(FbWindow &win, FbDrawable &drawable); + protected: inline void setTitleVisibility(bool b) {

@@ -177,12 +179,14 @@ titleWindow().raise();

} virtual void itemSelected(int button, unsigned int index) { } - virtual int drawItem(unsigned int index, - bool clear = false, - int x= -1, int y= -1, - unsigned int width= 0, unsigned int height= 0); - virtual void redrawTitle(); - virtual void redrawFrame(); + // renders item onto pm + int drawItem(FbDrawable &pm, unsigned int index, + bool highlight = false, + bool exclusive_drawable = false); + void clearItem(int index, bool clear = true); + void highlightItem(int index); + virtual void redrawTitle(FbDrawable &pm); + virtual void redrawFrame(FbDrawable &pm); virtual void internal_hide();

@@ -197,7 +201,7 @@ void stopHide();

typedef std::vector<MenuItem *> Menuitems; - const MenuTheme &m_theme; + MenuTheme &m_theme; Menu *m_parent; ImageControl &m_image_ctrl; Menuitems menuitems;

@@ -215,7 +219,7 @@ int m_which_sub, m_which_press, m_which_sbl;

Alignment m_alignment; struct _menu { - Pixmap frame_pixmap, title_pixmap, hilite_pixmap, sel_pixmap; + Pixmap frame_pixmap, title_pixmap, hilite_pixmap; FbTk::FbWindow window, frame, title; std::string label;
M src/FbTk/MenuIcon.ccsrc/FbTk/MenuIcon.cc

@@ -53,35 +53,39 @@ }

void MenuIcon::draw(FbDrawable &drawable, const MenuTheme &theme, - bool highlight, + bool highlight, bool draw_foreground, bool draw_background, int x, int y, unsigned int width, unsigned int height) const { - Display *disp = FbTk::App::instance()->display(); - if (height - 2*theme.bevelWidth() != m_pixmap.height() && - !m_filename.empty()) { - unsigned int scale_size = height - 2*theme.bevelWidth(); - m_pixmap.scale(scale_size, scale_size); - m_mask.scale(scale_size, scale_size); - } + // all background + if (draw_background) { + Display *disp = FbTk::App::instance()->display(); + if (height - 2*theme.bevelWidth() != m_pixmap.height() && + !m_filename.empty()) { + unsigned int scale_size = height - 2*theme.bevelWidth(); + m_pixmap.scale(scale_size, scale_size); + m_mask.scale(scale_size, scale_size); + } - if (m_pixmap.drawable() != 0) { - GC gc = theme.frameTextGC().gc(); + if (m_pixmap.drawable() != 0) { + GC gc = theme.frameTextGC().gc(); - // enable clip mask - XSetClipMask(disp, gc, m_mask.drawable()); - XSetClipOrigin(disp, gc, x + theme.bevelWidth(), y + theme.bevelWidth()); + // enable clip mask + XSetClipMask(disp, gc, m_mask.drawable()); + XSetClipOrigin(disp, gc, x + theme.bevelWidth(), y + theme.bevelWidth()); - drawable.copyArea(m_pixmap.drawable(), - gc, - 0, 0, - x + theme.bevelWidth(), y + theme.bevelWidth(), - m_pixmap.width(), m_pixmap.height()); + drawable.copyArea(m_pixmap.drawable(), + gc, + 0, 0, + x + theme.bevelWidth(), y + theme.bevelWidth(), + m_pixmap.width(), m_pixmap.height()); - // restore clip mask - XSetClipMask(disp, gc, None); + // restore clip mask + XSetClipMask(disp, gc, None); + } } - FbTk::MenuItem::draw(drawable, theme, highlight, x, y, width, height); + FbTk::MenuItem::draw(drawable, theme, highlight, + draw_background, draw_foreground, x, y, width, height); } unsigned int MenuIcon::width(const MenuTheme &theme) const {
M src/FbTk/MenuIcon.hhsrc/FbTk/MenuIcon.hh

@@ -38,6 +38,7 @@ MenuIcon(const std::string &filename, const std::string &label, int screen_num);

void draw(FbDrawable &drawable, const MenuTheme &theme, bool highlight, + bool draw_foreground, bool draw_background, int x, int y, unsigned int width, unsigned int height) const; unsigned int width(const MenuTheme &item) const;
M src/FbTk/MenuItem.ccsrc/FbTk/MenuItem.cc

@@ -39,142 +39,194 @@ }

void MenuItem::draw(FbDrawable &draw, const MenuTheme &theme, - bool highlight, + bool highlight, bool draw_foreground, bool draw_background, int x, int y, unsigned int width, unsigned int height) const { + // text and submenu icon are background + // selected pixmaps are foreground + Display *disp = App::instance()->display(); // // Icon // - if (m_icon.get() != 0 && m_icon->pixmap.get() != 0) { - // scale pixmap to right size - if (height - 2*theme.bevelWidth() != m_icon->pixmap->height() && - !m_icon->filename.empty()) { - unsigned int scale_size = height - 2*theme.bevelWidth(); - m_icon->pixmap->scale(scale_size, scale_size); - } + if (draw_background) { + if (m_icon.get() != 0 && m_icon->pixmap.get() != 0) { + // scale pixmap to right size + if (height - 2*theme.bevelWidth() != m_icon->pixmap->height() && + !m_icon->filename.empty()) { + unsigned int scale_size = height - 2*theme.bevelWidth(); + m_icon->pixmap->scale(scale_size, scale_size); + } - if (m_icon->pixmap->pixmap().drawable() != 0) { - GC gc = theme.frameTextGC().gc(); - int icon_x = x + theme.bevelWidth(); - int icon_y = y + theme.bevelWidth(); - // enable clip mask - XSetClipMask(disp, gc, m_icon->pixmap->mask().drawable()); - XSetClipOrigin(disp, gc, icon_x, icon_y); + if (m_icon->pixmap->pixmap().drawable() != 0) { + GC gc = theme.frameTextGC().gc(); + int icon_x = x + theme.bevelWidth(); + int icon_y = y + theme.bevelWidth(); + // enable clip mask + XSetClipMask(disp, gc, m_icon->pixmap->mask().drawable()); + XSetClipOrigin(disp, gc, icon_x, icon_y); - draw.copyArea(m_icon->pixmap->pixmap().drawable(), - gc, - 0, 0, - icon_x, icon_y, - m_icon->pixmap->width(), m_icon->pixmap->height()); + draw.copyArea(m_icon->pixmap->pixmap().drawable(), + gc, + 0, 0, + icon_x, icon_y, + m_icon->pixmap->width(), m_icon->pixmap->height()); - // restore clip mask - XSetClipMask(disp, gc, None); + // restore clip mask + XSetClipMask(disp, gc, None); + } } - } if (label().empty()) return; - const GContext &tgc = - (highlight ? theme.hiliteTextGC() : - (isEnabled() ? theme.frameTextGC() : theme.disableTextGC() ) ); - // - // Text - // - int text_y = y, text_x = x; + // text is background + if (draw_background) { + const GContext &tgc = + (highlight ? theme.hiliteTextGC() : + (isEnabled() ? theme.frameTextGC() : theme.disableTextGC() ) ); + // + // Text + // + int text_y = y, text_x = x; - int text_w = theme.frameFont().textWidth(label().c_str(), label().size()); + int text_w = theme.frameFont().textWidth(label().c_str(), label().size()); - int height_offset = theme.itemHeight() - (theme.frameFont().height() + 2*theme.bevelWidth()); - text_y = y + theme.bevelWidth() + theme.frameFont().ascent() + height_offset/2; ///2 + height/2; + int height_offset = theme.itemHeight() - (theme.frameFont().height() + 2*theme.bevelWidth()); + text_y = y + theme.bevelWidth() + theme.frameFont().ascent() + height_offset/2; - switch(theme.frameFontJustify()) { - case FbTk::LEFT: - text_x = x + theme.bevelWidth() + height + 1; - break; + switch(theme.frameFontJustify()) { + case FbTk::LEFT: + text_x = x + theme.bevelWidth() + height + 1; + break; + + case FbTk::RIGHT: + text_x = x + width - (height + theme.bevelWidth() + text_w); + break; + default: //center + text_x = x + ((width + 1 - text_w) / 2); + break; + } - case FbTk::RIGHT: - text_x = x + width - (height + theme.bevelWidth() + text_w); - break; - default: //center - text_x = x + ((width + 1 - text_w) / 2); - break; + theme.frameFont().drawText(draw, // drawable + theme.screenNum(), + tgc.gc(), + m_label.c_str(), m_label.size(), // text string and lenght + text_x, text_y); // position } - theme.frameFont().drawText(draw, // drawable - theme.screenNum(), - tgc.gc(), - m_label.c_str(), m_label.size(), // text string and lenght - text_x, text_y); // position + GC gc = (highlight) ? theme.hiliteTextGC().gc() : + theme.frameTextGC().gc(); + int sel_x = x; + int sel_y = y; + unsigned int item_pm_height = theme.itemHeight(); - GC gc = - ((highlight || isSelected()) ? theme.hiliteTextGC().gc() : - theme.frameTextGC().gc()); + if (theme.bulletPos() == FbTk::RIGHT) + sel_x += width - height - theme.bevelWidth(); - int sel_x = x + height/4; + // selected pixmap is foreground + if (draw_foreground && isToggleItem()) { + // + // ToggleItem + // + const PixmapWithMask *pm = 0; - if (theme.bulletPos() == FbTk::RIGHT) - sel_x += width - height - 2*theme.bevelWidth(); + if (isSelected()) { + if (highlight && theme.highlightSelectedPixmap().pixmap().drawable() != 0) + pm = &theme.highlightSelectedPixmap(); + else + pm = &theme.selectedPixmap(); + } else { + if (highlight && theme.highlightUnselectedPixmap().pixmap().drawable() != 0) + pm = &theme.highlightUnselectedPixmap(); + else + pm = &theme.unselectedPixmap(); + } + if (pm != 0 && pm->pixmap().drawable() != 0) { + unsigned int selw = pm->width(); + unsigned int selh = pm->height(); + int offset_x = 0; + int offset_y = 0; + if (selw < item_pm_height) + offset_x += (item_pm_height - selw) / 2; + if (selh < item_pm_height) + offset_y += (item_pm_height - selh) / 2; - // - // ToggleItem - // - if (isToggleItem() && theme.unselectedPixmap().pixmap().drawable() != 0) { - XSetClipMask(disp, gc, theme.unselectedPixmap().mask().drawable()); - XSetClipOrigin(disp, gc, sel_x, y); - // copy bullet pixmap to drawable - draw.copyArea(theme.unselectedPixmap().pixmap().drawable(), - gc, - 0, 0, - sel_x, y, - theme.unselectedPixmap().width(), - theme.unselectedPixmap().height()); - // disable clip mask - XSetClipMask(disp, gc, None); + XSetClipMask(disp, gc, pm->mask().drawable()); + XSetClipOrigin(disp, gc, sel_x+offset_x, sel_y+offset_y); + // copy bullet pixmap to drawable + draw.copyArea(pm->pixmap().drawable(), + gc, + 0, 0, + sel_x+offset_x, sel_y+offset_y, + selw, + selh); + // disable clip mask + XSetClipMask(disp, gc, None); + } else if (isSelected()) { + draw.fillRectangle(theme.hiliteGC().gc(), + sel_x+item_pm_height/4, sel_y+item_pm_height/4, item_pm_height/2, item_pm_height/2); + } } // - // Submenu + // Submenu (background) // - if (submenu()) { - if (theme.bulletPixmap().pixmap().drawable() != 0) { - // enable clip mask - XSetClipMask(disp, gc, theme.bulletPixmap().mask().drawable()); - XSetClipOrigin(disp, gc, sel_x, y); - // copy bullet pixmap to frame - draw.copyArea(theme.bulletPixmap().pixmap().drawable(), + if (draw_background && submenu()) { + + const PixmapWithMask *pm = 0; + + if (highlight && theme.highlightBulletPixmap().pixmap().drawable() != 0) + pm = &theme.highlightBulletPixmap(); + else + pm = &theme.bulletPixmap(); + + if (pm && pm->pixmap().drawable() != 0) { + unsigned int selw = pm->width(); + unsigned int selh = pm->height(); + + int offset_x = 0; + int offset_y = 0; + if (selw < item_pm_height) + offset_x += (item_pm_height - selw) / 2; + if (selh < item_pm_height) + offset_y += (item_pm_height - selh) / 2; + + XSetClipMask(disp, gc, pm->mask().drawable()); + XSetClipOrigin(disp, gc, sel_x+offset_x, sel_y+offset_y); + // copy bullet pixmap to drawable + draw.copyArea(pm->pixmap().drawable(), gc, 0, 0, - sel_x, y, - theme.bulletPixmap().width(), - theme.bulletPixmap().height()); + sel_x+offset_x, sel_y+offset_y, + selw, + selh); // disable clip mask XSetClipMask(disp, gc, None); + } else { - unsigned int half_w = height / 2, quarter_w = height / 4; - int sel_y = y + height/4; + unsigned int half_w = item_pm_height / 2, quarter_w = item_pm_height / 4; switch (theme.bullet()) { case MenuTheme::SQUARE: - draw.drawRectangle(gc, sel_x, sel_y, half_w, half_w); + draw.drawRectangle(gc, sel_x+quarter_w, y+quarter_w, half_w, half_w); break; case MenuTheme::TRIANGLE: XPoint tri[3]; if (theme.bulletPos() == FbTk::RIGHT) { - tri[0].x = sel_x + quarter_w - 2; - tri[0].y = sel_y + quarter_w - 2; + tri[0].x = sel_x + half_w - 2; + tri[0].y = sel_y + half_w - 2; tri[1].x = 4; tri[1].y = 2; tri[2].x = -4; tri[2].y = 2; - } else { - tri[0].x = sel_x + quarter_w - 2; - tri[0].y = y + half_w; + } else { // point the other way + tri[0].x = sel_x + half_w - 2; + tri[0].y = sel_y + half_w; tri[1].x = 4; tri[1].y = 2; tri[2].x = 0;

@@ -188,8 +240,8 @@

case MenuTheme::DIAMOND: XPoint dia[4]; - dia[0].x = sel_x + quarter_w - 3; - dia[0].y = y + half_w; + dia[0].x = sel_x + half_w - 3; + dia[0].y = sel_y + half_w; dia[1].x = 3; dia[1].y = -3; dia[2].x = 3;

@@ -225,7 +277,7 @@ screen_num));

} unsigned int MenuItem::height(const MenuTheme &theme) const { - return std::max(theme.frameFont().height() + theme.bevelWidth(), theme.itemHeight()); + return std::max(theme.frameFont().height() + 2*theme.bevelWidth(), theme.itemHeight()); } unsigned int MenuItem::width(const MenuTheme &theme) const {

@@ -233,7 +285,6 @@ // textwidth + bevel width on each side of the text

const unsigned int icon_width = height(theme); const unsigned int normal = theme.frameFont().textWidth(label().c_str(), label().size()) + 2 * (theme.bevelWidth() + icon_width); - return m_icon.get() == 0 ? normal : normal + icon_width; }
M src/FbTk/MenuItem.hhsrc/FbTk/MenuItem.hh

@@ -96,6 +96,8 @@ virtual unsigned int height(const MenuTheme &theme) const;

virtual void draw(FbDrawable &drawable, const MenuTheme &theme, bool highlight, + // "foreground" is the transient bits - more likely to change + bool draw_foreground, bool draw_background, int x, int y, unsigned int width, unsigned int height) const; virtual void updateTheme(const MenuTheme &theme);
M src/FbTk/MenuTheme.ccsrc/FbTk/MenuTheme.cc

@@ -61,6 +61,9 @@ m_border_color(*this, "menu.borderColor", "Menu.BorderColor"),

m_bullet_pixmap(*this, "menu.submenu.pixmap", "Menu.Submenu.Pixmap"), m_selected_pixmap(*this, "menu.selected.pixmap", "Menu.Selected.Pixmap"), m_unselected_pixmap(*this, "menu.unselected.pixmap", "Menu.Unselected.Pixmap"), + m_hl_bullet_pixmap(*this, "menu.hilite.submenu.pixmap", "Menu.Hilite.Submenu.Pixmap"), + m_hl_selected_pixmap(*this, "menu.hilite.selected.pixmap", "Menu.Hilite.Selected.Pixmap"), + m_hl_unselected_pixmap(*this, "menu.hilite.unselected.pixmap", "Menu.Hilite.Unselected.Pixmap"), m_display(FbTk::App::instance()->display()), t_text_gc(RootWindow(m_display, screen_num)), f_text_gc(RootWindow(m_display, screen_num)),

@@ -109,12 +112,18 @@ m_real_item_height = std::max(*m_item_height, frameFont().height() + 2*bevelWidth());

m_real_title_height = std::max(*m_title_height, titleFont().height() + 2*bevelWidth()); - m_real_item_height = m_real_item_height == 0 ? 1 : m_real_item_height; - m_real_title_height = m_real_title_height == 0 ? 1 : m_real_title_height; + unsigned int minsize = 2*bevelWidth()+1; + m_real_item_height = m_real_item_height < minsize ? minsize: m_real_item_height; + m_real_title_height = m_real_title_height == minsize ? minsize : m_real_title_height; + unsigned int item_pm_height = itemHeight(); - m_bullet_pixmap->scale(itemHeight(), itemHeight()); - m_selected_pixmap->scale(itemHeight(), itemHeight()); - m_unselected_pixmap->scale(itemHeight(), itemHeight()); + m_bullet_pixmap->scale(item_pm_height, item_pm_height); + m_selected_pixmap->scale(item_pm_height, item_pm_height); + m_unselected_pixmap->scale(item_pm_height, item_pm_height); + + m_hl_bullet_pixmap->scale(item_pm_height, item_pm_height); + m_hl_selected_pixmap->scale(item_pm_height, item_pm_height); + m_hl_unselected_pixmap->scale(item_pm_height, item_pm_height); t_text_gc.setForeground(*t_text); f_text_gc.setForeground(*f_text);
M src/FbTk/MenuTheme.hhsrc/FbTk/MenuTheme.hh

@@ -71,6 +71,10 @@

inline const FbTk::PixmapWithMask &bulletPixmap() const { return *m_bullet_pixmap; } inline const FbTk::PixmapWithMask &selectedPixmap() const { return *m_selected_pixmap; } inline const FbTk::PixmapWithMask &unselectedPixmap() const { return *m_unselected_pixmap; } + + inline const FbTk::PixmapWithMask &highlightBulletPixmap() const { return *m_hl_bullet_pixmap; } + inline const FbTk::PixmapWithMask &highlightSelectedPixmap() const { return *m_hl_selected_pixmap; } + inline const FbTk::PixmapWithMask &highlightUnselectedPixmap() const { return *m_hl_unselected_pixmap; } /** @name fonts */

@@ -121,6 +125,10 @@ inline int delayClose() const { return m_delayclose; }

inline const FbTk::Color &borderColor() const { return *m_border_color; } + // special override + inline void setSelectedPixmap(Pixmap pm) { m_selected_pixmap->pixmap() = pm; } + inline void setHighlightSelectedPixmap(Pixmap pm) { m_hl_selected_pixmap->pixmap() = pm; } + private: FbTk::ThemeItem<FbTk::Color> t_text, f_text, h_text, d_text; FbTk::ThemeItem<FbTk::Texture> title, frame, hilite;

@@ -133,6 +141,7 @@ FbTk::ThemeItem<unsigned int> m_border_width;

FbTk::ThemeItem<unsigned int> m_bevel_width; FbTk::ThemeItem<FbTk::Color> m_border_color; FbTk::ThemeItem<FbTk::PixmapWithMask> m_bullet_pixmap, m_selected_pixmap, m_unselected_pixmap; + FbTk::ThemeItem<FbTk::PixmapWithMask> m_hl_bullet_pixmap, m_hl_selected_pixmap, m_hl_unselected_pixmap; Display *m_display; FbTk::GContext t_text_gc, f_text_gc, h_text_gc, d_text_gc, hilite_gc;
M src/FbTk/TextButton.ccsrc/FbTk/TextButton.cc

@@ -24,8 +24,6 @@

#include "TextButton.hh" #include "Font.hh" #include "GContext.hh" -#include <iostream> -using namespace std; namespace FbTk {

@@ -38,6 +36,7 @@ m_text(text),

m_justify(FbTk::LEFT), m_bevel(1), m_left_padding(0), m_right_padding(0) { + setRenderer(*this); }

@@ -62,7 +61,11 @@ m_justify = just;

} void TextButton::setText(const std::string &text) { - m_text = text; + if (m_text != text) { + m_text = text; + parentMoved(); + clear(); + } } void TextButton::setFont(const FbTk::Font &font) {

@@ -102,30 +105,37 @@ void TextButton::clearArea(int x, int y,

unsigned int width, unsigned int height, bool exposure) { Button::clearArea(x, y, width, height, exposure); - // TODO: do we need to check if the text overlaps the clearing area - // and if so, then clear a rectangle that encompases all the text plus the - // requested area? - drawText(); + if (backgroundPixmap() == ParentRelative) + drawText(0, 0, this); } unsigned int TextButton::textWidth() const { return font().textWidth(text().c_str(), text().size()); } -void TextButton::drawText(int x_offset, int y_offset) { +void TextButton::renderForeground(FbWindow &win, FbDrawable &drawable) { + // (win should always be *this, no need to check) + drawText(0, 0, &drawable); +} + +void TextButton::drawText(int x_offset, int y_offset, FbDrawable *drawable) { unsigned int textlen = text().size(); // do text alignment + int align_x = FbTk::doAlignment(width() - x_offset - m_left_padding - m_right_padding, bevel(), justify(), font(), text().c_str(), text().size(), - textlen); // return new text len + textlen); // return new text lne // center text by default int center_pos = height()/2 + font().ascent()/2 - 1; - font().drawText(*this, + if (drawable == 0) + drawable = this; + + font().drawText(*drawable, screenNumber(), gc(), // graphic context text().c_str(), textlen, // string and string size
M src/FbTk/TextButton.hhsrc/FbTk/TextButton.hh

@@ -35,7 +35,7 @@

class Font; /// Displays a text on a button -class TextButton: public FbTk::Button { +class TextButton: public FbTk::Button, FbTk::FbWindowRenderer { public: TextButton(const FbTk::FbWindow &parent, const FbTk::Font &font, const std::string &text);

@@ -61,6 +61,8 @@ bool exposure = false);

void exposeEvent(XExposeEvent &event); + void renderForeground(FbDrawable &drawable); + inline FbTk::Justify justify() const { return m_justify; } inline const std::string &text() const { return m_text; } inline const FbTk::Font &font() const { return *m_font; }

@@ -69,8 +71,10 @@ int bevel() const { return m_bevel; }

unsigned int leftPadding() const { return m_left_padding; } unsigned int rightPadding() const { return m_right_padding; } + void renderForeground(FbWindow &win, FbDrawable &drawable); + protected: - virtual void drawText(int x_offset = 0, int y_offset = 0); + virtual void drawText(int x_offset, int y_offset, FbDrawable *drawable_override); private: const FbTk::Font *m_font;
M src/FbWinFrame.ccsrc/FbWinFrame.cc

@@ -377,7 +377,7 @@ m_labelbuttons.erase(it);

// insert on the new place m_labelbuttons.insert(new_pos, item); // update titlebar - redrawTitle(); + redrawTitlebar(); } void FbWinFrame::moveLabelButtonRight(const FbTk::TextButton &btn) {

@@ -395,7 +395,7 @@ new_pos++;

// insert on the new place m_labelbuttons.insert(new_pos, item); // update titlebar - redrawTitle(); + redrawTitlebar(); } void FbWinFrame::moveLabelButtonTo(FbTk::TextButton &btn, int x, int y) {

@@ -464,7 +464,7 @@ m_labelbuttons.erase(it);

//insert on the new place m_labelbuttons.insert(new_pos, item); //update titlebar - redrawTitle(); + redrawTitlebar(); } void FbWinFrame::moveLabelButtonRightOf(const FbTk::TextButton &btn, const FbTk::TextButton &dest) {

@@ -494,7 +494,7 @@ m_labelbuttons.push_back(item);

else m_labelbuttons.insert(new_pos, item); //update titlebar - redrawTitle(); + redrawTitlebar(); } void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) {

@@ -893,8 +893,8 @@

/** aligns and redraws title */ -void FbWinFrame::redrawTitle() { - if (m_labelbuttons.empty()) +void FbWinFrame::redrawTitlebar() { + if (!m_use_titlebar || m_labelbuttons.empty()) return; int focus_button_min_percent = Fluxbox::instance()->getFocusedTabMinWidth();

@@ -965,14 +965,6 @@ m_titlebar.clear();

} } -void FbWinFrame::redrawTitlebar() { - if (!m_use_titlebar) - return; - - redrawTitle(); - - } - /** Align buttons with title text window */

@@ -998,7 +990,6 @@ unsigned int next_x = m_bevel;

unsigned int button_size = buttonHeight(); m_button_size = button_size; for (size_t i=0; i < m_buttons_left.size(); i++, next_x += button_size + m_bevel) { - //cerr<<"m_buttons_left["<<i<<"]->moveResize(next_x="<<next_x<<", m_bev="<<m_bevel<<", bs="<<button_size<<", bs="<<button_size<<")"<<endl; m_buttons_left[i]->moveResize(next_x, m_bevel, button_size, button_size); }

@@ -1024,7 +1015,6 @@ m_buttons_right[i]->moveResize(next_x, m_bevel,

button_size, button_size); } -// renderTitlebar(); // gets done outside m_titlebar.raise(); // always on top }
M src/FbWinFrame.hhsrc/FbWinFrame.hh

@@ -193,7 +193,6 @@ //@}

private: void redrawTitlebar(); - void redrawTitle(); /// reposition titlebar items void reconfigureTitlebar();
M src/IconButton.ccsrc/IconButton.cc

@@ -288,12 +288,12 @@ }

FbTk::TextButton::clear(); } -void IconButton::drawText(int x, int y) { +void IconButton::drawText(int x, int y, FbTk::FbDrawable *drawable) { // offset text if (m_icon_pixmap.drawable() != 0) - FbTk::TextButton::drawText(m_icon_window.x() + m_icon_window.width() + 1, y); + FbTk::TextButton::drawText(m_icon_window.x() + m_icon_window.width() + 1, y, drawable); else - FbTk::TextButton::drawText(1, y); + FbTk::TextButton::drawText(1, y, drawable); }
M src/IconButton.hhsrc/IconButton.hh

@@ -54,7 +54,7 @@ FluxboxWindow &win() { return m_win; }

const FluxboxWindow &win() const { return m_win; } protected: - void drawText(int x = 0, int y = 0); + void drawText(int x, int y, FbTk::FbDrawable *drawable_override); private: void setupWindow();
M src/ToggleMenu.hhsrc/ToggleMenu.hh

@@ -48,12 +48,11 @@ // the items each time we get a button release event

// so that the last toggled item gets redrawn as // not toggled. if (ev.window == frameWindow()) { - frameWindow().clear(); - for (size_t i = 0; i < numberOfItems(); ++i) { - drawItem(i, // index - false); // clear - - } + // force full foreground update (by setting bg to same thing) + frameWindow().parentMoved(); +// for (size_t i = 0; i < numberOfItems(); ++i) { +// clearItem(i); +// } } }
M src/Window.ccsrc/Window.cc

@@ -1207,11 +1207,8 @@ void FluxboxWindow::updateTitleFromClient(WinClient &client) {

client.updateTitle(); // compare old title with new and see if we need to update // graphics - if (m_labelbuttons[&client]->text() != client.title()) { + if (m_labelbuttons[&client]->text() != client.title()) m_labelbuttons[&client]->setText(client.title()); - m_labelbuttons[&client]->clear(); // redraw text - //m_labelbuttons[&client]->updateTransparent(); - } } /// update icon title from client

@@ -2346,7 +2343,9 @@ // mapRequestEvent(event.xmaprequest);

//break; case PropertyNotify: { #ifdef DEBUG - cerr<<"PropertyNotify("<<title()<<")"<<endl; + char *atomname = XGetAtomName(display, event.xproperty.atom); + cerr<<"PropertyNotify("<<title()<<"), property = "<<atomname<<endl; + XFree(atomname); #endif // DEBUG WinClient *client = findClient(event.xproperty.window); if (client) {
M src/fluxbox.ccsrc/fluxbox.cc

@@ -156,6 +156,8 @@ namespace {

Window last_bad_window = None; +// *** NOTE: if you want to debug here the X errors are +// coming from, you should turn on the XSynchronise call below int handleXErrors(Display *d, XErrorEvent *e) { if (e->error_code == BadWindow) last_bad_window = e->resourceid;

@@ -277,7 +279,7 @@ to.tv_usec = 1;

m_reconfig_timer.setTimeout(to); m_reconfig_timer.setCommand(reconfig_cmd); m_reconfig_timer.fireOnce(true); -// XSynchronize(disp, True); + // XSynchronize(disp, True); s_singleton = this; m_have_shape = false;