433 lines
14 KiB
C
433 lines
14 KiB
C
#include "screenwrap.h"
|
|
#include "openbox.h"
|
|
#include "screen.h"
|
|
#include "kbind.h"
|
|
#include "mbind.h"
|
|
|
|
ScreenWrap *screenwrap_instance;
|
|
|
|
/***************************************************************************
|
|
|
|
Define the type 'ScreenWrap'
|
|
|
|
***************************************************************************/
|
|
|
|
#define IS_SWRAP(v) ((v)->ob_type == &ScreenWrapType)
|
|
#define CHECK_SWRAP(self, funcname) { \
|
|
if (!IS_SWRAP(self)) { \
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
"descriptor '" funcname "' a 'Screen' object"); \
|
|
return NULL; \
|
|
} \
|
|
}
|
|
|
|
staticforward PyTypeObject ScreenWrapType;
|
|
|
|
/***************************************************************************
|
|
|
|
Attribute methods
|
|
|
|
***************************************************************************/
|
|
|
|
static PyObject *swrap_number(ScreenWrap *self, PyObject *args)
|
|
{
|
|
CHECK_SWRAP(self, "number");
|
|
if (!PyArg_ParseTuple(args, ":number"))
|
|
return NULL;
|
|
return PyInt_FromLong(ob_screen);
|
|
}
|
|
|
|
static PyObject *swrap_rootWindow(ScreenWrap *self, PyObject *args)
|
|
{
|
|
CHECK_SWRAP(self, "rootWindow");
|
|
if (!PyArg_ParseTuple(args, ":rootWindow"))
|
|
return NULL;
|
|
return PyInt_FromLong(ob_root);
|
|
}
|
|
|
|
static PyObject *swrap_state(ScreenWrap *self, PyObject *args)
|
|
{
|
|
CHECK_SWRAP(self, "state");
|
|
if (!PyArg_ParseTuple(args, ":state"))
|
|
return NULL;
|
|
return PyInt_FromLong(ob_state);
|
|
}
|
|
|
|
static PyObject *swrap_numDesktops(ScreenWrap *self, PyObject *args)
|
|
{
|
|
CHECK_SWRAP(self, "numDesktops");
|
|
if (!PyArg_ParseTuple(args, ":numDesktops"))
|
|
return NULL;
|
|
return PyInt_FromLong(screen_num_desktops);
|
|
}
|
|
|
|
static PyObject *swrap_desktop(ScreenWrap *self, PyObject *args)
|
|
{
|
|
CHECK_SWRAP(self, "desktop");
|
|
if (!PyArg_ParseTuple(args, ":desktop"))
|
|
return NULL;
|
|
return PyInt_FromLong(screen_desktop);
|
|
}
|
|
|
|
static PyObject *swrap_physicalSize(ScreenWrap *self, PyObject *args)
|
|
{
|
|
PyObject *tuple;
|
|
|
|
CHECK_SWRAP(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 *swrap_showingDesktop(ScreenWrap *self, PyObject *args)
|
|
{
|
|
CHECK_SWRAP(self, "showingDesktop");
|
|
if (!PyArg_ParseTuple(args, ":showingDesktop"))
|
|
return NULL;
|
|
return PyInt_FromLong(screen_showing_desktop ? 1 : 0);
|
|
}
|
|
|
|
static PyObject *swrap_desktopLayout(ScreenWrap *self, PyObject *args)
|
|
{
|
|
PyObject *tuple;
|
|
|
|
CHECK_SWRAP(self, "desktopLayout");
|
|
if (!PyArg_ParseTuple(args, ":desktopLayout"))
|
|
return NULL;
|
|
tuple = PyTuple_New(4);
|
|
PyTuple_SET_ITEM(tuple, 0,
|
|
PyInt_FromLong(screen_desktop_layout.orientation));
|
|
PyTuple_SET_ITEM(tuple, 1,
|
|
PyInt_FromLong(screen_desktop_layout.start_corner));
|
|
PyTuple_SET_ITEM(tuple, 2,
|
|
PyInt_FromLong(screen_desktop_layout.rows));
|
|
PyTuple_SET_ITEM(tuple, 3,
|
|
PyInt_FromLong(screen_desktop_layout.columns));
|
|
return tuple;
|
|
}
|
|
|
|
static PyObject *swrap_desktopNames(ScreenWrap *self, PyObject *args)
|
|
{
|
|
PyObject *list;
|
|
guint s, i;
|
|
|
|
CHECK_SWRAP(self, "desktopNames");
|
|
if (!PyArg_ParseTuple(args, ":desktopNames"))
|
|
return NULL;
|
|
s = screen_desktop_names->len;
|
|
list = PyList_New(s);
|
|
for (i = 0; i < s; ++i)
|
|
PyList_SET_ITEM(list, i, PyString_FromString
|
|
(g_ptr_array_index(screen_desktop_names, i)));
|
|
return list;
|
|
}
|
|
|
|
static PyObject *swrap_area(ScreenWrap *self, PyObject *args)
|
|
{
|
|
PyObject * tuple;
|
|
Rect *r;
|
|
guint i;
|
|
|
|
CHECK_SWRAP(self, "area");
|
|
if (!PyArg_ParseTuple(args, "i:area", &i))
|
|
return NULL;
|
|
r = screen_area(i);
|
|
if (r == NULL) {
|
|
PyErr_SetString(PyExc_IndexError,
|
|
"the requested desktop was not valid");
|
|
return NULL;
|
|
}
|
|
tuple = PyTuple_New(4);
|
|
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(r->x));
|
|
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(r->y));
|
|
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(r->width));
|
|
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(r->height));
|
|
return tuple;
|
|
}
|
|
|
|
static PyObject *swrap_strut(ScreenWrap *self, PyObject *args)
|
|
{
|
|
PyObject *tuple;
|
|
Strut *s;
|
|
guint i;
|
|
|
|
CHECK_SWRAP(self, "strut");
|
|
if (!PyArg_ParseTuple(args, "i:strut", &i))
|
|
return NULL;
|
|
s = screen_strut(i);
|
|
if (s == NULL) {
|
|
PyErr_SetString(PyExc_IndexError,
|
|
"the requested desktop was not valid");
|
|
return NULL;
|
|
}
|
|
tuple = PyTuple_New(4);
|
|
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(s->left));
|
|
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(s->top));
|
|
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(s->right));
|
|
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(s->bottom));
|
|
return tuple;
|
|
}
|
|
|
|
static PyObject *swrap_grabKey(ScreenWrap *self, PyObject *args)
|
|
{
|
|
PyObject *item, *tuple;
|
|
GList *keylist = NULL, *it;
|
|
int i, s;
|
|
gboolean grab = FALSE;
|
|
|
|
CHECK_SWRAP(self, "grabKey");
|
|
if (!PyArg_ParseTuple(args, "O:grabKey", &tuple))
|
|
return NULL;
|
|
|
|
if (PyTuple_Check(tuple)) {
|
|
s = PyTuple_GET_SIZE(tuple);
|
|
if (s > 0) {
|
|
for (i = 0; i < s; ++i) {
|
|
item = PyTuple_GET_ITEM(tuple, i);
|
|
if (!PyString_Check(item))
|
|
break;
|
|
keylist = g_list_append(keylist,
|
|
g_strdup(PyString_AsString(item)));
|
|
}
|
|
if (i == s)
|
|
grab = kbind_add(keylist);
|
|
|
|
for (it = keylist; it != NULL; it = it->next)
|
|
g_free(it->data);
|
|
g_list_free(it);
|
|
|
|
if (grab) {
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"the key could not be grabbed");
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, "expected a tuple of strings");
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *swrap_clearKeyGrabs(ScreenWrap *self, PyObject *args)
|
|
{
|
|
CHECK_SWRAP(self, "clearKeyGrabs");
|
|
if (!PyArg_ParseTuple(args, ":clearKeyGrabs"))
|
|
return NULL;
|
|
kbind_clearall();
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject *swrap_grabKeyboard(ScreenWrap *self, PyObject *args)
|
|
{
|
|
int grab;
|
|
|
|
CHECK_SWRAP(self, "grabKeyboard");
|
|
if (!PyArg_ParseTuple(args, "i:grabKeyboard", &grab))
|
|
return NULL;
|
|
if (!kbind_grab_keyboard(grab)) {
|
|
PyErr_SetString(PyExc_RuntimeError, "failed to grab keyboard");
|
|
return NULL;
|
|
}
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject *swrap_grabButton(ScreenWrap *self, PyObject *args)
|
|
{
|
|
char *name;
|
|
char *context_str;
|
|
GQuark context;
|
|
|
|
CHECK_SWRAP(self, "grabButton");
|
|
if (!PyArg_ParseTuple(args, "ss:grabKey", &name, &context_str))
|
|
return NULL;
|
|
|
|
context = g_quark_try_string(context_str);
|
|
|
|
if (!context) {
|
|
PyErr_SetString(PyExc_ValueError, "invalid context");
|
|
return NULL;
|
|
}
|
|
|
|
if (mbind_add(name, context)) {
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"the button could not be grabbed");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static PyObject *swrap_clearButtonGrabs(ScreenWrap *self, PyObject *args)
|
|
{
|
|
CHECK_SWRAP(self, "clearButtonGrabs");
|
|
if (!PyArg_ParseTuple(args, ":clearButtonGrabs"))
|
|
return NULL;
|
|
mbind_clearall();
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject *swrap_grabPointer(ScreenWrap *self, PyObject *args)
|
|
{
|
|
int grab;
|
|
|
|
CHECK_SWRAP(self, "grabPointer");
|
|
if (!PyArg_ParseTuple(args, "i:grabPointer", &grab))
|
|
return NULL;
|
|
if (!mbind_grab_pointer(grab)) {
|
|
PyErr_SetString(PyExc_RuntimeError, "failed to grab pointer");
|
|
return NULL;
|
|
}
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyMethodDef ScreenWrapAttributeMethods[] = {
|
|
{"number", (PyCFunction)swrap_number, METH_VARARGS,
|
|
"Screen.number() -- Returns the number of the screen on the X server on "
|
|
"which this Openbox instance is running."},
|
|
{"rootWindow", (PyCFunction)swrap_rootWindow, METH_VARARGS,
|
|
"Screen.rootWindow() -- Returns the window id of the root window."},
|
|
{"state", (PyCFunction)swrap_state, METH_VARARGS,
|
|
"Screen.state() -- Returns the running state of Openbox. One of the "
|
|
"ob.State_ constants."},
|
|
{"numDesktops", (PyCFunction)swrap_numDesktops, METH_VARARGS,
|
|
"Screen.numDesktops() -- Returns the number of desktops available."},
|
|
{"desktop", (PyCFunction)swrap_desktop, METH_VARARGS,
|
|
"Screen.desktop() -- Returns the currently visible desktop."},
|
|
{"physicalSize", (PyCFunction)swrap_physicalSize, METH_VARARGS,
|
|
"Screen.physicalSize() -- Returns the physical size (in pixels) of the "
|
|
"display in a tuple. The tuple is formatted as (width, height)."},
|
|
{"showingDesktop", (PyCFunction)swrap_showingDesktop, METH_VARARGS,
|
|
"Screen.showingDesktop() -- Returns if in showing-the-desktop mode or "
|
|
"not."},
|
|
{"desktopNames", (PyCFunction)swrap_desktopNames, METH_VARARGS,
|
|
"Screen.desktopNames() -- Returns a list of the names of all the "
|
|
"desktops, and possibly for desktops beyond those. The names are encoded "
|
|
"as UTF-8."},
|
|
{"desktopLayout", (PyCFunction)swrap_desktopLayout, METH_VARARGS,
|
|
"Screen.desktopLayout() -- Returns the layout of the desktops, as "
|
|
"specified by a compliant pager, in a tuple. The format of the tuple is "
|
|
"(orientation, corner, rows, columns). Where, orientation is one of the "
|
|
"ob.Orientation_ constants, corner is one of the ob.Corner_ constants, "
|
|
"and rows and columns specify the size of the layout. The rows and "
|
|
"columns will always include all the desktops."},
|
|
{"area", (PyCFunction)swrap_area, METH_VARARGS,
|
|
"Screen.area(d) -- Returns the usuable area on the Screen for a desktop, "
|
|
"in the form of a tuple. The tuples format is (x, y, width, height). The "
|
|
"desktop must be in the range of desktops on the screen, or 0xffffffff "
|
|
"to get a combined area for 'all desktops'."},
|
|
{"strut", (PyCFunction)swrap_area, METH_VARARGS,
|
|
"Screen.strut(d) -- Returns the combined strut of all clients on a "
|
|
"desktop, in the form of a tuple. The tuples format is "
|
|
"(left, top, right, bottom). The desktop must be in the range of "
|
|
"desktops on the screen, or 0xffffffff to get a combined strut for "
|
|
"'all desktops'."},
|
|
{"grabKey", (PyCFunction)swrap_grabKey, METH_VARARGS,
|
|
"Screen.grabKey(('Mod1-C-a', 'd')) -- Grabs a key chain so that key "
|
|
"events for it will occur. The argument must be a tuple of one or "
|
|
"more elements. Each key element is made up of "
|
|
"Modifier-Modifier-...-Key, where Modifier is one of Mod1, Mod2, "
|
|
"Mod3, Mod4, Mod5, S (for Shift), or C (for Control)."},
|
|
{"clearKeyGrabs", (PyCFunction)swrap_clearKeyGrabs, METH_VARARGS,
|
|
"Screen.clearKeyGrabs() -- Removes all key grabs that have been done "
|
|
"with grabKey()."},
|
|
{"grabKeyboard", (PyCFunction)swrap_grabKeyboard, METH_VARARGS,
|
|
"Screen.grabKeyboard(grab) -- Grabs or ungrabs the entire keyboard. When "
|
|
"the keyboard is grabbed, all key presses will be sent to the "
|
|
"hooks.keyboard hook. (grabbed keys will go to the hooks.events hook "
|
|
"too. "},
|
|
{"grabButton", (PyCFunction)swrap_grabButton, METH_VARARGS,
|
|
"Screen.grabButton('C-1', \"frame\") -- Grabs a pointer button "
|
|
"for the given context. The context must be one of the ob.Context_* "
|
|
"constants. The button definition is made up of "
|
|
"Modifier-Modifier-...-Button, where Modifier is one of Mod1, Mod2, "
|
|
"Mod3, Mod4, Mod5, S (for Shift), or C (for Control)."},
|
|
{"clearButtonGrabs", (PyCFunction)swrap_clearButtonGrabs, METH_VARARGS,
|
|
"Screen.clearButtonGrabs() -- Removes all button grabs that have been "
|
|
"done with grabButton()."},
|
|
{"grabPointer", (PyCFunction)swrap_grabPointer, METH_VARARGS,
|
|
"grabPointer(grab) -- Grabs or ungrabs the pointer device. When the "
|
|
"pointer is grabbed, all pointer events will be sent to the "
|
|
"hooks.pointer hook. (grabbed buttons will NOT go to the hooks.events "
|
|
"hook while the pointer is grabbed)."},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
/***************************************************************************
|
|
|
|
Type methods/struct
|
|
|
|
***************************************************************************/
|
|
|
|
static PyObject *swrap_getattr(ScreenWrap *self, char *name)
|
|
{
|
|
CHECK_SWRAP(self, "getattr");
|
|
return Py_FindMethod(ScreenWrapAttributeMethods, (PyObject*)self, name);
|
|
}
|
|
|
|
static void swrap_dealloc(ScreenWrap *self)
|
|
{
|
|
PyObject_Del((PyObject*) self);
|
|
}
|
|
|
|
static PyTypeObject ScreenWrapType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0,
|
|
"Screen",
|
|
sizeof(ScreenWrap),
|
|
0,
|
|
(destructor) swrap_dealloc, /*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
(getattrfunc) swrap_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 screenwrap_startup()
|
|
{
|
|
PyObject *ob, *obdict;
|
|
ScreenWrap *swrap;
|
|
|
|
ScreenWrapType.ob_type = &PyType_Type;
|
|
ScreenWrapType.tp_doc = "Wraps information and functionality global to an "
|
|
"instance of Openbox.";
|
|
PyType_Ready(&ScreenWrapType);
|
|
swrap = PyObject_New(ScreenWrap, &ScreenWrapType);
|
|
|
|
/* get the ob module/dict */
|
|
ob = PyImport_ImportModule("ob"); /* new */
|
|
g_assert(ob != NULL);
|
|
obdict = PyModule_GetDict(ob); /* borrowed */
|
|
g_assert(obdict != NULL);
|
|
|
|
PyDict_SetItemString(obdict, "Screen", (PyObject*)swrap);
|
|
Py_DECREF(swrap);
|
|
Py_DECREF(ob);
|
|
}
|
|
|
|
void screenwrap_shutdown()
|
|
{
|
|
}
|
|
|
|
|