Fixed 'make dist', and added:
authorbillh <billh@e2bd861d-eb25-0410-b326-f6ed22b6b98c>
Mon, 8 Oct 2001 16:57:19 +0000 (16:57 +0000)
committerbillh <billh@e2bd861d-eb25-0410-b326-f6ed22b6b98c>
Mon, 8 Oct 2001 16:57:19 +0000 (16:57 +0000)
fixes for EditableText
more DeviceEventController stuff, and some keygrab implementation
Please see ChangeLog for additional info.

git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@70 e2bd861d-eb25-0410-b326-f6ed22b6b98c

35 files changed:
ChangeLog
configure.in
cspi/Makefile.am
cspi/spi-listener.h
cspi/spi.h
cspi/spi_accessible.c
cspi/spi_event.c
cspi/spi_registry.c
cspi/spi_text.c
idl/Accessibility_Registry.idl
idl/Accessibility_Text.idl
idl/Makefile.am
idl/Registry.idl
idl/Text.idl
libspi/Makefile.am
libspi/deviceeventcontroller.c
libspi/deviceeventcontroller.h
libspi/editabletext.c
libspi/editabletext.h
libspi/keystrokelistener.c
libspi/keystrokelistener.h
libspi/registry.c
libspi/registry.h
libspi/text.c
libspi/text.h
registryd/deviceeventcontroller.c
registryd/deviceeventcontroller.h
registryd/registry-main.c
registryd/registry.c
registryd/registry.h
registryd/registryd.c
test/simple-at.c
util/Accessibility_Util.server.in
util/Makefile.am
util/mag_client.c

index 5416f33..35f3af6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,78 @@
+<2001-10-08  Bill Haneman <bill.haneman@sun.com>
+
+       * util/Makefile.am:
+       * idl/Makefile.am:
+               Fixed 'make dist' so that distro compiles...
+       * libspi/keymasks.h:
+               new file.
+       * cspi/spi-listener.c:
+               KeystrokeListenerCB now returns a boolean.
+       * cspi/spi.h:
+               Added KeyEventType struct, and KeyStroke.
+               Also added createKeystrokeListener(),
+       KeystrokeListener_addCallback(),
+       KeystrokeListener_removeCallback(), and added a keymask to
+       registerKeystrokeListener().
+       * cspi/spi_accessible.c:
+               Changed numerous return types for interfaces from
+       AccessibleComponent to Accessible<InterfaceName>; this was
+       probably a cut-and-paste error.
+       * cspi/spi_event.c:
+               Implementations of new KeystrokeListener api (from spi.h,
+       above).
+       * idl/Registry.idl:
+               Changes to key modifier mapping.
+               Created ControllerEventMask struct.
+               Made DeviceEventController derive from Bonobo::Unknown.
+       * idl/Text.idl:
+               Removed TEXT_BOUNDARY_CURSOR_POS boundary type.
+       * libspi/deviceeventcontroller.c:
+               Added a number of new internal (private) methods.
+       * libspi/editabletext.c:
+       * libspi/editabletext.h:
+               Fixed a number of bugs related to the fact that
+       editabletext inherits from text.  Fixed the EditableText struct,
+       the init() call, and use correct casts when calling Text methods
+       from an EditableText object.  Removed (duplicate) atko from the
+       EditableText structure, we use the one in the parent Text
+       structure via the casts mentioned above.
+       * libspi/keystrokelistener.[ch]:
+       * libspi/registry.c:
+               Changes in support of keyboard handling (above).
+       
+       Keyboard handling, though partly functional, is still not
+       recommended for at-spi client use as there is considerable 
+       work yet to be done.
+
+       * libspi/text.c:
+               Changed some places where pointers to various int types
+       are cast to be pointers to CORBA_long types and vice-versa:
+       pointer casting is not safe so we pass pointers of the correct
+       types and then cast the result before putting it into the target
+       pointers.
+
+       * libspi/text.h: minor typos corrected.
+       * test/simple-at.c: 
+               We now speak not only the name of a Text element, but the
+       first sentence of its content, when it receives focus.
+               I also changed the text compression to 75% from 50%.
+       * util/Accessibility_Util.server.in:
+               Changed the default magnifier type to be a 3x vertical
+       splitscreen magnifier (was previously a 2x horizontal one).
+
+<2001-10-03  Bill Haneman <bill.haneman@sun.com>
+
+       * libspi/keystrokelistener.h:
+       * libspi/keystrokelistener.c:
+               Initial functional implementations of KeystrokeListener.
+       * idl/Registry.idl:
+       
 <2001-10-05  Marc Mulcahy <marc.mulcahy@sun.com>
-       Fixed string handling for NULL strings in libspi.
+
+       Fixed string handling for NULL strings in libspi.
        Added spi_freeString to free strings returned by C bindings.
 
-       <2001-09-30  Bill Haneman <bill.haneman@sun.com>
+<2001-09-30  Bill Haneman <bill.haneman@sun.com>
 
        * libspi/keystrokelistener.h:
        * libspi/keystrokelistener.c:
index c1a14e0..09bd8b4 100644 (file)
@@ -83,7 +83,7 @@ dnl             to make this work with the tarballs.
 AM_CONDITIONAL(ENABLE_GTK_DOC, test x$enable_gtk_doc = xyes)
 
 dnl Checks for libraries
-PKG_CHECK_MODULES(LIBSPI, bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 ORBit-2.0 >= 2.3.94 atk >= 0.2)
+PKG_CHECK_MODULES(LIBSPI, bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 ORBit-2.0 >= 2.3.94 atk >= 0.2 gtk+-2.0 >= 1.3.2)
 AC_SUBST(LIBSPI_LIBS)
 AC_SUBST(LIBSPI_CFLAGS)
 
index c7bb192..2abf4d2 100644 (file)
@@ -38,4 +38,6 @@ SPICSOURCES =        spi_main.c               \
                     spi_text.c\
                     spi_value.c
 
-spi.c : $(SPICSOURCES)
+EXTRA_DIST = $(SPICSOURCES)
+
+spi.c : $(SPICSOURCES) ../libspi/keymasks.h
index c03851f..616d74e 100644 (file)
@@ -6,6 +6,7 @@
 extern "C" {
 #endif /* __cplusplus */
 
+#include "keystrokelistener.h"
 #include "accessibleeventlistener.h"
 
 /*
@@ -24,15 +25,11 @@ typedef Accessibility_Event AccessibleEvent;
  * usage: signatures should be
  * void (*AccessibleEventListenerCB) (AccessibleEvent *event);
  *
- * void (*KeystrokeListenerCB) (KeystrokeEvent *Event);
+ * boolean (*KeystrokeListenerCB) (KeystrokeEvent *Event);
  */
 
 typedef VoidEventListenerCB AccessibleEventListenerCB;
-typedef VoidEventListenerCB KeystrokeListenerCB;
-
-typedef struct _KeystrokeListener {
-   KeystrokeListenerCB callback;
-} KeystrokeListener;
+typedef BooleanKeystrokeListenerCB KeystrokeListenerCB;
 
 #ifdef __cplusplus
 }
index 4570e49..bb63dc1 100644 (file)
@@ -57,6 +57,18 @@ typedef enum _AccessibleCoordType {
   COORD_TYPE_WINDOW
 } AccessibleCoordType;
 
+typedef enum _KeyEventType {
+  KEY_PRESSED,
+  KEY_RELEASED
+} KeyEventType;
+
+typedef struct _KeyStroke
+{
+       long keyID;
+       KeyEventType type;
+       unsigned short modifiers;
+} KeyStroke;
+
 
 /*
  *
@@ -169,6 +181,46 @@ boolean
 EventListener_removeCallback (AccessibleEventListener *listener,
                               AccessibleEventListenerCB callback);
 
+/**
+ * createKeyListener:
+ * @callback : an #KeystrokeListenerCB callback function, or NULL.
+ *
+ * Create a new #KeystrokeListener with a specified callback function.
+ *
+ * Returns: a pointer to a newly-created #KeystrokeListener.
+ *
+ **/
+KeystrokeListener *
+createKeystrokeListener (KeystrokeListenerCB callback);
+
+/**
+ * KeystrokeListener_addCallback:
+ * @listener: the #KeystrokeListener instance to modify.
+ * @callback: an #KeystrokeListenerCB function pointer.
+ *
+ * Add an in-process callback function to an existing #KeystrokeListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+boolean
+KeystrokeListener_addCallback (KeystrokeListener *listener,
+                              KeystrokeListenerCB callback);
+
+/**
+ * KeystrokeListener_removeCallback:
+ * @listener: the #KeystrokeListener instance to modify.
+ * @callback: an #KeystrokeListenerCB function pointer.
+ *
+ * Remove an in-process callback function from an existing #KeystrokeListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+boolean
+KeystrokeListener_removeCallback (KeystrokeListener *listener,
+                                 KeystrokeListenerCB callback);
+
 /*
  *
  * Global functions serviced by the registry
@@ -253,7 +305,7 @@ getDesktopList (Accessible **list);
  *
  **/
 void
