summaryrefslogtreecommitdiff
path: root/c/eventdata.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/eventdata.c')
-rw-r--r--c/eventdata.c433
1 files changed, 433 insertions, 0 deletions
diff --git a/c/eventdata.c b/c/eventdata.c
new file mode 100644
index 00000000..e3bf15e1
--- /dev/null
+++ b/c/eventdata.c
@@ -0,0 +1,433 @@
+#include "eventdata.h"
+#include "openbox.h"
+#include "event.h"
+#include "clientwrap.h"
+#include <X11/Xlib.h>
+
+/*
+ *
+ * Define the type 'EventData'
+ *
+ */
+
+#define IS_EVENTDATA(v) ((v)->ob_type == &EventDataType)
+#define CHECK_EVENTDATA(self, funcname) { \
+ if (!IS_EVENTDATA(self)) { \
+ PyErr_SetString(PyExc_TypeError, \
+ "descriptor '" funcname "' requires an 'EventData' " \
+ "object"); \
+ return NULL; \
+ } \
+}
+
+staticforward PyTypeObject EventDataType;
+
+static PyObject *eventdata_type(EventData *self, PyObject *args)
+{
+ CHECK_EVENTDATA(self, "type");
+ if (!PyArg_ParseTuple(args, ":type"))
+ return NULL;
+ return PyInt_FromLong(self->type);
+}
+
+static PyObject *eventdata_time(EventData *self, PyObject *args)
+{
+ CHECK_EVENTDATA(self, "time");
+ if (!PyArg_ParseTuple(args, ":time"))
+ return NULL;
+ return PyInt_FromLong(event_lasttime);
+}
+
+static PyObject *eventdata_context(EventData *self, PyObject *args)
+{
+ CHECK_EVENTDATA(self, "context");
+ if (!PyArg_ParseTuple(args, ":context"))
+ return NULL;
+ return PyString_FromString(self->context);
+}
+
+static PyObject *eventdata_client(EventData *self, PyObject *args)
+{
+ CHECK_EVENTDATA(self, "client");
+ if (!PyArg_ParseTuple(args, ":client"))
+ return NULL;
+ if (self->client == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ } else {
+ return clientwrap_new(self->client);
+ }
+}
+
+static PyObject *eventdata_keycode(EventData *self, PyObject *args)
+{
+ CHECK_EVENTDATA(self, "keycode");
+ if (!PyArg_ParseTuple(args, ":keycode"))
+ return NULL;
+ switch (self->type) {
+ case Key_Press:
+ case Key_Release:
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "The EventData object is not a Key event");
+ return NULL;
+ }
+ return PyInt_FromLong(self->details.key->keycode);
+}
+
+static PyObject *eventdata_modifiers(EventData *self, PyObject *args)
+{
+ CHECK_EVENTDATA(self, "key");
+ if (!PyArg_ParseTuple(args, ":key"))
+ return NULL;
+ switch (self->type) {
+ case Key_Press:
+ case Key_Release:
+ case Pointer_Press:
+ case Pointer_Release:
+ case Pointer_Motion:
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "The EventData object is not a Key or Pointer event");
+ return NULL;
+ }
+ return PyInt_FromLong(self->details.key->modifiers);
+}
+
+static PyObject *eventdata_keyName(EventData *self, PyObject *args)
+{
+ GList *it;
+ PyObject *tuple;
+ int i;
+
+ CHECK_EVENTDATA(self, "keyName");
+ if (!PyArg_ParseTuple(args, ":keyName"))
+ return NULL;
+ switch (self->type) {
+ case Key_Press:
+ case Key_Release:
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "The EventData object is not a Key event");
+ return NULL;
+ }
+
+ if (self->details.key->keylist != NULL) {
+ tuple = PyTuple_New(g_list_length(self->details.key->keylist));
+ for (i = 0, it = self->details.key->keylist; it != NULL;
+ it = it->next, ++i)
+ PyTuple_SET_ITEM(tuple, i, PyString_FromString(it->data));
+ return tuple;
+ } else {
+ GString *str = g_string_sized_new(0);
+ KeySym sym;
+
+ if (self->details.key->modifiers & ControlMask)
+ g_string_append(str, "C-");
+ if (self->details.key->modifiers & ShiftMask)
+ g_string_append(str, "S-");
+ if (self->details.key->modifiers & Mod1Mask)
+ g_string_append(str, "Mod1-");
+ if (self->details.key->modifiers & Mod2Mask)
+ g_string_append(str, "Mod2-");
+ if (self->details.key->modifiers & Mod3Mask)
+ g_string_append(str, "Mod3-");
+ if (self->details.key->modifiers & Mod4Mask)
+ g_string_append(str, "Mod4-");
+ if (self->details.key->modifiers & Mod5Mask)
+ g_string_append(str, "Mod5-");
+
+ sym = XKeycodeToKeysym(ob_display, self->details.key->keycode, 0);
+ if (sym == NoSymbol)
+ g_string_append(str, "NoSymbol");
+ else {
+ char *name = XKeysymToString(sym);
+ if (name == NULL)
+ name = "Undefined";
+ g_string_append(str, name);
+ }
+
+ tuple = PyTuple_New(1);
+ PyTuple_SET_ITEM(tuple, 0, PyString_FromString(str->str));
+ g_string_free(str, TRUE);
+
+ return tuple;
+ }
+}
+
+static PyObject *eventdata_button(EventData *self, PyObject *args)
+{
+ CHECK_EVENTDATA(self, "button");
+ if (!PyArg_ParseTuple(args, ":button"))
+ return NULL;
+ switch (self->type) {
+ case Pointer_Press:
+ case Pointer_Release:
+ case Pointer_Motion:
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "The EventData object is not a Pointer event");
+ return NULL;
+ }
+ return PyInt_FromLong(self->details.pointer->button);
+}
+
+static PyObject *eventdata_buttonName(EventData *self, PyObject *args)
+{
+ CHECK_EVENTDATA(self, "buttonName");
+ if (!PyArg_ParseTuple(args, ":buttonName"))
+ return NULL;
+ switch (self->type) {
+ case Pointer_Press:
+ case Pointer_Release:
+ case Pointer_Motion:
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "The EventData object is not a Pointer event");
+ return NULL;
+ }
+
+ if (self->details.pointer->name != NULL) {
+ return PyString_FromString(self->details.pointer->name);
+ } else {
+ PyObject *pystr;
+ GString *str = g_string_sized_new(0);
+
+ if (self->details.pointer->modifiers & ControlMask)
+ g_string_append(str, "C-");
+ if (self->details.pointer->modifiers & ShiftMask)
+ g_string_append(str, "S-");
+ if (self->details.pointer->modifiers & Mod1Mask)
+ g_string_append(str, "Mod1-");
+ if (self->details.pointer->modifiers & Mod2Mask)
+ g_string_append(str, "Mod2-");
+ if (self->details.pointer->modifiers & Mod3Mask)
+ g_string_append(str, "Mod3-");
+ if (self->details.pointer->modifiers & Mod4Mask)
+ g_string_append(str, "Mod4-");
+ if (self->details.pointer->modifiers & Mod5Mask)
+ g_string_append(str, "Mod5-");
+
+ g_string_append_printf(str, "%d", self->details.pointer->button);
+
+ pystr = PyString_FromString(str->str);
+
+ g_string_free(str, TRUE);
+
+ return pystr;
+ }
+}
+
+static PyObject *eventdata_position(EventData *self, PyObject *args)
+{
+ PyObject *tuple;
+
+ CHECK_EVENTDATA(self, "position");
+ if (!PyArg_ParseTuple(args, ":position"))
+ return NULL;
+ switch (self->type) {
+ case Pointer_Press:
+ case Pointer_Release:
+ case Pointer_Motion:
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "The EventData object is not a Pointer event");
+ return NULL;
+ }
+ tuple = PyTuple_New(2);
+ PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->details.pointer->xroot));
+ PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->details.pointer->yroot));
+ return tuple;
+}
+
+static PyMethodDef EventDataAttributeMethods[] = {
+ {"type", (PyCFunction)eventdata_type, METH_VARARGS,
+ "data.type() -- Return the event type"},
+ {"context", (PyCFunction)eventdata_context, METH_VARARGS,
+ "data.context() -- Return the context for the event. If it is "
+ "\"client\", then data.client() can be used to find out the "
+ "client."},
+ {"client", (PyCFunction)eventdata_client, METH_VARARGS,
+ "data.client() -- Return the client for the event. This may be None if "
+ "there is no client, even if data.context() gives Context_Client."},
+ {"time", (PyCFunction)eventdata_time, METH_VARARGS,
+ "data.time() -- Return the time at which the last X event occured with "
+ "a timestamp. Should be the time at which this event, or the event that "
+ "caused this event to occur happened."},
+ {"modifiers", (PyCFunction)eventdata_modifiers, METH_VARARGS,
+ "data.modifiers() -- Return the modifier keymask that was pressed "
+ "when the event occured. A bitmask of ShiftMask, LockMask, ControlMask, "
+ "Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask. Cannot be used "
+ "when the data.type() is not a Key_* or Pointer_* event type."},
+ {"keycode", (PyCFunction)eventdata_keycode, METH_VARARGS,
+ "data.keycode() -- Return the keycode for the key which generated the "
+ "event. Cannot be used when the data.type() is not a Key_* event type."},
+ {"keyName", (PyCFunction)eventdata_keyName, METH_VARARGS,
+ "data.keyName() -- Return a tuple of the string names of the key which "
+ "generated the event. Cannot be used when the data.type() is not a Key_* "
+ "event "
+ "type."},
+ {"button", (PyCFunction)eventdata_button, METH_VARARGS,
+ "data.button() -- Return the pointer button which generated the event. "
+ "Cannot be used when the data.type() is not a Pointer_* event type."},
+ {"buttonName", (PyCFunction)eventdata_keyName, METH_VARARGS,
+ "data.buttonName() -- Return the name of the button which generated the "
+ "event. Cannot be used when the data.type() is not a Pointer_* event "
+ "type."},
+ {"position", (PyCFunction)eventdata_position, METH_VARARGS,
+ "data.position() -- Returns the current position of the pointer on the "
+ "root window when the event was generated. Gives the position in a tuple "
+ "with a format of (x, y). Cannot be used when the data.type() is not a "
+ "Pointer_* event type."},
+ { NULL, NULL, 0, NULL }
+};
+
+static void data_dealloc(EventData *self)
+{
+ GList *it;
+
+ switch(self->type) {
+ case Logical_EnterWindow:
+ case Logical_LeaveWindow:
+ case Logical_NewWindow:
+ case Logical_CloseWindow:
+ case Logical_Startup:
+ case Logical_Shutdown:
+ case Logical_RequestActivate:
+ case Logical_WindowShow:
+ case Logical_WindowHide:
+ case Logical_Focus:
+ case Logical_Bell:
+ case Logical_UrgentWindow:
+ g_free(self->details.logical);
+ break;
+ case Pointer_Press:
+ case Pointer_Release:
+ case Pointer_Motion:
+ if (self->details.pointer->name != NULL)
+ g_free(self->details.pointer->name);
+ g_free(self->details.pointer);
+ break;
+ case Key_Press:
+ case Key_Release:
+ for (it = self->details.key->keylist; it != NULL; it = it->next)
+ g_free(it->data);
+ g_list_free(self->details.key->keylist);
+ g_free(self->details.key);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ PyObject_Del((PyObject*) self);
+}
+
+static PyObject *eventdata_getattr(EventData *self, char *name)
+{
+ return Py_FindMethod(EventDataAttributeMethods, (PyObject*)self, name);
+}
+
+static PyTypeObject EventDataType = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "EventData",
+ sizeof(EventData),
+ 0,
+ (destructor) data_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc) eventdata_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 */
+};
+
+
+
+void eventdata_startup()
+{
+ EventDataType.ob_type = &PyType_Type;
+ PyType_Ready(&EventDataType);
+}
+
+void eventdata_shutdown()
+{
+}
+
+void eventdata_free(EventData *data)
+{
+ Py_DECREF(data);
+}
+
+EventData *eventdata_new_logical(EventType type, GQuark context,
+ struct Client *client)
+{
+ EventData *data;
+
+ g_assert(type < Pointer_Press);
+
+ data = PyObject_New(EventData, &EventDataType);
+ data->type = type;
+ data->context = g_quark_to_string(context);
+ data->client = client;
+ data->details.logical = g_new(LogicalEvent, 1);
+ return data;
+}
+
+EventData *eventdata_new_pointer(EventType type, GQuark context,
+ struct Client *client, guint modifiers,
+ guint button, char *name,
+ int xroot, int yroot)
+{
+ EventData *data;
+
+ g_assert(type >= Pointer_Press && type < Key_Press);
+
+ data = PyObject_New(EventData, &EventDataType);
+ data->type = type;
+ data->context = g_quark_to_string(context);
+ data->client = client;
+ data->details.pointer = g_new(PointerEvent, 1);
+ data->details.pointer->modifiers = modifiers;
+ data->details.pointer->button = button;
+ data->details.pointer->name = name == NULL ? name : g_strdup(name);
+ data->details.pointer->xroot = xroot;
+ data->details.pointer->yroot = yroot;
+ return data;
+}
+
+EventData *eventdata_new_key(EventType type, GQuark context,
+ struct Client *client, guint modifiers,
+ guint keycode, GList *keylist)
+{
+ EventData *data;
+ GList *mykeylist, *it;
+
+ g_assert(type >= Key_Press);
+
+ data = PyObject_New(EventData, &EventDataType);
+ data->type = type;
+ data->context = g_quark_to_string(context);
+ data->client = client;
+ data->details.key = g_new(KeyEvent, 1);
+
+ /* make a copy of the keylist.
+ If the user were to clear the key bindings, then the keylist given here
+ would no longer point at valid memory.*/
+ mykeylist = g_list_copy(keylist); /* shallow copy */
+ for (it = mykeylist; it != NULL; it = it->next) /* deep copy */
+ it->data = g_strdup(it->data);
+
+ data->details.key->keylist = mykeylist;
+ data->details.key->keycode = keycode;
+ data->details.key->modifiers = modifiers;
+ return data;
+}