Big changes to how transparency works

Consequently rearrange lots of rendering ops, and strip calls to 
updateTransparent
This commit is contained in:
simonb 2005-04-10 18:18:14 +00:00
parent 6cf66c6655
commit 88c66f0687
28 changed files with 750 additions and 955 deletions

View file

@ -1,5 +1,33 @@
(Format: Year/Month/Day)
Changes for 0.9.13
*05/04/11:
* Rework lots of stuff relating to transparency, esp menus+frame (Simon)
+ Massively reduce pixmap memory usage (view with xrestop)
+ Should also improve startup+style change times, esp for large menus
+ This introduces a few rendering bugs, but I'd like stuff tested
+ Transparency is done differently now. People shouldn't need to
call updateTransparent.
+ Do not use persistent pixmap buffers unless you're sure!
XSetWindowBackground already copies/buffers the set pixmap, so
things need to be rendered to a temp pixmap once, then can be
freed.
Known bugs (please report others to Rathnor on #fluxbox):
- different focus/unfocus transparency doesn't update labelbuttons
properly. Workaround: use same transparency for both.
- Text sometimes gets overdrawn a lot. Probably should render it to
background using a virtual hook in FbWindow::updateBackground
- Changing style resizes things, not all pixmaps updated properly
Workaround: restart fluxbox after changing style
- Probably breaks Composite support. Let me know how.
TODO:
+ FbPixmap::getRootPixmap called very often. It should cache the
result and watch the relevant properties.
Changed:
FbTk/ FbWindow.hh/cc Button.hh/cc Menu.hh/cc TextButton.hh/cc
Transparent.hh/cc FbPixmap.cc
Window.hh/cc FbWinFrame.hh/cc fluxbox.hh/cc ArrowButton.cc
ButtonTool.cc Container.cc GenericTool.cc Slit.cc ToggleMenu.hh
Toolbar.cc WinButton.hh/cc WinClient.cc
*05/04/09:
* minor fix to startfluxbox (Mathias)
*05/04/07:

View file

@ -52,13 +52,11 @@ ArrowButton::ArrowButton(ArrowButton::Type arrow_type,
void ArrowButton::clear() {
FbTk::Button::clear();
updateTransparent();
drawArrow();
}
void ArrowButton::exposeEvent(XExposeEvent &event) {
FbTk::Button::exposeEvent(event);
updateTransparent(event.x, event.y, event.width, event.height);
drawArrow();
}

View file

@ -87,6 +87,5 @@ void ButtonTool::renderTheme(unsigned char alpha) {
m_image_ctrl.removeImage(old_pm);
btn.clear();
btn.updateTransparent();
}

View file

@ -132,7 +132,6 @@ void Container::removeAll() {
m_item_list.clear();
if (!m_update_lock) {
clear();
updateTransparent();
}
}
@ -176,7 +175,6 @@ void Container::setAlignment(Container::Alignment a) {
void Container::exposeEvent(XExposeEvent &event) {
if (!m_update_lock) {
clearArea(event.x, event.y, event.width, event.height);
updateTransparent(event.x, event.y, event.width, event.height);
}
}

View file

@ -33,10 +33,9 @@ Button::Button(int screen_num, int x, int y,
unsigned int width, unsigned int height):
FbWindow(screen_num, x, y, width, height,
ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_foreground_pm(0),
m_background_pm(0),
m_pressed_pm(0),
m_pressed_color("black", screen_num),
m_pressed_color(),
m_gc(DefaultGC(FbTk::App::instance()->display(), screen_num)),
m_pressed(false) {
@ -48,10 +47,9 @@ Button::Button(const FbWindow &parent, int x, int y,
unsigned int width, unsigned int height):
FbWindow(parent, x, y, width, height,
ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_foreground_pm(0),
m_background_pm(0),
m_pressed_pm(0),
m_pressed_color("black", parent.screenNumber()),
m_pressed_color(),
m_gc(DefaultGC(FbTk::App::instance()->display(), screenNumber())),
m_pressed(false) {
// add this to eventmanager
@ -70,15 +68,12 @@ void Button::setOnClick(RefCount<Command> &cmd, int button) {
m_onclick[button - 1] = cmd;
}
void Button::setPixmap(Pixmap pm) {
m_foreground_pm = pm;
}
void Button::setPressedPixmap(Pixmap pm) {
m_pressed_pm = pm;
}
void Button::setPressedColor(const FbTk::Color &color) {
m_pressed_pm = None;
m_pressed_color = color;
}
@ -115,27 +110,16 @@ void Button::buttonReleaseEvent(XButtonEvent &event) {
if (m_background_pm) {
if (m_pressed_pm != 0) {
update = true;
setBackgroundPixmap(m_background_pm);
FbTk::FbWindow::setBackgroundPixmap(m_background_pm);
}
} else if (m_pressed_color.isAllocated()) {
update = true;
setBackgroundColor(m_background_color);
FbTk::FbWindow::setBackgroundColor(m_background_color);
}
if (update) {
if (update)
clear(); // clear background
if (m_foreground_pm) { // draw foreground pixmap
Display *disp = App::instance()->display();
if (m_gc == 0) // get default gc if we dont have one
m_gc = DefaultGC(disp, screenNumber());
XCopyArea(disp, m_foreground_pm, window(), m_gc, 0, 0, width(), height(), 0, 0);
}
}
// finaly, execute command (this must be done last since this object might be deleted by the command)
if (event.button > 0 && event.button <= 5 &&
event.x > 0 && event.x < static_cast<signed>(width()) &&
@ -147,14 +131,7 @@ void Button::buttonReleaseEvent(XButtonEvent &event) {
}
void Button::exposeEvent(XExposeEvent &event) {
/*
if (m_background_pm)
setBackgroundPixmap(m_background_pm);
else
setBackgroundColor(m_background_color);
*/
clearArea(event.x, event.y, event.width, event.height);
// updateTransparent(event.x, event.y, event.width, event.height);
}
}; // end namespace FbTk

View file

@ -48,11 +48,9 @@ public:
/// sets action when the button is clicked with #button mouse btn
void setOnClick(RefCount<Command> &com, int button = 1);
/// sets foreground pixmap
void setPixmap(Pixmap pm);
/// sets the pixmap to be viewed when the button is pressed
void setPressedPixmap(Pixmap pm);
void setPressedColor(const FbTk::Color &color);
virtual void setPressedPixmap(Pixmap pm);
virtual void setPressedColor(const FbTk::Color &color);
/// sets graphic context for drawing
void setGC(GC gc) { m_gc = gc; }
/// sets background pixmap, this will override background color
@ -78,9 +76,7 @@ public:
GC gc() const { return m_gc; }
Pixmap backgroundPixmap() const { return m_background_pm; }
const Color &backgroundColor() const { return m_background_color; }
Pixmap foregroundPixmap() const { return m_foreground_pm; }
private:
Pixmap m_foreground_pm; ///< foreground pixmap
Pixmap m_background_pm; ///< background pixmap
Color m_background_color; ///< background color
Pixmap m_pressed_pm; ///< pressed pixmap

View file

@ -311,13 +311,12 @@ Pixmap FbPixmap::getRootPixmap(int screen_num) {
if (XGetWindowProperty(display(),
RootWindow(display(), screen_num),
XInternAtom(display(), prop_ids[prop], False),
0l, 4l,
0l, 1l,
False, XA_PIXMAP,
&real_type, &real_format,
&items_read, &items_left,
(unsigned char **) &data) == Success) {
if (real_format == 32 && items_read == 1) {
if (print_error && strcmp(prop_ids[prop], "_XSETROOT_ID") == 0) {
cerr<<error_message;
print_error = false;

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_buffer_pm(0){
m_lastbg_pm(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_buffer_pm(0) {
m_lastbg_pm(0) {
the_copy.m_window = 0;
}
@ -73,7 +73,9 @@ FbWindow::FbWindow(int screen_num,
m_parent(0),
m_screen_num(screen_num),
m_destroy(true),
m_buffer_pm(0) {
m_lastbg_color_set(false),
m_lastbg_color(0),
m_lastbg_pm(0) {
create(RootWindow(display(), screen_num),
x, y, width, height, eventmask,
@ -89,7 +91,9 @@ FbWindow::FbWindow(const FbWindow &parent,
m_parent(&parent),
m_screen_num(parent.screenNumber()),
m_destroy(true),
m_buffer_pm(0) {
m_lastbg_color_set(false),
m_lastbg_color(0x42),
m_lastbg_pm(0) {
create(parent.window(), x, y, width, height, eventmask,
override_redirect, save_unders, depth, class_type);
@ -105,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_buffer_pm(0) {
m_lastbg_pm(0) {
setNew(client);
}
@ -124,13 +128,90 @@ FbWindow::~FbWindow() {
}
}
void FbWindow::setBackgroundColor(const FbTk::Color &bg_color) {
XSetWindowBackground(display(), m_window, bg_color.pixel());
if (bg_color.isAllocated()) {
m_lastbg_color = bg_color.pixel();
m_lastbg_color_set = true;
m_lastbg_pm = None;
} else {
m_lastbg_color_set = false;
}
updateBackground(false);
}
void FbWindow::setBackgroundPixmap(Pixmap bg_pixmap) {
XSetWindowBackgroundPixmap(display(), m_window, bg_pixmap);
m_lastbg_pm = bg_pixmap;
if (bg_pixmap != None)
m_lastbg_color_set = false;
updateBackground(false);
}
void FbWindow::updateBackground(bool only_if_alpha) {
Pixmap newbg = m_lastbg_pm;
unsigned char alpha = 255;
bool free_newbg = false;
if (m_transparent.get() != 0)
alpha = m_transparent->alpha();
if (only_if_alpha && alpha == 255)
return;
if (alpha != 255 && m_lastbg_pm != ParentRelative) {
// update source and destination if needed
Pixmap root = FbPixmap::getRootPixmap(screenNumber());
if (m_transparent->source() != root)
m_transparent->setSource(root, screenNumber());
newbg = XCreatePixmap(display(), window(), width(), height(), depth());
free_newbg = true;
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());
} 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);
}
XFreeGC(display(), gc);
m_transparent->setDest(newbg, screenNumber());
// get root position
const FbWindow *root_parent = parent();
// our position in parent ("root")
int root_x = x() + borderWidth(), root_y = y() + 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();
}
}
// render background image from root pos to our window
m_transparent->render(root_x, root_y,
0, 0,
width(), height());
m_transparent->freeDest(); // it's only temporary, don't leave it hanging around
}
if (newbg != None)
XSetWindowBackgroundPixmap(display(), m_window, newbg);
else if (m_lastbg_color_set)
XSetWindowBackground(display(), m_window, m_lastbg_color);
if (free_newbg)
XFreePixmap(display(), newbg);
}
void FbWindow::setBorderColor(const FbTk::Color &border_color) {
@ -168,6 +249,13 @@ 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()) &&
the_x <= 0 && the_y <= 0) {
// do the whole thing
updateBackground(true);
return;
}
if (the_width == 0 || the_height == 0) {
the_width = width();
the_height = height();
@ -183,14 +271,9 @@ 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_buffer_pm) {
if (m_transparent->dest() != m_buffer_pm) {
m_transparent->setDest(m_buffer_pm, screenNumber());
}
} else if (m_transparent->dest() != window())
if (m_transparent->dest() != window())
m_transparent->setDest(window(), screenNumber());
// get root position
const FbWindow *root_parent = parent();
@ -414,9 +497,11 @@ void FbWindow::setOpaque(unsigned char alpha) {
#endif // HAVE_XRENDER
}
/*
void FbWindow::setBufferPixmap(Pixmap pm) {
m_buffer_pm = pm;
m_lastbg_pm = pm;
}
*/
void FbWindow::updateGeometry() {
if (m_window == 0)

View file

@ -93,24 +93,40 @@ public:
virtual void show();
virtual void showSubwindows();
/// Notify that the parent window was moved,
/// thus the absolute position of this one moved
virtual inline void parentMoved() {
updateBackground(true);
}
virtual inline void move(int x, int y) {
if (x == m_x && y == m_y)
return;
XMoveWindow(s_display, m_window, x, y);
m_x = x;
m_y = y;
updateBackground(true);
}
virtual inline void resize(unsigned int width, unsigned int height) {
XResizeWindow(s_display, m_window, width, height);
m_width = width;
m_height = height;
if (width == m_width && height == m_height)
return;
XResizeWindow(s_display, m_window, width, height);
m_width = width;
m_height = height;
updateBackground(true);
}
virtual inline void moveResize(int x, int y, unsigned int width, unsigned int height) {
if (x == m_x && y == m_y && width == m_width && height == m_height)
return;
XMoveResizeWindow(s_display, m_window, x, y, width, height);
m_x = x;
m_y = y;
m_width = width;
m_height = height;
updateBackground(true);
}
virtual void lower();
virtual void raise();
@ -139,8 +155,6 @@ public:
void deleteProperty(Atom property);
void setBufferPixmap(Pixmap pm);
std::string textProperty(Atom property) const;
/// @return parent FbWindow
@ -184,6 +198,9 @@ private:
bool save_unders,
int depth,
int class_type);
/// forces full background change, recalcing of alpha values if necessary
void updateBackground(bool only_if_alpha);
const FbWindow *m_parent; ///< parent FbWindow
int m_screen_num; ///< screen num on which this window exist
mutable Window m_window; ///< the X window
@ -193,7 +210,9 @@ private:
int m_depth; ///< bit depth
bool m_destroy; ///< wheter the x window was created before
std::auto_ptr<FbTk::Transparent> m_transparent;
Pixmap m_buffer_pm;
bool m_lastbg_color_set;
unsigned long m_lastbg_color;
Pixmap m_lastbg_pm;
};
bool operator == (Window win, const FbWindow &fbwin);

View file

@ -86,7 +86,6 @@ Menu::Menu(MenuTheme &tm, ImageControl &imgctrl):
m_alignment(ALIGNDONTCARE),
m_active_index(-1),
m_need_update(true) {
// setup timers
RefCount<Command> show_cmd(new SimpleCommand<Menu>(*this, &Menu::openSubmenu));
@ -286,9 +285,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
true); // transp
drawItem(old_which_press, true); // clear
}
// restore old in case we changed m_which_press
@ -309,9 +306,7 @@ void Menu::nextItem() {
m_active_index = m_which_press;
drawItem(m_which_press,
true, // clear
true); // transp
drawItem(m_which_press, true); // clear
}
@ -325,9 +320,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
true); // transp
drawItem(old_which_press, true); // clear
}
// restore old in case we changed m_which_press
m_which_press = old_which_press - 1;
@ -347,9 +340,7 @@ void Menu::prevItem() {
m_active_index = m_which_press;
drawItem(m_which_press,
true, // clear
true); // transp
drawItem(m_which_press, true); // clear
}
@ -379,9 +370,7 @@ void Menu::enterParent() {
submenu->internal_hide();
m_active_index = -1;
drawItem(m_which_press,
true, // clear
true); // transp
drawItem(m_which_press, true); // clear
m_which_press = -1; // dont select any in this
// hide self
m_visible = false;
@ -399,10 +388,13 @@ void Menu::enableTitle() {
}
void Menu::updateMenu(int active_index) {
if (!m_visible) {
m_need_update = true;
return;
}
if (m_title_vis) {
menu.item_w = theme().titleFont().textWidth(menu.label.c_str(),
menu.label.size());
menu.item_w += (theme().bevelWidth() * 2);
} else
menu.item_w = 1;
@ -433,6 +425,9 @@ void Menu::updateMenu(int active_index) {
menu.persub = 0;
}
if (menu.frame.alpha() != alpha())
menu.frame.setAlpha(alpha());
int itmp = (theme().itemHeight() * menu.persub);
menu.frame_h = itmp < 1 ? 1 : itmp;
@ -461,60 +456,16 @@ void Menu::updateMenu(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(), theme().titleHeight(), tex);
// set pixmap that we have as real face to the user
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() != theme().titleHeight()) {
if (m_title_pm.drawable() != None) {
m_title_pm.resize(width(), theme().titleHeight());
m_real_title_pm.resize(width(), theme().titleHeight());
} else {
m_title_pm.create(menu.title.window(),
width(), theme().titleHeight(),
menu.title.depth());
m_real_title_pm.create(menu.title.window(),
width(), theme().titleHeight(),
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;
@ -522,9 +473,11 @@ void Menu::updateMenu(int active_index) {
if (m_need_update) {
if (!frame_tex.usePixmap()) {
menu.frame_pixmap = None;
menu.frame.setBackgroundColor(frame_tex.color());
} else {
menu.frame_pixmap =
m_image_ctrl.renderImage(width(), menu.frame_h, frame_tex);
menu.frame.setBackgroundPixmap(menu.frame_pixmap);
}
if (tmp)
@ -563,71 +516,12 @@ void Menu::updateMenu(int active_index) {
menu.title.borderWidth()*2 : 1),
width(), menu.frame_h);
if (m_need_update || m_frame_pm.width() != menu.frame.width() ||
m_frame_pm.height() != menu.frame.height()){
if (m_frame_pm.drawable() != None) {
m_frame_pm.resize(menu.frame.width(), menu.frame.height());
m_real_frame_pm.resize(menu.frame.width(), menu.frame.height());
} else {
m_frame_pm.create(menu.frame.window(),
menu.frame.width(), menu.frame.height(),
menu.frame.depth());
m_real_frame_pm.create(menu.frame.window(),
menu.frame.width(), menu.frame.height(),
menu.frame.depth());
}
if (m_transp.get() != 0)
m_transp->setDest(m_real_frame_pm.drawable(), screenNumber());
menu.frame.setBackgroundPixmap(m_real_frame_pm.drawable());
GContext def_gc(menu.frame);
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()<<", "<<menu.frame.width()<<", "<<
menu.frame.height()<<
", "<<menu.frame.depth()<<") !"<<endl;
} else {
if (menu.frame_pixmap == 0) {
def_gc.setForeground(theme().frameTexture().color());
m_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(m_frame_pm.drawable(),
def_gc.gc(),
0, 0,
0, 0,
m_frame_pm.width(), m_frame_pm.height());
}
// if menu m_visible and title m_visible
if (m_title_vis && m_visible)
redrawTitle();
if (active_index >= 0 || m_need_update) {
renderTransp(0, 0,
m_real_frame_pm.width(), m_real_frame_pm.height());
for (unsigned int i = 0; i < menuitems.size(); i++) {
drawItem(i, // index
true, // clear
false); // render_trans
}
if (m_visible && (active_index >= 0 || m_need_update)) {
redrawFrame();
}
m_need_update = false;
@ -636,8 +530,13 @@ void Menu::updateMenu(int active_index) {
void Menu::show() {
if (m_need_update)
if (m_visible)
return;
if (m_need_update) {
m_visible = true;
updateMenu();
}
menu.window.showSubwindows();
menu.window.show();
@ -683,16 +582,16 @@ void Menu::grabInputFocus() {
void Menu::clearWindow() {
redrawTitle();
if (alpha() < 255) {
renderTransp(0, 0,
menu.frame.width(), menu.frame.height());
updateMenu();
redrawTitle();
redrawFrame();
}
void Menu::redrawFrame() {
menu.frame.clear();
for (unsigned int i = 0; i < menuitems.size(); i++) {
drawItem(i, false); // no clear
}
menu.title.clear();
menu.frame.clear();
}
void Menu::internal_hide() {
@ -713,7 +612,7 @@ void Menu::internal_hide() {
m_torn = m_visible = false;
m_which_sub = m_which_press = m_which_sub = -1;
menu.window.hide();
}
@ -722,33 +621,19 @@ void Menu::move(int x, int y) {
if (x == this->x() && y == this->y())
return;
// if we're not m_visible and we do transparency
// we need to update transparency when we call
// show() next time
if (alpha() < 255)
m_need_update = true;
menu.window.move(x, y);
// potentially transparent children
menu.title.parentMoved();
menu.frame.parentMoved();
if (!isVisible())
return;
if (alpha() < 255)
clearWindow();
if (m_which_sub != -1)
drawSubmenu(m_which_sub);
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,
true, // clear
false); // transparent
}
m_need_update = false;
}
}
@ -776,16 +661,11 @@ void Menu::redrawTitle() {
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.clear();
// difference between height based on font, and style-set height
int height_offset = theme().titleHeight() - (font.height() + 2*theme().bevelWidth());
menu.title.updateTransparent();
font.drawText(m_real_title_pm, // drawable
font.drawText(menu.title, // drawable
screenNumber(),
theme().titleTextGC().gc(), // graphic context
text, len, // text string with length
@ -885,17 +765,22 @@ bool Menu::hasSubmenu(unsigned int index) const {
}
int Menu::drawItem(unsigned int index, bool clear, bool render_trans,
int Menu::drawItem(unsigned int index, bool clear,
int x, int y, unsigned int w, unsigned int h) {
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();
@ -914,50 +799,23 @@ int Menu::drawItem(unsigned int index, bool clear, bool render_trans,
sel_y = item_y + quarter_w;
if (clear) {
GContext def_gc(menu.frame);
if (menu.frame_pixmap == 0) {
def_gc.setForeground(theme().frameTexture().color());
m_frame_pm.fillRectangle(def_gc.gc(), item_x, item_y, menu.item_w, theme().itemHeight());
} else {
m_frame_pm.copyArea(menu.frame_pixmap, def_gc.gc(),
item_x, item_y,
item_x, item_y,
menu.item_w, theme().itemHeight());
}
} 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 + theme().itemHeight(), 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;
hilite_h = std::min(item_y + theme().itemHeight(), y + h) - hilite_y;
hoff_x = hilite_x % menu.item_w;
hoff_y = hilite_y % theme().itemHeight();
}
frameWindow().clearArea(item_x, item_y,
menu.item_w, theme().itemHeight(), False);
}
if (highlight && (menu.hilite_pixmap != ParentRelative)) {
if (menu.hilite_pixmap) {
m_frame_pm.copyArea(menu.hilite_pixmap,
menu.frame.copyArea(menu.hilite_pixmap,
theme().hiliteGC().gc(), hoff_x, hoff_y,
hilite_x, hilite_y,
hilite_w, hilite_h);
} else {
m_frame_pm.fillRectangle(theme().hiliteGC().gc(),
hilite_x, hilite_y, hilite_w, hilite_h);
item_x, item_y,
item_w, item_h);
} else {
menu.frame.fillRectangle(theme().hiliteGC().gc(),
item_x, item_y, item_w, item_h);
}
}
if (render_trans) {
renderTransp(item_x, item_y,
menu.item_w, theme().itemHeight());
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
@ -974,7 +832,7 @@ int Menu::drawItem(unsigned int index, bool clear, bool render_trans,
XSetClipOrigin(disp,
gc, sel_x, item_y);
// copy bullet pixmap to frame
m_real_frame_pm.copyArea(theme().selectedPixmap().pixmap().drawable(),
menu.frame.copyArea(theme().selectedPixmap().pixmap().drawable(),
gc,
0, 0,
sel_x, item_y,
@ -985,31 +843,24 @@ int Menu::drawItem(unsigned int index, bool clear, bool render_trans,
gc,
None);
} else {
if (menu.sel_pixmap) {
m_real_frame_pm.copyArea(highlight ? menu.frame_pixmap : menu.sel_pixmap,
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 {
m_real_frame_pm.fillRectangle(theme().hiliteGC().gc(),
menu.frame.fillRectangle(theme().hiliteGC().gc(),
sel_x, sel_y, half_w, half_w);
}
}
}
item->draw(m_real_frame_pm, theme(), highlight,
item->draw(menu.frame, theme(), highlight,
item_x, item_y,
menu.item_w, theme().itemHeight());
if (clear) {
frameWindow().clearArea(item_x, item_y,
menu.item_w, theme().itemHeight(), False);
}
return item_y;
}
@ -1104,11 +955,8 @@ void Menu::buttonPressEvent(XButtonEvent &be) {
if (!item->submenu()->isVisible())
drawSubmenu(w);
} else {
drawItem(w,
true, // clear
true); // render transparency
drawItem(w, true); // clear
}
}
} else {
menu.x_move = be.x_root - x();
@ -1126,16 +974,11 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
drawSubmenu(m_which_sub);
if (alpha() < 255) {
// update these since we've (probably) moved
menu.title.parentMoved();
menu.frame.parentMoved();
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,
true, // clear
false); // transparent
}
redrawFrame();
}
}
@ -1158,9 +1001,7 @@ void Menu::buttonReleaseEvent(XButtonEvent &re) {
}
}
drawItem(p,
true, // clear
true); // transparent
drawItem(p, true); // clear
}
}
}
@ -1174,9 +1015,7 @@ 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
true); // render transparency
m_parent->drawItem(m_parent->m_which_sub, true); // clear
m_parent->m_which_sub = -1;
}
@ -1207,9 +1046,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
if (item != 0) {
drawItem(old,
true, // clear
true); // transparent
drawItem(old, true); // clear
if (item->submenu()) {
@ -1247,8 +1084,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
// draw item highlighted and
// start submenu open delay
drawItem(w,
true); // clear
drawItem(w, true); // clear
if (theme().menuMode() == MenuTheme::DELAY_OPEN) {
// setup show menu timer
@ -1265,9 +1101,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
// draw highlighted
m_submenu_timer.stop();
if (itmp->isEnabled()) {
drawItem(w,
true, // clear
true); // transp
drawItem(w, true); // clear
}
}
@ -1278,9 +1112,38 @@ 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)
} 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
// items down in that sublevel
int sbl = (ee.x / menu.item_w), id = (ee.y / theme().itemHeight()),
// next... figure out how many sublevels over the redrawspans
sbl_d = ((ee.x + ee.width) / menu.item_w),
// then we see how many items down to redraw
id_d = ((ee.y + ee.height) / theme().itemHeight());
if (id_d > menu.persub) id_d = menu.persub;
// draw the sublevels and the number of items the exposure spans
int i, ii;
for (i = sbl; i <= sbl_d; i++) {
// set the iterator to the first item in the sublevel needing redrawing
int index = id + i * menu.persub;
if (index < static_cast<int>(menuitems.size()) && index >= 0) {
Menuitems::iterator it = menuitems.begin() + index;
Menuitems::iterator it_end = menuitems.end();
for (ii = id; ii <= id_d && it != it_end; ++it, ii++) {
int index = ii + (i * menu.persub);
// redraw the item
drawItem(index, false); // no clear
}
}
}
}
}
@ -1307,9 +1170,13 @@ void Menu::enterNotifyEvent(XCrossingEvent &ce) {
}
if (m_shifted)
if (m_shifted) {
menu.window.move(menu.x_shift, menu.y_shift);
menu.title.parentMoved();
menu.frame.parentMoved();
clearWindow();
}
if (validIndex(m_which_sub)) {
MenuItem *tmp = menuitems[m_which_sub];
if (tmp->submenu()->isVisible()) {
@ -1319,9 +1186,7 @@ void Menu::enterNotifyEvent(XCrossingEvent &ce) {
if (w != m_which_sub && (! tmp->submenu()->isTorn())) {
tmp->submenu()->internal_hide();
drawItem(m_which_sub,
true, // clear
true); // transp
drawItem(m_which_sub, true); // clear
m_which_sub = -1;
}
}
@ -1335,9 +1200,7 @@ void Menu::leaveNotifyEvent(XCrossingEvent &ce) {
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
true); // transp
drawItem(p, true); // clear
m_which_sbl = m_which_press = -1;
}
@ -1390,31 +1253,13 @@ void Menu::keyPressEvent(XKeyEvent &event) {
void Menu::reconfigure() {
if (FbTk::Transparent::haveComposite()) {
if (m_transp.get() != 0)
m_transp.reset(0);
if (FbTk::Transparent::haveComposite())
menu.window.setOpaque(alpha());
} else 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(FbPixmap::getRootPixmap(screenNumber()),
m_real_frame_pm.drawable(), alpha(),
screenNumber()));
} else {
Pixmap root = FbPixmap::getRootPixmap(screenNumber());
if (m_transp->source() != root)
m_transp->setSource(root, screenNumber());
m_transp->setAlpha(alpha());
}
}
m_need_update = true; // redraw items
menu.title.setAlpha(alpha());
menu.frame.setAlpha(alpha());
menu.window.setBorderColor(theme().borderColor());
menu.title.setBorderColor(theme().borderColor());
@ -1423,9 +1268,9 @@ void Menu::reconfigure() {
menu.window.setBorderWidth(theme().borderWidth());
menu.title.setBorderWidth(theme().borderWidth());
updateMenu();
if (m_visible) {
updateMenu();
}
}
@ -1438,8 +1283,7 @@ void Menu::openSubmenu() {
if (!validIndex(item))
return;
drawItem(item,
true); // clear
drawItem(item, true); // clear
if (menuitems[item]->submenu() != 0 && !menuitems[item]->submenu()->isVisible())
drawSubmenu(item);
@ -1474,61 +1318,6 @@ void Menu::update(FbTk::Subject *subj) {
}
void Menu::renderTransp(int x, int y,
unsigned int width, unsigned int height) {
// even though we dont render transparency
// we do need to copy the style background
GContext def_gc(menu.frame);
m_real_frame_pm.copyArea(m_frame_pm.drawable(),
def_gc.gc(),
x, y,
x, y,
width, height);
// no need to render transparent unless visible
// but we do need to render it if we marked it as
// need update
if (!isVisible() && !m_need_update || m_transp.get() == 0)
return;
// render the root background
#ifdef HAVE_XRENDER
Pixmap root = FbPixmap::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
}
void Menu::setScreen(int x, int y, int w, int h) {
m_screen_x = x;
m_screen_y = y;

View file

@ -45,7 +45,6 @@ namespace FbTk {
class MenuItem;
class ImageControl;
class Transparent;
/// Base class for menus
class Menu: public FbTk::EventHandler, protected FbTk::Observer {
@ -179,15 +178,16 @@ protected:
virtual void itemSelected(int button, unsigned int index) { }
virtual int drawItem(unsigned int index,
bool clear = false, bool render_trans = true,
bool clear = false,
int x= -1, int y= -1,
unsigned int width= 0, unsigned int height= 0);
virtual void redrawTitle();
virtual void redrawFrame();
virtual void internal_hide();
void update(FbTk::Subject *);
void renderTransp(int x, int y,
unsigned int width, unsigned int height);
private:
void openSubmenu();
@ -229,11 +229,6 @@ 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, ///< 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;
Timer m_hide_timer;

View file

@ -37,8 +37,7 @@ TextButton::TextButton(const FbTk::FbWindow &parent,
m_text(text),
m_justify(FbTk::LEFT), m_bevel(1),
m_left_padding(0),
m_right_padding(0),
m_buffer(drawable(), width(), height(), depth()) {
m_right_padding(0) {
}
@ -46,10 +45,6 @@ void TextButton::resize(unsigned int width, unsigned int height) {
if (this->width() == width && height == this->height())
return;
m_buffer.resize(width, height);
if (backgroundPixmap() != ParentRelative)
FbWindow::setBackgroundPixmap(m_buffer.drawable());
Button::resize(width, height);
}
@ -59,12 +54,6 @@ void TextButton::moveResize(int x, int y,
x == this->x() && y == this->y())
return;
if (this->width() != width || height != this->height())
m_buffer.resize(width, height);
if (backgroundPixmap() != ParentRelative)
FbWindow::setBackgroundPixmap(m_buffer.drawable());
Button::moveResize(x, y, width, height);
}
@ -112,37 +101,12 @@ void TextButton::clear() {
void TextButton::clearArea(int x, int y,
unsigned int width, unsigned int height,
bool exposure) {
if (backgroundPixmap() != ParentRelative) {
if (backgroundPixmap()) {
m_buffer.copyArea(backgroundPixmap(),
gc(),
x, y,
x, y,
width, height);
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();
} else { // fill with background color
FbTk::GContext gc(m_buffer);
gc.setForeground(backgroundColor());
m_buffer.fillRectangle(gc.gc(),
x, y,
width, height);
}
drawText();
setBufferPixmap(m_buffer.drawable());
FbWindow::setBackgroundPixmap(m_buffer.drawable());
updateTransparent(x, y, width, height);
FbWindow::clearArea(x, y, width, height, exposure);
} else { // parent relative
FbWindow::setBufferPixmap(0);
FbWindow::setBackgroundPixmap(backgroundPixmap());
Button::clearArea(x, y, width, height, exposure);
updateTransparent(x, y, width, height);
drawText();
}
}
unsigned int TextButton::textWidth() const {
@ -161,11 +125,8 @@ void TextButton::drawText(int x_offset, int y_offset) {
// center text by default
int center_pos = height()/2 + font().ascent()/2 - 1;
FbDrawable *drawable = &m_buffer;
if (backgroundPixmap() == ParentRelative)
drawable = this;
font().drawText(*drawable,
font().drawText(*this,
screenNumber(),
gc(), // graphic context
text().c_str(), textlen, // string and string size

View file

@ -81,7 +81,6 @@ private:
unsigned int m_left_padding; ///< space between buttonborder and text
unsigned int m_right_padding; ///< space between buttonborder and text
FbTk::FbPixmap m_buffer; ///< for background buffer
};
} // end namespace FbTk

View file

@ -206,6 +206,17 @@ void Transparent::setAlpha(unsigned char alpha) {
allocAlpha(alpha);
}
void Transparent::freeDest() {
#ifdef HAVE_XRENDER
if (m_dest_pic != 0) {
Display *disp = FbTk::App::instance()->display();
XRenderFreePicture(disp, m_dest_pic);
m_dest_pic = 0;
}
m_dest = None;
#endif
}
void Transparent::setDest(Drawable dest, int screen_num) {
#ifdef HAVE_XRENDER
if (m_dest == dest || !s_render)
@ -213,10 +224,7 @@ void Transparent::setDest(Drawable dest, int screen_num) {
Display *disp = FbTk::App::instance()->display();
if (m_dest_pic != 0) {
XRenderFreePicture(disp, m_dest_pic);
m_dest_pic = 0;
}
freeDest();
// create new dest pic if we have a valid dest drawable
if (dest != 0) {

View file

@ -39,6 +39,7 @@ public:
void setSource(Drawable src, int screen_num);
/// sets destination drawable
void setDest(Drawable dest, int screen_num);
void freeDest();
/**
renders to dest from src with specified coordinates and size
*/

View file

@ -82,37 +82,14 @@ FbWinFrame::FbWinFrame(FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
m_focused(false),
m_visible(false),
m_button_pm(0),
m_need_render(true),
m_themelistener(*this),
m_shape(new Shape(m_window, theme.shapePlace())) {
m_theme.reconfigSig().attach(&m_themelistener);
init();
}
/*
FbWinFrame::FbWinFrame(FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl, const FbTk::FbWindow &parent, int x, int y,
unsigned int width, unsigned int height):
m_theme(theme),
m_imagectrl(imgctrl),
m_window(parent, x, y, width, height, ExposureMask | StructureNotifyMask),
m_titlebar(m_window, 0, 0, 100, 16,
ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_label(m_titlebar, 0, 0, 100, 16,
ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_grip_right(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_grip_left(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_handle(m_window, 0, 0, 100, 100, ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_clientarea(m_window, 0, 0, 100, 100, SubstructureRedirectMask),
m_bevel(1),
m_use_titlebar(true),
m_use_handles(true),
m_button_pm(0) {
init();
}
*/
FbWinFrame::~FbWinFrame() {
m_update_timer.stop();
removeEventHandler();
removeAllButtons();
}
@ -141,9 +118,15 @@ void FbWinFrame::hide() {
void FbWinFrame::show() {
m_visible = true;
if (m_need_render) {
renderAll();
applyAll();
clearAll();
}
m_window.showSubwindows();
m_window.show();
updateTransparent();
}
/**
@ -217,14 +200,11 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh
if (move && resize) {
m_window.moveResize(x, y, width, height);
notifyMoved(false); // will reconfigure
} else if (move) {
m_window.move(x, y);
// this stuff will be caught by reconfigure if resized
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (alpha != 255) {
// restart update timer
m_update_timer.start();
}
notifyMoved(true);
} else {
m_window.resize(width, height);
}
@ -233,29 +213,86 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh
reconfigure();
}
void FbWinFrame::notifyMoved(bool clear) {
// not important if no alpha...
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (alpha == 255)
return;
if (m_use_titlebar) {
m_titlebar.parentMoved();
m_label.parentMoved();
for_each(m_buttons_left.begin(),
m_buttons_left.end(),
mem_fun(&FbTk::Button::parentMoved));
for_each(m_buttons_right.begin(),
m_buttons_right.end(),
mem_fun(&FbTk::Button::parentMoved));
for_each(m_labelbuttons.begin(),
m_labelbuttons.end(),
mem_fun(&FbTk::Button::parentMoved));
}
if (m_use_handle) {
m_handle.parentMoved();
m_grip_left.parentMoved();
m_grip_right.parentMoved();
}
if (clear && (m_use_handle || m_use_titlebar)) {
clearAll();
}
}
void FbWinFrame::clearAll() {
if (m_use_titlebar) {
redrawTitlebar();
for_each(m_buttons_left.begin(),
m_buttons_left.end(),
mem_fun(&FbTk::Button::clear));
for_each(m_buttons_right.begin(),
m_buttons_right.end(),
mem_fun(&FbTk::Button::clear));
}
if (m_use_handle) {
m_handle.clear();
m_grip_left.clear();
m_grip_right.clear();
}
}
void FbWinFrame::setFocus(bool newvalue) {
if (m_focused == newvalue)
return;
m_focused = newvalue;
if (theme().focusedAlpha() != theme().unfocusedAlpha()) {
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (FbTk::Transparent::haveComposite()) {
m_window.setOpaque(alpha);
} else {
LabelList::iterator btn_it = m_labelbuttons.begin();
LabelList::iterator btn_it_end = m_labelbuttons.end();
for (; btn_it != btn_it_end; ++btn_it) {
(*btn_it)->setAlpha(alpha);
}
}
}
if (currentLabel()) {
if (newvalue) // focused
renderButtonFocus(*m_current_label);
applyFocusLabel(*m_current_label);
else // unfocused
renderButtonActive(*m_current_label);
applyActiveLabel(*m_current_label);
}
if (theme().focusedAlpha() != theme().unfocusedAlpha() && FbTk::Transparent::haveComposite()) {
if (m_focused)
m_window.setOpaque(theme().focusedAlpha());
else
m_window.setOpaque(theme().unfocusedAlpha());
}
renderTitlebar();
renderButtons(); // parent relative buttons -> need render after titlebar
renderHandles();
applyTitlebar();
applyHandles();
clearAll();
}
void FbWinFrame::setDoubleClickTime(unsigned int time) {
@ -266,7 +303,7 @@ void FbWinFrame::addLeftButton(FbTk::Button *btn) {
if (btn == 0) // valid button?
return;
setupButton(*btn); // setup theme and other stuff
applyButton(*btn); // setup theme and other stuff
m_buttons_left.push_back(btn);
}
@ -275,7 +312,7 @@ void FbWinFrame::addRightButton(FbTk::Button *btn) {
if (btn == 0) // valid button?
return;
setupButton(*btn); // setup theme and other stuff
applyButton(*btn); // setup theme and other stuff
m_buttons_right.push_back(btn);
}
@ -470,14 +507,14 @@ void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) {
// render label buttons
if (currentLabel() != 0)
renderButtonUnfocus(*m_current_label);
applyUnfocusLabel(*m_current_label);
m_current_label = *it; // current focused button
if (m_focused)
renderButtonFocus(*m_current_label);
applyFocusLabel(*m_current_label);
else
renderButtonActive(*m_current_label);
applyActiveLabel(*m_current_label);
}
void FbWinFrame::setClientWindow(FbTk::FbWindow &win) {
@ -571,9 +608,11 @@ bool FbWinFrame::showHandle() {
if (m_use_handle || theme().handleWidth() == 0)
return false;
// weren't previously rendered...
renderHandles();
m_use_handle = true;
renderHandles();
m_handle.show();
m_handle.showSubwindows(); // shows grips
@ -691,19 +730,14 @@ void FbWinFrame::buttonReleaseEvent(XButtonEvent &event) {
void FbWinFrame::exposeEvent(XExposeEvent &event) {
if (m_titlebar == event.window) {
m_titlebar.clearArea(event.x, event.y, event.width, event.height);
m_titlebar.updateTransparent(event.x, event.y, event.width, event.height);
} else if (m_label == event.window) {
m_label.clearArea(event.x, event.y, event.width, event.height);
m_label.updateTransparent(event.x, event.y, event.width, event.height);
} else if (m_handle == event.window) {
m_handle.clearArea(event.x, event.y, event.width, event.height);
m_handle.updateTransparent(event.x, event.y, event.width, event.height);
} else if (m_grip_left == event.window) {
m_grip_left.clearArea(event.x, event.y, event.width, event.height);
m_grip_left.updateTransparent(event.x, event.y, event.width, event.height);
} else if (m_grip_right == event.window) {
m_grip_right.clearArea(event.x, event.y, event.width, event.height);
m_grip_right.updateTransparent(event.x, event.y, event.width, event.height);
} else {
// create compare function
// that we should use with find_if
@ -819,9 +853,8 @@ void FbWinFrame::reconfigure() {
// render the theme
renderButtons();
if (!m_shaded)
renderHandles();
renderAll();
applyAll();
if (m_shape.get() && theme().shapePlace() == Shape::NONE || m_disable_shape)
m_shape.reset(0);
@ -914,20 +947,15 @@ void FbWinFrame::redrawTitle() {
dx - border_width,
label().height() + border_width);
}
if (isVisible()) {
for_each(m_labelbuttons.begin(),
m_labelbuttons.end(),
mem_fun(&FbTk::Button::clear));
}
mem_fun(&FbTk::TextButton::clear));
if (isVisible()) {
m_label.clear();
m_label.updateTransparent();
m_titlebar.clear();
m_titlebar.updateTransparent();
}
}
@ -964,12 +992,13 @@ 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);
}
next_x += m_bevel;
// space left on titlebar between left and right buttons
unsigned int space_left = m_titlebar.width() - next_x;
if (!m_buttons_right.empty())
@ -989,14 +1018,33 @@ void FbWinFrame::reconfigureTitlebar() {
button_size, button_size);
}
renderTitlebar();
// renderTitlebar(); // gets done outside
m_titlebar.raise(); // always on top
}
void FbWinFrame::renderAll() {
m_need_render = false;
renderTitlebar();
renderHandles();
renderLabelButtons();
}
void FbWinFrame::applyAll() {
applyTitlebar();
applyHandles();
applyLabelButtons();
}
void FbWinFrame::renderTitlebar() {
if (!m_use_titlebar)
return;
if (!isVisible()) {
m_need_render = true;
return;
}
// render pixmaps
render(m_theme.titleFocusTexture(), m_title_focused_color,
m_title_focused_pm,
@ -1006,7 +1054,6 @@ void FbWinFrame::renderTitlebar() {
m_title_unfocused_pm,
m_titlebar.width(), m_titlebar.height());
render(m_theme.labelFocusTexture(), m_label_focused_color,
m_label_focused_pm,
m_label.width(), m_label.height());
@ -1016,12 +1063,12 @@ void FbWinFrame::renderTitlebar() {
m_label_unfocused_pm,
m_label.width(), m_label.height());
render(m_theme.labelActiveTexture(), m_label_active_color,
m_label_active_pm,
m_label.width(), m_label.height());
renderButtons();
}
void FbWinFrame::applyTitlebar() {
// finaly set up pixmaps for titlebar windows
// set up pixmaps for titlebar windows
Pixmap label_pm = None;
Pixmap title_pm = None;
FbTk::Color label_color;
@ -1029,6 +1076,10 @@ void FbWinFrame::renderTitlebar() {
getCurrentFocusPixmap(label_pm, title_pm,
label_color, title_color);
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
m_titlebar.setAlpha(alpha);
m_label.setAlpha(alpha);
if (label_pm != 0)
m_label.setBackgroundPixmap(label_pm);
else
@ -1039,18 +1090,7 @@ void FbWinFrame::renderTitlebar() {
else
m_titlebar.setBackgroundColor(title_color);
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
m_titlebar.setAlpha(alpha);
m_label.setAlpha(alpha);
LabelList::iterator btn_it = m_labelbuttons.begin();
LabelList::iterator btn_it_end = m_labelbuttons.end();
for (; btn_it != btn_it_end; ++btn_it) {
(*btn_it)->setAlpha(alpha);
}
renderLabelButtons();
redrawTitlebar();
applyButtons();
}
@ -1058,6 +1098,11 @@ void FbWinFrame::renderHandles() {
if (!m_use_handle)
return;
if (!isVisible()) {
m_need_render = true;
return;
}
render(m_theme.handleFocusTexture(), m_handle_focused_color,
m_handle_focused_pm,
m_handle.width(), m_handle.height());
@ -1066,20 +1111,6 @@ void FbWinFrame::renderHandles() {
m_handle_unfocused_pm,
m_handle.width(), m_handle.height());
if (m_focused) {
if (m_handle_focused_pm) {
m_handle.setBackgroundPixmap(m_handle_focused_pm);
} else {
m_handle.setBackgroundColor(m_handle_focused_color);
}
} else {
if (m_handle_unfocused_pm) {
m_handle.setBackgroundPixmap(m_handle_unfocused_pm);
} else {
m_handle.setBackgroundColor(m_handle_unfocused_color);
}
}
render(m_theme.gripFocusTexture(), m_grip_focused_color, m_grip_focused_pm,
m_grip_left.width(), m_grip_left.height());
@ -1087,7 +1118,23 @@ void FbWinFrame::renderHandles() {
m_grip_unfocused_pm,
m_grip_left.width(), m_grip_left.height());
}
void FbWinFrame::applyHandles() {
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
m_handle.setAlpha(alpha);
m_grip_left.setAlpha(alpha);
m_grip_right.setAlpha(alpha);
if (m_focused) {
if (m_handle_focused_pm) {
m_handle.setBackgroundPixmap(m_handle_focused_pm);
} else {
m_handle.setBackgroundColor(m_handle_focused_color);
}
if (m_grip_focused_pm) {
m_grip_left.setBackgroundPixmap(m_grip_focused_pm);
m_grip_right.setBackgroundPixmap(m_grip_focused_pm);
@ -1095,7 +1142,15 @@ void FbWinFrame::renderHandles() {
m_grip_left.setBackgroundColor(m_grip_focused_color);
m_grip_right.setBackgroundColor(m_grip_focused_color);
}
} else {
if (m_handle_unfocused_pm) {
m_handle.setBackgroundPixmap(m_handle_unfocused_pm);
} else {
m_handle.setBackgroundColor(m_handle_unfocused_color);
}
if (m_grip_unfocused_pm) {
m_grip_left.setBackgroundPixmap(m_grip_unfocused_pm);
m_grip_right.setBackgroundPixmap(m_grip_unfocused_pm);
@ -1105,23 +1160,17 @@ void FbWinFrame::renderHandles() {
}
}
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
m_handle.setAlpha(alpha);
m_grip_left.setAlpha(alpha);
m_grip_right.setAlpha(alpha);
m_grip_left.clear();
m_grip_left.updateTransparent();
m_grip_right.clear();
m_grip_right.updateTransparent();
m_handle.clear();
m_handle.updateTransparent();
}
void FbWinFrame::renderButtons() {
render(m_theme.buttonFocusTexture(), m_button_color, m_button_pm,
if (!isVisible()) {
m_need_render = true;
return;
}
render(m_theme.buttonFocusTexture(), m_button_color,
m_button_pm,
m_button_size, m_button_size);
render(m_theme.buttonUnfocusTexture(), m_button_unfocused_color,
@ -1131,23 +1180,15 @@ void FbWinFrame::renderButtons() {
render(m_theme.buttonPressedTexture(), m_button_pressed_color,
m_button_pressed_pm,
m_button_size, m_button_size);
}
void FbWinFrame::applyButtons() {
// setup left and right buttons
for (size_t i=0; i < m_buttons_left.size(); ++i)
setupButton(*m_buttons_left[i]);
applyButton(*m_buttons_left[i]);
for (size_t i=0; i < m_buttons_right.size(); ++i)
setupButton(*m_buttons_right[i]);
if (isVisible()) {
for_each(m_buttons_left.begin(),
m_buttons_left.end(),
mem_fun(&FbTk::Button::clear));
for_each(m_buttons_right.begin(),
m_buttons_right.end(),
mem_fun(&FbTk::Button::clear));
}
applyButton(*m_buttons_right[i]);
}
void FbWinFrame::init() {
@ -1157,13 +1198,6 @@ void FbWinFrame::init() {
m_window.setOpaque(theme().focusedAlpha());
else
m_window.setOpaque(theme().unfocusedAlpha());
} else {
// setup update timer
FbTk::RefCount<FbTk::Command> update_transp(new FbTk::SimpleCommand<FbWinFrame>(*this,
&FbWinFrame::updateTransparent));
m_update_timer.setCommand(update_transp);
m_update_timer.setTimeout(10L);
m_update_timer.fireOnce(true);
}
if (theme().handleWidth() == 0)
@ -1177,7 +1211,8 @@ void FbWinFrame::init() {
// clear pixmaps
m_title_focused_pm = m_title_unfocused_pm = 0;
m_label_focused_pm = m_label_unfocused_pm = m_label_active_pm = 0;
m_label_focused_pm = m_label_unfocused_pm = 0;
m_labelbutton_focused_pm = m_labelbutton_unfocused_pm = m_labelbutton_active_pm = 0;
m_handle_focused_pm = m_handle_unfocused_pm = 0;
m_button_pm = m_button_unfocused_pm = m_button_pressed_pm = 0;
m_grip_unfocused_pm = m_grip_focused_pm = 0;
@ -1200,27 +1235,28 @@ void FbWinFrame::init() {
/**
Setups upp background, pressed pixmap/color of the button to current theme
*/
void FbWinFrame::setupButton(FbTk::Button &btn) {
void FbWinFrame::applyButton(FbTk::Button &btn) {
if (m_button_pressed_pm)
btn.setPressedPixmap(m_button_pressed_pm);
//!! TODO button pressed color
else
btn.setPressedColor(m_button_pressed_color);
if (focused()) { // focused
btn.setAlpha(theme().focusedAlpha());
btn.setGC(m_theme.buttonPicFocusGC());
if (m_button_pm)
btn.setBackgroundPixmap(m_button_pm);
else
btn.setBackgroundColor(m_button_color);
btn.setAlpha(theme().focusedAlpha());
} else { // unfocused
btn.setAlpha(theme().unfocusedAlpha());
btn.setGC(m_theme.buttonPicUnfocusGC());
if (m_button_unfocused_pm)
btn.setBackgroundPixmap(m_button_unfocused_pm);
else
btn.setBackgroundColor(m_button_unfocused_color);
btn.setAlpha(theme().unfocusedAlpha());
}
}
@ -1244,10 +1280,10 @@ void FbWinFrame::render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm,
void FbWinFrame::getCurrentFocusPixmap(Pixmap &label_pm, Pixmap &title_pm,
FbTk::Color &label_color, FbTk::Color &title_color) {
if (m_focused) {
if (m_label_focused_pm != 0)
label_pm = m_label_focused_pm;
if (m_labelbutton_focused_pm != 0)
label_pm = m_labelbutton_focused_pm;
else
label_color = m_label_focused_color;
label_color = m_labelbutton_focused_color;
if (m_title_focused_pm != 0)
title_pm = m_title_focused_pm;
@ -1266,10 +1302,10 @@ void FbWinFrame::getActiveLabelPixmap(Pixmap &label_pm, Pixmap &title_pm,
FbTk::Color &label_color,
FbTk::Color &title_color) {
if (m_label_active_pm != 0)
label_pm = m_label_active_pm;
if (m_labelbutton_active_pm != 0)
label_pm = m_labelbutton_active_pm;
else
label_color = m_label_active_color;
label_color = m_labelbutton_active_color;
if (m_title_unfocused_pm != 0)
title_pm = m_title_unfocused_pm;
@ -1278,36 +1314,39 @@ void FbWinFrame::getActiveLabelPixmap(Pixmap &label_pm, Pixmap &title_pm,
}
void FbWinFrame::renderLabelButtons() {
if (!isVisible()) {
m_need_render = true;
return;
}
Pixmap label_pm = 0;
Pixmap not_used_pm = 0;
FbTk::Color label_color;
FbTk::Color not_used_color;
getCurrentFocusPixmap(label_pm, not_used_pm,
label_color, not_used_color);
render(m_theme.labelFocusTexture(), m_labelbutton_focused_color,
m_labelbutton_focused_pm,
m_label.width(), m_label.height());
render(m_theme.labelUnfocusTexture(), m_labelbutton_unfocused_color,
m_labelbutton_unfocused_pm,
m_label.width(), m_label.height());
render(m_theme.labelActiveTexture(), m_labelbutton_active_color,
m_labelbutton_active_pm,
m_label.width(), m_label.height());
}
void FbWinFrame::applyLabelButtons() {
LabelList::iterator btn_it = m_labelbuttons.begin();
LabelList::iterator btn_it_end = m_labelbuttons.end();
for (; btn_it != btn_it_end; ++btn_it) {
if (*btn_it == m_current_label) {
if (m_focused)
renderButtonFocus(**btn_it);
applyFocusLabel(**btn_it);
else
renderButtonActive(**btn_it);
applyActiveLabel(**btn_it);
} else
renderButtonUnfocus(**btn_it);
applyUnfocusLabel(**btn_it);
}
if (m_current_label != 0) {
if (label_pm) {
m_current_label->setBackgroundPixmap(label_pm);
} else
m_current_label->setBackgroundColor(label_color);
}
}
void FbWinFrame::setBorderWidth(unsigned int border_width) {
@ -1338,50 +1377,48 @@ void FbWinFrame::setBorderWidth(unsigned int border_width) {
resize(width(), height() + bw_changes);
}
void FbWinFrame::renderButtonFocus(FbTk::TextButton &button) {
void FbWinFrame::applyFocusLabel(FbTk::TextButton &button) {
button.setGC(theme().labelTextFocusGC());
button.setJustify(theme().justify());
button.setBorderWidth(1);
button.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (m_label_focused_pm != 0) {
// already set
if (button.backgroundPixmap() != m_label_focused_pm)
button.setBackgroundPixmap(m_label_focused_pm);
if (m_labelbutton_focused_pm != 0) {
button.setBackgroundPixmap(m_labelbutton_focused_pm);
} else
button.setBackgroundColor(m_label_focused_color);
button.setBackgroundColor(m_labelbutton_focused_color);
}
void FbWinFrame::renderButtonActive(FbTk::TextButton &button) {
void FbWinFrame::applyActiveLabel(FbTk::TextButton &button) {
button.setGC(theme().labelTextActiveGC());
button.setJustify(theme().justify());
button.setBorderWidth(1);
button.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (m_label_active_pm != 0) {
// already set
if (button.backgroundPixmap() != m_label_active_pm)
button.setBackgroundPixmap(m_label_active_pm);
if (m_labelbutton_active_pm != 0) {
button.setBackgroundPixmap(m_labelbutton_active_pm);
} else
button.setBackgroundColor(m_label_active_color);
button.setBackgroundColor(m_labelbutton_active_color);
}
void FbWinFrame::renderButtonUnfocus(FbTk::TextButton &button) {
void FbWinFrame::applyUnfocusLabel(FbTk::TextButton &button) {
button.setGC(theme().labelTextUnfocusGC());
button.setJustify(theme().justify());
button.setBorderWidth(1);
button.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (m_label_unfocused_pm != 0) {
// already set
if (button.backgroundPixmap() != m_label_unfocused_pm)
button.setBackgroundPixmap(m_label_unfocused_pm);
if (m_labelbutton_unfocused_pm != 0) {
button.setBackgroundPixmap(m_labelbutton_unfocused_pm);
} else
button.setBackgroundColor(m_label_unfocused_color);
button.setBackgroundColor(m_labelbutton_unfocused_color);
}
namespace {
class IgnoreEvent {
public:
@ -1403,58 +1440,6 @@ private:
};
}
void FbWinFrame::updateTransparent() {
if (FbTk::Transparent::haveComposite())
return;
m_label.clear();
m_label.updateTransparent();
m_titlebar.clear();
m_titlebar.updateTransparent();
for_each(m_labelbuttons.begin(),
m_labelbuttons.end(),
mem_fun(&FbTk::Button::clear));
for_each(m_buttons_left.begin(),
m_buttons_left.end(),
mem_fun(&FbTk::Button::clear));
for_each(m_buttons_right.begin(),
m_buttons_right.end(),
mem_fun(&FbTk::Button::clear));
// ignore exposure events, since we already cleared
// and redrawn the windows
IgnoreEvent ign(ExposureMask);
// base windows
ign(m_label.window());
ign(m_titlebar.window());
// labels
for_each(m_labelbuttons.begin(),
m_labelbuttons.end(),
FbTk::Compose(ign, mem_fun(&FbTk::Button::window)));
// win buttons
for_each(m_buttons_right.begin(),
m_buttons_right.end(),
FbTk::Compose(ign, mem_fun(&FbTk::Button::window)));
for_each(m_buttons_left.begin(),
m_buttons_left.end(),
FbTk::Compose(ign, mem_fun(&FbTk::Button::window)));
m_grip_left.clear();
m_grip_left.updateTransparent();
ign(m_grip_left.window());
m_grip_right.clear();
m_grip_right.updateTransparent();
ign(m_grip_right.window());
m_handle.clear();
m_handle.updateTransparent();
ign(m_handle.window());
}
// this function translates its arguments according to win_gravity
// if win_gravity is negative, it does an inverse translation
// This function should be used when a window is mapped/unmapped/pos configured

View file

@ -30,7 +30,6 @@
#include "FbTk/Observer.hh"
#include "FbTk/Color.hh"
#include "FbTk/FbPixmap.hh"
#include "FbTk/Timer.hh"
#include <vector>
#include <list>
@ -87,6 +86,11 @@ public:
// can elect to ignore move or resize (mainly for use of move/resize individual functions
void moveResize(int x, int y, unsigned int width, unsigned int height, bool move = true, bool resize = true, int win_gravity=ForgetGravity);
/// some outside move/resize happened, and we need to notify all of our windows
/// in case of transparency
void notifyMoved(bool clear);
void clearAll();
/// set focus/unfocus style
void setFocus(bool newvalue);
void setDoubleClickTime(unsigned int time);
@ -151,8 +155,6 @@ public:
void reconfigure();
void setUseShape(bool value);
void setUpdateDelayTime(long t) { m_update_timer.setTimeout(t); }
/**
@name accessors
*/
@ -199,31 +201,43 @@ private:
@name render helper functions
*/
//@{
void renderAll();
void renderTitlebar();
void renderHandles();
void renderButtons();
// focused => has focus
void renderButtonFocus(FbTk::TextButton &button);
// unfocus => has no focus, label not the active one
void renderButtonUnfocus(FbTk::TextButton &button);
// active => doesn't have keybaord focus, but is the active tab
void renderButtonActive(FbTk::TextButton &button);
void renderLabel();
void renderLabelButtons();
void renderButtons(); // subset of renderTitlebar - don't call directly
/// renders to pixmap or sets color
void render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm,
unsigned int width, unsigned int height);
//@}
/**
@name apply pixmaps depending on focus
*/
//@{
void applyAll();
void applyTitlebar();
void applyHandles();
void applyLabelButtons();
void applyFocusLabel(FbTk::TextButton &button);
void applyUnfocusLabel(FbTk::TextButton &button);
void applyActiveLabel(FbTk::TextButton &button);
void applyButtons(); // only called within applyTitlebar
void getActiveLabelPixmap(Pixmap &label_pm, Pixmap &title_pm,
FbTk::Color &label_color, FbTk::Color &title_color);
void getCurrentFocusPixmap(Pixmap &label_pm, Pixmap &title_pm,
FbTk::Color &label_color, FbTk::Color &title_color);
void renderLabelButtons();
/// initiate inserted button for current theme
void applyButton(FbTk::Button &btn);
//@}
/// initiate some commont variables
void init();
/// initiate inserted buttons for current theme
void setupButton(FbTk::Button &btn);
void updateTransparent();
FbWinFrameTheme &m_theme; ///< theme to be used
FbTk::ImageControl &m_imagectrl; ///< Image control for rendering
@ -265,8 +279,13 @@ private:
FbTk::Color m_label_focused_color; ///< color for focused label
Pixmap m_label_unfocused_pm; ///< pixmap for unfocused label
FbTk::Color m_label_unfocused_color; ///< color for unfocued label
Pixmap m_label_active_pm; ///< pixmap for active label
FbTk::Color m_label_active_color; ///< color for active label
Pixmap m_labelbutton_focused_pm; ///< pixmap for focused label
FbTk::Color m_labelbutton_focused_color; ///< color for focused label
Pixmap m_labelbutton_unfocused_pm; ///< pixmap for unfocused label
FbTk::Color m_labelbutton_unfocused_color; ///< color for unfocued label
Pixmap m_labelbutton_active_pm; ///< pixmap for active label
FbTk::Color m_labelbutton_active_color; ///< color for active label
FbTk::Color m_handle_focused_color, m_handle_unfocused_color;
Pixmap m_handle_focused_pm, m_handle_unfocused_pm;
@ -285,6 +304,7 @@ private:
FbTk::Color m_grip_unfocused_color; ///< unfocused color for grip if no pixmap is given
//@}
bool m_need_render;
int m_button_size; ///< size for all titlebar buttons
unsigned int m_width_before_shade, ///< width before shade, so we can restore it when we unshade
m_height_before_shade; ///< height before shade, so we can restore it when we unshade
@ -309,7 +329,6 @@ private:
ThemeListener m_themelistener;
std::auto_ptr<Shape> m_shape;
bool m_disable_shape;
FbTk::Timer m_update_timer;
};
#endif // FBWINFRAME_HH

View file

@ -79,10 +79,8 @@ unsigned int GenericTool::borderWidth() const {
void GenericTool::renderTheme(unsigned char alpha) {
m_window->setAlpha(alpha);
m_window->clear();
m_window->updateTransparent();
}
void GenericTool::update(FbTk::Subject *subj) {
m_window->clear();
m_window->updateTransparent();
}

View file

@ -1084,7 +1084,6 @@ void Slit::exposeEvent(XExposeEvent &ev) {
// we don't need to clear the entire window
// just the are that gets exposed
frame.window.clearArea(ev.x, ev.y, ev.width, ev.height);
frame.window.updateTransparent(ev.x, ev.y, ev.width, ev.height);
}
void Slit::update(FbTk::Subject *subj) {
@ -1093,7 +1092,6 @@ void Slit::update(FbTk::Subject *subj) {
void Slit::clearWindow() {
frame.window.clear();
frame.window.updateTransparent();
}
void Slit::toggleHidden() {

View file

@ -48,15 +48,12 @@ public:
// so that the last toggled item gets redrawn as
// not toggled.
if (ev.window == frameWindow()) {
renderTransp(0, 0, width(), frameWindow().height());
frameWindow().clear();
for (size_t i = 0; i < numberOfItems(); ++i) {
drawItem(i, // index
true, // clear
false); // render transparent
drawItem(i, // index
false); // clear
}
frameWindow().clear();
}
}

View file

@ -462,7 +462,6 @@ void Toolbar::reconfigure() {
frame.window.setAlpha(alpha());
}
frame.window.clear();
frame.window.updateTransparent();
if (theme().shape() && m_shape.get())
m_shape->update();
@ -563,8 +562,6 @@ void Toolbar::exposeEvent(XExposeEvent &ee) {
if (ee.window == frame.window) {
frame.window.clearArea(ee.x, ee.y,
ee.width, ee.height);
frame.window.updateTransparent(ee.x, ee.y,
ee.width, ee.height);
}
}
@ -1028,8 +1025,6 @@ void Toolbar::rearrangeItems() {
// unlock
m_resize_lock = false;
frame.window.clear();
frame.window.updateTransparent();
}
void Toolbar::deleteItems() {
@ -1047,7 +1042,6 @@ void Toolbar::updateAlpha() {
} else {
frame.window.setAlpha(*m_rc_alpha);
frame.window.clear();
frame.window.updateTransparent();
ItemList::iterator item_it = m_item_list.begin();
ItemList::iterator item_it_end = m_item_list.end();

View file

@ -25,6 +25,7 @@
#include "App.hh"
#include "Window.hh"
#include "WinButtonTheme.hh"
#include "FbTk/Color.hh"
WinButton::WinButton(const FluxboxWindow &listen_to,
WinButtonTheme &theme,
@ -32,261 +33,206 @@ WinButton::WinButton(const FluxboxWindow &listen_to,
int x, int y,
unsigned int width, unsigned int height):
FbTk::Button(parent, x, y, width, height),
m_type(buttontype), m_listen_to(listen_to), m_theme(theme) {
m_type(buttontype), m_listen_to(listen_to), m_theme(theme),
overrode_bg(false), overrode_pressed(false) {
theme.reconfigSig().attach(this);
}
void WinButton::exposeEvent(XExposeEvent &event) {
FbTk::Button::exposeEvent(event);
drawType(false, false);
drawType();
}
void WinButton::buttonReleaseEvent(XButtonEvent &event) {
FbTk::Button::buttonReleaseEvent(event);
}
// when someone else tries to set the background, we may override it
void WinButton::setBackgroundPixmap(Pixmap pm) {
Pixmap my_pm = getBackgroundPixmap();
if (my_pm != 0) {
overrode_bg = true;
pm = my_pm;
} else {
overrode_bg = false;
}
FbTk::Button::setBackgroundPixmap(pm);
}
void WinButton::setBackgroundColor(const FbTk::Color &color) {
Pixmap my_pm = getBackgroundPixmap();
if (my_pm != 0) {
overrode_bg = true;
FbTk::Button::setBackgroundPixmap(my_pm);
} else {
overrode_bg = false;
FbTk::Button::setBackgroundColor(color);
}
}
void WinButton::setPressedPixmap(Pixmap pm) {
Pixmap my_pm = getPressedPixmap();
if (my_pm != 0) {
overrode_pressed = true;
pm = my_pm;
} else {
overrode_pressed = false;
}
FbTk::Button::setBackgroundPixmap(pm);
}
void WinButton::setPressedColor(const FbTk::Color &color) {
Pixmap my_pm = getPressedPixmap();
if (my_pm != 0) {
overrode_pressed = true;
FbTk::Button::setPressedPixmap(my_pm);
} else {
overrode_pressed = false;
FbTk::Button::setPressedColor(color);
}
}
Pixmap WinButton::getBackgroundPixmap() const {
bool focused = m_listen_to.isFocused();
switch(m_type) {
case MAXIMIZE:
if (focused)
return m_theme.maximizePixmap().pixmap().drawable();
else
return m_theme.maximizeUnfocusPixmap().pixmap().drawable();
break;
case MINIMIZE:
if (focused)
return m_theme.iconifyPixmap().pixmap().drawable();
else
return m_theme.iconifyUnfocusPixmap().pixmap().drawable();
break;
case STICK: {
bool stuck = m_listen_to.isStuck();
if (stuck) {
if (focused)
return m_theme.stuckPixmap().pixmap().drawable();
else
return m_theme.stuckUnfocusPixmap().pixmap().drawable();
} else {
if (focused)
return m_theme.stickPixmap().pixmap().drawable();
else
return m_theme.stickUnfocusPixmap().pixmap().drawable();
}
}
break;
case CLOSE:
if (focused)
return m_theme.closePixmap().pixmap().drawable();
else
return m_theme.closeUnfocusPixmap().pixmap().drawable();
break;
case SHADE:
if (focused)
return m_theme.shadePixmap().pixmap().drawable();
else
return m_theme.shadeUnfocusPixmap().pixmap().drawable();
break;
}
return None;
}
Pixmap WinButton::getPressedPixmap() const {
switch(m_type) {
case MAXIMIZE:
return m_theme.maximizePressedPixmap().pixmap().drawable();
case MINIMIZE:
return m_theme.iconifyPressedPixmap().pixmap().drawable();
case STICK:
return m_theme.stickPressedPixmap().pixmap().drawable();
case CLOSE:
return m_theme.closePressedPixmap().pixmap().drawable();
case SHADE:
return m_theme.shadePressedPixmap().pixmap().drawable();
}
return None;
}
// clear is used to force this to clear the window (e.g. called from clear())
void WinButton::drawType(bool clear, bool no_trans) {
void WinButton::drawType() {
bool used = false;
// if it's odd and we're centring, we need to add one
int oddW = width()%2;
int oddH = height()%2;
bool is_pressed = pressed();
if (is_pressed && overrode_pressed)
return;
if (!is_pressed && overrode_bg)
return;
if (gc() == 0)
return;
// otherwise draw old style imagery
switch (m_type) {
case MAXIMIZE:
if (pressed() && m_theme.maximizePressedPixmap().pixmap().drawable() != 0) {
FbTk::FbWindow::setBackgroundPixmap(m_theme.
maximizePressedPixmap().
pixmap().drawable());
used = true;
} else {
// check focus
if (!m_listen_to.isFocused()) {
if (m_theme.maximizeUnfocusPixmap().pixmap().drawable() != 0) {
// not focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
maximizeUnfocusPixmap().
pixmap().drawable());
used = true;
}
} else if (m_theme.maximizePixmap().pixmap().drawable() != 0) {
FbTk::FbWindow::setBackgroundPixmap(m_theme.
maximizePixmap().
pixmap().drawable());
used = true;
}
}
if (used || clear)
FbTk::FbWindow::clear();
// if no pixmap was used, use old style
if (!used) {
if (gc() == 0) // must have valid graphic context
return;
if (gc() == 0) // must have valid graphic context
return;
drawRectangle(gc(),
2, 2, width() - 5, height() - 5);
drawLine(gc(),
2, 3, width() - 3, 3);
}
drawRectangle(gc(),
2, 2, width() - 5, height() - 5);
drawLine(gc(),
2, 3, width() - 3, 3);
break;
case MINIMIZE:
if (pressed() && m_theme.iconifyPressedPixmap().pixmap().drawable() != 0) {
FbTk::FbWindow::setBackgroundPixmap(m_theme.
iconifyPressedPixmap().
pixmap().drawable());
used = true;
} else {
if (m_theme.iconifyPixmap().pixmap().drawable()){
// check focus
if (!m_listen_to.isFocused()) {
if (m_theme.iconifyUnfocusPixmap().pixmap().drawable() != 0) {
// not focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
iconifyUnfocusPixmap().
pixmap().drawable());
used = true;
}
} else if (m_theme.iconifyPixmap().pixmap().drawable() != 0) {
FbTk::FbWindow::setBackgroundPixmap(m_theme.
iconifyPixmap().
pixmap().drawable());
used = true;
}
}
}
if (used || clear) {
FbTk::FbWindow::clear();
}
if (!used && gc() != 0) { // must have valid graphic context
FbTk::FbWindow::drawRectangle(gc(),
2, height() - 5, width() - 5, 2);
}
FbTk::FbWindow::drawRectangle(gc(),
2, height() - 5, width() - 5, 2);
break;
case STICK:
if (m_listen_to.isStuck() && !pressed()) {
if ( m_theme.stuckPixmap().pixmap().drawable() &&
! pressed()) { // we're using the same pixmap for pressed as in not stuck
// check focus
if (!m_listen_to.isFocused()) {
if ( m_theme.stuckUnfocusPixmap().pixmap().drawable() != 0) {
// not focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
stuckUnfocusPixmap().
pixmap().drawable());
used = true;
}
} else if (m_theme.stuckPixmap().pixmap().drawable() != 0) {
// focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
stuckPixmap().
pixmap().drawable());
used = true;
}
}
} else { // not stuck and pressed
if (pressed()) {
if (m_theme.stickPressedPixmap().pixmap().drawable() != 0) {
FbTk::FbWindow::setBackgroundPixmap(m_theme.
stickPressedPixmap().
pixmap().drawable());
used = true;
}
} else { // not pressed
// check focus
if (!m_listen_to.isFocused()) {
if (m_theme.stickUnfocusPixmap().pixmap().drawable() != 0) {
// not focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
stickUnfocusPixmap().
pixmap().drawable());
used = true;
}
} else if (m_theme.stickPixmap().pixmap().drawable()) { // focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
stickPixmap().
pixmap().drawable());
used = true;
}
}
}
if (used || clear)
FbTk::FbWindow::clear();
if (!used && gc() != 0) {
// width/4 != width/2, so we use /4*2 so that it's properly centred
if (m_listen_to.isStuck()) {
fillRectangle(gc(),
width()/2 - width()/4, height()/2 - height()/4,
width()/4*2 + oddW, height()/4*2 + oddH);
} else {
fillRectangle(gc(),
width()/2 - width()/10, height()/2 - height()/10,
width()/10*2 + oddW, height()/10*2 + oddH);
}
// width/4 != width/2, so we use /4*2 so that it's properly centred
if (m_listen_to.isStuck()) {
fillRectangle(gc(),
width()/2 - width()/4, height()/2 - height()/4,
width()/4*2 + oddW, height()/4*2 + oddH);
} else {
fillRectangle(gc(),
width()/2 - width()/10, height()/2 - height()/10,
width()/10*2 + oddW, height()/10*2 + oddH);
}
break;
case CLOSE:
if (pressed()) {
if (m_theme.closePressedPixmap().pixmap().drawable()) {
FbTk::FbWindow::setBackgroundPixmap(m_theme.
closePressedPixmap().
pixmap().drawable());
used = true;
}
} else { // not pressed
// check focus
if (!m_listen_to.isFocused()) {
if (m_theme.closeUnfocusPixmap().pixmap().drawable() != 0) {
// not focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
closeUnfocusPixmap().
pixmap().drawable());
used = true;
}
} else if (m_theme.closePixmap().pixmap().drawable() != 0) { // focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
closePixmap().
pixmap().drawable());
used = true;
}
}
drawLine(gc(),
2, 2,
width() - 3, height() - 3);
// I can't figure out why this second one needs a y offset of 1?????
// but it does - at least on my box:
// XFree86 Version 4.2.1.1 (Debian 4.2.1-12.1 20031003005825)
// (protocol Version 11, revision 0, vendor release 6600)
// But not on mine? It's wonky. Put back to the same coords.
// was width-2, 1 in the second drawline
// Perhaps some X versions don't draw the endpoint?
// Mine:
// XFree86 Version 4.3.0.1 (Debian 4.3.0.dfsg.1-1 20040428170728)
// (X Protocol Version 11, Revision 0, Release 6.6)
if (used || clear)
FbTk::FbWindow::clear();
if (!used && gc() != 0) { // must have valid graphic context
drawLine(gc(),
2, 2,
width() - 3, height() - 3);
// I can't figure out why this second one needs a y offset of 1?????
// but it does - at least on my box:
// XFree86 Version 4.2.1.1 (Debian 4.2.1-12.1 20031003005825)
// (protocol Version 11, revision 0, vendor release 6600)
// But not on mine? It's wonky. Put back to the same coords.
// was width-2, 1 in the second drawline
// Perhaps some X versions don't draw the endpoint?
// Mine:
// XFree86 Version 4.3.0.1 (Debian 4.3.0.dfsg.1-1 20040428170728)
// (X Protocol Version 11, Revision 0, Release 6.6)
drawLine(gc(),
2, height() - 3,
width() - 3, 2);
}
drawLine(gc(),
2, height() - 3,
width() - 3, 2);
break;
case SHADE:
if (pressed()) {
if (m_theme.shadePressedPixmap().pixmap().drawable()) {
FbTk::FbWindow::setBackgroundPixmap(m_theme.
shadePressedPixmap().
pixmap().drawable());
used = true;
}
} else { // not pressed
// check focus
if (!m_listen_to.isFocused()) {
if ( m_theme.shadeUnfocusPixmap().pixmap().drawable() != 0) {
// not focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
shadeUnfocusPixmap().
pixmap().drawable());
used = true;
}
} else if (m_theme.shadePixmap().pixmap().drawable() != 0) { // focused
FbTk::FbWindow::setBackgroundPixmap(m_theme.
shadePixmap().
pixmap().drawable());
used = true;
}
}
if (used || clear)
FbTk::FbWindow::clear();
// no cute image defined
break;
}
// if ((used || clear) && !no_trans)
updateTransparent();
}
void WinButton::clear() {
drawType(true, true);
FbTk::Button::clear();
drawType();
}
void WinButton::update(FbTk::Subject *subj) {

View file

@ -27,6 +27,10 @@
class FluxboxWindow;
class WinButtonTheme;
namespace FbTk{
class Color;
}
/// draws and handles basic window button graphic
class WinButton:public FbTk::Button, public FbTk::Observer {
public:
@ -39,13 +43,20 @@ public:
/// override for drawing
void exposeEvent(XExposeEvent &event);
void buttonReleaseEvent(XButtonEvent &event);
void setBackgroundPixmap(Pixmap pm);
void setPressedPixmap(Pixmap pm);
void setBackgroundColor(const FbTk::Color &color);
void setPressedColor(const FbTk::Color &color);
Pixmap getBackgroundPixmap() const;
Pixmap getPressedPixmap() const;
/// override for redrawing
void clear();
void update(FbTk::Subject *subj);
private:
void drawType(bool clear, bool no_trans); // don't update transparency (eg in clear)
void drawType();
Type m_type; ///< the button type
const FluxboxWindow &m_listen_to;
WinButtonTheme &m_theme;
bool overrode_bg, overrode_pressed;
};

View file

@ -358,7 +358,7 @@ void WinClient::updateIconTitle() {
void WinClient::saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs) {
changeProperty(FbAtoms::instance()->getFluxboxAttributesAtom(),
PropModeReplace, XA_CARDINAL, 32,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&blackbox_attribs,
FluxboxWindow::PropBlackboxAttributesElements
);

View file

@ -1194,7 +1194,6 @@ void FluxboxWindow::reconfigure() {
grabButtons();
frame().setDoubleClickTime(Fluxbox::instance()->getDoubleClickInterval());
frame().setUpdateDelayTime(Fluxbox::instance()->getUpdateDelayTime());
frame().reconfigure();
@ -1210,7 +1209,7 @@ void FluxboxWindow::updateTitleFromClient(WinClient &client) {
if (m_labelbuttons[&client]->text() != client.title()) {
m_labelbuttons[&client]->setText(client.title());
m_labelbuttons[&client]->clear(); // redraw text
m_labelbuttons[&client]->updateTransparent();
//m_labelbuttons[&client]->updateTransparent();
}
}
@ -1341,8 +1340,9 @@ void FluxboxWindow::resize(unsigned int width, unsigned int height) {
moveResize(frame().x(), frame().y(), width, height);
}
// send_event is just an override
void FluxboxWindow::moveResize(int new_x, int new_y,
unsigned int new_width, unsigned int new_height, int gravity) {
unsigned int new_width, unsigned int new_height, int gravity, bool send_event) {
// magic to detect if moved during initialisation
if (!isInitialized())
@ -1352,7 +1352,7 @@ void FluxboxWindow::moveResize(int new_x, int new_y,
frame().gravityTranslate(new_x, new_y, gravity, false);
}
bool send_event = (frame().x() != new_x || frame().y() != new_y);
send_event = send_event || (frame().x() != new_x || frame().y() != new_y);
if (new_width != frame().width() || new_height != frame().height()) {
if ((((signed) frame().width()) + new_x) < 0)
@ -1368,7 +1368,6 @@ void FluxboxWindow::moveResize(int new_x, int new_y,
frame().moveResize(new_x, new_y, new_width, new_height);
setFocusFlag(focused);
shaded = false;
send_event = true;
} else if (send_event)
@ -2848,7 +2847,9 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
m_last_move_x = dx;
m_last_move_y = dy;
} else {
moveResize(dx, dy, frame().width(), frame().height());
//moveResize(dx, dy, frame().width(), frame().height());
// need to move the base window without interfering with transparency
frame().window().moveResize(dx, dy, frame().width(), frame().height());
}
screen().showPosition(dx, dy);
@ -3216,7 +3217,6 @@ void FluxboxWindow::stopMoving(bool interrupted) {
fluxbox->maskWindowEvents(0, 0);
if (! screen().doOpaqueMove()) {
parent().drawRectangle(screen().rootTheme().opGC(),
m_last_move_x, m_last_move_y,
@ -3231,8 +3231,8 @@ void FluxboxWindow::stopMoving(bool interrupted) {
}
fluxbox->ungrab();
} else if (!interrupted) {
moveResize(frame().x(), frame().y(), frame().width(), frame().height());
sendConfigureNotify();
moveResize(frame().x(), frame().y(), frame().width(), frame().height(), ForgetGravity, true);
frame().notifyMoved(true);
}

View file

@ -232,7 +232,7 @@ public:
/// resize frame to width, height
void resize(unsigned int width, unsigned int height);
/// move and resize frame to pox x,y and size width, height
void moveResize(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity);
void moveResize(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity, bool send_event = false);
/// move to pos x,y and resize client window to size width, height
void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity);
void setWorkspace(int n);

View file

@ -200,7 +200,6 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
"session.colorsPerChannel", "Session.ColorsPerChannel"),
m_rc_numlayers(m_resourcemanager, 13, "session.numLayers", "Session.NumLayers"),
m_rc_double_click_interval(m_resourcemanager, 250, "session.doubleClickInterval", "Session.DoubleClickInterval"),
m_rc_update_delay_time(m_resourcemanager, 0, "session.updateDelayTime", "Session.UpdateDelayTime"),
m_rc_stylefile(m_resourcemanager, DEFAULTSTYLE, "session.styleFile", "Session.StyleFile"),
m_rc_menufile(m_resourcemanager, DEFAULTMENU, "session.menuFile", "Session.MenuFile"),
m_rc_keyfile(m_resourcemanager, DEFAULTKEYSFILE, "session.keyFile", "Session.KeyFile"),
@ -278,7 +277,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;
@ -377,8 +376,7 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
// setup theme manager to have our style file ready to be scanned
FbTk::ThemeManager::instance().load(FbTk::StringUtil::expandFilename(getStyleFilename()));
XSynchronize(disp, False);
//XSynchronize(disp, True);
//XSynchronize(disp, False);
sync(false);
m_reconfigure_wait = m_reread_menu_wait = false;
@ -1854,7 +1852,6 @@ void Fluxbox::setFocusedWindow(WinClient *client) {
m_focused_window = 0;
if (screen != 0) {
screen->updateNetizenWindowFocus();
for (AtomHandlerContainerIt it= m_atomhandler.begin();
@ -1871,7 +1868,6 @@ void Fluxbox::setFocusedWindow(WinClient *client) {
it != m_atomhandler.end(); it++)
(*it).first->updateFocusedWindow(*old_screen, 0);
}
}
/**

View file

@ -102,7 +102,6 @@ public:
BScreen *searchScreen(Window w);
inline unsigned int getDoubleClickInterval() const { return *m_rc_double_click_interval; }
inline unsigned int getUpdateDelayTime() const { return *m_rc_update_delay_time; }
inline Time getLastTime() const { return m_last_time; }
AtomHandler *getAtomHandler(const std::string &name);
@ -260,7 +259,7 @@ private:
FbTk::Resource<bool> m_rc_tabs, m_rc_ignoreborder;
FbTk::Resource<bool> m_rc_pseudotrans;
FbTk::Resource<int> m_rc_colors_per_channel, m_rc_numlayers,
m_rc_double_click_interval, m_rc_update_delay_time,
m_rc_double_click_interval,
m_rc_tabs_padding,
m_rc_focused_tab_min_width;
FbTk::Resource<std::string> m_rc_stylefile,