-registerKeystrokeListener (KeystrokeListener *listener);
+registerKeystrokeListener (KeystrokeListener *listener, KeyMaskType keymask);
 
 /**
  * generateKeyEvent:
index 6099f44..6707224 100644 (file)
@@ -484,7 +484,7 @@ Accessible_getHypertext (Accessible *obj)
 AccessibleImage *
 Accessible_getImage (Accessible *obj)
 {
-  AccessibleComponent iface =
+  AccessibleImage iface =
     Accessibility_Accessible_queryInterface (*obj,
                                              "IDL:Accessibility/Image:1.0",
                                              &ev);
@@ -496,7 +496,7 @@ Accessible_getImage (Accessible *obj)
 AccessibleSelection *
 Accessible_getSelection (Accessible *obj)
 {
-  AccessibleComponent iface =
+  AccessibleSelection iface =
     Accessibility_Accessible_queryInterface (*obj,
                                              "IDL:Accessibility/Selection:1.0",
                                              &ev);
@@ -508,7 +508,7 @@ Accessible_getSelection (Accessible *obj)
 AccessibleTable *
 Accessible_getTable (Accessible *obj)
 {
-  AccessibleComponent iface =
+  AccessibleTable iface =
     Accessibility_Accessible_queryInterface (*obj,
                                              "IDL:Accessibility/Table:1.0",
                                              &ev);
@@ -520,7 +520,7 @@ Accessible_getTable (Accessible *obj)
 AccessibleText *
 Accessible_getText (Accessible *obj)
 {
-  AccessibleComponent iface =
+  AccessibleText iface =
     Accessibility_Accessible_queryInterface (*obj,
                                              "IDL:Accessibility/Text:1.0",
                                              &ev);
index f109cc6..60081ac 100644 (file)
@@ -54,3 +54,59 @@ EventListener_removeCallback (AccessibleEventListener *listener,
   accessible_event_listener_remove_callback (listener, callback);
   return TRUE;
 }
+
+/**
+ * createKeystrokeListener:
+ * @callback : an #KeystrokeListenerCB callback function, or NULL.
+ *
+ * Create a new #KeystrokeListener with a specified callback function.
+ *
+ * Returns: a pointer to a newly-created #KeystrokeListener.
+ *
+ **/
+KeystrokeListener *
+createKeystrokeListener (KeystrokeListenerCB callback)
+{
+  KeystrokeListener *listener = g_object_new (KEYSTROKE_LISTENER_TYPE, NULL);
+  if (callback)
+    {
+      keystroke_listener_add_callback (listener, callback);
+    }
+  return listener;
+}
+
+/**
+ * KeystrokeListener_addCallback:
+ * @listener: the #KeystrokeListener instance to modify.
+ * @callback: an #KeystrokeListenerCB function pointer.
+ *
+ * Add an in-process callback function to an existing #KeystrokeListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+boolean
+KeystrokeListener_addCallback (KeystrokeListener *listener,
+                           KeystrokeListenerCB callback)
+{
+  keystroke_listener_add_callback (listener, callback);
+  return TRUE;
+}
+
+/**
+ * KeystrokeListener_removeCallback:
+ * @listener: the #KeystrokeListener instance to modify.
+ * @callback: an #KeystrokeListenerCB function pointer.
+ *
+ * Remove an in-process callback function from an existing KeystrokeListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+boolean
+KeystrokeListener_removeCallback (KeystrokeListener *listener,
+                                 KeystrokeListenerCB callback)
+{
+  keystroke_listener_remove_callback (listener, callback);
+  return TRUE;
+}
index 784d642..37b4b45 100644 (file)
@@ -110,9 +110,27 @@ getDesktopList (Accessible **list)
  *
  **/
 void
-registerKeystrokeListener (KeystrokeListener *listener)
+registerKeystrokeListener (KeystrokeListener *listener, KeyMaskType keymask)
 {
-  ;
+  Accessibility_ControllerEventMask *controller_event_mask =
+         Accessibility_ControllerEventMask__alloc();
+  Accessibility_DeviceEventController device_event_controller = 
+         Accessibility_Registry_getDeviceEventController (registry, &ev);
+  Accessibility_DeviceEventController_ref (device_event_controller, &ev);
+  controller_event_mask->value = (CORBA_unsigned_long) keymask;
+  controller_event_mask->refcount = (CORBA_unsigned_short) 1;
+  /*
+  fprintf (stderr, "controller %p, mask value %lu\n", (void *) device_event_controller,
+          (unsigned long) controller_event_mask->value );
+  */
+  Accessibility_DeviceEventController_generateKeyEvent (device_event_controller,
+                                                       (CORBA_long) 32, &ev);
+  Accessibility_DeviceEventController_registerKeystrokeListener (
+         device_event_controller,
+         (Accessibility_KeystrokeListener)
+             bonobo_object_corba_objref (bonobo_object (listener)),
+         controller_event_mask,
+         &ev);
 }
 
 /**
index 000a201..6c672e9 100644 (file)
@@ -94,11 +94,21 @@ AccessibleText_getTextAtOffset (AccessibleText *obj,
                                     TEXT_BOUNDARY_TYPE type,
                                    long *startOffset, long *endOffset)
 {
-  return (char *)
-    Accessibility_Text_getTextAtOffset (*obj,
-                                       (CORBA_long) offset, (Accessibility_TEXT_BOUNDARY_TYPE) type,
-                                       (CORBA_long *) startOffset, (CORBA_long *) endOffset,
-                                       &ev);
+  CORBA_long corbaStartOffset;
+  CORBA_long corbaEndOffset;
+  char *retval = "";
+  retval = Accessibility_Text_getTextAtOffset (*obj,
+                                              (CORBA_long) offset,
+                                              (Accessibility_TEXT_BOUNDARY_TYPE) type,
+                                              &corbaStartOffset,
+                                              &corbaEndOffset,
+                                              &ev);
+  *startOffset = (long) corbaStartOffset;
+  *endOffset = (long) corbaEndOffset;
+#ifdef SPI_DEBUG
+  fprintf (stderr, "text offsets %ld to %ld\n", *startOffset, *endOffset);
+#endif
+  return retval;
 }
 
 
index e6b54d8..3308029 100644 (file)
@@ -158,38 +158,45 @@ module Accessibility {
   };
 
   enum ModifierType {
+    MODIFIER_SHIFT,
     MODIFIER_ALT,
-    MODIFIER_META,
     MODIFIER_CONTROL,
-    MODIFIER_SHIFT,
+    MODIFIER_META,
     MODIFIER_META2,
-    MODIFIER_META3
+    MODIFIER_META3,
+    MODIFIER_SHIFTLOCK,
+    MODIFIER_NUMLOCK
   };
 
-  typedef sequence<ModifierType> ModifierSeq;
+  struct ControllerEventMask {
+    unsigned long value;
+    unsigned short refcount;
+  };
 
   struct KeyStroke {
     long keyID;
     KeyEventType type; 
-    ModifierSeq modifiers;
+    unsigned short modifiers;
   };
 
   interface KeystrokeListener {
         boolean keyEvent (in KeyStroke key);
   };
 
-  interface DeviceEventController {
+  interface DeviceEventController : Bonobo::Unknown {
 
        /**
          * registerKeystrokeListener:
          * @listener: a @KeystrokeListener which will intercept key events.
+         * @mask:     a @ControllerEventMask filtering the intercepted key events.
         * Returns: void
          *
          * Register to intercept keyboard events, and either pass them on or
          * consume them. 
          *
         **/
-        void registerKeystrokeListener (in KeystrokeListener listener);
+        void registerKeystrokeListener (in KeystrokeListener listener, 
+                                       in ControllerEventMask mask);
     
         /**
          * generateKeyEvent:
index 1fdcae5..5d1c442 100644 (file)
@@ -24,7 +24,6 @@ module Accessibility {
 
   enum TEXT_BOUNDARY_TYPE {
     TEXT_BOUNDARY_CHAR,
-    TEXT_BOUNDARY_CURSOR_POS,
     TEXT_BOUNDARY_WORD_START,
     TEXT_BOUNDARY_WORD_END,
     TEXT_BOUNDARY_SENTENCE_START,
index e4c4a8b..d6a0982 100644 (file)
@@ -1,12 +1,22 @@
 idldir = $(datadir)/idl
 
-idl_DATA = Accessible.idl   \
+idl_DATA = Accessibility.idl\
+          Accessible.idl   \
+          Action.idl       \
+          Application.idl  \
+          Component.idl    \
            Desktop.idl      \
-           Relation.idl     \
-           State.idl        \
-           Application.idl  \
+          EditableText.idl \
            Event.idl        \
-           Registry.idl     \
-           Role.idl
+          Hyperlink.idl    \
+          Image.idl        \
+          Registry.idl     \
+          Relation.idl     \
+          Role.idl         \
+           State.idl        \
+          StreamableContent.idl \
+          Table.idl    \
+          Text.idl     \
+          Value.idl
 
 EXTRA_DIST=$(idl_DATA)
index e6b54d8..3308029 100644 (file)
@@ -158,38 +158,45 @@ module Accessibility {
   };
 
   enum ModifierType {
+    MODIFIER_SHIFT,
     MODIFIER_ALT,
-    MODIFIER_META,
     MODIFIER_CONTROL,
-    MODIFIER_SHIFT,
+    MODIFIER_META,
     MODIFIER_META2,
-    MODIFIER_META3
+    MODIFIER_META3,
+    MODIFIER_SHIFTLOCK,
+    MODIFIER_NUMLOCK
   };
 
-  typedef sequence<ModifierType> ModifierSeq;
+  struct ControllerEventMask {
+    unsigned long value;
+    unsigned short refcount;
+  };
 
   struct KeyStroke {
     long keyID;
     KeyEventType type; 
-    ModifierSeq modifiers;
+    unsigned short modifiers;
   };
 
   interface KeystrokeListener {
         boolean keyEvent (in KeyStroke key);
   };
 
-  interface DeviceEventController {
+  interface DeviceEventController : Bonobo::Unknown {
 
        /**
          * registerKeystrokeListener:
          * @listener: a @KeystrokeListener which will intercept key events.
+         * @mask:     a @ControllerEventMask filtering the intercepted key events.
         * Returns: void
          *
          * Register to intercept keyboard events, and either pass them on or
          * consume them. 
          *
         **/
-        void registerKeystrokeListener (in KeystrokeListener listener);
+        void registerKeystrokeListener (in KeystrokeListener listener, 
+                                       in ControllerEventMask mask);
     
         /**
          * generateKeyEvent:
index 1fdcae5..5d1c442 100644 (file)
@@ -24,7 +24,6 @@ module Accessibility {
 
   enum TEXT_BOUNDARY_TYPE {
     TEXT_BOUNDARY_CHAR,
-    TEXT_BOUNDARY_CURSOR_POS,
     TEXT_BOUNDARY_WORD_START,
     TEXT_BOUNDARY_WORD_END,
     TEXT_BOUNDARY_SENTENCE_START,
index ea022d1..1031b69 100644 (file)
@@ -32,6 +32,7 @@ libspiinclude_HEADERS = accessible.h       \
                        accessibleeventlistener.h       \
                        deviceeventcontroller.h \
                         registry.h         \
+                       keymasks.h      \
                         Accessibility.h
 
 IDL_OUT = Accessibility.h Accessibility-stubs.c Accessibility-skels.c Accessibility-common.c
@@ -86,6 +87,7 @@ libspi_la_SOURCES = accessible.c         \
                    accessibleeventlistener.h   \
                     registry.c           \
                     registry.h           \
+                   keymasks.h          \
                     $(IDL_OUT)
 
 IDLFLAGS = -I$(BONOBO_ACTIVATION_IDL_DIR) \
index 33adf5d..76b5666 100644 (file)
 #include <stdio.h>
 #endif
 
+#include <X11/Xlib.h>
 #include <config.h>
+#include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
+#include <gdk/gdkwindow.h>
 #include <bonobo/Bonobo.h>
 #include <libspi/Accessibility.h>
 
  */
 static GObjectClass *device_event_controller_parent_class;
 
