Add support for stacked tiling via ArrangeWindows*

This commit is contained in:
John Sennesael 2013-08-02 08:56:07 +02:00 committed by Mathias Gumz
parent 58e09b7190
commit 57ec44e994
3 changed files with 124 additions and 17 deletions

View file

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

View file

@ -186,7 +186,20 @@ FbTk::Command<void> *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);

View file

@ -86,7 +86,7 @@ private:
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()) { }