From af1ac846ccb5fab8a3c83d8688db3d3f96f5a98b Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Thu, 16 Jan 2003 23:32:16 +0000 Subject: [PATCH] new raise/lower window code. only restacks 2 windows (1 move) at a time, ever. ManMower, u rulz. --- scripts/builtins.py | 4 +-- src/client.cc | 8 +++--- src/openbox.py | 3 ++- src/openbox_wrap.cc | 36 ++++++++++++++++++-------- src/screen.cc | 62 +++++++++++++++++++++++++++++++-------------- src/screen.hh | 15 ++++++++--- 6 files changed, 89 insertions(+), 39 deletions(-) diff --git a/scripts/builtins.py b/scripts/builtins.py index fee56e63..69271b21 100644 --- a/scripts/builtins.py +++ b/scripts/builtins.py @@ -93,12 +93,12 @@ def restart(data, other = ""): def raise_win(data): """Raises the window on which the event occured""" if not data.client: return - openbox.screen(data.screen).restack(1, data.client) + openbox.screen(data.screen).raiseWindow(data.client) def lower_win(data): """Lowers the window on which the event occured""" if not data.client: return - openbox.screen(data.screen).restack(0, data.client) + openbox.screen(data.screen).lowerWindow(data.client) def toggle_shade(data): """Toggles the shade status of the window on which the event occured""" diff --git a/src/client.cc b/src/client.cc index f564786f..9667a6f9 100644 --- a/src/client.cc +++ b/src/client.cc @@ -339,7 +339,7 @@ void Client::calcLayer() { if we don't have a frame, then we aren't mapped yet (and this would SIGSEGV :) */ - openbox->screen(_screen)->restack(true, this); // raise + openbox->screen(_screen)->raiseWindow(this); } } } @@ -856,7 +856,7 @@ void Client::clientMessageHandler(const XClientMessageEvent &e) shade(false); // XXX: deiconify focus(); - openbox->screen(_screen)->restack(true, this); // raise + openbox->screen(_screen)->raiseWindow(this); } } @@ -1165,13 +1165,13 @@ void Client::configureRequestHandler(const XConfigureRequestEvent &e) switch (e.detail) { case Below: case BottomIf: - openbox->screen(_screen)->restack(false, this); // lower + openbox->screen(_screen)->lowerWindow(this); break; case Above: case TopIf: default: - openbox->screen(_screen)->restack(true, this); // raise + openbox->screen(_screen)->raiseWindow(this); break; } } diff --git a/src/openbox.py b/src/openbox.py index 732b03f8..3e4ec195 100644 --- a/src/openbox.py +++ b/src/openbox.py @@ -665,7 +665,8 @@ class Screen(EventHandler,): def manageExisting(*args): return apply(_openbox.Screen_manageExisting,args) def manageWindow(*args): return apply(_openbox.Screen_manageWindow,args) def unmanageWindow(*args): return apply(_openbox.Screen_unmanageWindow,args) - def restack(*args): return apply(_openbox.Screen_restack,args) + def raiseWindow(*args): return apply(_openbox.Screen_raiseWindow,args) + def lowerWindow(*args): return apply(_openbox.Screen_lowerWindow,args) def setDesktopName(*args): return apply(_openbox.Screen_setDesktopName,args) def propertyHandler(*args): return apply(_openbox.Screen_propertyHandler,args) def clientMessageHandler(*args): return apply(_openbox.Screen_clientMessageHandler,args) diff --git a/src/openbox_wrap.cc b/src/openbox_wrap.cc index 9881acc2..1d88365c 100644 --- a/src/openbox_wrap.cc +++ b/src/openbox_wrap.cc @@ -8333,21 +8333,36 @@ static PyObject *_wrap_Screen_unmanageWindow(PyObject *self, PyObject *args) { } -static PyObject *_wrap_Screen_restack(PyObject *self, PyObject *args) { +static PyObject *_wrap_Screen_raiseWindow(PyObject *self, PyObject *args) { PyObject *resultobj; ob::Screen *arg1 = (ob::Screen *) 0 ; - bool arg2 ; - ob::Client *arg3 = (ob::Client *) 0 ; + ob::Client *arg2 = (ob::Client *) 0 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - if(!PyArg_ParseTuple(args,(char *)"OOO:Screen_restack",&obj0,&obj1,&obj2)) goto fail; + if(!PyArg_ParseTuple(args,(char *)"OO:Screen_raiseWindow",&obj0,&obj1)) goto fail; if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__Screen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; - arg2 = (bool) PyInt_AsLong(obj1); - if (PyErr_Occurred()) SWIG_fail; - if ((SWIG_ConvertPtr(obj2,(void **) &arg3, SWIGTYPE_p_ob__Client,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; - (arg1)->restack(arg2,arg3); + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_ob__Client,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + (arg1)->raiseWindow(arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Screen_lowerWindow(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::Screen *arg1 = (ob::Screen *) 0 ; + ob::Client *arg2 = (ob::Client *) 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:Screen_lowerWindow",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__Screen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_ob__Client,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + (arg1)->lowerWindow(arg2); Py_INCREF(Py_None); resultobj = Py_None; return resultobj; @@ -10995,7 +11010,8 @@ static PyMethodDef SwigMethods[] = { { (char *)"Screen_manageExisting", _wrap_Screen_manageExisting, METH_VARARGS }, { (char *)"Screen_manageWindow", _wrap_Screen_manageWindow, METH_VARARGS }, { (char *)"Screen_unmanageWindow", _wrap_Screen_unmanageWindow, METH_VARARGS }, - { (char *)"Screen_restack", _wrap_Screen_restack, METH_VARARGS }, + { (char *)"Screen_raiseWindow", _wrap_Screen_raiseWindow, METH_VARARGS }, + { (char *)"Screen_lowerWindow", _wrap_Screen_lowerWindow, METH_VARARGS }, { (char *)"Screen_setDesktopName", _wrap_Screen_setDesktopName, METH_VARARGS }, { (char *)"Screen_propertyHandler", _wrap_Screen_propertyHandler, METH_VARARGS }, { (char *)"Screen_clientMessageHandler", _wrap_Screen_clientMessageHandler, METH_VARARGS }, diff --git a/src/screen.cc b/src/screen.cc index e7d559f1..498c9c86 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -125,7 +125,7 @@ Screen::Screen(int screen) _focuswindow = XCreateWindow(**otk::display, _info->rootWindow(), -100, -100, 1, 1, 0, 0, InputOnly, _info->visual(), CWOverrideRedirect, &attr); - XMapWindow(**otk::display, _focuswindow); + XMapRaised(**otk::display, _focuswindow); // these may be further updated if any pre-existing windows are found in // the manageExising() function @@ -512,7 +512,7 @@ void Screen::manageWindow(Window window) clients.push_back(client); // this puts into the stacking order, then raises it _stacking.push_back(client); - restack(true, client); + raiseWindow(client); // update the root properties changeClientList(); @@ -590,30 +590,54 @@ void Screen::unmanageWindow(Client *client) changeClientList(); } -void Screen::restack(bool raise, Client *client) +void Screen::lowerWindow(Client *client) { - const int layer = client->layer(); - std::vector wins; + Window wins[2]; // only ever restack 2 windows. + + assert(!_stacking.empty()); // this would be bad + + Client::List::iterator it = --_stacking.end(); + Client::List::const_iterator end = _stacking.begin(); + + for (; it != end && (*it)->layer() < client->layer(); --it); + if (*it == client) return; // already the bottom, return + + wins[0] = (*it)->frame->window(); + wins[1] = client->frame->window(); _stacking.remove(client); + _stacking.insert(++it, client); - // the stacking list is from highest to lowest + XRestackWindows(**otk::display, wins, 2); + changeStackingList(); +} + +void Screen::raiseWindow(Client *client) +{ + Window wins[2]; // only ever restack 2 windows. + + assert(!_stacking.empty()); // this would be bad + + // remove the client before looking so we can't run into ourselves + _stacking.remove(client); - Client::List::iterator it = _stacking.begin(), end = _stacking.end(); - // insert the windows above this window - for (; it != end; ++it) { - if ((*it)->layer() < layer || (raise && (*it)->layer() == layer)) - break; - wins.push_back((*it)->frame->window()); - } - // insert our client - wins.push_back(client->frame->window()); + Client::List::iterator it = _stacking.begin(); + Client::List::const_iterator end = _stacking.end(); + + // the stacking list is from highest to lowest + for (; it != end && (*it)->layer() > client->layer(); ++it); + + /* + if our new position is the top, we want to stack under the _focuswindow + otherwise, we want to stack under the previous window in the stack. + */ + wins[0] = (it == _stacking.begin() ? _focuswindow : + ((*(--Client::List::const_iterator(it)))->frame->window())); + wins[1] = client->frame->window(); + _stacking.insert(it, client); - // insert the remaining below this window - for (; it != end; ++it) - wins.push_back((*it)->frame->window()); - XRestackWindows(**otk::display, &wins[0], wins.size()); + XRestackWindows(**otk::display, wins, 2); changeStackingList(); } diff --git a/src/screen.hh b/src/screen.hh index c3af7b6c..7f33b9c8 100644 --- a/src/screen.hh +++ b/src/screen.hh @@ -182,9 +182,18 @@ public: */ void unmanageWindow(Client *client); - //! Raises/Lowers a client window above/below all others in its stacking - //! layer - void restack(bool raise, Client *client); + //! Raises a client window above all others in its stacking layer + /*! + raiseWindow has a couple of constraints that lowerWindow does not.
+ 1) raiseWindow can be called after changing a Client's stack layer, and + the list will be reorganized properly.
+ 2) raiseWindow guarantees that XRestackWindows() will always be + called for the specified client. + */ + void raiseWindow(Client *client); + + //! Lowers a client window below all others in its stacking layer + void lowerWindow(Client *client); //! Sets the name of a desktop by changing the root window property /*! -- 2.39.2