From 1fb3c4bc6ba863a4dec09c0b1097b9e6c752d766 Mon Sep 17 00:00:00 2001 From: michael Date: Fri, 11 Jan 2002 17:00:10 +0000 Subject: [PATCH] 2002-01-11 Michael Meeks * registryd/deviceeventcontroller.c (spi_device_event_controller_forward_key_event): kill XUngrabKey / XKeyGrab race. (spi_controller_grab_keyboard): rename to (spi_controller_update_key_grabs): this, and deal with incremental adding / removing grabs more sensibly. (_register_keygrab): ensure we're not pending a remove. (spi_grab_mask_free): impl. (spi_controller_register_global_keygrabs): split out common code into: (handle_keygrab): impl. (_deregister_keygrab): impl. (spi_controller_deregister_global_keygrabs): impl. (spi_controller_update_key_grabs): re-issue the grab if we just recieved a notification. * test/test-simple.c (key_listener_cb): remove debug. * registryd/deviceeventcontroller.c (spi_controller_register_device_listener): after registering a global keygrab, actualy register it ! don't wait for a timeout; doh ! * registryd/deviceeventcontroller.[ch]: s/DeviceEvent/DE/ to make it more readable / manipulable. s/grabmask/grab_mask/ s/refcount/ref_count/ s/keyval/key_val/ s/modmask/mod_mask 2002-01-08 Michael Meeks * registryd/deviceeventcontroller.c (spi_controller_register_with_devices): use gdk calls to setup a filter. (global_filter_fn): implement the filter. (spi_device_event_controller_check_key_event): rename to (spi_device_event_controller_forward_key_event): this & upd. (spi_get_display): replace with GDK_DISPLAY. * registryd/deviceeventcontroller.c (spi_controller_deregister_device_listener): unroll into (impl_deregister_keystroke_listener): here to simplify. (spi_controller_register_global_keygrabs): split cut and paste (!) out into (_register_keygrab): here, shorter & sweeter. (spi_controller_deregister_device_listener): remove. (impl_register_mouse_listener): remove, no mouse listener support in at-spi-1.0 * registryd/registry.c (_device_event_controller_hook): kill. (spi_registry_init): upd. * registryd/deviceeventcontroller.c (spi_device_event_controller_class_init): upd. (spi_check_key_event): merge into. (spi_device_event_controller_check_key_event): here and kill strange static ev init, don't leak the x_event - nor dynamicaly allocate it. * registryd/registry-main.c (main): re-direct timeout to remove strange vtable mess. * registryd/deviceeventcontroller.c (remove_listener_cb): impl. (spi_controller_deregister_device_listener): fix re-enterancy hazard. 2002-01-07 Michael Meeks * registryd/deviceeventcontroller.c (spi_device_event_controller_new): upd. (impl_notify_listeners_sync): upd. debug. (spi_notify_keylisteners): fix re-enterancy hazards, prettify, remove O(n*n) iteration. (spi_controller_grab_keyboard): fix iteration. (spi_check_key_event): re-format to suit coding style. Clean all the warnings - we're warning free. * registryd/deviceeventcontroller.h: * registryd/registry.h: make mutualy referential with typesafe forward references instead of (!) void pointer hacks. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@219 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- ChangeLog | 85 ++++ cspi/spi_registry.c | 8 +- idl/Accessibility_Registry.idl | 2 +- registryd/deviceeventcontroller.c | 918 ++++++++++++++++++++------------------ registryd/deviceeventcontroller.h | 32 +- registryd/registry-main.c | 2 +- registryd/registry.c | 79 ++-- registryd/registry.h | 25 +- test/test-simple.c | 29 +- 9 files changed, 672 insertions(+), 508 deletions(-) diff --git a/ChangeLog b/ChangeLog index eac1850..17ebb58 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,90 @@ 2002-01-11 Michael Meeks + * registryd/deviceeventcontroller.c + (spi_device_event_controller_forward_key_event): kill + XUngrabKey / XKeyGrab race. + (spi_controller_grab_keyboard): rename to + (spi_controller_update_key_grabs): this, and deal + with incremental adding / removing grabs more + sensibly. + (_register_keygrab): ensure we're not pending a remove. + (spi_grab_mask_free): impl. + (spi_controller_register_global_keygrabs): split out + common code into: + (handle_keygrab): impl. + (_deregister_keygrab): impl. + (spi_controller_deregister_global_keygrabs): impl. + (spi_controller_update_key_grabs): re-issue the grab if + we just recieved a notification. + + * test/test-simple.c (key_listener_cb): remove debug. + + * registryd/deviceeventcontroller.c + (spi_controller_register_device_listener): after + registering a global keygrab, actualy register it ! + don't wait for a timeout; doh ! + + * registryd/deviceeventcontroller.[ch]: s/DeviceEvent/DE/ + to make it more readable / manipulable. + s/grabmask/grab_mask/ s/refcount/ref_count/ + s/keyval/key_val/ s/modmask/mod_mask + +2002-01-08 Michael Meeks + + * registryd/deviceeventcontroller.c + (spi_controller_register_with_devices): use gdk calls to + setup a filter. + (global_filter_fn): implement the filter. + (spi_device_event_controller_check_key_event): rename to + (spi_device_event_controller_forward_key_event): this & upd. + (spi_get_display): replace with GDK_DISPLAY. + + * registryd/deviceeventcontroller.c + (spi_controller_deregister_device_listener): unroll into + (impl_deregister_keystroke_listener): here to simplify. + (spi_controller_register_global_keygrabs): split cut and + paste (!) out into (_register_keygrab): here, shorter & sweeter. + (spi_controller_deregister_device_listener): remove. + (impl_register_mouse_listener): remove, no mouse listener + support in at-spi-1.0 + + * registryd/registry.c + (_device_event_controller_hook): kill. + (spi_registry_init): upd. + + * registryd/deviceeventcontroller.c + (spi_device_event_controller_class_init): upd. + (spi_check_key_event): merge into. + (spi_device_event_controller_check_key_event): + here and kill strange static ev init, don't leak + the x_event - nor dynamicaly allocate it. + + * registryd/registry-main.c (main): re-direct + timeout to remove strange vtable mess. + + * registryd/deviceeventcontroller.c + (remove_listener_cb): impl. + (spi_controller_deregister_device_listener): + fix re-enterancy hazard. + +2002-01-07 Michael Meeks + + * registryd/deviceeventcontroller.c + (spi_device_event_controller_new): upd. + (impl_notify_listeners_sync): upd. debug. + (spi_notify_keylisteners): fix re-enterancy hazards, + prettify, remove O(n*n) iteration. + (spi_controller_grab_keyboard): fix iteration. + (spi_check_key_event): re-format to suit coding style. + Clean all the warnings - we're warning free. + + * registryd/deviceeventcontroller.h: + * registryd/registry.h: make mutualy referential with + typesafe forward references instead of (!) void pointer + hacks. + +2002-01-11 Michael Meeks + * cspi/spi_accessible.c (role_names): add a role name to sync this array with the enum; and make the regression tests pass, sigh. diff --git a/cspi/spi_registry.c b/cspi/spi_registry.c index 0f393f2..58f7e7b 100644 --- a/cspi/spi_registry.c +++ b/cspi/spi_registry.c @@ -310,10 +310,10 @@ SPI_freeDesktopList (Accessible **desktop_list) * Returns: #TRUE if successful, otherwise #FALSE. **/ SPIBoolean -SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener, - AccessibleKeySet *keys, - AccessibleKeyMaskType modmask, - AccessibleKeyEventMask eventmask, +SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener, + AccessibleKeySet *keys, + AccessibleKeyMaskType modmask, + AccessibleKeyEventMask eventmask, AccessibleKeyListenerSyncType sync_type) { gint i, mask; diff --git a/idl/Accessibility_Registry.idl b/idl/Accessibility_Registry.idl index 1d2a225..3d9d212 100644 --- a/idl/Accessibility_Registry.idl +++ b/idl/Accessibility_Registry.idl @@ -66,7 +66,7 @@ module Accessibility { * **/ void registerGlobalEventListener (in EventListener listener, - in string eventName); + in string eventName); /** * deregisterGlobalEventListener: diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index 23587fa..04586e0 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -26,17 +26,21 @@ #undef SPI_DEBUG -#ifdef SPI_DEBUG -# include -#endif +#include +#include +#include +#include #include #include #define XK_MISCELLANY #include +#include #include /* TODO: hide dependency (wrap in single porting file) */ +#include #include +#include "../libspi/spi-private.h" #include "deviceeventcontroller.h" /* Our parent Gtk object type */ @@ -45,124 +49,94 @@ /* A pointer to our parent object class */ static GObjectClass *spi_device_event_controller_parent_class; -static gboolean kbd_registered = FALSE; - -static Window root_window; - typedef enum { SPI_DEVICE_TYPE_KBD, - SPI_DEVICE_TYPE_MOUSE, SPI_DEVICE_TYPE_LAST_DEFINED } SpiDeviceTypeCategory; -struct _DEControllerGrabMask { - Accessibility_ControllerEventMask modmask; - CORBA_unsigned_long keyval; - unsigned int refcount; -}; +typedef struct { + guint ref_count : 30; + guint pending_add : 1; + guint pending_remove : 1; -typedef struct _DEControllerGrabMask DEControllerGrabMask; + Accessibility_ControllerEventMask mod_mask; + CORBA_unsigned_long key_val; /* KeyCode */ +} DEControllerGrabMask; -struct _DEControllerListener { +typedef struct { CORBA_Object object; SpiDeviceTypeCategory type; -}; +} DEControllerListener; -typedef struct _DEControllerListener DEControllerListener; - -struct _DEControllerKeyListener { +typedef struct { DEControllerListener listener; - Accessibility_KeySet *keys; - Accessibility_ControllerEventMask mask; - Accessibility_KeyEventTypeSeq *typeseq; - Accessibility_EventListenerMode *mode; -}; -typedef struct _DEControllerKeyListener DEControllerKeyListener; + Accessibility_KeySet *keys; + Accessibility_ControllerEventMask mask; + Accessibility_KeyEventTypeSeq *typeseq; + Accessibility_EventListenerMode *mode; +} DEControllerKeyListener; -static gboolean spi_controller_register_with_devices (SpiDeviceEventController *controller); -static gboolean spi_controller_grab_keyboard (SpiDeviceEventController *controller); +static void spi_controller_register_with_devices (SpiDEController *controller); +static gboolean spi_controller_update_key_grabs (SpiDEController *controller, + Accessibility_DeviceEvent *recv); +static void spi_controller_register_device_listener (SpiDEController *controller, + DEControllerListener *l, + CORBA_Environment *ev); +static void spi_device_event_controller_forward_key_event (SpiDEController *controller, + const XEvent *event); -static void spi_controller_register_device_listener (SpiDeviceEventController *controller, - DEControllerListener *l, - CORBA_Environment *ev); +/* Private methods */ -/* - * Private methods - */ - -static Display * -spi_get_display (void ) +static KeyCode +keycode_for_keysym (long keysym) { - static Display *display = NULL; - /* We must open a new connection to the server to avoid clashing with the GDK event loop */ - /* - * TODO: fixme, this makes the foolish assumption that registryd uses - * the same display as the apps, and the the DISPLAY environment variable is set. - */ - - if (!display) - { - display = XOpenDisplay (g_getenv ("DISPLAY")); - } - return display; + return XKeysymToKeycode (GDK_DISPLAY (), (KeySym) keysym); } static DEControllerGrabMask * -spi_grabmask_clone (DEControllerGrabMask *grabmask) +spi_grab_mask_clone (DEControllerGrabMask *grab_mask) { - DEControllerGrabMask *clone = g_new0 (DEControllerGrabMask, 1); - memcpy (clone, grabmask, sizeof (DEControllerGrabMask)); - return clone; -} + DEControllerGrabMask *clone = g_new (DEControllerGrabMask, 1); -static gint -spi_compare_corba_objects (gconstpointer p1, gconstpointer p2) -{ - CORBA_Environment ev; - gint retval; - retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev); + memcpy (clone, grab_mask, sizeof (DEControllerGrabMask)); -#ifdef SPI_DEBUG - fprintf (stderr, "comparing %p to %p; result %d\n", - p1, p2, - retval); -#endif - return retval; + clone->ref_count = 1; + clone->pending_add = TRUE; + clone->pending_remove = FALSE; + + return clone; } -static gint -spi_compare_listeners (gconstpointer p1, gconstpointer p2) +static void +spi_grab_mask_free (DEControllerGrabMask *grab_mask) { - DEControllerListener *l1 = (DEControllerListener *) p1; - DEControllerListener *l2 = (DEControllerListener *) p2; - return spi_compare_corba_objects (l1->object, l2->object); + g_free (grab_mask); } static gint -spi_grabmask_compare_values (gconstpointer p1, gconstpointer p2) +spi_grab_mask_compare_values (gconstpointer p1, gconstpointer p2) { - DEControllerGrabMask *l1; - DEControllerGrabMask *l2; + DEControllerGrabMask *l1 = (DEControllerGrabMask *) p1; + DEControllerGrabMask *l2 = (DEControllerGrabMask *) p2; + if (p1 == p2) { return 0; } else { - l1 = (DEControllerGrabMask *) p1; - l2 = (DEControllerGrabMask *) p2; - return ((l1->modmask != l2->modmask) || (l1->keyval != l2->keyval)); + return ((l1->mod_mask != l2->mod_mask) || (l1->key_val != l2->key_val)); } } static DEControllerKeyListener * -spi_dec_key_listener_new (CORBA_Object l, - const Accessibility_KeySet *keys, +spi_dec_key_listener_new (CORBA_Object l, + const Accessibility_KeySet *keys, const Accessibility_ControllerEventMask mask, - const Accessibility_KeyEventTypeSeq *typeseq, - const Accessibility_EventListenerMode *mode, - CORBA_Environment *ev) + const Accessibility_KeyEventTypeSeq *typeseq, + const Accessibility_EventListenerMode *mode, + CORBA_Environment *ev) { DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1); key_listener->listener.object = bonobo_object_dup_ref (l, ev); @@ -176,16 +150,19 @@ spi_dec_key_listener_new (CORBA_Object l, key_listener->mode = NULL; #ifdef SPI_DEBUG - g_print ("new listener, with mask %x, is_global %d, keys %p\n", + g_print ("new listener, with mask %x, is_global %d, keys %p (%d)\n", (unsigned int) key_listener->mask, - (int) mode->global, - (void *) key_listener->keys); + (int) (mode ? mode->global : 0), + (void *) key_listener->keys, + (int) (key_listener->keys ? key_listener->keys->_length : 0)); #endif + return key_listener; } static void -spi_dec_key_listener_free (DEControllerKeyListener *key_listener, CORBA_Environment *ev) +spi_dec_key_listener_free (DEControllerKeyListener *key_listener, + CORBA_Environment *ev) { bonobo_object_release_unref (key_listener->listener.object, ev); CORBA_free (key_listener->typeseq); @@ -194,156 +171,173 @@ spi_dec_key_listener_free (DEControllerKeyListener *key_listener, CORBA_Environm } static void -spi_controller_deregister_global_keygrabs (SpiDeviceEventController *controller, - DEControllerKeyListener *key_listener) +_register_keygrab (SpiDEController *controller, + DEControllerGrabMask *grab_mask) +{ + GList *l; + + l = g_list_find_custom (controller->keygrabs_list, grab_mask, + spi_grab_mask_compare_values); + if (l) + { + DEControllerGrabMask *cur_mask = l->data; + + cur_mask->ref_count++; + if (cur_mask->pending_remove) + { + cur_mask->pending_remove = FALSE; + } + } + else + { + controller->keygrabs_list = + g_list_prepend (controller->keygrabs_list, + spi_grab_mask_clone (grab_mask)); + } +} + +static void +_deregister_keygrab (SpiDEController *controller, + DEControllerGrabMask *grab_mask) { - GList *list_ptr; - DEControllerGrabMask *mask_ptr; - /* TODO: implement this! Also remember to release any keygrabs still held */ - ; + GList *l; + + l = g_list_find_custom (controller->keygrabs_list, grab_mask, + spi_grab_mask_compare_values); + + if (l) + { + DEControllerGrabMask *cur_mask = l->data; + + cur_mask->ref_count--; + cur_mask->pending_remove = TRUE; + } + else + { + g_warning ("De-registering non-existant grab"); + } } static void -spi_controller_register_global_keygrabs (SpiDeviceEventController *controller, - DEControllerKeyListener *key_listener) +handle_keygrab (SpiDEController *controller, + DEControllerKeyListener *key_listener, + void (*process_cb) (SpiDEController *controller, + DEControllerGrabMask *grab_mask)) { - DEControllerGrabMask grabmask, *grabmask_ptr; - GList *list_ptr; - gint i; - /* TODO: deregistration version of this function */ - - grabmask.modmask = key_listener->mask; + DEControllerGrabMask grab_mask = { 0 }; + + grab_mask.mod_mask = key_listener->mask; if (key_listener->keys->_length == 0) /* special case means AnyKey/AllKeys */ { - grabmask.keyval = AnyKey; - list_ptr = g_list_find_custom (controller->keygrabs_list, &grabmask, - spi_grabmask_compare_values); - if (list_ptr) - { - grabmask_ptr = (DEControllerGrabMask *) list_ptr->data; - grabmask_ptr->refcount++; - } - else - { - controller->keygrabs_list = - g_list_prepend (controller->keygrabs_list, - spi_grabmask_clone (&grabmask)); - } + grab_mask.key_val = AnyKey; + process_cb (controller, &grab_mask); } else { + int i; + for (i = 0; i < key_listener->keys->_length; ++i) { - long int keyval = key_listener->keys->_buffer[i]; + long int key_val = key_listener->keys->_buffer[i]; /* X Grabs require keycodes, not keysyms */ - if (keyval >= 0) + if (key_val >= 0) { - keyval = XKeysymToKeycode(spi_get_display (), (KeySym) keyval); + key_val = XKeysymToKeycode (GDK_DISPLAY (), (KeySym) key_val); } - grabmask.keyval = keyval; - list_ptr = g_list_find_custom (controller->keygrabs_list, &grabmask, - spi_grabmask_compare_values); - if (list_ptr) - { - grabmask_ptr = (DEControllerGrabMask *) list_ptr->data; - grabmask_ptr->refcount++; - } - else - { - controller->keygrabs_list = - g_list_prepend (controller->keygrabs_list, - spi_grabmask_clone (&grabmask)); - fprintf (stderr, "appending mask with val=%lu\n", - (unsigned long) grabmask.modmask); - } - } + grab_mask.key_val = key_val; + + process_cb (controller, &grab_mask); + } } } static void -spi_controller_register_device_listener (SpiDeviceEventController *controller, +spi_controller_register_global_keygrabs (SpiDEController *controller, + DEControllerKeyListener *key_listener) +{ + handle_keygrab (controller, key_listener, _register_keygrab); + spi_controller_update_key_grabs (controller, NULL); +} + +static void +spi_controller_deregister_global_keygrabs (SpiDEController *controller, + DEControllerKeyListener *key_listener) +{ + handle_keygrab (controller, key_listener, _deregister_keygrab); + spi_controller_update_key_grabs (controller, NULL); +} + +static void +spi_controller_register_device_listener (SpiDEController *controller, DEControllerListener *listener, - CORBA_Environment *ev) + CORBA_Environment *ev) { DEControllerKeyListener *key_listener; switch (listener->type) { case SPI_DEVICE_TYPE_KBD: - key_listener = (DEControllerKeyListener *) listener; - controller->key_listeners = g_list_prepend (controller->key_listeners, key_listener); + key_listener = (DEControllerKeyListener *) listener; + + controller->key_listeners = g_list_prepend (controller->key_listeners, + key_listener); if (key_listener->mode->global) { spi_controller_register_global_keygrabs (controller, key_listener); } break; - case SPI_DEVICE_TYPE_MOUSE: -/* controller->mouse_listeners = g_list_append (controller->mouse_listeners, - CORBA_Object_duplicate (l, ev));*/ - -/* this interface should only be used for mouse motion events, not mouse clicks events */ + default: break; } } -static void -spi_controller_deregister_device_listener (SpiDeviceEventController *controller, - DEControllerListener *listener, - CORBA_Environment *ev) -{ - Accessibility_ControllerEventMask *mask_ptr; - DEControllerListener *dec_listener; - GList *list_ptr; - switch (listener->type) - { - case SPI_DEVICE_TYPE_KBD: - spi_controller_deregister_global_keygrabs (controller, - (DEControllerKeyListener *) listener); +static GdkFilterReturn +global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) +{ + XEvent *xevent = gdk_xevent; + SpiDEController *controller; - /* now, remove this listener from the keylistener list */ - list_ptr = g_list_find_custom (controller->key_listeners, listener, spi_compare_listeners); - if (list_ptr) - { - dec_listener = (DEControllerListener *) list_ptr->data; -#ifdef SPI_DEBUG - g_print ("removing keylistener %p\n", dec_listener->object); -#endif - controller->key_listeners = g_list_remove_link (controller->key_listeners, - list_ptr); - spi_dec_key_listener_free ((DEControllerKeyListener *) dec_listener, ev); - } - break; - case SPI_DEVICE_TYPE_MOUSE: /* TODO: implement */ - break; + if (xevent->type != KeyPress && xevent->type != KeyRelease) + { + return GDK_FILTER_CONTINUE; } + + controller = SPI_DEVICE_EVENT_CONTROLLER (data); + + spi_device_event_controller_forward_key_event (controller, xevent); + + /* FIXME: is this right ? */ + return GDK_FILTER_CONTINUE; } -static gboolean -spi_controller_register_with_devices (SpiDeviceEventController *controller) +static void +spi_controller_register_with_devices (SpiDEController *controller) { - gboolean retval = FALSE; - /* calls to device-specific implementations and routines go here */ /* register with: keyboard hardware code handler */ /* register with: (translated) keystroke handler */ - /* We must open a new connection to the server to avoid clashing with the GDK event loop */ - root_window = DefaultRootWindow (spi_get_display ()); - XSelectInput (spi_get_display (), - root_window, + gdk_window_add_filter (NULL, global_filter_fn, controller); + + gdk_window_set_events (gdk_get_default_root_window (), + GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); + + XSelectInput (GDK_DISPLAY (), + DefaultRootWindow (GDK_DISPLAY ()), KeyPressMask | KeyReleaseMask); - /* register with: mouse hardware device handler? */ - /* register with: mouse event handler */ - return retval; } static gboolean -spi_key_set_contains_key (Accessibility_KeySet *key_set, const Accessibility_DeviceEvent *key_event) +spi_key_set_contains_key (Accessibility_KeySet *key_set, + const Accessibility_DeviceEvent *key_event) { gint i; gint len; - /* g_assert (key_set); */ - if (!key_set) { g_print ("null key set!"); return TRUE; } + if (!key_set) + { + g_print ("null key set!"); + return TRUE; + } len = key_set->_length; @@ -353,17 +347,21 @@ spi_key_set_contains_key (Accessibility_KeySet *key_set, const Accessibility_Dev return TRUE; } - for (i=0; i_buffer[i], - (int) key_event->id, - (int) key_event->hw_code); + i, (int) key_set->_buffer[i], + (int) key_event->id, (int) key_event->hw_code); #endif - if (key_set->_buffer[i] == (CORBA_long) key_event->id) return TRUE; - if (key_set->_buffer[i] == (CORBA_long) -key_event->hw_code) return TRUE; + if (key_set->_buffer[i] == (CORBA_long) key_event->id) + { + return TRUE; + } + if (key_set->_buffer[i] == (CORBA_long) -key_event->hw_code) + { + return TRUE; + } } return FALSE; @@ -376,8 +374,12 @@ spi_key_eventtype_seq_contains_event (Accessibility_KeyEventTypeSeq *type_seq, gint i; gint len; - /* g_assert (type_seq); */ - if (!type_seq) { g_print ("null type seq!"); return TRUE; } + + if (!type_seq) + { + g_print ("null type seq!"); + return TRUE; + } len = type_seq->_length; @@ -386,13 +388,16 @@ spi_key_eventtype_seq_contains_event (Accessibility_KeyEventTypeSeq *type_seq, return TRUE; } - for (i=0; i_buffer[i], - (int) key_event->type); + g_print ("type_seq[%d] = %d; key event type = %d\n", i, + (int) type_seq->_buffer[i], (int) key_event->type); #endif - if (type_seq->_buffer[i] == (CORBA_long) key_event->type) return TRUE; + if (type_seq->_buffer[i] == (CORBA_long) key_event->type) + { + return TRUE; + } } return FALSE; @@ -403,7 +408,6 @@ spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event, DEControllerKeyListener *listener, CORBA_boolean is_system_global) { - g_print ("checking keycode %d\n", (int) key_event->hw_code); if ((key_event->modifiers == (CORBA_unsigned_short) (listener->mask & 0xFFFF)) && spi_key_set_contains_key (listener->keys, key_event) && spi_key_eventtype_seq_contains_event (listener->typeseq, key_event) && @@ -412,39 +416,71 @@ spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event, return TRUE; } else - return FALSE; + { + return FALSE; + } } static gboolean -spi_notify_keylisteners (GList *key_listeners, +spi_notify_keylisteners (GList **key_listeners, const Accessibility_DeviceEvent *key_event, - CORBA_boolean is_system_global, - CORBA_Environment *ev) + CORBA_boolean is_system_global, + CORBA_Environment *ev) { - int i, n_listeners = g_list_length (key_listeners); - gboolean is_consumed = FALSE; + GList *l; + GSList *notify = NULL, *l2; + gboolean is_consumed; - for (i=0; ilistener.object; - if (spi_key_event_matches_listener (key_event, key_listener, is_system_global)) - { - if (!CORBA_Object_is_nil(ls, ev)) - { - is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, key_event, ev); - } - } - else - { + return FALSE; + } + + for (l = *key_listeners; l; l = l->next) + { + DEControllerKeyListener *key_listener = l->data; + + if (spi_key_event_matches_listener (key_event, key_listener, is_system_global)) + { + Accessibility_DeviceEventListener ls = key_listener->listener.object; + + if (ls != CORBA_OBJECT_NIL) + { + notify = g_slist_prepend (notify, CORBA_Object_duplicate (ls, ev)); + } + } + } + #ifdef SPI_KEYEVENT_DEBUG - g_print ("no match for listener %d\n", i); + if (!notify) + { + g_print ("no match for listener %d\n", i); + } #endif - ; - } + + is_consumed = FALSE; + for (l2 = notify; l2 && !is_consumed; l2 = l2->next) + { + Accessibility_DeviceEventListener ls = l2->data; + + is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, key_event, ev); + + if (BONOBO_EX (ev)) + { + is_consumed = FALSE; + CORBA_exception_free (ev); + } + + CORBA_Object_release (ls, ev); + } + + for (; l2; l2 = l2->next) + { + CORBA_Object_release (l2->data, ev); } + + g_slist_free (notify); + return is_consumed; } @@ -515,95 +551,86 @@ spi_keystroke_from_x_key_event (XKeyEvent *x_key_event) return key_event; } - static gboolean -spi_check_key_event (SpiDeviceEventController *controller) -{ - static gboolean initialized = FALSE; - XEvent *x_event = g_new0 (XEvent, 1); - XKeyEvent *x_key_event; - gboolean is_consumed = FALSE; - Accessibility_DeviceEvent key_event; - static CORBA_Environment ev; - - if (!initialized) - { - initialized = TRUE; - CORBA_exception_init (&ev); - } +spi_controller_update_key_grabs (SpiDEController *controller, + Accessibility_DeviceEvent *recv) +{ + GList *l, *next; - while (XPending(spi_get_display ())) - { - XNextEvent (spi_get_display (), x_event); - if (XFilterEvent (x_event, None)) continue; - if (x_event->type == KeyPress || x_event->type == KeyRelease) - { - key_event = spi_keystroke_from_x_key_event ((XKeyEvent *) x_event); - /* relay to listeners, and decide whether to consume it or not */ - is_consumed = spi_notify_keylisteners (controller->key_listeners, &key_event, CORBA_TRUE, &ev); - } - else - { -#ifdef SPI_KEYEVENT_DEBUG - fprintf (stderr, "other event, type %d\n", (int) x_event->type); -#endif - } + g_return_val_if_fail (controller != NULL, FALSE); - if (is_consumed) - { - XAllowEvents (spi_get_display (), AsyncKeyboard, CurrentTime); - } - else - { - XAllowEvents (spi_get_display (), ReplayKeyboard, CurrentTime); - } - } - XUngrabKey (spi_get_display (), AnyKey, AnyModifier, root_window); + /* + * 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 (l = controller->keygrabs_list; l; l = next) + { + gboolean do_remove; + gboolean re_issue_grab; + DEControllerGrabMask *grab_mask = l->data; - return spi_controller_grab_keyboard (controller); -} + next = l->next; -static gboolean -spi_controller_grab_keyboard (SpiDeviceEventController *controller) -{ - GList *maskList = controller->keygrabs_list; - int i; - int last_mask; - last_mask = g_list_length (maskList); + re_issue_grab = recv && + (recv->modifiers & grab_mask->mod_mask) && + (grab_mask->key_val == keycode_for_keysym (recv->id)); -/* - * 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) - { - DEControllerGrabMask * grab_mask - = (DEControllerGrabMask *) g_list_nth_data (maskList, i); - unsigned long maskVal = 0xFFFFFFFF; - int keyVal = AnyKey; - if (grab_mask) - { - maskVal = (unsigned long) grab_mask->modmask; - keyVal = grab_mask->keyval; - } #ifdef SPI_DEBUG - fprintf (stderr, "mask=%lx\n", maskVal); + fprintf (stderr, "mask=%lx %lx (%c%c) %s\n", + (long int) grab_mask->key_val, + (long int) grab_mask->mod_mask, + grab_mask->pending_add ? '+' : '.', + grab_mask->pending_remove ? '-' : '.', + re_issue_grab ? "re-issue": ""); #endif - XGrabKey (spi_get_display (), - keyVal, - maskVal, - root_window, - True, - GrabModeAsync, - GrabModeAsync); - /* TODO: check call for errors and return FALSE if error occurs */ + + do_remove = FALSE; + + if (grab_mask->pending_add && grab_mask->pending_remove) + { + do_remove = TRUE; + } + else if (grab_mask->pending_remove) + { + XUngrabKey (GDK_DISPLAY (), + grab_mask->key_val, + grab_mask->mod_mask, + gdk_x11_get_default_root_xwindow ()); + + do_remove = TRUE; + } + else if (grab_mask->pending_add || re_issue_grab) + { + XGrabKey (GDK_DISPLAY (), + grab_mask->key_val, + grab_mask->mod_mask, + gdk_x11_get_default_root_xwindow (), + True, + GrabModeAsync, + GrabModeAsync); + } + + grab_mask->pending_add = FALSE; + grab_mask->pending_remove = FALSE; + + if (do_remove) + { + g_assert (grab_mask->ref_count <= 0); + + controller->keygrabs_list = g_list_delete_link ( + controller->keygrabs_list, l); + + spi_grab_mask_free (grab_mask); + } + + /* TODO: check calls for errors and return FALSE if error occurs */ } + return TRUE; } @@ -613,6 +640,9 @@ spi_controller_grab_keyboard (SpiDeviceEventController *controller) static void spi_device_event_controller_object_finalize (GObject *object) { + SpiDEController *controller; + + controller = SPI_DEVICE_EVENT_CONTROLLER (object); #ifdef SPI_DEBUG fprintf(stderr, "spi_device_event_controller_object_finalize called\n"); @@ -623,19 +653,19 @@ spi_device_event_controller_object_finalize (GObject *object) } /* - * CORBA Accessibility::DeviceEventController::registerKeystrokeListener + * CORBA Accessibility::DEController::registerKeystrokeListener * method implementation */ static void -impl_register_keystroke_listener (PortableServer_Servant servant, +impl_register_keystroke_listener (PortableServer_Servant servant, const Accessibility_DeviceEventListener l, - const Accessibility_KeySet *keys, + const Accessibility_KeySet *keys, const Accessibility_ControllerEventMask mask, - const Accessibility_KeyEventTypeSeq *type, - const Accessibility_EventListenerMode *mode, - CORBA_Environment *ev) + const Accessibility_KeyEventTypeSeq *type, + const Accessibility_EventListenerMode *mode, + CORBA_Environment *ev) { - SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER ( + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER ( bonobo_object_from_servant (servant)); DEControllerKeyListener *dec_listener; #ifdef SPI_DEBUG @@ -643,80 +673,85 @@ impl_register_keystroke_listener (PortableServer_Servant servant, (void *) l, (unsigned long) mask); #endif dec_listener = spi_dec_key_listener_new (l, keys, mask, type, mode, ev); - spi_controller_register_device_listener (controller, (DEControllerListener *) dec_listener, ev); + spi_controller_register_device_listener ( + controller, (DEControllerListener *) dec_listener, ev); +} + + +typedef struct { + CORBA_Environment *ev; + DEControllerKeyListener *key_listener; +} RemoveKeyListenerClosure; + +static SpiReEnterantContinue +remove_key_listener_cb (GList * const *list, + gpointer user_data) +{ + DEControllerKeyListener *key_listener = (*list)->data; + RemoveKeyListenerClosure *ctx = user_data; + + if (CORBA_Object_is_equivalent (ctx->key_listener->listener.object, + key_listener->listener.object, ctx->ev)) + { + spi_re_enterant_list_delete_link (list); + spi_dec_key_listener_free (key_listener, ctx->ev); + } + + return SPI_RE_ENTERANT_CONTINUE; } /* - * CORBA Accessibility::DeviceEventController::deregisterKeystrokeListener + * CORBA Accessibility::DEController::deregisterKeystrokeListener * method implementation */ static void -impl_deregister_keystroke_listener (PortableServer_Servant servant, +impl_deregister_keystroke_listener (PortableServer_Servant servant, const Accessibility_DeviceEventListener l, - const Accessibility_KeySet *keys, + const Accessibility_KeySet *keys, const Accessibility_ControllerEventMask mask, - const Accessibility_KeyEventTypeSeq *type, - CORBA_Environment *ev) -{ - SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER ( - bonobo_object_from_servant (servant)); - DEControllerKeyListener *key_listener = spi_dec_key_listener_new (l, - keys, - mask, - type, - NULL, - ev); + const Accessibility_KeyEventTypeSeq *type, + CORBA_Environment *ev) +{ + DEControllerKeyListener *key_listener; + RemoveKeyListenerClosure ctx; + SpiDEController *controller; + + controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant)); + + key_listener = spi_dec_key_listener_new (l, keys, mask, type, NULL, ev); + #ifdef SPI_DEREGISTER_DEBUG - fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n", - (void *) l, (unsigned long) mask->value); + fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n", + (void *) l, (unsigned long) mask->value); #endif - spi_controller_deregister_device_listener(controller, - (DEControllerListener *) key_listener, - ev); - spi_dec_key_listener_free (key_listener, ev); -} -/* - * CORBA Accessibility::DeviceEventController::registerMouseListener - * method implementation - */ -/* -static void -impl_register_mouse_listener (PortableServer_Servant servant, - const Accessibility_MouseListener *l, - CORBA_Environment *ev) -{ - SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER ( - bonobo_object_from_servant (servant)); -#ifdef SPI_DEBUG - fprintf (stderr, "registering mouse listener %p\n", l); -#endif - spi_controller_register_device_listener(controller, DEVICE_TYPE_MOUSE, l, keys, mask, ev); -} -*/ + spi_controller_deregister_global_keygrabs (controller, key_listener); -static KeyCode -keycode_for_keysym (long keysym) -{ - return XKeysymToKeycode (spi_get_display (), (KeySym) keysym); -} + ctx.ev = ev; + ctx.key_listener = key_listener; -#define SPI_DEBUG + spi_re_enterant_list_foreach (&controller->key_listeners, + remove_key_listener_cb, &ctx); + + spi_dec_key_listener_free (key_listener, ev); +} /* - * CORBA Accessibility::DeviceEventController::registerKeystrokeListener + * CORBA Accessibility::DEController::registerKeystrokeListener * method implementation */ static void -impl_generate_keyboard_event (PortableServer_Servant servant, - const CORBA_long keycode, - const CORBA_char *keystring, +impl_generate_keyboard_event (PortableServer_Servant servant, + const CORBA_long keycode, + const CORBA_char *keystring, const Accessibility_KeySynthType synth_type, - CORBA_Environment *ev) + CORBA_Environment *ev) { long key_synth_code; + #ifdef SPI_DEBUG - fprintf (stderr, "synthesizing keystroke %ld, type %d\n", (long) keycode, (int) synth_type); + fprintf (stderr, "synthesizing keystroke %ld, type %d\n", + (long) keycode, (int) synth_type); #endif /* TODO: hide/wrap/remove X dependency */ @@ -728,26 +763,34 @@ impl_generate_keyboard_event (PortableServer_Servant servant, */ /* TODO: implement keystring mode also */ - + gdk_error_trap_push (); + switch (synth_type) { case Accessibility_KEY_PRESS: - XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, True, CurrentTime); - break; + XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, True, CurrentTime); + break; case Accessibility_KEY_PRESSRELEASE: - XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, True, CurrentTime); + XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, True, CurrentTime); case Accessibility_KEY_RELEASE: - XTestFakeKeyEvent (spi_get_display (), (unsigned int) keycode, False, CurrentTime); - break; + XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) keycode, False, CurrentTime); + break; case Accessibility_KEY_SYM: - key_synth_code = keycode_for_keysym (keycode); - XTestFakeKeyEvent (spi_get_display (), (unsigned int) key_synth_code, True, CurrentTime); - XTestFakeKeyEvent (spi_get_display (), (unsigned int) key_synth_code, False, CurrentTime); - break; - } + key_synth_code = keycode_for_keysym (keycode); + XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) key_synth_code, True, CurrentTime); + XTestFakeKeyEvent (GDK_DISPLAY (), (unsigned int) key_synth_code, False, CurrentTime); + break; + case Accessibility_KEY_STRING: + fprintf (stderr, "Not yet implemented\n"); + break; + } + if (gdk_error_trap_pop ()) + { + g_warning ("Error emitting keystroke"); + } } -/* Accessibility::DeviceEventController::generateMouseEvent */ +/* Accessibility::DEController::generateMouseEvent */ static void impl_generate_mouse_event (PortableServer_Servant servant, const CORBA_long x, @@ -756,90 +799,121 @@ impl_generate_mouse_event (PortableServer_Servant servant, CORBA_Environment *ev) { #ifdef SPI_DEBUG - fprintf (stderr, "generating mouse %s event at %ld, %ld\n", eventName, x, y); + fprintf (stderr, "generating mouse %s event at %ld, %ld\n", + eventName, (long int) x, (long int) y); #endif + g_warning ("not yet implemented"); } -/* Accessibility::DeviceEventController::notifyListenersSync */ +/* Accessibility::DEController::notifyListenersSync */ static CORBA_boolean -impl_notify_listeners_sync(PortableServer_Servant servant, - const Accessibility_DeviceEvent *event, - CORBA_Environment *ev) +impl_notify_listeners_sync (PortableServer_Servant servant, + const Accessibility_DeviceEvent *event, + CORBA_Environment *ev) { - SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER ( - bonobo_object_from_servant (servant)); + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER ( + bonobo_object_from_servant (servant)); #ifdef SPI_DEBUG - g_print ("notifylistening listeners synchronously: controller %x, event id %d\n", - (void *) controller, (int) event->id); + g_print ("notifylistening listeners synchronously: controller %p, event id %d\n", + controller, (int) event->id); #endif - return (spi_notify_keylisteners (controller->key_listeners, event, CORBA_FALSE, ev) ? - CORBA_TRUE : CORBA_FALSE); + return spi_notify_keylisteners (&controller->key_listeners, event, CORBA_FALSE, ev) ? + CORBA_TRUE : CORBA_FALSE; } -/* Accessibility::DeviceEventController::notifyListenersAsync */ +/* Accessibility::DEController::notifyListenersAsync */ static void -impl_notify_listeners_async (PortableServer_Servant servant, +impl_notify_listeners_async (PortableServer_Servant servant, const Accessibility_DeviceEvent *event, - CORBA_Environment *ev) + CORBA_Environment *ev) { - SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER( - bonobo_object_from_servant (servant)); + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER ( + bonobo_object_from_servant (servant)); #ifdef SPI_DEBUG fprintf (stderr, "notifying listeners asynchronously\n"); #endif - spi_notify_keylisteners (controller->key_listeners, event, CORBA_FALSE, ev); + spi_notify_keylisteners (&controller->key_listeners, event, CORBA_FALSE, ev); } static void -spi_device_event_controller_class_init (SpiDeviceEventControllerClass *klass) +spi_device_event_controller_class_init (SpiDEControllerClass *klass) { - GObjectClass * object_class = (GObjectClass *) klass; - POA_Accessibility_DeviceEventController__epv *epv = &klass->epv; - spi_device_event_controller_parent_class = g_type_class_peek_parent (klass); - - object_class->finalize = spi_device_event_controller_object_finalize; + GObjectClass * object_class = (GObjectClass *) klass; + POA_Accessibility_DeviceEventController__epv *epv = &klass->epv; - epv->registerKeystrokeListener = impl_register_keystroke_listener; - epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener; -/* epv->registerMouseListener = impl_register_mouse_listener; */ - epv->generateKeyboardEvent = impl_generate_keyboard_event; - epv->generateMouseEvent = impl_generate_mouse_event; - epv->notifyListenersSync = impl_notify_listeners_sync; - epv->notifyListenersAsync = impl_notify_listeners_async; - klass->check_key_event = spi_check_key_event; + spi_device_event_controller_parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = spi_device_event_controller_object_finalize; + + epv->registerKeystrokeListener = impl_register_keystroke_listener; + epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener; + epv->generateKeyboardEvent = impl_generate_keyboard_event; + epv->generateMouseEvent = impl_generate_mouse_event; + epv->notifyListenersSync = impl_notify_listeners_sync; + epv->notifyListenersAsync = impl_notify_listeners_async; } static void -spi_device_event_controller_init (SpiDeviceEventController *device_event_controller) +spi_device_event_controller_init (SpiDEController *device_event_controller) { - device_event_controller->key_listeners = NULL; + device_event_controller->key_listeners = NULL; device_event_controller->mouse_listeners = NULL; - device_event_controller->keygrabs_list = NULL; - kbd_registered = spi_controller_register_with_devices (device_event_controller); + device_event_controller->keygrabs_list = NULL; + + /* + * TODO: fixme, this module makes the foolish assumptions that + * registryd uses the same display as the apps, and that the + * DISPLAY environment variable is set. + */ + gdk_init (NULL, NULL); + + spi_controller_register_with_devices (device_event_controller); } -gboolean -spi_device_event_controller_check_key_event (SpiDeviceEventController *controller) +static void +spi_device_event_controller_forward_key_event (SpiDEController *controller, + const XEvent *event) { - SpiDeviceEventControllerClass *klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); - if (klass->check_key_event) - return (klass->check_key_event) (controller); - return FALSE; + gboolean is_consumed = FALSE; + CORBA_Environment ev; + Accessibility_DeviceEvent key_event; + + g_assert (event->type == KeyPress || event->type == KeyRelease); + + CORBA_exception_init (&ev); + + key_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event); + /* relay to listeners, and decide whether to consume it or not */ + is_consumed = spi_notify_keylisteners ( + &controller->key_listeners, &key_event, CORBA_TRUE, &ev); + + CORBA_exception_free (&ev); + + if (is_consumed) + { + XAllowEvents (GDK_DISPLAY (), AsyncKeyboard, CurrentTime); + } + else + { + XAllowEvents (GDK_DISPLAY (), ReplayKeyboard, CurrentTime); + } + + spi_controller_update_key_grabs (controller, &key_event); } -SpiDeviceEventController * -spi_device_event_controller_new (void *registryp) +SpiDEController * +spi_device_event_controller_new (SpiRegistry *registry) { - BonoboObject *registry = (BonoboObject *) registryp; - SpiDeviceEventController *retval = g_object_new ( - SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL); - retval->registry = registry; - bonobo_object_ref (registry); + SpiDEController *retval = g_object_new ( + SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL); + + retval->registry = SPI_REGISTRY (bonobo_object_ref ( + BONOBO_OBJECT (registry))); + return retval; } -BONOBO_TYPE_FUNC_FULL (SpiDeviceEventController, +BONOBO_TYPE_FUNC_FULL (SpiDEController, Accessibility_DeviceEventController, PARENT_TYPE, spi_device_event_controller); - diff --git a/registryd/deviceeventcontroller.h b/registryd/deviceeventcontroller.h index a943063..8431193 100644 --- a/registryd/deviceeventcontroller.h +++ b/registryd/deviceeventcontroller.h @@ -27,32 +27,36 @@ #include #include +typedef struct _SpiDEController SpiDEController; + +#include "registry.h" + G_BEGIN_DECLS #define SPI_DEVICE_EVENT_CONTROLLER_TYPE (spi_device_event_controller_get_type ()) -#define SPI_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDeviceEventController)) -#define SPI_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDeviceEventControllerClass)) +#define SPI_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDEController)) +#define SPI_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDEControllerClass)) #define SPI_IS_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SPI_DEVICE_EVENT_CONTROLLER_TYPE)) #define SPI_IS_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_DEVICE_EVENT_CONTROLLER_TYPE)) -#define SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDeviceEventControllerClass)) +#define SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDEControllerClass)) -typedef struct { +struct _SpiDEController { BonoboObject parent; - void *registry; - GList *key_listeners; - GList *mouse_listeners; - GList *keygrabs_list; -} SpiDeviceEventController; + + SpiRegistry *registry; + GList *key_listeners; + GList *mouse_listeners; + GList *keygrabs_list; +}; typedef struct { BonoboObjectClass parent_class; + POA_Accessibility_DeviceEventController__epv epv; - gboolean (*check_key_event) (SpiDeviceEventController *controller); -} SpiDeviceEventControllerClass; +} SpiDEControllerClass; -GType spi_device_event_controller_get_type (void); -SpiDeviceEventController *spi_device_event_controller_new (void *registry); -gboolean spi_device_event_controller_check_key_event (SpiDeviceEventController *controller); +GType spi_device_event_controller_get_type (void); +SpiDEController *spi_device_event_controller_new (SpiRegistry *registry); G_END_DECLS diff --git a/registryd/registry-main.c b/registryd/registry-main.c index c3f5509..47ac78b 100644 --- a/registryd/registry-main.c +++ b/registryd/registry-main.c @@ -24,6 +24,7 @@ #include #endif +#include #include #include #include "registry.h" @@ -59,7 +60,6 @@ main (int argc, char **argv) #ifdef AT_SPI_DEBUG fprintf (stderr, "SpiRegistry Message: SpiRegistry daemon is running.\n"); #endif - g_timeout_add_full (G_PRIORITY_HIGH_IDLE, 200, registry->kbd_event_hook, registry, NULL); bonobo_main (); } diff --git a/registryd/registry.c b/registryd/registry.c index 50b6aeb..f05a6cd 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -30,6 +30,7 @@ #endif #include +#include "../libspi/spi-private.h" #include "registry.h" /* Our parent GObject type */ @@ -63,8 +64,6 @@ typedef struct { EventTypeCategory event_type_cat; } SpiListenerStruct; -/* static function prototypes */ -static gboolean _device_event_controller_hook (gpointer source); SpiListenerStruct * spi_listener_struct_new (Accessibility_EventListener listener, CORBA_Environment *ev) @@ -323,7 +322,9 @@ impl_accessibility_registry_register_global_event_listener ( EventTypeStruct etype; GList **list; - fprintf(stderr, "registering for events of type %s\n", event_name); +#ifdef SPI_DEBUG + fprintf (stderr, "registering for events of type %s\n", event_name); +#endif /* parse, check major event type and add listener accordingly */ parse_event_type (&etype, event_name); @@ -347,7 +348,7 @@ impl_accessibility_registry_register_global_event_listener ( } } -static void +static SpiReEnterantContinue remove_listener_cb (GList * const *list, gpointer user_data) { SpiListenerStruct *ls = (SpiListenerStruct *) (*list)->data; @@ -363,6 +364,8 @@ remove_listener_cb (GList * const *list, gpointer user_data) } CORBA_exception_free (&ev); + + return SPI_RE_ENTERANT_CONTINUE; } /* @@ -407,7 +410,7 @@ impl_accessibility_registry_deregister_global_event_listener ( parse_event_type (&etype, (char *) event_name); spi_re_enterant_list_foreach (get_listener_list (registry, etype.type_cat), - remove_listener_cb, listener); + remove_listener_cb, listener); } @@ -484,16 +487,16 @@ impl_accessibility_registry_get_desktop_list (PortableServer_Servant servant, static Accessibility_DeviceEventController impl_accessibility_registry_get_device_event_controller (PortableServer_Servant servant, - CORBA_Environment *ev) + CORBA_Environment *ev) { SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); - if (!registry->device_event_controller) + if (!registry->de_controller) { - registry->device_event_controller = spi_device_event_controller_new (registry); + registry->de_controller = spi_device_event_controller_new (registry); } - return bonobo_object_dup_ref (BONOBO_OBJREF (registry->device_event_controller), ev); + return bonobo_object_dup_ref (BONOBO_OBJREF (registry->de_controller), ev); } typedef struct { @@ -503,7 +506,7 @@ typedef struct { Accessibility_Event e_out; } NotifyContext; -static void +static SpiReEnterantContinue notify_listeners_cb (GList * const *list, gpointer user_data) { SpiListenerStruct *ls; @@ -531,7 +534,9 @@ notify_listeners_cb (GList * const *list, gpointer user_data) ctx->e_out.source = bonobo_object_dup_ref (ctx->source, ctx->ev); if (BONOBO_EX (ctx->ev)) - return; + { + return SPI_RE_ENTERANT_CONTINUE;; + } if ((*list) && (*list)->data == ls) { @@ -549,6 +554,8 @@ notify_listeners_cb (GList * const *list, gpointer user_data) bonobo_object_release_unref (ctx->e_out.source, ctx->ev); } } + + return SPI_RE_ENTERANT_CONTINUE; } static void @@ -582,37 +589,28 @@ impl_registry_notify_event (PortableServer_Servant servant, } } -static gboolean -_device_event_controller_hook (gpointer p) -{ - SpiRegistry *registry = (SpiRegistry *)p; - SpiDeviceEventController *controller = registry->device_event_controller; - if (controller) - spi_device_event_controller_check_key_event (controller); - return TRUE; -} static void spi_registry_class_init (SpiRegistryClass *klass) { - GObjectClass * object_class = (GObjectClass *) klass; - POA_Accessibility_Registry__epv *epv = &klass->epv; - - spi_registry_parent_class = g_type_class_ref (SPI_LISTENER_TYPE); - - object_class->finalize = spi_registry_object_finalize; + GObjectClass * object_class = (GObjectClass *) klass; + POA_Accessibility_Registry__epv *epv = &klass->epv; - epv->registerApplication = impl_accessibility_registry_register_application; - epv->deregisterApplication = impl_accessibility_registry_deregister_application; - epv->registerGlobalEventListener = impl_accessibility_registry_register_global_event_listener; - epv->deregisterGlobalEventListener = impl_accessibility_registry_deregister_global_event_listener; - epv->deregisterGlobalEventListenerAll = impl_accessibility_registry_deregister_global_event_listener_all; - epv->getDeviceEventController = impl_accessibility_registry_get_device_event_controller; - epv->getDesktopCount = impl_accessibility_registry_get_desktop_count; - epv->getDesktop = impl_accessibility_registry_get_desktop; - epv->getDesktopList = impl_accessibility_registry_get_desktop_list; + spi_registry_parent_class = g_type_class_ref (SPI_LISTENER_TYPE); + + object_class->finalize = spi_registry_object_finalize; - ((SpiListenerClass *) klass)->epv.notifyEvent = impl_registry_notify_event; + klass->parent_class.epv.notifyEvent = impl_registry_notify_event; + + epv->registerApplication = impl_accessibility_registry_register_application; + epv->deregisterApplication = impl_accessibility_registry_deregister_application; + epv->registerGlobalEventListener = impl_accessibility_registry_register_global_event_listener; + epv->deregisterGlobalEventListener = impl_accessibility_registry_deregister_global_event_listener; + epv->deregisterGlobalEventListenerAll = impl_accessibility_registry_deregister_global_event_listener_all; + epv->getDeviceEventController = impl_accessibility_registry_get_device_event_controller; + epv->getDesktopCount = impl_accessibility_registry_get_desktop_count; + epv->getDesktop = impl_accessibility_registry_get_desktop; + epv->getDesktopList = impl_accessibility_registry_get_desktop_list; } static void @@ -622,8 +620,7 @@ spi_registry_init (SpiRegistry *registry) registry->window_listeners = NULL; registry->toolkit_listeners = NULL; registry->desktop = spi_desktop_new (); - registry->device_event_controller = NULL; - registry->kbd_event_hook = _device_event_controller_hook; + registry->de_controller = NULL; } BONOBO_TYPE_FUNC_FULL (SpiRegistry, @@ -634,7 +631,7 @@ BONOBO_TYPE_FUNC_FULL (SpiRegistry, SpiRegistry * spi_registry_new (void) { - SpiRegistry *retval = g_object_new (SPI_REGISTRY_TYPE, NULL); - bonobo_object_set_immortal (BONOBO_OBJECT (retval), TRUE); - return retval; + SpiRegistry *retval = g_object_new (SPI_REGISTRY_TYPE, NULL); + bonobo_object_set_immortal (BONOBO_OBJECT (retval), TRUE); + return retval; } diff --git a/registryd/registry.h b/registryd/registry.h index e9789ee..d7109ef 100644 --- a/registryd/registry.h +++ b/registryd/registry.h @@ -26,6 +26,8 @@ #include #include +typedef struct _SpiRegistry SpiRegistry; + #include "desktop.h" #include "deviceeventcontroller.h" @@ -37,19 +39,20 @@ G_BEGIN_DECLS #define SPI_IS_REGISTRY(o) (G_TYPE_CHECK__INSTANCE_TYPE ((o), SPI_REGISTRY_TYPE)) #define SPI_IS_REGISTRY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_REGISTRY_TYPE)) -typedef struct { - SpiListener parent; - GList *object_listeners; - GList *window_listeners; - GList *toolkit_listeners; - SpiDeviceEventController *device_event_controller; - SpiDesktop *desktop; - gboolean (*kbd_event_hook) (gpointer source); -} SpiRegistry; +struct _SpiRegistry { + SpiListener parent; + + GList *object_listeners; + GList *window_listeners; + GList *toolkit_listeners; + SpiDEController *de_controller; + SpiDesktop *desktop; +}; typedef struct { - SpiListenerClass parent_class; - POA_Accessibility_Registry__epv epv; + SpiListenerClass parent_class; + + POA_Accessibility_Registry__epv epv; } SpiRegistryClass; GType spi_registry_get_type (void); diff --git a/test/test-simple.c b/test/test-simple.c index eba026c..8d1b7bc 100644 --- a/test/test-simple.c +++ b/test/test-simple.c @@ -651,38 +651,39 @@ key_listener_cb (const AccessibleKeystroke *stroke, *s = *stroke; - g_warning ("Key listener callback"); - return FALSE; } static void test_keylisteners (void) { + int i; AccessibleKeystroke stroke; AccessibleKeystrokeListener *key_listener; + fprintf (stderr, "Testing keyboard listeners ...\n"); + key_listener = SPI_createAccessibleKeystrokeListener ( key_listener_cb, &stroke); g_assert (SPI_registerAccessibleKeystrokeListener ( - key_listener, SPI_KEYSET_ALL_KEYS, 0, + key_listener, + SPI_KEYSET_ALL_KEYS, + 0, SPI_KEY_PRESSED | SPI_KEY_RELEASED, - SPI_KEYLISTENER_CANCONSUME)); + SPI_KEYLISTENER_CANCONSUME | SPI_KEYLISTENER_ALL_WINDOWS)); -#if FIXME_HOW_SHOULD_THIS_WORK - memset (&stroke, 0, sizeof (AccessibleKeystroke)); - - g_assert (SPI_generateKeyboardEvent (33, "!", SPI_KEY_PRESSRELEASE)); + for (i = 0; i < 3; i++) { + memset (&stroke, 0, sizeof (AccessibleKeystroke)); + g_assert (SPI_generateKeyboardEvent (33, "!", SPI_KEY_PRESSRELEASE)); + while (stroke.type == 0) + g_main_iteration (TRUE); + } - while (stroke.type == 0) - g_main_iteration (TRUE); + g_assert (SPI_deregisterAccessibleKeystrokeListener (key_listener, 0)); - g_assert (!strcmp (stroke.keystring, "!")); + /* FIXME: expand the validation here */ g_assert (stroke.type == SPI_KEY_PRESSRELEASE); -#endif - - g_assert (SPI_deregisterAccessibleKeystrokeListener (key_listener, 0)); AccessibleKeystrokeListener_unref (key_listener); } -- 2.7.4