X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fopenboxwrap.c;fp=openbox%2Fopenboxwrap.c;h=c73e725ae59a6b9d78a954bba8b9b44d03006a38;hb=f8a47de5ec444c452093371e3db16857eb39a490;hp=0000000000000000000000000000000000000000;hpb=8ba0586bcbdc7fe9648f1063812126d71a041670;p=chaz%2Fopenbox diff --git a/openbox/openboxwrap.c b/openbox/openboxwrap.c new file mode 100644 index 00000000..c73e725a --- /dev/null +++ b/openbox/openboxwrap.c @@ -0,0 +1,502 @@ +#include "openboxwrap.h" +#include "openbox.h" +#include "screen.h" +#include "prop.h" + +/*************************************************************************** + + Define the type 'OpenboxWrap' + + ***************************************************************************/ + +#define IS_OWRAP(v) ((v)->ob_type == &OpenboxWrapType) +#define CHECK_OWRAP(self, funcname) { \ + if (!IS_OWRAP(self)) { \ + PyErr_SetString(PyExc_TypeError, \ + "descriptor '" funcname "' requires a 'Openbox' " \ + "object"); \ + return NULL; \ + } \ +} + + +staticforward PyTypeObject OpenboxWrapType; + +/*************************************************************************** + + Attribute methods + + ***************************************************************************/ + +static PyObject *owrap_shutdown(OpenboxWrap *self, PyObject *args) +{ + CHECK_OWRAP(self, "shutdown"); + if (!PyArg_ParseTuple(args, ":shutdown")) + return NULL; + ob_shutdown = TRUE; + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *owrap_restart(OpenboxWrap *self, PyObject *args) +{ + char *path = NULL; + + CHECK_OWRAP(self, "restart"); + if (!PyArg_ParseTuple(args, "|s:restart", &path)) + return NULL; + ob_shutdown = ob_restart = TRUE; + ob_restart_path = path; + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *owrap_state(OpenboxWrap *self, PyObject *args) +{ + CHECK_OWRAP(self, "state"); + if (!PyArg_ParseTuple(args, ":state")) + return NULL; + return PyInt_FromLong(ob_state); +} + +static PyObject *owrap_desktop(OpenboxWrap *self, PyObject *args) +{ + CHECK_OWRAP(self, "desktop"); + if (!PyArg_ParseTuple(args, ":desktop")) + return NULL; + return PyInt_FromLong(screen_desktop); +} + +static PyObject *owrap_setDesktop(OpenboxWrap *self, PyObject *args) +{ + int desktop; + + CHECK_OWRAP(self, "setDesktop"); + if (!PyArg_ParseTuple(args, "i:setDesktop", &desktop)) + return NULL; + if (desktop < 0 || (unsigned)desktop >= screen_num_desktops) { + PyErr_SetString(PyExc_ValueError, "invalid desktop"); + return NULL; + } + screen_set_desktop(desktop); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *owrap_setNextDesktop(OpenboxWrap *self, PyObject *args) +{ + gboolean wrap = TRUE; + guint d; + + CHECK_OWRAP(self, "setNextDesktop"); + if (!PyArg_ParseTuple(args, "|i:setNextDesktop", &wrap)) + return NULL; + d = screen_desktop + 1; + if (d >= screen_num_desktops && wrap) + d = 0; + if (d < screen_num_desktops) + screen_set_desktop(d); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *owrap_setPreviousDesktop(OpenboxWrap *self, PyObject *args) +{ + gboolean wrap = TRUE; + guint d; + + CHECK_OWRAP(self, "setPreviousDesktop"); + if (!PyArg_ParseTuple(args, "|i:setPreviousDesktop", &wrap)) + return NULL; + d = screen_desktop - 1; + if (d >= screen_num_desktops && wrap) + d = screen_num_desktops - 1; + if (d < screen_num_desktops) + screen_set_desktop(d); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *owrap_numDesktops(OpenboxWrap *self, PyObject *args) +{ + CHECK_OWRAP(self, "numDesktops"); + if (!PyArg_ParseTuple(args, ":numDesktops")) + return NULL; + return PyInt_FromLong(screen_num_desktops); +} + +static PyObject *owrap_setNumDesktops(OpenboxWrap *self, PyObject *args) +{ + int desktops; + + CHECK_OWRAP(self, "setNumDesktops"); + if (!PyArg_ParseTuple(args, "i:setNumDesktops", &desktops)) + return NULL; + if (desktops <= 0) { + PyErr_SetString(PyExc_ValueError, "invalid number of desktops"); + return NULL; + } + screen_set_num_desktops(desktops); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *owrap_desktopNames(OpenboxWrap *self, PyObject *args) +{ + PyObject *tuple; + int i, s; + + CHECK_OWRAP(self, "desktopNames"); + if (!PyArg_ParseTuple(args, ":desktopNames")) + return NULL; + s = screen_desktop_names->len; + tuple = PyTuple_New(s); + for (i = 0; i < s; ++i) + PyTuple_SET_ITEM(tuple, i, g_ptr_array_index(screen_desktop_names, i)); + return tuple; +} + +static PyObject *owrap_setDesktopNames(OpenboxWrap *self, PyObject *args) +{ + PyObject *seq; + int i, s; + GPtrArray *data; + + CHECK_OWRAP(self, "setDesktopNames"); + if (!PyArg_ParseTuple(args, "O:setDesktopNames", &seq)) + return NULL; + if (!PySequence_Check(seq)) + PyErr_SetString(PyExc_TypeError, "expected a sequence"); + return NULL; + + s = PySequence_Size(seq); + for (i = 0; i < s; ++i) { + PyObject *item; + gboolean check; + item = PySequence_GetItem(seq, i); /* new */ + check = PyString_Check(item); + Py_DECREF(item); + if (!check) { + PyErr_SetString(PyExc_TypeError, "expected a sequence of strings"); + return NULL; + } + } + + data = g_ptr_array_sized_new(s); + for (i = 0; i < s; ++i) { + PyObject *item; + item = PySequence_GetItem(seq, i); /* new */ + g_ptr_array_index(data, i) = PyString_AsString(item); /* borrowed */ + Py_DECREF(item); + } + + PROP_SETSA(ob_root, net_desktop_names, utf8, data); + g_ptr_array_free(data, TRUE); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *owrap_showingDesktop(OpenboxWrap *self, PyObject *args) +{ + CHECK_OWRAP(self, "showingDesktop"); + if (!PyArg_ParseTuple(args, ":showingDesktop")) + return NULL; + return PyInt_FromLong(!!screen_showing_desktop); +} + +static PyObject *owrap_setShowingDesktop(OpenboxWrap *self, PyObject *args) +{ + int show; + + CHECK_OWRAP(self, "setShowingDesktop"); + if (!PyArg_ParseTuple(args, "i:setShowingDesktop", &show)) + return NULL; + screen_show_desktop(show); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *owrap_screenArea(OpenboxWrap *self, PyObject *args) +{ + int desktop; + Rect *area; + PyObject *tuple; + + CHECK_OWRAP(self, "screenArea"); + if (!PyArg_ParseTuple(args, "i:screenArea", &desktop)) + return NULL; + + area = screen_area(desktop); + if (area == NULL) { + PyErr_SetString(PyExc_ValueError, "invalid desktop"); + return NULL; + } + + tuple = PyTuple_New(4); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(area->x)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(area->y)); + PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(area->width)); + PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(area->height)); + return tuple; +} + +static PyObject *owrap_screenStrut(OpenboxWrap *self, PyObject *args) +{ + int desktop; + Strut *strut; + PyObject *tuple; + + CHECK_OWRAP(self, "screenStrut"); + if (!PyArg_ParseTuple(args, "i:screenStrut", &desktop)) + return NULL; + + strut = screen_strut(desktop); + if (strut == NULL) { + PyErr_SetString(PyExc_ValueError, "invalid desktop"); + return NULL; + } + + tuple = PyTuple_New(4); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(strut->left)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(strut->top)); + PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(strut->right)); + PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(strut->bottom)); + return tuple; +} + +static PyObject *owrap_physicalSize(OpenboxWrap *self, PyObject *args) +{ + PyObject *tuple; + + CHECK_OWRAP(self, "physicalSize"); + if (!PyArg_ParseTuple(args, ":physicalSize")) + return NULL; + + tuple = PyTuple_New(2); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(screen_physical_size.width)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(screen_physical_size.height)); + return tuple; +} + +static PyObject *owrap_screenNumber(OpenboxWrap *self, PyObject *args) +{ + CHECK_OWRAP(self, "screenNumber"); + if (!PyArg_ParseTuple(args, ":screenNumber")) + return NULL; + return PyInt_FromLong(ob_screen); +} + +static PyObject *owrap_rootWindow(OpenboxWrap *self, PyObject *args) +{ + CHECK_OWRAP(self, "rootWindow"); + if (!PyArg_ParseTuple(args, ":rootWindow")) + return NULL; + return PyInt_FromLong(ob_root); +} + +static PyObject *owrap_clientList(OpenboxWrap *self, PyObject *args) +{ + CHECK_OWRAP(self, "clientList"); + if (!PyArg_ParseTuple(args, ":clientList")) + return NULL; + Py_INCREF(self->client_list); + return self->client_list; +} + +#define METH(n, d) {#n, (PyCFunction)owrap_##n, METH_VARARGS, #d} + +static PyMethodDef OpenboxWrapMethods[] = { + METH(shutdown, + "Causes Openbox to shutdown and exit."), + METH(restart, + "Causes Openbox to shutdown and restart. If path is specified, " + "Openbox will shutdown and attempt to run the specified executable " + "instead of restarting itself. If that fails, however, it will " + "restart itself."), + METH(state, + "Returns Openbox's current state, this will be one of the State " + "constants."), + METH(desktop, + "Returns the number of the currently visible desktop. This will be " + "in the range of [0, numDesktops())."), + METH(setDesktop, + "Sets the specified desktop as the visible desktop."), + METH(setNextDesktop, + "Sets the visible desktop to the next desktop, optionally wrapping " + "around when reaching the last."), + METH(setPreviousDesktop, + "Sets the visible desktop to the previous desktop, optionally " + "wrapping around when reaching the first."), + METH(numDesktops, + "Returns the number of desktops available."), + METH(desktopNames, + "Returns a tuple of names, containing a name for each desktop. The " + "tuple may have a length greater than numDesktops() if more names " + "have been specified."), + METH(setDesktopNames, + "Sets the names for the desktops."), + METH(showingDesktop, + "Returns True or False, depicting if Openbox is in 'showing the " + "desktop' mode. In 'showing the desktop' mode, all normal clients " + "are hidden and the desktop is given focus if possible."), + METH(setShowingDesktop, + "Enters or leaves 'showing the desktop' mode. See showingDesktop() " + "for a description of this mode."), + METH(screenArea, + "Returns the on-screen available area. This is the area not reserved " + "by applications' struts. Windows should be placed within this area, " + "not within the physicalSize()."), + METH(screenStrut, + "Returns the combined strut which has been reserved by all " + "applications on the desktops."), + METH(physicalSize, + "Returns the physical size of the display device (in pixels)."), + METH(screenNumber, + "Returns the number of the screen on which Openbox is running."), + METH(rootWindow, + "Return the window id of the root window."), + METH(clientList, + "Returns a all clients currently being managed by Openbox. This list " + "is updated as clients are managed and closed/destroyed/released."), + { NULL, NULL, 0, NULL } +}; + +/*************************************************************************** + + Type methods/struct + + ***************************************************************************/ + +/*static PyObject *owrap_getattr(OpenboxWrap *self, char *name) +{ + CHECK_OWRAP(self, "getattr"); + return Py_FindMethod(OpenboxWrapAttributeMethods, (PyObject*)self, name); +}*/ + +static void owrap_dealloc(OpenboxWrap *self) +{ + PyObject_Del((PyObject*) self); +} + +static PyTypeObject OpenboxWrapType = { + PyObject_HEAD_INIT(NULL) + 0, + "Openbox", + sizeof(OpenboxWrap), + 0, + (destructor) owrap_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +/*************************************************************************** + + Define the type 'OpenboxState' + + ***************************************************************************/ + +#define IS_OSTATE(v) ((v)->ob_type == &OpenboxStateType) +#define CHECK_OSTATE(self, funcname) { \ + if (!IS_OSTATE(self)) { \ + PyErr_SetString(PyExc_TypeError, \ + "descriptor '" funcname "' requires a 'State' " \ + "object"); \ + return NULL; \ + } \ +} + +staticforward PyTypeObject OpenboxStateType; + +typedef struct OpenboxState { + PyObject_HEAD +} OpenboxState; + +static void ostate_dealloc(PyObject *self) +{ + PyObject_Del(self); +} + +static PyObject *ostate_getattr(OpenboxState *self, char *name) +{ + struct S { char *name; int val; }; + struct S s[] = { + { "Starting", State_Starting }, + { "Running", State_Running }, + { "Exiting", State_Exiting }, + { NULL, 0 } }; + int i; + + CHECK_OSTATE(self, "__getattr__"); + + for (i = 0; s[i].name != NULL; ++i) + if (!strcmp(s[i].name, name)) + return PyInt_FromLong(s[i].val); + PyErr_SetString(PyExc_AttributeError, "invalid attribute"); + return NULL; +} + +static PyTypeObject OpenboxStateType = { + PyObject_HEAD_INIT(NULL) + 0, + "State", + sizeof(OpenboxState), + 0, + (destructor) ostate_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + (getattrfunc) ostate_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +/*************************************************************************** + + External methods + + ***************************************************************************/ + +void openboxwrap_startup() +{ + PyObject *ob, *obdict, *state; + + OpenboxWrapType.ob_type = &PyType_Type; + OpenboxWrapType.tp_methods = OpenboxWrapMethods; + PyType_Ready(&OpenboxWrapType); + + /* get the ob module/dict */ + ob = PyImport_ImportModule("ob"); /* new */ + g_assert(ob != NULL); + obdict = PyModule_GetDict(ob); /* borrowed */ + g_assert(obdict != NULL); + + /* add an Openbox instance to the ob module */ + openboxwrap_obj = PyObject_New(OpenboxWrap, &OpenboxWrapType); + openboxwrap_obj->client_list = PyList_New(0); + + PyDict_SetItemString(obdict, "Openbox", (PyObject*) openboxwrap_obj); + + /* add an instance of OpenboxState */ + state = (PyObject*) PyObject_New(OpenboxState, &OpenboxStateType); + PyDict_SetItemString(obdict, "State", state); + Py_DECREF(state); + + Py_DECREF(ob); +} + +void openboxwrap_shutdown() +{ + Py_DECREF(openboxwrap_obj->client_list); + Py_DECREF(openboxwrap_obj); +}