+static gboolean kbd_registered = FALSE;
+
+typedef enum {
+  DEVICE_TYPE_KBD,
+  DEVICE_TYPE_MOUSE,
+  DEVICE_TYPE_LAST_DEFINED
+} DeviceTypeCategory;
+
+static gboolean _controller_register_with_devices (DeviceEventController *controller);
+static gboolean _controller_grab_keyboard (DeviceEventController *controller);
+
+static void _controller_register_device_listener (DeviceEventController *controller,
+                                                 const CORBA_Object l,
+                                                 const Accessibility_ControllerEventMask *mask,
+                                                 DeviceTypeCategory type,
+                                                 CORBA_Environment *ev);
+
+/*
+ * Private methods
+ */
+
+static gint
+_compare_corba_objects (gconstpointer p1, gconstpointer p2)
+{
+  CORBA_Environment ev;
+  gint retval;
+  retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
+
+#ifdef SPI_DEBUG
+  fprintf (stderr, "comparing %p to %p; result %d\n",
+          p1, p2,
+          retval);
+#endif
+  return retval;  
+}
+
+static gint
+_eventmask_compare_value (gconstpointer p1, gconstpointer p2)
+{
+    if (!p1 || !p2)
+       return (gint) (p1?1:(p2?-1:0));
+    else
+       return ((long)((Accessibility_ControllerEventMask*)p2)->value) -
+               ((long)((Accessibility_ControllerEventMask*)p1)->value);
+}
+
+static void
+_controller_register_device_listener (DeviceEventController *controller,
+                                     const CORBA_Object l,
+                                     const Accessibility_ControllerEventMask *mask,
+                                     DeviceTypeCategory type,
+                                     CORBA_Environment *ev)
+{
+  Accessibility_ControllerEventMask *mask_ptr;
+  
+  switch (type) {
+  case DEVICE_TYPE_KBD:
+      controller->key_listeners = g_list_append (controller->key_listeners,
+                                                CORBA_Object_duplicate (l, ev));
+      
+      mask_ptr = (Accessibility_ControllerEventMask *)
+             g_list_find_custom (controller->keymask_list, (gpointer) mask,
+                                 _eventmask_compare_value);
+      if (mask_ptr)
+             ++(mask_ptr->refcount);
+      else
+      {
+             if (mask->refcount != (CORBA_unsigned_short) 1)
+                     fprintf (stderr, "mask initial refcount is not 1!\n");
+             if (mask->value > (CORBA_unsigned_long) 2048)
+                     fprintf (stderr, "mask value looks invalid (%lu)\n",
+                              (unsigned long) mask->value);
+             else
+                     fprintf (stderr, "appending mask with val=%lu\n",
+                              (unsigned long) mask->value);
+             mask_ptr = Accessibility_ControllerEventMask__alloc();
+             mask_ptr->value = mask->value;
+             mask_ptr->refcount = (CORBA_unsigned_short) 1;
+             controller->keymask_list = g_list_append (controller->keymask_list,
+                                                       (gpointer) mask_ptr);
+      }
+      break;
+  case DEVICE_TYPE_MOUSE:
+/*    controller->mouse_listeners = g_list_append (controller->mouse_listeners,
+                                                   CORBA_Object_duplicate (l, ev));*/
+
+/* possibly this interface should NOT be used for mouse events ? */
+      break;
+  }
+}
+
+static void
+_controller_deregister_device_listener (DeviceEventController *controller,
+                                       const CORBA_Object l,
+                                       const Accessibility_ControllerEventMask *mask,
+                                       DeviceTypeCategory type,
+                                       CORBA_Environment *ev)
+{
+  Accessibility_ControllerEventMask *mask_ptr;
+  GList *list_ptr;
+  switch (type) {
+  case DEVICE_TYPE_KBD:
+      list_ptr = g_list_find_custom (controller->key_listeners, l, _compare_corba_objects);
+      if (list_ptr)
+         controller->key_listeners = g_list_remove (controller->key_listeners, list_ptr);
+      
+      mask_ptr = (Accessibility_ControllerEventMask *)
+                 g_list_find_custom (controller->keymask_list, (gpointer) mask,
+                                    _eventmask_compare_value);
+      if (mask_ptr)
+             --mask_ptr->refcount;
+      if (!mask_ptr->refcount)
+      {
+          controller->keymask_list = g_list_remove (controller->keymask_list, mask_ptr);
+          ;  /* release any key grabs that are in place for this key mask */
+      }
+      break;
+  case DEVICE_TYPE_MOUSE:
+/*    controller->mouse_listeners = g_list_append (controller->mouse_listeners,
+                                                   CORBA_Object_duplicate (l, ev));*/
+
+/* possibly this interface should NOT be used for mouse events ? */
+      break;
+  }
+}
+
+static gboolean
+_controller_register_with_devices (DeviceEventController *controller)
+{
+  gboolean retval = FALSE;
+  Display *default_display;
+  Window root_window;
+
+  default_display = GDK_DISPLAY();
+  root_window = GDK_ROOT_WINDOW();  
+  /* calls to device-specific implementations and routines go here */
+  /* register with: keyboard hardware code handler */
+  /* register with: (translated) keystroke handler */
+#ifdef SPI_DEBUG
+  fprintf (stderr, "About to request events on window %ld of display %p\n",
+          (unsigned long) root_window, default_display);
+#endif
+  XSelectInput (default_display,
+               root_window,
+               KeyPressMask);
+  XSelectInput (default_display,
+               root_window,
+               KeyReleaseMask);
+  /* register with: mouse hardware device handler? */
+  /* register with: mouse event handler */
+  return retval;
+}
+
+static gboolean _check_key_event (DeviceEventController *controller)
+{
+#ifdef SPI_DEBUG
+       static Accessibility_ControllerEventMask shiftlock_mask =
+               {(CORBA_unsigned_long) LockMask, (CORBA_unsigned_short) 1};
+#endif
+       static gboolean initialized = FALSE;
+       static gboolean is_active = FALSE;
+       XEvent *x_event = g_new0 (XEvent, 1);
+       XKeyEvent *x_key_event;
+       KeySym keysym;
+       gboolean is_consumed = FALSE;
+       char key_name[16];
+       int i;
+       int n_listeners = g_list_length (controller->key_listeners);
+       Accessibility_KeyStroke key_event;
+       static CORBA_Environment ev;
+       
+       if (!initialized)
+       {
+               initialized = TRUE;
+               CORBA_exception_init (&ev);
+       }
+
+/*        if (!XPending(GDK_DISPLAY())) return TRUE; */
+
+       /*
+        * the call to XPending seemed like a good idea, why did it
+        * wreak such havoc?
+        */
+
+       XPeekEvent (GDK_DISPLAY(), x_event);
+       if (x_event->type == KeyPress)
+       {
+           x_key_event = (XKeyEvent *)x_event;
+           keysym = XLookupKeysym (x_key_event, 0);
+           key_event.keyID = (CORBA_long)(keysym);
+           key_event.type = Accessibility_KEY_PRESSED;
+           key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
+#if defined SPI_KEYEVENT_DEBUG
+           fprintf (stderr,
+                    "Key %lu pressed (%c), modifiers %d\n",
+                    (unsigned long) keysym,
+                    (char) keysym,
+                    (int) x_key_event->state);
+#elif defined SPI_DEBUG
+           fprintf(stderr, "%s%c",
+                   (x_key_event->state & Mod1Mask)?"Alt-":"",
+                   ((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))?
+                   (char) toupper((int) keysym) : (char) tolower((int)keysym));
+#endif /* SPI_DEBUG */
+       }
+       else
+       {
+#ifdef SPI_KEYEVENT_DEBUG
+               fprintf (stderr, "other event, type %d\n", (int) x_event->type);
+#endif
+       }
+       /* relay to listeners, and decide whether to consume it or not */
+       for (i=0; i<n_listeners && !is_consumed; ++i)
+       {
+         Accessibility_KeystrokeListener ls;
+         ls = (Accessibility_KeystrokeListener)
+                       g_list_nth_data (controller->key_listeners, i);
+         if (!CORBA_Object_is_nil(ls, &ev))
+         {
+           is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev);
+         }             
+       }
+       if (is_consumed) XNextEvent (GDK_DISPLAY(), x_event);
+       XAllowEvents (GDK_DISPLAY(), ReplayKeyboard, CurrentTime);
+/*
+ *  I haven't figure out how to make this work correctly yet :-(
+ *
+ *     XGrabKeyboard (GDK_DISPLAY(), GDK_ROOT_WINDOW(), True,
+ *                    GrabModeAsync, GrabModeSync, CurrentTime);
+ *      XAllowEvents (GDK_DISPLAY(), SyncKeyboard, CurrentTime);
+ *
+ *
+ * ControlMask grabs are broken, must be in use already.
+ *
+ */
+       
+/* Always grab ShiftLock in DEBUG mode */
+#ifdef SPI_DEBUG
+       if (!controller->keymask_list)
+           controller->keymask_list =
+               g_list_append (controller->keymask_list, &shiftlock_mask);
+#endif
+       return _controller_grab_keyboard (controller);
+}
+
+static gboolean
+_controller_grab_keyboard (DeviceEventController *controller)
+{
+       Display *display = GDK_DISPLAY();
+       Window root_window = GDK_ROOT_WINDOW();
+       GList *maskList = controller->keymask_list;
+       int i;
+       int last_mask = g_list_length (maskList);
+
+/*
+ * masks known to work with default RH 7.1: 
+ * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
+ * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
+ * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
+ * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
+ *
+ * ControlMask grabs are broken, must be in use already
+ */
+       
+       for (i=0; i < last_mask; ++i)
+       {
+               Accessibility_ControllerEventMask *mask
+                       = (Accessibility_ControllerEventMask *)g_list_nth_data (maskList, i);
+               unsigned long maskVal = 0xFFFFFFFF;
+               if (mask) maskVal = (unsigned long) mask->value;
+#ifdef SPI_KEYEVENT_DEBUG
+               fprintf (stderr, "mask=%lx\n", maskVal);
+#endif
+               if (!(maskVal & ControlMask))
+               {
+#ifdef SPI_KEYEVENT_DEBUG
+                       fprintf (stderr, "grabbing for mod %lu\n", (unsigned long) maskVal);
+#endif
+                       XGrabKey (display,
+                                 AnyKey,
+                                 maskVal,
+                                 root_window,
+                                 True,
+                                 GrabModeAsync,
+                                 GrabModeSync);
+                       /* TODO: check call for errors and return FALSE if error occurs */
+               } else {
+                       return FALSE; /* can't do control key yet */
+               }
+       }
+       return TRUE;
+}
+
 /*
  * Implemented GObject::finalize
  */
