From: billh Date: Mon, 8 Oct 2001 16:57:19 +0000 (+0000) Subject: Fixed 'make dist', and added: X-Git-Tag: AT_SPI2_CORE_0_1_3~1098 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e5a9e644107d0a366d8f4036fc8d363a4ff82255;p=platform%2Fupstream%2Fat-spi2-core.git Fixed 'make dist', and added: 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 --- diff --git a/ChangeLog b/ChangeLog index 5416f33..35f3af6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,78 @@ +<2001-10-08 Bill Haneman + + * 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; 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 + + * libspi/keystrokelistener.h: + * libspi/keystrokelistener.c: + Initial functional implementations of KeystrokeListener. + * idl/Registry.idl: + <2001-10-05 Marc Mulcahy - 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 +<2001-09-30 Bill Haneman * libspi/keystrokelistener.h: * libspi/keystrokelistener.c: diff --git a/configure.in b/configure.in index c1a14e0..09bd8b4 100644 --- a/configure.in +++ b/configure.in @@ -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) diff --git a/cspi/Makefile.am b/cspi/Makefile.am index c7bb192..2abf4d2 100644 --- a/cspi/Makefile.am +++ b/cspi/Makefile.am @@ -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 diff --git a/cspi/spi-listener.h b/cspi/spi-listener.h index c03851f..616d74e 100644 --- a/cspi/spi-listener.h +++ b/cspi/spi-listener.h @@ -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 } diff --git a/cspi/spi.h b/cspi/spi.h index 4570e49..bb63dc1 100644 --- a/cspi/spi.h +++ b/cspi/spi.h @@ -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: diff --git a/cspi/spi_accessible.c b/cspi/spi_accessible.c index 6099f44..6707224 100644 --- a/cspi/spi_accessible.c +++ b/cspi/spi_accessible.c @@ -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); diff --git a/cspi/spi_event.c b/cspi/spi_event.c index f109cc6..60081ac 100644 --- a/cspi/spi_event.c +++ b/cspi/spi_event.c @@ -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; +} diff --git a/cspi/spi_registry.c b/cspi/spi_registry.c index 784d642..37b4b45 100644 --- a/cspi/spi_registry.c +++ b/cspi/spi_registry.c @@ -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); } /** diff --git a/cspi/spi_text.c b/cspi/spi_text.c index 000a201..6c672e9 100644 --- a/cspi/spi_text.c +++ b/cspi/spi_text.c @@ -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; } diff --git a/idl/Accessibility_Registry.idl b/idl/Accessibility_Registry.idl index e6b54d8..3308029 100644 --- a/idl/Accessibility_Registry.idl +++ b/idl/Accessibility_Registry.idl @@ -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 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: diff --git a/idl/Accessibility_Text.idl b/idl/Accessibility_Text.idl index 1fdcae5..5d1c442 100644 --- a/idl/Accessibility_Text.idl +++ b/idl/Accessibility_Text.idl @@ -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, diff --git a/idl/Makefile.am b/idl/Makefile.am index e4c4a8b..d6a0982 100644 --- a/idl/Makefile.am +++ b/idl/Makefile.am @@ -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) diff --git a/idl/Registry.idl b/idl/Registry.idl index e6b54d8..3308029 100644 --- a/idl/Registry.idl +++ b/idl/Registry.idl @@ -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 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: diff --git a/idl/Text.idl b/idl/Text.idl index 1fdcae5..5d1c442 100644 --- a/idl/Text.idl +++ b/idl/Text.idl @@ -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, diff --git a/libspi/Makefile.am b/libspi/Makefile.am index ea022d1..1031b69 100644 --- a/libspi/Makefile.am +++ b/libspi/Makefile.am @@ -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) \ diff --git a/libspi/deviceeventcontroller.c b/libspi/deviceeventcontroller.c index 33adf5d..76b5666 100644 --- a/libspi/deviceeventcontroller.c +++ b/libspi/deviceeventcontroller.c @@ -29,7 +29,10 @@ #include #endif +#include #include +#include /* TODO: hide dependency (wrap in single porting file) */ +#include #include #include @@ -48,6 +51,299 @@ */ 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; ikey_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 diff --git a/libspi/deviceeventcontroller.h b/libspi/deviceeventcontroller.h index 60255da..dd195db 100644 --- a/libspi/deviceeventcontroller.h +++ b/libspi/deviceeventcontroller.h @@ -29,20 +29,26 @@ extern "C" { #include #include +#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); diff --git a/libspi/editabletext.c b/libspi/editabletext.c index 89a7b85..4c14c20 100644 --- a/libspi/editabletext.c +++ b/libspi/editabletext.c @@ -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); } diff --git a/libspi/editabletext.h b/libspi/editabletext.h index 5db4c19..9d4fc6e 100644 --- a/libspi/editabletext.h +++ b/libspi/editabletext.h @@ -28,6 +28,7 @@ extern "C" { #include #include #include +#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; }; diff --git a/libspi/keystrokelistener.c b/libspi/keystrokelistener.c index 61f883c..68736c9 100644 --- a/libspi/keystrokelistener.c +++ b/libspi/keystrokelistener.c @@ -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 diff --git a/libspi/keystrokelistener.h b/libspi/keystrokelistener.h index 93a15a6..7daca15 100644 --- a/libspi/keystrokelistener.h +++ b/libspi/keystrokelistener.h @@ -30,15 +30,19 @@ extern "C" { #include #include #include +#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 } diff --git a/libspi/registry.c b/libspi/registry.c index 0f39ed7..208cab5 100644 --- a/libspi/registry.c +++ b/libspi/registry.c @@ -36,6 +36,14 @@ #include /* + * 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 +#include + +/* * 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 diff --git a/libspi/registry.h b/libspi/registry.h index 18fe392..7622fe2 100644 --- a/libspi/registry.h +++ b/libspi/registry.h @@ -27,9 +27,11 @@ extern "C" { #endif /* __cplusplus */ +#include #include #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 { diff --git a/libspi/text.c b/libspi/text.c index afb4a7e..8e87079 100644 --- a/libspi/text.c +++ b/libspi/text.c @@ -28,6 +28,7 @@ #include #include +#include /* * 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; } diff --git a/libspi/text.h b/libspi/text.h index e9594b7..53f4817 100644 --- a/libspi/text.h +++ b/libspi/text.h @@ -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 #include #include +#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; diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index 33adf5d..76b5666 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -29,7 +29,10 @@ #include #endif +#include #include +#include /* TODO: hide dependency (wrap in single porting file) */ +#include #include #include @@ -48,6 +51,299 @@ */ 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; ikey_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 diff --git a/registryd/deviceeventcontroller.h b/registryd/deviceeventcontroller.h index 60255da..dd195db 100644 --- a/registryd/deviceeventcontroller.h +++ b/registryd/deviceeventcontroller.h @@ -29,20 +29,26 @@ extern "C" { #include #include +#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); diff --git a/registryd/registry-main.c b/registryd/registry-main.c index d99c72c..880c006 100644 --- a/registryd/registry-main.c +++ b/registryd/registry-main.c @@ -25,6 +25,7 @@ #endif #include +#include #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; diff --git a/registryd/registry.c b/registryd/registry.c index 0f39ed7..208cab5 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -36,6 +36,14 @@ #include /* + * 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 +#include + +/* * 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 diff --git a/registryd/registry.h b/registryd/registry.h index 18fe392..7622fe2 100644 --- a/registryd/registry.h +++ b/registryd/registry.h @@ -27,9 +27,11 @@ extern "C" { #endif /* __cplusplus */ +#include #include #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 { diff --git a/registryd/registryd.c b/registryd/registryd.c index d99c72c..880c006 100644 --- a/registryd/registryd.c +++ b/registryd/registryd.c @@ -25,6 +25,7 @@ #endif #include +#include #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; diff --git a/test/simple-at.c b/test/simple-at.c index b423408..c06b527 100644 --- a/test/simple-at.c +++ b/test/simple-at.c @@ -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); diff --git a/util/Accessibility_Util.server.in b/util/Accessibility_Util.server.in index 1eb2214..a1c06fb 100644 --- a/util/Accessibility_Util.server.in +++ b/util/Accessibility_Util.server.in @@ -1,6 +1,6 @@ + type="exe" location="magnifier -vz 2"> diff --git a/util/Makefile.am b/util/Makefile.am index 2bd92c2..8f886ce 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -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) diff --git a/util/mag_client.c b/util/mag_client.c index 9829e44..7849991 100644 --- a/util/mag_client.c +++ b/util/mag_client.c @@ -36,7 +36,6 @@ get_magnifier() magnifier = (Accessibility_Magnifier) oclient; - /* bonobo_activate (); ? */ } return magnifier;