[g-a-devel]Re: proto at-spi patch ...



Michael Meeks wrote:
> 
> Hi Bill,
> 
>         This patch removes the timeout polling, and well - does a load of work
> around the place. However, for some reason strace reveals I'm not
> receiving the keyboard input as I am expecting too.

Hi Michael:

I would prefer that you keep the keygrab work separate as it is more
dangerous and more likely to be rejected as a patch; lots of issues
there as I'm sure you are aware after having looked at it a bit.  I see
a number of things that should not go in on just a quick examination. 
Can you break this into smaller patches that preferably do not depend on
one another?

In any case this should wait until the beta2 packages, which I hardly
have time to create and test before Monday.

>         Being no X expert; I have no idea how to ask X to allow us to filter
> all keyboard events on a display, and until I can get that to happen I'm
> somewhat stymied - and all that just to test whether the thing works
> still.

Hmm, well the short answer is that you can't get X to do that.  The only
thing you can do is call XGrabKey, as the existing code does.  I am
99.9% sure that we cannot use gdk calls to implement the keygrab stuff
we need, having looked at it at length before.

Pleeeeze don't even _think_ of changing the code in
spi_controller_grab_keyboard, all we can safely change is the way in
which spi_check_key_event is called.

>         So - can you give it a read, and let me know your thoughts / how to get
> those X events.
> 
>         I'd like to commit the 'const' change to the event passing API -
> clients shouldn't be fiddling with the events we send them; and that
> breaks no code [ but makes some old code spew warnings ].
> 
>         I'd also like to  rename SpiDeviceEventController to SpiController in
> the C implementation it, would save a lot of typing and this header /
> impl. is not installed.

I would prefer not to make that kind of API change now, we are in
'freeze' or at least we must argue for such changes to the release team.
 
>         I'm also concerned to some degree that we need to be able to detect
> when apps that have asked the registry to take a keygrab die - otherwise
> we're going to leak keygrabs - which is a pernicious evil. Do we have
> the API strength to do this ?

Not sure.  If the keygrabs took place in the C binding stuff (in the AT
client process space) then X would take care of it for us, but for other
reasons we needed to move the grabs into the registry.  It's a potential
issue all right, but as it now stands whenever an existing passive grab
is activated we re-grab, so as long as we can confirm that the grabs in
the list belong to live clients then we can prevent re-issuing defunct
grabs.
 
>         Using the CSPI API it's not clear when adding a keygrab what values to
> pass as AccessibleKeyMaskType, or for the AccessibleKeyEventMask, the
> SPI_KEYLISTENER_ALL_WINDOWS sync type is not quite clear to me either.
> Can we elucidate with comments, enums or typedefs ?

Someday I will have time to comment this I hope.  Certainly not at the
moment, I'm afraid.  Suffice it to say that at the moment
SPI_KEYLISTENER_ALL_WINDOWS is the only grab bit that should cause the
XGrabKey stuff to be used.
 
Regards,

Bill