@@ -68,12 +364,18 @@ device_event_controller_object_finalize (GObject *object)
 static void
 impl_register_keystroke_listener (PortableServer_Servant     servant,
                                  const Accessibility_KeystrokeListener l,
+                                 const Accessibility_ControllerEventMask *mask,
                                  CORBA_Environment         *ev)
 {
+       DeviceEventController *controller = DEVICE_EVENT_CONTROLLER (
+               bonobo_object_from_servant (servant));
 #ifdef SPI_DEBUG
-       fprintf (stderr, "registering keystroke listener %p\n", l);
+       fprintf (stderr, "registering keystroke listener %p with maskVal %lu\n",
+                (void *) l, (unsigned long) mask->value);
 #endif
+       _controller_register_device_listener(controller, l, mask, DEVICE_TYPE_KBD, ev);
 }
+
 /*
  * CORBA Accessibility::DeviceEventController::registerMouseListener
  *     method implementation
@@ -84,9 +386,12 @@ impl_register_mouse_listener (PortableServer_Servant     servant,
                              const Accessibility_MouseListener *l,
                              CORBA_Environment         *ev)
 {
+       DeviceEventController *controller = DEVICE_EVENT_CONTROLLER (
+               bonobo_object_from_servant (servant));
 #ifdef SPI_DEBUG
        fprintf (stderr, "registering mouse listener %p\n", l);
 #endif
+       _controller_register_device_listener(controller, l, mask, DEVICE_TYPE_MOUSE, ev);
 }
 */
 
@@ -100,7 +405,7 @@ impl_generate_key_event (PortableServer_Servant     servant,
                         CORBA_Environment         *ev)
 {
 #ifdef SPI_DEBUG
-       fprintf (stderr, "synthesizing keystroke %ld\n", keyEventID);
+       fprintf (stderr, "synthesizing keystroke %ld\n", (long) keyEventID);
 #endif
 }
 
@@ -133,11 +438,23 @@ device_event_controller_class_init (DeviceEventControllerClass *klass)
 /*        epv->registerMouseListener = impl_register_mouse_listener; */
         epv->generateKeyEvent = impl_generate_key_event;
         epv->generateMouseEvent = impl_generate_mouse_event;
+       klass->check_key_event = _check_key_event;
 }
 
 static void
 device_event_controller_init (DeviceEventController *device_event_controller)
 {
+  device_event_controller->key_listeners = NULL;
+  device_event_controller->key_listeners = NULL;
+  device_event_controller->keymask_list = NULL;
+  kbd_registered = _controller_register_with_devices (device_event_controller);
+}
+
+gboolean device_event_controller_check_key_event (DeviceEventController *controller)
+{
+       DeviceEventControllerClass *klass = DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
+       if (klass->check_key_event)
+               return (klass->check_key_event) (controller);
 }
 
 GType
