all repos — fluxbox @ 88c66f0687d2a9e2018f22407b2587dc4d87d012

custom fork of the fluxbox windowmanager

Big changes to how transparency works
Consequently rearrange lots of rendering ops, and strip calls to 
updateTransparent
simonb simonb
commit

88c66f0687d2a9e2018f22407b2587dc4d87d012

parent

6cf66c66554a20a1c98eddf26af9e35b7c90cbd5

M ChangeLogChangeLog

@@ -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:
M src/ArrowButton.ccsrc/ArrowButton.cc

@@ -52,13 +52,11 @@ }

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(); }
M src/ButtonTool.ccsrc/ButtonTool.cc

@@ -87,6 +87,5 @@ if (old_pm)

m_image_ctrl.removeImage(old_pm); btn.clear(); - btn.updateTransparent(); }
M src/Container.ccsrc/Container.cc

@@ -132,7 +132,6 @@ m_selected = 0;

m_item_list.clear(); if (!m_update_lock) { clear(); - updateTransparent(); } }

@@ -176,7 +175,6 @@

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); } }
M src/FbTk/Button.ccsrc/FbTk/Button.cc

@@ -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 @@ //set on click command for the 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 @@ bool update = false;

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::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
M src/FbTk/Button.hhsrc/FbTk/Button.hh

@@ -48,11 +48,9 @@

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

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
M src/FbTk/FbPixmap.ccsrc/FbTk/FbPixmap.cc

@@ -311,13 +311,12 @@ for (prop = 0; prop_ids[prop]; prop++) {

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;
M src/FbTk/FbWindow.ccsrc/FbTk/FbWindow.cc

@@ -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 @@ m_x(the_copy.x()), m_y(the_copy.y()),

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 @@ FbDrawable(),

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 @@ int depth, int class_type):

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 @@ m_width(1), m_height(1),

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 @@ XDestroyWindow(display(), m_window);

} } +void FbWindow::setBackgroundColor(const FbTk::Color &bg_color) { + 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; + } -void FbWindow::setBackgroundColor(const FbTk::Color &bg_color) { - XSetWindowBackground(display(), m_window, bg_color.pixel()); + 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 @@

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,13 +271,8 @@ Pixmap root = FbPixmap::getRootPixmap(screenNumber());

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

@@ -414,9 +497,11 @@ changeProperty(m_alphaatom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1l);

#endif // HAVE_XRENDER } +/* void FbWindow::setBufferPixmap(Pixmap pm) { - m_buffer_pm = pm; + m_lastbg_pm = pm; } +*/ void FbWindow::updateGeometry() { if (m_window == 0)
M src/FbTk/FbWindow.hhsrc/FbTk/FbWindow.hh

@@ -93,24 +93,40 @@ virtual void hide();

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();

@@ -138,8 +154,6 @@ unsigned char *data,

int nelements); void deleteProperty(Atom property); - - void setBufferPixmap(Pixmap pm); std::string textProperty(Atom property) const;

@@ -184,6 +198,9 @@ bool override_redirect,

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 @@ unsigned int m_border_width; ///< border size

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);
M src/FbTk/Menu.ccsrc/FbTk/Menu.cc

@@ -86,7 +86,6 @@ m_screen_height(DisplayHeight(FbTk::App::instance()->display(), tm.screenNum())),

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 @@ // we need to do this explicitly on the menu.window

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

