From 57ec44e9940992554c8d55b09e885f9c020a209d Mon Sep 17 00:00:00 2001 From: John Sennesael Date: Fri, 2 Aug 2013 08:56:07 +0200 Subject: Add support for stacked tiling via ArrangeWindows* --- doc/asciidoc/fluxbox-keys.txt | 17 +++++++ src/WorkspaceCmd.cc | 116 ++++++++++++++++++++++++++++++++++++------ src/WorkspaceCmd.hh | 8 ++- 3 files changed, 124 insertions(+), 17 deletions(-) diff --git a/doc/asciidoc/fluxbox-keys.txt b/doc/asciidoc/fluxbox-keys.txt index 02fc745..4d92c43 100644 --- a/doc/asciidoc/fluxbox-keys.txt +++ b/doc/asciidoc/fluxbox-keys.txt @@ -417,6 +417,23 @@ doing so. 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. diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc index 42cc05e..2d4de03 100644 --- a/src/WorkspaceCmd.cc +++ b/src/WorkspaceCmd.cc @@ -186,7 +186,20 @@ FbTk::Command *parseWindowList(const string &command, } 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 @@ void AttachCmd::execute() { first->attachClient((*it)->fbwindow()->winClient()); } } - + } } @@ -393,13 +410,33 @@ void ArrangeWindowsCmd::execute() { 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 @@ void ArrangeWindowsCmd::execute() { 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 @@ void ArrangeWindowsCmd::execute() { 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 @@ void ArrangeWindowsCmd::execute() { 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 @@ void ArrangeWindowsCmd::execute() { 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 @@ void ArrangeWindowsCmd::execute() { 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 @@ void ArrangeWindowsCmd::execute() { // 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); diff --git a/src/WorkspaceCmd.hh b/src/WorkspaceCmd.hh index f4f90a6..f4609b6 100644 --- a/src/WorkspaceCmd.hh +++ b/src/WorkspaceCmd.hh @@ -86,7 +86,7 @@ private: class PrevWindowCmd: public FbTk::Command { 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()) { } -- cgit v0.11.2