From 12108e16e166034cd1840627502280d9a1ab0b9e Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 10 Feb 2003 06:50:19 +0000 Subject: [PATCH] keep track of struts for each desktop --- scripts/motion.py | 2 +- scripts/windowplacement.py | 4 +- src/actions.cc | 5 +- src/actions.hh | 1 + src/client.cc | 19 ++++-- src/client.hh | 4 ++ src/screen.cc | 124 ++++++++++++++++++++++++------------- src/screen.hh | 26 +++++--- 8 files changed, 123 insertions(+), 62 deletions(-) diff --git a/scripts/motion.py b/scripts/motion.py index 2d6939c5..e0a1d352 100644 --- a/scripts/motion.py +++ b/scripts/motion.py @@ -106,7 +106,7 @@ def _do_move(): w = _client.area().width() + fs.left + fs.right h = _client.area().height() + fs.top + fs.bottom # use the area based on the struts - area = ob.openbox.screen(_screen).area() + area = ob.openbox.screen(_screen).area(_client.desktop()) l = area.left() r = area.right() - w + 1 t = area.top() diff --git a/scripts/windowplacement.py b/scripts/windowplacement.py index e7ba187d..a319c7b1 100644 --- a/scripts/windowplacement.py +++ b/scripts/windowplacement.py @@ -25,7 +25,7 @@ def random(data): if data.client.positionRequested(): return client_area = data.client.area() frame_size = data.client.frame.size() - screen_area = ob.openbox.screen(data.screen).area() + screen_area = ob.openbox.screen(data.screen).area(data.client.desktop()) width = screen_area.width() - (client_area.width() + frame_size.left + frame_size.right) height = screen_area.height() - (client_area.height() + @@ -44,7 +44,7 @@ def cascade(data): if data.client.positionRequested(): return client_area = data.client.area() frame_size = data.client.frame.size() - screen_area = ob.openbox.screen(data.screen).area() + screen_area = ob.openbox.screen(data.screen).area(data.client.desktop()) width = screen_area.width() - (client_area.width() + frame_size.left + frame_size.right) height = screen_area.height() - (client_area.height() + diff --git a/src/actions.cc b/src/actions.cc index 3eb29215..3a7ff369 100644 --- a/src/actions.cc +++ b/src/actions.cc @@ -42,6 +42,7 @@ void Actions::insertPress(const XButtonEvent &e) _posqueue[i] = _posqueue[i-1]; } _posqueue[0] = a; + a->win = e.window; a->button = e.button; a->pos = otk::Point(e.x_root, e.y_root); @@ -274,6 +275,8 @@ void Actions::motionHandler(const XMotionEvent &e) if (!e.same_screen) return; // this just gets stupid + if (e.window != _posqueue[0]->win) return; + MouseContext::MC context; EventHandler *h = openbox->findHandler(e.window); Frame *f = dynamic_cast(h); @@ -287,7 +290,7 @@ void Actions::motionHandler(const XMotionEvent &e) return; // not a valid mouse context int x_root = e.x_root, y_root = e.y_root; - + // compress changes to a window into a single change XEvent ce; while (XCheckTypedWindowEvent(**otk::display, e.window, e.type, &ce)) { diff --git a/src/actions.hh b/src/actions.hh index f18696a1..c2de2b68 100644 --- a/src/actions.hh +++ b/src/actions.hh @@ -35,6 +35,7 @@ public: }; struct ButtonPressAction { + Window win; unsigned int button; otk::Point pos; otk::Rect clientarea; diff --git a/src/client.cc b/src/client.cc index 091b095e..b495a71c 100644 --- a/src/client.cc +++ b/src/client.cc @@ -45,7 +45,7 @@ Client::Client(int screen, Window window) _positioned = false; _disabled_decorations = 0; _group = None; - _desktop = 0; + _desktop = _old_desktop = 0; getArea(); getDesktop(); @@ -638,7 +638,7 @@ void Client::updateStrut() // updating here is pointless while we're being mapped cuz we're not in // the screen's client list yet if (frame) - openbox->screen(_screen)->updateStrut(); + openbox->screen(_screen)->updateStruts(); } delete [] data; @@ -748,7 +748,8 @@ void Client::setDesktop(long target) if (!(target >= 0 || target == (signed)0xffffffff || target == ICONIC_DESKTOP)) return; - + + _old_desktop = _desktop; _desktop = target; // set the desktop hint, but not if we're iconifying @@ -781,8 +782,10 @@ void Client::setDesktop(long target) } changeState(); } - + + changeAllowedActions(); frame->adjustState(); + openbox->screen(_screen)->updateStruts(); } @@ -1301,6 +1304,7 @@ void Client::changeAllowedActions(void) void Client::remaximize() { + printf("REMAXIMIZE!!!!!!!!!!!!!!!!!!!\n"); int dir; if (_max_horz && _max_vert) dir = 0; @@ -1391,7 +1395,8 @@ void Client::maximize(bool max, int dir, bool savearea) if (dir == 2 && !_max_vert) return; } - const otk::Rect &a = openbox->screen(_screen)->area(); + const otk::Rect &a = openbox->screen(_screen)->area(_iconic ? + _old_desktop : _desktop); int x = frame->area().x(), y = frame->area().y(), w = _area.width(), h = _area.height(); @@ -1536,7 +1541,9 @@ void Client::fullscreen(bool fs, bool savearea) delete dimensions; } else { // pick some fallbacks... - const otk::Rect &a = openbox->screen(_screen)->area(); + const otk::Rect &a = openbox->screen(_screen)->area(_iconic ? + _old_desktop : + _desktop); x = a.x() + a.width() / 4; y = a.y() + a.height() / 4; w = a.width() / 2; diff --git a/src/client.hh b/src/client.hh index b7efefa2..0505c361 100644 --- a/src/client.hh +++ b/src/client.hh @@ -190,6 +190,10 @@ private: //! The desktop on which the window resides (0xffffffff for all desktops) long _desktop; + //! The last desktop to which the window belonged, mostly useful when the + //! window is iconified, to see where it used to be. + long _old_desktop; + //! Normal window title otk::ustring _title; //! Window title when iconifiged diff --git a/src/screen.cc b/src/screen.cc index 2c49c6cc..081b68d1 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -122,7 +122,6 @@ Screen::Screen(int screen) // these may be further updated if any pre-existing windows are found in // the manageExising() function changeClientList(); // initialize the client lists, which will be empty - calcArea(); // initialize the available working area // register this class as the event handler for the root window openbox->registerHandler(_info->rootWindow(), this); @@ -200,26 +199,48 @@ void Screen::manageExisting() } -void Screen::updateStrut() +void Screen::updateStruts() { - _strut.left = _strut.right = _strut.top = _strut.bottom = 0; + struct ApplyStrut { + void operator()(otk::Strut &self, const otk::Strut &other) { + self.left = std::max(self.left, other.left); + self.right = std::max(self.right, other.right); + self.top = std::max(self.top, other.top); + self.bottom = std::max(self.bottom, other.bottom); + } + } apply; - ClientList::iterator it, end = clients.end(); + StrutList::iterator sit, send = _struts.end(); + // reset them all + for (sit = _struts.begin(); sit != send; ++sit) + sit->left = sit->right = sit->top = sit->bottom = 0; + + ClientList::const_iterator it, end = clients.end(); for (it = clients.begin(); it != end; ++it) { + long desk = (*it)->desktop(); const otk::Strut &s = (*it)->strut(); - _strut.left = std::max(_strut.left, s.left); - _strut.right = std::max(_strut.right, s.right); - _strut.top = std::max(_strut.top, s.top); - _strut.bottom = std::max(_strut.bottom, s.bottom); + + if (desk == (signed) 0xffffffff) + for (unsigned int i = 0, e = _struts.size(); i < e; ++i) + apply(_struts[i], s); + else if ((unsigned)desk < _struts.size()) + apply(_struts[desk], s); + else if (desk == Client::ICONIC_DESKTOP) + continue; // skip for the 'all desktops' strut + else + assert(false); // invalid desktop otherwise.. + // apply to the 'all desktops' strut + apply(_struts.back(), s); } - calcArea(); + changeWorkArea(); } -void Screen::calcArea() +void Screen::changeWorkArea() { - otk::Rect old_area = _area; - + unsigned long *dims = new unsigned long[4 * _num_desktops]; + for (long i = 0; i < _num_desktops + 1; ++i) { + otk::Rect old_area = _area[i]; /* #ifdef XINERAMA // reset to the full areas @@ -228,10 +249,12 @@ void Screen::calcArea() #endif // XINERAMA */ - _area = otk::Rect(_strut.left, _strut.top, - _info->size().width() - (_strut.left + _strut.right), - _info->size().height() - (_strut.top + _strut.bottom)); - + _area[i] = otk::Rect(_struts[i].left, _struts[i].top, + _info->size().width() - (_struts[i].left + + _struts[i].right), + _info->size().height() - (_struts[i].top + + _struts[i].bottom)); + /* #ifdef XINERAMA if (isXineramaActive()) { @@ -254,15 +277,31 @@ void Screen::calcArea() } #endif // XINERAMA */ - - if (old_area != _area) { - // the area has changed, adjust all the maximized windows - ClientList::iterator it, end = clients.end(); - for (it = clients.begin(); it != end; ++it) - (*it)->remaximize(); - } + if (old_area != _area[i]) { + // the area has changed, adjust all the maximized windows + ClientList::iterator it, end = clients.end(); + for (it = clients.begin(); it != end; ++it) + if (i < _num_desktops) { + if ((*it)->desktop() == i) + (*it)->remaximize(); + } else { + // the 'all desktops' size + if ((*it)->desktop() == (signed) 0xffffffff) + (*it)->remaximize(); + } + } - changeWorkArea(); + // don't set these for the 'all desktops' area + if (i < _num_desktops) { + dims[(i * 4) + 0] = _area[i].x(); + dims[(i * 4) + 1] = _area[i].y(); + dims[(i * 4) + 2] = _area[i].width(); + dims[(i * 4) + 3] = _area[i].height(); + } + } + otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_workarea, + otk::Property::atoms.cardinal, dims, 4 * _num_desktops); + delete [] dims; } @@ -411,20 +450,6 @@ void Screen::changeStackingList() } -void Screen::changeWorkArea() { - unsigned long *dims = new unsigned long[4 * _num_desktops]; - for (long i = 0; i < _num_desktops; ++i) { - dims[(i * 4) + 0] = _area.x(); - dims[(i * 4) + 1] = _area.y(); - dims[(i * 4) + 2] = _area.width(); - dims[(i * 4) + 3] = _area.height(); - } - otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_workarea, - otk::Property::atoms.cardinal, dims, 4 * _num_desktops); - delete [] dims; -} - - void Screen::manageWindow(Window window) { Client *client = 0; @@ -526,7 +551,7 @@ void Screen::manageWindow(Window window) clients.push_back(client); // once the client is in the list, update our strut to include the new // client's (it is good that this happens after window placement!) - updateStrut(); + updateStruts(); // this puts into the stacking order, then raises it _stacking.push_back(client); raiseWindow(client); @@ -592,7 +617,7 @@ void Screen::unmanageWindow(Client *client) // once the client is out of the list, update our strut to remove it's // influence - updateStrut(); + updateStruts(); // unset modal before dropping our focus client->_modal = false; @@ -750,12 +775,14 @@ void Screen::changeNumDesktops(long num) viewport, _num_desktops * 2); delete [] viewport; - // update the work area hint - changeWorkArea(); + // change our struts/area to match + _area.resize(_num_desktops + 1); + _struts.resize(_num_desktops + 1); + updateStruts(); // change our desktop if we're on one that no longer exists! - if (_desktop >= num) - changeDesktop(num - 1); + if (_desktop >= _num_desktops) + changeDesktop(_num_desktops - 1); } @@ -786,6 +813,15 @@ void Screen::setDesktopName(long i, const otk::ustring &name) } +const otk::Rect& Screen::area(long desktop) const { + assert(desktop >= 0 || desktop == (signed) 0xffffffff); + assert(desktop < _num_desktops || desktop == (signed) 0xffffffff); + if (desktop >= 0 && desktop < _num_desktops) + return _area[desktop]; + else + return _area[_num_desktops]; +} + void Screen::installColormap(bool install) const { if (install) diff --git a/src/screen.hh b/src/screen.hh index 9244bb2d..16a4225b 100644 --- a/src/screen.hh +++ b/src/screen.hh @@ -30,7 +30,9 @@ class Client; class Screen : public otk::EventHandler { public: //! Holds a list of otk::Strut objects - typedef std::list StrutList; + typedef std::vector StrutList; + //! Holds a list of otk::Rect objects + typedef std::vector RectList; static const unsigned long event_mask = ColormapChangeMask | EnterWindowMask | @@ -59,11 +61,13 @@ private: //! Is the root colormap currently installed? bool _root_cmap_installed; - //! Area usable for placement etc (total - struts) - otk::Rect _area; + //! Area usable for placement etc (total - struts), one per desktop, + //! plus one extra for windows on all desktops + RectList _area; - //! Combined strut from all of the clients' struts - otk::Strut _strut; + //! Combined strut from all of the clients' struts, one per desktop, + //! plus one extra for windows on all desktops + StrutList _struts; //! An offscreen window which gets focus when nothing else has it Window _focuswindow; @@ -139,8 +143,6 @@ public: used. */ inline bool managed() const { return _managed; } - //! Returns the area of the screen not reserved by applications' Struts - inline const otk::Rect &area() const { return _area; } //! An offscreen window which gets focus when nothing else has it inline Window focuswindow() const { return _focuswindow; } //! Returns the desktop being displayed @@ -148,11 +150,19 @@ public: //! Returns the number of desktops inline long numDesktops() const { return _num_desktops; } + //! Returns the area of the screen not reserved by applications' Struts + /*! + @param desktop The desktop number of the area to retrieve for. A value of + 0xffffffff will return an area that combines all struts + on all desktops. + */ + const otk::Rect& area(long desktop) const; + //! Update's the screen's combined strut of all the clients. /*! Clients should call this whenever they change their strut. */ - void updateStrut(); + void updateStruts(); //! Manage any pre-existing windows on the screen void manageExisting(); -- 2.45.2