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
// 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
#ifndef _GNU_SOURCE
@ -132,16 +132,15 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl):
menu.hilite_pixmap =
menu.sel_pixmap = None;
menu.bevel_w = 2;
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.persub =
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 |
ButtonMotionMask | KeyPressMask | ExposureMask | FocusChangeMask;
@ -389,27 +388,28 @@ void Menu::enableTitle() {
void Menu::update(int active_index) {
if (menu.bevel_w > 10) // clamp to "normal" size
menu.bevel_w = 10;
if (m_border_width > 20)
m_border_width = 20;
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
menu.title_h = theme().titleFont().height() + menu.bevel_w*2;
menu.title_h = theme().titleFont().height() + theme().bevelWidth()*2;
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
menu.item_h = theme().frameFont().height() + menu.bevel_w;
menu.item_h = theme().frameFont().height() +theme().bevelWidth();
if (title_vis) {
menu.item_w = theme().titleFont().textWidth(menu.label.c_str(),
menu.label.size());
menu.item_w += (menu.bevel_w * 2);
menu.item_w += (theme().bevelWidth() * 2);
} else
menu.item_w = 1;
@ -463,16 +463,53 @@ void Menu::update(int active_index) {
const FbTk::Texture &tex = theme().titleTexture();
if (!tex.usePixmap()) {
menu.title_pixmap = None;
menu.title.setBackgroundColor(tex.color());
} else {
menu.title_pixmap =
m_image_ctrl.renderImage(width(), menu.title_h, tex);
menu.title.setBackgroundPixmap(menu.title_pixmap);
}
if (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;
@ -544,9 +581,11 @@ void Menu::update(int active_index) {
// TODO: fill only that part of the menuframe with the
// 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);
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(),
0, 0,
width(), menu.frame_h);
@ -590,11 +629,11 @@ void Menu::update(int active_index) {
false); // render transparent
}
if (m_parent)
m_parent->drawSubmenu(m_parent->which_sub);
// if (m_parent)
// m_parent->drawSubmenu(m_parent->which_sub);
/*
renderTransp(0, active_index*menu.item_h,
width(), menu.item_h);
renderTransp(0, active_index*menu.item_h,
width(), menu.item_h);
*/
}
@ -631,6 +670,10 @@ void Menu::show() {
void Menu::hide() {
if (!isVisible())
return;
if ((! torn) && hide_tree && m_parent && m_parent->isVisible()) {
Menu *p = m_parent;
@ -652,12 +695,15 @@ void Menu::grabInputFocus() {
void Menu::clearWindow() {
menu.window.clear();
redrawTitle();
renderTransp(0, 0,
m_real_frame_pm.width(), m_real_frame_pm.height());
if (alpha() < 255) {
renderTransp(0, 0,
menu.frame.width(), menu.frame.height());
update();
}
menu.title.clear();
menu.frame.clear();
}
@ -682,32 +728,38 @@ void Menu::internal_hide() {
void Menu::move(int x, int y) {
menu.window.move(x, y);
if (!isVisible())
return;
if (which_sub != -1)
drawSubmenu(which_sub);
redrawTitle();
if (!(m_parent && m_parent->moving) && !torn) {
if (alpha() < 255) {
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() {
const char *text = menu.label.c_str();
const FbTk::Font &font = m_theme.titleFont();
int dx = menu.bevel_w, len = menu.label.size();
unsigned int l = font.textWidth(text, len) + menu.bevel_w*2;
const FbTk::Font &font = theme().titleFont();
int dx = theme().bevelWidth(), len = menu.label.size();
unsigned int l = font.textWidth(text, len) + theme().bevelWidth()*2;
switch (m_theme.titleFontJustify()) {
switch (theme().titleFontJustify()) {
case FbTk::RIGHT:
dx += width() - l;
break;
@ -722,14 +774,20 @@ void Menu::redrawTitle() {
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
FbTk::GContext def_gc(menu.title);
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;
}
item->submenu()->moving = moving;
which_sub = index;
if (new_y < 0)
new_y = 0;
@ -801,8 +862,7 @@ void Menu::drawSubmenu(unsigned int index) {
item->submenu()->raise();
}
item->submenu()->moving = moving;
which_sub = index;
} else
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;
GC gc =
((highlight || item->isSelected()) ? m_theme.hiliteTextGC().gc() :
m_theme.frameTextGC().gc());
((highlight || item->isSelected()) ? theme().hiliteTextGC().gc() :
theme().frameTextGC().gc());
sel_x = item_x;
if (m_theme.bulletPos() == FbTk::RIGHT)
sel_x += (menu.item_w - menu.item_h - menu.bevel_w);
if (theme().bulletPos() == FbTk::RIGHT)
sel_x += (menu.item_w - menu.item_h - theme().bevelWidth());
sel_x += 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) {
GContext def_gc(menu.frame);
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);
} 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 (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_w, hilite_h);
} else {
m_frame_pm.fillRectangle(m_theme.hiliteGC().gc(),
m_frame_pm.fillRectangle(theme().hiliteGC().gc(),
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 (m_theme.selectedPixmap().pixmap().drawable()) {
if (theme().selectedPixmap().pixmap().drawable()) {
// enable clip mask
XSetClipMask(FbTk::App::instance()->display(),
gc,
m_theme.selectedPixmap().mask().drawable());
theme().selectedPixmap().mask().drawable());
XSetClipOrigin(FbTk::App::instance()->display(),
gc, sel_x, item_y);
// copy bullet pixmap to frame
m_frame_pm.copyArea(m_theme.selectedPixmap().pixmap().drawable(),
m_frame_pm.copyArea(theme().selectedPixmap().pixmap().drawable(),
gc,
0, 0,
sel_x, item_y,
m_theme.selectedPixmap().width(),
m_theme.selectedPixmap().height());
theme().selectedPixmap().width(),
theme().selectedPixmap().height());
// disable clip mask
XSetClipMask(FbTk::App::instance()->display(),
gc,
@ -911,12 +971,12 @@ int Menu::drawItem(unsigned int index, bool highlight, bool clear, bool render_t
} else {
if (menu.sel_pixmap) {
m_frame_pm.copyArea(highlight ? menu.frame_pixmap : menu.sel_pixmap,
m_theme.hiliteGC().gc(),
theme().hiliteGC().gc(),
0, 0,
sel_x, sel_y,
half_w, half_w);
} else {
m_frame_pm.fillRectangle(m_theme.hiliteGC().gc(),
m_frame_pm.fillRectangle(theme().hiliteGC().gc(),
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,
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,
menu.item_w, menu.item_h);
@ -1033,21 +1093,7 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
if (re.window == menu.title) {
if (moving) {
moving = false;
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
}
}
move(x(), y());
}
if (re.x >= 0 && re.x <= (signed) width() &&
@ -1170,7 +1216,9 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
void Menu::exposeEvent(XExposeEvent &ee) {
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) {
if (moving) {
@ -1213,18 +1261,12 @@ void Menu::exposeEvent(XExposeEvent &ee) {
(which_sub == static_cast<signed>(index)), // highlight
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);
*/
}
}
@ -1345,24 +1387,18 @@ void Menu::reconfigure() {
m_need_update = true; // redraw items
menu.bevel_w = theme().bevelWidth();
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
m_border_width = 20;
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());
menu.window.setBorderColor(m_theme.borderColor());
menu.title.setBorderColor(m_theme.borderColor());
menu.frame.setBorderColor(m_theme.borderColor());
menu.window.setBorderColor(theme().borderColor());
menu.title.setBorderColor(theme().borderColor());
menu.frame.setBorderColor(theme().borderColor());
menu.window.setBorderWidth(m_border_width);
menu.title.setBorderWidth(m_border_width);
@ -1415,14 +1451,20 @@ void Menu::update(FbTk::Subject *subj) {
reconfigure();
}
void Menu::renderTransp(int x, int y,
unsigned int width, unsigned int height) {
// no need to render transparent unless visible
if (!isVisible())
return;
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;
@ -1433,7 +1475,6 @@ void Menu::renderTransp(int x, int y,
m_transp->setSource(root, screenNumber());
if (m_transp->dest() != m_real_frame_pm.drawable())
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
// 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
#define FBTK_MENU_HH
@ -205,13 +205,15 @@ private:
std::string label;
int x_move, y_move, x_shift, y_shift, sublevels, persub, minsub,
grab_x, grab_y;
unsigned int title_h, frame_h, item_w, item_h, bevel_w,
bevel_h;
unsigned int title_h, frame_h, item_w, item_h, bevel_w;
} menu;
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, 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;
bool m_need_update;
Timer m_submenu_timer;