Allow hooking to object-specific events (partial).
authorSadrul Habib Chowdhury <sadrul@users.sourceforge.net>
Wed, 17 Jun 2009 07:45:08 +0000 (17 03:45 -0400)
committerSadrul Habib Chowdhury <sadrul@users.sourceforge.net>
Wed, 17 Jun 2009 07:45:08 +0000 (17 03:45 -0400)
src/python.c

index 29a4a27..1572450 100644 (file)
@@ -46,6 +46,7 @@ extern struct layer *flayer;
 static PyObject * SPy_Get(PyObject *obj, void *closure);
 static PyObject * SPy_Set(PyObject *obj, PyObject *value, void *closure);
 static int PyDispatch(void *handler, const char *params, va_list va);
+static PyObject * register_event_hook(PyObject *self, PyObject *args, PyObject *kw, void *object);
 
 typedef struct
 {
@@ -82,6 +83,7 @@ register_##type(PyObject *module) \
       getsets[i].get = SPy_Get; \
       getsets[i].set = SPy_Set; \
     } \
+  PyType##Type.tp_base = &ScreenObjectType; \
   PyType##Type.tp_getset = getsets; \
   PyType##Type.tp_methods = methods; \
   PyType##Type.tp_compare = compare_##type; \
@@ -95,7 +97,7 @@ register_##type(PyObject *module) \
 #define DEFINE_TYPE(str, Type) \
 typedef struct \
 { \
-  PyObject_HEAD \
+  ScreenObject __parent; \
   str *_obj; \
 } Py##Type; \
 \
@@ -127,6 +129,48 @@ PyString_FromStringSafe(const char *str)
   RETURN_NONE;
 }
 
+/** Generic Object {{{ */
+typedef struct
+{
+  PyObject_HEAD
+  char *name;
+} ScreenObject;
+
+static PyObject *
+object_hook(PyObject *self, PyObject *args, PyObject *kw)
+{
+  char *object;
+  object = *(char **)((char *)self + sizeof(ScreenObject));   /* ugliness */
+  return register_event_hook(self, args, kw, object);
+}
+
+static PyMethodDef omethods[] = {
+  {"hook", (PyCFunction)object_hook, METH_VARARGS | METH_KEYWORDS, "Hook to an event on the object."},
+  {NULL}
+};
+
+static PyTypeObject ScreenObjectType =
+{
+  PyObject_HEAD_INIT(NULL)
+  .ob_size = 0,
+  .tp_name = "screen.Object",
+  .tp_basicsize = sizeof(ScreenObject),
+  .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+  .tp_doc = "Generic object",
+  .tp_methods = omethods,
+  .tp_getset = NULL,
+};
+
+static int
+register_object(PyObject *module)
+{
+  PyType_Ready(&ScreenObjectType);
+  Py_INCREF(&ScreenObjectType);
+  PyModule_AddObject(module, "Generic Object", (PyObject *)&ScreenObjectType);
+}
+
+/** }}} */
+
 /** Window {{{ */
 DEFINE_TYPE(struct win, Window)
 
@@ -359,51 +403,11 @@ PyDispatch(void *handler, const char *params, va_list va)
   return retval;
 }
 
-/** Screen {{{ */
-static PyObject *
-screen_display(PyObject *self)
-{
-  if (!display)
-    {
-      RETURN_NONE;
-    }
-  return PyObject_FromDisplay(display);
-}
-
-static PyObject *
-screen_displays(PyObject *self)
-{
-  struct display *d = displays;
-  int count = 0;
-  for (; d; d = d->d_next)
-    ++count;
-  PyObject *tuple = PyTuple_New(count);
-
-  for (d = displays, count = 0; d; d = d->d_next, ++count)
-    PyTuple_SetItem(tuple, count, PyObject_FromDisplay(d));
-
-  return tuple;
-}
-
 static PyObject *
-screen_windows(PyObject *self)
-{
-  struct win *w = windows;
-  int count = 0;
-  for (; w; w = w->w_next)
-    ++count;
-  PyObject *tuple = PyTuple_New(count);
-
-  for (w = windows, count = 0; w; w = w->w_next, ++count)
-    PyTuple_SetItem(tuple, count, PyObject_FromWindow(w));
-
-  return tuple;
-}
-
-static PyObject *
-hook_event(PyObject *self, PyObject *args, PyObject *kw)
+register_event_hook(PyObject *self, PyObject *args, PyObject *kw, void *object)
 {
   static char *kwlist[] = {"event", "callback", NULL};
+
   PyObject *callback;
   char *name;
 
@@ -421,7 +425,7 @@ hook_event(PyObject *self, PyObject *args, PyObject *kw)
       return NULL;
     }
 
-  sev = object_get_event(NULL, name);
+  sev = object_get_event(object, name);
   if (!sev)
     {
       LMsg(0, "No event named '%s'", name);
@@ -451,6 +455,55 @@ hook_event(PyObject *self, PyObject *args, PyObject *kw)
 
   Py_INCREF((PyObject *)l->handler);
   return l->handler;
+
+  RETURN_NONE;
+}
+
+/** Screen {{{ */
+static PyObject *
+screen_display(PyObject *self)
+{
+  if (!display)
+    {
+      RETURN_NONE;
+    }
+  return PyObject_FromDisplay(display);
+}
+
+static PyObject *
+screen_displays(PyObject *self)
+{
+  struct display *d = displays;
+  int count = 0;
+  for (; d; d = d->d_next)
+    ++count;
+  PyObject *tuple = PyTuple_New(count);
+
+  for (d = displays, count = 0; d; d = d->d_next, ++count)
+    PyTuple_SetItem(tuple, count, PyObject_FromDisplay(d));
+
+  return tuple;
+}
+
+static PyObject *
+screen_windows(PyObject *self)
+{
+  struct win *w = windows;
+  int count = 0;
+  for (; w; w = w->w_next)
+    ++count;
+  PyObject *tuple = PyTuple_New(count);
+
+  for (w = windows, count = 0; w; w = w->w_next, ++count)
+    PyTuple_SetItem(tuple, count, PyObject_FromWindow(w));
+
+  return tuple;
+}
+
+static PyObject *
+hook_event(PyObject *self, PyObject *args, PyObject *kw)
+{
+  return register_event_hook(self, args, kw, NULL);
 }
 
 static void
@@ -514,6 +567,7 @@ SPyInit(void)
   Py_Initialize();
 
   m = Py_InitModule3 ("screen", py_methods, NULL);
+  register_object(m);
   register_window(m);
   register_display(m);
   register_callback(m);