]> Dogcows Code - chaz/openbox/blob - c/eventdata.c
merge the C branch into HEAD
[chaz/openbox] / 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 }
This page took 0.052708 seconds and 4 git commands to generate.