all repos — openbox @ e18ff901fc7236e3008266f0a09048e6905de724

openbox fork - make it a bit more like ryudo

xinerama support for window placement
Dana Jansens danakj@orodu.net
commit

e18ff901fc7236e3008266f0a09048e6905de724

parent

6ea8fb9afa1df8415fe88198525254c59a01230e

M src/Screen.ccsrc/Screen.cc

@@ -2074,16 +2074,12 @@ return usableArea;

} -RectList BScreen::allAvailableAreas(void) const { #ifdef XINERAMA - if (isXineramaActive()) - return xineramaUsableArea; -#endif // XINERAMA - - RectList list; - list.push_back(availableArea()); - return list; +RectList BScreen::allAvailableAreas(void) const { + assert(isXineramaActive()); + return xineramaUsableArea; } +#endif // XINERAMA void BScreen::updateAvailableArea(void) {
M src/Screen.hhsrc/Screen.hh

@@ -312,7 +312,9 @@

// allAvailableAreas should be used whenever possible instead of this function // as then Xinerama will work correctly. const Rect& availableArea(void) const; +#ifdef XINERAMA RectList allAvailableAreas(void) const; +#endif // XINERAMA void updateAvailableArea(void); void addStrut(Strut *strut); void removeStrut(Strut *strut);
M src/Util.ccsrc/Util.cc

@@ -141,6 +141,18 @@ std::max(_y1, a._y1) <= std::min(_y2, a._y2);

} +bool Rect::contains(int __x, int __y) const { + return __x >= _x1 && __x <= _x2 && + __y >= _y1 && __y <= _y2; +} + + +bool Rect::contains(const Rect& a) const { + return a._x1 >= _x1 && a._x2 <= _x2 && + a._y1 >= _y1 && a._y2 <= _y2; +} + + string expandTilde(const string& s) { if (s[0] != '~') return s;
M src/Util.hhsrc/Util.hh

@@ -72,6 +72,8 @@

inline bool valid(void) const { return _x2 > _x1 && _y2 > _y1; } bool intersects(const Rect &a) const; + bool contains(int __x, int __y) const; + bool contains(const Rect &a) const; private: int _x1, _y1, _x2, _y2;
M src/Workspace.ccsrc/Workspace.cc

@@ -584,9 +584,22 @@ return first.right() > second.right();

} -bool Workspace::smartPlacement(Rect& win, const Rect& availableArea) { +bool Workspace::smartPlacement(Rect& win) { rectList spaces; - spaces.push_back(availableArea); //initially the entire screen is free + + //initially the entire screen is free +#ifdef XINERAMA + if (screen->isXineramaActive() && + screen->getBlackbox()->doXineramaPlacement()) { + RectList availableAreas = screen->allAvailableAreas(); + assert(availableAreas.size() > 0); + RectList::iterator it, end = availableAreas.end(); + + for (it = availableAreas.begin(); it != end; ++it) + spaces.push_back(*it); + } else +#endif // XINERAMA + spaces.push_back(screen->availableArea()); //Find Free Spaces BlackboxWindowList::const_iterator wit = windowList.begin(),

@@ -661,23 +674,40 @@ return True;

} -bool Workspace::underMousePlacement(Rect &win, const Rect &availableArea) { +bool Workspace::underMousePlacement(Rect &win) { int x, y, rx, ry; Window c, r; unsigned int m; XQueryPointer(screen->getBlackbox()->getXDisplay(), screen->getRootWindow(), &r, &c, &rx, &ry, &x, &y, &m); + + Rect area; +#ifdef XINERAMA + if (screen->isXineramaActive() && + screen->getBlackbox()->doXineramaPlacement()) { + RectList availableAreas = screen->allAvailableAreas(); + assert(availableAreas.size() > 0); + RectList::iterator it, end = availableAreas.end(); + + for (it = availableAreas.begin(); it != end; ++it) + if (it->contains(rx, ry)) break; + assert(it != end); // the mouse isn't inside an area? + area = *it; + } else +#endif // XINERAMA + area = screen->availableArea(); + x = rx - win.width() / 2; y = ry - win.height() / 2; - if (x < availableArea.x()) - x = availableArea.x(); - if (y < availableArea.y()) - y = availableArea.y(); - if (x + win.width() > availableArea.x() + availableArea.width()) - x = availableArea.x() + availableArea.width() - win.width(); - if (y + win.height() > availableArea.y() + availableArea.height()) - y = availableArea.y() + availableArea.height() - win.height(); + if (x < area.x()) + x = area.x(); + if (y < area.y()) + y = area.y(); + if (x + win.width() > area.x() + area.width()) + x = area.x() + area.width() - win.width(); + if (y + win.height() > area.y() + area.height()) + y = area.y() + area.height() - win.height(); win.setX(x); win.setY(y);

@@ -686,7 +716,9 @@ return True;

} -bool Workspace::cascadePlacement(Rect &win, const Rect &availableArea) { +bool Workspace::cascadePlacement(Rect &win) { + const Rect &availableArea = screen->availableArea(); + if ((cascade_x > static_cast<signed>(availableArea.width() / 2)) || (cascade_y > static_cast<signed>(availableArea.height() / 2))) cascade_x = cascade_y = 32;

@@ -703,32 +735,29 @@ }

void Workspace::placeWindow(BlackboxWindow *win) { - Rect availableArea(screen->availableArea()), - new_win(availableArea.x(), availableArea.y(), - win->frameRect().width(), win->frameRect().height()); + Rect new_win(0, 0, win->frameRect().width(), win->frameRect().height()); bool placed = False; switch (screen->getPlacementPolicy()) { case BScreen::RowSmartPlacement: case BScreen::ColSmartPlacement: - placed = smartPlacement(new_win, availableArea); + placed = smartPlacement(new_win); break; case BScreen::UnderMousePlacement: case BScreen::ClickMousePlacement: - placed = underMousePlacement(new_win, availableArea); + placed = underMousePlacement(new_win); default: break; // handled below } // switch if (placed == False) { - cascadePlacement(new_win, availableArea); + cascadePlacement(new_win); cascade_x += win->getTitleHeight() + (screen->getBorderWidth() * 2); cascade_y += win->getTitleHeight() + (screen->getBorderWidth() * 2); } - if (new_win.right() > availableArea.right()) - new_win.setX(availableArea.left()); - if (new_win.bottom() > availableArea.bottom()) - new_win.setY(availableArea.top()); + // make sure the placement was valid + assert(screen->availableArea().contains(new_win)); + win->configure(new_win.x(), new_win.y(), new_win.width(), new_win.height()); }
M src/Workspace.hhsrc/Workspace.hh

@@ -63,9 +63,9 @@ void lowerTransients(const BlackboxWindow * const win,

StackVector::iterator &stack); void placeWindow(BlackboxWindow *win); - bool cascadePlacement(Rect& win, const Rect& availableArea); - bool smartPlacement(Rect& win, const Rect& availableArea); - bool underMousePlacement(Rect& win, const Rect& availableArea); + bool cascadePlacement(Rect& win); + bool smartPlacement(Rect& win); + bool underMousePlacement(Rect& win); public: Workspace(BScreen *scrn, unsigned int i = 0);
M src/blackbox.ccsrc/blackbox.cc

@@ -1164,6 +1164,32 @@ XSync(getXDisplay(), False);

} +#ifdef XINERAMA +void Blackbox::saveXineramaPlacement(bool x) { + resource.xinerama_placement = x; + config.setValue("session.xineramaSupport.windowPlacement", + resource.xinerama_placement); + reconfigure(); // make sure all screens get this change +} + + +void Blackbox::saveXineramaMaximizing(bool x) { + resource.xinerama_maximize = x; + config.setValue("session.xineramaSupport.windowMaximizing", + resource.xinerama_maximize); + reconfigure(); // make sure all screens get this change +} + + +void Blackbox::saveXineramaSnapping(bool x) { + resource.xinerama_snap = x; + config.setValue("session.xineramaSupport.windowSnapping", + resource.xinerama_snap); + reconfigure(); // make sure all screens get this change +} +#endif // XINERAMA + + /* * Save all values as they are so that the defaults will be written to the rc * file

@@ -1182,6 +1208,12 @@ config.setValue("session.cacheMax", resource.cache_max);

config.setValue("session.styleFile", resource.style_file); config.setValue("session.titlebarLayout", resource.titlebar_layout); +#ifdef XINERAMA + saveXineramaPlacement(resource.xinerama_placement); + saveXineramaMaximizing(resource.xinerama_maximize); + saveXineramaSnapping(resource.xinerama_snap); +#endif // XINERAMA + std::for_each(screenList.begin(), screenList.end(), std::mem_fun(&BScreen::save_rc));

@@ -1228,10 +1260,28 @@ resource.cache_max = 200;

if (! config.getValue("session.titlebarLayout", resource.titlebar_layout)) resource.titlebar_layout = "ILMC"; + +#ifdef XINERAMA + if (! config.getValue("session.xineramaSupport.windowPlacement", + resource.xinerama_placement)) + resource.xinerama_placement = true; + + if (! config.getValue("session.xineramaSupport.windowMaximizing", + resource.xinerama_maximize)) + resource.xinerama_maximize = true; + + if (! config.getValue("session.xineramaSupport.windowSnapping", + resource.xinerama_snap)) + resource.xinerama_snap = true; +#endif // XINERAMA } void Blackbox::reconfigure(void) { + // don't reconfigure while saving the initial rc file, it's a waste and it + // breaks somethings (workspace names) + if (isStartup()) return; + reconfigure_wait = True; if (! timer->isTiming()) timer->start();
M src/blackbox.hhsrc/blackbox.hh

@@ -115,6 +115,10 @@ int colors_per_channel;

timeval auto_raise_delay; unsigned long cache_life, cache_max; std::string titlebar_layout; + +#ifdef XINERAMA + bool xinerama_placement, xinerama_maximize, xinerama_snap; +#endif // XINERAMA } resource; typedef std::map<Window, BlackboxWindow*> WindowLookup;

@@ -181,6 +185,19 @@ BScreen *searchScreen(Window window);

Toolbar *searchToolbar(Window); Slit *searchSlit(Window); +#ifdef XINERAMA + inline bool doXineramaPlacement(void) const + { return resource.xinerama_placement; } + inline bool doXineramaMaximizing(void) const + { return resource.xinerama_maximize; } + inline bool doXineramaSnapping(void) const + { return resource.xinerama_snap; } + + void saveXineramaPlacement(bool x); + void saveXineramaMaximizing(bool x); + void saveXineramaSnapping(bool x); +#endif // XINERAMA + void saveMenuSearch(Window window, Basemenu *data); void saveSystrayWindowSearch(Window window, BScreen *screen); void saveWindowSearch(Window window, BlackboxWindow *data);