]> icculus.org git repositories - dana/openbox.git/blob - c/screenwrap.c
merge the C branch into HEAD
[dana/openbox.git] / c / screenwrap.c
1 #include "screenwrap.h"
2 #include "openbox.h"
3 #include "screen.h"
4 #include "kbind.h"
5 #include "mbind.h"
6
7 ScreenWrap *screenwrap_instance;
8
9 /***************************************************************************
10  
11    Define the type 'ScreenWrap'
12
13  ***************************************************************************/
14
15 #define IS_SWRAP(v)  ((v)->ob_type == &ScreenWrapType)
16 #define CHECK_SWRAP(self, funcname) { \
17     if (!IS_SWRAP(self)) { \
18         PyErr_SetString(PyExc_TypeError, \
19                         "descriptor '" funcname "'  a 'Screen' object"); \
20         return NULL; \
21     } \
22 }
23
24 staticforward PyTypeObject ScreenWrapType;
25
26 /***************************************************************************
27  
28    Attribute methods
29  
30  ***************************************************************************/
31
32 static PyObject *swrap_number(ScreenWrap *self, PyObject *args)
33 {
34     CHECK_SWRAP(self, "number");
35     if (!PyArg_ParseTuple(args, ":number"))
36         return NULL;
37     return PyInt_FromLong(ob_screen);
38 }
39
40 static PyObject *swrap_rootWindow(ScreenWrap *self, PyObject *args)
41 {
42     CHECK_SWRAP(self, "rootWindow");
43     if (!PyArg_ParseTuple(args, ":rootWindow"))
44         return NULL;
45     return PyInt_FromLong(ob_root);
46 }
47
48 static PyObject *swrap_state(ScreenWrap *self, PyObject *args)
49 {
50     CHECK_SWRAP(self, "state");
51     if (!PyArg_ParseTuple(args, ":state"))
52         return NULL;
53     return PyInt_FromLong(ob_state);
54 }
55
56 static PyObject *swrap_numDesktops(ScreenWrap *self, PyObject *args)
57 {
58     CHECK_SWRAP(self, "numDesktops");
59     if (!PyArg_ParseTuple(args, ":numDesktops"))
60         return NULL;
61     return PyInt_FromLong(screen_num_desktops);
62 }
63
64 static PyObject *swrap_desktop(ScreenWrap *self, PyObject *args)
65 {
66     CHECK_SWRAP(self, "desktop");
67     if (!PyArg_ParseTuple(args, ":desktop"))
68         return NULL;
69     return PyInt_FromLong(screen_desktop);
70 }
71
72 static PyObject *swrap_physicalSize(ScreenWrap *self, PyObject *args)
73 {
74     PyObject *tuple;
75
76     CHECK_SWRAP(self, "physicalSize");
77     if (!PyArg_ParseTuple(args, ":physicalSize"))
78         return NULL;
79     tuple = PyTuple_New(2);
80     PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(screen_physical_size.width));
81     PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(screen_physical_size.height));
82     return tuple;
83 }
84
85 static PyObject *swrap_showingDesktop(ScreenWrap *self, PyObject *args)
86 {
87     CHECK_SWRAP(self, "showingDesktop");
88     if (!PyArg_ParseTuple(args, ":showingDesktop"))
89         return NULL;
90     return PyInt_FromLong(screen_showing_desktop ? 1 : 0);
91 }
92
93 static PyObject *swrap_desktopLayout(ScreenWrap *self, PyObject *args)
94 {
95     PyObject *tuple;
96
97     CHECK_SWRAP(self, "desktopLayout");
98     if (!PyArg_ParseTuple(args, ":desktopLayout"))
99         return NULL;
100     tuple = PyTuple_New(4);
101     PyTuple_SET_ITEM(tuple, 0,
102                      PyInt_FromLong(screen_desktop_layout.orientation));
103     PyTuple_SET_ITEM(tuple, 1,
104                      PyInt_FromLong(screen_desktop_layout.start_corner));
105     PyTuple_SET_ITEM(tuple, 2,
106                      PyInt_FromLong(screen_desktop_layout.rows));
107     PyTuple_SET_ITEM(tuple, 3,
108                      PyInt_FromLong(screen_desktop_layout.columns));
109     return tuple;
110 }
111
112 static PyObject *swrap_desktopNames(ScreenWrap *self, PyObject *args)
113 {
114     PyObject *list;
115     guint s, i;
116
117     CHECK_SWRAP(self, "desktopNames");
118     if (!PyArg_ParseTuple(args, ":desktopNames"))
119         return NULL;
120     s = screen_desktop_names->len;
121     list = PyList_New(s);
122     for (i = 0; i < s; ++i)
123         PyList_SET_ITEM(list, i, PyString_FromString
124                         (g_ptr_array_index(screen_desktop_names, i)));
125     return list;
126 }
127
128 static PyObject *swrap_area(ScreenWrap *self, PyObject *args)
129 {
130     PyObject * tuple;
131     Rect *r;
132     guint i;
133
134     CHECK_SWRAP(self, "area");
135     if (!PyArg_ParseTuple(args, "i:area", &i))
136         return NULL;
137     r = screen_area(i);
138     if (r == NULL) {
139         PyErr_SetString(PyExc_IndexError,
140                         "the requested desktop was not valid");
141         return NULL;
142     }
143     tuple = PyTuple_New(4);
144     PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(r->x));
145     PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(r->y));
146     PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(r->width));
147     PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(r->height));
148     return tuple;
149 }
150
151 static PyObject *swrap_strut(ScreenWrap *self, PyObject *args)
152 {
153     PyObject *tuple;
154     Strut *s;
155     guint i;
156
157     CHECK_SWRAP(self, "strut");
158     if (!PyArg_ParseTuple(args, "i:strut", &i))
159         return NULL;
160     s = screen_strut(i);
161     if (s == NULL) {
162         PyErr_SetString(PyExc_IndexError,
163                         "the requested desktop was not valid");
164         return NULL;
165     }
166     tuple = PyTuple_New(4);
167     PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(s->left));
168     PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(s->top));
169     PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(s->right));
170     PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(s->bottom));
171     return tuple;
172 }
173
174 static PyObject *swrap_grabKey(ScreenWrap *self, PyObject *args)
175 {
176     PyObject *item, *tuple;
177     GList *keylist = NULL, *it;
178     int i, s;
179     gboolean grab = FALSE;
180
181     CHECK_SWRAP(self, "grabKey");
182     if (!PyArg_ParseTuple(args, "O:grabKey", &tuple))
183         return NULL;
184
185     if (PyTuple_Check(tuple)) {
186         s = PyTuple_GET_SIZE(tuple);
187         if (s > 0) {
188             for (i = 0; i < s; ++i) {
189                 item = PyTuple_GET_ITEM(tuple, i);
190                 if (!PyString_Check(item))
191                     break;
192                 keylist = g_list_append(keylist,
193                                         g_strdup(PyString_AsString(item)));
194             }
195             if (i == s)
196                 grab = kbind_add(keylist);
197
198             for (it = keylist; it != NULL; it = it->next)
199                 g_free(it->data);
200             g_list_free(it);
201
202             if (grab) {
203                 Py_INCREF(Py_None);
204                 return Py_None;
205             } else {
206                 PyErr_SetString(PyExc_ValueError,
207                                 "the key could not be grabbed");
208                 return NULL;
209             }
210         }
211     }
212
213     PyErr_SetString(PyExc_TypeError, "expected a tuple of strings");
214     return NULL;
215 }
216
217 static PyObject *swrap_clearKeyGrabs(ScreenWrap *self, PyObject *args)
218 {
219     CHECK_SWRAP(self, "clearKeyGrabs");
220     if (!PyArg_ParseTuple(args, ":clearKeyGrabs"))
221         return NULL;
222     kbind_clearall();
223     Py_INCREF(Py_None);
224     return Py_None;
225 }
226
227 static PyObject *swrap_grabKeyboard(ScreenWrap *self, PyObject *args)
228 {
229     int grab;
230
231     CHECK_SWRAP(self, "grabKeyboard");
232     if (!PyArg_ParseTuple(args, "i:grabKeyboard", &grab))
233         return NULL;
234     if (!kbind_grab_keyboard(grab)) {
235         PyErr_SetString(PyExc_RuntimeError, "failed to grab keyboard");
236         return NULL;
237     }
238     Py_INCREF(Py_None);
239     return Py_None;
240 }
241
242 static PyObject *swrap_grabButton(ScreenWrap *self, PyObject *args)
243 {
244     char *name;
245     char *context_str;
246     GQuark context;
247
248     CHECK_SWRAP(self, "grabButton");
249     if (!PyArg_ParseTuple(args, "ss:grabKey", &name, &context_str))
250         return NULL;
251
252     context = g_quark_try_string(context_str);
253
254     if (!context) {
255         PyErr_SetString(PyExc_ValueError, "invalid context");
256         return NULL;
257     }
258
259     if (mbind_add(name, context)) {
260         Py_INCREF(Py_None);
261         return Py_None;
262     } else {
263         PyErr_SetString(PyExc_ValueError,
264                         "the button could not be grabbed");
265         return NULL;
266     }
267 }
268
269 static PyObject *swrap_clearButtonGrabs(ScreenWrap *self, PyObject *args)
270 {
271     CHECK_SWRAP(self, "clearButtonGrabs");
272     if (!PyArg_ParseTuple(args, ":clearButtonGrabs"))
273         return NULL;
274     mbind_clearall();
275     Py_INCREF(Py_None);
276     return Py_None;
277 }
278
279 static PyObject *swrap_grabPointer(ScreenWrap *self, PyObject *args)
280 {
281     int grab;
282
283     CHECK_SWRAP(self, "grabPointer");
284     if (!PyArg_ParseTuple(args, "i:grabPointer", &grab))
285         return NULL;
286     if (!mbind_grab_pointer(grab)) {
287         PyErr_SetString(PyExc_RuntimeError, "failed to grab pointer");
288         return NULL;
289     }
290     Py_INCREF(Py_None);
291     return Py_None;
292 }
293
294 static PyMethodDef ScreenWrapAttributeMethods[] = {
295     {"number", (PyCFunction)swrap_number, METH_VARARGS,
296      "Screen.number() -- Returns the number of the screen on the X server on "
297      "which this Openbox instance is running."},
298     {"rootWindow", (PyCFunction)swrap_rootWindow, METH_VARARGS,
299      "Screen.rootWindow() -- Returns the window id of the root window."},
300     {"state", (PyCFunction)swrap_state, METH_VARARGS,
301      "Screen.state() -- Returns the running state of Openbox. One of the "
302      "ob.State_ constants."},
303     {"numDesktops", (PyCFunction)swrap_numDesktops, METH_VARARGS,
304      "Screen.numDesktops() -- Returns the number of desktops available."},
305     {"desktop", (PyCFunction)swrap_desktop, METH_VARARGS,
306      "Screen.desktop() -- Returns the currently visible desktop."},
307     {"physicalSize", (PyCFunction)swrap_physicalSize, METH_VARARGS,
308      "Screen.physicalSize() -- Returns the physical size (in pixels) of the "
309      "display in a tuple. The tuple is formatted as (width, height)."},
310     {"showingDesktop", (PyCFunction)swrap_showingDesktop, METH_VARARGS,
311      "Screen.showingDesktop() -- Returns if in showing-the-desktop mode or "
312      "not."},
313     {"desktopNames", (PyCFunction)swrap_desktopNames, METH_VARARGS,
314      "Screen.desktopNames() -- Returns a list of the names of all the "
315      "desktops, and possibly for desktops beyond those. The names are encoded "
316      "as UTF-8."},
317     {"desktopLayout", (PyCFunction)swrap_desktopLayout, METH_VARARGS,
318      "Screen.desktopLayout() -- Returns the layout of the desktops, as "
319      "specified by a compliant pager, in a tuple. The format of the tuple is "
320      "(orientation, corner, rows, columns). Where, orientation is one of the "
321      "ob.Orientation_ constants, corner is one of the ob.Corner_ constants, "
322      "and rows and columns specify the size of the layout. The rows and "
323      "columns will always include all the desktops."},
324     {"area", (PyCFunction)swrap_area, METH_VARARGS,
325      "Screen.area(d) -- Returns the usuable area on the Screen for a desktop, "
326      "in the form of a tuple. The tuples format is (x, y, width, height). The "
327      "desktop must be in the range of desktops on the screen, or 0xffffffff "
328      "to get a combined area for 'all desktops'."},
329     {"strut", (PyCFunction)swrap_area, METH_VARARGS,
330      "Screen.strut(d) -- Returns the combined strut of all clients on a "
331      "desktop, in the form of a tuple. The tuples format is "
332      "(left, top, right, bottom). The desktop must be in the range of "
333      "desktops on the screen, or 0xffffffff to get a combined strut for "
334      "'all desktops'."},
335     {"grabKey", (PyCFunction)swrap_grabKey, METH_VARARGS,
336      "Screen.grabKey(('Mod1-C-a', 'd')) -- Grabs a key chain so that key "
337      "events for it will occur. The argument must be a tuple of one or "
338      "more elements. Each key element is made up of "
339      "Modifier-Modifier-...-Key, where Modifier is one of Mod1, Mod2, "
340      "Mod3, Mod4, Mod5, S (for Shift), or C (for Control)."},
341     {"clearKeyGrabs", (PyCFunction)swrap_clearKeyGrabs, METH_VARARGS,
342      "Screen.clearKeyGrabs() -- Removes all key grabs that have been done "
343      "with grabKey()."},
344     {"grabKeyboard", (PyCFunction)swrap_grabKeyboard, METH_VARARGS,
345      "Screen.grabKeyboard(grab) -- Grabs or ungrabs the entire keyboard. When "
346      "the keyboard is grabbed, all key presses will be sent to the "
347      "hooks.keyboard hook. (grabbed keys will go to the hooks.events hook "
348      "too. "},
349     {"grabButton", (PyCFunction)swrap_grabButton, METH_VARARGS,
350      "Screen.grabButton('C-1', \"frame\") -- Grabs a pointer button "
351      "for the given context. The context must be one of the ob.Context_* "
352      "constants. The button definition is made up of "
353      "Modifier-Modifier-...-Button, where Modifier is one of Mod1, Mod2, "
354      "Mod3, Mod4, Mod5, S (for Shift), or C (for Control)."},
355     {"clearButtonGrabs", (PyCFunction)swrap_clearButtonGrabs, METH_VARARGS,
356      "Screen.clearButtonGrabs() -- Removes all button grabs that have been "
357      "done with grabButton()."},
358     {"grabPointer", (PyCFunction)swrap_grabPointer, METH_VARARGS,
359      "grabPointer(grab) -- Grabs or ungrabs the pointer device. When the "
360      "pointer is grabbed, all pointer events will be sent to the "
361      "hooks.pointer  hook. (grabbed buttons will NOT go to the hooks.events "
362      "hook while the pointer is grabbed)."},
363     {NULL, NULL, 0, NULL}
364 };
365
366 /***************************************************************************
367  
368    Type methods/struct
369  
370  ***************************************************************************/
371
372 static PyObject *swrap_getattr(ScreenWrap *self, char *name)
373 {
374     CHECK_SWRAP(self, "getattr");
375     return Py_FindMethod(ScreenWrapAttributeMethods, (PyObject*)self, name);
376 }
377
378 static void swrap_dealloc(ScreenWrap *self)
379 {
380     PyObject_Del((PyObject*) self);
381 }
382
383 static PyTypeObject ScreenWrapType = {
384     PyObject_HEAD_INIT(NULL)
385     0,
386     "Screen",
387     sizeof(ScreenWrap),
388     0,
389     (destructor) swrap_dealloc,     /*tp_dealloc*/
390     0,                              /*tp_print*/
391     (getattrfunc) swrap_getattr,    /*tp_getattr*/
392     0,                              /*tp_setattr*/
393     0,                              /*tp_compare*/
394     0,                              /*tp_repr*/
395     0,                              /*tp_as_number*/
396     0,                              /*tp_as_sequence*/
397     0,                              /*tp_as_mapping*/
398     0,                              /*tp_hash */
399 };
400
401 /***************************************************************************
402  
403    External methods
404  
405  ***************************************************************************/
406
407 void screenwrap_startup()
408 {
409     PyObject *ob, *obdict;
410     ScreenWrap *swrap;
411
412     ScreenWrapType.ob_type = &PyType_Type;
413     ScreenWrapType.tp_doc = "Wraps information and functionality global to an "
414         "instance of Openbox.";
415     PyType_Ready(&ScreenWrapType);
416     swrap = PyObject_New(ScreenWrap, &ScreenWrapType);
417
418     /* get the ob module/dict */
419     ob = PyImport_ImportModule("ob"); /* new */
420     g_assert(ob != NULL);
421     obdict = PyModule_GetDict(ob); /* borrowed */
422     g_assert(obdict != NULL);
423
424     PyDict_SetItemString(obdict, "Screen", (PyObject*)swrap);
425     Py_DECREF(swrap);
426     Py_DECREF(ob);
427 }
428
429 void screenwrap_shutdown()
430 {
431 }
432
433