index 60255da..dd195db 100644 (file)
@@ -29,20 +29,26 @@ extern "C" {
 
 #include <bonobo/bonobo-object.h>
 #include <libspi/Accessibility.h>
+#include "keystrokelistener.h"
 
 #define DEVICE_EVENT_CONTROLLER_TYPE        (device_event_controller_get_type ())
 #define DEVICE_EVENT_CONTROLLER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventController))
 #define DEVICE_EVENT_CONTROLLER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventControllerClass))
-#define IS_DEVICE_EVENT_CONTROLLER(o)       (G_TYPE_CHECK__INSTANCE_TYPE ((o), DEVICE_EVENT_CONTROLLER_TYPE))
+#define IS_DEVICE_EVENT_CONTROLLER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVICE_EVENT_CONTROLLER_TYPE))
 #define IS_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVICE_EVENT_CONTROLLER_TYPE))
+#define DEVICE_EVENT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventControllerClass))
 
 typedef struct {
         BonoboObject parent;
+        GList *key_listeners;
+        GList *mouse_listeners;
+       GList *keymask_list;
 } DeviceEventController;
 
 typedef struct {
         BonoboObjectClass parent_class;
         POA_Accessibility_DeviceEventController__epv epv;
+       gboolean (*check_key_event) (DeviceEventController *controller);
 } DeviceEventControllerClass;
 
 GType               device_event_controller_get_type   (void);
index 89a7b85..4c14c20 100644 (file)
@@ -108,7 +108,7 @@ editable_text_get_type (void)
      * use bonobo_type_unique.
      */
     type = bonobo_type_unique (
-                              BONOBO_OBJECT_TYPE,
+                              TEXT_TYPE,
                               POA_Accessibility_EditableText__init,
                               NULL,
                               G_STRUCT_OFFSET (EditableTextClass, epv),
@@ -149,8 +149,9 @@ static void
 editable_text_finalize (GObject *obj)
 {
   EditableText *editable = EDITABLE_TEXT(obj);
-  g_object_unref (editable->atko);
-  editable->atko = NULL;
+  Text *text = TEXT(obj);
+  g_object_unref (text->atko);
+  text->atko = NULL;
   parent_class->finalize (obj);
 }
 
@@ -159,7 +160,7 @@ editable_text_interface_new (AtkObject *obj)
 {
   EditableText *new_editable =
     EDITABLE_TEXT(g_object_new (EDITABLE_TEXT_TYPE, NULL));
-  new_editable->atko = obj;
+  TEXT (new_editable)->atko = obj;
   g_object_ref (obj);
 return new_editable;
 }
@@ -184,7 +185,7 @@ impl_setTextContents (PortableServer_Servant _servant,
                      CORBA_Environment * ev)
 {
   EditableText *editable = EDITABLE_TEXT(bonobo_object_from_servant (_servant));
-  atk_editable_text_set_text_contents (ATK_EDITABLE_TEXT(editable->atko),
+  atk_editable_text_set_text_contents (ATK_EDITABLE_TEXT( TEXT (editable)->atko),
                                       (gchar *) newContents);
 }
 
@@ -198,7 +199,7 @@ impl_insertText (PortableServer_Servant _servant,
                 CORBA_Environment * ev)
 {
   EditableText *editable = EDITABLE_TEXT (bonobo_object_from_servant(_servant));
-  atk_editable_text_insert_text (ATK_EDITABLE_TEXT(editable->atko),
+  atk_editable_text_insert_text (ATK_EDITABLE_TEXT( TEXT (editable)->atko),
                                 (gchar *) text,
                                 (gint) length,
                                 (gint *) &position);
@@ -211,7 +212,7 @@ impl_copyText (PortableServer_Servant _servant,
               CORBA_Environment * ev)
 {
   EditableText *editable = EDITABLE_TEXT (bonobo_object_from_servant(_servant));
-  atk_editable_text_copy_text (ATK_EDITABLE_TEXT(editable->atko),
+  atk_editable_text_copy_text (ATK_EDITABLE_TEXT( TEXT(editable)->atko),
                               (gint) startPos, (gint) endPos);
 }
 
@@ -223,7 +224,7 @@ impl_cutText (PortableServer_Servant _servant,
              CORBA_Environment * ev)
 {
   EditableText *editable = EDITABLE_TEXT (bonobo_object_from_servant(_servant));
-  atk_editable_text_cut_text (ATK_EDITABLE_TEXT(editable->atko),
+  atk_editable_text_cut_text (ATK_EDITABLE_TEXT(TEXT (editable)->atko),
                                 (gint) startPos, (gint) endPos);
 }
 
@@ -236,7 +237,7 @@ impl_deleteText (PortableServer_Servant _servant,
                 CORBA_Environment * ev)
 {
   EditableText *editable = EDITABLE_TEXT (bonobo_object_from_servant(_servant));
-  atk_editable_text_delete_text (ATK_EDITABLE_TEXT(editable->atko),
+  atk_editable_text_delete_text (ATK_EDITABLE_TEXT( TEXT(editable)->atko),
                                 (gint) startPos, (gint) endPos);
 }
 
@@ -246,6 +247,6 @@ impl_pasteText (PortableServer_Servant _servant,
                const CORBA_long position, CORBA_Environment * ev)
 {
   EditableText *editable = EDITABLE_TEXT (bonobo_object_from_servant(_servant));
-  atk_editable_text_paste_text (ATK_EDITABLE_TEXT(editable->atko), position);
+  atk_editable_text_paste_text (ATK_EDITABLE_TEXT( TEXT(editable)->atko), position);
 }
 
index 5db4c19..9d4fc6e 100644 (file)
@@ -28,6 +28,7 @@ extern "C" {
 #include <bonobo/bonobo-object.h>
 #include <atk/atk.h>
 #include <libspi/Accessibility.h>
+#include "text.h"
 
 #define EDITABLE_TEXT_TYPE        (editable_text_get_type ())
 #define EDITABLE_TEXT(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), EDITABLE_TEXT_TYPE, EditableText))
@@ -39,12 +40,11 @@ typedef struct _EditableText EditableText;
 typedef struct _EditableTextClass EditableTextClass;
 
 struct _EditableText {
-  BonoboObject parent;
-  AtkObject *atko;
+  Text parent;
 };
 
 struct _EditableTextClass {
-  BonoboObjectClass parent_class;
+  TextClass parent_class;
   POA_Accessibility_EditableText__epv epv;
 };
 
index 61f883c..68736c9 100644 (file)
@@ -62,11 +62,27 @@ keystroke_listener_object_finalize (GObject *object)
         keystroke_listener_parent_class->finalize (object);
 }
 
+void   keystroke_listener_add_callback (KeystrokeListener *listener,
+                                       BooleanKeystrokeListenerCB callback)
+{
+  listener->callbacks = g_list_append (listener->callbacks, callback);
+#ifdef SPI_DEBUG
+        fprintf(stderr, "keystroke_listener_add_callback (%p) called\n",
+               (gpointer) callback);
+#endif
+}
+
+void   keystroke_listener_remove_callback (KeystrokeListener *listener,
+                                          BooleanKeystrokeListenerCB callback)
+{
+  listener->callbacks = g_list_remove (listener->callbacks, callback);
+}
+
 /*
  * CORBA Accessibility::KeystrokeListener::keyEvent method implementation
  */
 
-static void
+static CORBA_boolean
 impl_key_event (PortableServer_Servant     servant,
                const Accessibility_KeyStroke *key,
                CORBA_Environment         *ev)
@@ -78,6 +94,12 @@ impl_key_event (PortableServer_Servant     servant,
             CORBA_exception_id(ev));
     exit(-1);
   }
+  else {
+    fprintf(stderr, "%s%c",
+           (key->modifiers & KEYMASK_ALT)?"Alt-":"",
+           ((key->modifiers & KEYMASK_SHIFT)^(key->modifiers & KEYMASK_SHIFTLOCK))?
+           (char) toupper((int) key->keyID) : (char) tolower((int) key->keyID));
+  }
 #endif
 }
 
@@ -96,6 +118,7 @@ keystroke_listener_class_init (KeystrokeListenerClass *klass)
 static void
 keystroke_listener_init (KeystrokeListener *keystroke_listener)
 {
+       keystroke_listener->callbacks = NULL;
 }
 
 GType
index 93a15a6..7daca15 100644 (file)
@@ -30,15 +30,19 @@ extern "C" {
 #include <bonobo/bonobo-object.h>
 #include <atk/atkobject.h>
 #include <libspi/Accessibility.h>
+#include "keymasks.h"
 
 #define KEYSTROKE_LISTENER_TYPE        (keystroke_listener_get_type ())
 #define KEYSTROKE_LISTENER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), KEYSTROKE_LISTENER_TYPE, KeystrokeListener))
 #define KEYSTROKE_LISTENER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), KEYSTROKE_LISTENER_TYPE, KeystrokeListenerClass))
-#define IS_KEYSTROKE_LISTENER(o)       (G_TYPE_CHECK__INSTANCE_TYPE ((o), KEYSTROKE_LISTENER_TYPE))
+#define IS_KEYSTROKE_LISTENER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), KEYSTROKE_LISTENER_TYPE))
 #define IS_KEYSTROKE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), KEYSTROKE_LISTENER_TYPE))
 
+typedef gboolean (*BooleanKeystrokeListenerCB) (void *keystroke_ptr);
+
 typedef struct {
         BonoboObject parent;
+       GList *callbacks;
 } KeystrokeListener;
 
 typedef struct {
@@ -48,6 +52,11 @@ typedef struct {
 
 GType               keystroke_listener_get_type   (void);
 KeystrokeListener  *keystroke_listener_new       (void);
+void   keystroke_listener_add_callback (KeystrokeListener *listener,
+                                        BooleanKeystrokeListenerCB callback);
+void   keystroke_listener_remove_callback (KeystrokeListener *listener,
+                                           BooleanKeystrokeListenerCB callback);
+
 
 #ifdef __cplusplus
 }
index 0f39ed7..208cab5 100644 (file)
 #include <libspi/Accessibility.h>
 
 /*
+ * We'd like to replace the dependance on X-isms with a wrapper layer,
+ * to the extent that it can't be done with pure GDK.
+ * Anyone want to help?
+ */
+#include <X11/Xlib.h>
+#include <gdk/gdkx.h>
+
+/*
  * This pulls the definition for the BonoboObject (GType)
  */
 #include "registry.h"
@@ -79,6 +87,8 @@ static void _registry_notify_listeners ( GList *listeners,
 
 static long _get_unique_id();
 
+static gboolean _device_event_controller_hook (gpointer source);
+
 /*
  * Implemented GObject::finalize
  */
@@ -124,7 +134,7 @@ impl_accessibility_registry_register_application (PortableServer_Servant servant
 }
 
 static gint
-compare_object_hash (gconstpointer p1, gconstpointer p2)
+compare_corba_objects (gconstpointer p1, gconstpointer p2)
 {
   CORBA_Environment ev;
   gint retval;
@@ -248,7 +258,7 @@ impl_accessibility_registry_deregister_application (PortableServer_Servant serva
                                                     CORBA_Environment * ev)
 {
   Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
-  GList *list = g_list_find_custom (registry->desktop->applications, application, compare_object_hash);
+  GList *list = g_list_find_custom (registry->desktop->applications, application, compare_corba_objects);
 
 #ifdef SPI_DEBUG
   gint i;
@@ -277,8 +287,8 @@ impl_accessibility_registry_deregister_application (PortableServer_Servant serva
  * CORBA Accessibility::Registry::registerGlobalEventListener method implementation
  */
 static void
-impl_accessibility_registry_register_global_event_listener
-                                            (PortableServer_Servant  servant,
+impl_accessibility_registry_register_global_event_listener (
+                                            PortableServer_Servant  servant,
                                              Accessibility_EventListener listener,
                                              const CORBA_char *event_name,
                                              CORBA_Environment      *ev)
@@ -319,13 +329,13 @@ impl_accessibility_registry_register_global_event_listener
  * CORBA Accessibility::Registry::deregisterGlobalEventListenerAll method implementation
  */
 static void
-impl_accessibility_registry_deregister_global_event_listener_all
-                                                   (PortableServer_Servant  servant,
+impl_accessibility_registry_deregister_global_event_listener_all (
+                                                    PortableServer_Servant  servant,
                                                     Accessibility_EventListener listener,
                                                     CORBA_Environment      *ev)
 {
   Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
-  GList *list = g_list_find_custom (registry->focus_listeners, listener, compare_object_hash);
+  GList *list = g_list_find_custom (registry->focus_listeners, listener, compare_corba_objects);
 
   /*
    * TODO : de-register with toolkit if the last instance of a listener
@@ -336,14 +346,14 @@ impl_accessibility_registry_deregister_global_event_listener_all
     {
       fprintf (stderr, "deregistering listener\n");
       registry->focus_listeners = g_list_delete_link (registry->focus_listeners, list);
-      list = g_list_find_custom (registry->focus_listeners, listener, compare_object_hash);
+      list = g_list_find_custom (registry->focus_listeners, listener, compare_corba_objects);
     }
-  list = g_list_find_custom (registry->toolkit_listeners, listener, compare_object_hash);
+  list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects);
   while (list)
     {
       fprintf (stderr, "deregistering listener\n");
       registry->toolkit_listeners = g_list_delete_link (registry->toolkit_listeners, list);
-      list = g_list_find_custom (registry->toolkit_listeners, listener, compare_object_hash);
+      list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects);
     }
 }
 
@@ -351,8 +361,8 @@ impl_accessibility_registry_deregister_global_event_listener_all
  * CORBA Accessibility::Registry::deregisterGlobalEventListener method implementation
  */
 static void
-impl_accessibility_registry_deregister_global_event_listener
-                                                   (PortableServer_Servant  servant,
+impl_accessibility_registry_deregister_global_event_listener (
+                                                    PortableServer_Servant  servant,
                                                     Accessibility_EventListener listener,
                                                     const CORBA_char * event_name,
                                                     CORBA_Environment      *ev)
@@ -453,12 +463,16 @@ impl_accessibility_registry_get_desktop_list (PortableServer_Servant servant,
   return (Accessibility_DesktopSeq *) NULL;
 }
 
-static CORBA_Object
+static Accessibility_DeviceEventController
 impl_accessibility_registry_get_device_event_controller (PortableServer_Servant servant,
                                                          CORBA_Environment * ev)
 {
-  /* TODO: not yet implemented! */
-  return CORBA_OBJECT_NIL;
+  Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
+  if (!registry->device_event_controller)
+    registry->device_event_controller = g_object_new (DEVICE_EVENT_CONTROLLER_TYPE, NULL);
+  return CORBA_Object_duplicate (
+         bonobo_object_corba_objref (
+                 bonobo_object (registry->device_event_controller)), ev);
 }
 
 static void
@@ -536,6 +550,15 @@ _registry_notify_listeners ( GList *listeners,
     }
 }
 
+static gboolean _device_event_controller_hook (gpointer p)
+{
+    Registry *registry = (Registry *)p;
+    DeviceEventController *controller = registry->device_event_controller;
+    if (controller)
+       device_event_controller_check_key_event (controller);
+    return TRUE;
+}
+
 static void
 registry_class_init (RegistryClass *klass)
 {
@@ -567,6 +590,8 @@ registry_init (Registry *registry)
   registry->toolkit_listeners = NULL;
   registry->applications = NULL;
   registry->desktop = desktop_new();
+  registry->device_event_controller = NULL;
+  registry->kbd_event_hook = _device_event_controller_hook;
 }
 
 GType
index 18fe392..7622fe2 100644 (file)
 extern "C" {
 #endif /* __cplusplus */
 
+#include <glib/gmain.h>
 #include <libspi/Accessibility.h>
 #include "listener.h"
 #include "desktop.h"
+#include "deviceeventcontroller.h"
 
 #define REGISTRY_TYPE        (registry_get_type ())
 #define REGISTRY(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), REGISTRY_TYPE, Registry))
@@ -43,7 +45,9 @@ typedef struct {
   GList *window_listeners;
   GList *toolkit_listeners;
   GList *applications;
+  DeviceEventController *device_event_controller;
   Desktop *desktop;
+  gboolean (*kbd_event_hook) (gpointer source);
 } Registry;
 
 typedef struct {
index afb4a7e..8e87079 100644 (file)
@@ -28,6 +28,7 @@
 #include <bonobo/Bonobo.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 
 /*
  * This pulls the CORBA definitions for the "Accessibility::Accessible" server
@@ -65,8 +66,8 @@ impl_getTextAfterOffset (PortableServer_Servant _servant,
 static CORBA_string
 impl_getTextAtOffset (PortableServer_Servant _servant,
                      const CORBA_long offset,
-                     const Accessibility_TEXT_BOUNDARY_TYPE
-                     type, CORBA_long * startOffset,
+                     const Accessibility_TEXT_BOUNDARY_TYPE type,
+                     CORBA_long * startOffset,
                      CORBA_long * endOffset,
                      CORBA_Environment * ev);
 static CORBA_wchar
@@ -285,18 +286,28 @@ impl_getTextAfterOffset (PortableServer_Servant _servant,
 static CORBA_string
 impl_getTextAtOffset (PortableServer_Servant _servant,
                      const CORBA_long offset,
-                     const Accessibility_TEXT_BOUNDARY_TYPE
-                     type, CORBA_long * startOffset,
+                     const Accessibility_TEXT_BOUNDARY_TYPE type,
+                     CORBA_long * startOffset,
                      CORBA_long * endOffset,
                      CORBA_Environment * ev)
 {
-  Text *text = TEXT (bonobo_object_from_servant (_servant));
-  gchar *txt;
+  Text *text;
+  CORBA_char *txt;
   CORBA_char *rv;
+  gint intStartOffset, intEndOffset;
 
-  txt = atk_text_get_text_at_offset (ATK_TEXT(text->atko),
+  BonoboObject *obj;
+  fprintf (stderr, "getting bonobo-object from text servant\n");
+  obj = (bonobo_object_from_servant (_servant));
+  
+  g_return_val_if_fail (IS_TEXT (bonobo_object_from_servant (_servant)), (CORBA_char *)"");
+                       g_return_val_if_fail (ATK_IS_TEXT (text->atko), (CORBA_char *)"");
+  txt = (CORBA_char *) atk_text_get_text_at_offset (ATK_TEXT (text->atko),
                                    (gint) offset, (AtkTextBoundary) type,
-                                   (gint *) startOffset, (gint *) endOffset);
+                                   &intStartOffset, &intEndOffset);
+  *startOffset = (CORBA_long) intStartOffset;
+  *endOffset = (CORBA_long) intEndOffset;
+
   if (txt)
     {
       rv = CORBA_string_dup (txt);
@@ -304,6 +315,7 @@ impl_getTextAtOffset (PortableServer_Servant _servant,
     }
   else
     rv = CORBA_string_dup ("");
+
   return rv;
 }
 
index e9594b7..53f4817 100644 (file)
@@ -1,4 +1,4 @@
-/* ATK -  Accessibility Toolkit
+/* AT-SPI -  Assistive Technology Service Provider Interface
  * Copyright 2001 Sun Microsystems Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -28,12 +28,13 @@ extern "C" {
 #include <bonobo/bonobo-object.h>
 #include <atk/atk.h>
 #include <libspi/Accessibility.h>
+#include "accessible.h"
 
 #define TEXT_TYPE        (text_get_type ())
 #define TEXT(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEXT_TYPE, Text))
 #define TEXT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), TEXT_TYPE, TextClass))
-#define IS_TEXT(obj)       (G_TYPE_CHECK__INSTANCE_TYPE ((obj), TEXT_TYPE))
-#define IS_TEX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEXT_TYPE))
+#define IS_TEXT(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEXT_TYPE))
+#define IS_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEXT_TYPE))
 
 typedef struct _Text Text;
 typedef struct _TextClass TextClass;
index 33adf5d..76b5666 100644 (file)
 #include <stdio.h>
 #endif
 
+#include <X11/Xlib.h>
 #include <config.h>
+#include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
+#include <gdk/gdkwindow.h>
 #include <bonobo/Bonobo.h>
 #include <libspi/Accessibility.h>
 
  */
 static GObjectClass *device_event_controller_parent_class;
 
+static gboolean kbd_registered = FALSE;
+
+typedef enum {
+  DEVICE_TYPE_KBD,
+  DEVICE_TYPE_MOUSE,
+  DEVICE_TYPE_LAST_DEFINED
+} DeviceTypeCategory;
+
+static gboolean _controller_register_with_devices (DeviceEventController *controller);
+static gboolean _controller_grab_keyboard (DeviceEventController *controller);
+
+static void _controller_register_device_listener (DeviceEventController *controller,
+                                                 const CORBA_Object l,
+                                                 const Accessibility_ControllerEventMask *mask,
+                                                 DeviceTypeCategory type,
+                                                 CORBA_Environment *ev);
+
+/*
+ * Private methods
+ */
+
+static gint
+_compare_corba_objects (gconstpointer p1, gconstpointer p2)
+{
+  CORBA_Environment ev;
+  gint retval;
+  retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
+
+#ifdef SPI_DEBUG
+  fprintf (stderr, "comparing %p to %p; result %d\n",
+          p1, p2,
+          retval);
+#endif
+  return retval;  
+}
+
+static gint
+_eventmask_compare_value (gconstpointer p1, gconstpointer p2)
+{
+    if (!p1 || !p2)
+       return (gint) (p1?1:(p2?-1:0));
+    else
+       return ((long)((Accessibility_ControllerEventMask*)p2)->value) -
+               ((long)((Accessibility_ControllerEventMask*)p1)->value);
+}
+
+static void
+_controller_register_device_listener (DeviceEventController *controller,
+                                     const CORBA_Object l,
+                                     const Accessibility_ControllerEventMask *mask,
+                                     DeviceTypeCategory type,
+                                     CORBA_Environment *ev)
+{
+  Accessibility_ControllerEventMask *mask_ptr;
+  
+  switch (type) {
+  case DEVICE_TYPE_KBD:
+      controller->key_listeners = g_list_append (controller->key_listeners,
+                                                CORBA_Object_duplicate (l, ev));
+      
+      mask_ptr = (Accessibility_ControllerEventMask *)
+             g_list_find_custom (controller->keymask_list, (gpointer) mask,
+                                 _eventmask_compare_value);
+      if (mask_ptr)
+             ++(mask_ptr->refcount);
+      else
+      {
+             if (mask->refcount != (CORBA_unsigned_short) 1)
+                     fprintf (stderr, "mask initial refcount is not 1!\n");
+             if (mask->value > (CORBA_unsigned_long) 2048)
+                     fprintf (stderr, "mask value looks invalid (%lu)\n",
+                              (unsigned long) mask->value);
+             else
+                     fprintf (stderr, "appending mask with val=%lu\n",
+                              (unsigned long) mask->value);
+             mask_ptr = Accessibility_ControllerEventMask__alloc();
+             mask_ptr->value = mask->value;
+             mask_ptr->refcount = (CORBA_unsigned_short) 1;
+             controller->keymask_list = g_list_append (controller->keymask_list,
+                                                       (gpointer) mask_ptr);
+      }
+      break;
+  case DEVICE_TYPE_MOUSE:
+/*    controller->mouse_listeners = g_list_append (controller->mouse_listeners,
+                                                   CORBA_Object_duplicate (l, ev));*/
+
+/* possibly this interface should NOT be used for mouse events ? */
+      break;
+  }
+}
+
+static void
+_controller_deregister_device_listener (DeviceEventController *controller,
+                                       const CORBA_Object l,
+                                       const Accessibility_ControllerEventMask *mask,
+                                       DeviceTypeCategory type,
+                                       CORBA_Environment *ev)
+{
+  Accessibility_ControllerEventMask *mask_ptr;
+  GList *list_ptr;
+  switch (type) {
+  case DEVICE_TYPE_KBD:
+      list_ptr = g_list_find_custom (controller->key_listeners, l, _compare_corba_objects);
+      if (list_ptr)
+         controller->key_listeners = g_list_remove (controller->key_listeners, list_ptr);
+      
+      mask_ptr = (Accessibility_ControllerEventMask *)
+                 g_list_find_custom (controller->keymask_list, (gpointer) mask,
+                                    _eventmask_compare_value);
+      if (mask_ptr)
+             --mask_ptr->refcount;
+      if (!mask_ptr->refcount)
+      {
+          controller->keymask_list = g_list_remove (controller->keymask_list, mask_ptr);
+          ;  /* release any key grabs that are in place for this key mask */
+      }
+      break;
+  case DEVICE_TYPE_MOUSE:
+/*    controller->mouse_listeners = g_list_append (controller->mouse_listeners,
+                                                   CORBA_Object_duplicate (l, ev));*/
+
+/* possibly this interface should NOT be used for mouse events ? */
+      break;
+  }
+}
+
+static gboolean
+_controller_register_with_devices (DeviceEventController *controller)
+{
+  gboolean retval = FALSE;
+  Display *default_display;
+  Window root_window;
+
+  default_display = GDK_DISPLAY();
+  root_window = GDK_ROOT_WINDOW();  
+  /* calls to device-specific implementations and routines go here */
+  /* register with: keyboard hardware code handler */
+  /* register with: (translated) keystroke handler */
+#ifdef SPI_DEBUG
+  fprintf (stderr, "About to request events on window %ld of display %p\n",
+          (unsigned long) root_window, default_display);
+#endif
+  XSelectInput (default_display,
+               root_window,
+               KeyPressMask);
+  XSelectInput (default_display,
+               root_window,
+               KeyReleaseMask);
+  /* register with: mouse hardware device handler? */
+  /* register with: mouse event handler */
+  return retval;
+}
+
+static gboolean _check_key_event (DeviceEventController *controller)
+{
+#ifdef SPI_DEBUG
+       static Accessibility_ControllerEventMask shiftlock_mask =
+               {(CORBA_unsigned_long) LockMask, (CORBA_unsigned_short) 1};
+#endif
+       static gboolean initialized = FALSE;
+       static gboolean is_active = FALSE;
+       XEvent *x_event = g_new0 (XEvent, 1);
+       XKeyEvent *x_key_event;
+       KeySym keysym;
+       gboolean is_consumed = FALSE;
+       char key_name[16];
+       int i;
+       int n_listeners = g_list_length (controller->key_listeners);
+       Accessibility_KeyStroke key_event;
+       static CORBA_Environment ev;
+       
+       if (!initialized)
+       {
+               initialized = TRUE;
+               CORBA_exception_init (&ev);
+       }
+
+/*        if (!XPending(GDK_DISPLAY())) return TRUE; */
+
+       /*
+        * the call to XPending seemed like a good idea, why did it
+        * wreak such havoc?
+        */
+
+       XPeekEvent (GDK_DISPLAY(), x_event);
+       if (x_event->type == KeyPress)
+       {
+           x_key_event = (XKeyEvent *)x_event;
+           keysym = XLookupKeysym (x_key_event, 0);
+           key_event.keyID = (CORBA_long)(keysym);
+           key_event.type = Accessibility_KEY_PRESSED;
+           key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
+#if defined SPI_KEYEVENT_DEBUG
+           fprintf (stderr,
+                    "Key %lu pressed (%c), modifiers %d\n",
+                    (unsigned long) keysym,
+                    (char) keysym,
+                    (int) x_key_event->state);
+#elif defined SPI_DEBUG
+           fprintf(stderr, "%s%c",
+                   (x_key_event->state & Mod1Mask)?"Alt-":"",
+                   ((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))?
+                   (char) toupper((int) keysym) : (char) tolower((int)keysym));
+#endif /* SPI_DEBUG */
+       }
+       else
+       {
+#ifdef SPI_KEYEVENT_DEBUG
+               fprintf (stderr, "other event, type %d\n", (int) x_event->type);
+#endif
+       }
+       /* relay to listeners, and decide whether to consume it or not */
+       for (i=0; i<n_listeners && !is_consumed; ++i)
+       {
+         Accessibility_KeystrokeListener ls;
+         ls = (Accessibility_KeystrokeListener)
+                       g_list_nth_data (controller->key_listeners, i);
+         if (!CORBA_Object_is_nil(ls, &ev))
+         {
+           is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev);
+         }             
+       }
+       if (is_consumed) XNextEvent (GDK_DISPLAY(), x_event);
+       XAllowEvents (GDK_DISPLAY(), ReplayKeyboard, CurrentTime);
+/*
+ *  I haven't figure out how to make this work correctly yet :-(
+ *
+ *     XGrabKeyboard (GDK_DISPLAY(), GDK_ROOT_WINDOW(), True,
+ *                    GrabModeAsync, GrabModeSync, CurrentTime);
+ *      XAllowEvents (GDK_DISPLAY(), SyncKeyboard, CurrentTime);
+ *
+ *
+ * ControlMask grabs are broken, must be in use already.
+ *
+ */
+       
+/* Always grab ShiftLock in DEBUG mode */
+#ifdef SPI_DEBUG
+       if (!controller->keymask_list)
+           controller->keymask_list =
+               g_list_append (controller->keymask_list, &shiftlock_mask);
+#endif
+       return _controller_grab_keyboard (controller);
+}
+
+static gboolean
+_controller_grab_keyboard (DeviceEventController *controller)
+{
+       Display *display = GDK_DISPLAY();
+       Window root_window = GDK_ROOT_WINDOW();
+       GList *maskList = controller->keymask_list;
+       int i;
+       int last_mask = g_list_length (maskList);
+
+/*
+ * masks known to work with default RH 7.1: 
+ * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
+ * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
+ * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
+ * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
+ *
+ * ControlMask grabs are broken, must be in use already
+ */
+       
+       for (i=0; i < last_mask; ++i)
+       {
+               Accessibility_ControllerEventMask *mask
+                       = (Accessibility_ControllerEventMask *)g_list_nth_data (maskList, i);
+               unsigned long maskVal = 0xFFFFFFFF;
+               if (mask) maskVal = (unsigned long) mask->value;
+#ifdef SPI_KEYEVENT_DEBUG
+               fprintf (stderr, "mask=%lx\n", maskVal);
+#endif
+               if (!(maskVal & ControlMask))
+               {
+#ifdef SPI_KEYEVENT_DEBUG
+                       fprintf (stderr, "grabbing for mod %lu\n", (unsigned long) maskVal);
+#endif
+                       XGrabKey (display,
+                                 AnyKey,
+                                 maskVal,
+                                 root_window,
+                                 True,
+                                 GrabModeAsync,
+                                 GrabModeSync);
+                       /* TODO: check call for errors and return FALSE if error occurs */
+               } else {
+                       return FALSE; /* can't do control key yet */
+               }
+       }
+       return TRUE;
+}
+
 /*
  * Implemented GObject::finalize
  */
@@ -68,12 +364,18 @@ device_event_controller_object_finalize (GObject *object)
 static void
 impl_register_keystroke_listener (PortableServer_Servant     servant,
                                  const Accessibility_KeystrokeListener l,
+                                 const Accessibility_ControllerEventMask *mask,
                                  CORBA_Environment         *ev)
 {
+       DeviceEventController *controller = DEVICE_EVENT_CONTROLLER (
+               bonobo_object_from_servant (servant));
 #ifdef SPI_DEBUG
-       fprintf (stderr, "registering keystroke listener %p\n", l);
+       fprintf (stderr, "registering keystroke listener %p with maskVal %lu\n",
+                (void *) l, (unsigned long) mask->value);
 #endif
+       _controller_register_device_listener(controller, l, mask, DEVICE_TYPE_KBD, ev);
 }
+
 /*
  * CORBA Accessibility::DeviceEventController::registerMouseListener
  *     method implementation
@@ -84,9 +386,12 @@ impl_register_mouse_listener (PortableServer_Servant     servant,
                              const Accessibility_MouseListener *l,
                              CORBA_Environment         *ev)
 {
+       DeviceEventController *controller = DEVICE_EVENT_CONTROLLER (
+               bonobo_object_from_servant (servant));
 #ifdef SPI_DEBUG
        fprintf (stderr, "registering mouse listener %p\n", l);
 #endif
+       _controller_register_device_listener(controller, l, mask, DEVICE_TYPE_MOUSE, ev);
 }
 */
 
@@ -100,7 +405,7 @@ impl_generate_key_event (PortableServer_Servant     servant,
                         CORBA_Environment         *ev)
 {
 #ifdef SPI_DEBUG
-       fprintf (stderr, "synthesizing keystroke %ld\n", keyEventID);
+       fprintf (stderr, "synthesizing keystroke %ld\n", (long) keyEventID);
 #endif
 }
 
@@ -133,11 +438,23 @@ device_event_controller_class_init (DeviceEventControllerClass *klass)
 /*        epv->registerMouseListener = impl_register_mouse_listener; */
         epv->generateKeyEvent = impl_generate_key_event;
         epv->generateMouseEvent = impl_generate_mouse_event;
+       klass->check_key_event = _check_key_event;
 }
 
 static void
 device_event_controller_init (DeviceEventController *device_event_controller)
 {
+  device_event_controller->key_listeners = NULL;
+  device_event_controller->key_listeners = NULL;
+  device_event_controller->keymask_list = NULL;
+  kbd_registered = _controller_register_with_devices (device_event_controller);
+}
+
+gboolean device_event_controller_check_key_event (DeviceEventController *controller)
+{
+       DeviceEventControllerClass *klass = DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
+       if (klass->check_key_event)
+               return (klass->check_key_event) (controller);
 }
 
 GType
index 60255da..dd195db 100644 (file)
@@ -29,20 +29,26 @@ extern "C" {
 
 #include <bonobo/bonobo-object.h>
 #include <libspi/Accessibility.h>
+#include "keystrokelistener.h"
 
 #define DEVICE_EVENT_CONTROLLER_TYPE        (device_event_controller_get_type ())
 #define DEVICE_EVENT_CONTROLLER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventController))
 #define DEVICE_EVENT_CONTROLLER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventControllerClass))
-#define IS_DEVICE_EVENT_CONTROLLER(o)       (G_TYPE_CHECK__INSTANCE_TYPE ((o), DEVICE_EVENT_CONTROLLER_TYPE))
+#define IS_DEVICE_EVENT_CONTROLLER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVICE_EVENT_CONTROLLER_TYPE))
 #define IS_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVICE_EVENT_CONTROLLER_TYPE))
+#define DEVICE_EVENT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventControllerClass))
 
 typedef struct {
         BonoboObject parent;
+        GList *key_listeners;
+        GList *mouse_listeners;
+       GList *keymask_list;
 } DeviceEventController;
 
 typedef struct {
         BonoboObjectClass parent_class;
         POA_Accessibility_DeviceEventController__epv epv;
+       gboolean (*check_key_event) (DeviceEventController *controller);
 } DeviceEventControllerClass;
 
 GType               device_event_controller_get_type   (void);
index d99c72c..880c006 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #include <libbonobo.h>
+#include <glib/gmain.h>
 #include "registry.h"
 
 int
@@ -32,6 +33,7 @@ main (int argc,
       char **argv)
 {
         Registry *registry;
+       GSource *keyevent_source;
         char *obj_id;
 
         if (!bonobo_init (&argc, argv))
@@ -50,6 +52,12 @@ main (int argc,
 #ifdef AT_SPI_DEBUG
         fprintf (stderr, "Registry Message: Registry daemon is running.\n");
 #endif
+  
+        gdk_init(&argc, &argv);
+       g_idle_add (registry->kbd_event_hook, registry);
+/*     keyevent_source =
+               g_source_new (registry->kbd_event_hook, sizeof (GSourceFunc));
+               g_source_attach (keyevent_source, g_main_context_default());*/
         bonobo_main ();
 
         return 0;
index 0f39ed7..208cab5 100644 (file)
 #include <libspi/Accessibility.h>
 
 /*
+ * We'd like to replace the dependance on X-isms with a wrapper layer,
+ * to the extent that it can't be done with pure GDK.
+ * Anyone want to help?
+ */
+#include <X11/Xlib.h>
+#include <gdk/gdkx.h>
+
+/*
  * This pulls the definition for the BonoboObject (GType)
  */
 #include "registry.h"
@@ -79,6 +87,8 @@ static void _registry_notify_listeners ( GList *listeners,
 
 static long _get_unique_id();
 
+static gboolean _device_event_controller_hook (gpointer source);
+
 /*
  * Implemented GObject::finalize
  */
@@ -124,7 +134,7 @@ impl_accessibility_registry_register_application (PortableServer_Servant servant
 }
 
 static gint
-compare_object_hash (gconstpointer p1, gconstpointer p2)
+compare_corba_objects (gconstpointer p1, gconstpointer p2)
 {
   CORBA_Environment ev;
   gint retval;
@@ -248,7 +258,7 @@ impl_accessibility_registry_deregister_application (PortableServer_Servant serva
                                                     CORBA_Environment * ev)
 {
   Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
-  GList *list = g_list_find_custom (registry->desktop->applications, application, compare_object_hash);
+  GList *list = g_list_find_custom (registry->desktop->applications, application, compare_corba_objects);
 
 #ifdef SPI_DEBUG
   gint i;
@@ -277,8 +287,8 @@ impl_accessibility_registry_deregister_application (PortableServer_Servant serva
  * CORBA Accessibility::Registry::registerGlobalEventListener method implementation
  */
 static void
-impl_accessibility_registry_register_global_event_listener
-                                            (PortableServer_Servant  servant,
+impl_accessibility_registry_register_global_event_listener (
+                                            PortableServer_Servant  servant,
                                              Accessibility_EventListener listener,
                                              const CORBA_char *event_name,
                                              CORBA_Environment      *ev)
@@ -319,13 +329,13 @@ impl_accessibility_registry_register_global_event_listener
  * CORBA Accessibility::Registry::deregisterGlobalEventListenerAll method implementation
  */
 static void
-impl_accessibility_registry_deregister_global_event_listener_all
-                                                   (PortableServer_Servant  servant,
+impl_accessibility_registry_deregister_global_event_listener_all (
+                                                    PortableServer_Servant  servant,
                                                     Accessibility_EventListener listener,
                                                     CORBA_Environment      *ev)
 {
   Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
-  GList *list = g_list_find_custom (registry->focus_listeners, listener, compare_object_hash);
+  GList *list = g_list_find_custom (registry->focus_listeners, listener, compare_corba_objects);
 
   /*
    * TODO : de-register with toolkit if the last instance of a listener
@@ -336,14 +346,14 @@ impl_accessibility_registry_deregister_global_event_listener_all
     {
       fprintf (stderr, "deregistering listener\n");
       registry->focus_listeners = g_list_delete_link (registry->focus_listeners, list);
-      list = g_list_find_custom (registry->focus_listeners, listener, compare_object_hash);
+      list = g_list_find_custom (registry->focus_listeners, listener, compare_corba_objects);
     }
-  list = g_list_find_custom (registry->toolkit_listeners, listener, compare_object_hash);
+  list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects);
   while (list)
     {
       fprintf (stderr, "deregistering listener\n");
       registry->toolkit_listeners = g_list_delete_link (registry->toolkit_listeners, list);
-      list = g_list_find_custom (registry->toolkit_listeners, listener, compare_object_hash);
+      list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects);
     }
 }
 
@@ -351,8 +361,8 @@ impl_accessibility_registry_deregister_global_event_listener_all
  * CORBA Accessibility::Registry::deregisterGlobalEventListener method implementation
  */
 static void
-impl_accessibility_registry_deregister_global_event_listener
-                                                   (PortableServer_Servant  servant,
+impl_accessibility_registry_deregister_global_event_listener (
+                                                    PortableServer_Servant  servant,
                                                     Accessibility_EventListener listener,
                                                     const CORBA_char * event_name,
                                                     CORBA_Environment      *ev)
@@ -453,12 +463,16 @@ impl_accessibility_registry_get_desktop_list (PortableServer_Servant servant,
   return (Accessibility_DesktopSeq *) NULL;
 }
 
-static CORBA_Object
+static Accessibility_DeviceEventController
 impl_accessibility_registry_get_device_event_controller (PortableServer_Servant servant,
                                                          CORBA_Environment * ev)
 {
-  /* TODO: not yet implemented! */
-  return CORBA_OBJECT_NIL;
+  Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
+  if (!registry->device_event_controller)
+    registry->device_event_controller = g_object_new (DEVICE_EVENT_CONTROLLER_TYPE, NULL);
+  return CORBA_Object_duplicate (
+         bonobo_object_corba_objref (
+                 bonobo_object (registry->device_event_controller)), ev);
 }
 
 static void
@@ -536,6 +550,15 @@ _registry_notify_listeners ( GList *listeners,
     }
 }
 
+static gboolean _device_event_controller_hook (gpointer p)
+{
+    Registry *registry = (Registry *)p;
+    DeviceEventController *controller = registry->device_event_controller;
+    if (controller)
+       device_event_controller_check_key_event (controller);
+    return TRUE;
+}
+
 static void
 registry_class_init (RegistryClass *klass)
 {
@@ -567,6 +590,8 @@ registry_init (Registry *registry)
   registry->toolkit_listeners = NULL;
   registry->applications = NULL;
   registry->desktop = desktop_new();
+  registry->device_event_controller = NULL;
+  registry->kbd_event_hook = _device_event_controller_hook;
 }
 
 GType
index 18fe392..7622fe2 100644 (file)
 extern "C" {
 #endif /* __cplusplus */
 
+#include <glib/gmain.h>
 #include <libspi/Accessibility.h>
 #include "listener.h"
 #include "desktop.h"
+#include "deviceeventcontroller.h"
 
 #define REGISTRY_TYPE        (registry_get_type ())
 #define REGISTRY(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), REGISTRY_TYPE, Registry))
@@ -43,7 +45,9 @@ typedef struct {
   GList *window_listeners;
   GList *toolkit_listeners;
   GList *applications;
+  DeviceEventController *device_event_controller;
   Desktop *desktop;
+  gboolean (*kbd_event_hook) (gpointer source);
 } Registry;
 
 typedef struct {
index d99c72c..880c006 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #include <libbonobo.h>
+#include <glib/gmain.h>
 #include "registry.h"
 
 int
@@ -32,6 +33,7 @@ main (int argc,
       char **argv)
 {
         Registry *registry;
+       GSource *keyevent_source;
         char *obj_id;
 
         if (!bonobo_init (&argc, argv))
@@ -50,6 +52,12 @@ main (int argc,
 #ifdef AT_SPI_DEBUG
         fprintf (stderr, "Registry Message: Registry daemon is running.\n");
 #endif
+  
+        gdk_init(&argc, &argv);
+       g_idle_add (registry->kbd_event_hook, registry);
+/*     keyevent_source =
+               g_source_new (registry->kbd_event_hook, sizeof (GSourceFunc));
+               g_source_attach (keyevent_source, g_main_context_default());*/
         bonobo_main ();
 
         return 0;
index b423408..c06b527 100644 (file)
@@ -27,6 +27,7 @@
 
 static void report_focus_event (void *fp);
 static void report_button_press (void *fp);
+static boolean report_key_event (void *fp);
 static void get_environment_vars (void);
 
 static int _festival_init ();
@@ -47,6 +48,7 @@ main(int argc, char **argv)
   Accessible *application;
   AccessibleEventListener *focus_listener;
   AccessibleEventListener *button_listener;
+  KeystrokeListener *key_listener;
 
   if ((argc > 1) && (!strncmp(argv[1],"-h",2)))
   {
@@ -77,6 +79,10 @@ main(int argc, char **argv)
         }
     }
 
+  /* prepare the keyboard snoopers */
+  /* key_listener = createKeystrokeListener(report_key_event);
+     registerKeystrokeListener(key_listener, KEYMASK_SHIFT); */
+
   get_environment_vars();
 
   SPI_event_main(FALSE);
@@ -127,6 +133,17 @@ report_focus_event (void *p)
              magnifier_set_roi (x, y, width, height);        
       }
     }
+  if (Accessible_isText(&ev->source))
+    /* if this is a text object, speak the first sentence. */
+  {
+     AccessibleText *text_interface = Accessible_getText (&ev->source);
+     long start_offset, end_offset;
+     char *first_sentence = "";
+     first_sentence = AccessibleText_getTextAtOffset (
+            text_interface, (long) 0, TEXT_BOUNDARY_WORD_END,
+            &start_offset, &end_offset); 
+     _festival_say(first_sentence, "voice_don_diphone", festival_chatty==FALSE);
+  }
 }
 
 void
@@ -137,6 +154,14 @@ report_button_press (void *p)
            Accessible_getName (&ev->source));
 }
 
+static boolean
+report_key_event (void *p)
+{
+  KeyStroke *key = (KeyStroke *) p;
+  fprintf (stderr, ".");
+  return FALSE;
+}
+
 static int _festival_init ()
 {
   int fd;
@@ -157,7 +182,7 @@ static int _festival_init ()
 
   _festival_write ("(audio_mode'async)\n", fd);
   _festival_write ("(Parameter.set 'Duration_Model 'Tree_ZScore)\n", fd);
-  _festival_write ("(Parameter.set 'Duration_Stretch 0.7)\n", fd);
+  _festival_write ("(Parameter.set 'Duration_Stretch 0.75)\n", fd);
   return fd;
 }
 
@@ -198,7 +223,7 @@ static void _festival_say (const char *text, const char *voice, boolean shutup)
       snprintf (voice_spec, 32, "(%s)\n", voice); 
       _festival_write (voice_spec, fd);
       _festival_write ("(Parameter.set 'Duration_Model 'Tree_ZScore)\n", fd);
-      _festival_write ("(Parameter.set 'Duration_Stretch 0.5)\n", fd);
+      _festival_write ("(Parameter.set 'Duration_Stretch 0.75)\n", fd);
     }
 
   _festival_write (quoted, fd);
index 1eb2214..a1c06fb 100644 (file)
@@ -1,6 +1,6 @@
 <oaf_info>
        <oaf_server iid="OAFIID:Accessibility_Util_Magnifier:proto0.1"
-                   type="exe" location="magnifier -h">
+                   type="exe" location="magnifier -vz 2">
                <oaf_attribute name="repo_ids" type="stringv">
                        <item value="IDL:Accessibility/Magnifier:1.0"/>
                </oaf_attribute>
index 2bd92c2..8f886ce 100644 (file)
@@ -1,4 +1,10 @@
-NULL=
+NULL =
+
+idldir = $(top_srcdir)/util/idl
+
+idl_DATA = idl/Magnifier.idl
+
+dist_SUBDIRS = idl
 
 lib_LTLIBRARIES = libat-util.la
 
@@ -16,11 +22,15 @@ libat_util_la_DEPENDENCIES = \
        Magnifier.h
 
 magnifier_SOURCES = magnifier.c \
-       mag_image.c mag_image.h Magnifier.h \
+       mag_image.c \
+       mag_image.h \
+       magnifier.h \
+       Magnifier.h \
        Magnifier-skels.c \
        Magnifier-common.c
 
-mag_control_SOURCES = mag_control.c mag_client.h\
+mag_control_SOURCES = mag_control.c \
+       mag_client.h\
        Magnifier-common.c      \
        Magnifier-stubs.c
 
@@ -32,7 +42,7 @@ CFLAGS += $(UTILS_CFLAGS)
 
 IDL_OUT = Magnifier.h Magnifier-skels.c Magnifier-stubs.c Magnifier-common.c
 
-IDL = $(top_srcdir)/util/idl/Magnifier.idl
+IDL = $(idl_DATA)
 
 BUILT_SOURCES = $(IDL_OUT)
 CLEANFILES+=$(IDL_OUT)
@@ -50,7 +60,7 @@ serverinfo_DATA = Accessibility_Util.server
 
 @XML_I18N_MERGE_SERVER_RULE@
 
-EXTRA_DIST = Accessibility_Util.server.in $(serverinfo_DATA)
+EXTRA_DIST = Accessibility_Util.server.in $(serverinfo_DATA) $(idl_DATA)
 
 $(IDL_OUT) : $(IDL) $(ORBIT_IDL)
        $(ORBIT_IDL) $(IDLFLAGS) $(IDL)
index 9829e44..7849991 100644 (file)
@@ -36,7 +36,6 @@ get_magnifier()
 
     magnifier = (Accessibility_Magnifier) oclient;
 
-    /* bonobo_activate (); ? */
   }
 
   return magnifier;