all repos — fluxbox @ b772fd969f039f7683d2bd666b7573eeb9d468e3

custom fork of the fluxbox windowmanager

moved placement strategies to different PlacementStrategy classes
fluxgen fluxgen
commit

b772fd969f039f7683d2bd666b7573eeb9d468e3

parent

d099e7673a51f76b2e6f54484152901288f90ae2

A src/CascadePlacement.cc

@@ -0,0 +1,75 @@

+// CascadePlacement.cc +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#include "CascadePlacement.hh" + +#include "Window.hh" +#include "Screen.hh" + +CascadePlacement::CascadePlacement(const BScreen &screen) { + // +1 ? + m_cascade_x = new int[screen.numHeads() + 1]; + m_cascade_y = new int[screen.numHeads() + 1]; + for (int i=0; i < screen.numHeads() + 1; i++) { + m_cascade_x[i] = 32 + screen.getHeadX(i); + m_cascade_y[i] = 32 + screen.getHeadY(i); + } + +} + +CascadePlacement::~CascadePlacement() { + delete [] m_cascade_x; + delete [] m_cascade_y; +} + +bool CascadePlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &win, + int &place_x, int &place_y) { + + int head = (signed) win.screen().getCurrHead(); + int head_left = (signed) win.screen().maxLeft(head); + int head_right = (signed) win.screen().maxRight(head); + int head_top = (signed) win.screen().maxTop(head); + int head_bot = (signed) win.screen().maxBottom(head); + + if ((m_cascade_x[head] > ((head_left + head_right) / 2)) || + (m_cascade_y[head] > ((head_top + head_bot) / 2))) { + m_cascade_x[head] = head_left + 32; + m_cascade_y[head] = head_top + 32; + } + + place_x = m_cascade_x[head]; + place_y = m_cascade_y[head]; + + // just one borderwidth, so they can share a borderwidth (looks better) + int titlebar_height = + win.titlebarHeight() + win.fbWindow().borderWidth(); + if (titlebar_height < 4) // make sure it is not insignificant + titlebar_height = 32; + + m_cascade_x[head] += titlebar_height; + m_cascade_y[head] += titlebar_height; + + return true; +} +
A src/CascadePlacement.hh

@@ -0,0 +1,45 @@

+// CascadePlacement.hh +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#ifndef CASCADEPLACEMENT_HH +#define CASCADEPLACEMENT_HH + +#include "PlacementStrategy.hh" +#include "FbTk/NotCopyable.hh" + +class BScreen; + +class CascadePlacement: public PlacementStrategy, + private FbTk::NotCopyable { +public: + explicit CascadePlacement(const BScreen &screen); + ~CascadePlacement(); + bool placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &window, + int &place_x, int &place_y); +private: + int *m_cascade_x; ///< need a cascade for each head (Xinerama) + int *m_cascade_y; ///< need a cascade for each head (Xinerama) +}; + +#endif // CASCADEPLACEMENT_HH
A src/ColSmartPlacement.cc

@@ -0,0 +1,136 @@

+// ColSmartPlacement.cc +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#include "ColSmartPlacement.hh" + +#include "Screen.hh" +#include "ScreenPlacement.hh" +#include "Window.hh" + +bool ColSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &win, + int &place_x, int &place_y) { + + // xinerama head constraints + int head = (signed) win.screen().getCurrHead(); + int head_left = (signed) win.screen().maxLeft(head); + int head_right = (signed) win.screen().maxRight(head); + int head_top = (signed) win.screen().maxTop(head); + int head_bot = (signed) win.screen().maxBottom(head); + + bool placed = false; + int next_x, next_y; + const ScreenPlacement &screen_placement = + dynamic_cast<const ScreenPlacement &>(win.screen().placementStrategy()); + + bool top_bot = screen_placement.colDirection() == ScreenPlacement::TOPBOTTOM; + bool left_right = screen_placement.rowDirection() == ScreenPlacement::LEFTRIGHT; + + int test_x; + + int win_w = win.width() + win.fbWindow().borderWidth()*2; + int win_h = win.height() + win.fbWindow().borderWidth()*2; + + if (left_right) + test_x = head_left; + else + test_x = head_right - win_w; + + int change_y = 1; + if (screen_placement.colDirection() == ScreenPlacement::BOTTOMTOP) + change_y = -1; + + while (!placed && + (left_right ? test_x + win_w <= head_right + : test_x >= head_left)) { + + if (left_right) + next_x = head_right; // it will get shrunk + else + next_x = head_left-1; + + int test_y; + if (top_bot) + test_y = head_top; + else + test_y = head_bot - win_h; + + while (!placed && + (top_bot ? test_y + win_h <= head_bot + : test_y >= head_top)) { + placed = true; + + next_y = test_y + change_y; + + std::vector<FluxboxWindow *>::const_iterator it = + windowlist.begin(); + std::vector<FluxboxWindow *>::const_iterator it_end = + windowlist.end(); + for (; it != it_end && placed; ++it) { + int curr_x = (*it)->x(); + int curr_y = (*it)->y(); + int curr_w = (*it)->width() + (*it)->fbWindow().borderWidth()*2; + int curr_h = (*it)->height() + (*it)->fbWindow().borderWidth()*2; + + if (curr_x < test_x + win_w && + curr_x + curr_w > test_x && + curr_y < test_y + win_h && + curr_y + curr_h > test_y) { + // this window is in the way + placed = false; + + // we find the next y that we can go to (a window will be in the way + // all the way to its bottom) + if (top_bot) { + if (curr_y + curr_h > next_y) + next_y = curr_y + curr_h; + } else { + if (curr_y - win_h < next_y) + next_y = curr_y - win_h; + } + + // but we can only go to the nearest x, since that is where the + // next time current windows in the way will change + if (left_right) { + if (curr_x + curr_w < next_x) + next_x = curr_x + curr_w; + } else { + if (curr_x - win_w > next_x) + next_x = curr_x - win_w; + } + } + } + + if (placed) { + place_x = test_x; + place_y = test_y; + } + + test_y = next_y; + } // end while + + test_x = next_x; + } // end while + + return placed; +}
A src/ColSmartPlacement.hh