>         Regards,
> 
>                 Michael.
> 
> Index: ChangeLog
> ===================================================================
> RCS file: /cvs/gnome/at-spi/ChangeLog,v
> retrieving revision 1.134
> diff -u -p -u -r1.134 ChangeLog
> --- ChangeLog   2002/01/08 09:11:43     1.134
> +++ ChangeLog   2002/01/09 12:13:34
> @@ -1,5 +1,69 @@
>  2002-01-08  Michael Meeks  <michael ximian com>
> 
> +       * registryd/deviceeventcontroller.c
> +       (spi_controller_register_with_devices): use gdk calls to
> +       setup a filter.
> +       (global_filter_fn): implement the filter.
> +       (spi_device_event_controller_check_key_event): rename to
> +       (spi_device_event_controller_forward_key_event): this & upd.
> +       (spi_get_display): replace with GDK_DISPLAY.
> +
> +       * test/test-simple.c (key_listener_cb): impl.
> +       (test_keylisteners): impl.
> +
> +       * cspi/spi-listener.h: make listener signatures const
> +       on the provided (const) events.
> +
> +       * test/keysynth-demo.c: upd. to const events.
> +
> +       * test/simple-at.c: ditto.
> +
> +       * registryd/deviceeventcontroller.c
> +       (spi_controller_deregister_device_listener): unroll into
> +       (impl_deregister_keystroke_listener): here to simplify.
> +       (spi_controller_register_global_keygrabs): split cut and
> +       paste (!) out into (_register_keygrab): here, shorter & sweeter.
> +       (spi_controller_deregister_device_listener): remove.
> +       (impl_register_mouse_listener): remove, no mouse listener
> +       support in at-spi-1.0
> +
> +       * registryd/registry.c
> +       (_device_event_controller_hook): kill.
> +       (spi_registry_init): upd.
> +
> +       * registryd/deviceeventcontroller.c
> +       (spi_device_event_controller_class_init): upd.
> +       (spi_check_key_event): merge into.
> +       (spi_device_event_controller_check_key_event):
> +       here and kill strange static ev init, don't leak
> +       the x_event - nor dynamicaly allocate it.
> +
> +       * registryd/registry-main.c (main): re-direct
> +       timeout to remove strange vtable mess.
> +
> +       * registryd/deviceeventcontroller.c
> +       (remove_listener_cb): impl.
> +       (spi_controller_deregister_device_listener):
> +       fix re-enterancy hazard.
> +
> +2002-01-07  Michael Meeks  <michael ximian com>
> +
> +       * registryd/deviceeventcontroller.c
> +       (spi_device_event_controller_new): upd.
> +       (impl_notify_listeners_sync): upd. debug.
> +       (spi_notify_keylisteners): fix re-enterancy hazards,
> +       prettify, remove O(n*n) iteration.
> +       (spi_controller_grab_keyboard): fix iteration.
> +       (spi_check_key_event): re-format to suit coding style.
> +       Clean all the warnings - we're warning free.
> +
> +       * registryd/deviceeventcontroller.h:
> +       * registryd/registry.h: make mutualy referential with
> +       typesafe forward references instead of (!) void pointer
> +       hacks.
> +
> +2002-01-08  Michael Meeks  <michael ximian com>
> +
>         * registryd/registry.c (parse_event_type): remove strndup.
> 
>         * libspi/Makefile.am (libspi_la_SOURCES): remove
> Index: cspi/spi-listener.h
> ===================================================================
> RCS file: /cvs/gnome/at-spi/cspi/spi-listener.h,v
> retrieving revision 1.15
> diff -u -p -u -r1.15 spi-listener.h
> --- cspi/spi-listener.h 2001/12/18 11:24:56     1.15
> +++ cspi/spi-listener.h 2002/01/09 12:13:34
> @@ -42,10 +42,10 @@ typedef struct {
>   *
>   * SPIBoolean (*AccessibleKeystrokeListenerCB) (AccessibleKeystrokeEvent *Event);
>   */
> -typedef void       (*AccessibleEventListenerCB)     (AccessibleEvent     *event,
> -                                                    void                *user_data);
> -typedef SPIBoolean (*AccessibleKeystrokeListenerCB) (AccessibleKeystroke *stroke,
> -                                                    void                *user_data);
> +typedef void       (*AccessibleEventListenerCB)     (const AccessibleEvent *event,
> +                                                    void                  *user_data);
> +typedef SPIBoolean (*AccessibleKeystrokeListenerCB) (const AccessibleKeystroke *stroke,
> +                                                    void                      *user_data);
> 
>  #ifdef  __cplusplus
>  }
> Index: cspi/spi_registry.c
> ===================================================================
> RCS file: /cvs/gnome/at-spi/cspi/spi_registry.c,v
> retrieving revision 1.28
> diff -u -p -u -r1.28 spi_registry.c
> --- cspi/spi_registry.c 2002/01/08 09:11:44     1.28
> +++ cspi/spi_registry.c 2002/01/09 12:13:35
> @@ -310,10 +310,10 @@ SPI_freeDesktopList (Accessible **deskto
>   * Returns: #TRUE if successful, otherwise #FALSE.
>   **/
>  SPIBoolean
> -SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
> -                                        AccessibleKeySet *keys,
> -                                        AccessibleKeyMaskType modmask,
> -                                        AccessibleKeyEventMask eventmask,
> +SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener  *listener,
> +                                        AccessibleKeySet             *keys,
> +                                        AccessibleKeyMaskType         modmask,
> +                                        AccessibleKeyEventMask        eventmask,
>                                          AccessibleKeyListenerSyncType sync_type)
>  {
>    gint                                i, mask;
> Index: idl/Accessibility_Registry.idl
> ===================================================================
> RCS file: /cvs/gnome/at-spi/idl/Accessibility_Registry.idl,v
> retrieving revision 1.16
> diff -u -p -u -r1.16 Accessibility_Registry.idl
> --- idl/Accessibility_Registry.idl      2002/01/01 22:35:29     1.16
> +++ idl/Accessibility_Registry.idl      2002/01/09 12:13:35
> @@ -66,7 +66,7 @@ module Accessibility {
>           *
>          **/
>          void registerGlobalEventListener (in EventListener listener,
> -                                           in string eventName);
> +                                         in string eventName);
> 
>         /**
>           * deregisterGlobalEventListener:
> Index: registryd/deviceeventcontroller.c
> ===================================================================
> RCS file: /cvs/gnome/at-spi/registryd/deviceeventcontroller.c,v
> retrieving revision 1.27
> diff -u -p -u -r1.27 deviceeventcontroller.c
> --- registryd/deviceeventcontroller.c   2002/01/08 09:11:46     1.27
> +++ registryd/deviceeventcontroller.c   2002/01/09 12:13:35
> @@ -24,19 +24,23 @@
> 
>  #include <config.h>
> 
> -#undef SPI_DEBUG
> +#define SPI_DEBUG
> 
> -#ifdef SPI_DEBUG
> -#  include <stdio.h>
> -#endif
> +#include <string.h>
> +#include <ctype.h>
> +#include <stdio.h>
> +#include <bonobo/bonobo-exception.h>
> 
>  #include <X11/Xlib.h>
>  #include <X11/extensions/XTest.h>
>  #define XK_MISCELLANY
>  #include <X11/keysymdef.h>
> +#include <gdk/gdk.h>
>  #include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
> +#include <gdk/gdkkeysyms.h>
>  #include <gdk/gdkwindow.h>
> 
> +#include "../libspi/spi-private.h"
>  #include "deviceeventcontroller.h"
> 
>  /* Our parent Gtk object type */
> @@ -45,98 +49,51 @@
>  /* A pointer to our parent object class */
>  static GObjectClass *spi_device_event_controller_parent_class;
> 
> -static gboolean kbd_registered = FALSE;
> -
>  static Window root_window;
> 
>  typedef enum {
>    SPI_DEVICE_TYPE_KBD,
> -  SPI_DEVICE_TYPE_MOUSE,
>    SPI_DEVICE_TYPE_LAST_DEFINED
>  } SpiDeviceTypeCategory;
> 
> -struct _DEControllerGrabMask {
> +typedef struct {
>    Accessibility_ControllerEventMask modmask;
>    CORBA_unsigned_long               keyval;
>    unsigned int                      refcount;
> -};
> -
> -typedef struct _DEControllerGrabMask DEControllerGrabMask;
> +} DEControllerGrabMask;
> 
> -struct _DEControllerListener {
> +typedef struct {
>    CORBA_Object          object;
>    SpiDeviceTypeCategory type;
> -};
> -
> -typedef struct _DEControllerListener DEControllerListener;
> +} DEControllerListener;
> 
> -struct _DEControllerKeyListener {
> +typedef struct {
>    DEControllerListener listener;
> -  Accessibility_KeySet *keys;
> -  Accessibility_ControllerEventMask mask;
> -  Accessibility_KeyEventTypeSeq *typeseq;
> -  Accessibility_EventListenerMode *mode;
> -};
> -
> -typedef struct _DEControllerKeyListener DEControllerKeyListener;
> -
> -static gboolean spi_controller_register_with_devices (SpiDeviceEventController *controller);
> -static gboolean spi_controller_grab_keyboard (SpiDeviceEventController *controller);
> -
> -static void spi_controller_register_device_listener (SpiDeviceEventController *controller,
> -                                                    DEControllerListener *l,
> -                                                    CORBA_Environment *ev);
> 
> -/*
> - * Private methods
> - */
> +  Accessibility_KeySet             *keys;
> +  Accessibility_ControllerEventMask mask;
> +  Accessibility_KeyEventTypeSeq    *typeseq;
> +  Accessibility_EventListenerMode  *mode;
> +} DEControllerKeyListener;
> +
> +static void     spi_controller_register_with_devices          (SpiDeviceEventController *controller);
> +static gboolean spi_controller_grab_keyboard                  (SpiDeviceEventController *controller);
> +static void     spi_controller_register_device_listener       (SpiDeviceEventController *controller,
> +                                                              DEControllerListener     *l,
> +                                                              CORBA_Environment        *ev);
> +static void     spi_device_event_controller_forward_key_event (SpiDeviceEventController *controller,
> +                                                              const XEvent             *event);
> 
> -static Display *
> -spi_get_display (void )
> -{
> - static Display *display = NULL;
> - /* We must open a new connection to the server to avoid clashing with the GDK event loop */
> - /*
> -  * TODO: fixme, this makes the foolish assumption that registryd uses
> -  * the same display as the apps, and the the DISPLAY environment variable is set.
> -  */
> -
> - if (!display)
> -   {
> -     display = XOpenDisplay (g_getenv ("DISPLAY"));
> -   }
> - return display;
> -}
> +/* Private methods */
> 
>  static DEControllerGrabMask *
>  spi_grabmask_clone (DEControllerGrabMask *grabmask)
> -{
> -  DEControllerGrabMask *clone = g_new0 (DEControllerGrabMask, 1);
> -  memcpy (clone, grabmask, sizeof (DEControllerGrabMask));
> -  return clone;
> -}
> -
> -static gint
> -spi_compare_corba_objects (gconstpointer p1, gconstpointer p2)
>  {
> -  CORBA_Environment ev;
> -  gint retval;
> -  retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
> +  DEControllerGrabMask *clone = g_new (DEControllerGrabMask, 1);
> 
> -#ifdef SPI_DEBUG
> -  fprintf (stderr, "comparing %p to %p; result %d\n",
> -          p1, p2,
> -          retval);
> -#endif
> -  return retval;
> -}
> +  memcpy (clone, grabmask, sizeof (DEControllerGrabMask));
> 
> -static gint
> -spi_compare_listeners (gconstpointer p1, gconstpointer p2)
> -{
> -  DEControllerListener *l1 = (DEControllerListener *) p1;
> -  DEControllerListener *l2 = (DEControllerListener *) p2;
> -  return spi_compare_corba_objects (l1->object, l2->object);
> +  return clone;
>  }
> 
>  static gint
> @@ -181,11 +138,13 @@ spi_dec_key_listener_new (CORBA_Object l
>             (int) mode->global,
>            (void *) key_listener->keys);
>  #endif
> +
>    return key_listener;
>  }
> 
>  static void
> -spi_dec_key_listener_free (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
> +spi_dec_key_listener_free (DEControllerKeyListener *key_listener,
> +                          CORBA_Environment       *ev)
>  {
>    bonobo_object_release_unref (key_listener->listener.object, ev);
>    CORBA_free (key_listener->typeseq);
> @@ -195,75 +154,70 @@ spi_dec_key_listener_free (DEControllerK
> 
>  static void
>  spi_controller_deregister_global_keygrabs (SpiDeviceEventController *controller,
> -                                          DEControllerKeyListener *key_listener)
> +                                          DEControllerKeyListener  *key_listener)
>  {
> -  GList *list_ptr;
> -  DEControllerGrabMask *mask_ptr;
>    /* TODO: implement this! Also remember to release any keygrabs still held */
> -  ;
> +}
> +
> +static void
> +_register_keygrab (SpiDeviceEventController *controller,
> +                  DEControllerGrabMask     *grabmask)
> +{
> +  GList *l;
> +
> +  l = g_list_find_custom (controller->keygrabs_list, grabmask,
> +                         spi_grabmask_compare_values);
> +  if (l)
> +    {
> +      DEControllerGrabMask *cur_mask = l->data;
> +
> +      cur_mask->refcount++;
> +    }
> +  else
> +    {
> +      controller->keygrabs_list =
> +        g_list_prepend (controller->keygrabs_list,
> +                       spi_grabmask_clone (grabmask));
> +    }
>  }
> 
>  static void
>  spi_controller_register_global_keygrabs (SpiDeviceEventController *controller,
> -                                        DEControllerKeyListener *key_listener)
> +                                        DEControllerKeyListener  *key_listener)
>  {
> -  DEControllerGrabMask grabmask, *grabmask_ptr;
> -  GList *list_ptr;
> -  gint i;
> +  DEControllerGrabMask grabmask;
> +
>    /* TODO: deregistration version of this function */
> 
>    grabmask.modmask = key_listener->mask;
>    if (key_listener->keys->_length == 0) /* special case means AnyKey/AllKeys */
>      {
>        grabmask.keyval = AnyKey;
> -      list_ptr = g_list_find_custom (controller->keygrabs_list, &grabmask,
> -                                    spi_grabmask_compare_values);
> -      if (list_ptr)
> -        {
> -          grabmask_ptr = (DEControllerGrabMask *) list_ptr->data;
> -         grabmask_ptr->refcount++;
> -        }
> -      else
> -        {
> -         controller->keygrabs_list =
> -                 g_list_prepend (controller->keygrabs_list,
> -                                 spi_grabmask_clone (&grabmask));
> -        }
> +      _register_keygrab (controller, &grabmask);
>      }
>    else
>      {
> +      int i;
> +
>        for (i = 0; i < key_listener->keys->_length; ++i)
>          {
>           long int keyval = key_listener->keys->_buffer[i];
>           /* X Grabs require keycodes, not keysyms */
>           if (keyval >= 0)
>             {
> -             keyval = XKeysymToKeycode(spi_get_display (), (KeySym) keyval);
> +             keyval = XKeysymToKeycode (GDK_DISPLAY (), (KeySym) keyval);
>             }
>           grabmask.keyval = keyval;
> -          list_ptr = g_list_find_custom (controller->keygrabs_list, &grabmask,
> -                                            spi_grabmask_compare_values);
> -          if (list_ptr)
> -            {
> -             grabmask_ptr = (DEControllerGrabMask *) list_ptr->data;
> -              grabmask_ptr->refcount++;
> -            }
> -          else
> -            {
> -             controller->keygrabs_list =
> -                 g_list_prepend (controller->keygrabs_list,
> -                                 spi_grabmask_clone (&grabmask));
> -             fprintf (stderr, "appending mask with val=%lu\n",
> -                      (unsigned long) grabmask.modmask);
> -            }
> -        }
> +
> +         _register_keygrab (controller, &grabmask);
> +       }
>      }
>  }
> 
>  static void
>  spi_controller_register_device_listener (SpiDeviceEventController *controller,
> -                                        DEControllerListener *listener,
> -                                        CORBA_Environment *ev)
> +                                        DEControllerListener     *listener,
> +                                        CORBA_Environment        *ev)
>  {
>    DEControllerKeyListener *key_listener;
> 
> @@ -276,74 +230,65 @@ spi_controller_register_device_listener
>           spi_controller_register_global_keygrabs (controller, key_listener);
>         }
>        break;
> -  case SPI_DEVICE_TYPE_MOUSE:
> -/*    controller->mouse_listeners = g_list_append (controller->mouse_listeners,
> -                                                   CORBA_Object_duplicate (l, ev));*/
> -
> -/* this interface should only be used for mouse motion events, not mouse clicks events */
> +    default:
>        break;
>    }
>  }
> 
> -static void
> -spi_controller_deregister_device_listener (SpiDeviceEventController *controller,
> -                                          DEControllerListener *listener,
> -                                          CORBA_Environment *ev)
> -{
> -  Accessibility_ControllerEventMask *mask_ptr;
> -  DEControllerListener *dec_listener;
> -  GList *list_ptr;
> -  switch (listener->type)
> -    {
> -      case SPI_DEVICE_TYPE_KBD:
> -        spi_controller_deregister_global_keygrabs (controller,
> -                                                  (DEControllerKeyListener *) listener);
> -
> -        /* now, remove this listener from the keylistener list */
> -        list_ptr = g_list_find_custom (controller->key_listeners, listener, spi_compare_listeners);
> -        if (list_ptr)
> -          {
> -           dec_listener = (DEControllerListener *) list_ptr->data;
> -#ifdef SPI_DEBUG
> -           g_print ("removing keylistener %p\n", dec_listener->object);
> -#endif
> -           controller->key_listeners = g_list_remove_link (controller->key_listeners,
> -                                                         list_ptr);
> -           spi_dec_key_listener_free ((DEControllerKeyListener *) dec_listener, ev);
> -         }
> -        break;
> -      case SPI_DEVICE_TYPE_MOUSE: /* TODO: implement */
> -        break;
> +static GdkFilterReturn
> +global_filter_fn (GdkXEvent *gdk_xevent,
> +                 GdkEvent  *event,
> +                 gpointer   data)
> +{
> +  XEvent *xevent = gdk_xevent;
> +  SpiDeviceEventController *controller;
> +
> +  if (xevent->type != KeyPress && xevent->type != KeyRelease)
> +    {
> +      g_print ("Event %d\n", xevent->type);
> +      return GDK_FILTER_CONTINUE;
>      }
> +
> +  controller = SPI_DEVICE_EVENT_CONTROLLER (data);
> +
> +  spi_device_event_controller_forward_key_event (controller, xevent);
> +
> +  /* FIXME: is this right ? */
> +  return GDK_FILTER_CONTINUE;
>  }
> 
> -static gboolean
> +static void
>  spi_controller_register_with_devices (SpiDeviceEventController *controller)
>  {
> -  gboolean retval = FALSE;
> -
>    /* calls to device-specific implementations and routines go here */
>    /* register with: keyboard hardware code handler */
>    /* register with: (translated) keystroke handler */
> 
> -  /* We must open a new connection to the server to avoid clashing with the GDK event loop */
> -  root_window = DefaultRootWindow (spi_get_display ());
> -  XSelectInput (spi_get_display (),
> -               root_window,
> +/*  root_window = DefaultRootWindow (GDK_DISPLAY ());
> +    XSelectInput (GDK_DISPLAY (), root_window, KeyPressMask | KeyReleaseMask);*/
> +
> +  gdk_window_add_filter (NULL, global_filter_fn, controller);
> +
> +  gdk_window_set_events (gdk_get_default_root_window (),
> +                        GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
> +
> +  XSelectInput (GDK_DISPLAY (),
> +               DefaultRootWindow (GDK_DISPLAY ()),
>                 KeyPressMask | KeyReleaseMask);
> -  /* register with: mouse hardware device handler? */
> -  /* register with: mouse event handler */
> -  return retval;
>  }
> 
>  static gboolean
> -spi_key_set_contains_key (Accessibility_KeySet *key_set, const Accessibility_DeviceEvent *key_event)
> +spi_key_set_contains_key (Accessibility_KeySet            *key_set,
> +                         const Accessibility_DeviceEvent *key_event)
>  {
>    gint i;
>    gint len;
> 
> -  /* g_assert (key_set); */
> -  if (!key_set) { g_print ("null key set!"); return TRUE; }
> +  if (!key_set)
> +    {
> +      g_print ("null key set!");
> +      return TRUE;
> +    }
> 
>    len = key_set->_length;
> 
> @@ -353,17 +298,21 @@ spi_key_set_contains_key (Accessibility_
>        return TRUE;
>      }
> 
> -  for (i=0; i<len; ++i)
> +  for (i = 0; i < len; ++i)
>      {
>  #ifdef SPI_KEYEVENT_DEBUG
>        g_print ("key_set[%d] = %d; key_event %d, code %d\n",
> -               i,
> -              (int) key_set->_buffer[i],
> -              (int) key_event->id,
> -              (int) key_event->hw_code);
> +               i, (int) key_set->_buffer[i],
> +              (int) key_event->id, (int) key_event->hw_code);
>  #endif
> -      if (key_set->_buffer[i] == (CORBA_long) key_event->id) return TRUE;
> -      if (key_set->_buffer[i] == (CORBA_long) -key_event->hw_code) return TRUE;
> +      if (key_set->_buffer[i] == (CORBA_long) key_event->id)
> +        {
> +          return TRUE;
> +       }
> +      if (key_set->_buffer[i] == (CORBA_long) -key_event->hw_code)
> +        {
> +          return TRUE;
> +       }
>      }
> 
>    return FALSE;
> @@ -375,9 +324,13 @@ spi_key_eventtype_seq_contains_event (Ac
>  {
>    gint i;
>    gint len;
> +
> 
> -  /* g_assert (type_seq); */
> -  if (!type_seq) { g_print ("null type seq!"); return TRUE; }
> +  if (!type_seq)
> +    {
> +      g_print ("null type seq!");
> +      return TRUE;
> +    }
> 
>    len = type_seq->_length;
> 
> @@ -386,13 +339,16 @@ spi_key_eventtype_seq_contains_event (Ac
>        return TRUE;
>      }
> 
> -  for (i=0; i<len; ++i)
> +  for (i = 0; i < len; ++i)
>      {
>  #ifdef SPI_DEBUG
> -      g_print ("type_seq[%d] = %d; key event type = %d\n", i, (int) type_seq->_buffer[i],
> -              (int) key_event->type);
> +      g_print ("type_seq[%d] = %d; key event type = %d\n", i,
> +              (int) type_seq->_buffer[i], (int) key_event->type);
>  #endif
> -      if (type_seq->_buffer[i] == (CORBA_long) key_event->type) return TRUE;
> +      if (type_seq->_buffer[i] == (CORBA_long) key_event->type)
> +        {
> +          return TRUE;
> +       }
>      }
> 
>    return FALSE;
> @@ -404,6 +360,7 @@ spi_key_event_matches_listener (const Ac
>                                 CORBA_boolean                    is_system_global)
>  {
>    g_print ("checking keycode %d\n", (int) key_event->hw_code);
> +
>    if ((key_event->modifiers == (CORBA_unsigned_short) (listener->mask & 0xFFFF)) &&
>         spi_key_set_contains_key (listener->keys, key_event) &&
>         spi_key_eventtype_seq_contains_event (listener->typeseq, key_event) &&
> @@ -412,39 +369,71 @@ spi_key_event_matches_listener (const Ac
>        return TRUE;
>      }
>    else
> -    return FALSE;
> +    {
> +      return FALSE;
> +    }
>  }
> 
>  static gboolean
> -spi_notify_keylisteners (GList *key_listeners,
> +spi_notify_keylisteners (GList                          **key_listeners,
>                          const Accessibility_DeviceEvent *key_event,
> -                        CORBA_boolean is_system_global,
> -                        CORBA_Environment *ev)
> +                        CORBA_boolean                    is_system_global,
> +                        CORBA_Environment               *ev)
>  {
> -  int i, n_listeners = g_list_length (key_listeners);
> -  gboolean is_consumed = FALSE;
> +  GList   *l;
> +  GSList  *notify = NULL, *l2;
> +  gboolean is_consumed;
> 
> -  for (i=0; i<n_listeners && !is_consumed; ++i)
> +  if (!key_listeners)
>      {
> -      Accessibility_DeviceEventListener ls;
> -      DEControllerKeyListener *key_listener = (DEControllerKeyListener *)
> -           g_list_nth_data (key_listeners, i);
> -      ls = (Accessibility_DeviceEventListener) key_listener->listener.object;
> -      if (spi_key_event_matches_listener (key_event, key_listener, is_system_global))
> -        {
> -          if (!CORBA_Object_is_nil(ls, ev))
> -            {
> -             is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, key_event, ev);
> -            }
> -        }
> -      else
> -        {
> +      return FALSE;
> +    }
> +
> +  for (l = *key_listeners; l; l = l->next)
> +    {
> +       DEControllerKeyListener *key_listener = l->data;
> +
> +       if (spi_key_event_matches_listener (key_event, key_listener, is_system_global))
> +         {
> +           Accessibility_DeviceEventListener ls = key_listener->listener.object;
> +
> +          if (ls != CORBA_OBJECT_NIL)
> +            {
> +               notify = g_slist_prepend (notify, CORBA_Object_duplicate (ls, ev));
> +            }
> +         }
> +    }
> +
>  #ifdef SPI_KEYEVENT_DEBUG
> -             g_print ("no match for listener %d\n", i);
> +  if (!notify)
> +    {
> +      g_print ("no match for listener %d\n", i);
> +    }
>  #endif
> -             ;
> -       }
> +
> +  is_consumed = FALSE;
> +  for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
> +    {
> +      Accessibility_DeviceEventListener ls = l2->data;
> +
> +      is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, key_event, ev);
> +
> +      if (BONOBO_EX (ev))
> +        {
> +          is_consumed = FALSE;
> +         CORBA_exception_free (ev);
> +        }
> +
> +      CORBA_Object_release (ls, ev);
> +    }
> +
> +  for (; l2; l2 = l2->next)
> +    {
> +      CORBA_Object_release (l2->data, ev);
>      }
> +
> +  g_slist_free (notify);
> +
>    return is_consumed;
>  }
> 
> @@ -515,62 +504,13 @@ spi_keystroke_from_x_key_event (XKeyEven
>    return key_event;
>  }
> 
> -
> -static gboolean
> -spi_check_key_event (SpiDeviceEventController *controller)
> -{
> -       static gboolean initialized = FALSE;
> -       XEvent *x_event = g_new0 (XEvent, 1);
> -       XKeyEvent *x_key_event;
> -       gboolean is_consumed = FALSE;
> -       Accessibility_DeviceEvent key_event;
> -       static CORBA_Environment ev;
> -
> -       if (!initialized)
> -       {
> -         initialized = TRUE;
> -         CORBA_exception_init (&ev);
> -       }
> -
> -       while (XPending(spi_get_display ()))
> -         {
> -           XNextEvent (spi_get_display (), x_event);
> -           if (XFilterEvent (x_event, None)) continue;
> -           if (x_event->type == KeyPress || x_event->type == KeyRelease)
> -             {
> -               key_event = spi_keystroke_from_x_key_event ((XKeyEvent *) x_event);
> -               /* relay to listeners, and decide whether to consume it or not */
> -               is_consumed = spi_notify_keylisteners (controller->key_listeners, &key_event, CORBA_TRUE, &ev);
> -             }
> -           else
> -             {
> -#ifdef SPI_KEYEVENT_DEBUG
> -               fprintf (stderr, "other event, type %d\n", (int) x_event->type);
> -#endif
> -             }
> -
> -           if (is_consumed)
> -             {
> -               XAllowEvents (spi_get_display (), AsyncKeyboard, CurrentTime);
> -             }
> -           else
> -             {
> -               XAllowEvents (spi_get_display (), ReplayKeyboard, CurrentTime);
> -             }
> -         }
> -       XUngrabKey (spi_get_display (), AnyKey, AnyModifier, root_window);
> -
> -       return spi_controller_grab_keyboard (controller);
> -}
> -
>  static gboolean
>  spi_controller_grab_keyboard (SpiDeviceEventController *controller)
>  {
> -  GList *maskList = controller->keygrabs_list;
> -  int i;
> -  int last_mask;
> -  last_mask = g_list_length (maskList);
> +  GList *l;
> 
> +  g_return_val_if_fail (controller != NULL, FALSE);
> +
>  /*
>   * masks known to work with default RH 7.1:
>   * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
> @@ -580,30 +520,29 @@ spi_controller_grab_keyboard (SpiDeviceE
>   *
>   * ControlMask grabs are broken, must be in use already
>   */
> -
> -  for (i=0; i < last_mask; ++i)
> +
> +  for (l = controller->keygrabs_list; l; l = l->next)
>      {
> -      DEControllerGrabMask * grab_mask
> -               = (DEControllerGrabMask *) g_list_nth_data (maskList, i);
> -      unsigned long maskVal = 0xFFFFFFFF;
> -      int           keyVal = AnyKey;
> -      if (grab_mask)
> -        {
> -         maskVal = (unsigned long) grab_mask->modmask;
> -         keyVal =  grab_mask->keyval;
> -        }
> +      DEControllerGrabMask *grab_mask = l->data;
> +
> +      g_assert (grab_mask != NULL);
> +
>  #ifdef SPI_DEBUG
> -      fprintf (stderr, "mask=%lx\n", maskVal);
> +      fprintf (stderr, "mask=%lx %lx\n",
> +              (long int) grab_mask->keyval,
> +              (long int) grab_mask->modmask);
>  #endif
> -      XGrabKey (spi_get_display (),
> -               keyVal,
> -               maskVal,
> +
> +      XGrabKey (GDK_DISPLAY (),
> +               grab_mask->keyval,
> +               grab_mask->modmask,
>                 root_window,
>                 True,
>                 GrabModeAsync,
>                 GrabModeAsync);
>           /* TODO: check call for errors and return FALSE if error occurs */
>      }
> +
>    return TRUE;
>  }
> 
> @@ -613,7 +552,10 @@ spi_controller_grab_keyboard (SpiDeviceE
>  static void
>  spi_device_event_controller_object_finalize (GObject *object)
>  {
> +  SpiDeviceEventController *controller;
> 
> +  controller = SPI_DEVICE_EVENT_CONTROLLER (object);
> +
>  #ifdef SPI_DEBUG
>    fprintf(stderr, "spi_device_event_controller_object_finalize called\n");
>  #endif
> @@ -627,13 +569,13 @@ spi_device_event_controller_object_final
>   *     method implementation
>   */
>  static void
> -impl_register_keystroke_listener (PortableServer_Servant     servant,
> +impl_register_keystroke_listener (PortableServer_Servant                  servant,
>                                   const Accessibility_DeviceEventListener l,
> -                                 const Accessibility_KeySet *keys,
> +                                 const Accessibility_KeySet             *keys,
>                                   const Accessibility_ControllerEventMask mask,
> -                                 const Accessibility_KeyEventTypeSeq *type,
> -                                 const Accessibility_EventListenerMode *mode,
> -                                 CORBA_Environment         *ev)
> +                                 const Accessibility_KeyEventTypeSeq    *type,
> +                                 const Accessibility_EventListenerMode  *mode,
> +                                 CORBA_Environment                      *ev)
>  {
>    SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER (
>           bonobo_object_from_servant (servant));
> @@ -646,59 +588,69 @@ impl_register_keystroke_listener (Portab
>    spi_controller_register_device_listener (controller, (DEControllerListener *) dec_listener, ev);
>  }
> 
> +
> +typedef struct {
> +       CORBA_Environment       *ev;
> +       DEControllerKeyListener *key_listener;
> +} RemoveKeyListenerClosure;
> +
> +static SpiReEnterantContinue
> +remove_key_listener_cb (GList * const *list,
> +                       gpointer       user_data)
> +{
> +  DEControllerKeyListener  *key_listener = (*list)->data;
> +  RemoveKeyListenerClosure *ctx = user_data;
> +
> +  if (CORBA_Object_is_equivalent (ctx->key_listener->listener.object,
> +                                 key_listener->listener.object, ctx->ev))
> +    {
> +      spi_re_enterant_list_delete_link (list);
> +      spi_dec_key_listener_free (key_listener, ctx->ev);
> +    }
> +
> +  return SPI_RE_ENTERANT_CONTINUE;
> +}
> +
>  /*
>   * CORBA Accessibility::DeviceEventController::deregisterKeystrokeListener
>   *     method implementation
>   */
>  static void
> -impl_deregister_keystroke_listener (PortableServer_Servant     servant,
> +impl_deregister_keystroke_listener (PortableServer_Servant                  servant,
>                                     const Accessibility_DeviceEventListener l,
> -                                   const Accessibility_KeySet *keys,
> +                                   const Accessibility_KeySet             *keys,
>                                     const Accessibility_ControllerEventMask mask,
> -                                   const Accessibility_KeyEventTypeSeq *type,
> -                                   CORBA_Environment         *ev)
> +                                   const Accessibility_KeyEventTypeSeq    *type,
> +                                   CORBA_Environment                      *ev)
>  {
> -       SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER (
> -               bonobo_object_from_servant (servant));
> -       DEControllerKeyListener *key_listener = spi_dec_key_listener_new (l,
> -                                                                         keys,
> -                                                                         mask,
> -                                                                         type,
> -                                                                         NULL,
> -                                                                         ev);
> +  DEControllerKeyListener  *key_listener;
> +  RemoveKeyListenerClosure  ctx;
> +  SpiDeviceEventController *controller;
> +
> +  controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
> +
> +  key_listener = spi_dec_key_listener_new (l, keys, mask, type, NULL, ev);
> +
>  #ifdef SPI_DEREGISTER_DEBUG
> -       fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
> -                (void *) l, (unsigned long) mask->value);
> +  fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
> +          (void *) l, (unsigned long) mask->value);
>  #endif
> -       spi_controller_deregister_device_listener(controller,
> -                                             (DEControllerListener *) key_listener,
> -                                             ev);
> -       spi_dec_key_listener_free (key_listener, ev);
> -}
> 
> -/*
> - * CORBA Accessibility::DeviceEventController::registerMouseListener
> - *     method implementation
> - */
> -/*
> -static void
> -impl_register_mouse_listener (PortableServer_Servant     servant,
> -                             const Accessibility_MouseListener *l,
> -                             CORBA_Environment         *ev)
> -{
> -       SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER (
> -               bonobo_object_from_servant (servant));
> -#ifdef SPI_DEBUG
> -       fprintf (stderr, "registering mouse listener %p\n", l);
> -#endif
> -       spi_controller_register_device_listener(controller, DEVICE_TYPE_MOUSE, l, keys, mask, ev);
> +  spi_controller_deregister_global_keygrabs (controller, key_listener);
> +
> +  ctx.ev = ev;
> +  ctx.key_listener = key_listener;
> +
> +  spi_re_enterant_list_foreach (&controller->key_listeners,
> +                               remove_key_listener_cb, &ctx);
> +
> +  spi_dec_key_listener_free (key_listener, ev);
>  }
> -*/
> 
>  static KeyCode
>  keycode_for_keysym (long keysym)
>  {
> -  return XKeysymToKeycode (spi_get_display (), (KeySym) keysym);
> +  return XKeysymToKeycode (GDK_DISPLAY (), (KeySym) keysym);
>  }
> 
>  #define SPI_DEBUG
> @@ -715,6 +667,7 @@ impl_generate_keyboard_event (PortableSe
>                               CORBA_Environment          *ev)
>  {
>    long key_synth_code;
> +
>  #ifdef SPI_DEBUG
>    fprintf (stderr, "synthesizing keystroke %ld, type %d\n", (long) keycode, (int) synth_type);
>  #endif
> @@ -732,17 +685,20 @@ impl_generate_keyboard_event (PortableSe
>    switch (synth_type)
>      {
>        case Accessibility_KEY_PRESS:
> -         XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, True, CurrentTime);
> +         XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, True, CurrentTime);
>           break;
>        case Accessibility_KEY_PRESSRELEASE:
> -         XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, True, CurrentTime);
> +         XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, True, CurrentTime);
>        case Accessibility_KEY_RELEASE:
> -         XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, False, CurrentTime);
> +         XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, False, CurrentTime);
>           break;
>        case Accessibility_KEY_SYM:
>           key_synth_code = keycode_for_keysym (keycode);
> -         XTestFakeKeyEvent (spi_get_display (), (unsigned int) key_synth_code, True, CurrentTime);
> -         XTestFakeKeyEvent (spi_get_display (), (unsigned int) key_synth_code, False, CurrentTime);
> +         XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) key_synth_code, True, CurrentTime);
> +         XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) key_synth_code, False, CurrentTime);
> +         break;
> +      case Accessibility_KEY_STRING:
> +         fprintf (stderr, "Not yet implemented\n");
>           break;
>     }
>  }
> @@ -756,85 +712,121 @@ impl_generate_mouse_event (PortableServe
>                            CORBA_Environment     *ev)
>  {
>  #ifdef SPI_DEBUG
> -  fprintf (stderr, "generating mouse %s event at %ld, %ld\n", eventName, x, y);
> +  fprintf (stderr, "generating mouse %s event at %ld, %ld\n",
> +          eventName, (long int) x, (long int) y);
>  #endif
> +  g_warning ("not yet implemented");
>  }
> 
>  /* Accessibility::DeviceEventController::notifyListenersSync */
>  static CORBA_boolean
> -impl_notify_listeners_sync(PortableServer_Servant     servant,
> -                          const Accessibility_DeviceEvent *event,
> -                          CORBA_Environment         *ev)
> +impl_notify_listeners_sync (PortableServer_Servant           servant,
> +                           const Accessibility_DeviceEvent *event,
> +                           CORBA_Environment               *ev)
>  {
>    SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER (
> -                                         bonobo_object_from_servant (servant));
> +    bonobo_object_from_servant (servant));
>  #ifdef SPI_DEBUG
> -  g_print ("notifylistening listeners synchronously: controller %x, event id %d\n",
> -          (void *) controller, (int) event->id);
> +  g_print ("notifylistening listeners synchronously: controller %p, event id %d\n",
> +          controller, (int) event->id);
>  #endif
> -  return (spi_notify_keylisteners (controller->key_listeners, event, CORBA_FALSE, ev) ?
> -         CORBA_TRUE : CORBA_FALSE);
> +  return spi_notify_keylisteners (&controller->key_listeners, event, CORBA_FALSE, ev) ?
> +         CORBA_TRUE : CORBA_FALSE;
>  }
> 
>  /* Accessibility::DeviceEventController::notifyListenersAsync */
>  static void
> -impl_notify_listeners_async (PortableServer_Servant     servant,
> +impl_notify_listeners_async (PortableServer_Servant           servant,
>                              const Accessibility_DeviceEvent *event,
> -                            CORBA_Environment         *ev)
> +                            CORBA_Environment               *ev)
>  {
> -  SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER(
> -                                        bonobo_object_from_servant (servant));
> +  SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER (
> +    bonobo_object_from_servant (servant));
>  #ifdef SPI_DEBUG
>    fprintf (stderr, "notifying listeners asynchronously\n");
>  #endif
> -  spi_notify_keylisteners (controller->key_listeners, event, CORBA_FALSE, ev);
> +  spi_notify_keylisteners (&controller->key_listeners, event, CORBA_FALSE, ev);
>  }
> 
>  static void
>  spi_device_event_controller_class_init (SpiDeviceEventControllerClass *klass)
>  {
> -        GObjectClass * object_class = (GObjectClass *) klass;
> -        POA_Accessibility_DeviceEventController__epv *epv = &klass->epv;
> -        spi_device_event_controller_parent_class = g_type_class_peek_parent (klass);
> -
> -        object_class->finalize = spi_device_event_controller_object_finalize;
> -
> -        epv->registerKeystrokeListener = impl_register_keystroke_listener;
> -        epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener;
> -/*        epv->registerMouseListener = impl_register_mouse_listener; */
> -        epv->generateKeyboardEvent = impl_generate_keyboard_event;
> -        epv->generateMouseEvent = impl_generate_mouse_event;
> -       epv->notifyListenersSync = impl_notify_listeners_sync;
> -       epv->notifyListenersAsync = impl_notify_listeners_async;
> -       klass->check_key_event = spi_check_key_event;
> +  GObjectClass * object_class = (GObjectClass *) klass;
> +  POA_Accessibility_DeviceEventController__epv *epv = &klass->epv;
> +
> +  spi_device_event_controller_parent_class = g_type_class_peek_parent (klass);
> +
> +  object_class->finalize = spi_device_event_controller_object_finalize;
> +
> +  epv->registerKeystrokeListener   = impl_register_keystroke_listener;
> +  epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener;
> +  epv->generateKeyboardEvent       = impl_generate_keyboard_event;
> +  epv->generateMouseEvent          = impl_generate_mouse_event;
> +  epv->notifyListenersSync         = impl_notify_listeners_sync;
> +  epv->notifyListenersAsync        = impl_notify_listeners_async;
>  }
> 
>  static void
>  spi_device_event_controller_init (SpiDeviceEventController *device_event_controller)
>  {
> -  device_event_controller->key_listeners = NULL;
> +  device_event_controller->key_listeners   = NULL;
>    device_event_controller->mouse_listeners = NULL;
> -  device_event_controller->keygrabs_list = NULL;
> -  kbd_registered = spi_controller_register_with_devices (device_event_controller);
> +  device_event_controller->keygrabs_list   = NULL;
> +
> +  /*
> +   * TODO: fixme, this module makes the foolish assumption that
> +   * registryd uses the same display as the apps, and the the DISPLAY
> +   * environment variable is set.
> +   */
> +  gdk_init (NULL, NULL);
> +
> +  spi_controller_register_with_devices (device_event_controller);
>  }
> 
> -gboolean
> -spi_device_event_controller_check_key_event (SpiDeviceEventController *controller)
> +static void
> +spi_device_event_controller_forward_key_event (SpiDeviceEventController *controller,
> +                                              const XEvent             *event)
>  {
> -  SpiDeviceEventControllerClass *klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
> -  if (klass->check_key_event)
> -       return (klass->check_key_event) (controller);
> -  return FALSE;
> +  gboolean is_consumed = FALSE;
> +  CORBA_Environment ev;
> +  Accessibility_DeviceEvent key_event;
> +
> +  g_assert (event->type == KeyPress || event->type == KeyRelease);
> +
> +  CORBA_exception_init (&ev);
> +
> +  g_warning ("Got key event");
> +
> +  key_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event);
> +  /* relay to listeners, and decide whether to consume it or not */
> +  is_consumed = spi_notify_keylisteners (
> +    &controller->key_listeners, &key_event, CORBA_TRUE, &ev);
> +
> +  CORBA_exception_free (&ev);
> +
> +  if (is_consumed)
> +    {
> +      XAllowEvents (GDK_DISPLAY (), AsyncKeyboard, CurrentTime);
> +    }
> +  else
> +    {
> +      XAllowEvents (GDK_DISPLAY (), ReplayKeyboard, CurrentTime);
> +    }
> +
> +  /* FIXME - this looks strange and inefficient */
> +  XUngrabKey (GDK_DISPLAY (), AnyKey, AnyModifier, root_window);
> +  spi_controller_grab_keyboard (controller);
>  }
> 
>  SpiDeviceEventController *
> -spi_device_event_controller_new (void *registryp)
> +spi_device_event_controller_new (SpiRegistry *registry)
>  {
> -  BonoboObject *registry = (BonoboObject *) registryp;
>    SpiDeviceEventController *retval = g_object_new (
> -         SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
> -  retval->registry = registry;
> -  bonobo_object_ref (registry);
> +    SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
> +
> +  retval->registry = SPI_REGISTRY (bonobo_object_ref (
> +         BONOBO_OBJECT (registry)));
> +
>    return retval;
>  }
> 
> Index: registryd/deviceeventcontroller.h
> ===================================================================
> RCS file: /cvs/gnome/at-spi/registryd/deviceeventcontroller.h,v
> retrieving revision 1.10
> diff -u -p -u -r1.10 deviceeventcontroller.h
> --- registryd/deviceeventcontroller.h   2001/12/15 22:54:00     1.10
> +++ registryd/deviceeventcontroller.h   2002/01/09 12:13:35
> @@ -27,6 +27,10 @@
>  #include <libspi/Accessibility.h>
>  #include <libspi/keystrokelistener.h>
> 
> +typedef struct _SpiDeviceEventController SpiDeviceEventController;
> +
> +#include "registry.h"
> +
>  G_BEGIN_DECLS
> 
>  #define SPI_DEVICE_EVENT_CONTROLLER_TYPE        (spi_device_event_controller_get_type ())
> @@ -36,23 +40,23 @@ G_BEGIN_DECLS
>  #define SPI_IS_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_DEVICE_EVENT_CONTROLLER_TYPE))
>  #define SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDeviceEventControllerClass))
> 
> -typedef struct {
> +struct _SpiDeviceEventController {
>    BonoboObject parent;
> -  void  *registry;
> -  GList *key_listeners;
> -  GList *mouse_listeners;
> -  GList *keygrabs_list;
> -} SpiDeviceEventController;
> 
> +  SpiRegistry *registry;
> +  GList       *key_listeners;
> +  GList       *mouse_listeners;
> +  GList       *keygrabs_list;
> +};
> +
>  typedef struct {
>    BonoboObjectClass parent_class;
> +
>    POA_Accessibility_DeviceEventController__epv epv;
> -  gboolean (*check_key_event) (SpiDeviceEventController *controller);
>  } SpiDeviceEventControllerClass;
> 
>  GType                     spi_device_event_controller_get_type        (void);
> -SpiDeviceEventController *spi_device_event_controller_new             (void *registry);
> -gboolean                  spi_device_event_controller_check_key_event (SpiDeviceEventController *controller);
> +SpiDeviceEventController *spi_device_event_controller_new             (SpiRegistry  *registry);
> 
>  G_END_DECLS
> 
> Index: registryd/registry-main.c
> ===================================================================
> RCS file: /cvs/gnome/at-spi/registryd/registry-main.c,v
> retrieving revision 1.10
> diff -u -p -u -r1.10 registry-main.c
> --- registryd/registry-main.c   2001/12/07 16:43:30     1.10
> +++ registryd/registry-main.c   2002/01/09 12:13:35
> @@ -24,6 +24,7 @@
>  #include <stdlib.h>
>  #endif
> 
> +#include <gdk/gdk.h>
>  #include <libbonobo.h>
>  #include <glib/gmain.h>
>  #include "registry.h"
> @@ -59,7 +60,6 @@ main (int argc, char **argv)
>  #ifdef AT_SPI_DEBUG
>        fprintf (stderr, "SpiRegistry Message: SpiRegistry daemon is running.\n");
>  #endif
> -      g_timeout_add_full (G_PRIORITY_HIGH_IDLE, 200, registry->kbd_event_hook, registry, NULL);
>        bonobo_main ();
>      }
> 
> Index: registryd/registry.c
> ===================================================================
> RCS file: /cvs/gnome/at-spi/registryd/registry.c,v
> retrieving revision 1.35
> diff -u -p -u -r1.35 registry.c
> --- registryd/registry.c        2002/01/08 09:11:46     1.35
> +++ registryd/registry.c        2002/01/09 12:13:35
> @@ -30,6 +30,7 @@
>  #endif
> 
>  #include <bonobo/bonobo-exception.h>
> +#include "../libspi/spi-private.h"
>  #include "registry.h"
> 
>  /* Our parent GObject type  */
> @@ -63,8 +64,6 @@ typedef struct {
>    EventTypeCategory event_type_cat;
>  } SpiListenerStruct;
> 
> -/* static function prototypes */
> -static gboolean _device_event_controller_hook (gpointer source);
> 
>  SpiListenerStruct *
>  spi_listener_struct_new (Accessibility_EventListener listener, CORBA_Environment *ev)
> @@ -347,7 +346,7 @@ impl_accessibility_registry_register_glo
>      }
>  }
> 
> -static void
> +static SpiReEnterantContinue
>  remove_listener_cb (GList * const *list, gpointer user_data)
>  {
>    SpiListenerStruct *ls = (SpiListenerStruct *) (*list)->data;
> @@ -363,6 +362,8 @@ remove_listener_cb (GList * const *list,
>      }
> 
>    CORBA_exception_free (&ev);
> +
> +  return SPI_RE_ENTERANT_CONTINUE;
>  }
> 
>  /*
> @@ -407,7 +408,7 @@ impl_accessibility_registry_deregister_g
>    parse_event_type (&etype, (char *) event_name);
> 
>    spi_re_enterant_list_foreach (get_listener_list (registry, etype.type_cat),
> -                           remove_listener_cb, listener);
> +                               remove_listener_cb, listener);
>  }
> 
> 
> @@ -503,7 +504,7 @@ typedef struct {
>    Accessibility_Event e_out;
>  } NotifyContext;
> 
> -static void
> +static SpiReEnterantContinue
>  notify_listeners_cb (GList * const *list, gpointer user_data)
>  {
>    SpiListenerStruct *ls;
> @@ -531,7 +532,9 @@ notify_listeners_cb (GList * const *list
> 
>        ctx->e_out.source = bonobo_object_dup_ref (ctx->source, ctx->ev);
>        if (BONOBO_EX (ctx->ev))
> -             return;
> +        {
> +          return SPI_RE_ENTERANT_CONTINUE;;
> +       }
> 
>        if ((*list) && (*list)->data == ls)
>          {
> @@ -549,6 +552,8 @@ notify_listeners_cb (GList * const *list
>            bonobo_object_release_unref (ctx->e_out.source, ctx->ev);
>         }
>      }
> +
> +  return SPI_RE_ENTERANT_CONTINUE;
>  }
> 
>  static void
> @@ -582,37 +587,28 @@ impl_registry_notify_event (PortableServ
>      }
>  }
> 
> -static gboolean
> -_device_event_controller_hook (gpointer p)
> -{
> -    SpiRegistry *registry = (SpiRegistry *)p;
> -    SpiDeviceEventController *controller = registry->device_event_controller;
> -    if (controller)
> -       spi_device_event_controller_check_key_event (controller);
> -    return TRUE;
> -}
> 
>  static void
>  spi_registry_class_init (SpiRegistryClass *klass)
>  {
> -        GObjectClass * object_class = (GObjectClass *) klass;
> -        POA_Accessibility_Registry__epv *epv = &klass->epv;
> +  GObjectClass * object_class = (GObjectClass *) klass;
> +  POA_Accessibility_Registry__epv *epv = &klass->epv;
> 
> -        spi_registry_parent_class = g_type_class_ref (SPI_LISTENER_TYPE);
> -
> -        object_class->finalize = spi_registry_object_finalize;
> -
> -        epv->registerApplication = impl_accessibility_registry_register_application;
> -        epv->deregisterApplication = impl_accessibility_registry_deregister_application;
> -        epv->registerGlobalEventListener = impl_accessibility_registry_register_global_event_listener;
> -        epv->deregisterGlobalEventListener = impl_accessibility_registry_deregister_global_event_listener;
> -        epv->deregisterGlobalEventListenerAll = impl_accessibility_registry_deregister_global_event_listener_all;
> -        epv->getDeviceEventController = impl_accessibility_registry_get_device_event_controller;
> -        epv->getDesktopCount = impl_accessibility_registry_get_desktop_count;
> -        epv->getDesktop = impl_accessibility_registry_get_desktop;
> -        epv->getDesktopList = impl_accessibility_registry_get_desktop_list;
> -
> -        ((SpiListenerClass *) klass)->epv.notifyEvent = impl_registry_notify_event;
> +  spi_registry_parent_class = g_type_class_ref (SPI_LISTENER_TYPE);
> +
> +  object_class->finalize = spi_registry_object_finalize;
> +
> +  epv->registerApplication = impl_accessibility_registry_register_application;
> +  epv->deregisterApplication = impl_accessibility_registry_deregister_application;
> +  epv->registerGlobalEventListener = impl_accessibility_registry_register_global_event_listener;
> +  epv->deregisterGlobalEventListener = impl_accessibility_registry_deregister_global_event_listener;
> +  epv->deregisterGlobalEventListenerAll = impl_accessibility_registry_deregister_global_event_listener_all;
> +  epv->getDeviceEventController = impl_accessibility_registry_get_device_event_controller;
> +  epv->getDesktopCount = impl_accessibility_registry_get_desktop_count;
> +  epv->getDesktop = impl_accessibility_registry_get_desktop;
> +  epv->getDesktopList = impl_accessibility_registry_get_desktop_list;
> +
> +  ((SpiListenerClass *) klass)->epv.notifyEvent = impl_registry_notify_event;
>  }
> 
>  static void
> @@ -623,7 +619,6 @@ spi_registry_init (SpiRegistry *registry
>    registry->toolkit_listeners = NULL;
>    registry->desktop = spi_desktop_new ();
>    registry->device_event_controller = NULL;
> -  registry->kbd_event_hook = _device_event_controller_hook;
>  }
> 
>  BONOBO_TYPE_FUNC_FULL (SpiRegistry,
> @@ -634,7 +629,7 @@ BONOBO_TYPE_FUNC_FULL (SpiRegistry,
>  SpiRegistry *
>  spi_registry_new (void)
>  {
> -    SpiRegistry *retval = g_object_new (SPI_REGISTRY_TYPE, NULL);
> -    bonobo_object_set_immortal (BONOBO_OBJECT (retval), TRUE);
> -    return retval;
> +  SpiRegistry *retval = g_object_new (SPI_REGISTRY_TYPE, NULL);
> +  bonobo_object_set_immortal (BONOBO_OBJECT (retval), TRUE);
> +  return retval;
>  }
> Index: registryd/registry.h
> ===================================================================
> RCS file: /cvs/gnome/at-spi/registryd/registry.h,v
> retrieving revision 1.13
> diff -u -p -u -r1.13 registry.h
> --- registryd/registry.h        2001/12/12 16:08:46     1.13
> +++ registryd/registry.h        2002/01/09 12:13:35
> @@ -26,6 +26,8 @@
>  #include <glib/gmain.h>
>  #include <libspi/listener.h>
> 
> +typedef struct _SpiRegistry SpiRegistry;
> +
>  #include "desktop.h"
>  #include "deviceeventcontroller.h"
> 
> @@ -37,15 +39,14 @@ G_BEGIN_DECLS
>  #define SPI_IS_REGISTRY(o)       (G_TYPE_CHECK__INSTANCE_TYPE ((o), SPI_REGISTRY_TYPE))
>  #define SPI_IS_REGISTRY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_REGISTRY_TYPE))
> 
> -typedef struct {
> +struct _SpiRegistry {
>    SpiListener parent;
>    GList *object_listeners;
>    GList *window_listeners;
>    GList *toolkit_listeners;
>    SpiDeviceEventController *device_event_controller;
>    SpiDesktop *desktop;
> -  gboolean (*kbd_event_hook) (gpointer source);
> -} SpiRegistry;
> +};
> 
>  typedef struct {
>          SpiListenerClass parent_class;
> Index: test/keysynth-demo.c
> ===================================================================
> RCS file: /cvs/gnome/at-spi/test/keysynth-demo.c,v
> retrieving revision 1.14
> diff -u -p -u -r1.14 keysynth-demo.c
> --- test/keysynth-demo.c        2002/01/01 22:35:33     1.14
> +++ test/keysynth-demo.c        2002/01/09 12:13:35
> @@ -319,7 +319,7 @@ button_exit (GtkButton *notused, void *a
>  }
> 
>  static SPIBoolean
> -is_command_key (AccessibleKeystroke *key, void *user_data)
> +is_command_key (const AccessibleKeystroke *key, void *user_data)
>  {
>    switch (key->keyID)
>      {
> @@ -332,7 +332,7 @@ is_command_key (AccessibleKeystroke *key
>  }
> 
>  static SPIBoolean
> -switch_callback (AccessibleKeystroke *key, void *user_data)
> +switch_callback (const AccessibleKeystroke *key, void *user_data)
>  {
>    static SPIBoolean is_down = FALSE;
> 
> Index: test/simple-at.c
> ===================================================================
> RCS file: /cvs/gnome/at-spi/test/simple-at.c,v
> retrieving revision 1.31
> diff -u -p -u -r1.31 simple-at.c
> --- test/simple-at.c    2002/01/08 09:11:47     1.31
> +++ test/simple-at.c    2002/01/09 12:13:35
> @@ -28,12 +28,12 @@
>  #include "../util/mag_client.h"
>  #include "../cspi/spi-private.h" /* A hack for now */
> 
> -static void report_focus_event    (AccessibleEvent *event, void *user_data);
> -static void report_generic_event  (AccessibleEvent *event, void *user_data);
> -static void report_button_press   (AccessibleEvent *event, void *user_data);
> -static void check_property_change (AccessibleEvent *event, void *user_data);
> -static SPIBoolean report_command_key_event  (AccessibleKeystroke *stroke, void *user_data);
> -static SPIBoolean report_ordinary_key_event (AccessibleKeystroke *stroke, void *user_data);
> +static void report_focus_event    (const AccessibleEvent *event, void *user_data);
> +static void report_generic_event  (const AccessibleEvent *event, void *user_data);
> +static void report_button_press   (const AccessibleEvent *event, void *user_data);
> +static void check_property_change (const AccessibleEvent *event, void *user_data);
> +static SPIBoolean report_command_key_event  (const AccessibleKeystroke *stroke, void *user_data);
> +static SPIBoolean report_ordinary_key_event (const AccessibleKeystroke *stroke, void *user_data);
>  static void get_environment_vars (void);
> 
>  static int _festival_init ();
> @@ -242,7 +242,7 @@ report_focussed_accessible (Accessible *
>  }
> 
>  void
> -report_focus_event (AccessibleEvent *event, void *user_data)
> +report_focus_event (const AccessibleEvent *event, void *user_data)
>  {
>    char *s;
> 
> @@ -259,13 +259,13 @@ report_focus_event (AccessibleEvent *eve
>  }
> 
>  void
> -report_generic_event (AccessibleEvent *event, void *user_data)
> +report_generic_event (const AccessibleEvent *event, void *user_data)
>  {
>    fprintf (stderr, "%s event received\n", event->type);
>  }
> 
>  void
> -report_button_press (AccessibleEvent *event, void *user_data)
> +report_button_press (const AccessibleEvent *event, void *user_data)
>  {
>    char *s;
> 
> @@ -281,7 +281,7 @@ report_button_press (AccessibleEvent *ev
>  }
> 
>  void
> -check_property_change (AccessibleEvent *event, void *user_data)
> +check_property_change (const AccessibleEvent *event, void *user_data)
>  {
>    AccessibleSelection *selection = Accessible_getSelection (event->source);
>    int n_selections;
> @@ -335,7 +335,7 @@ simple_at_exit ()
>  }
> 
>  static SPIBoolean
> -is_command_key (AccessibleKeystroke *key)
> +is_command_key (const AccessibleKeystroke *key)
>  {
>    switch (key->keyID)
>      {
> @@ -359,7 +359,7 @@ is_command_key (AccessibleKeystroke *key
>  }
> 
>  static SPIBoolean
> -report_command_key_event (AccessibleKeystroke *key, void *user_data)
> +report_command_key_event (const AccessibleKeystroke *key, void *user_data)
>  {
>    fprintf (stderr, "Command KeyEvent %s%c (keycode %d); string=%s; time=%lx\n",
>           (key->modifiers & SPI_KEYMASK_ALT)?"Alt-":"",
> @@ -373,7 +373,7 @@ report_command_key_event (AccessibleKeys
> 
> 
>  static SPIBoolean
> -report_ordinary_key_event (AccessibleKeystroke *key, void *user_data)
> +report_ordinary_key_event (const AccessibleKeystroke *key, void *user_data)
>  {
>    fprintf (stderr, "Received key event:\tsym %ld\n\tmods %x\n\tcode %d\n\tstring=\'%s\'\n\ttime %lx\n",
>            (long) key->keyID,
> Index: test/test-simple.c
> ===================================================================
> RCS file: /cvs/gnome/at-spi/test/test-simple.c,v
> retrieving revision 1.16
> diff -u -p -u -r1.16 test-simple.c
> --- test/test-simple.c  2002/01/08 09:11:47     1.16
> +++ test/test-simple.c  2002/01/09 12:13:36
> @@ -611,8 +611,8 @@ test_misc (void)
>  }
> 
>  static void
> -global_listener_cb (AccessibleEvent     *event,
> -                   void                *user_data)
> +global_listener_cb (const AccessibleEvent *event,
> +                   void                  *user_data)
>  {
>         TestWindow *win = user_data;
>         Accessible *desktop;
> @@ -643,6 +643,48 @@ global_listener_cb (AccessibleEvent
>         validate_accessible (event->source, TRUE, TRUE);
>  }
> 
> +static SPIBoolean
> +key_listener_cb (const AccessibleKeystroke *stroke,
> +                void                      *user_data)
> +{
> +       AccessibleKeystroke *s = user_data;
> +
> +       *s = *stroke;
> +
> +       g_warning ("Key listener callback");
> +
> +       return FALSE;
> +}
> +
> +static void
> +test_keylisteners (void)
> +{
> +       AccessibleKeystroke stroke;
> +       AccessibleKeystrokeListener *key_listener;
> +
> +       key_listener = SPI_createAccessibleKeystrokeListener (
> +               key_listener_cb, &stroke);
> +
> +       g_assert (SPI_registerAccessibleKeystrokeListener (
> +               key_listener, SPI_KEYSET_ALL_KEYS, 0,
> +               SPI_KEY_PRESSED | SPI_KEY_RELEASED,
> +               SPI_KEYLISTENER_CANCONSUME));
> +
> +       memset (&stroke, 0, sizeof (AccessibleKeystroke));
> +
> +       g_assert (SPI_generateKeyboardEvent (33, "!", SPI_KEY_PRESSRELEASE));
> +
> +       while (stroke.type == 0)
> +               g_main_iteration (TRUE);
> +
> +       g_assert (!strcmp (stroke.keystring, "!"));
> +       g_assert (stroke.type == SPI_KEY_PRESSRELEASE);
> +
> +       g_assert (SPI_deregisterAccessibleKeystrokeListener (key_listener, 0));
> +
> +       AccessibleKeystrokeListener_unref (key_listener);
> +}
> +
>  int
>  main (int argc, char **argv)
>  {
> @@ -670,6 +712,7 @@ main (int argc, char **argv)
>         test_roles ();
>         test_misc ();
>         test_desktop ();
> +       test_keylisteners ();
> 
>         win = create_test_window ();
> 
> 
> --
>  mmeeks gnu org  <><, Pseudo Engineer, itinerant idiot



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]