m_active_index = m_which_press; - drawItem(m_which_press, - true, // clear - true); // transp + drawItem(m_which_press, true); // clear }

@@ -325,9 +320,7 @@ // we need to do this explicitly on the menu.window

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

m_active_index = m_which_press; - drawItem(m_which_press, - true, // clear - true); // transp + drawItem(m_which_press, true); // clear }

@@ -379,9 +370,7 @@ if (submenu)

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 @@ setTitleVisibility(true);

} 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;

@@ -432,6 +424,9 @@ } else {

menu.sublevels = 0; 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 @@ tmp = menu.title_pixmap;

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 @@ const FbTk::Texture &frame_tex = theme().frameTexture();

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 @@ menu.frame.moveResize(0, ((m_title_vis) ? menu.title.y() + menu.title.height() +

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::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::clearWindow() { - redrawTitle(); - - if (alpha() < 255) { - renderTransp(0, 0, - menu.frame.width(), menu.frame.height()); - updateMenu(); - } + redrawTitle(); + redrawFrame(); +} - menu.title.clear(); +void Menu::redrawFrame() { menu.frame.clear(); + for (unsigned int i = 0; i < menuitems.size(); i++) { + drawItem(i, false); // no clear + } + } void Menu::internal_hide() {

@@ -713,7 +612,7 @@ shown = (Menu *) 0;

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 @@ menu.title.setAlpha(alpha());

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,10 +765,14 @@ return true;

} -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];

@@ -896,6 +780,7 @@ 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 @@ sel_x += quarter_w;

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()); + frameWindow().clearArea(item_x, item_y, + menu.item_w, theme().itemHeight(), False); + } - } 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(); - } - - } - 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); } - - } - + menu.frame.updateTransparent(item_x, item_y, item_w, item_h); + } - if (render_trans) { - renderTransp(item_x, item_y, - menu.item_w, theme().itemHeight()); - } //!! //!! TODO: Move this out to MenuItem //!! current problem: menu.sel_pixmap needs a image control instance

