2001-12-10 Michael Meeks <michael@ximian.com>
[platform/core/uifw/at-spi2-atk.git] / cspi / spi-listener-impl.c
index ac1523c..c87aa31 100644 (file)
@@ -1,6 +1,59 @@
 #include <cspi/spi-private.h>
 #include <cspi/spi-listener-impl.h>
 
+typedef struct
+{
+  union
+    {
+      AccessibleEventListenerCB     event;
+      AccessibleKeystrokeListenerCB key_event;
+      gpointer                      method;
+    } cb;
+  gpointer user_data;
+} EventHandler;
+
+GObjectClass *event_parent_class;
+GObjectClass *keystroke_parent_class;
+
+/*
+ * Misc. helpers.
+ */
+
+static EventHandler *
+event_handler_new (gpointer method, gpointer user_data)
+{
+  EventHandler *eh = g_new0 (EventHandler, 1);
+
+  eh->cb.method = method;
+  eh->user_data = user_data;
+
+  return eh;
+}
+
+static void
+event_handler_free (EventHandler *handler)
+{
+  g_free (handler);
+}
+
+static GList *
+event_list_remove_by_callback (GList *list, gpointer callback)
+{
+  GList *l, *next;
+       
+  for (l = list; l; l = next)
+    {
+      EventHandler *eh = l->data;
+      next = l->next;
+      
+      list = g_list_delete_link (list, l);
+      
+      event_handler_free (eh);
+    }
+
+  return list;
+}
+
 /*
  * Standard event dispatcher
  */
@@ -12,22 +65,27 @@ static void
 cspi_event (SpiEventListener    *listener,
            Accessibility_Event *event)
 {
-  GSList *l;
+  GList *l;
   CSpiEventListener *clistener = (CSpiEventListener *) listener;
-  AccessibleEvent aevent;
+  AccessibleEvent    aevent;
+  Accessible        *source;
+
+  source = cspi_object_add (bonobo_object_dup_ref (event->source, cspi_ev ()));
 
   aevent.type    = event->type;
-  aevent.source  = cspi_object_add (event->source);
+  aevent.source  = source;
   aevent.detail1 = event->detail1;
   aevent.detail2 = event->detail2;
 
+  /* FIXME: re-enterancy hazard on this list */
   for (l = clistener->callbacks; l; l = l->next)
     {
-      AccessibleEventListenerCB cb = l->data;
-      cb (&aevent);
+      EventHandler *eh = l->data;
+
+      eh->cb.event (&aevent, eh->user_data);
     }
-  
-  cspi_object_unref (aevent.source);
+
+  cspi_object_unref (source);
 }
 
 static void
@@ -36,31 +94,54 @@ cspi_event_listener_instance_init (CSpiEventListener *listener)
 }
 
 static void
