From 00e2c5aaad4a0831fd1e0d1b1c287df4d6eaac93 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 7 Jan 2003 00:57:00 +0000 Subject: [PATCH] keep track of desktops... --- src/Makefile.am | 2 +- src/client.cc | 2 +- src/client.hh | 4 +- src/openbox_wrap.cc | 203 ++++++++++++++++++++++++++++++++++---- src/rootwindow.cc | 95 ------------------ src/screen.cc | 233 +++++++++++++++++++++++++++++++++++--------- src/screen.hh | 61 ++++++++++-- 7 files changed, 425 insertions(+), 175 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index fab23110..620789c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ bin_PROGRAMS= openbox3 openbox3_LDADD=-L../otk -lotk @LIBINTL@ openbox3_SOURCES= actions.cc client.cc frame.cc openbox.cc screen.cc \ - main.cc rootwindow.cc backgroundwidget.cc labelwidget.cc \ + main.cc backgroundwidget.cc labelwidget.cc \ buttonwidget.cc python.cc bindings.cc \ openbox_wrap.cc diff --git a/src/client.cc b/src/client.cc index 91a75bff..c0e63f2c 100644 --- a/src/client.cc +++ b/src/client.cc @@ -93,7 +93,7 @@ void OBClient::getDesktop() property->get(_window, otk::OBProperty::net_wm_desktop, otk::OBProperty::Atom_Cardinal, - &_desktop); + (long unsigned*)&_desktop); } diff --git a/src/client.hh b/src/client.hh index dd4bfe9f..83f5f1a0 100644 --- a/src/client.hh +++ b/src/client.hh @@ -179,7 +179,7 @@ private: OBClient::List _transients; //! The desktop on which the window resides (0xffffffff for all desktops) - unsigned long _desktop; + long _desktop; //! Normal window title std::string _title; // XXX: Have to keep track if this string is Utf8 or not @@ -399,7 +399,7 @@ public: This value is a 0-based index.
A value of 0xffffffff indicates that the window exists on all desktops. */ - inline unsigned long desktop() const { return _desktop; } + inline long desktop() const { return _desktop; } //! Returns the window's title inline const std::string &title() const { return _title; } //! Returns the window's title when it is iconified diff --git a/src/openbox_wrap.cc b/src/openbox_wrap.cc index 808f0466..428426b8 100644 --- a/src/openbox_wrap.cc +++ b/src/openbox_wrap.cc @@ -655,22 +655,23 @@ SWIG_InstallConstants(PyObject *d, swig_const_info constants[]) { #define SWIGTYPE_p_ob__OBClient swig_types[7] #define SWIGTYPE_p_ob__Openbox swig_types[8] #define SWIGTYPE_p_otk__Strut swig_types[9] -#define SWIGTYPE_p_XConfigureRequestEvent swig_types[10] -#define SWIGTYPE_p_otk__OtkEventHandler swig_types[11] -#define SWIGTYPE_p_otk__Rect swig_types[12] -#define SWIGTYPE_p_ob__OBWidget swig_types[13] -#define SWIGTYPE_p_XFocusChangeEvent swig_types[14] +#define SWIGTYPE_p_XMapRequestEvent swig_types[10] +#define SWIGTYPE_p_XConfigureRequestEvent swig_types[11] +#define SWIGTYPE_p_otk__OtkEventHandler swig_types[12] +#define SWIGTYPE_p_otk__Rect swig_types[13] +#define SWIGTYPE_p_ob__OBWidget swig_types[14] #define SWIGTYPE_p_XClientMessageEvent swig_types[15] -#define SWIGTYPE_p_otk__OBProperty swig_types[16] -#define SWIGTYPE_p_otk__OtkEventDispatcher swig_types[17] -#define SWIGTYPE_p_XPropertyEvent swig_types[18] -#define SWIGTYPE_p_XDestroyWindowEvent swig_types[19] -#define SWIGTYPE_p_otk__BImageControl swig_types[20] -#define SWIGTYPE_p_PyObject swig_types[21] -#define SWIGTYPE_p_ob__OBBindings swig_types[22] -#define SWIGTYPE_p_ob__MwmHints swig_types[23] -#define SWIGTYPE_p_XUnmapEvent swig_types[24] -static swig_type_info *swig_types[26]; +#define SWIGTYPE_p_XFocusChangeEvent swig_types[16] +#define SWIGTYPE_p_otk__OBProperty swig_types[17] +#define SWIGTYPE_p_otk__OtkEventDispatcher swig_types[18] +#define SWIGTYPE_p_XPropertyEvent swig_types[19] +#define SWIGTYPE_p_XDestroyWindowEvent swig_types[20] +#define SWIGTYPE_p_otk__BImageControl swig_types[21] +#define SWIGTYPE_p_PyObject swig_types[22] +#define SWIGTYPE_p_ob__OBBindings swig_types[23] +#define SWIGTYPE_p_ob__MwmHints swig_types[24] +#define SWIGTYPE_p_XUnmapEvent swig_types[25] +static swig_type_info *swig_types[27]; /* -------- TYPES TABLE (END) -------- */ @@ -1513,6 +1514,23 @@ static PyObject *_wrap_OBScreen_focuswindow(PyObject *self, PyObject *args) { } +static PyObject *_wrap_OBScreen_desktop(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; + unsigned long result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:OBScreen_desktop",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBScreen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (unsigned long)((ob::OBScreen const *)arg1)->desktop(); + + resultobj = PyInt_FromLong((long)result); + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_OBScreen_updateStrut(PyObject *self, PyObject *args) { PyObject *resultobj; ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; @@ -1607,6 +1625,134 @@ static PyObject *_wrap_OBScreen_restack(PyObject *self, PyObject *args) { } +static PyObject *_wrap_OBScreen_changeDesktop(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; + long arg2 ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Ol:OBScreen_changeDesktop",&obj0,&arg2)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBScreen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + (arg1)->changeDesktop(arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_OBScreen_changeNumDesktops(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; + long arg2 ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"Ol:OBScreen_changeNumDesktops",&obj0,&arg2)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBScreen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + (arg1)->changeNumDesktops(arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_OBScreen_setDesktopName(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; + long arg2 ; + std::string *arg3 = 0 ; + std::string temp3 ; + PyObject * obj0 = 0 ; + PyObject * obj2 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OlO:OBScreen_setDesktopName",&obj0,&arg2,&obj2)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBScreen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + { + if (PyString_Check(obj2)) { + temp3 = std::string(PyString_AsString(obj2)); + arg3 = &temp3; + }else { + SWIG_exception(SWIG_TypeError, "string expected"); + } + } + (arg1)->setDesktopName(arg2,(std::string const &)*arg3); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_OBScreen_propertyHandler(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; + XPropertyEvent *arg2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:OBScreen_propertyHandler",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBScreen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_XPropertyEvent,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg2 == NULL) { + PyErr_SetString(PyExc_TypeError,"null reference"); SWIG_fail; + } + (arg1)->propertyHandler((XPropertyEvent const &)*arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_OBScreen_clientMessageHandler(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; + XClientMessageEvent *arg2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:OBScreen_clientMessageHandler",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBScreen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_XClientMessageEvent,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg2 == NULL) { + PyErr_SetString(PyExc_TypeError,"null reference"); SWIG_fail; + } + (arg1)->clientMessageHandler((XClientMessageEvent const &)*arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_OBScreen_mapRequestHandler(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; + XMapRequestEvent *arg2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:OBScreen_mapRequestHandler",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBScreen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_XMapRequestEvent,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg2 == NULL) { + PyErr_SetString(PyExc_TypeError,"null reference"); SWIG_fail; + } + (arg1)->mapRequestHandler((XMapRequestEvent const &)*arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + static PyObject * OBScreen_swigregister(PyObject *self, PyObject *args) { PyObject *obj; if (!PyArg_ParseTuple(args,(char*)"O", &obj)) return NULL; @@ -1873,12 +2019,12 @@ static PyObject *_wrap_OBClient_normal(PyObject *self, PyObject *args) { static PyObject *_wrap_OBClient_desktop(PyObject *self, PyObject *args) { PyObject *resultobj; ob::OBClient *arg1 = (ob::OBClient *) 0 ; - unsigned long result; + long result; PyObject * obj0 = 0 ; if(!PyArg_ParseTuple(args,(char *)"O:OBClient_desktop",&obj0)) goto fail; if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBClient,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; - result = (unsigned long)((ob::OBClient const *)arg1)->desktop(); + result = (long)((ob::OBClient const *)arg1)->desktop(); resultobj = PyInt_FromLong((long)result); return resultobj; @@ -2754,11 +2900,18 @@ static PyMethodDef SwigMethods[] = { { (char *)"OBScreen_area", _wrap_OBScreen_area, METH_VARARGS }, { (char *)"OBScreen_style", _wrap_OBScreen_style, METH_VARARGS }, { (char *)"OBScreen_focuswindow", _wrap_OBScreen_focuswindow, METH_VARARGS }, + { (char *)"OBScreen_desktop", _wrap_OBScreen_desktop, METH_VARARGS }, { (char *)"OBScreen_updateStrut", _wrap_OBScreen_updateStrut, METH_VARARGS }, { (char *)"OBScreen_manageExisting", _wrap_OBScreen_manageExisting, METH_VARARGS }, { (char *)"OBScreen_manageWindow", _wrap_OBScreen_manageWindow, METH_VARARGS }, { (char *)"OBScreen_unmanageWindow", _wrap_OBScreen_unmanageWindow, METH_VARARGS }, { (char *)"OBScreen_restack", _wrap_OBScreen_restack, METH_VARARGS }, + { (char *)"OBScreen_changeDesktop", _wrap_OBScreen_changeDesktop, METH_VARARGS }, + { (char *)"OBScreen_changeNumDesktops", _wrap_OBScreen_changeNumDesktops, METH_VARARGS }, + { (char *)"OBScreen_setDesktopName", _wrap_OBScreen_setDesktopName, METH_VARARGS }, + { (char *)"OBScreen_propertyHandler", _wrap_OBScreen_propertyHandler, METH_VARARGS }, + { (char *)"OBScreen_clientMessageHandler", _wrap_OBScreen_clientMessageHandler, METH_VARARGS }, + { (char *)"OBScreen_mapRequestHandler", _wrap_OBScreen_mapRequestHandler, METH_VARARGS }, { (char *)"OBScreen_swigregister", OBScreen_swigregister, METH_VARARGS }, { (char *)"MwmHints_flags_set", _wrap_MwmHints_flags_set, METH_VARARGS }, { (char *)"MwmHints_flags_get", _wrap_MwmHints_flags_get, METH_VARARGS }, @@ -2831,9 +2984,15 @@ static void *_p_ob__OBActionsTo_p_otk__OtkEventHandler(void *x) { static void *_p_ob__OpenboxTo_p_otk__OtkEventHandler(void *x) { return (void *)((otk::OtkEventHandler *) ((ob::Openbox *) x)); } +static void *_p_ob__OBScreenTo_p_otk__OtkEventHandler(void *x) { + return (void *)((otk::OtkEventHandler *) ((ob::OBScreen *) x)); +} static void *_p_ob__OBClientTo_p_otk__OtkEventHandler(void *x) { return (void *)((otk::OtkEventHandler *) ((ob::OBClient *) x)); } +static void *_p_ob__OBScreenTo_p_ob__OBWidget(void *x) { + return (void *)((ob::OBWidget *) ((ob::OBScreen *) x)); +} static void *_p_ob__OBClientTo_p_ob__OBWidget(void *x) { return (void *)((ob::OBWidget *) ((ob::OBClient *) x)); } @@ -2850,12 +3009,13 @@ static swig_type_info _swigt__p_XReparentEvent[] = {{"_p_XReparentEvent", 0, "XR static swig_type_info _swigt__p_ob__OBClient[] = {{"_p_ob__OBClient", 0, "ob::OBClient *", 0},{"_p_ob__OBClient"},{0}}; static swig_type_info _swigt__p_ob__Openbox[] = {{"_p_ob__Openbox", 0, "ob::Openbox *", 0},{"_p_ob__Openbox"},{0}}; static swig_type_info _swigt__p_otk__Strut[] = {{"_p_otk__Strut", 0, "otk::Strut *", 0},{"_p_otk__Strut"},{0}}; +static swig_type_info _swigt__p_XMapRequestEvent[] = {{"_p_XMapRequestEvent", 0, "XMapRequestEvent *", 0},{"_p_XMapRequestEvent"},{0}}; static swig_type_info _swigt__p_XConfigureRequestEvent[] = {{"_p_XConfigureRequestEvent", 0, "XConfigureRequestEvent *", 0},{"_p_XConfigureRequestEvent"},{0}}; -static swig_type_info _swigt__p_otk__OtkEventHandler[] = {{"_p_otk__OtkEventHandler", 0, "otk::OtkEventHandler *", 0},{"_p_ob__OBActions", _p_ob__OBActionsTo_p_otk__OtkEventHandler},{"_p_otk__OtkEventHandler"},{"_p_ob__Openbox", _p_ob__OpenboxTo_p_otk__OtkEventHandler},{"_p_ob__OBClient", _p_ob__OBClientTo_p_otk__OtkEventHandler},{0}}; +static swig_type_info _swigt__p_otk__OtkEventHandler[] = {{"_p_otk__OtkEventHandler", 0, "otk::OtkEventHandler *", 0},{"_p_ob__OBActions", _p_ob__OBActionsTo_p_otk__OtkEventHandler},{"_p_otk__OtkEventHandler"},{"_p_ob__Openbox", _p_ob__OpenboxTo_p_otk__OtkEventHandler},{"_p_ob__OBScreen", _p_ob__OBScreenTo_p_otk__OtkEventHandler},{"_p_ob__OBClient", _p_ob__OBClientTo_p_otk__OtkEventHandler},{0}}; static swig_type_info _swigt__p_otk__Rect[] = {{"_p_otk__Rect", 0, "otk::Rect *", 0},{"_p_otk__Rect"},{0}}; -static swig_type_info _swigt__p_ob__OBWidget[] = {{"_p_ob__OBWidget", 0, "ob::OBWidget *", 0},{"_p_ob__OBWidget"},{"_p_ob__OBClient", _p_ob__OBClientTo_p_ob__OBWidget},{0}}; -static swig_type_info _swigt__p_XFocusChangeEvent[] = {{"_p_XFocusChangeEvent", 0, "XFocusChangeEvent *", 0},{"_p_XFocusChangeEvent"},{0}}; +static swig_type_info _swigt__p_ob__OBWidget[] = {{"_p_ob__OBWidget", 0, "ob::OBWidget *", 0},{"_p_ob__OBWidget"},{"_p_ob__OBScreen", _p_ob__OBScreenTo_p_ob__OBWidget},{"_p_ob__OBClient", _p_ob__OBClientTo_p_ob__OBWidget},{0}}; static swig_type_info _swigt__p_XClientMessageEvent[] = {{"_p_XClientMessageEvent", 0, "XClientMessageEvent *", 0},{"_p_XClientMessageEvent"},{0}}; +static swig_type_info _swigt__p_XFocusChangeEvent[] = {{"_p_XFocusChangeEvent", 0, "XFocusChangeEvent *", 0},{"_p_XFocusChangeEvent"},{0}}; static swig_type_info _swigt__p_otk__OBProperty[] = {{"_p_otk__OBProperty", 0, "otk::OBProperty *", 0},{"_p_otk__OBProperty"},{0}}; static swig_type_info _swigt__p_otk__OtkEventDispatcher[] = {{"_p_otk__OtkEventDispatcher", 0, "otk::OtkEventDispatcher *", 0},{"_p_otk__OtkEventDispatcher"},{"_p_ob__Openbox", _p_ob__OpenboxTo_p_otk__OtkEventDispatcher},{0}}; static swig_type_info _swigt__p_XPropertyEvent[] = {{"_p_XPropertyEvent", 0, "XPropertyEvent *", 0},{"_p_XPropertyEvent"},{0}}; @@ -2877,12 +3037,13 @@ _swigt__p_XReparentEvent, _swigt__p_ob__OBClient, _swigt__p_ob__Openbox, _swigt__p_otk__Strut, +_swigt__p_XMapRequestEvent, _swigt__p_XConfigureRequestEvent, _swigt__p_otk__OtkEventHandler, _swigt__p_otk__Rect, _swigt__p_ob__OBWidget, -_swigt__p_XFocusChangeEvent, _swigt__p_XClientMessageEvent, +_swigt__p_XFocusChangeEvent, _swigt__p_otk__OBProperty, _swigt__p_otk__OtkEventDispatcher, _swigt__p_XPropertyEvent, diff --git a/src/rootwindow.cc b/src/rootwindow.cc index 78017dd3..0b7de57d 100644 --- a/src/rootwindow.cc +++ b/src/rootwindow.cc @@ -27,102 +27,7 @@ OBRootWindow::~OBRootWindow() } -void OBRootWindow::updateDesktopNames() -{ - const int numWorkspaces = 1; // XXX: change this to the number of workspaces! - - const otk::OBProperty *property = Openbox::instance->property(); - - unsigned long num = (unsigned) -1; - - if (!property->get(_info->rootWindow(), - otk::OBProperty::net_desktop_names, - otk::OBProperty::utf8, &num, &_names)) - _names.clear(); - while ((signed)_names.size() < numWorkspaces) - _names.push_back("Unnamed"); -} - - -void OBRootWindow::propertyHandler(const XPropertyEvent &e) -{ - otk::OtkEventHandler::propertyHandler(e); - - const otk::OBProperty *property = Openbox::instance->property(); - - // compress changes to a single property into a single change - XEvent ce; - while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) { - // XXX: it would be nice to compress ALL changes to a property, not just - // changes in a row without other props between. - if (ce.xproperty.atom != e.atom) { - XPutBackEvent(otk::OBDisplay::display, &ce); - break; - } - } - - if (e.atom == property->atom(otk::OBProperty::net_desktop_names)) - updateDesktopNames(); -} - - -void OBRootWindow::clientMessageHandler(const XClientMessageEvent &e) -{ - otk::OtkEventHandler::clientMessageHandler(e); - - if (e.format != 32) return; - //const otk::OBProperty *property = Openbox::instance->property(); - - // XXX: so many client messages to handle here! ..or not.. they go to clients -} - - -void OBRootWindow::setDesktopNames(const otk::OBProperty::StringVect &names) -{ - _names = names; - const otk::OBProperty *property = Openbox::instance->property(); - property->set(_info->rootWindow(), otk::OBProperty::net_desktop_names, - otk::OBProperty::utf8, names); -} - -void OBRootWindow::setDesktopName(int i, const std::string &name) -{ - const int numWorkspaces = 1; // XXX: change this to the number of workspaces! - assert(i >= 0); - assert(i < numWorkspaces); - const otk::OBProperty *property = Openbox::instance->property(); - - otk::OBProperty::StringVect newnames = _names; - newnames[i] = name; - property->set(_info->rootWindow(), otk::OBProperty::net_desktop_names, - otk::OBProperty::utf8, newnames); -} - - -void OBRootWindow::mapRequestHandler(const XMapRequestEvent &e) -{ - otk::OtkEventHandler::mapRequestHandler(e); - -#ifdef DEBUG - printf("MapRequest for 0x%lx\n", e.window); -#endif // DEBUG - - /* - MapRequest events come here even after the window exists instead of going - right to the client window, because of how they are sent and their struct - layout. - */ - OBClient *c = Openbox::instance->findClient(e.window); - - if (c) { - if (c->shaded()) - c->shade(false); - // XXX: uniconify the window - c->focus(); - } else - Openbox::instance->screen(_info->screen())->manageWindow(e.window); -} } diff --git a/src/screen.cc b/src/screen.cc index d7cea024..991d3dc5 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -9,6 +9,10 @@ extern "C" { # include #endif // HAVE_STDIO_H +#ifdef HAVE_STRING_H +# include +#endif // HAVE_STRING_H + #ifdef HAVE_UNISTD_H # include # include @@ -42,8 +46,8 @@ namespace ob { OBScreen::OBScreen(int screen) - : _number(screen), - _root(screen) + : OBWidget(OBWidget::Type_Root), + _number(screen) { assert(screen >= 0); assert(screen < ScreenCount(otk::OBDisplay::display)); _info = otk::OBDisplay::screenInfo(screen); @@ -92,26 +96,33 @@ OBScreen::OBScreen(int screen) _style.load(sconfig); // set up notification of netwm support - setSupportedAtoms(); + changeSupportedAtoms(); - // Set the netwm properties for geometry and viewport + // Set the netwm properties for geometry unsigned long geometry[] = { _info->width(), _info->height() }; Openbox::instance->property()->set(_info->rootWindow(), otk::OBProperty::net_desktop_geometry, otk::OBProperty::Atom_Cardinal, geometry, 2); - unsigned long viewport[] = { 0, 0 }; - Openbox::instance->property()->set(_info->rootWindow(), - otk::OBProperty::net_desktop_viewport, - otk::OBProperty::Atom_Cardinal, - viewport, 2); // Set the net_desktop_names property std::vector names; python_get_stringlist("desktop_names", &names); - _root.setDesktopNames(names); - + Openbox::instance->property()->set(_info->rootWindow(), + otk::OBProperty::net_desktop_names, + otk::OBProperty::utf8, + names); + // the above set() will cause the updateDesktopNames to fire right away so + // we have a list of desktop names + + if (!python_get_long("number_of_desktops", &_num_desktops)) + _num_desktops = 4; + changeNumDesktops(_num_desktops); // set the hint + + _desktop = 0; + changeDesktop(0); // set the hint + // create the window which gets focus when no clients get it XSetWindowAttributes attr; attr.override_redirect = true; @@ -122,8 +133,11 @@ OBScreen::OBScreen(int screen) // these may be further updated if any pre-existing windows are found in // the manageExising() function - setClientList(); // initialize the client lists, which will be empty + 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::instance->registerHandler(_info->rootWindow(), this); } @@ -250,11 +264,11 @@ void OBScreen::calcArea() if (old_area != _area) // XXX: re-maximize windows - setWorkArea(); + changeWorkArea(); } -void OBScreen::setSupportedAtoms() +void OBScreen::changeSupportedAtoms() { // create the netwm support window _supportwindow = XCreateSimpleWindow(otk::OBDisplay::display, @@ -280,10 +294,8 @@ void OBScreen::setSupportedAtoms() Atom supported[] = { -/* otk::OBProperty::net_current_desktop, otk::OBProperty::net_number_of_desktops, -*/ otk::OBProperty::net_desktop_geometry, otk::OBProperty::net_desktop_viewport, otk::OBProperty::net_active_window, @@ -353,7 +365,7 @@ void OBScreen::setSupportedAtoms() } -void OBScreen::setClientList() +void OBScreen::changeClientList() { Window *windows; unsigned int size = clients.size(); @@ -379,11 +391,11 @@ void OBScreen::setClientList() if (size) delete [] windows; - setStackingList(); + changeStackingList(); } -void OBScreen::setStackingList() +void OBScreen::changeStackingList() { Window *windows; unsigned int size = _stacking.size(); @@ -414,32 +426,20 @@ void OBScreen::setStackingList() } -void OBScreen::setWorkArea() { - unsigned long area[] = { _area.x(), _area.y(), - _area.width(), _area.height() }; +void OBScreen::changeWorkArea() { + unsigned long *dims = new unsigned long[4 * _num_desktops]; + for (long i = 0; i < _num_desktops; ++i) { + // XXX: this could be different for each workspace + dims[(i * 4) + 0] = _area.x(); + dims[(i * 4) + 1] = _area.y(); + dims[(i * 4) + 2] = _area.width(); + dims[(i * 4) + 3] = _area.height(); + } Openbox::instance->property()->set(_info->rootWindow(), otk::OBProperty::net_workarea, otk::OBProperty::Atom_Cardinal, - area, 4); - /* - if (workspacesList.size() > 0) { - unsigned long *dims = new unsigned long[4 * workspacesList.size()]; - for (unsigned int i = 0, m = workspacesList.size(); i < m; ++i) { - // XXX: this could be different for each workspace - const otk::Rect &area = availableArea(); - dims[(i * 4) + 0] = area.x(); - dims[(i * 4) + 1] = area.y(); - dims[(i * 4) + 2] = area.width(); - dims[(i * 4) + 3] = area.height(); - } - xatom->set(getRootWindow(), otk::OBProperty::net_workarea, - otk::OBProperty::Atom_Cardinal, - dims, 4 * workspacesList.size()); - delete [] dims; - } else - xatom->set(getRootWindow(), otk::OBProperty::net_workarea, - otk::OBProperty::Atom_Cardinal, 0, 0); - */ + dims, 4 * _num_desktops); + delete [] dims; } @@ -515,7 +515,7 @@ void OBScreen::manageWindow(Window window) _stacking.push_back(client); restack(true, client); // update the root properties - setClientList(); + changeClientList(); Openbox::instance->bindings()->grabButtons(true, client); @@ -594,7 +594,7 @@ void OBScreen::unmanageWindow(OBClient *client) delete client; // update the root properties - setClientList(); + changeClientList(); } void OBScreen::restack(bool raise, OBClient *client) @@ -621,7 +621,150 @@ void OBScreen::restack(bool raise, OBClient *client) wins.push_back((*it)->frame->window()); XRestackWindows(otk::OBDisplay::display, &wins[0], wins.size()); - setStackingList(); + changeStackingList(); +} + +void OBScreen::changeDesktop(long desktop) +{ + assert(desktop >= 0 && desktop < _num_desktops); + + if (!(desktop >= 0 && desktop < _num_desktops)) return; + + long old = _desktop; + + _desktop = desktop; + Openbox::instance->property()->set(_info->rootWindow(), + otk::OBProperty::net_current_desktop, + otk::OBProperty::Atom_Cardinal, + _desktop); + + OBClient::List::iterator it, end = clients.end(); + for (it = clients.begin(); it != end; ++it) { + if ((*it)->desktop() == old) { + // XXX hide + } else if ((*it)->desktop() == _desktop) { + // XXX show + } + } } +void OBScreen::changeNumDesktops(long num) +{ + assert(num > 0); + + if (!(num > 0)) return; + + _num_desktops = num; + Openbox::instance->property()->set(_info->rootWindow(), + otk::OBProperty::net_number_of_desktops, + otk::OBProperty::Atom_Cardinal, + _num_desktops); + + // set the viewport hint + unsigned long *viewport = new unsigned long[_num_desktops * 2]; + memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2); + Openbox::instance->property()->set(_info->rootWindow(), + otk::OBProperty::net_desktop_viewport, + otk::OBProperty::Atom_Cardinal, + viewport, _num_desktops * 2); + delete [] viewport; + + // update the work area hint + changeWorkArea(); +} + + +void OBScreen::updateDesktopNames() +{ + const otk::OBProperty *property = Openbox::instance->property(); + + unsigned long num = (unsigned) -1; + + if (!property->get(_info->rootWindow(), + otk::OBProperty::net_desktop_names, + otk::OBProperty::utf8, &num, &_desktop_names)) + _desktop_names.clear(); + while ((long)_desktop_names.size() < _num_desktops) + _desktop_names.push_back("Unnamed"); +} + + +void OBScreen::setDesktopName(long i, const std::string &name) +{ + assert(i >= 0); + + if (i >= _num_desktops) return; + + const otk::OBProperty *property = Openbox::instance->property(); + + otk::OBProperty::StringVect newnames = _desktop_names; + newnames[i] = name; + property->set(_info->rootWindow(), otk::OBProperty::net_desktop_names, + otk::OBProperty::utf8, newnames); +} + + +void OBScreen::propertyHandler(const XPropertyEvent &e) +{ + otk::OtkEventHandler::propertyHandler(e); + + const otk::OBProperty *property = Openbox::instance->property(); + + // compress changes to a single property into a single change + XEvent ce; + while (XCheckTypedEvent(otk::OBDisplay::display, e.type, &ce)) { + // XXX: it would be nice to compress ALL changes to a property, not just + // changes in a row without other props between. + if (ce.xproperty.atom != e.atom) { + XPutBackEvent(otk::OBDisplay::display, &ce); + break; + } + } + + if (e.atom == property->atom(otk::OBProperty::net_desktop_names)) + updateDesktopNames(); +} + + +void OBScreen::clientMessageHandler(const XClientMessageEvent &e) +{ + otk::OtkEventHandler::clientMessageHandler(e); + + if (e.format != 32) return; + + const otk::OBProperty *property = Openbox::instance->property(); + + if (e.message_type == property->atom(otk::OBProperty::net_current_desktop)) { + changeDesktop(e.data.l[0]); + } else if (e.message_type == + property->atom(otk::OBProperty::net_number_of_desktops)) { + changeNumDesktops(e.data.l[0]); + } + // XXX: so many client messages to handle here! ..or not.. they go to clients +} + + +void OBScreen::mapRequestHandler(const XMapRequestEvent &e) +{ + otk::OtkEventHandler::mapRequestHandler(e); + +#ifdef DEBUG + printf("MapRequest for 0x%lx\n", e.window); +#endif // DEBUG + + /* + MapRequest events come here even after the window exists instead of going + right to the client window, because of how they are sent and their struct + layout. + */ + OBClient *c = Openbox::instance->findClient(e.window); + + if (c) { + if (c->shaded()) + c->shade(false); + // XXX: uniconify the window + c->focus(); + } else + manageWindow(e.window); +} } diff --git a/src/screen.hh b/src/screen.hh index e57ab2ed..aea9d293 100644 --- a/src/screen.hh +++ b/src/screen.hh @@ -11,14 +11,17 @@ extern "C" { } #include "client.hh" -#include "rootwindow.hh" +#include "widget.hh" #include "otk/image.hh" #include "otk/strut.hh" #include "otk/rect.hh" #include "otk/style.hh" -#include "otk/configuration.hh" // TEMPORARY +#include "otk/screeninfo.hh" +#include "otk/eventhandler.hh" +#include "otk/property.hh" #include +#include namespace ob { @@ -28,7 +31,7 @@ class OBRootWindow; //! Manages a single screen /*! */ -class OBScreen { +class OBScreen : public otk::OtkEventHandler, public OBWidget { public: //! Holds a list of otk::Strut objects typedef std::list StrutList; @@ -61,9 +64,6 @@ private: //! The style with which to render on the screen otk::Style _style; - //! The screen's root window - OBRootWindow _root; - //! Is the root colormap currently installed? bool _root_cmap_installed; @@ -83,26 +83,38 @@ private: //! A list of all managed clients on the screen, in their stacking order OBClient::List _stacking; + //! The desktop currently being displayed + long _desktop; + + //! The number of desktops + long _num_desktops; + + //! The names of all desktops + otk::OBProperty::StringVect _desktop_names; + //! Calculate the OBScreen::_area member void calcArea(); //! Set the list of supported NETWM atoms on the root window - void setSupportedAtoms(); + void changeSupportedAtoms(); //! Set the client list on the root window /*! Sets the _NET_CLIENT_LIST root window property.
Also calls OBScreen::updateStackingList. */ - void setClientList(); + void changeClientList(); //! Set the client stacking list on the root window /*! Set the _NET_CLIENT_LIST_STACKING root window property. */ - void setStackingList(); + void changeStackingList(); //! Set the work area hint on the root window /*! Set the _NET_WORKAREA root window property. */ - void setWorkArea(); + void changeWorkArea(); + + //! Get desktop names from the root window property + void updateDesktopNames(); public: #ifndef SWIG @@ -128,6 +140,8 @@ public: inline const otk::Style *style() const { return &_style; } //! An offscreen window which gets focus when nothing else has it inline Window focuswindow() const { return _focuswindow; } + //! Returns the desktop being displayed + inline unsigned long desktop() const { return _desktop; } //! Update's the screen's combined strut of all the clients. /*! @@ -152,6 +166,33 @@ public: //! Raises/Lowers a client window above/below all others in its stacking //! layer void restack(bool raise, OBClient *client); + + //! Changes to the specified desktop, displaying windows on it and hiding + //! windows on the others. + /*! + @param desktop The number of the desktop to switch to (starts from 0). + If the desktop is out of valid range, it is ignored. + */ + void changeDesktop(long desktop); + + //! Changes the number of desktops. + /*! + @param num The number of desktops that should exist. This value must be + greater than 0 or it will be ignored. + */ + void changeNumDesktops(long num); + + //! Sets the name of a desktop + /*! + @param i The index of the desktop to set the name for (starts at 0) + @param name The name to set for the desktop + If the index is too large, it is simply ignored. + */ + void setDesktopName(long i, const std::string &name); + + virtual void propertyHandler(const XPropertyEvent &e); + virtual void clientMessageHandler(const XClientMessageEvent &e); + virtual void mapRequestHandler(const XMapRequestEvent &e); }; } -- 2.39.2