Use "session.titlebarLayout: IMLC" to define the layout for window titlebars. Any combination or order can be used, although checks are made for sanity. Meaning: I = iconify button, C = close, M = maximize, L = text label. diff -ruN blackbox/src/BlackboxResource.cc bb.titlebar/src/BlackboxResource.cc --- blackbox/src/BlackboxResource.cc 2004-02-13 09:36:18.000000000 +0200 +++ bb.titlebar/src/BlackboxResource.cc 2004-02-16 00:21:10.000000000 +0200 @@ -86,6 +86,9 @@ menu_file = bt::expandTilde(res.read("session.menuFile", "Session.MenuFile", DEFAULTMENU)); + titlebar_layout = res.read("session.titlebarLayout", + "Session.TitlebarLayout", "ILMC"); + unsigned int maxcolors = res.read("session.maximumColors", "Session.MaximumColors", ~0u); @@ -146,6 +149,8 @@ res.write("session.menuFile", menuFilename()); + res.write("session.titlebarLayout", titlebarLayout()); + res.write("session.styleFile", styleFilename()); res.write("session.maximumColors", bt::Image::maximumColors()); diff -ruN blackbox/src/BlackboxResource.hh bb.titlebar/src/BlackboxResource.hh --- blackbox/src/BlackboxResource.hh 2004-02-13 09:36:18.000000000 +0200 +++ bb.titlebar/src/BlackboxResource.hh 2004-02-16 00:21:10.000000000 +0200 @@ -203,7 +203,7 @@ }; BCursor cursor; - std::string menu_file, style_file, rc_file; + std::string menu_file, style_file, rc_file, titlebar_layout; Time double_click_interval; bt::timeval auto_raise_delay; @@ -232,6 +232,8 @@ { return menu_file.c_str(); } inline const char* styleFilename(void) const { return style_file.c_str(); } + inline const char* titlebarLayout(void) const + { return titlebar_layout.c_str(); } inline void saveStyleFilename(const std::string& name) { style_file = name; } diff -ruN blackbox/src/Window.cc bb.titlebar/src/Window.cc --- blackbox/src/Window.cc 2004-02-13 09:36:18.000000000 +0200 +++ bb.titlebar/src/Window.cc 2004-02-16 00:22:59.000000000 +0200 @@ -822,87 +822,171 @@ void BlackboxWindow::positionButtons(bool redecorate_label) { - // we need to use signed ints here to detect windows that are too small - const int - bw = frame.style->button_width + frame.style->bevel_width + 1, - by = frame.style->bevel_width + 1; - int lx = by, lw = frame.inside_w - by; + char *format = (char *) blackbox->resource().titlebarLayout(); + int bc = 0, x = 0, lw = 0; + int tx = frame.style->bevel_width; + int ty = frame.style->bevel_width; + char layout[5] = ""; + + // parse the user provided titlebar format + // and add things to our own layout, with sanity checks + for (x=0, bc=0; &format[x] != "" && x <= 3; x++) { + switch (*(format + x)) { + case 'I': + { + if (!strrchr(layout, 'I') && (client.decorations & WindowDecorationIconify)) { + strcat(layout, "I"); + bc++; + } + break; + } + case 'M': + { + if (!strrchr(layout, 'M') && (client.decorations & WindowDecorationMaximize)) { + strcat(layout, "M"); + bc++; + } + } + case 'C': + { + if (!strrchr(layout, 'C') && (client.decorations & WindowDecorationClose)) { + strcat(layout, "C"); + bc++; + } + break; + } + case 'L': + { + if (!strrchr(layout, 'L')) { + strcat(layout, "L"); + } + break; + } + } + } + + // if there's no label + if (!strrchr(layout,'L')) { + // add it; gotta have the label :) + strcat(layout, "L"); + } + + // calculate the label width: it's the frame for the width, + // minus the width of all the buttons, minus a bevel for each + // button, for the label, and for the end side of the bar + lw = frame.inside_w - bc * frame.style->button_width - (bc + 2) * frame.style->bevel_width; + + // sanity check; if the label falls under 1 we'll crash later + frame.label_w = (lw > 0) ? lw : 1; + + // parse our own sane layout and render elements + for (x=0; x < strlen(layout); x++) { + switch (layout[x]) { + case 'I': + { + tx += BlackboxWindow::positionIconifyButton(tx,ty); + break; + } + case 'L': + { + tx += BlackboxWindow::positionLabel(tx,ty); + break; + } + case 'M': + { + tx += BlackboxWindow::positionMaximizeButton(tx,ty); + break; + } + case 'C': + { + tx += BlackboxWindow::positionCloseButton(tx,ty); + break; + } + } + } + + // if a label refresh was requested + if (redecorate_label) { + // try to find it in the cache first + frame.flabel = + bt::PixmapCache::find(screen->screenNumber(), + frame.style->l_focus, + frame.label_w, frame.style->label_height, + frame.flabel); + frame.ulabel = + bt::PixmapCache::find(screen->screenNumber(), + frame.style->l_unfocus, + frame.label_w, frame.style->label_height, + frame.ulabel); + } + + // if the text is bigger than the label, show "..." instead + const std::string ellided = + bt::ellideText(client.title, frame.label_w, "...", + screen->screenNumber(), frame.style->font); + + // use the shortened text, if needed + if (ellided != client.visible_title) { + client.visible_title = ellided; + blackbox->netwm().setWMVisibleName(client.window, client.visible_title); + } + + // actually draw stuff + redrawLabel(); + redrawAllButtons(); +} + +int BlackboxWindow::positionIconifyButton(int tx, int ty) { if (client.decorations & WindowDecorationIconify) { if (frame.iconify_button == None) createIconifyButton(); - - XMoveResizeWindow(blackbox->XDisplay(), frame.iconify_button, by, by, + XMoveResizeWindow(blackbox->XDisplay(), frame.iconify_button, tx, ty, frame.style->button_width, frame.style->button_width); XMapWindow(blackbox->XDisplay(), frame.iconify_button); - - lx += bw; - lw -= bw; + return frame.style->button_width + frame.style->bevel_width; } else if (frame.iconify_button) { destroyIconifyButton(); + return 0; } + return 0; +} - int bx = frame.inside_w - bw; +int BlackboxWindow::positionCloseButton(int tx, int ty) { if (client.decorations & WindowDecorationClose) { if (frame.close_button == None) createCloseButton(); - - XMoveResizeWindow(blackbox->XDisplay(), frame.close_button, bx, by, + XMoveResizeWindow(blackbox->XDisplay(), frame.close_button, tx, ty, frame.style->button_width, frame.style->button_width); XMapWindow(blackbox->XDisplay(), frame.close_button); - - bx -= bw; - lw -= bw; + return frame.style->button_width + frame.style->bevel_width; } else if (frame.close_button) { destroyCloseButton(); + return 0; } + return 0; +} + +int BlackboxWindow::positionMaximizeButton(int tx, int ty) { if (client.decorations & WindowDecorationMaximize) { if (frame.maximize_button == None) createMaximizeButton(); - - XMoveResizeWindow(blackbox->XDisplay(), frame.maximize_button, bx, by, + XMoveResizeWindow(blackbox->XDisplay(), frame.maximize_button, tx, ty, frame.style->button_width, frame.style->button_width); XMapWindow(blackbox->XDisplay(), frame.maximize_button); - - bx -= bw; - lw -= bw; + return frame.style->button_width + frame.style->bevel_width; } else if (frame.maximize_button) { destroyMaximizeButton(); + return 0; } + return 0; +} - if (lw > by) { - frame.label_w = lw - by; - XMoveResizeWindow(blackbox->XDisplay(), frame.label, lx, - frame.style->bevel_width, - frame.label_w, frame.style->label_height); - XMapWindow(blackbox->XDisplay(), frame.label); - - if (redecorate_label) { - frame.flabel = - bt::PixmapCache::find(screen->screenNumber(), - frame.style->l_focus, - frame.label_w, frame.style->label_height, - frame.flabel); - frame.ulabel = - bt::PixmapCache::find(screen->screenNumber(), - frame.style->l_unfocus, - frame.label_w, frame.style->label_height, - frame.ulabel); - } - - const std::string ellided = - bt::ellideText(client.title, frame.label_w, "...", - screen->screenNumber(), frame.style->font); - - if (ellided != client.visible_title) { - client.visible_title = ellided; - blackbox->netwm().setWMVisibleName(client.window, client.visible_title); - } - } else { - XUnmapWindow(blackbox->XDisplay(), frame.label); - } - redrawLabel(); - redrawAllButtons(); +int BlackboxWindow::positionLabel(int tx, int ty) { + XMoveResizeWindow(blackbox->XDisplay(), frame.label, tx, ty, + frame.label_w, frame.style->label_height); + XMapWindow(blackbox->XDisplay(), frame.label); + return frame.label_w + frame.style->bevel_width; } diff -ruN blackbox/src/Window.hh bb.titlebar/src/Window.hh --- blackbox/src/Window.hh 2004-02-13 09:36:18.000000000 +0200 +++ bb.titlebar/src/Window.hh 2004-02-16 00:21:10.000000000 +0200 @@ -244,6 +244,11 @@ void positionButtons(bool redecorate_label = false); void positionWindows(void); + int positionCloseButton(int tx, int ty); + int positionMaximizeButton(int tx, int ty); + int positionIconifyButton(int tx, int ty); + int positionLabel(int tx, int ty); + void createTitlebar(void); void destroyTitlebar(void); void createHandle(void);