+cspi_event_listener_finalize (GObject *object)
+{
+  CSpiEventListener *listener = (CSpiEventListener *) object;
+  GList *l;
+  
+  for (l = listener->callbacks; l; l = l->next)
+    {
+      event_handler_free (l->data);
+    }
+  
+  g_list_free (listener->callbacks);
+
+  event_parent_class->finalize (object);
+}
+
+static void
 cspi_event_listener_class_init (CSpiEventListenerClass *klass)
 {
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  event_parent_class = g_type_class_peek_parent (klass);
+  object_class->finalize = cspi_event_listener_finalize;
+
   klass->event = cspi_event;
 }
 
 CSpiEventListener *
 cspi_event_listener_new (void)
 {
-  return g_object_new (spi_event_listener_get_type (), NULL);
+  return g_object_new (cspi_event_listener_get_type (), NULL);
 }
 
 void
 cspi_event_listener_add_callback (CSpiEventListener        *listener,
-                                 AccessibleEventListenerCB callback)
+                                 AccessibleEventListenerCB callback,
+                                 void                     *user_data)
 {
-  g_return_if_fail (IS_CSPI_KEYSTROKE_LISTENER (listener));
-  listener->callbacks = g_slist_prepend (listener->callbacks, callback);
+  g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
+  listener->callbacks = g_list_prepend (listener->callbacks,
+                                       event_handler_new (callback, user_data));
 }
 
 void
 cspi_event_listener_remove_callback (CSpiEventListener        *listener,
                                     AccessibleEventListenerCB callback)
 {
-  g_return_if_fail (IS_CSPI_KEYSTROKE_LISTENER (listener));
-  listener->callbacks = g_slist_remove (listener->callbacks, callback);
+  g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
+  listener->callbacks = event_list_remove_by_callback (listener->callbacks, callback);
 }
 
 /*
@@ -71,11 +152,24 @@ static gboolean
 cspi_key_event (SpiKeystrokeListener          *listener,
                const Accessibility_KeyStroke *keystroke)
 {
-  GSList *l;
+  GList *l;
   CSpiKeystrokeListener *clistener = (CSpiKeystrokeListener *) listener;
   AccessibleKeystroke akeystroke;
   gboolean handled = FALSE;
 
+#ifdef SPI_KEYEVENT_DEBUG
+  fprintf (stderr, "%s%c",
+          (keystroke->modifiers & SPI_KEYMASK_ALT)?"Alt-":"",
+          ((keystroke->modifiers & SPI_KEYMASK_SHIFT)^(keystroke->modifiers & SPI_KEYMASK_SHIFTLOCK))?
+          (char) toupper((int) keystroke->keyID) : (char) tolower((int) keystroke->keyID));
+  
+  fprintf (stderr, "Key:\tsym %ld\n\tmods %x\n\tcode %d\n\ttime %ld\n",
+          (long) keystroke->keyID,
+          (unsigned int) keystroke->modifiers,
+          (int) keystroke->keycode,
+          (long int) keystroke->timestamp);
+#endif
+
   switch (keystroke->type)
     {
       case Accessibility_KEY_PRESSED:
@@ -93,10 +187,12 @@ cspi_key_event (SpiKeystrokeListener          *listener,
   akeystroke.timestamp = keystroke->timestamp;
   akeystroke.modifiers = keystroke->modifiers;
 
+  /* FIXME: re-enterancy hazard on this list */
   for (l = clistener->callbacks; l; l = l->next)
     {
-      AccessibleKeystrokeListenerCB cb = l->data;
-      if ((handled = cb (&akeystroke)))
+      EventHandler *eh = l->data;
+
+      if ((handled = eh->cb.key_event (&akeystroke, eh->user_data)))
         {
          break;
        }
@@ -110,9 +206,31 @@ cspi_keystroke_listener_init (CSpiKeystrokeListener *listener)
 {
 }
 
+
+static void
+cspi_keystroke_listener_finalize (GObject *object)
+{
+  CSpiKeystrokeListener *listener = (CSpiKeystrokeListener *) object;
+  GList *l;
+  
+  for (l = listener->callbacks; l; l = l->next)
+    {
+      event_handler_free (l->data);
+    }
+  
+  g_list_free (listener->callbacks);
+
+  keystroke_parent_class->finalize (object);
+}
+
 static void
 cspi_keystroke_listener_class_init (CSpiKeystrokeListenerClass *klass)
 {
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  keystroke_parent_class = g_type_class_peek_parent (klass);
+  object_class->finalize = cspi_keystroke_listener_finalize;
+
   klass->key_event = cspi_key_event;
 }
 
@@ -123,21 +241,23 @@ BONOBO_TYPE_FUNC (CSpiKeystrokeListener,
 CSpiKeystrokeListener *
 cspi_keystroke_listener_new (void)
 {
-  return g_object_new (spi_keystroke_listener_get_type (), NULL);
+  return g_object_new (cspi_keystroke_listener_get_type (), NULL);
 }
 
 void
 cspi_keystroke_listener_add_callback (CSpiKeystrokeListener        *listener,
-                                     AccessibleKeystrokeListenerCB callback)
+                                     AccessibleKeystrokeListenerCB callback,
+                                     void                         *user_data)
 {
-  g_return_if_fail (IS_CSPI_KEYSTROKE_LISTENER (listener));
-  listener->callbacks = g_slist_prepend (listener->callbacks, callback);
+  g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
+  listener->callbacks = g_list_prepend (listener->callbacks,
+                                       event_handler_new (callback, user_data));
 }
 
 void
 cspi_keystroke_listener_remove_callback (CSpiKeystrokeListener        *listener,
                                         AccessibleKeystrokeListenerCB callback)
 {
-  g_return_if_fail (IS_CSPI_KEYSTROKE_LISTENER (listener));
-  listener->callbacks = g_slist_remove (listener->callbacks, callback);
+  g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
+  listener->callbacks = event_list_remove_by_callback (listener->callbacks, callback);
 }