transparency improvements, added buffer for title window to reduce flickering and removed menu.bevel_w since its already in MenuTheme

This commit is contained in:
fluxgen 2004-06-13 00:31:29 +00:00
parent 4366436c50
commit 46a06cdb02
2 changed files with 141 additions and 98 deletions

View file

@ -22,7 +22,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// $Id: Menu.cc,v 1.62 2004/06/07 20:28:50 fluxgen Exp $ // $Id: Menu.cc,v 1.63 2004/06/13 00:31:29 fluxgen Exp $
//use GNU extensions //use GNU extensions
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
@ -132,16 +132,15 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl):
menu.hilite_pixmap = menu.hilite_pixmap =
menu.sel_pixmap = None; menu.sel_pixmap = None;
menu.bevel_w = 2;
menu.title_h = menu.item_w = menu.frame_h = menu.title_h = menu.item_w = menu.frame_h =
m_theme.titleFont().height() + menu.bevel_w * 2; theme().titleFont().height() + theme().bevelWidth() * 2;
menu.sublevels = menu.sublevels =
menu.persub = menu.persub =
menu.minsub = 0; menu.minsub = 0;
menu.item_h = m_theme.frameFont().height() + menu.bevel_w; menu.item_h = theme().frameFont().height() + theme().bevelWidth();
long event_mask = ButtonPressMask | ButtonReleaseMask | long event_mask = ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | KeyPressMask | ExposureMask | FocusChangeMask; ButtonMotionMask | KeyPressMask | ExposureMask | FocusChangeMask;
@ -389,27 +388,28 @@ void Menu::enableTitle() {
void Menu::update(int active_index) { void Menu::update(int active_index) {
if (menu.bevel_w > 10) // clamp to "normal" size
menu.bevel_w = 10;
if (m_border_width > 20) if (m_border_width > 20)
m_border_width = 20; m_border_width = 20;
if (theme().titleHeight() != 0) if (theme().titleHeight() != 0)
menu.title_h = std::max(theme().titleHeight(), theme().titleFont().height() + menu.bevel_w*2); menu.title_h = std::max(theme().titleHeight(),
theme().titleFont().height() + theme().bevelWidth());
else else
menu.title_h = theme().titleFont().height() + menu.bevel_w*2; menu.title_h = theme().titleFont().height() + theme().bevelWidth()*2;
if (theme().itemHeight() != 0) if (theme().itemHeight() != 0)
menu.item_h = std::max(theme().itemHeight(), theme().frameFont().height() + menu.bevel_w); menu.item_h = std::max(theme().itemHeight(),
theme().frameFont().height() + theme().bevelWidth());
else else
menu.item_h = theme().frameFont().height() + menu.bevel_w; menu.item_h = theme().frameFont().height() +theme().bevelWidth();
if (title_vis) { if (title_vis) {
menu.item_w = theme().titleFont().textWidth(menu.label.c_str(), menu.item_w = theme().titleFont().textWidth(menu.label.c_str(),
menu.label.size()); menu.label.size());
menu.item_w += (menu.bevel_w * 2); menu.item_w += (theme().bevelWidth() * 2);
} else } else
menu.item_w = 1; menu.item_w = 1;
@ -463,16 +463,53 @@ void Menu::update(int active_index) {
const FbTk::Texture &tex = theme().titleTexture(); const FbTk::Texture &tex = theme().titleTexture();
if (!tex.usePixmap()) { if (!tex.usePixmap()) {
menu.title_pixmap = None; menu.title_pixmap = None;
menu.title.setBackgroundColor(tex.color());
} else { } else {
menu.title_pixmap = menu.title_pixmap =
m_image_ctrl.renderImage(width(), menu.title_h, tex); m_image_ctrl.renderImage(width(), menu.title_h, tex);
menu.title.setBackgroundPixmap(menu.title_pixmap);
} }
if (tmp) if (tmp)
m_image_ctrl.removeImage(tmp); m_image_ctrl.removeImage(tmp);
// if new size of title doesn't match our
// buffer pixmap -> resize buffer pixmap
if (m_title_pm.width() != width() ||
m_title_pm.height() != menu.title_h) {
m_title_pm = FbPixmap(menu.title.window(),
width(), menu.title_h,
menu.title.depth());
m_real_title_pm = FbPixmap(menu.title.window(),
width(), menu.title_h,
menu.title.depth());
// set pixmap that we have as real face to the user
menu.title.setBackgroundPixmap(m_real_title_pm.drawable());
menu.title.setBufferPixmap(m_real_title_pm.drawable());
//!! TODO: error checking?
GContext def_gc(menu.title);
if (menu.title_pixmap == 0) {
def_gc.setForeground(theme().titleTexture().color());
m_title_pm.fillRectangle(def_gc.gc(),
0, 0,
m_title_pm.width(), m_title_pm.height());
m_real_title_pm.fillRectangle(def_gc.gc(),
0, 0,
m_title_pm.width(), m_title_pm.height());
} else {
m_title_pm.copyArea(menu.title_pixmap,
def_gc.gc(),
0, 0,
0, 0,
m_title_pm.width(), m_title_pm.height());
m_real_title_pm.copyArea(menu.title_pixmap,
def_gc.gc(),
0, 0,
0, 0,
m_title_pm.width(), m_title_pm.height());
}
}
} }
tmp = menu.frame_pixmap; tmp = menu.frame_pixmap;
@ -544,9 +581,11 @@ void Menu::update(int active_index) {
// TODO: fill only that part of the menuframe with the // TODO: fill only that part of the menuframe with the
// pixmap/color, that has actually NO buttons on it // pixmap/color, that has actually NO buttons on it
// ??? did I made this comment ? (fluxgen)
// if so, what am I talking about?
GContext def_gc(menu.frame); GContext def_gc(menu.frame);
if (menu.frame_pixmap == 0) { if (menu.frame_pixmap == 0) {
def_gc.setForeground(m_theme.frameTexture().color()); def_gc.setForeground(theme().frameTexture().color());
m_frame_pm.fillRectangle(def_gc.gc(), m_frame_pm.fillRectangle(def_gc.gc(),
0, 0, 0, 0,
width(), menu.frame_h); width(), menu.frame_h);
@ -590,11 +629,11 @@ void Menu::update(int active_index) {
false); // render transparent false); // render transparent
} }
if (m_parent) // if (m_parent)
m_parent->drawSubmenu(m_parent->which_sub); // m_parent->drawSubmenu(m_parent->which_sub);
/* /*
renderTransp(0, active_index*menu.item_h, renderTransp(0, active_index*menu.item_h,
width(), menu.item_h); width(), menu.item_h);
*/ */
} }
@ -631,6 +670,10 @@ void Menu::show() {
void Menu::hide() { void Menu::hide() {
if (!isVisible())
return;
if ((! torn) && hide_tree && m_parent && m_parent->isVisible()) { if ((! torn) && hide_tree && m_parent && m_parent->isVisible()) {
Menu *p = m_parent; Menu *p = m_parent;
@ -652,12 +695,15 @@ void Menu::grabInputFocus() {
void Menu::clearWindow() { void Menu::clearWindow() {
menu.window.clear();
redrawTitle(); redrawTitle();
renderTransp(0, 0, if (alpha() < 255) {
m_real_frame_pm.width(), m_real_frame_pm.height()); renderTransp(0, 0,
menu.frame.width(), menu.frame.height());
update();
}
menu.title.clear();
menu.frame.clear(); menu.frame.clear();
} }
@ -682,32 +728,38 @@ void Menu::internal_hide() {
void Menu::move(int x, int y) { void Menu::move(int x, int y) {
menu.window.move(x, y); menu.window.move(x, y);
if (!isVisible())
return;
if (which_sub != -1) if (which_sub != -1)
drawSubmenu(which_sub); drawSubmenu(which_sub);
redrawTitle(); if (alpha() < 255) {
if (!(m_parent && m_parent->moving) && !torn) { redrawTitle();
menu.title.clear();
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
}
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());
} }
} }
void Menu::redrawTitle() { void Menu::redrawTitle() {
const char *text = menu.label.c_str(); const char *text = menu.label.c_str();
const FbTk::Font &font = m_theme.titleFont(); const FbTk::Font &font = theme().titleFont();
int dx = menu.bevel_w, len = menu.label.size(); int dx = theme().bevelWidth(), len = menu.label.size();
unsigned int l = font.textWidth(text, len) + menu.bevel_w*2; unsigned int l = font.textWidth(text, len) + theme().bevelWidth()*2;
switch (m_theme.titleFontJustify()) { switch (theme().titleFontJustify()) {
case FbTk::RIGHT: case FbTk::RIGHT:
dx += width() - l; dx += width() - l;
break; break;
@ -722,14 +774,20 @@ void Menu::redrawTitle() {
if (menu.title.alpha() != alpha()) if (menu.title.alpha() != alpha())
menu.title.setAlpha(alpha()); menu.title.setAlpha(alpha());
menu.title.clear(); FbTk::GContext def_gc(menu.title);
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
m_real_title_pm.copyArea(m_title_pm.drawable(),
def_gc.gc(),
0, 0,
0, 0,
m_title_pm.width(), m_title_pm.height());
menu.title.updateTransparent();
font.drawText(m_real_title_pm.drawable(), // drawable
screenNumber(),
theme().titleTextGC().gc(), // graphic context
text, len, // text string with lenght
dx, font.ascent() + theme().bevelWidth()); // position
} }
@ -789,6 +847,9 @@ void Menu::drawSubmenu(unsigned int index) {
menu.window.borderWidth() * 2; menu.window.borderWidth() * 2;
} }
item->submenu()->moving = moving;
which_sub = index;
if (new_y < 0) if (new_y < 0)
new_y = 0; new_y = 0;
@ -801,8 +862,7 @@ void Menu::drawSubmenu(unsigned int index) {
item->submenu()->raise(); item->submenu()->raise();
} }
item->submenu()->moving = moving;
which_sub = index;
} else } else
which_sub = -1; which_sub = -1;
@ -837,13 +897,13 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4; unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4;
GC gc = GC gc =
((highlight || item->isSelected()) ? m_theme.hiliteTextGC().gc() : ((highlight || item->isSelected()) ? theme().hiliteTextGC().gc() :
m_theme.frameTextGC().gc()); theme().frameTextGC().gc());
sel_x = item_x; sel_x = item_x;
if (m_theme.bulletPos() == FbTk::RIGHT) if (theme().bulletPos() == FbTk::RIGHT)
sel_x += (menu.item_w - menu.item_h - menu.bevel_w); sel_x += (menu.item_w - menu.item_h - theme().bevelWidth());
sel_x += quarter_w; sel_x += quarter_w;
sel_y = item_y + quarter_w; sel_y = item_y + quarter_w;
@ -851,7 +911,7 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
if (clear) { if (clear) {
GContext def_gc(menu.frame); GContext def_gc(menu.frame);
if (menu.frame_pixmap == 0) { if (menu.frame_pixmap == 0) {
def_gc.setForeground(m_theme.frameTexture().color()); def_gc.setForeground(theme().frameTexture().color());
m_frame_pm.fillRectangle(def_gc.gc(), item_x, item_y, menu.item_w, menu.item_h); m_frame_pm.fillRectangle(def_gc.gc(), item_x, item_y, menu.item_w, menu.item_h);
} else { } else {
@ -878,11 +938,11 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
if (highlight && (menu.hilite_pixmap != ParentRelative)) { if (highlight && (menu.hilite_pixmap != ParentRelative)) {
if (menu.hilite_pixmap) { if (menu.hilite_pixmap) {
m_frame_pm.copyArea(menu.hilite_pixmap, m_frame_pm.copyArea(menu.hilite_pixmap,
m_theme.hiliteGC().gc(), hoff_x, hoff_y, theme().hiliteGC().gc(), hoff_x, hoff_y,
hilite_x, hilite_y, hilite_x, hilite_y,
hilite_w, hilite_h); hilite_w, hilite_h);
} else { } else {
m_frame_pm.fillRectangle(m_theme.hiliteGC().gc(), m_frame_pm.fillRectangle(theme().hiliteGC().gc(),
hilite_x, hilite_y, hilite_w, hilite_h); hilite_x, hilite_y, hilite_w, hilite_h);
} }
@ -890,20 +950,20 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
if (item->isToggleItem() && item->isSelected()) { if (item->isToggleItem() && item->isSelected()) {
if (m_theme.selectedPixmap().pixmap().drawable()) { if (theme().selectedPixmap().pixmap().drawable()) {
// enable clip mask // enable clip mask
XSetClipMask(FbTk::App::instance()->display(), XSetClipMask(FbTk::App::instance()->display(),
gc, gc,
m_theme.selectedPixmap().mask().drawable()); theme().selectedPixmap().mask().drawable());
XSetClipOrigin(FbTk::App::instance()->display(), XSetClipOrigin(FbTk::App::instance()->display(),
gc, sel_x, item_y); gc, sel_x, item_y);
// copy bullet pixmap to frame // copy bullet pixmap to frame
m_frame_pm.copyArea(m_theme.selectedPixmap().pixmap().drawable(), m_frame_pm.copyArea(theme().selectedPixmap().pixmap().drawable(),
gc, gc,
0, 0, 0, 0,
sel_x, item_y, sel_x, item_y,
m_theme.selectedPixmap().width(), theme().selectedPixmap().width(),
m_theme.selectedPixmap().height()); theme().selectedPixmap().height());
// disable clip mask // disable clip mask
XSetClipMask(FbTk::App::instance()->display(), XSetClipMask(FbTk::App::instance()->display(),
gc, gc,
@ -911,12 +971,12 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
} else { } else {
if (menu.sel_pixmap) { if (menu.sel_pixmap) {
m_frame_pm.copyArea(highlight ? menu.frame_pixmap : menu.sel_pixmap, m_frame_pm.copyArea(highlight ? menu.frame_pixmap : menu.sel_pixmap,
m_theme.hiliteGC().gc(), theme().hiliteGC().gc(),
0, 0, 0, 0,
sel_x, sel_y, sel_x, sel_y,
half_w, half_w); half_w, half_w);
} else { } else {
m_frame_pm.fillRectangle(m_theme.hiliteGC().gc(), m_frame_pm.fillRectangle(theme().hiliteGC().gc(),
sel_x, sel_y, half_w, half_w); sel_x, sel_y, half_w, half_w);
} }
} }
@ -927,7 +987,7 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
renderTransp(item_x, item_y, renderTransp(item_x, item_y,
width(), menu.item_h); width(), menu.item_h);
item->draw(m_real_frame_pm, m_theme, highlight, item->draw(m_real_frame_pm, theme(), highlight,
item_x, item_y, item_x, item_y,
menu.item_w, menu.item_h); menu.item_w, menu.item_h);
@ -1033,21 +1093,7 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
if (re.window == menu.title) { if (re.window == menu.title) {
if (moving) { if (moving) {
moving = false; moving = false;
move(x(), y());
if (which_sub >= 0)
drawSubmenu(which_sub);
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() && if (re.x >= 0 && re.x <= (signed) width() &&
@ -1170,7 +1216,9 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
void Menu::exposeEvent(XExposeEvent &ee) { void Menu::exposeEvent(XExposeEvent &ee) {
if (ee.window == menu.title) { if (ee.window == menu.title) {
redrawTitle(); if (alpha() < 255)
redrawTitle();
menu.title.clearArea(ee.x, ee.y, ee.width, ee.height);
} else if (ee.window == menu.frame) { } else if (ee.window == menu.frame) {
if (moving) { if (moving) {
@ -1213,18 +1261,12 @@ void Menu::exposeEvent(XExposeEvent &ee) {
(which_sub == static_cast<signed>(index)), // highlight (which_sub == static_cast<signed>(index)), // highlight
false, // clear false, // clear
true), max_y); // render trans 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.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);
*/
} }
} }
@ -1345,24 +1387,18 @@ void Menu::reconfigure() {
m_need_update = true; // redraw items m_need_update = true; // redraw items
menu.bevel_w = theme().bevelWidth();
m_border_width = theme().borderWidth(); m_border_width = theme().borderWidth();
if (menu.bevel_w > 10) // clamp to "normal" size
menu.bevel_w = 10;
if (m_border_width > 20) // clamp to normal size if (m_border_width > 20) // clamp to normal size
m_border_width = 20; m_border_width = 20;
if (m_border_width < 0) if (m_border_width < 0)
m_border_width = 0; m_border_width = 0;
menu.title.setAlpha(alpha()); menu.title.setAlpha(alpha());
menu.window.setBackgroundColor(m_theme.borderColor());
menu.title.setBackgroundColor(m_theme.borderColor());
menu.window.setBorderColor(m_theme.borderColor()); menu.window.setBorderColor(theme().borderColor());
menu.title.setBorderColor(m_theme.borderColor()); menu.title.setBorderColor(theme().borderColor());
menu.frame.setBorderColor(m_theme.borderColor()); menu.frame.setBorderColor(theme().borderColor());
menu.window.setBorderWidth(m_border_width); menu.window.setBorderWidth(m_border_width);
menu.title.setBorderWidth(m_border_width); menu.title.setBorderWidth(m_border_width);
@ -1415,14 +1451,20 @@ void Menu::update(FbTk::Subject *subj) {
reconfigure(); reconfigure();
} }
void Menu::renderTransp(int x, int y, void Menu::renderTransp(int x, int y,
unsigned int width, unsigned int height) { unsigned int width, unsigned int height) {
// no need to render transparent unless visible
if (!isVisible())
return;
GContext def_gc(menu.frame); GContext def_gc(menu.frame);
m_real_frame_pm.copyArea(m_frame_pm.drawable(), m_real_frame_pm.copyArea(m_frame_pm.drawable(),
def_gc.gc(), def_gc.gc(),
x, y, x, y,
x, y, x, y,
width, height); width, height);
if (m_transp.get() == 0) if (m_transp.get() == 0)
return; return;
@ -1433,7 +1475,6 @@ void Menu::renderTransp(int x, int y,
m_transp->setSource(root, screenNumber()); m_transp->setSource(root, screenNumber());
if (m_transp->dest() != m_real_frame_pm.drawable()) if (m_transp->dest() != m_real_frame_pm.drawable())
m_transp->setDest(m_real_frame_pm.drawable(), screenNumber()); m_transp->setDest(m_real_frame_pm.drawable(), screenNumber());

View file

@ -22,7 +22,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// $Id: Menu.hh,v 1.33 2004/06/10 11:38:26 fluxgen Exp $ // $Id: Menu.hh,v 1.34 2004/06/13 00:31:29 fluxgen Exp $
#ifndef FBTK_MENU_HH #ifndef FBTK_MENU_HH
#define FBTK_MENU_HH #define FBTK_MENU_HH
@ -205,13 +205,15 @@ private:
std::string label; std::string label;
int x_move, y_move, x_shift, y_shift, sublevels, persub, minsub, int x_move, y_move, x_shift, y_shift, sublevels, persub, minsub,
grab_x, grab_y; grab_x, grab_y;
unsigned int title_h, frame_h, item_w, item_h, bevel_w, unsigned int title_h, frame_h, item_w, item_h, bevel_w;
bevel_h;
} menu; } menu;
Drawable m_root_pm; Drawable m_root_pm;
static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused static Menu *s_focused; ///< holds current input focused menu, so one can determine if a menu is focused
FbPixmap m_frame_pm, m_real_frame_pm; FbPixmap m_frame_pm, ///< buffer pixmap
m_real_frame_pm; ///< buffer pixmap (this one is shown to the user)
FbPixmap m_title_pm, ///< buffer pixmap to avoid flicker
m_real_title_pm; ///< buffer pixmap (this one is shown to the user)
std::auto_ptr<Transparent> m_transp; std::auto_ptr<Transparent> m_transp;
bool m_need_update; bool m_need_update;
Timer m_submenu_timer; Timer m_submenu_timer;