all repos — fluxbox @ 57ec44e9940992554c8d55b09e885f9c020a209d

custom fork of the fluxbox windowmanager

Add support for stacked tiling via ArrangeWindows*
John Sennesael john@adminking.com
commit

57ec44e9940992554c8d55b09e885f9c020a209d

parent

58e09b719077605efadac9b712acb8f5e752f732

3 files changed, 124 insertions(+), 17 deletions(-)

jump to
M doc/asciidoc/fluxbox-keys.txtdoc/asciidoc/fluxbox-keys.txt

@@ -417,6 +417,23 @@ (windows side by side), whereas *ArrangeWindowsHorizontal* prefers horizontal

splits (windows on top of eachother). See *CLIENT PATTERNS* for more about the 'pattern' arguments. +*ArrangeWindowsStackLeft* 'pattern' / *ArrangeWindowsStackRight* 'pattern':: + Similar to *ArrangeWindows*, these commands arrange windows on the current + workspace. The currently focussed window is used as the 'main' window, and + will fill half the screen, while the other windows are tiled on the + other half of the screen as if they were tiled with ArrangeWindows. + *ArrangeWindowsStackLeft* puts the main window on the RIGHT hand side of the + screen, and the tiled windows are on the LEFT hand side of the screen. + *ArrangeWindowsStackRight* puts the main window on the LEFT hand side of the + screen, and the tiled windows are on the RIGHT hand side of the screen. + +*ArrangeWindowsStackTop* 'pattern' / *ArrangeWindowsStackBottom 'pattern':: + Behaves just like *ArrangeWindowsStackLeft* and *ArrangeWindowsStackRight*. + *ArrangeWindowsStackBottom* places the main window on the TOP half of the + screen, and the tiled windows on the bottom half of the screen. + *ArrangeWindowsStackTop* places the main window on the BOTTOM half of the + screen and the tiled windows on the top half of the screen. + *ShowDesktop*:: Minimizes all windows on the current workspace. If they are already all minimized, then it restores them.
M src/WorkspaceCmd.ccsrc/WorkspaceCmd.cc

@@ -186,7 +186,20 @@ return new ArrangeWindowsCmd(method,pat);

} else if (command == "arrangewindowshorizontal") { int method = ArrangeWindowsCmd::HORIZONTAL; return new ArrangeWindowsCmd(method,pat); + } else if (command == "arrangewindowsstackleft") { + int method = ArrangeWindowsCmd::STACKLEFT; + return new ArrangeWindowsCmd(method,pat); + } else if (command == "arrangewindowsstackright") { + int method = ArrangeWindowsCmd::STACKRIGHT; + return new ArrangeWindowsCmd(method,pat); + } else if (command == "arrangewindowsstacktop") { + int method = ArrangeWindowsCmd::STACKTOP; + return new ArrangeWindowsCmd(method,pat); + } else if (command == "arrangewindowsstackbottom") { + int method = ArrangeWindowsCmd::STACKBOTTOM; + return new ArrangeWindowsCmd(method,pat); } + return 0; }

@@ -198,6 +211,10 @@ REGISTER_COMMAND_PARSER(prevgroup, parseWindowList, void);

REGISTER_COMMAND_PARSER(arrangewindows, parseWindowList, void); REGISTER_COMMAND_PARSER(arrangewindowsvertical, parseWindowList, void); REGISTER_COMMAND_PARSER(arrangewindowshorizontal, parseWindowList, void); +REGISTER_COMMAND_PARSER(arrangewindowsstackleft, parseWindowList, void); +REGISTER_COMMAND_PARSER(arrangewindowsstackright, parseWindowList, void); +REGISTER_COMMAND_PARSER(arrangewindowsstacktop, parseWindowList, void); +REGISTER_COMMAND_PARSER(arrangewindowsstackbottom, parseWindowList, void); } // end anonymous namespace

@@ -217,7 +234,7 @@ else

first->attachClient((*it)->fbwindow()->winClient()); } } - + } }

@@ -393,13 +410,33 @@ Workspace::Windows::iterator win;

Workspace::Windows normal_windows; Workspace::Windows shaded_windows; + FluxboxWindow* main_window = NULL; // Main (big) window for stacked modes for(win = space->windowList().begin(); win != space->windowList().end(); ++win) { int winhead = screen->getHead((*win)->fbWindow()); if ((winhead == head || winhead == 0) && m_pat.match(**win)) { - if ((*win)->isShaded()) - shaded_windows.push_back(*win); - else - normal_windows.push_back(*win); + // If using stacked tiling, and this window is focused, set it as main window + if (((m_tile_method == STACKLEFT) || (m_tile_method == STACKRIGHT) + || (m_tile_method == STACKBOTTOM) || (m_tile_method == STACKTOP)) + && (*win)->isFocused()){ + main_window = (*win); + } + else{ + if ((*win)->isShaded()) + shaded_windows.push_back(*win); + else + normal_windows.push_back(*win); + } + } + } + // if using stacked-left/right/top/bottom and we don't have a main window yet + // (no focused window?), we'll fall back on using the last window in the + // window list. + if (main_window == NULL) + { + if ((m_tile_method == STACKLEFT) || (m_tile_method == STACKRIGHT) + || (m_tile_method == STACKTOP) || (m_tile_method == STACKBOTTOM)) { + main_window = normal_windows.back(); + normal_windows.pop_back(); } }

