transient window support..halfway
This commit is contained in:
parent
b9a7f6fbcb
commit
c7b22b4f9c
7 changed files with 110 additions and 65 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 <X11/Xlib.h>
|
||||
|
||||
|
@ -16,13 +22,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
#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 {
|
||||
|
||||
|
@ -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<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,
|
||||
|
@ -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
|
||||
/*!
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -10,6 +10,7 @@ extern "C" {
|
|||
#include <X11/Xlib.h>
|
||||
}
|
||||
|
||||
#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<OBClient*> ClientList;
|
||||
//! Holds a list of otk::Strut objects
|
||||
typedef std::list<otk::Strut*> 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();
|
||||
|
|
Loading…
Reference in a new issue