+<2001-10-08 Bill Haneman <bill.haneman@sun.com>
+
+ * util/Makefile.am:
+ * idl/Makefile.am:
+ Fixed 'make dist' so that distro compiles...
+ * libspi/keymasks.h:
+ new file.
+ * cspi/spi-listener.c:
+ KeystrokeListenerCB now returns a boolean.
+ * cspi/spi.h:
+ Added KeyEventType struct, and KeyStroke.
+ Also added createKeystrokeListener(),
+ KeystrokeListener_addCallback(),
+ KeystrokeListener_removeCallback(), and added a keymask to
+ registerKeystrokeListener().
+ * cspi/spi_accessible.c:
+ Changed numerous return types for interfaces from
+ AccessibleComponent to Accessible<InterfaceName>; this was
+ probably a cut-and-paste error.
+ * cspi/spi_event.c:
+ Implementations of new KeystrokeListener api (from spi.h,
+ above).
+ * idl/Registry.idl:
+ Changes to key modifier mapping.
+ Created ControllerEventMask struct.
+ Made DeviceEventController derive from Bonobo::Unknown.
+ * idl/Text.idl:
+ Removed TEXT_BOUNDARY_CURSOR_POS boundary type.
+ * libspi/deviceeventcontroller.c:
+ Added a number of new internal (private) methods.
+ * libspi/editabletext.c:
+ * libspi/editabletext.h:
+ Fixed a number of bugs related to the fact that
+ editabletext inherits from text. Fixed the EditableText struct,
+ the init() call, and use correct casts when calling Text methods
+ from an EditableText object. Removed (duplicate) atko from the
+ EditableText structure, we use the one in the parent Text
+ structure via the casts mentioned above.
+ * libspi/keystrokelistener.[ch]:
+ * libspi/registry.c:
+ Changes in support of keyboard handling (above).
+
+ Keyboard handling, though partly functional, is still not
+ recommended for at-spi client use as there is considerable
+ work yet to be done.
+
+ * libspi/text.c:
+ Changed some places where pointers to various int types
+ are cast to be pointers to CORBA_long types and vice-versa:
+ pointer casting is not safe so we pass pointers of the correct
+ types and then cast the result before putting it into the target
+ pointers.
+
+ * libspi/text.h: minor typos corrected.
+ * test/simple-at.c:
+ We now speak not only the name of a Text element, but the
+ first sentence of its content, when it receives focus.
+ I also changed the text compression to 75% from 50%.
+ * util/Accessibility_Util.server.in:
+ Changed the default magnifier type to be a 3x vertical
+ splitscreen magnifier (was previously a 2x horizontal one).
+
+<2001-10-03 Bill Haneman <bill.haneman@sun.com>
+
+ * libspi/keystrokelistener.h:
+ * libspi/keystrokelistener.c:
+ Initial functional implementations of KeystrokeListener.
+ * idl/Registry.idl:
+
<2001-10-05 Marc Mulcahy <marc.mulcahy@sun.com>
- Fixed string handling for NULL strings in libspi.
+
+ Fixed string handling for NULL strings in libspi.
Added spi_freeString to free strings returned by C bindings.
- <2001-09-30 Bill Haneman <bill.haneman@sun.com>
+<2001-09-30 Bill Haneman <bill.haneman@sun.com>
* libspi/keystrokelistener.h:
* libspi/keystrokelistener.c:
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)
spi_text.c\
spi_value.c
-spi.c : $(SPICSOURCES)
+EXTRA_DIST = $(SPICSOURCES)
+
+spi.c : $(SPICSOURCES) ../libspi/keymasks.h
extern "C" {
#endif /* __cplusplus */
+#include "keystrokelistener.h"
#include "accessibleeventlistener.h"
/*
* 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
}
COORD_TYPE_WINDOW
} AccessibleCoordType;
+typedef enum _KeyEventType {
+ KEY_PRESSED,
+ KEY_RELEASED
+} KeyEventType;
+
+typedef struct _KeyStroke
+{
+ long keyID;
+ KeyEventType type;
+ unsigned short modifiers;
+} KeyStroke;
+
/*
*
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
*
**/
void
-registerKeystrokeListener (KeystrokeListener *listener);
+registerKeystrokeListener (KeystrokeListener *listener, KeyMaskType keymask);
/**
* generateKeyEvent:
AccessibleImage *
Accessible_getImage (Accessible *obj)
{
- AccessibleComponent iface =
+ AccessibleImage iface =
Accessibility_Accessible_queryInterface (*obj,
"IDL:Accessibility/Image:1.0",
&ev);
AccessibleSelection *
Accessible_getSelection (Accessible *obj)
{
- AccessibleComponent iface =
+ AccessibleSelection iface =
Accessibility_Accessible_queryInterface (*obj,
"IDL:Accessibility/Selection:1.0",
&ev);
AccessibleTable *
Accessible_getTable (Accessible *obj)
{
- AccessibleComponent iface =
+ AccessibleTable iface =
Accessibility_Accessible_queryInterface (*obj,
"IDL:Accessibility/Table:1.0",
&ev);
AccessibleText *
Accessible_getText (Accessible *obj)
{
- AccessibleComponent iface =
+ AccessibleText iface =
Accessibility_Accessible_queryInterface (*obj,
"IDL:Accessibility/Text:1.0",
&ev);
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;
+}
*
**/
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);
}
/**
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;
}
};
enum ModifierType {
+ MODIFIER_SHIFT,
MODIFIER_ALT,
- MODIFIER_META,
MODIFIER_CONTROL,
- MODIFIER_SHIFT,
+ MODIFIER_META,
MODIFIER_META2,
- MODIFIER_META3
+ MODIFIER_META3,
+ MODIFIER_SHIFTLOCK,
+ MODIFIER_NUMLOCK
};
- typedef sequence<ModifierType> ModifierSeq;
+ struct ControllerEventMask {
+ unsigned long value;
+ unsigned short refcount;
+ };
struct KeyStroke {
long keyID;
KeyEventType type;
- ModifierSeq modifiers;
+ unsigned short modifiers;
};
interface KeystrokeListener {
boolean keyEvent (in KeyStroke key);
};
- interface DeviceEventController {
+ interface DeviceEventController : Bonobo::Unknown {
/**
* registerKeystrokeListener:
* @listener: a @KeystrokeListener which will intercept key events.
+ * @mask: a @ControllerEventMask filtering the intercepted key events.
* Returns: void
*
* Register to intercept keyboard events, and either pass them on or
* consume them.
*
**/
- void registerKeystrokeListener (in KeystrokeListener listener);
+ void registerKeystrokeListener (in KeystrokeListener listener,
+ in ControllerEventMask mask);
/**
* generateKeyEvent:
enum TEXT_BOUNDARY_TYPE {
TEXT_BOUNDARY_CHAR,
- TEXT_BOUNDARY_CURSOR_POS,
TEXT_BOUNDARY_WORD_START,
TEXT_BOUNDARY_WORD_END,
TEXT_BOUNDARY_SENTENCE_START,
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)
};
enum ModifierType {
+ MODIFIER_SHIFT,
MODIFIER_ALT,
- MODIFIER_META,
MODIFIER_CONTROL,
- MODIFIER_SHIFT,
+ MODIFIER_META,
MODIFIER_META2,
- MODIFIER_META3
+ MODIFIER_META3,
+ MODIFIER_SHIFTLOCK,
+ MODIFIER_NUMLOCK
};
- typedef sequence<ModifierType> ModifierSeq;
+ struct ControllerEventMask {
+ unsigned long value;
+ unsigned short refcount;
+ };
struct KeyStroke {
long keyID;
KeyEventType type;
- ModifierSeq modifiers;
+ unsigned short modifiers;
};
interface KeystrokeListener {
boolean keyEvent (in KeyStroke key);
};
- interface DeviceEventController {
+ interface DeviceEventController : Bonobo::Unknown {
/**
* registerKeystrokeListener:
* @listener: a @KeystrokeListener which will intercept key events.
+ * @mask: a @ControllerEventMask filtering the intercepted key events.
* Returns: void
*
* Register to intercept keyboard events, and either pass them on or
* consume them.
*
**/
- void registerKeystrokeListener (in KeystrokeListener listener);
+ void registerKeystrokeListener (in KeystrokeListener listener,
+ in ControllerEventMask mask);
/**
* generateKeyEvent:
enum TEXT_BOUNDARY_TYPE {
TEXT_BOUNDARY_CHAR,
- TEXT_BOUNDARY_CURSOR_POS,
TEXT_BOUNDARY_WORD_START,
TEXT_BOUNDARY_WORD_END,
TEXT_BOUNDARY_SENTENCE_START,
accessibleeventlistener.h \
deviceeventcontroller.h \
registry.h \
+ keymasks.h \
Accessibility.h
IDL_OUT = Accessibility.h Accessibility-stubs.c Accessibility-skels.c Accessibility-common.c
accessibleeventlistener.h \
registry.c \
registry.h \
+ keymasks.h \
$(IDL_OUT)
IDLFLAGS = -I$(BONOBO_ACTIVATION_IDL_DIR) \
#include <stdio.h>
#endif
+#include <X11/Xlib.h>
#include <config.h>
+#include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
+#include <gdk/gdkwindow.h>
#include <bonobo/Bonobo.h>
#include <libspi/Accessibility.h>
*/
static GObjectClass *device_event_controller_parent_class;
+static gboolean kbd_registered = FALSE;
+
+typedef enum {
+ DEVICE_TYPE_KBD,
+ DEVICE_TYPE_MOUSE,
+ DEVICE_TYPE_LAST_DEFINED
+} DeviceTypeCategory;
+
+static gboolean _controller_register_with_devices (DeviceEventController *controller);
+static gboolean _controller_grab_keyboard (DeviceEventController *controller);
+
+static void _controller_register_device_listener (DeviceEventController *controller,
+ const CORBA_Object l,
+ const Accessibility_ControllerEventMask *mask,
+ DeviceTypeCategory type,
+ CORBA_Environment *ev);
+
+/*
+ * Private methods
+ */
+
+static gint
+_compare_corba_objects (gconstpointer p1, gconstpointer p2)
+{
+ CORBA_Environment ev;
+ gint retval;
+ retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
+
+#ifdef SPI_DEBUG
+ fprintf (stderr, "comparing %p to %p; result %d\n",
+ p1, p2,
+ retval);
+#endif
+ return retval;
+}
+
+static gint
+_eventmask_compare_value (gconstpointer p1, gconstpointer p2)
+{
+ if (!p1 || !p2)
+ return (gint) (p1?1:(p2?-1:0));
+ else
+ return ((long)((Accessibility_ControllerEventMask*)p2)->value) -
+ ((long)((Accessibility_ControllerEventMask*)p1)->value);
+}
+
+static void
+_controller_register_device_listener (DeviceEventController *controller,
+ const CORBA_Object l,
+ const Accessibility_ControllerEventMask *mask,
+ DeviceTypeCategory type,
+ CORBA_Environment *ev)
+{
+ Accessibility_ControllerEventMask *mask_ptr;
+
+ switch (type) {
+ case DEVICE_TYPE_KBD:
+ controller->key_listeners = g_list_append (controller->key_listeners,
+ CORBA_Object_duplicate (l, ev));
+
+ mask_ptr = (Accessibility_ControllerEventMask *)
+ g_list_find_custom (controller->keymask_list, (gpointer) mask,
+ _eventmask_compare_value);
+ if (mask_ptr)
+ ++(mask_ptr->refcount);
+ else
+ {
+ if (mask->refcount != (CORBA_unsigned_short) 1)
+ fprintf (stderr, "mask initial refcount is not 1!\n");
+ if (mask->value > (CORBA_unsigned_long) 2048)
+ fprintf (stderr, "mask value looks invalid (%lu)\n",
+ (unsigned long) mask->value);
+ else
+ fprintf (stderr, "appending mask with val=%lu\n",
+ (unsigned long) mask->value);
+ mask_ptr = Accessibility_ControllerEventMask__alloc();
+ mask_ptr->value = mask->value;
+ mask_ptr->refcount = (CORBA_unsigned_short) 1;
+ controller->keymask_list = g_list_append (controller->keymask_list,
+ (gpointer) mask_ptr);
+ }
+ break;
+ case DEVICE_TYPE_MOUSE:
+/* controller->mouse_listeners = g_list_append (controller->mouse_listeners,
+ CORBA_Object_duplicate (l, ev));*/
+
+/* possibly this interface should NOT be used for mouse events ? */
+ break;
+ }
+}
+
+static void
+_controller_deregister_device_listener (DeviceEventController *controller,
+ const CORBA_Object l,
+ const Accessibility_ControllerEventMask *mask,
+ DeviceTypeCategory type,
+ CORBA_Environment *ev)
+{
+ Accessibility_ControllerEventMask *mask_ptr;
+ GList *list_ptr;
+ switch (type) {
+ case DEVICE_TYPE_KBD:
+ list_ptr = g_list_find_custom (controller->key_listeners, l, _compare_corba_objects);
+ if (list_ptr)
+ controller->key_listeners = g_list_remove (controller->key_listeners, list_ptr);
+
+ mask_ptr = (Accessibility_ControllerEventMask *)
+ g_list_find_custom (controller->keymask_list, (gpointer) mask,
+ _eventmask_compare_value);
+ if (mask_ptr)
+ --mask_ptr->refcount;
+ if (!mask_ptr->refcount)
+ {
+ controller->keymask_list = g_list_remove (controller->keymask_list, mask_ptr);
+ ; /* release any key grabs that are in place for this key mask */
+ }
+ break;
+ case DEVICE_TYPE_MOUSE:
+/* controller->mouse_listeners = g_list_append (controller->mouse_listeners,
+ CORBA_Object_duplicate (l, ev));*/
+
+/* possibly this interface should NOT be used for mouse events ? */
+ break;
+ }
+}
+
+static gboolean
+_controller_register_with_devices (DeviceEventController *controller)
+{
+ gboolean retval = FALSE;
+ Display *default_display;
+ Window root_window;
+
+ default_display = GDK_DISPLAY();
+ root_window = GDK_ROOT_WINDOW();
+ /* calls to device-specific implementations and routines go here */
+ /* register with: keyboard hardware code handler */
+ /* register with: (translated) keystroke handler */
+#ifdef SPI_DEBUG
+ fprintf (stderr, "About to request events on window %ld of display %p\n",
+ (unsigned long) root_window, default_display);
+#endif
+ XSelectInput (default_display,
+ root_window,
+ KeyPressMask);
+ XSelectInput (default_display,
+ root_window,
+ KeyReleaseMask);
+ /* register with: mouse hardware device handler? */
+ /* register with: mouse event handler */
+ return retval;
+}
+
+static gboolean _check_key_event (DeviceEventController *controller)
+{
+#ifdef SPI_DEBUG
+ static Accessibility_ControllerEventMask shiftlock_mask =
+ {(CORBA_unsigned_long) LockMask, (CORBA_unsigned_short) 1};
+#endif
+ static gboolean initialized = FALSE;
+ static gboolean is_active = FALSE;
+ XEvent *x_event = g_new0 (XEvent, 1);
+ XKeyEvent *x_key_event;
+ KeySym keysym;
+ gboolean is_consumed = FALSE;
+ char key_name[16];
+ int i;
+ int n_listeners = g_list_length (controller->key_listeners);
+ Accessibility_KeyStroke key_event;
+ static CORBA_Environment ev;
+
+ if (!initialized)
+ {
+ initialized = TRUE;
+ CORBA_exception_init (&ev);
+ }
+
+/* if (!XPending(GDK_DISPLAY())) return TRUE; */
+
+ /*
+ * the call to XPending seemed like a good idea, why did it
+ * wreak such havoc?
+ */
+
+ XPeekEvent (GDK_DISPLAY(), x_event);
+ if (x_event->type == KeyPress)
+ {
+ x_key_event = (XKeyEvent *)x_event;
+ keysym = XLookupKeysym (x_key_event, 0);
+ key_event.keyID = (CORBA_long)(keysym);
+ key_event.type = Accessibility_KEY_PRESSED;
+ key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
+#if defined SPI_KEYEVENT_DEBUG
+ fprintf (stderr,
+ "Key %lu pressed (%c), modifiers %d\n",
+ (unsigned long) keysym,
+ (char) keysym,
+ (int) x_key_event->state);
+#elif defined SPI_DEBUG
+ fprintf(stderr, "%s%c",
+ (x_key_event->state & Mod1Mask)?"Alt-":"",
+ ((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))?
+ (char) toupper((int) keysym) : (char) tolower((int)keysym));
+#endif /* SPI_DEBUG */
+ }
+ else
+ {
+#ifdef SPI_KEYEVENT_DEBUG
+ fprintf (stderr, "other event, type %d\n", (int) x_event->type);
+#endif
+ }
+ /* relay to listeners, and decide whether to consume it or not */
+ for (i=0; i<n_listeners && !is_consumed; ++i)
+ {
+ Accessibility_KeystrokeListener ls;
+ ls = (Accessibility_KeystrokeListener)
+ g_list_nth_data (controller->key_listeners, i);
+ if (!CORBA_Object_is_nil(ls, &ev))
+ {
+ is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev);
+ }
+ }
+ if (is_consumed) XNextEvent (GDK_DISPLAY(), x_event);
+ XAllowEvents (GDK_DISPLAY(), ReplayKeyboard, CurrentTime);
+/*
+ * I haven't figure out how to make this work correctly yet :-(
+ *
+ * XGrabKeyboard (GDK_DISPLAY(), GDK_ROOT_WINDOW(), True,
+ * GrabModeAsync, GrabModeSync, CurrentTime);
+ * XAllowEvents (GDK_DISPLAY(), SyncKeyboard, CurrentTime);
+ *
+ *
+ * ControlMask grabs are broken, must be in use already.
+ *
+ */
+
+/* Always grab ShiftLock in DEBUG mode */
+#ifdef SPI_DEBUG
+ if (!controller->keymask_list)
+ controller->keymask_list =
+ g_list_append (controller->keymask_list, &shiftlock_mask);
+#endif
+ return _controller_grab_keyboard (controller);
+}
+
+static gboolean
+_controller_grab_keyboard (DeviceEventController *controller)
+{
+ Display *display = GDK_DISPLAY();
+ Window root_window = GDK_ROOT_WINDOW();
+ GList *maskList = controller->keymask_list;
+ int i;
+ int last_mask = g_list_length (maskList);
+
+/*
+ * masks known to work with default RH 7.1:
+ * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
+ * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
+ * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
+ * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
+ *
+ * ControlMask grabs are broken, must be in use already
+ */
+
+ for (i=0; i < last_mask; ++i)
+ {
+ Accessibility_ControllerEventMask *mask
+ = (Accessibility_ControllerEventMask *)g_list_nth_data (maskList, i);
+ unsigned long maskVal = 0xFFFFFFFF;
+ if (mask) maskVal = (unsigned long) mask->value;
+#ifdef SPI_KEYEVENT_DEBUG
+ fprintf (stderr, "mask=%lx\n", maskVal);
+#endif
+ if (!(maskVal & ControlMask))
+ {
+#ifdef SPI_KEYEVENT_DEBUG
+ fprintf (stderr, "grabbing for mod %lu\n", (unsigned long) maskVal);
+#endif
+ XGrabKey (display,
+ AnyKey,
+ maskVal,
+ root_window,
+ True,
+ GrabModeAsync,
+ GrabModeSync);
+ /* TODO: check call for errors and return FALSE if error occurs */
+ } else {
+ return FALSE; /* can't do control key yet */
+ }
+ }
+ return TRUE;
+}
+
/*
* Implemented GObject::finalize
*/
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
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);
}
*/
CORBA_Environment *ev)
{
#ifdef SPI_DEBUG
- fprintf (stderr, "synthesizing keystroke %ld\n", keyEventID);
+ fprintf (stderr, "synthesizing keystroke %ld\n", (long) keyEventID);
#endif
}
/* 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
#include <bonobo/bonobo-object.h>
#include <libspi/Accessibility.h>
+#include "keystrokelistener.h"
#define DEVICE_EVENT_CONTROLLER_TYPE (device_event_controller_get_type ())
#define DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventController))
#define DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventControllerClass))
-#define IS_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK__INSTANCE_TYPE ((o), DEVICE_EVENT_CONTROLLER_TYPE))
+#define IS_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVICE_EVENT_CONTROLLER_TYPE))
#define IS_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVICE_EVENT_CONTROLLER_TYPE))
+#define DEVICE_EVENT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventControllerClass))
typedef struct {
BonoboObject parent;
+ GList *key_listeners;
+ GList *mouse_listeners;
+ GList *keymask_list;
} DeviceEventController;
typedef struct {
BonoboObjectClass parent_class;
POA_Accessibility_DeviceEventController__epv epv;
+ gboolean (*check_key_event) (DeviceEventController *controller);
} DeviceEventControllerClass;
GType device_event_controller_get_type (void);
* use bonobo_type_unique.
*/
type = bonobo_type_unique (
- BONOBO_OBJECT_TYPE,
+ TEXT_TYPE,
POA_Accessibility_EditableText__init,
NULL,
G_STRUCT_OFFSET (EditableTextClass, epv),
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);
}
{
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;
}
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);
}
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);
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);
}
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);
}
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);
}
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);
}
#include <bonobo/bonobo-object.h>
#include <atk/atk.h>
#include <libspi/Accessibility.h>
+#include "text.h"
#define EDITABLE_TEXT_TYPE (editable_text_get_type ())
#define EDITABLE_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EDITABLE_TEXT_TYPE, EditableText))
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;
};
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)
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
}
static void
keystroke_listener_init (KeystrokeListener *keystroke_listener)
{
+ keystroke_listener->callbacks = NULL;
}
GType
#include <bonobo/bonobo-object.h>
#include <atk/atkobject.h>
#include <libspi/Accessibility.h>
+#include "keymasks.h"
#define KEYSTROKE_LISTENER_TYPE (keystroke_listener_get_type ())
#define KEYSTROKE_LISTENER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), KEYSTROKE_LISTENER_TYPE, KeystrokeListener))
#define KEYSTROKE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), KEYSTROKE_LISTENER_TYPE, KeystrokeListenerClass))
-#define IS_KEYSTROKE_LISTENER(o) (G_TYPE_CHECK__INSTANCE_TYPE ((o), KEYSTROKE_LISTENER_TYPE))
+#define IS_KEYSTROKE_LISTENER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), KEYSTROKE_LISTENER_TYPE))
#define IS_KEYSTROKE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), KEYSTROKE_LISTENER_TYPE))
+typedef gboolean (*BooleanKeystrokeListenerCB) (void *keystroke_ptr);
+
typedef struct {
BonoboObject parent;
+ GList *callbacks;
} KeystrokeListener;
typedef struct {
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
}
#include <libspi/Accessibility.h>
/*
+ * We'd like to replace the dependance on X-isms with a wrapper layer,
+ * to the extent that it can't be done with pure GDK.
+ * Anyone want to help?
+ */
+#include <X11/Xlib.h>
+#include <gdk/gdkx.h>
+
+/*
* This pulls the definition for the BonoboObject (GType)
*/
#include "registry.h"
static long _get_unique_id();
+static gboolean _device_event_controller_hook (gpointer source);
+
/*
* Implemented GObject::finalize
*/
}
static gint
-compare_object_hash (gconstpointer p1, gconstpointer p2)
+compare_corba_objects (gconstpointer p1, gconstpointer p2)
{
CORBA_Environment ev;
gint retval;
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;
* 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)
* 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
{
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);
}
}
* 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)
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
}
}
+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)
{
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
extern "C" {
#endif /* __cplusplus */
+#include <glib/gmain.h>
#include <libspi/Accessibility.h>
#include "listener.h"
#include "desktop.h"
+#include "deviceeventcontroller.h"
#define REGISTRY_TYPE (registry_get_type ())
#define REGISTRY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), REGISTRY_TYPE, Registry))
GList *window_listeners;
GList *toolkit_listeners;
GList *applications;
+ DeviceEventController *device_event_controller;
Desktop *desktop;
+ gboolean (*kbd_event_hook) (gpointer source);
} Registry;
typedef struct {
#include <bonobo/Bonobo.h>
#include <stdio.h>
+#include <stdlib.h>
/*
* This pulls the CORBA definitions for the "Accessibility::Accessible" server
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
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);
}
else
rv = CORBA_string_dup ("");
+
return rv;
}
-/* 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
#include <bonobo/bonobo-object.h>
#include <atk/atk.h>
#include <libspi/Accessibility.h>
+#include "accessible.h"
#define TEXT_TYPE (text_get_type ())
#define TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEXT_TYPE, Text))
#define TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TEXT_TYPE, TextClass))
-#define IS_TEXT(obj) (G_TYPE_CHECK__INSTANCE_TYPE ((obj), TEXT_TYPE))
-#define IS_TEX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEXT_TYPE))
+#define IS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEXT_TYPE))
+#define IS_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEXT_TYPE))
typedef struct _Text Text;
typedef struct _TextClass TextClass;
#include <stdio.h>
#endif
+#include <X11/Xlib.h>
#include <config.h>
+#include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
+#include <gdk/gdkwindow.h>
#include <bonobo/Bonobo.h>
#include <libspi/Accessibility.h>
*/
static GObjectClass *device_event_controller_parent_class;
+static gboolean kbd_registered = FALSE;
+
+typedef enum {
+ DEVICE_TYPE_KBD,
+ DEVICE_TYPE_MOUSE,
+ DEVICE_TYPE_LAST_DEFINED
+} DeviceTypeCategory;
+
+static gboolean _controller_register_with_devices (DeviceEventController *controller);
+static gboolean _controller_grab_keyboard (DeviceEventController *controller);
+
+static void _controller_register_device_listener (DeviceEventController *controller,
+ const CORBA_Object l,
+ const Accessibility_ControllerEventMask *mask,
+ DeviceTypeCategory type,
+ CORBA_Environment *ev);
+
+/*
+ * Private methods
+ */
+
+static gint
+_compare_corba_objects (gconstpointer p1, gconstpointer p2)
+{
+ CORBA_Environment ev;
+ gint retval;
+ retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
+
+#ifdef SPI_DEBUG
+ fprintf (stderr, "comparing %p to %p; result %d\n",
+ p1, p2,
+ retval);
+#endif
+ return retval;
+}
+
+static gint
+_eventmask_compare_value (gconstpointer p1, gconstpointer p2)
+{
+ if (!p1 || !p2)
+ return (gint) (p1?1:(p2?-1:0));
+ else
+ return ((long)((Accessibility_ControllerEventMask*)p2)->value) -
+ ((long)((Accessibility_ControllerEventMask*)p1)->value);
+}
+
+static void
+_controller_register_device_listener (DeviceEventController *controller,
+ const CORBA_Object l,
+ const Accessibility_ControllerEventMask *mask,
+ DeviceTypeCategory type,
+ CORBA_Environment *ev)
+{
+ Accessibility_ControllerEventMask *mask_ptr;
+
+ switch (type) {
+ case DEVICE_TYPE_KBD:
+ controller->key_listeners = g_list_append (controller->key_listeners,
+ CORBA_Object_duplicate (l, ev));
+
+ mask_ptr = (Accessibility_ControllerEventMask *)
+ g_list_find_custom (controller->keymask_list, (gpointer) mask,
+ _eventmask_compare_value);
+ if (mask_ptr)
+ ++(mask_ptr->refcount);
+ else
+ {
+ if (mask->refcount != (CORBA_unsigned_short) 1)
+ fprintf (stderr, "mask initial refcount is not 1!\n");
+ if (mask->value > (CORBA_unsigned_long) 2048)
+ fprintf (stderr, "mask value looks invalid (%lu)\n",
+ (unsigned long) mask->value);
+ else
+ fprintf (stderr, "appending mask with val=%lu\n",
+ (unsigned long) mask->value);
+ mask_ptr = Accessibility_ControllerEventMask__alloc();
+ mask_ptr->value = mask->value;
+ mask_ptr->refcount = (CORBA_unsigned_short) 1;
+ controller->keymask_list = g_list_append (controller->keymask_list,
+ (gpointer) mask_ptr);
+ }
+ break;
+ case DEVICE_TYPE_MOUSE:
+/* controller->mouse_listeners = g_list_append (controller->mouse_listeners,
+ CORBA_Object_duplicate (l, ev));*/
+
+/* possibly this interface should NOT be used for mouse events ? */
+ break;
+ }
+}
+
+static void
+_controller_deregister_device_listener (DeviceEventController *controller,
+ const CORBA_Object l,
+ const Accessibility_ControllerEventMask *mask,
+ DeviceTypeCategory type,
+ CORBA_Environment *ev)
+{
+ Accessibility_ControllerEventMask *mask_ptr;
+ GList *list_ptr;
+ switch (type) {
+ case DEVICE_TYPE_KBD:
+ list_ptr = g_list_find_custom (controller->key_listeners, l, _compare_corba_objects);
+ if (list_ptr)
+ controller->key_listeners = g_list_remove (controller->key_listeners, list_ptr);
+
+ mask_ptr = (Accessibility_ControllerEventMask *)
+ g_list_find_custom (controller->keymask_list, (gpointer) mask,
+ _eventmask_compare_value);
+ if (mask_ptr)
+ --mask_ptr->refcount;
+ if (!mask_ptr->refcount)
+ {
+ controller->keymask_list = g_list_remove (controller->keymask_list, mask_ptr);
+ ; /* release any key grabs that are in place for this key mask */
+ }
+ break;
+ case DEVICE_TYPE_MOUSE:
+/* controller->mouse_listeners = g_list_append (controller->mouse_listeners,
+ CORBA_Object_duplicate (l, ev));*/
+
+/* possibly this interface should NOT be used for mouse events ? */
+ break;
+ }
+}
+
+static gboolean
+_controller_register_with_devices (DeviceEventController *controller)
+{
+ gboolean retval = FALSE;
+ Display *default_display;
+ Window root_window;
+
+ default_display = GDK_DISPLAY();
+ root_window = GDK_ROOT_WINDOW();
+ /* calls to device-specific implementations and routines go here */
+ /* register with: keyboard hardware code handler */
+ /* register with: (translated) keystroke handler */
+#ifdef SPI_DEBUG
+ fprintf (stderr, "About to request events on window %ld of display %p\n",
+ (unsigned long) root_window, default_display);
+#endif
+ XSelectInput (default_display,
+ root_window,
+ KeyPressMask);
+ XSelectInput (default_display,
+ root_window,
+ KeyReleaseMask);
+ /* register with: mouse hardware device handler? */
+ /* register with: mouse event handler */
+ return retval;
+}
+
+static gboolean _check_key_event (DeviceEventController *controller)
+{
+#ifdef SPI_DEBUG
+ static Accessibility_ControllerEventMask shiftlock_mask =
+ {(CORBA_unsigned_long) LockMask, (CORBA_unsigned_short) 1};
+#endif
+ static gboolean initialized = FALSE;
+ static gboolean is_active = FALSE;
+ XEvent *x_event = g_new0 (XEvent, 1);
+ XKeyEvent *x_key_event;
+ KeySym keysym;
+ gboolean is_consumed = FALSE;
+ char key_name[16];
+ int i;
+ int n_listeners = g_list_length (controller->key_listeners);
+ Accessibility_KeyStroke key_event;
+ static CORBA_Environment ev;
+
+ if (!initialized)
+ {
+ initialized = TRUE;
+ CORBA_exception_init (&ev);
+ }
+
+/* if (!XPending(GDK_DISPLAY())) return TRUE; */
+
+ /*
+ * the call to XPending seemed like a good idea, why did it
+ * wreak such havoc?
+ */
+
+ XPeekEvent (GDK_DISPLAY(), x_event);
+ if (x_event->type == KeyPress)
+ {
+ x_key_event = (XKeyEvent *)x_event;
+ keysym = XLookupKeysym (x_key_event, 0);
+ key_event.keyID = (CORBA_long)(keysym);
+ key_event.type = Accessibility_KEY_PRESSED;
+ key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
+#if defined SPI_KEYEVENT_DEBUG
+ fprintf (stderr,
+ "Key %lu pressed (%c), modifiers %d\n",
+ (unsigned long) keysym,
+ (char) keysym,
+ (int) x_key_event->state);
+#elif defined SPI_DEBUG
+ fprintf(stderr, "%s%c",
+ (x_key_event->state & Mod1Mask)?"Alt-":"",
+ ((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))?
+ (char) toupper((int) keysym) : (char) tolower((int)keysym));
+#endif /* SPI_DEBUG */
+ }
+ else
+ {
+#ifdef SPI_KEYEVENT_DEBUG
+ fprintf (stderr, "other event, type %d\n", (int) x_event->type);
+#endif
+ }
+ /* relay to listeners, and decide whether to consume it or not */
+ for (i=0; i<n_listeners && !is_consumed; ++i)
+ {
+ Accessibility_KeystrokeListener ls;
+ ls = (Accessibility_KeystrokeListener)
+ g_list_nth_data (controller->key_listeners, i);
+ if (!CORBA_Object_is_nil(ls, &ev))
+ {
+ is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev);
+ }
+ }
+ if (is_consumed) XNextEvent (GDK_DISPLAY(), x_event);
+ XAllowEvents (GDK_DISPLAY(), ReplayKeyboard, CurrentTime);
+/*
+ * I haven't figure out how to make this work correctly yet :-(
+ *
+ * XGrabKeyboard (GDK_DISPLAY(), GDK_ROOT_WINDOW(), True,
+ * GrabModeAsync, GrabModeSync, CurrentTime);
+ * XAllowEvents (GDK_DISPLAY(), SyncKeyboard, CurrentTime);
+ *
+ *
+ * ControlMask grabs are broken, must be in use already.
+ *
+ */
+
+/* Always grab ShiftLock in DEBUG mode */
+#ifdef SPI_DEBUG
+ if (!controller->keymask_list)
+ controller->keymask_list =
+ g_list_append (controller->keymask_list, &shiftlock_mask);
+#endif
+ return _controller_grab_keyboard (controller);
+}
+
+static gboolean
+_controller_grab_keyboard (DeviceEventController *controller)
+{
+ Display *display = GDK_DISPLAY();
+ Window root_window = GDK_ROOT_WINDOW();
+ GList *maskList = controller->keymask_list;
+ int i;
+ int last_mask = g_list_length (maskList);
+
+/*
+ * masks known to work with default RH 7.1:
+ * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
+ * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
+ * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
+ * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
+ *
+ * ControlMask grabs are broken, must be in use already
+ */
+
+ for (i=0; i < last_mask; ++i)
+ {
+ Accessibility_ControllerEventMask *mask
+ = (Accessibility_ControllerEventMask *)g_list_nth_data (maskList, i);
+ unsigned long maskVal = 0xFFFFFFFF;
+ if (mask) maskVal = (unsigned long) mask->value;
+#ifdef SPI_KEYEVENT_DEBUG
+ fprintf (stderr, "mask=%lx\n", maskVal);
+#endif
+ if (!(maskVal & ControlMask))
+ {
+#ifdef SPI_KEYEVENT_DEBUG
+ fprintf (stderr, "grabbing for mod %lu\n", (unsigned long) maskVal);
+#endif
+ XGrabKey (display,
+ AnyKey,
+ maskVal,
+ root_window,
+ True,
+ GrabModeAsync,
+ GrabModeSync);
+ /* TODO: check call for errors and return FALSE if error occurs */
+ } else {
+ return FALSE; /* can't do control key yet */
+ }
+ }
+ return TRUE;
+}
+
/*
* Implemented GObject::finalize
*/
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
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);
}
*/
CORBA_Environment *ev)
{
#ifdef SPI_DEBUG
- fprintf (stderr, "synthesizing keystroke %ld\n", keyEventID);
+ fprintf (stderr, "synthesizing keystroke %ld\n", (long) keyEventID);
#endif
}
/* 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
#include <bonobo/bonobo-object.h>
#include <libspi/Accessibility.h>
+#include "keystrokelistener.h"
#define DEVICE_EVENT_CONTROLLER_TYPE (device_event_controller_get_type ())
#define DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventController))
#define DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventControllerClass))
-#define IS_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK__INSTANCE_TYPE ((o), DEVICE_EVENT_CONTROLLER_TYPE))
+#define IS_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVICE_EVENT_CONTROLLER_TYPE))
#define IS_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVICE_EVENT_CONTROLLER_TYPE))
+#define DEVICE_EVENT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEVICE_EVENT_CONTROLLER_TYPE, DeviceEventControllerClass))
typedef struct {
BonoboObject parent;
+ GList *key_listeners;
+ GList *mouse_listeners;
+ GList *keymask_list;
} DeviceEventController;
typedef struct {
BonoboObjectClass parent_class;
POA_Accessibility_DeviceEventController__epv epv;
+ gboolean (*check_key_event) (DeviceEventController *controller);
} DeviceEventControllerClass;
GType device_event_controller_get_type (void);
#endif
#include <libbonobo.h>
+#include <glib/gmain.h>
#include "registry.h"
int
char **argv)
{
Registry *registry;
+ GSource *keyevent_source;
char *obj_id;
if (!bonobo_init (&argc, argv))
#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;
#include <libspi/Accessibility.h>
/*
+ * We'd like to replace the dependance on X-isms with a wrapper layer,
+ * to the extent that it can't be done with pure GDK.
+ * Anyone want to help?
+ */
+#include <X11/Xlib.h>
+#include <gdk/gdkx.h>
+
+/*
* This pulls the definition for the BonoboObject (GType)
*/
#include "registry.h"
static long _get_unique_id();
+static gboolean _device_event_controller_hook (gpointer source);
+
/*
* Implemented GObject::finalize
*/
}
static gint
-compare_object_hash (gconstpointer p1, gconstpointer p2)
+compare_corba_objects (gconstpointer p1, gconstpointer p2)
{
CORBA_Environment ev;
gint retval;
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;
* 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)
* 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
{
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);
}
}
* 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)
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
}
}
+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)
{
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
extern "C" {
#endif /* __cplusplus */
+#include <glib/gmain.h>
#include <libspi/Accessibility.h>
#include "listener.h"
#include "desktop.h"
+#include "deviceeventcontroller.h"
#define REGISTRY_TYPE (registry_get_type ())
#define REGISTRY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), REGISTRY_TYPE, Registry))
GList *window_listeners;
GList *toolkit_listeners;
GList *applications;
+ DeviceEventController *device_event_controller;
Desktop *desktop;
+ gboolean (*kbd_event_hook) (gpointer source);
} Registry;
typedef struct {
#endif
#include <libbonobo.h>
+#include <glib/gmain.h>
#include "registry.h"
int
char **argv)
{
Registry *registry;
+ GSource *keyevent_source;
char *obj_id;
if (!bonobo_init (&argc, argv))
#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;
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 ();
Accessible *application;
AccessibleEventListener *focus_listener;
AccessibleEventListener *button_listener;
+ KeystrokeListener *key_listener;
if ((argc > 1) && (!strncmp(argv[1],"-h",2)))
{
}
}
+ /* prepare the keyboard snoopers */
+ /* key_listener = createKeystrokeListener(report_key_event);
+ registerKeystrokeListener(key_listener, KEYMASK_SHIFT); */
+
get_environment_vars();
SPI_event_main(FALSE);
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
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;
_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;
}
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);
<oaf_info>
<oaf_server iid="OAFIID:Accessibility_Util_Magnifier:proto0.1"
- type="exe" location="magnifier -h">
+ type="exe" location="magnifier -vz 2">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Accessibility/Magnifier:1.0"/>
</oaf_attribute>
-NULL=
+NULL =
+
+idldir = $(top_srcdir)/util/idl
+
+idl_DATA = idl/Magnifier.idl
+
+dist_SUBDIRS = idl
lib_LTLIBRARIES = libat-util.la
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
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)
@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)
magnifier = (Accessibility_Magnifier) oclient;
- /* bonobo_activate (); ? */
}
return magnifier;