extension of previous big patch. Move a bunch of menu things onto

background pixmap. Same for textbuttons.
This commit is contained in:
simonb 2005-04-26 01:41:55 +00:00
parent b49432be05
commit 1c2f92a3d2
22 changed files with 462 additions and 386 deletions

View file

@ -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

View file

@ -249,6 +249,7 @@ void ClockTool::updateTime() {
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

View file

@ -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 @@ FbWindow::FbWindow(const FbWindow& the_copy):FbDrawable(),
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 @@ FbWindow::FbWindow(int 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 @@ FbWindow::FbWindow(const FbWindow &parent,
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 @@ FbWindow::FbWindow(Window client):FbDrawable(), m_parent(0),
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 @@ void FbWindow::updateBackground(bool only_if_alpha) {
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 @@ void FbWindow::updateBackground(bool only_if_alpha) {
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::clear() {
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,13 +256,16 @@ void FbWindow::updateTransparent(int the_x, int the_y, unsigned int the_width, u
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();
the_height = height();
@ -271,8 +281,8 @@ void FbWindow::updateTransparent(int the_x, int the_y, unsigned int the_width, u
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 @@ void FbWindow::updateTransparent(int the_x, int the_y, unsigned int the_width, u
// 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
}
@ -497,12 +507,6 @@ void FbWindow::setOpaque(unsigned char alpha) {
#endif // HAVE_XRENDER
}
/*
void FbWindow::setBufferPixmap(Pixmap pm) {
m_lastbg_pm = pm;
}
*/
void FbWindow::updateGeometry() {
if (m_window == 0)
return;

View file

@ -34,6 +34,8 @@ namespace FbTk {
class Color;
class Transparent;
class FbPixmap;
class FbWindowRenderer;
/// Wrapper for X window
/**
@ -82,7 +84,7 @@ public:
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 @@ public:
// 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 @@ private:
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,9 +241,15 @@ private:
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
#endif // FBTK_FBWINDOW_HH

View file

@ -131,6 +131,7 @@ public:
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; }

View file

@ -121,9 +121,7 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl):
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 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl):
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 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl):
false, // override redirect
true); // save under
evm.add(*this, menu.frame);
menu.frame.setRenderer(*this);
menu.title.raise();
@ -190,9 +190,6 @@ Menu::~Menu() {
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 @@ void Menu::nextItem() {
// 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 @@ void Menu::nextItem() {
m_active_index = m_which_press;
drawItem(m_which_press, true); // clear
clearItem(m_which_press);
}
@ -320,7 +317,7 @@ void Menu::prevItem() {
// 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 @@ void Menu::prevItem() {
m_active_index = m_which_press;
drawItem(m_which_press, true); // clear
clearItem(m_which_press);
}
@ -370,7 +367,7 @@ void Menu::enterParent() {
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 @@ void Menu::updateMenu(int active_index) {
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 @@ void Menu::updateMenu(int active_index) {
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::grabInputFocus() {
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 @@ void Menu::internal_hide() {
// 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 @@ void Menu::move(int x, int y) {
}
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 @@ void Menu::redrawTitle() {
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 @@ void Menu::drawSubmenu(unsigned int index) {
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 @@ bool Menu::hasSubmenu(unsigned int index) const {
}
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 @@ void Menu::buttonPressEvent(XButtonEvent &be) {
if (item->submenu()) {
if (!item->submenu()->isVisible())
drawSubmenu(w);
} else {
drawItem(w, true); // clear
}
}
} else {
@ -978,8 +886,7 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
// update these since we've (probably) moved
menu.title.parentMoved();
menu.frame.parentMoved();
redrawTitle();
redrawFrame();
clearWindow();
}
}
@ -1002,7 +909,7 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
}
}
drawItem(p, true); // clear
clearItem(p);
}
}
}
@ -1016,8 +923,8 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
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 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
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 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
// 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 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
// draw highlighted
m_submenu_timer.stop();
if (itmp->isEnabled()) {
drawItem(w, true); // clear
clearItem(w);
}
}
@ -1112,10 +1018,8 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
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 @@ void Menu::exposeEvent(XExposeEvent &ee) {
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 @@ void Menu::enterNotifyEvent(XCrossingEvent &ce) {
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 @@ void Menu::openSubmenu() {
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 @@ void Menu::update(FbTk::Subject *subj) {
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();
}
@ -1324,4 +1217,72 @@ void Menu::setScreen(int x, int y, int w, int h) {
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

View file

@ -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 @@ public:
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 @@ protected:
}
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 @@ private:
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 @@ private:
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;

View file

@ -53,35 +53,39 @@ void MenuIcon::updateTheme(const MenuTheme &theme) {
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();
// 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());
// restore clip mask
XSetClipMask(disp, gc, None);
}
}
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());
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);
}
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 {

View file

@ -38,6 +38,7 @@ public:
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;

View file

@ -39,142 +39,194 @@ void MenuItem::click(int button, int time) {
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);
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);
}
}
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());
// 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 || isSelected()) ? theme.hiliteTextGC().gc() :
theme.frameTextGC().gc());
int sel_x = x + height/4;
GC gc = (highlight) ? theme.hiliteTextGC().gc() :
theme.frameTextGC().gc();
int sel_x = x;
int sel_y = y;
unsigned int item_pm_height = theme.itemHeight();
if (theme.bulletPos() == FbTk::RIGHT)
sel_x += width - height - 2*theme.bevelWidth();
sel_x += width - height - theme.bevelWidth();
//
// 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);
// selected pixmap is foreground
if (draw_foreground && isToggleItem()) {
//
// ToggleItem
//
const PixmapWithMask *pm = 0;
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;
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 @@ void MenuItem::draw(FbDrawable &draw,
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 @@ void MenuItem::setIcon(const std::string &filename, int 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 @@ unsigned int MenuItem::width(const MenuTheme &theme) const {
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;
}

View file

@ -96,6 +96,8 @@ public:
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);

View file

@ -61,6 +61,9 @@ MenuTheme::MenuTheme(int screen_num):
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 @@ void MenuTheme::reconfigTheme() {
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);

View file

@ -71,6 +71,10 @@ public:
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 @@ public:
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 @@ private:
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;

View file

@ -24,8 +24,6 @@
#include "TextButton.hh"
#include "Font.hh"
#include "GContext.hh"
#include <iostream>
using namespace std;
namespace FbTk {
@ -38,6 +36,7 @@ TextButton::TextButton(const FbTk::FbWindow &parent,
m_justify(FbTk::LEFT), m_bevel(1),
m_left_padding(0),
m_right_padding(0) {
setRenderer(*this);
}
@ -62,7 +61,11 @@ void TextButton::setJustify(FbTk::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

View file

@ -35,7 +35,7 @@ namespace FbTk {
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 @@ public:
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 @@ public:
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;

View file

@ -377,7 +377,7 @@ void FbWinFrame::moveLabelButtonLeft(const FbTk::TextButton &btn) {
// 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 @@ void FbWinFrame::moveLabelButtonRight(const FbTk::TextButton &btn) {
// 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 @@ void FbWinFrame::moveLabelButtonLeftOf(const FbTk::TextButton &btn, const FbTk::
//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 @@ void FbWinFrame::moveLabelButtonRightOf(const FbTk::TextButton &btn, const FbTk:
else
m_labelbuttons.insert(new_pos, item);
//update titlebar
redrawTitle();
redrawTitlebar();
}
void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) {
@ -893,8 +893,8 @@ unsigned int FbWinFrame::buttonHeight() const {
/**
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 @@ void FbWinFrame::redrawTitle() {
}
}
void FbWinFrame::redrawTitlebar() {
if (!m_use_titlebar)
return;
redrawTitle();
}
/**
Align buttons with title text window
*/
@ -998,7 +990,6 @@ void FbWinFrame::reconfigureTitlebar() {
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 @@ void FbWinFrame::reconfigureTitlebar() {
button_size, button_size);
}
// renderTitlebar(); // gets done outside
m_titlebar.raise(); // always on top
}

View file

@ -193,7 +193,6 @@ public:
private:
void redrawTitlebar();
void redrawTitle();
/// reposition titlebar items
void reconfigureTitlebar();

View file

@ -288,12 +288,12 @@ void IconButton::setupWindow() {
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);
}

View file

@ -54,7 +54,7 @@ public:
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();

View file

@ -48,12 +48,11 @@ public:
// 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);
// }
}
}

View file

@ -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 @@ void FluxboxWindow::handleEvent(XEvent &event) {
//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) {

View file

@ -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 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
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;