From 34edd2640a35cb825a647e8d37db6cbc8e6afea1 Mon Sep 17 00:00:00 2001 From: fluxgen Date: Mon, 7 Jun 2004 20:28:50 +0000 Subject: improved transparent rendering and fixed drawing of menu items in MenuItem class --- src/FbTk/Menu.cc | 512 +++++++++++++++++++++++++++++-------------------------- src/FbTk/Menu.hh | 13 +- 2 files changed, 275 insertions(+), 250 deletions(-) diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc index 8736edf..f0e5c59 100644 --- a/src/FbTk/Menu.cc +++ b/src/FbTk/Menu.cc @@ -1,5 +1,5 @@ // Menu.cc for FbTk - Fluxbox Toolkit -// Copyright (c) 2001 - 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net) +// Copyright (c) 2001 - 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) // // Basemenu.cc for blackbox - an X11 Window manager // Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net) @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Menu.cc,v 1.61 2004/06/07 11:46:05 rathnor Exp $ +// $Id: Menu.cc,v 1.62 2004/06/07 20:28:50 fluxgen Exp $ //use GNU extensions #ifndef _GNU_SOURCE @@ -31,6 +31,10 @@ #include "Menu.hh" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + #include "MenuItem.hh" #include "ImageControl.hh" #include "MenuTheme.hh" @@ -56,6 +60,28 @@ static Menu *shown = 0; Menu *Menu::s_focused = 0; +static Pixmap getRootPixmap(int screen_num) { + Pixmap root_pm = 0; + // get root pixmap for transparency + Display *disp = FbTk::App::instance()->display(); + Atom real_type; + int real_format; + unsigned long items_read, items_left; + unsigned int *data; + if (XGetWindowProperty(disp, RootWindow(disp, screen_num), + XInternAtom(disp, "_XROOTPMAP_ID", false), + 0L, 1L, + false, XA_PIXMAP, &real_type, + &real_format, &items_read, &items_left, + (unsigned char **) &data) == Success && + items_read) { + root_pm = (Pixmap) (*data); + XFree(data); + } + + return root_pm; +} + Menu::Menu(MenuTheme &tm, ImageControl &imgctrl): m_theme(tm), m_parent(0), @@ -135,23 +161,30 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl): event_mask |= EnterWindowMask | LeaveWindowMask; //create menu title - menu.title = FbTk::FbWindow(menu.window, - 0, 0, width(), menu.title_h, - event_mask); + menu.title = FbTk::FbWindow(menu.window, // parent + 0, 0, width(), menu.title_h, // pos and size + event_mask, // mask + false, // override redirect + true); // save under evm.add(*this, menu.title); event_mask |= PointerMotionMask; - menu.frame = FbTk::FbWindow(menu.window, - 0, menu.title_h, - width(), menu.frame_h ? menu.frame_h : 1, - event_mask, false, true); + menu.frame = FbTk::FbWindow(menu.window, // parent + 0, menu.title_h, // pos + width(), menu.frame_h ? menu.frame_h : 1, // size + event_mask, // mask + false, // override redirect + true); // save under evm.add(*this, menu.frame); + + // update style - reconfigure(); + // reconfigure(); } Menu::~Menu() { + menu.window.hide(); if (shown && shown->window() == window()) @@ -361,35 +394,34 @@ void Menu::update(int active_index) { if (m_border_width > 20) m_border_width = 20; - menu.item_h = m_theme.frameFont().height() + menu.bevel_w; - menu.title_h = m_theme.titleFont().height() + menu.bevel_w*2; + if (theme().titleHeight() != 0) + menu.title_h = std::max(theme().titleHeight(), theme().titleFont().height() + menu.bevel_w*2); + else + menu.title_h = theme().titleFont().height() + menu.bevel_w*2; + + if (theme().itemHeight() != 0) + menu.item_h = std::max(theme().itemHeight(), theme().frameFont().height() + menu.bevel_w); + else + menu.item_h = theme().frameFont().height() + menu.bevel_w; + if (title_vis) { - menu.item_w = m_theme.titleFont().textWidth(menu.label.c_str(), + menu.item_w = theme().titleFont().textWidth(menu.label.c_str(), menu.label.size()); menu.item_w += (menu.bevel_w * 2); } else menu.item_w = 1; - int ii = 0; + unsigned int ii = 0; Menuitems::iterator it = menuitems.begin(); Menuitems::iterator it_end = menuitems.end(); for (; it != it_end; ++it) { - MenuItem *itmp = (*it); - - const char *s = itmp->label().c_str(); - int l = itmp->label().size(); - - ii = m_theme.frameFont().textWidth(s, l); - - - ii += (menu.bevel_w * 2) + (menu.item_h * 2); - - menu.item_w = ((menu.item_w < (unsigned int) ii) ? ii : menu.item_w); + ii = (*it)->width(theme()); + menu.item_w = (ii > menu.item_w ? ii : menu.item_w); } - if (menuitems.size()) { + if (!menuitems.empty()) { menu.sublevels = 1; while (menu.item_h * (menuitems.size() + 1) / menu.sublevels + @@ -425,10 +457,10 @@ void Menu::update(int active_index) { menu.window.resize(new_width, new_height); - Pixmap tmp; - if (title_vis) { + Pixmap tmp = 0; + if (title_vis && m_need_update) { tmp = menu.title_pixmap; - const FbTk::Texture &tex = m_theme.titleTexture(); + const FbTk::Texture &tex = theme().titleTexture(); if (!tex.usePixmap()) { menu.title_pixmap = None; menu.title.setBackgroundColor(tex.color()); @@ -444,19 +476,21 @@ void Menu::update(int active_index) { } tmp = menu.frame_pixmap; - const FbTk::Texture &frame_tex = m_theme.frameTexture(); - if (!frame_tex.usePixmap()) { - menu.frame_pixmap = None; - } else { - menu.frame_pixmap = - m_image_ctrl.renderImage(width(), menu.frame_h, frame_tex); - } + const FbTk::Texture &frame_tex = theme().frameTexture(); + if (m_need_update) { + if (!frame_tex.usePixmap()) { + menu.frame_pixmap = None; + } else { + menu.frame_pixmap = + m_image_ctrl.renderImage(width(), menu.frame_h, frame_tex); + } - if (tmp) - m_image_ctrl.removeImage(tmp); + if (tmp) + m_image_ctrl.removeImage(tmp); + } tmp = menu.hilite_pixmap; - const FbTk::Texture &hilite_tex = m_theme.hiliteTexture(); + const FbTk::Texture &hilite_tex = theme().hiliteTexture(); if (!hilite_tex.usePixmap()) { menu.hilite_pixmap = None; } else @@ -495,62 +529,86 @@ void Menu::update(int active_index) { menu.frame.width(), menu.frame.height(), menu.frame.depth()); + m_real_frame_pm = FbTk::FbPixmap(menu.frame.window(), + menu.frame.width(), menu.frame.height(), + menu.frame.depth()); + + menu.frame.setBackgroundPixmap(m_real_frame_pm.drawable()); if (m_frame_pm.drawable() == 0) { _FB_USES_NLS; cerr<<"FbTk::Menu: "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<" ("<< menu.frame.window()<<", "< 0 && menu.persub * menu.sublevels != menuitems.size()) { + } else if (menu.sublevels > 0 && menu.persub * menu.sublevels != (int)menuitems.size()) { // TODO: fill only that part of the menuframe with the // pixmap/color, that has actually NO buttons on it - FbTk::GContext def_gc(menu.frame.window()); + GContext def_gc(menu.frame); if (menu.frame_pixmap == 0) { def_gc.setForeground(m_theme.frameTexture().color()); m_frame_pm.fillRectangle(def_gc.gc(), 0, 0, width(), menu.frame_h); - + m_real_frame_pm.fillRectangle(def_gc.gc(), + 0, 0, + width(), menu.frame_h); } else { m_frame_pm.copyArea(menu.frame_pixmap, def_gc.gc(), 0, 0, 0, 0, width(), menu.frame_h); + + m_real_frame_pm.copyArea(menu.frame_pixmap, + def_gc.gc(), + 0, 0, + 0, 0, + width(), menu.frame_h); } + } + } - menu.frame.setBackgroundPixmap(m_frame_pm.drawable()); - - // clearWindow(); - + // if menu visible and title visible if (title_vis && visible) redrawTitle(); - if (active_index >= 0) { - for (unsigned int i = 0; visible && i < menuitems.size(); i++) { + if (active_index >= 0 && visible) { + renderTransp(0, 0, + m_real_frame_pm.width(), m_real_frame_pm.height()); + for (unsigned int i = 0; i < menuitems.size(); i++) { if (i == (unsigned int)which_sub) { - drawItem(i, true, true, false); + drawItem(i, true, // highlight + true, // clear + false); // render_trans } else - drawItem(i, (static_cast(i) == active_index && isItemEnabled(i)), true, false); + drawItem(i, + // high light + (static_cast(i) == active_index && isItemEnabled(i)), + true, // clear + false); // render transparent } - if (m_parent && visible) + if (m_parent) m_parent->drawSubmenu(m_parent->which_sub); + /* + renderTransp(0, active_index*menu.item_h, + width(), menu.item_h); + */ - menu.frame.clearArea(0, active_index * menu.item_h, - width(), menu.item_h); - menu.frame.updateTransparent(0, active_index * menu.item_h, - width(), menu.item_h); + } + if (m_need_update) { + for (unsigned int i = 0; i < menuitems.size(); i++) { + if (i == (unsigned int)which_sub) { + drawItem(i, true, true, false); + } else + drawItem(i, (static_cast(i) == active_index && isItemEnabled(i)), true, true); + } } - menu.window.clear(); - renderTransFrame(); - m_need_update = false; - menu.window.showSubwindows(); } @@ -559,7 +617,6 @@ void Menu::show() { update(); menu.window.showSubwindows(); menu.window.show(); - //!! TODO, this should probably be done explicit if one don't want to raise raise(); visible = true; @@ -596,7 +653,11 @@ void Menu::grabInputFocus() { void Menu::clearWindow() { menu.window.clear(); - menu.title.clear(); + redrawTitle(); + + renderTransp(0, 0, + m_real_frame_pm.width(), m_real_frame_pm.height()); + menu.frame.clear(); } @@ -627,9 +688,14 @@ void Menu::move(int x, int y) { if (which_sub != -1) drawSubmenu(which_sub); + redrawTitle(); if (!(m_parent && m_parent->moving) && !torn) { - redrawTitle(); - renderTransFrame(); + + renderTransp(0, 0, + m_real_frame_pm.width(), m_real_frame_pm.height()); + } else if (!moving) { + renderTransp(0, 0, + m_real_frame_pm.width(), m_real_frame_pm.height()); } } @@ -652,15 +718,18 @@ void Menu::redrawTitle() { default: break; } + + if (menu.title.alpha() != alpha()) + menu.title.setAlpha(alpha()); + menu.title.clear(); + menu.title.updateTransparent(); font.drawText(menu.title.window(), // drawable screenNumber(), m_theme.titleTextGC().gc(), // graphic context text, len, // text string with lenght dx, font.ascent() + menu.bevel_w); // position - menu.title.updateTransparent(); - } @@ -697,7 +766,7 @@ void Menu::drawSubmenu(unsigned int index) { (menu.item_h * i) + ((title_vis) ? menu.title_h + menu.window.borderWidth() : 0) - ((item->submenu()->title_vis) ? - item->submenu()->menu.title_h + menu.window.borderWidth() : 0)); + item->submenu()->menu.title_h + menu.window.borderWidth() : 0)); } if (m_alignment == ALIGNBOTTOM && @@ -752,50 +821,24 @@ bool Menu::hasSubmenu(unsigned int index) const { int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_trans, - int x, int y, unsigned int w, unsigned int h) { - if (index >= menuitems.size() || menuitems.size() == 0 || + int x, int y, unsigned int w, unsigned int h) { + if (index >= menuitems.size() || menuitems.size() == 0 || menu.persub == 0) return 0; MenuItem *item = menuitems[index]; if (! item) return 0; - bool dotext = true, dohilite = true, dosel = true; - const char *text = item->label().c_str(); int sbl = index / menu.persub, i = index - (sbl * menu.persub); int item_x = (sbl * menu.item_w), item_y = (i * menu.item_h); int hilite_x = item_x, hilite_y = item_y, hoff_x = 0, hoff_y = 0; - int text_x = 0, text_y = 0, len = strlen(text), sel_x = 0, sel_y = 0; - unsigned int hilite_w = menu.item_w, hilite_h = menu.item_h, text_w = 0, text_h = 0; + int sel_x = 0, sel_y = 0; + unsigned int hilite_w = menu.item_w, hilite_h = menu.item_h; unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4; - const FbTk::Font &font = m_theme.frameFont(); - if (text) { - text_w = font.textWidth(text, len); - - text_y = item_y + menu.bevel_w/2 + font.ascent(); - - switch(m_theme.frameFontJustify()) { - case FbTk::LEFT: - text_x = item_x + menu.bevel_w + menu.item_h + 1; - break; - - case FbTk::RIGHT: - text_x = item_x + menu.item_w - (menu.item_h + menu.bevel_w + text_w); - break; - default: //center - text_x = item_x + ((menu.item_w + 1 - text_w) / 2); - break; - } - text_h = menu.item_h - menu.bevel_w; - } - GC gc = ((highlight || item->isSelected()) ? m_theme.hiliteTextGC().gc() : m_theme.frameTextGC().gc()); - const GContext &tgc = - (highlight ? m_theme.hiliteTextGC() : - (item->isEnabled() ? m_theme.frameTextGC() : m_theme.disableTextGC() ) ); sel_x = item_x; @@ -806,7 +849,7 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t sel_y = item_y + quarter_w; if (clear) { - FbTk::GContext def_gc(menu.frame.window()); + GContext def_gc(menu.frame); if (menu.frame_pixmap == 0) { def_gc.setForeground(m_theme.frameTexture().color()); m_frame_pm.fillRectangle(def_gc.gc(), item_x, item_y, menu.item_w, menu.item_h); @@ -820,10 +863,8 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t } } else if (! (x == y && y == -1 && w == h && h == 0)) { // calculate the which part of the hilite to redraw - if (! (std::max(item_x, x) <= (signed) std::min(item_x + menu.item_w, x + w) && - std::max(item_y, y) <= (signed) std::min(item_y + menu.item_h, y + h))) { - dohilite = False; - } else { + if (!(std::max(item_x, x) <= (signed) std::min(item_x + menu.item_w, x + w) && + std::max(item_y, y) <= (signed) std::min(item_y + menu.item_h, y + h))) { hilite_x = std::max(item_x, x); hilite_y = std::max(item_y, y); hilite_w = std::min(item_x + menu.item_w, x + w) - hilite_x; @@ -832,20 +873,9 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t hoff_y = hilite_y % menu.item_h; } - // check if we need to redraw the text - int text_ry = item_y + (menu.bevel_w / 2); - if (! (std::max(text_x, x) <= (signed) std::min(text_x + text_w, x + w) && - std::max(text_ry, y) <= (signed) std::min(text_ry + text_h, y + h))) - dotext = false; - - // check if we need to redraw the select pixmap/menu bullet - if (! (std::max(sel_x, x) <= (signed) std::min(sel_x + half_w, x + w) && - std::max(sel_y, y) <= (signed) std::min(sel_y + half_w, y + h))) - dosel = false; - } - if (dohilite && highlight && (menu.hilite_pixmap != ParentRelative)) { + if (highlight && (menu.hilite_pixmap != ParentRelative)) { if (menu.hilite_pixmap) { m_frame_pm.copyArea(menu.hilite_pixmap, m_theme.hiliteGC().gc(), hoff_x, hoff_y, @@ -859,8 +889,7 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t } - if (item->isToggleItem() && item->isSelected() && - menu.sel_pixmap != ParentRelative) { + if (item->isToggleItem() && item->isSelected()) { if (m_theme.selectedPixmap().pixmap().drawable()) { // enable clip mask XSetClipMask(FbTk::App::instance()->display(), @@ -892,119 +921,22 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t } } - } else if (item->isToggleItem() && m_theme.unselectedPixmap().pixmap().drawable() != 0) { - // enable clip mask - XSetClipMask(FbTk::App::instance()->display(), - gc, - m_theme.unselectedPixmap().mask().drawable()); - XSetClipOrigin(FbTk::App::instance()->display(), - gc, sel_x, item_y); - // copy bullet pixmap to frame - m_frame_pm.copyArea(m_theme.unselectedPixmap().pixmap().drawable(), - gc, - 0, 0, - sel_x, item_y, - m_theme.unselectedPixmap().width(), - m_theme.unselectedPixmap().height()); - // disable clip mask - XSetClipMask(FbTk::App::instance()->display(), - gc, - None); - } - - if (dotext && text) { - //!! TODO: this is just temporarly and will be removed - // once we've cleaned up the menu code this will be somewhere else... - if (strcmp(text, "---") == 0){ // draw separator - m_frame_pm.drawRectangle(tgc.gc(), - item_x + menu.bevel_w + menu.item_h + 1, item_y + (menu.item_h / 2), - menu.item_w - ((menu.bevel_w + menu.item_h) * 2) - 1, 0); - } else { // draw normal text - m_theme.frameFont().drawText(m_frame_pm.drawable(), // drawable - screenNumber(), - tgc.gc(), - text, len, // text string and lenght - text_x, text_y); // position - } } - if (dosel && item->submenu()) { - if (m_theme.bulletPixmap().pixmap().drawable() != 0) { - // enable clip mask - XSetClipMask(FbTk::App::instance()->display(), - gc, - m_theme.bulletPixmap().mask().drawable()); - XSetClipOrigin(FbTk::App::instance()->display(), - gc, sel_x, item_y); - // copy bullet pixmap to frame - m_frame_pm.copyArea(m_theme.bulletPixmap().pixmap().drawable(), - gc, - 0, 0, - sel_x, item_y, - m_theme.bulletPixmap().width(), - m_theme.bulletPixmap().height()); - // disable clip mask - XSetClipMask(FbTk::App::instance()->display(), - gc, - None); - } else { - switch (m_theme.bullet()) { - case MenuTheme::SQUARE: - m_frame_pm.drawRectangle(gc, sel_x, sel_y, half_w, half_w); - break; - - case MenuTheme::TRIANGLE: - XPoint tri[3]; - - if (m_theme.bulletPos() == FbTk::RIGHT) { - tri[0].x = sel_x + quarter_w - 2; - tri[0].y = sel_y + quarter_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 = item_y + half_w; - tri[1].x = 4; - tri[1].y = 2; - tri[2].x = 0; - tri[2].y = -4; - } - - m_frame_pm.fillPolygon(gc, tri, 3, Convex, - CoordModePrevious); - break; - - case MenuTheme::DIAMOND: - XPoint dia[4]; - - dia[0].x = sel_x + quarter_w - 3; - dia[0].y = item_y + half_w; - dia[1].x = 3; - dia[1].y = -3; - dia[2].x = 3; - dia[2].y = 3; - dia[3].x = -3; - dia[3].y = 3; - - m_frame_pm.fillPolygon(gc, dia, 4, Convex, - CoordModePrevious); - break; - default: - break; - } - } - } + if (render_trans) + renderTransp(item_x, item_y, + width(), menu.item_h); + + item->draw(m_real_frame_pm, m_theme, highlight, + item_x, item_y, + menu.item_w, menu.item_h); + + + if (clear) + menu.frame.clearArea(item_x, item_y, + menu.item_w, menu.item_h, False); - menu.frame.clearArea(item_x, item_y, - menu.item_w, menu.item_h, False); - if (render_trans) { - menu.frame.updateTransparent(item_x, item_y, - menu.item_w, menu.item_h); - } - return item_y; } @@ -1088,6 +1020,7 @@ void Menu::buttonPressEvent(XButtonEvent &be) { drawSubmenu(w); } else drawItem(w, item->isEnabled(), true, true); + } } else { menu.x_move = be.x_root - x(); @@ -1103,7 +1036,18 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) { if (which_sub >= 0) drawSubmenu(which_sub); - update(); + if (alpha() < 255) { + //m_need_update = true; + // update(); + renderTransp(0, 0, + m_real_frame_pm.width(), m_real_frame_pm.height()); + for (size_t i=0; i < menuitems.size(); ++i) { + drawItem(i, false, // highlight + true, // clear + false); // transparent + + } + } } if (re.x >= 0 && re.x <= (signed) width() && @@ -1126,9 +1070,8 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) { re.y > iy && re.y < (signed) (iy + menu.item_h)) { menuitems[w]->click(re.button, re.time); itemSelected(re.button, w); - // redraw whole menu as enableds for any item - // may have changed - update(w); + // just redraw this item + drawItem(w, true, true, true); } } else { drawItem(p, isItemEnabled(p) && (p == which_sub), true, true); @@ -1140,11 +1083,12 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) { void Menu::motionNotifyEvent(XMotionEvent &me) { - + // if draging the with the titlebar: if (me.window == menu.title && (me.state & Button1Mask)) { stopHide(); if (movable) { if (! moving) { + // if not moving: start moving operation if (m_parent && (! torn)) { m_parent->drawItem(m_parent->which_sub, false, true, true); m_parent->which_sub = -1; @@ -1178,7 +1122,9 @@ void Menu::motionNotifyEvent(XMotionEvent &me) { // don't redraw disabled items on enter/leave if (item != 0 && item->isEnabled()) { - drawItem(p, false, true, true); + drawItem(p, false, // highlight + true, // clear + true); // transparent if (item->submenu()) { @@ -1200,7 +1146,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) { if (itmp->submenu()) { - drawItem(w, true); + drawItem(w, true, true); if (theme().menuMode() == MenuTheme::DELAY_OPEN) { // setup show menu timer @@ -1226,6 +1172,12 @@ void Menu::exposeEvent(XExposeEvent &ee) { if (ee.window == menu.title) { redrawTitle(); } else if (ee.window == menu.frame) { + + if (moving) { + menu.frame.clearArea(ee.x, ee.y, ee.width, ee.height); + return; + } + // this is a compilicated algorithm... lets do it step by step... // first... we see in which sub level the expose starts... and how many // items down in that sublevel @@ -1259,16 +1211,20 @@ void Menu::exposeEvent(XExposeEvent &ee) { unsigned int index = row + (col * menu.persub); max_y = max(drawItem(index, (which_sub == static_cast(index)), // highlight - true, // clear - false, // render trans - ee.x, ee.y, ee.width, ee.height), max_y); + false, // clear + true), max_y); // render trans + // ee.x, ee.y, ee.width, ee.height), max_y); } } } + + menu.frame.clearArea(ee.x, ee.y, ee.width, ee.height); + /* menu.frame.updateTransparent(start_column * menu.item_w, start_row * menu.item_h, (end_column-start_column+1) * menu.item_w, (end_row-start_row+1) * menu.item_h); + */ } } @@ -1373,10 +1329,24 @@ void Menu::keyPressEvent(XKeyEvent &event) { } void Menu::reconfigure() { + + + if (alpha() == 255 && m_transp.get() != 0) { + m_transp.reset(0); + } else if (alpha () < 255) { + + if (m_transp.get() == 0) { + m_transp.reset(new Transparent(getRootPixmap(screenNumber()), + m_real_frame_pm.drawable(), alpha(), + screenNumber())); + } else + m_transp->setAlpha(alpha()); + } + m_need_update = true; // redraw items - menu.bevel_w = m_theme.bevelWidth(); - m_border_width = m_theme.borderWidth(); + menu.bevel_w = theme().bevelWidth(); + m_border_width = theme().borderWidth(); if (menu.bevel_w > 10) // clamp to "normal" size menu.bevel_w = 10; @@ -1386,6 +1356,7 @@ void Menu::reconfigure() { if (m_border_width < 0) m_border_width = 0; + menu.title.setAlpha(alpha()); menu.window.setBackgroundColor(m_theme.borderColor()); menu.title.setBackgroundColor(m_theme.borderColor()); @@ -1396,17 +1367,10 @@ void Menu::reconfigure() { menu.window.setBorderWidth(m_border_width); menu.title.setBorderWidth(m_border_width); - menu.frame.setAlpha(alpha()); - menu.title.setAlpha(alpha()); - menu.window.setAlpha(alpha()); update(); } -void Menu::renderTransFrame() { - menu.frame.clear(); - menu.frame.updateTransparent(); -} void Menu::openSubmenu() { if (!isVisible() || which_press < 0 || which_press >= static_cast(menuitems.size()) || @@ -1417,7 +1381,7 @@ void Menu::openSubmenu() { if (item < 0 || item >= static_cast(menuitems.size())) return; - drawItem(item, true); + drawItem(item, true, true); if (menuitems[item]->submenu() != 0 && !menuitems[item]->submenu()->isVisible()) drawSubmenu(item); @@ -1440,4 +1404,64 @@ void Menu::stopHide() { m_hide_timer.stop(); } +void Menu::update(FbTk::Subject *subj) { + + m_need_update = true; + + Menuitems::iterator it = menuitems.begin(); + Menuitems::iterator it_end = menuitems.end(); + for (; it != it_end; ++it) + (*it)->updateTheme(theme()); + reconfigure(); +} + +void Menu::renderTransp(int x, int y, + unsigned int width, unsigned int height) { + GContext def_gc(menu.frame); + m_real_frame_pm.copyArea(m_frame_pm.drawable(), + def_gc.gc(), + x, y, + x, y, + width, height); + if (m_transp.get() == 0) + return; + +#ifdef HAVE_XRENDER + + Pixmap root = getRootPixmap(screenNumber()); + if (m_transp->source() != root) + m_transp->setSource(root, screenNumber()); + + + + if (m_transp->dest() != m_real_frame_pm.drawable()) + m_transp->setDest(m_real_frame_pm.drawable(), screenNumber()); + + if (m_transp->alpha() != alpha()) + m_transp->setAlpha(alpha()); + + const FbWindow *root_parent = menu.frame.parent(); + // our position in parent ("root") + int root_x = menu.frame.x() - menu.frame.borderWidth(), + root_y = menu.frame.y() - menu.frame.borderWidth(); + if (root_parent != 0) { + root_x += root_parent->x() + root_parent->borderWidth(); + root_y += root_parent->y() + root_parent->borderWidth(); + while (root_parent->parent() != 0) { + root_parent = root_parent->parent(); + root_x += root_parent->x() + root_parent->borderWidth(); + root_y += root_parent->y() + root_parent->borderWidth(); + } + + } // else toplevel window so we already have x, y set + + // render background image from root pos to our window + m_transp->render(root_x + x, root_y + y, + x, y, + width, height); + +#endif // HAVE_XRENDER + +} + }; // end namespace FbTk diff --git a/src/FbTk/Menu.hh b/src/FbTk/Menu.hh index c7be717..2b668fa 100644 --- a/src/FbTk/Menu.hh +++ b/src/FbTk/Menu.hh @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Menu.hh,v 1.31 2004/04/18 18:48:58 fluxgen Exp $ +// $Id: Menu.hh,v 1.32 2004/06/07 20:28:49 fluxgen Exp $ #ifndef FBTK_MENU_HH #define FBTK_MENU_HH @@ -151,7 +151,7 @@ public: bool isItemSelected(unsigned int index) const; bool isItemEnabled(unsigned int index) const; inline const MenuTheme &theme() const { return m_theme; } - inline unsigned char alpha() const { return m_theme.alpha(); } + inline unsigned char alpha() const { return theme().alpha(); } inline static Menu *focused() { return s_focused; } /// @return menuitem at index inline const MenuItem *find(unsigned int index) const { return menuitems[index]; } @@ -174,7 +174,7 @@ protected: inline Menu *parent() { return m_parent; } inline const Menu *parent() const { return m_parent; } - void update(FbTk::Subject *) { reconfigure(); } + void update(FbTk::Subject *); private: @@ -183,8 +183,8 @@ private: void startHide(); void stopHide(); - void renderTransFrame(); - + void renderTransp(int x, int y, + unsigned int width, unsigned int height); typedef std::vector Menuitems; const MenuTheme &m_theme; Menu *m_parent; @@ -211,7 +211,8 @@ private: Drawable m_root_pm; static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused - FbPixmap m_frame_pm; + FbPixmap m_frame_pm, m_real_frame_pm; + std::auto_ptr m_transp; bool m_need_update; Timer m_submenu_timer; Timer m_hide_timer; -- cgit v0.11.2