From e18ff901fc7236e3008266f0a09048e6905de724 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 22 Jul 2002 04:29:40 +0000 Subject: [PATCH] xinerama support for window placement --- src/Screen.cc | 12 +++----- src/Screen.hh | 2 ++ src/Util.cc | 12 ++++++++ src/Util.hh | 2 ++ src/Workspace.cc | 73 +++++++++++++++++++++++++++++++++--------------- src/Workspace.hh | 6 ++-- src/blackbox.cc | 50 +++++++++++++++++++++++++++++++++ src/blackbox.hh | 17 +++++++++++ 8 files changed, 141 insertions(+), 33 deletions(-) diff --git a/src/Screen.cc b/src/Screen.cc index 60cd8e09..fc6979d8 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -2074,16 +2074,12 @@ const Rect& BScreen::availableArea(void) const { } -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) { diff --git a/src/Screen.hh b/src/Screen.hh index 06548d41..87d11c68 100644 --- a/src/Screen.hh +++ b/src/Screen.hh @@ -312,7 +312,9 @@ public: // 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); diff --git a/src/Util.cc b/src/Util.cc index 1b521aaf..d8083444 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -141,6 +141,18 @@ bool Rect::intersects(const Rect &a) const { } +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; diff --git a/src/Util.hh b/src/Util.hh index d70eabc8..46d8f339 100644 --- a/src/Util.hh +++ b/src/Util.hh @@ -72,6 +72,8 @@ public: 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; diff --git a/src/Workspace.cc b/src/Workspace.cc index 0a95c24f..8a62d1b0 100644 --- a/src/Workspace.cc +++ b/src/Workspace.cc @@ -584,9 +584,22 @@ static bool colRLBT(const Rect &first, const Rect &second) { } -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 @@ bool Workspace::smartPlacement(Rect& win, const Rect& availableArea) { } -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 @@ bool Workspace::underMousePlacement(Rect &win, const Rect &availableArea) { } -bool Workspace::cascadePlacement(Rect &win, const Rect &availableArea) { +bool Workspace::cascadePlacement(Rect &win) { + const Rect &availableArea = screen->availableArea(); + if ((cascade_x > static_cast(availableArea.width() / 2)) || (cascade_y > static_cast(availableArea.height() / 2))) cascade_x = cascade_y = 32; @@ -703,32 +735,29 @@ bool Workspace::cascadePlacement(Rect &win, const Rect &availableArea) { 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()); } diff --git a/src/Workspace.hh b/src/Workspace.hh index 09dc2779..18933acc 100644 --- a/src/Workspace.hh +++ b/src/Workspace.hh @@ -63,9 +63,9 @@ private: 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); diff --git a/src/blackbox.cc b/src/blackbox.cc index 8dc7db83..d30c01ed 100644 --- a/src/blackbox.cc +++ b/src/blackbox.cc @@ -1164,6 +1164,32 @@ void Blackbox::shutdown(void) { } +#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 @@ void Blackbox::save_rc(void) { 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 @@ void Blackbox::load_rc(void) { 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(); diff --git a/src/blackbox.hh b/src/blackbox.hh index a6e689d7..6a6a22d1 100644 --- a/src/blackbox.hh +++ b/src/blackbox.hh @@ -115,6 +115,10 @@ private: 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 WindowLookup; @@ -181,6 +185,19 @@ public: 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); -- 2.45.2