// 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);
}
// 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);
}
_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;
* 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;
}
}
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;
}
}
+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);
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();
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
}
{
if (state == _wmstate) return; // no change
- switch (state) {
+ _wmstate = state;
+ switch (_wmstate) {
case IconicState:
// XXX: cause it to iconify
break;
// XXX: cause it to uniconify
break;
}
- _wmstate = state;
}
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 <X11/Xlib.h>
}
#include <string>
-
-#include "screen.hh"
-#include "widget.hh"
-#include "otk/point.hh"
-#include "otk/strut.hh"
-#include "otk/rect.hh"
-#include "otk/eventhandler.hh"
+#include <list>
namespace ob {
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
*/
OBFrame *frame;
+ //! Holds a list of OBClients
+ typedef std::list<OBClient*> 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,
//! 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;
//! 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
/*!
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();
//! 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
/*!
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;
}
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;
}
{ 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},
{
_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);
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
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
// 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;
// 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))
#include <X11/Xlib.h>
}
+#include "client.hh"
#include "rootwindow.hh"
#include "otk/image.hh"
#include "otk/strut.hh"
*/
class OBScreen {
public:
- //! Holds a list of OBClient objects
- typedef std::list<OBClient*> ClientList;
//! Holds a list of otk::Strut objects
typedef std::list<otk::Strut*> StrutList;
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?
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();