@@ -974,7 +832,7 @@ theme().selectedPixmap().mask().drawable());

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,30 +843,23 @@ XSetClipMask(disp,

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 @@ if (item->submenu()) {

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 @@ if (m_which_sub != -1)

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 @@ itemSelected(re.button, w);

} } - drawItem(p, - true, // clear - true); // transparent + drawItem(p, true); // clear } } }

@@ -1174,9 +1015,7 @@

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 @@ MenuItem *item = menuitems[old];

if (item != 0) { - drawItem(old, - true, // clear - true); // transparent + drawItem(old, true); // clear if (item->submenu()) {

@@ -1247,8 +1084,7 @@ // if submenu,

// 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 @@ // else normal menu item

// 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::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 @@ m_shifted = true;

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

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

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

menu.window.setBorderWidth(theme().borderWidth()); menu.title.setBorderWidth(theme().borderWidth()); - - updateMenu(); - + if (m_visible) { + updateMenu(); + } }

@@ -1438,8 +1283,7 @@ int item = m_which_sbl * menu.persub + m_which_press;

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 @@ reconfigure();

} -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;
M src/FbTk/Menu.hhsrc/FbTk/Menu.hh

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

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 @@ int m_active_index; ///< current highlighted index

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;
M src/FbTk/TextButton.ccsrc/FbTk/TextButton.cc

@@ -37,8 +37,7 @@ m_font(&font),

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 @@ if (this->width() == width && height == this->height() &&

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::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 @@ textlen); // return new text len

// 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
M src/FbTk/TextButton.hhsrc/FbTk/TextButton.hh

@@ -81,7 +81,6 @@ int m_bevel;

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
M src/FbTk/Transparent.ccsrc/FbTk/Transparent.cc

@@ -206,6 +206,17 @@ freeAlpha();

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

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) {
M src/FbTk/Transparent.hhsrc/FbTk/Transparent.hh

@@ -39,6 +39,7 @@ /// sets source drawable

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 */
M src/FbWinFrame.ccsrc/FbWinFrame.cc

@@ -82,37 +82,14 @@ m_use_handle(true),

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::show() { m_visible = true; + + if (m_need_render) { + renderAll(); + applyAll(); + clearAll(); + } + m_window.showSubwindows(); m_window.show(); - updateTransparent(); } /**

@@ -217,14 +200,11 @@ }

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 @@ if (resize)

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

// 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::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 @@ }

// 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 @@ (*btn_it)->moveResize(last_x - border_width, - border_width,

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 @@ unsigned int next_x = m_bevel;

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 @@ m_buttons_right[i]->moveResize(next_x, m_bevel,

button_size, button_size); } +// renderTitlebar(); // gets done outside + m_titlebar.raise(); // always on top +} + +void FbWinFrame::renderAll() { + m_need_render = false; + renderTitlebar(); - m_titlebar.raise(); // always on top + 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,

@@ -1005,7 +1053,6 @@

render(m_theme.titleUnfocusTexture(), m_title_unfocused_color, m_title_unfocused_pm, m_titlebar.width(), m_titlebar.height()); - render(m_theme.labelFocusTexture(), m_label_focused_color, m_label_focused_pm,

@@ -1016,18 +1063,22 @@ render(m_theme.labelUnfocusTexture(), m_label_unfocused_color,

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; FbTk::Color title_color; 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);

@@ -1039,18 +1090,7 @@ m_titlebar.setBackgroundPixmap(title_pm);

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 @@ render(m_theme.handleUnfocusTexture(), m_handle_unfocused_color,

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 @@ render(m_theme.gripUnfocusTexture(), m_grip_unfocused_color,

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 @@ } else {

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 @@ m_grip_right.setBackgroundColor(m_grip_unfocused_color);

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

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 @@ if (m_focused)

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 @@ m_handle.showSubwindows();

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

/** 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::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 @@ title_color = m_title_unfocused_color;

} 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 @@ if (bw_changes != 0)

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:

@@ -1402,58 +1439,6 @@ Display *m_display;

long m_event_mask; }; } - -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
M src/FbWinFrame.hhsrc/FbWinFrame.hh

@@ -30,7 +30,6 @@ #include "FbTk/RefCount.hh"

#include "FbTk/Observer.hh" #include "FbTk/Color.hh" #include "FbTk/FbPixmap.hh" -#include "FbTk/Timer.hh" #include <vector> #include <list>

@@ -86,6 +85,11 @@ void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move = true, bool resize = true, int win_gravity=ForgetGravity);

// 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);

@@ -151,8 +155,6 @@

void reconfigure(); void setUseShape(bool value); - void setUpdateDelayTime(long t) { m_update_timer.setTimeout(t); } - /** @name accessors */

@@ -199,31 +201,43 @@ /**

@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 @@ Pixmap m_label_focused_pm; ///< pixmap for focused label

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 @@ Pixmap m_grip_unfocused_pm; ///< unfocused pixmap for grip

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

ThemeListener m_themelistener; std::auto_ptr<Shape> m_shape; bool m_disable_shape; - FbTk::Timer m_update_timer; }; #endif // FBWINFRAME_HH
M src/GenericTool.ccsrc/GenericTool.cc

@@ -79,10 +79,8 @@

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(); }
M src/Slit.ccsrc/Slit.cc

@@ -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::clearWindow() { frame.window.clear(); - frame.window.updateTransparent(); } void Slit::toggleHidden() {
M src/ToggleMenu.hhsrc/ToggleMenu.hh

@@ -48,15 +48,12 @@ // the items each time we get a button release event

// 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(); } }
M src/Toolbar.ccsrc/Toolbar.cc

@@ -462,7 +462,6 @@ } else {

frame.window.setAlpha(alpha()); } frame.window.clear(); - frame.window.updateTransparent(); if (theme().shape() && m_shape.get()) m_shape->update();

@@ -562,8 +561,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 @@ }

// unlock m_resize_lock = false; frame.window.clear(); - frame.window.updateTransparent(); - } void Toolbar::deleteItems() {

@@ -1047,7 +1042,6 @@ frame.window.setOpaque(*m_rc_alpha);

} 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();
M src/WinButton.ccsrc/WinButton.cc

@@ -25,6 +25,7 @@ #include "WinButton.hh"

#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 @@ Type buttontype, const FbTk::FbWindow &parent,

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); } -// clear is used to force this to clear the window (e.g. called from clear()) -void WinButton::drawType(bool clear, bool no_trans) { - bool used = false; +// when someone else tries to set the background, we may override it +void WinButton::setBackgroundPixmap(Pixmap pm) { + Pixmap my_pm = getBackgroundPixmap(); - // if it's odd and we're centring, we need to add one - int oddW = width()%2; - int oddH = height()%2; + if (my_pm != 0) { + overrode_bg = true; + pm = my_pm; + } else { + overrode_bg = false; + } - switch (m_type) { - case MAXIMIZE: + FbTk::Button::setBackgroundPixmap(pm); +} - 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; +void WinButton::setBackgroundColor(const FbTk::Color &color) { + Pixmap my_pm = getBackgroundPixmap(); - 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 (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 (used || clear) { - FbTk::FbWindow::clear(); - } - if (!used && gc() != 0) { // must have valid graphic context - FbTk::FbWindow::drawRectangle(gc(), - 2, height() - 5, width() - 5, 2); - } - break; - case STICK: + if (my_pm != 0) { + overrode_pressed = true; + pm = my_pm; + } else { + overrode_pressed = false; + } - 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; - } + FbTk::Button::setBackgroundPixmap(pm); +} - } - - } +void WinButton::setPressedColor(const FbTk::Color &color) { + Pixmap my_pm = getPressedPixmap(); - if (used || clear) - FbTk::FbWindow::clear(); + if (my_pm != 0) { + overrode_pressed = true; + FbTk::Button::setPressedPixmap(my_pm); + } else { + overrode_pressed = false; + FbTk::Button::setPressedColor(color); + } +} - 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); - } +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 (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; - } - } + 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; +} - - if (used || clear) - FbTk::FbWindow::clear(); +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; +} - if (!used && gc() != 0) { // must have valid graphic context +// clear is used to force this to clear the window (e.g. called from clear()) +void WinButton::drawType() { + bool used = false; - 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 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; - drawLine(gc(), - 2, height() - 3, - width() - 3, 2); + // otherwise draw old style imagery + switch (m_type) { + case MAXIMIZE: + // if no pixmap was used, use old style + if (gc() == 0) // must have valid graphic context + return; + + drawRectangle(gc(), + 2, 2, width() - 5, height() - 5); + drawLine(gc(), + 2, 3, width() - 3, 3); + break; + case MINIMIZE: + FbTk::FbWindow::drawRectangle(gc(), + 2, height() - 5, width() - 5, 2); + break; + case STICK: + // 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 SHADE: + case CLOSE: + 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 (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(); - + drawLine(gc(), + 2, height() - 3, + width() - 3, 2); + break; + case SHADE: + // 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) {
M src/WinButton.hhsrc/WinButton.hh

@@ -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 @@ unsigned int width, unsigned int height);

/// 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; };
M src/WinClient.ccsrc/WinClient.cc

@@ -358,7 +358,7 @@ }

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 );
M src/Window.ccsrc/Window.cc

@@ -1194,7 +1194,6 @@

grabButtons(); frame().setDoubleClickTime(Fluxbox::instance()->getDoubleClickInterval()); - frame().setUpdateDelayTime(Fluxbox::instance()->getUpdateDelayTime()); frame().reconfigure();

@@ -1210,7 +1209,7 @@ // graphics

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 @@ if (gravity != ForgetGravity) {

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)

@@ -1367,7 +1367,6 @@ }

frame().moveResize(new_x, new_y, new_width, new_height); setFocusFlag(focused); - shaded = false; send_event = true;

@@ -2848,7 +2847,9 @@ frame().height() + 2*frame().window().borderWidth()-1);

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 @@ Fluxbox *fluxbox = Fluxbox::instance();

fluxbox->maskWindowEvents(0, 0); - if (! screen().doOpaqueMove()) { parent().drawRectangle(screen().rootTheme().opGC(), m_last_move_x, m_last_move_y,

@@ -3231,8 +3231,8 @@ }

} 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); }
M src/Window.hhsrc/Window.hh

@@ -232,7 +232,7 @@ void move(int x, int y, int gravity = ForgetGravity);

/// 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);
M src/fluxbox.ccsrc/fluxbox.cc

@@ -200,7 +200,6 @@ m_rc_colors_per_channel(m_resourcemanager, 4,

"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 @@ to.tv_usec = 1;

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

// 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 @@ } else

m_focused_window = 0; - if (screen != 0) { screen->updateNetizenWindowFocus(); for (AtomHandlerContainerIt it= m_atomhandler.begin();

@@ -1871,7 +1868,6 @@ for (AtomHandlerContainerIt it= m_atomhandler.begin();

it != m_atomhandler.end(); it++) (*it).first->updateFocusedWindow(*old_screen, 0); } - } /**
M src/fluxbox.hhsrc/fluxbox.hh

@@ -102,7 +102,6 @@ int initScreen(int screen_nr);

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

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,