@@ -0,0 +1,36 @@

+// ColSmartPlacement.hh +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#ifndef COLSMARTPLACEMENT_HH +#define COLSMARTPLACEMENT_HH + +#include "PlacementStrategy.hh" + +class ColSmartPlacement: public PlacementStrategy { +public: + bool placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &win, + int &place_x, int &place_y); +}; + +#endif // COLSMARTPLACEMENT_HH
M src/Makefile.amsrc/Makefile.am

@@ -128,6 +128,11 @@ HeadArea.hh HeadArea.cc \

Resources.cc \ WindowCmd.hh WindowCmd.cc \ FocusControl.hh FocusControl.cc \ + CascadePlacement.hh CascadePlacement.cc \ + ColSmartPlacement.hh ColSmartPlacement.cc \ + RowSmartPlacement.hh RowSmartPlacement.cc \ + ScreenPlacement.hh ScreenPlacement.cc \ + UnderMousePlacement.hh UnderMousePlacement.cc \ ${newwmspec_SOURCE} ${gnome_SOURCE} \ ${REMEMBER_SOURCE} ${TOOLBAR_SOURCE}
A src/RowSmartPlacement.cc

@@ -0,0 +1,155 @@

+// RowSmartPlacement.cc +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#include "RowSmartPlacement.hh" + +#include "Window.hh" +#include "Screen.hh" +#include "ScreenPlacement.hh" + +bool RowSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &win, + int &place_x, int &place_y) { + + bool placed = false; + int next_x, next_y; + + // view (screen + head) constraints + int head = (signed) win.screen().getCurrHead(); + int head_left = (signed) win.screen().maxLeft(head); + int head_right = (signed) win.screen().maxRight(head); + int head_top = (signed) win.screen().maxTop(head); + int head_bot = (signed) win.screen().maxBottom(head); + + const ScreenPlacement &screen_placement = + dynamic_cast<const ScreenPlacement &>(win.screen().placementStrategy()); + + bool top_bot = + screen_placement.colDirection() == ScreenPlacement::TOPBOTTOM; + bool left_right = + screen_placement.rowDirection() == ScreenPlacement::LEFTRIGHT; + + int change_x = 1, change_y = 1; + + if (screen_placement.colDirection() == ScreenPlacement::BOTTOMTOP) + change_y = -1; + + if (screen_placement.rowDirection() == ScreenPlacement::RIGHTLEFT) + change_x = -1; + + + + + int win_h = win.height() + win.fbWindow().borderWidth()*2; + int win_w = win.width() + win.fbWindow().borderWidth()*2; + int test_y; + if (top_bot) + test_y = head_top; + else + test_y = head_bot - win_h; + + while (!placed && + (top_bot ? test_y + win_h <= head_bot + : test_y >= head_top)) { + + int test_x; + if (left_right) + test_x = head_left; + else + test_x = head_right - win_w; + + // The trick here is that we set it to the furthest away one, + // then the code brings it back down to the safest one that + // we can go to (i.e. the next untested area) + if (top_bot) + next_y = head_bot; // will be shrunk + else + next_y = head_top-1; + + while (!placed && + (left_right ? test_x + win_w <= head_right + : test_x >= head_left)) { + + placed = true; + + next_x = test_x + change_x; + + std::vector<FluxboxWindow *>::const_iterator win_it = + windowlist.begin(); + std::vector<FluxboxWindow *>::const_iterator win_it_end = + windowlist.end(); + + for (; win_it != win_it_end && placed; ++win_it) { + FluxboxWindow &window = **win_it; + + int curr_x = window.x(); + int curr_y = window.y(); + int curr_w = window.width() + window.fbWindow().borderWidth()*2; + int curr_h = window.height() + window.fbWindow().borderWidth()*2; + + if (curr_x < test_x + win_w && + curr_x + curr_w > test_x && + curr_y < test_y + win_h && + curr_y + curr_h > test_y) { + // this window is in the way + placed = false; + + // we find the next x that we can go to (a window will be in the way + // all the way to its far side) + if (left_right) { + if (curr_x + curr_w > next_x) + next_x = curr_x + curr_w; + } else { + if (curr_x - win_w < next_x) + next_x = curr_x - win_w; + } + + // but we can only go to the nearest y, since that is where the + // next time current windows in the way will change + if (top_bot) { + if (curr_y + curr_h < next_y) + next_y = curr_y + curr_h; + } else { + if (curr_y - win_h > next_y) + next_y = curr_y - win_h; + } + } + } + + + if (placed) { + place_x = test_x; + place_y = test_y; + + break; + } + + test_x = next_x; + } // end while + + test_y = next_y; + } // end while + + + return placed; +}
A src/RowSmartPlacement.hh

