]> icculus.org git repositories - dana/openbox.git/blob - c/eventdata.c
merge the C branch into HEAD
[dana/openbox.git] / c / eventdata.c
1 #include "eventdata.h"
2 #include "openbox.h"
3 #include "event.h"
4 #include "clientwrap.h"
5 #include <X11/Xlib.h>
6
7 /*
8  *
9  * Define the type 'EventData'
10  *
11  */
12
13 #define IS_EVENTDATA(v)  ((v)->ob_type == &EventDataType)
14 #define CHECK_EVENTDATA(self, funcname) { \
15     if (!IS_EVENTDATA(self)) { \
16         PyErr_SetString(PyExc_TypeError, \
17                         "descriptor '" funcname "' requires an 'EventData' " \
18                         "object"); \
19         return NULL; \
20     } \
21 }
22
23 staticforward PyTypeObject EventDataType;
24
25 static PyObject *eventdata_type(EventData *self, PyObject *args)
26 {
27     CHECK_EVENTDATA(self, "type");
28     if (!PyArg_ParseTuple(args, ":type"))
29         return NULL;
30     return PyInt_FromLong(self->type);
31 }
32
33 static PyObject *eventdata_time(EventData *self, PyObject *args)
34 {
35     CHECK_EVENTDATA(self, "time");
36     if (!PyArg_ParseTuple(args, ":time"))
37         return NULL;
38     return PyInt_FromLong(event_lasttime);
39 }
40
41 static PyObject *eventdata_context(EventData *self, PyObject *args)
42 {
43     CHECK_EVENTDATA(self, "context");
44     if (!PyArg_ParseTuple(args, ":context"))
45         return NULL;
46     return PyString_FromString(self->context);
47 }
48
49 static PyObject *eventdata_client(EventData *self, PyObject *args)
50 {
51     CHECK_EVENTDATA(self, "client");
52     if (!PyArg_ParseTuple(args, ":client"))
53         return NULL;
54     if (self->client == NULL) {
55         Py_INCREF(Py_None);
56         return Py_None;
57     } else {
58         return clientwrap_new(self->client);
59     }
60 }
61
62 static PyObject *eventdata_keycode(EventData *self, PyObject *args)
63 {
64     CHECK_EVENTDATA(self, "keycode");
65     if (!PyArg_ParseTuple(args, ":keycode"))
66         return NULL;
67     switch (self->type) {
68     case Key_Press:
69     case Key_Release:
70         break;
71     default:
72         PyErr_SetString(PyExc_TypeError,
73                         "The EventData object is not a Key event");
74         return NULL;
75     }
76     return PyInt_FromLong(self->details.key->keycode);
77 }
78
79 static PyObject *eventdata_modifiers(EventData *self, PyObject *args)
80 {
81     CHECK_EVENTDATA(self, "key");
82     if (!PyArg_ParseTuple(args, ":key"))
83         return NULL;
84     switch (self->type) {
85     case Key_Press:
86     case Key_Release:
87     case Pointer_Press:
88     case Pointer_Release:
89     case Pointer_Motion:
90         break;
91     default:
92         PyErr_SetString(PyExc_TypeError,
93                         "The EventData object is not a Key or Pointer event");
94         return NULL;
95     }
96     return PyInt_FromLong(self->details.key->modifiers);
97 }
98
99 static PyObject *eventdata_keyName(EventData *self, PyObject *args)
100 {
101     GList *it;
102     PyObject *tuple;
103     int i;
104
105     CHECK_EVENTDATA(self, "keyName");
106     if (!PyArg_ParseTuple(args, ":keyName"))
107         return NULL;
108     switch (self->type) {
109     case Key_Press:
110     case Key_Release:
111         break;
112     default:
113         PyErr_SetString(PyExc_TypeError,
114                         "The EventData object is not a Key event");
115         return NULL;
116     }
117
118     if (self->details.key->keylist != NULL) {
119         tuple = PyTuple_New(g_list_length(self->details.key->keylist));
120         for (i = 0, it = self->details.key->keylist; it != NULL;
121              it = it->next, ++i)
122             PyTuple_SET_ITEM(tuple, i, PyString_FromString(it->data));
123         return tuple;
124     } else {
125         GString *str = g_string_sized_new(0);
126         KeySym sym;
127
128         if (self->details.key->modifiers & ControlMask)
129             g_string_append(str, "C-");
130         if (self->details.key->modifiers & ShiftMask)
131             g_string_append(str, "S-");
132         if (self->details.key->modifiers & Mod1Mask)
133             g_string_append(str, "Mod1-");
134         if (self->details.key->modifiers & Mod2Mask)
135             g_string_append(str, "Mod2-");
136         if (self->details.key->modifiers & Mod3Mask)
137             g_string_append(str, "Mod3-");
138         if (self->details.key->modifiers & Mod4Mask)
139             g_string_append(str, "Mod4-");
140         if (self->details.key->modifiers & Mod5Mask)
141             g_string_append(str, "Mod5-");
142
143         sym = XKeycodeToKeysym(ob_display, self->details.key->keycode, 0);
144         if (sym == NoSymbol)
145             g_string_append(str, "NoSymbol");
146         else {
147             char *name = XKeysymToString(sym);
148             if (name == NULL)
149                 name = "Undefined";
150             g_string_append(str, name);
151         }
152
153         tuple = PyTuple_New(1);
154         PyTuple_SET_ITEM(tuple, 0, PyString_FromString(str->str));
155         g_string_free(str, TRUE);
156
157         return tuple;
158     }
159 }
160
161 static PyObject *eventdata_button(EventData *self, PyObject *args)
162 {
163     CHECK_EVENTDATA(self, "button");
164     if (!PyArg_ParseTuple(args, ":button"))
165         return NULL;
166     switch (self->type) {
167     case Pointer_Press:
168     case Pointer_Release:
169     case Pointer_Motion:
170         break;
171     default:
172         PyErr_SetString(PyExc_TypeError,
173                         "The EventData object is not a Pointer event");
174         return NULL;
175     }
176     return PyInt_FromLong(self->details.pointer->button);
177 }
178
179 static PyObject *eventdata_buttonName(EventData *self, PyObject *args)
180 {
181     CHECK_EVENTDATA(self, "buttonName");
182     if (!PyArg_ParseTuple(args, ":buttonName"))
183         return NULL;
184     switch (self->type) {
185     case Pointer_Press:
186     case Pointer_Release:
187     case Pointer_Motion:
188         break;
189     default:
190         PyErr_SetString(PyExc_TypeError,
191                         "The EventData object is not a Pointer event");
192         return NULL;
193     }
194
195     if (self->details.pointer->name != NULL) {
196         return PyString_FromString(self->details.pointer->name);
197     } else {
198         PyObject *pystr;
199         GString *str = g_string_sized_new(0);
200
201         if (self->details.pointer->modifiers & ControlMask)
202             g_string_append(str, "C-");
203         if (self->details.pointer->modifiers & ShiftMask)
204             g_string_append(str, "S-");
205         if (self->details.pointer->modifiers & Mod1Mask)
206             g_string_append(str, "Mod1-");
207         if (self->details.pointer->modifiers & Mod2Mask)
208             g_string_append(str, "Mod2-");
209         if (self->details.pointer->modifiers & Mod3Mask)
210             g_string_append(str, "Mod3-");
211         if (self->details.pointer->modifiers & Mod4Mask)
212             g_string_append(str, "Mod4-");
213         if (self->details.pointer->modifiers & Mod5Mask)
214             g_string_append(str, "Mod5-");
215         
216         g_string_append_printf(str, "%d", self->details.pointer->button);
217
218         pystr = PyString_FromString(str->str);
219
220         g_string_free(str, TRUE);
221
222         return pystr;
223     }
224 }
225
226 static PyObject *eventdata_position(EventData *self, PyObject *args)
227 {
228     PyObject *tuple;
229
230     CHECK_EVENTDATA(self, "position");
231     if (!PyArg_ParseTuple(args, ":position"))
232         return NULL;
233     switch (self->type) {
234     case Pointer_Press:
235     case Pointer_Release:
236     case Pointer_Motion:
237         break;
238     default:
239         PyErr_SetString(PyExc_TypeError,
240                         "The EventData object is not a Pointer event");
241         return NULL;
242     }
243     tuple = PyTuple_New(2);
244     PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->details.pointer->xroot));
245     PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->details.pointer->yroot));
246     return tuple;
247 }
248
249 static PyMethodDef EventDataAttributeMethods[] = {
250     {"type", (PyCFunction)eventdata_type, METH_VARARGS,
251      "data.type() -- Return the event type"},
252     {"context", (PyCFunction)eventdata_context, METH_VARARGS,
253      "data.context() -- Return the context for the event. If it is "
254      "\"client\", then data.client() can be used to find out the "
255      "client."},
256     {"client", (PyCFunction)eventdata_client, METH_VARARGS,
257      "data.client() -- Return the client for the event. This may be None if "
258      "there is no client, even if data.context() gives Context_Client."},
259     {"time", (PyCFunction)eventdata_time, METH_VARARGS,
260      "data.time() -- Return the time at which the last X event occured with "
261      "a timestamp. Should be the time at which this event, or the event that "
262      "caused this event to occur happened."},
263     {"modifiers", (PyCFunction)eventdata_modifiers, METH_VARARGS,
264      "data.modifiers() -- Return the modifier keymask that was pressed "
265      "when the event occured. A bitmask of ShiftMask, LockMask, ControlMask, "
266      "Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask. Cannot be used "
267      "when the data.type() is not a Key_* or Pointer_* event type."},
268     {"keycode", (PyCFunction)eventdata_keycode, METH_VARARGS,
269      "data.keycode() -- Return the keycode for the key which generated the "
270      "event. Cannot be used when the data.type() is not a Key_* event type."},
271     {"keyName", (PyCFunction)eventdata_keyName, METH_VARARGS,
272      "data.keyName() -- Return a tuple of the string names of the key which "
273      "generated the event. Cannot be used when the data.type() is not a Key_* "
274      "event "
275      "type."},
276     {"button", (PyCFunction)eventdata_button, METH_VARARGS,
277      "data.button() -- Return the pointer button which generated the event. "
278      "Cannot be used when the data.type() is not a Pointer_* event type."},
279     {"buttonName", (PyCFunction)eventdata_keyName, METH_VARARGS,
280      "data.buttonName() -- Return the name of the button which generated the "
281      "event. Cannot be used when the data.type() is not a Pointer_* event "
282      "type."},
283     {"position", (PyCFunction)eventdata_position, METH_VARARGS,
284      "data.position() -- Returns the current position of the pointer on the "
285      "root window when the event was generated. Gives the position in a tuple "
286      "with a format of (x, y). Cannot be used when the data.type() is not a "
287      "Pointer_* event type."},
288     { NULL, NULL, 0, NULL }
289 };
290
291 static void data_dealloc(EventData *self)
292 {
293     GList *it;
294
295     switch(self->type) {
296     case Logical_EnterWindow:
297     case Logical_LeaveWindow:
298     case Logical_NewWindow:
299     case Logical_CloseWindow:
300     case Logical_Startup:
301     case Logical_Shutdown:
302     case Logical_RequestActivate:
303     case Logical_WindowShow:
304     case Logical_WindowHide:
305     case Logical_Focus:
306     case Logical_Bell:
307     case Logical_UrgentWindow:
308         g_free(self->details.logical);
309         break;
310     case Pointer_Press:
311     case Pointer_Release:
312     case Pointer_Motion:
313         if (self->details.pointer->name != NULL)
314             g_free(self->details.pointer->name);
315         g_free(self->details.pointer);
316         break;
317     case Key_Press:
318     case Key_Release:
319         for (it = self->details.key->keylist; it != NULL; it = it->next)
320             g_free(it->data);
321         g_list_free(self->details.key->keylist);
322         g_free(self->details.key);
323         break;
324     default:
325         g_assert_not_reached();
326     }
327     PyObject_Del((PyObject*) self);
328 }
329
330 static PyObject *eventdata_getattr(EventData *self, char *name)
331 {
332     return Py_FindMethod(EventDataAttributeMethods, (PyObject*)self, name);
333 }
334
335 static PyTypeObject EventDataType = {
336     PyObject_HEAD_INIT(NULL)
337     0,
338     "EventData",
339     sizeof(EventData),
340     0,
341     (destructor) data_dealloc,       /*tp_dealloc*/
342     0,                               /*tp_print*/
343     (getattrfunc) eventdata_getattr, /*tp_getattr*/
344     0,                               /*tp_setattr*/
345     0,                               /*tp_compare*/
346     0,                               /*tp_repr*/
347     0,                               /*tp_as_number*/
348     0,                               /*tp_as_sequence*/
349     0,                               /*tp_as_mapping*/
350     0,                               /*tp_hash */
351 };
352
353
354
355 void eventdata_startup()
356 {
357     EventDataType.ob_type = &PyType_Type;
358     PyType_Ready(&EventDataType);
359 }
360
361 void eventdata_shutdown()
362 {
363 }
364
365 void eventdata_free(EventData *data)
366 {
367     Py_DECREF(data);
368 }
369
370 EventData *eventdata_new_logical(EventType type, GQuark context,
371                                  struct Client *client)
372 {
373     EventData *data;
374
375     g_assert(type < Pointer_Press);
376
377     data = PyObject_New(EventData, &EventDataType);
378     data->type = type;
379     data->context = g_quark_to_string(context);
380     data->client = client;
381     data->details.logical = g_new(LogicalEvent, 1);
382     return data;
383 }
384
385 EventData *eventdata_new_pointer(EventType type, GQuark context,
386                                  struct Client *client, guint modifiers,
387                                  guint button, char *name,
388                                  int xroot, int yroot)
389 {
390     EventData *data;
391
392     g_assert(type >= Pointer_Press && type < Key_Press);
393
394     data = PyObject_New(EventData, &EventDataType);
395     data->type = type;
396     data->context = g_quark_to_string(context);
397     data->client = client;
398     data->details.pointer = g_new(PointerEvent, 1);
399     data->details.pointer->modifiers = modifiers;
400     data->details.pointer->button = button;
401     data->details.pointer->name = name == NULL ? name : g_strdup(name);
402     data->details.pointer->xroot = xroot;
403     data->details.pointer->yroot = yroot;
404     return data;
405 }
406
407 EventData *eventdata_new_key(EventType type, GQuark context,
408                              struct Client *client, guint modifiers,
409                              guint keycode, GList *keylist)
410 {
411     EventData *data;
412     GList *mykeylist, *it;
413
414     g_assert(type >= Key_Press);
415
416     data = PyObject_New(EventData, &EventDataType);
417     data->type = type;
418     data->context = g_quark_to_string(context);
419     data->client = client;
420     data->details.key = g_new(KeyEvent, 1);
421
422     /* make a copy of the keylist.
423      If the user were to clear the key bindings, then the keylist given here
424      would no longer point at valid memory.*/
425     mykeylist = g_list_copy(keylist); /* shallow copy */
426     for (it = mykeylist; it != NULL; it = it->next) /* deep copy */
427         it->data = g_strdup(it->data);
428
429     data->details.key->keylist = mykeylist;
430     data->details.key->keycode = keycode;
431     data->details.key->modifiers = modifiers;
432     return data;
433 }