@@ -408,8 +445,16 @@ size_t win_count = normal_windows.size();

if (win_count == 0) return; - const unsigned int max_width = screen->maxRight(head) - screen->maxLeft(head); + unsigned int max_width = screen->maxRight(head) - screen->maxLeft(head); + // If stacked left or right, max width is divided in 2 + if ((m_tile_method == STACKLEFT) || (m_tile_method == STACKRIGHT)){ + max_width = max_width / 2; + } unsigned int max_height = screen->maxBottom(head) - screen->maxTop(head); + // If stacked top or bottom, max height is divided in 2 + if ((m_tile_method == STACKTOP) || (m_tile_method == STACKBOTTOM)){ + max_height = max_height / 2; + } // try to get the same number of rows as columns. unsigned int cols = int(sqrt((float)win_count)); // truncate to lower

@@ -421,7 +466,26 @@ }

unsigned int x_offs = screen->maxLeft(head); // window position offset in x unsigned int y_offs = screen->maxTop(head); // window position offset in y - // unsigned int window = 0; // current window + // Stacked mode only uses half the screen for tiled windows, so adjust offset to half the screen + // (horizontal or vertical depending on stacking mode) + switch(m_tile_method) + { + case STACKRIGHT: + x_offs = int(abs((screen->maxLeft(head)-screen->maxRight(head)))/2); + break; + case STACKBOTTOM: + y_offs = int(abs(screen->maxBottom(head) - screen->maxTop(head))/2); + break; + default: + // no change needed for STACKLEFT/STACKTOP + break; + } + // Since the placing algorithm loop below modifies the offsets, but we still need them to + // position the main window, we save the calculated values. + const unsigned int orig_x_offs = x_offs; + const unsigned int orig_y_offs = y_offs; + + // unsigned int window = 0; // current window const unsigned int cal_width = max_width/cols; // calculated width ratio (width of every window) unsigned int i; unsigned int j;

@@ -448,7 +512,7 @@

const unsigned int cal_height = max_height/rows; // height ratio (height of every window) // Resizes and sets windows positions in columns and rows. for (i = 0; i < rows; ++i) { - x_offs = screen->maxLeft(head); + x_offs = orig_x_offs; for (j = 0; j < cols && !normal_windows.empty(); ++j) {

@@ -461,7 +525,7 @@ for (win = normal_windows.begin(); win != normal_windows.end(); ++win) {

int win_center_x = (*win)->frame().x() + ((*win)->frame().x() + (*win)->frame().width() / 2); int win_center_y = (*win)->frame().y() + ((*win)->frame().y() + (*win)->frame().height() / 2); - unsigned int dist = (win_center_x - cell_center_x) * (win_center_x - cell_center_x) + + unsigned int dist = (win_center_x - cell_center_x) * (win_center_x - cell_center_x) + (win_center_y - cell_center_y) * (win_center_y - cell_center_y); if (dist < closest_dist) {

@@ -472,14 +536,14 @@ }

if (normal_windows.size() > 1) { (*closest)->moveResize(x_offs + (*closest)->xOffset(), - y_offs + (*closest)->yOffset(), - cal_width - (*closest)->widthOffset(), - cal_height - (*closest)->heightOffset()); + y_offs + (*closest)->yOffset(), + cal_width - (*closest)->widthOffset(), + cal_height - (*closest)->heightOffset()); } else { // the last window gets everything that is left. (*closest)->moveResize(x_offs + (*closest)->xOffset(), - y_offs + (*closest)->yOffset(), - screen->maxRight(head) - x_offs - (*closest)->widthOffset(), - cal_height - (*closest)->heightOffset()); + y_offs + (*closest)->yOffset(), + max_width - x_offs - (*closest)->widthOffset(), + cal_height - (*closest)->heightOffset()); } normal_windows.erase(closest);

@@ -490,6 +554,28 @@ }

// next y offset y_offs += cal_height; } + + // If using a stacked mechanism we now need to place the main window. + if (main_window != NULL){ + switch (m_tile_method){ + case STACKLEFT: + main_window->moveResize(max_width,orig_y_offs,max_width,max_height); + break; + case STACKRIGHT: + main_window->moveResize(screen->maxLeft(head),screen->maxTop(head),max_width,max_height); + break; + case STACKTOP: + main_window->moveResize(screen->maxLeft(head),max_height,max_width,max_height); + break; + case STACKBOTTOM: + main_window->moveResize(screen->maxLeft(head),screen->maxTop(head),max_width,max_height); + break; + default: + // Shouldn't happen. + break; + } + } + } REGISTER_COMMAND(showdesktop, ShowDesktopCmd, void);
M src/WorkspaceCmd.hhsrc/WorkspaceCmd.hh

@@ -86,7 +86,7 @@ };

class PrevWindowCmd: public FbTk::Command<void> { public: - explicit PrevWindowCmd(int option, std::string &pat): + explicit PrevWindowCmd(int option, std::string &pat): m_option(option), m_pat(pat.c_str()) { } void execute(); private:

@@ -173,7 +173,11 @@ public:

enum { UNSPECIFIED, VERTICAL, - HORIZONTAL + HORIZONTAL, + STACKLEFT, + STACKRIGHT, + STACKTOP, + STACKBOTTOM }; explicit ArrangeWindowsCmd(int tile_method, std::string &pat): m_tile_method( tile_method ), m_pat(pat.c_str()) { }