@@ -0,0 +1,37 @@

+// RowSmartPlacement.hh +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#ifndef ROWSMARTPLACEMENT_HH +#define ROWSMARTPLACEMENT_HH + +#include "PlacementStrategy.hh" + +class RowSmartPlacement: public PlacementStrategy { +public: + bool placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &win, + int &place_x, int &place_y); +}; + +#endif // ROWSMARTPLACEMENT_HH +
M src/Screen.ccsrc/Screen.cc

@@ -33,6 +33,7 @@ #include "Workspace.hh"

#include "Netizen.hh" #include "FocusControl.hh" +#include "ScreenPlacement.hh" // themes #include "FbWinFrameTheme.hh"

@@ -184,9 +185,7 @@ menu_alpha(rm, 255, scrname+".menu.alpha", altscrname+".Menu.Alpha"),

menu_delay(rm, 0, scrname + ".menuDelay", altscrname+".MenuDelay"), menu_delay_close(rm, 0, scrname + ".menuDelayClose", altscrname+".MenuDelayClose"), menu_mode(rm, FbTk::MenuTheme::DELAY_OPEN, scrname+".menuMode", altscrname+".MenuMode"), - placement_policy(rm, ROWSMARTPLACEMENT, scrname+".windowPlacement", altscrname+".WindowPlacement"), - row_direction(rm, LEFTRIGHT, scrname+".rowPlacementDirection", altscrname+".RowPlacementDirection"), - col_direction(rm, TOPBOTTOM, scrname+".colPlacementDirection", altscrname+".ColPlacementDirection"), + gc_line_width(rm, 1, scrname+".overlay.lineWidth", altscrname+".Overlay.LineWidth"), gc_line_style(rm, FbTk::GContext::LINESOLID,

@@ -238,6 +237,7 @@ m_resource_manager(rm),

m_name(screenname), m_altname(altscreenname), m_focus_control(new FocusControl(*this)), + m_placement_strategy(new ScreenPlacement(*this)), m_xinerama_headinfo(0), m_shutdown(false) {

@@ -446,7 +446,10 @@ m_slit.reset(0);

// TODO fluxgen: check if this is the right place delete [] m_head_areas; + delete m_focus_control; + delete m_placement_strategy; + } void BScreen::initWindows() {
M src/Screen.hhsrc/Screen.hh

@@ -30,6 +30,7 @@

#include "FbRootWindow.hh" #include "MenuTheme.hh" +#include "PlacementStrategy.hh" #include "FbTk/Resource.hh" #include "FbTk/Subject.hh"

@@ -63,6 +64,7 @@ class Strut;

class Slit; class HeadArea; class FocusControl; +class PlacementStrategy; namespace FbTk { class Menu;

@@ -90,15 +92,6 @@ BOTTOMRESIZE = 0,

QUADRANTRESIZE, DEFAULTRESIZE = BOTTOMRESIZE }; - enum PlacementPolicy { - ROWSMARTPLACEMENT, - COLSMARTPLACEMENT, - CASCADEPLACEMENT, - UNDERMOUSEPLACEMENT - }; - - enum RowDirection { LEFTRIGHT, RIGHTLEFT}; - enum ColumnDirection { TOPBOTTOM, BOTTOMTOP}; typedef std::vector<FluxboxWindow *> Icons;

@@ -218,10 +211,7 @@

/// hide all windowmenus except the given one (if given) void hideWindowMenus(const FluxboxWindow* except= 0); - inline PlacementPolicy getPlacementPolicy() const { return *resource.placement_policy; } inline int getEdgeSnapThreshold() const { return *resource.edge_snap_threshold; } - inline RowDirection getRowPlacementDirection() const { return *resource.row_direction; } - inline ColumnDirection getColPlacementDirection() const { return *resource.col_direction; } void setRootColormapInstalled(bool r) { root_colormap_installed = r; } void saveRootCommand(std::string rootcmd) { *resource.rootcommand = rootcmd; }

@@ -249,7 +239,9 @@ const std::string &name() const { return m_name; }

const std::string &altName() const { return m_altname; } bool isShuttingdown() const { return m_shutdown; } - + PlacementStrategy &placementStrategy() { return *m_placement_strategy; } + const PlacementStrategy &placementStrategy() const { return *m_placement_strategy; } + int addWorkspace(); int removeLastWorkspace(); // scroll workspaces

@@ -442,9 +434,7 @@ bool ordered_dither;

FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha, unfocused_alpha, menu_alpha, menu_delay, menu_delay_close; FbTk::Resource<FbTk::MenuTheme::MenuMode> menu_mode; - FbTk::Resource<PlacementPolicy> placement_policy; - FbTk::Resource<RowDirection> row_direction; - FbTk::Resource<ColumnDirection> col_direction; + FbTk::Resource<int> gc_line_width; FbTk::Resource<FbTk::GContext::LineStyle> gc_line_style; FbTk::Resource<FbTk::GContext::JoinStyle> gc_join_style;

@@ -458,6 +448,7 @@ FbTk::ResourceManager &m_resource_manager;

const std::string m_name, m_altname; FocusControl *m_focus_control; + PlacementStrategy *m_placement_strategy; // This is a map of windows to clients for clients that had a left // window set, but that window wasn't present at the time
A src/ScreenPlacement.cc

@@ -0,0 +1,207 @@

+// ScreenPlacement.cc +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#include "ScreenPlacement.hh" + + +#include "RowSmartPlacement.hh" +#include "UnderMousePlacement.hh" +#include "ColSmartPlacement.hh" +#include "CascadePlacement.hh" + +#include "Screen.hh" +#include "Window.hh" + +#include <iostream> +#include <exception> +using std::cerr; +using std::endl; + +ScreenPlacement::ScreenPlacement(BScreen &screen): + m_row_direction(screen.resourceManager(), LEFTRIGHT, + screen.name()+".rowPlacementDirection", + screen.altName()+".RowPlacementDirection"), + m_col_direction(screen.resourceManager(), TOPBOTTOM, + screen.name()+".colPlacementDirection", + screen.altName()+".ColPlacementDirection"), + m_placement_policy(screen.resourceManager(), ROWSMARTPLACEMENT, + screen.name()+".windowPlacement", + screen.altName()+".WindowPlacement"), + m_old_policy(*m_placement_policy), + m_strategy(new RowSmartPlacement()) +{ +} + +bool ScreenPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &win, + int &place_x, int &place_y) { + + // check the resource placement and see if has changed + // and if so update the strategy + if (m_old_policy != *m_placement_policy) { + m_old_policy = *m_placement_policy; + switch (*m_placement_policy) { + case ROWSMARTPLACEMENT: + m_strategy.reset(new RowSmartPlacement()); + break; + case COLSMARTPLACEMENT: + m_strategy.reset(new ColSmartPlacement()); + break; + case CASCADEPLACEMENT: + m_strategy.reset(new CascadePlacement(win.screen())); + break; + case UNDERMOUSEPLACEMENT: + m_strategy.reset(new UnderMousePlacement()); + break; + } + } + + // view (screen + head) constraints + int head = (signed) win.screen().getCurrHead(); + int head_left = (signed) win.screen().maxLeft(head); + int head_right = (signed) win.screen().maxRight(head); + int head_top = (signed) win.screen().maxTop(head); + int head_bot = (signed) win.screen().maxBottom(head); + + // start placement, top left corner + place_x = head_left; + place_y = head_top; + + bool placed = false; + try { + placed = m_strategy->placeWindow(windowlist, + win, + place_x, place_y); + } catch (std::bad_cast cast) { + // This should not happen. + // If for some reason we change the PlacementStrategy in Screen + // from ScreenPlacement to something else then we might get + // bad_cast from some placement strategies. + cerr<<"Failed to place window: "<<cast.what()<<endl; + } + + if (!placed) { + // Create fallback strategy, when we need it the first time + // This strategy must succeed! + if (m_fallback_strategy.get() == 0) + m_fallback_strategy.reset(new CascadePlacement(win.screen())); + + m_fallback_strategy->placeWindow(windowlist, + win, + place_x, place_y); + } + + + + int win_w = win.width() + win.fbWindow().borderWidth()*2, + win_h = win.height() + win.fbWindow().borderWidth()*2; + + + // make sure the window is inside our screen(head) area + if (place_x + win_w > head_right) + place_x = (head_right - win_w) / 2; + if (place_y + win_h > head_bot) + place_y = (head_bot - win_h) / 2; + + return true; +} + + + +////////////////////// Placement Resources +template <> +void FbTk::Resource<ScreenPlacement::PlacementPolicy>::setFromString(const char *str) { + if (strcasecmp("RowSmartPlacement", str) == 0) + *(*this) = ScreenPlacement::ROWSMARTPLACEMENT; + else if (strcasecmp("ColSmartPlacement", str) == 0) + *(*this) = ScreenPlacement::COLSMARTPLACEMENT; + else if (strcasecmp("UnderMousePlacement", str) == 0) + *(*this) = ScreenPlacement::UNDERMOUSEPLACEMENT; + else if (strcasecmp("CascadePlacement", str) == 0) + *(*this) = ScreenPlacement::CASCADEPLACEMENT; + else + setDefaultValue(); +} + +template <> +std::string FbTk::Resource<ScreenPlacement::PlacementPolicy>::getString() const { + switch (*(*this)) { + case ScreenPlacement::ROWSMARTPLACEMENT: + return "RowSmartPlacement"; + case ScreenPlacement::COLSMARTPLACEMENT: + return "ColSmartPlacement"; + case ScreenPlacement::UNDERMOUSEPLACEMENT: + return "UnderMousePlacement"; + case ScreenPlacement::CASCADEPLACEMENT: + return "CascadePlacement"; + } + + return "RowSmartPlacement"; +} + +template <> +void FbTk::Resource<ScreenPlacement::RowDirection>::setFromString(const char *str) { + if (strcasecmp("LeftToRight", str) == 0) + *(*this) = ScreenPlacement::LEFTRIGHT; + else if (strcasecmp("RightToLeft", str) == 0) + *(*this) = ScreenPlacement::RIGHTLEFT; + else + setDefaultValue(); + +} + +template <> +std::string FbTk::Resource<ScreenPlacement::RowDirection>::getString() const { + switch (*(*this)) { + case ScreenPlacement::LEFTRIGHT: + return "LeftToRight"; + case ScreenPlacement::RIGHTLEFT: + return "RightToLeft"; + } + + return "LeftToRight"; +} + + +template <> +void FbTk::Resource<ScreenPlacement::ColumnDirection>::setFromString(const char *str) { + if (strcasecmp("TopToBottom", str) == 0) + *(*this) = ScreenPlacement::TOPBOTTOM; + else if (strcasecmp("BottomToTop", str) == 0) + *(*this) = ScreenPlacement::BOTTOMTOP; + else + setDefaultValue(); + +} + +template <> +std::string FbTk::Resource<ScreenPlacement::ColumnDirection>::getString() const { + switch (*(*this)) { + case ScreenPlacement::TOPBOTTOM: + return "TopToBottom"; + case ScreenPlacement::BOTTOMTOP: + return "BottomToTop"; + } + + return "TopToBottom"; +}
A src/ScreenPlacement.hh

@@ -0,0 +1,77 @@

+// ScreenPlacement.hh +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#ifndef SCREENPLACEMENT_HH +#define SCREENPLACEMENT_HH + +#include "PlacementStrategy.hh" +#include "FbTk/Resource.hh" + +class BScreen; + +/** + * Main class for strategy handling + * This is a bridge between screen and + * the real placement strategy (rowcol, undermouse etc) + * The placeWindow function in this class is guaranteed to succeed. + * It holds a pointer to the real placement strategy which is + * called upon placeWindow, it also holds the placement resources + */ +class ScreenPlacement: public PlacementStrategy { +public: + enum PlacementPolicy { + ROWSMARTPLACEMENT, + COLSMARTPLACEMENT, + CASCADEPLACEMENT, + UNDERMOUSEPLACEMENT + }; + + enum RowDirection { + LEFTRIGHT, ///< from left to right + RIGHTLEFT ///< from right to left + }; + enum ColumnDirection { + TOPBOTTOM, ///< from top to bottom + BOTTOMTOP ///< from bottom to top + }; + + explicit ScreenPlacement(BScreen &screen); + /// placeWindow is guaranteed to succeed, ignore return value + /// @return true + bool placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &window, + int &place_x, int &place_y); + + RowDirection rowDirection() const { return *m_row_direction; } + ColumnDirection colDirection() const { return *m_col_direction; } + +private: + FbTk::Resource<RowDirection> m_row_direction; ///< row direction resource + FbTk::Resource<ColumnDirection> m_col_direction; ///< column direction resource + FbTk::Resource<PlacementPolicy> m_placement_policy; ///< placement policy resource + PlacementPolicy m_old_policy; ///< holds old policy, used to determine if resources has changed + std::auto_ptr<PlacementStrategy> m_strategy; ///< main strategy + std::auto_ptr<PlacementStrategy> m_fallback_strategy; ///< a fallback strategy if the main strategy fails +}; + +#endif // SCREENPLACEMENT_HH
M src/ScreenResources.ccsrc/ScreenResources.cc

@@ -29,82 +29,6 @@ #include "Screen.hh"

#include <string> using namespace std; -template <> -void FbTk::Resource<BScreen::PlacementPolicy>::setFromString(const char *str) { - if (strcasecmp("RowSmartPlacement", str) == 0) - *(*this) = BScreen::ROWSMARTPLACEMENT; - else if (strcasecmp("ColSmartPlacement", str) == 0) - *(*this) = BScreen::COLSMARTPLACEMENT; - else if (strcasecmp("UnderMousePlacement", str) == 0) - *(*this) = BScreen::UNDERMOUSEPLACEMENT; - else if (strcasecmp("CascadePlacement", str) == 0) - *(*this) = BScreen::CASCADEPLACEMENT; - else - setDefaultValue(); -} - -template <> -string FbTk::Resource<BScreen::PlacementPolicy>::getString() const { - switch (*(*this)) { - case BScreen::ROWSMARTPLACEMENT: - return "RowSmartPlacement"; - case BScreen::COLSMARTPLACEMENT: - return "ColSmartPlacement"; - case BScreen::UNDERMOUSEPLACEMENT: - return "UnderMousePlacement"; - case BScreen::CASCADEPLACEMENT: - return "CascadePlacement"; - } - - return "RowSmartPlacement"; -} - -template <> -void FbTk::Resource<BScreen::RowDirection>::setFromString(const char *str) { - if (strcasecmp("LeftToRight", str) == 0) - *(*this) = BScreen::LEFTRIGHT; - else if (strcasecmp("RightToLeft", str) == 0) - *(*this) = BScreen::RIGHTLEFT; - else - setDefaultValue(); - -} - -template <> -string FbTk::Resource<BScreen::RowDirection>::getString() const { - switch (*(*this)) { - case BScreen::LEFTRIGHT: - return "LeftToRight"; - case BScreen::RIGHTLEFT: - return "RightToLeft"; - } - - return "LeftToRight"; -} - - -template <> -void FbTk::Resource<BScreen::ColumnDirection>::setFromString(const char *str) { - if (strcasecmp("TopToBottom", str) == 0) - *(*this) = BScreen::TOPBOTTOM; - else if (strcasecmp("BottomToTop", str) == 0) - *(*this) = BScreen::BOTTOMTOP; - else - setDefaultValue(); - -} - -template <> -string FbTk::Resource<BScreen::ColumnDirection>::getString() const { - switch (*(*this)) { - case BScreen::TOPBOTTOM: - return "TopToBottom"; - case BScreen::BOTTOMTOP: - return "BottomToTop"; - } - - return "TopToBottom"; -} template <> string FbTk::Resource<FbTk::MenuTheme::MenuMode>::getString() const {
A src/UnderMousePlacement.cc

@@ -0,0 +1,75 @@

+// UnderMousePlacement.cc +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#include "UnderMousePlacement.hh" + +#include "FbTk/App.hh" +#include "Screen.hh" +#include "Window.hh" + +bool UnderMousePlacement::placeWindow(const std::vector<FluxboxWindow *> &list, + const FluxboxWindow &win, + int &place_x, int &place_y) { + + int root_x, root_y, ignore_i; + + unsigned int ignore_ui; + + Window ignore_w; + + XQueryPointer(FbTk::App::instance()->display(), + win.screen().rootWindow().window(), &ignore_w, + &ignore_w, &root_x, &root_y, + &ignore_i, &ignore_i, &ignore_ui); + + // 2*border = border on each side of the screen + int win_w = win.width() + win.fbWindow().borderWidth()*2, + win_h = win.height() + win.fbWindow().borderWidth()*2; + + int test_x = root_x - (win_w / 2); + int test_y = root_y - (win_h / 2); + + // keep the window inside the screen + int head = (signed) win.screen().getCurrHead(); + int head_left = (signed) win.screen().maxLeft(head); + int head_right = (signed) win.screen().maxRight(head); + int head_top = (signed) win.screen().maxTop(head); + int head_bot = (signed) win.screen().maxBottom(head); + + if (test_x < head_left) + test_x = head_left; + + if (test_x + win_w > head_right) + test_x = head_right - win_w; + + if (test_y < head_top) + test_y = head_top; + + if (test_y + win_h > head_bot) + test_y = head_bot - win_h; + + place_x = test_x; + place_y = test_y; + + return true; +}
A src/UnderMousePlacement.hh

@@ -0,0 +1,36 @@

+// UnderMousePlacement.hh +// Copyright (c) 2006 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id$ + +#ifndef UNDERMOUSEPLACEMENT_HH +#define UNDERMOUSEPLACEMENT_HH + +#include "PlacementStrategy.hh" + +class UnderMousePlacement: public PlacementStrategy { +public: + bool placeWindow(const std::vector<FluxboxWindow *> &windowlist, + const FluxboxWindow &win, + int &place_x, int &place_y); +}; + +#endif // UNDERMOUSEPLACEMENT_HH
M src/Workspace.ccsrc/Workspace.cc

@@ -33,6 +33,7 @@ #include "WinClient.hh"

#include "FbWinFrame.hh" #include "WindowCmd.hh" #include "FocusControl.hh" +#include "PlacementStrategy.hh" #include "FbTk/I18n.hh" #include "FbTk/MenuItem.hh"

@@ -140,21 +141,13 @@ m_layermanager(layermanager),

m_name(name), m_id(id) { - - m_cascade_x = new int[scrn.numHeads() + 1]; - m_cascade_y = new int[scrn.numHeads() + 1]; - for (int i=0; i < scrn.numHeads()+1; i++) { - m_cascade_x[i] = 32 + scrn.getHeadX(i); - m_cascade_y[i] = 32 + scrn.getHeadY(i); - } menu().setInternalMenu(); setName(name); + } Workspace::~Workspace() { - delete [] m_cascade_x; - delete [] m_cascade_y; } void Workspace::setLastFocusedWindow(FluxboxWindow *win) {

@@ -427,268 +420,12 @@ menu().updateMenu();

} void Workspace::placeWindow(FluxboxWindow &win) { - - bool placed = false; - - // restrictions - int head = (signed) screen().getCurrHead(); - int head_left = (signed) screen().maxLeft(head); - int head_right = (signed) screen().maxRight(head); - int head_top = (signed) screen().maxTop(head); - int head_bot = (signed) screen().maxBottom(head); - - int place_x = head_left, place_y = head_top, change_x = 1, change_y = 1; - - if (screen().getColPlacementDirection() == BScreen::BOTTOMTOP) - change_y = -1; - if (screen().getRowPlacementDirection() == BScreen::RIGHTLEFT) - change_x = -1; - - int win_w = win.width() + win.fbWindow().borderWidth()*2, - win_h = win.height() + win.fbWindow().borderWidth()*2; - - - int test_x, test_y, curr_x, curr_y, curr_w, curr_h; - - switch (screen().getPlacementPolicy()) { - case BScreen::UNDERMOUSEPLACEMENT: { - int root_x, root_y, ignore_i; - - unsigned int ignore_ui; - - Window ignore_w; - - XQueryPointer(FbTk::App::instance()->display(), - screen().rootWindow().window(), &ignore_w, - &ignore_w, &root_x, &root_y, - &ignore_i, &ignore_i, &ignore_ui); - - test_x = root_x - (win_w / 2); - test_y = root_y - (win_h / 2); - - // keep the window inside the screen - - if (test_x < head_left) - test_x = head_left; - - if (test_x + win_w > head_right) - test_x = head_right - win_w; - - if (test_y < head_top) - test_y = head_top; - - if (test_y + win_h > head_bot) - test_y = head_bot - win_h; - - place_x = test_x; - place_y = test_y; - - placed = true; - - break; - } // end case UNDERMOUSEPLACEMENT - - case BScreen::ROWSMARTPLACEMENT: { - int next_x, next_y; - bool top_bot = screen().getColPlacementDirection() == BScreen::TOPBOTTOM; - bool left_right = screen().getRowPlacementDirection() == BScreen::LEFTRIGHT; - - if (top_bot) - test_y = head_top; - else - test_y = head_bot - win_h; - - while (!placed && - (top_bot ? test_y + win_h <= head_bot - : test_y >= head_top)) { - - if (left_right) - test_x = head_left; - else - test_x = head_right - win_w; - - // The trick here is that we set it to the furthest away one, - // then the code brings it back down to the safest one that - // we can go to (i.e. the next untested area) - if (top_bot) - next_y = head_bot; // will be shrunk - else - next_y = head_top-1; - - while (!placed && - (left_right ? test_x + win_w <= head_right - : test_x >= head_left)) { - - placed = true; - - next_x = test_x + change_x; - - Windows::iterator win_it = m_windowlist.begin(); - const Windows::iterator win_it_end = m_windowlist.end(); - - for (; win_it != win_it_end && placed; ++win_it) { - FluxboxWindow &window = **win_it; - - curr_x = window.x(); - curr_y = window.y(); - curr_w = window.width() + window.fbWindow().borderWidth()*2; - curr_h = window.height() + window.fbWindow().borderWidth()*2; - - if (curr_x < test_x + win_w && - curr_x + curr_w > test_x && - curr_y < test_y + win_h && - curr_y + curr_h > test_y) { - // this window is in the way - placed = false; - - // we find the next x that we can go to (a window will be in the way - // all the way to its far side) - if (left_right) { - if (curr_x + curr_w > next_x) - next_x = curr_x + curr_w; - } else { - if (curr_x - win_w < next_x) - next_x = curr_x - win_w; - } - - // but we can only go to the nearest y, since that is where the - // next time current windows in the way will change - if (top_bot) { - if (curr_y + curr_h < next_y) - next_y = curr_y + curr_h; - } else { - if (curr_y - win_h > next_y) - next_y = curr_y - win_h; - } - } - } - - - if (placed) { - place_x = test_x; - place_y = test_y; - - break; - } - - test_x = next_x; - } // end while - - test_y = next_y; - } // end while - - break; - } // end case ROWSMARTPLACEMENT - - case BScreen::COLSMARTPLACEMENT: { - int next_x, next_y; - bool top_bot = screen().getColPlacementDirection() == BScreen::TOPBOTTOM; - bool left_right = screen().getRowPlacementDirection() == BScreen::LEFTRIGHT; - - if (left_right) - test_x = head_left; - else - test_x = head_right - win_w; - - while (!placed && - (left_right ? test_x + win_w <= head_right - : test_x >= head_left)) { - - if (left_right) - next_x = head_right; // it will get shrunk - else - next_x = head_left-1; - - if (top_bot) - test_y = head_top; - else - test_y = head_bot - win_h; - - while (!placed && - (top_bot ? test_y + win_h <= head_bot - : test_y >= head_top)) { - placed = True; - - next_y = test_y + change_y; - - Windows::iterator it = m_windowlist.begin(); - Windows::iterator it_end = m_windowlist.end(); - for (; it != it_end && placed; ++it) { - curr_x = (*it)->x(); - curr_y = (*it)->y(); - curr_w = (*it)->width() + (*it)->fbWindow().borderWidth()*2; - curr_h = (*it)->height() + (*it)->fbWindow().borderWidth()*2; - - if (curr_x < test_x + win_w && - curr_x + curr_w > test_x && - curr_y < test_y + win_h && - curr_y + curr_h > test_y) { - // this window is in the way - placed = False; - - // we find the next y that we can go to (a window will be in the way - // all the way to its bottom) - if (top_bot) { - if (curr_y + curr_h > next_y) - next_y = curr_y + curr_h; - } else { - if (curr_y - win_h < next_y) - next_y = curr_y - win_h; - } - - // but we can only go to the nearest x, since that is where the - // next time current windows in the way will change - if (left_right) { - if (curr_x + curr_w < next_x) - next_x = curr_x + curr_w; - } else { - if (curr_x - win_w > next_x) - next_x = curr_x - win_w; - } - } - } - - if (placed) { - place_x = test_x; - place_y = test_y; - } - - test_y = next_y; - } // end while - - test_x = next_x; - } // end while - - break; - } // end COLSMARTPLACEMENT - - } - - // cascade placement or smart placement failed - if (! placed) { - - if ((m_cascade_x[head] > ((head_left + head_right) / 2)) || - (m_cascade_y[head] > ((head_top + head_bot) / 2))) { - m_cascade_x[head] = head_left + 32; - m_cascade_y[head] = head_top + 32; - } - - place_x = m_cascade_x[head]; - place_y = m_cascade_y[head]; - - // just one borderwidth, so they can share a borderwidth (looks better) - int titlebar_height = win.titlebarHeight() + win.fbWindow().borderWidth(); - if (titlebar_height < 4) // make sure it is not insignificant - titlebar_height = 32; - m_cascade_x[head] += titlebar_height; - m_cascade_y[head] += titlebar_height; - } - - if (place_x + win_w > head_right) - place_x = (head_right - win_w) / 2; - if (place_y + win_h > head_bot) - place_y = (head_bot - win_h) / 2; - + int place_x, place_y; + // we ignore the return value, + // the screen placement strategy is guaranteed to succeed. + screen().placementStrategy().placeWindow(m_windowlist, + win, + place_x, place_y); win.moveResize(place_x, place_y, win.width(), win.height()); }