From c7b22b4f9cee63d860ad4f6617cd5210299b9d8b Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 5 Jan 2003 01:40:38 +0000 Subject: [PATCH] transient window support..halfway --- src/bindings.cc | 4 +-- src/client.cc | 72 ++++++++++++++++++++++++++++++++++----------- src/client.hh | 44 +++++++++++++++++++-------- src/openbox.i | 2 +- src/openbox_wrap.cc | 20 ++++++------- src/screen.cc | 14 ++++----- src/screen.hh | 19 ++---------- 7 files changed, 110 insertions(+), 65 deletions(-) diff --git a/src/bindings.cc b/src/bindings.cc index 77c1dcf8..6a135b6d 100644 --- a/src/bindings.cc +++ b/src/bindings.cc @@ -410,7 +410,7 @@ bool OBBindings::addButton(const std::string &but, MouseContext context, // grab the button on all clients for (int sn = 0; sn < Openbox::instance->screenCount(); ++sn) { OBScreen *s = Openbox::instance->screen(sn); - OBScreen::ClientList::iterator c_it, c_end = s->clients.end(); + OBClient::List::iterator c_it, c_end = s->clients.end(); for (c_it = s->clients.begin(); c_it != c_end; ++c_it) { grabButton(true, bind->binding, context, *c_it); } @@ -435,7 +435,7 @@ void OBBindings::removeAllButtons() // ungrab the button on all clients for (int sn = 0; sn < Openbox::instance->screenCount(); ++sn) { OBScreen *s = Openbox::instance->screen(sn); - OBScreen::ClientList::iterator c_it, c_end = s->clients.end(); + OBClient::List::iterator c_it, c_end = s->clients.end(); for (c_it = s->clients.begin(); c_it != c_end; ++c_it) { grabButton(false, (*it)->binding, (MouseContext)i, *c_it); } diff --git a/src/client.cc b/src/client.cc index 7b846729..8c259db3 100644 --- a/src/client.cc +++ b/src/client.cc @@ -41,12 +41,16 @@ OBClient::OBClient(int screen, Window window) _decorations = _functions = 0; // start unfocused _focused = false; + // not a transient by default of course + _transient_for = 0; getArea(); getDesktop(); - // XXX: updateTransientFor(); + updateTransientFor(); getType(); + // XXX: changeAllowedActions(); + // set the decorations and functions _decorations = Decor_Titlebar | Decor_Handle | Decor_Border | Decor_Iconify | Decor_Maximize; @@ -171,10 +175,9 @@ void OBClient::getType() * the window type hint was not set, which means we either classify ourself * as a normal window or a dialog, depending on if we are a transient. */ - // XXX: make this code work! - //if (isTransient()) - // _type = Type_Dialog; - //else + if (_transient_for) + _type = Type_Dialog; + else _type = Type_Normal; } } @@ -315,16 +318,16 @@ void OBClient::getShaped() void OBClient::calcLayer() { - if (_iconic) _layer = OBScreen::Layer_Icon; - else if (_fullscreen) _layer = OBScreen::Layer_Fullscreen; - else if (_type == Type_Desktop) _layer = OBScreen::Layer_Desktop; + if (_iconic) _layer = Layer_Icon; + else if (_fullscreen) _layer = Layer_Fullscreen; + else if (_type == Type_Desktop) _layer = Layer_Desktop; else if (_type == Type_Dock) { - if (!_below) _layer = OBScreen::Layer_Top; - else _layer = OBScreen::Layer_Normal; + if (!_below) _layer = Layer_Top; + else _layer = Layer_Normal; } - else if (_above) _layer = OBScreen::Layer_Above; - else if (_below) _layer = OBScreen::Layer_Below; - else _layer = OBScreen::Layer_Normal; + else if (_above) _layer = Layer_Above; + else if (_below) _layer = Layer_Below; + else _layer = Layer_Normal; } @@ -521,6 +524,41 @@ void OBClient::updateStrut() } +void OBClient::updateTransientFor() +{ + Window t = 0; + OBClient *c = 0; + + if (XGetTransientForHint(otk::OBDisplay::display, _window, &t) && + t != _window) { // cant be transient to itself! + c = Openbox::instance->findClient(t); + assert(c != this); // if this happens then we need to check for it + + if (!c /*XXX: && _group*/) { + // not transient to a client, see if it is transient for a group + if (//t == _group->leader() || + t == None || + t == otk::OBDisplay::screenInfo(_screen)->rootWindow()) { + // window is a transient for its group! + // XXX: for now this is treated as non-transient. + // this needs to be fixed! + } + } + } + + // if anything has changed... + if (c != _transient_for) { + if (_transient_for) + _transient_for->_transients.remove(this); // remove from old parent + _transient_for = c; + if (_transient_for) + _transient_for->_transients.push_back(this); // add to new parent + + // XXX: change decor status? + } +} + + void OBClient::propertyHandler(const XPropertyEvent &e) { otk::OtkEventHandler::propertyHandler(e); @@ -542,6 +580,8 @@ void OBClient::propertyHandler(const XPropertyEvent &e) updateNormalHints(); else if (e.atom == XA_WM_HINTS) updateWMHints(); + else if (e.atom == XA_WM_TRANSIENT_FOR) + updateTransientFor(); else if (e.atom == property->atom(otk::OBProperty::net_wm_name) || e.atom == property->atom(otk::OBProperty::wm_name)) updateTitle(); @@ -552,10 +592,8 @@ void OBClient::propertyHandler(const XPropertyEvent &e) updateClass(); else if (e.atom == property->atom(otk::OBProperty::wm_protocols)) updateProtocols(); - // XXX: transient for hint else if (e.atom == property->atom(otk::OBProperty::net_wm_strut)) updateStrut(); - // XXX: strut hint } @@ -563,7 +601,8 @@ void OBClient::setWMState(long state) { if (state == _wmstate) return; // no change - switch (state) { + _wmstate = state; + switch (_wmstate) { case IconicState: // XXX: cause it to iconify break; @@ -571,7 +610,6 @@ void OBClient::setWMState(long state) // XXX: cause it to uniconify break; } - _wmstate = state; } diff --git a/src/client.hh b/src/client.hh index 724cf518..1726ce44 100644 --- a/src/client.hh +++ b/src/client.hh @@ -7,6 +7,12 @@ property changes on the window and some client messages */ +#include "widget.hh" +#include "otk/point.hh" +#include "otk/strut.hh" +#include "otk/rect.hh" +#include "otk/eventhandler.hh" + extern "C" { #include @@ -16,13 +22,7 @@ extern "C" { } #include - -#include "screen.hh" -#include "widget.hh" -#include "otk/point.hh" -#include "otk/strut.hh" -#include "otk/rect.hh" -#include "otk/eventhandler.hh" +#include namespace ob { @@ -41,7 +41,6 @@ struct MwmHints { unsigned long decorations;//!< A bitmask of OBClient::MwmDecorations values }; - //! Maintains the state of a client window. /*! OBClient maintains the state of a client window. The state consists of the @@ -63,6 +62,22 @@ public: */ OBFrame *frame; + //! Holds a list of OBClients + typedef std::list List; + + //! The possible stacking layers a client window can be a part of + enum StackLayer { + Layer_Icon, //!< 0 - iconified windows, in any order at all + Layer_Desktop, //!< 1 - desktop windows + Layer_Below, //!< 2 - normal windows w/ below + Layer_Normal, //!< 3 - normal windows + Layer_Above, //!< 4 - normal windows w/ above + Layer_Top, //!< 5 - always-on-top-windows (docks?) + Layer_Fullscreen, //!< 6 - fullscreeen windows + Layer_Internal, //!< 7 - openbox windows/menus + NUM_LAYERS + }; + //! Corners of the client window, used for anchor positions enum Corner { TopLeft, TopRight, @@ -157,7 +172,11 @@ private: //! The id of the group the window belongs to Window _group; - // XXX: transient_for, transients + //! The client which this client is a transient (child) for + OBClient *_transient_for; + + //! The clients which are transients (children) of this client + OBClient::List _transients; //! The desktop on which the window resides (0xffffffff for all desktops) unsigned long _desktop; @@ -272,7 +291,7 @@ private: //! The window should be underneath other windows of the same type bool _below; - OBScreen::StackLayer _layer; + StackLayer _layer; //! A bitmask of values in the OBClient::Decoration enum /*! @@ -327,9 +346,10 @@ private: void updateIconTitle(); //! Updates the window's application name and class void updateClass(); - // XXX: updateTransientFor(); //! Updates the strut for the client void updateStrut(); + //! Updates the window's transient status, and any parents of it + void updateTransientFor(); //! Change the client's state hints to match the class' data void changeState(); @@ -435,7 +455,7 @@ public: //! Returns if the window is maximized horizontally inline bool maxHorz() const { return _max_horz; } //! Returns the window's stacking layer - inline OBScreen::StackLayer layer() const { return _layer; } + inline StackLayer layer() const { return _layer; } //! Removes or reapplies the client's border to its window /*! diff --git a/src/openbox.i b/src/openbox.i index 1b227568..508b678c 100644 --- a/src/openbox.i +++ b/src/openbox.i @@ -32,7 +32,7 @@ OBClient *client(int i) { if (i >= (int)self->clients.size()) return NULL; - ob::OBScreen::ClientList::iterator it = self->clients.begin(); + ob::OBClient::List::iterator it = self->clients.begin(); std::advance(it,i); return *it; } diff --git a/src/openbox_wrap.cc b/src/openbox_wrap.cc index 6f269706..8201bb76 100644 --- a/src/openbox_wrap.cc +++ b/src/openbox_wrap.cc @@ -783,7 +783,7 @@ static std::string SwigString_AsString(PyObject* o) { ob::OBClient *ob_OBScreen_client(ob::OBScreen *self,int i){ if (i >= (int)self->clients.size()) return NULL; - ob::OBScreen::ClientList::iterator it = self->clients.begin(); + ob::OBClient::List::iterator it = self->clients.begin(); std::advance(it,i); return *it; } @@ -2911,16 +2911,16 @@ static swig_const_info swig_const_table[] = { { SWIG_PY_INT, (char *)"Openbox_State_Normal", (long) ob::Openbox::State_Normal, 0, 0, 0}, { SWIG_PY_INT, (char *)"Openbox_State_Exiting", (long) ob::Openbox::State_Exiting, 0, 0, 0}, { SWIG_PY_INT, (char *)"OBScreen_event_mask", (long) ob::OBScreen::event_mask, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_Layer_Icon", (long) ob::OBScreen::Layer_Icon, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_Layer_Desktop", (long) ob::OBScreen::Layer_Desktop, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_Layer_Below", (long) ob::OBScreen::Layer_Below, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_Layer_Normal", (long) ob::OBScreen::Layer_Normal, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_Layer_Above", (long) ob::OBScreen::Layer_Above, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_Layer_Top", (long) ob::OBScreen::Layer_Top, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_Layer_Fullscreen", (long) ob::OBScreen::Layer_Fullscreen, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_Layer_Internal", (long) ob::OBScreen::Layer_Internal, 0, 0, 0}, -{ SWIG_PY_INT, (char *)"OBScreen_NUM_LAYERS", (long) ob::OBScreen::NUM_LAYERS, 0, 0, 0}, { SWIG_PY_INT, (char *)"MwmHints_elements", (long) ob::MwmHints::elements, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_Layer_Icon", (long) ob::OBClient::Layer_Icon, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_Layer_Desktop", (long) ob::OBClient::Layer_Desktop, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_Layer_Below", (long) ob::OBClient::Layer_Below, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_Layer_Normal", (long) ob::OBClient::Layer_Normal, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_Layer_Above", (long) ob::OBClient::Layer_Above, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_Layer_Top", (long) ob::OBClient::Layer_Top, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_Layer_Fullscreen", (long) ob::OBClient::Layer_Fullscreen, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_Layer_Internal", (long) ob::OBClient::Layer_Internal, 0, 0, 0}, +{ SWIG_PY_INT, (char *)"OBClient_NUM_LAYERS", (long) ob::OBClient::NUM_LAYERS, 0, 0, 0}, { SWIG_PY_INT, (char *)"OBClient_TopLeft", (long) ob::OBClient::TopLeft, 0, 0, 0}, { SWIG_PY_INT, (char *)"OBClient_TopRight", (long) ob::OBClient::TopRight, 0, 0, 0}, { SWIG_PY_INT, (char *)"OBClient_BottomLeft", (long) ob::OBClient::BottomLeft, 0, 0, 0}, diff --git a/src/screen.cc b/src/screen.cc index 8ea1b49e..307404ff 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -196,7 +196,7 @@ void OBScreen::updateStrut() { _strut.left = _strut.right = _strut.top = _strut.bottom = 0; - ClientList::iterator it, end = clients.end(); + OBClient::List::iterator it, end = clients.end(); for (it = clients.begin(); it != end; ++it) { const otk::Strut &s = (*it)->strut(); _strut.left = std::max(_strut.left, s.left); @@ -364,8 +364,8 @@ void OBScreen::setClientList() windows = new Window[size]; win_it = windows; - ClientList::const_iterator it = clients.begin(); - const ClientList::const_iterator end = clients.end(); + OBClient::List::const_iterator it = clients.begin(); + const OBClient::List::const_iterator end = clients.end(); for (; it != end; ++it, ++win_it) *win_it = (*it)->window(); } else @@ -397,8 +397,8 @@ void OBScreen::setStackingList() windows = new Window[size]; win_it = windows; - ClientList::const_iterator it = _stacking.begin(); - const ClientList::const_iterator end = _stacking.end(); + OBClient::List::const_iterator it = _stacking.begin(); + const OBClient::List::const_iterator end = _stacking.end(); for (; it != end; ++it, ++win_it) *win_it = (*it)->window(); } else @@ -547,7 +547,7 @@ void OBScreen::unmanageWindow(OBClient *client) // pass around focus if this window was focused XXX do this better! if (Openbox::instance->focusedClient() == client) { OBClient *newfocus = 0; - ClientList::iterator it, end = _stacking.end(); + OBClient::List::iterator it, end = _stacking.end(); for (it = _stacking.begin(); it != end; ++it) if ((*it)->normal() && (*it)->focus()) { newfocus = *it; @@ -604,7 +604,7 @@ void OBScreen::restack(bool raise, OBClient *client) // the stacking list is from highest to lowest - ClientList::iterator it = _stacking.begin(), end = _stacking.end(); + OBClient::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)) diff --git a/src/screen.hh b/src/screen.hh index cb078082..e57ab2ed 100644 --- a/src/screen.hh +++ b/src/screen.hh @@ -10,6 +10,7 @@ extern "C" { #include } +#include "client.hh" #include "rootwindow.hh" #include "otk/image.hh" #include "otk/strut.hh" @@ -29,8 +30,6 @@ class OBRootWindow; */ class OBScreen { public: - //! Holds a list of OBClient objects - typedef std::list ClientList; //! Holds a list of otk::Strut objects typedef std::list StrutList; @@ -43,20 +42,8 @@ public: ButtonPressMask | ButtonReleaseMask; - enum StackLayer { - Layer_Icon, // 0 - iconified windows, in any order at all - Layer_Desktop, // 1 - desktop windows - Layer_Below, // 2 - normal windows w/ below - Layer_Normal, // 3 - normal windows - Layer_Above, // 4 - normal windows w/ above - Layer_Top, // 5 - always-on-top-windows (docks?) - Layer_Fullscreen, // 6 - fullscreeen windows - Layer_Internal, // 7 - openbox windows/menus - NUM_LAYERS - }; - //! All managed clients on the screen (in order of being mapped) - ClientList clients; + OBClient::List clients; private: //! Was %Openbox able to manage the screen? @@ -94,7 +81,7 @@ private: Window _supportwindow; //! A list of all managed clients on the screen, in their stacking order - ClientList _stacking; + OBClient::List _stacking; //! Calculate the OBScreen::_area member void calcArea(); -- 2.45.2