+2002-11-19 Bill Haneman <bill.haneman@sun.com>
+
+ FIXES for 98836, 98842, other bugs.
+
+ * configure.in:
+ Revved to 1.1.4, interface-age=4, binary-age=4.
+
+ * registryd/deviceeventcontroller.c:
+ (statics):
+ Fixed crasher bug in last_mouse_pos initialization.
+
+ * registryd/registry.c:
+ (desktop_add_application, desktop_remove_application):
+ Added (and then commented out) some support for
+ object context marshalling. [TODO]
+
+ * atk-bridge/bridge.c:
+ (spi_atk_bridge_event_context_create):
+ Commented out object context creation until it can
+ be properly tested and debugged.
+
+ * registryd/registry.c:
+ (impl_registry_notify_event):
+ Fixed crasher bug, we were calling
+ spi_re_entrant_list_foreach () with an empty list.
+
+2002-11-18 Bill Haneman <bill.haneman@sun.com>
+
+ * idl/Accessibility_Action.idl:
+ * idl/Accessibility_Component.idl:
+ * idl/Accessibility_Desktop.idl:
+ * idl/Accessibility_Event.idl:
+ * idl/Accessibility_Hyperlink.idl:
+ * idl/Accessibility_Image.idl:
+ * idl/Accessibility_Relation.idl:
+ * idl/Accessibility_Selection.idl:
+ * idl/Accessibility_State.idl:
+ * idl/Accessibility_Value.idl:
+ Updated unimplemented slot count to minimum of
+ four for all interfaces, for ABI freeze.
+
+ * idl/Accessibility_EditableText.idl:
+ * idl/Accessibility_Text.idl:
+ Updated unimplemented slot count to six
+ for ABI freeze.
+
+ * idl/Accessibility_Registry.idl:
+ Updated unimplemented slot count to six
+ (also for DeviceEventController),
+ for ABI freeze.
+
+ * idl/Accessibility_Table.idl:
+ Updated unimplemented slot count to eight,
+ for ABI freeze.
+
+ * idl/Accessibility_Event.idl:
+ Added CORBA_any "any_data" member to Event struct.
+
+ * idl/Accessibility_Event.idl:
+ Added CORBA_any "any_data" member to Event struct.
+
+ * atk-bridge/bridge.c:
+ (statics):
+ atk_signal_text_changed, atk_signal_child_changed,
+ signal ids queried from gtype system.
+ (AtkBridgeEventContextType): New enum.
+ (AtkBridgeEventContextData): New struct.
+ (AtkBridgeEventContext): New struct.
+ (atk_bridge_init_event_type_consts):
+ New method, initializes type contants for comparison
+ prior to emit_eventv.
+ (atk_bridge_event_context_init): New method,
+ initializes a CORBA_any from an AtkBridgeEventContext.
+ (atk_bridge_focus_tracker): Call spi_init_any_nil to
+ initialize the event.any_data struct.
+ (spi_atk_bridge_event_context_create): New method,
+ creates an AtkBridgeEventContext from signal/event info.
+ (spi_atk_bridge_event_context_free): New method.
+ (spi_atk_emit_eventv): Changed to take an
+ AtkBridgeEventContext parameter. We now initialize
+ the event.any_data member prior to notifying the
+ Registry, via the AtkBridgeEventContext.
+ (spi_atk_bridge_property_event_listener):
+ (spi_atk_bridge_state_event_listener):
+ Match emit_eventv signature.
+ (spi_atk_bridge_object_event_listener):
+ Match emit_eventv signature, and create an
+ event context from the event details.
+ Free the event context afterwards.
+ (spi_atk_bridge_window_event_listener):
+ Create an event context, pass it to the
+ emit_eventv call.
+
+ * cspi/spi_event.c:
+ (AccessibleEvent_getContextString):
+ (AccessibleEvent_getContextObject):
+ New methods, allow query of AccessibleEvent objects
+ for more context details (via the "any_data" member
+ of the Event struct, above).
+
+ * cspi/spi.h:
+ Definitions for AccessibleEvent_getContextString
+ and AccessibleEvent_getContextObject.
+
+ * cspi/spi_listener.h:
+ (InternalEvent): New struct.
+
+ * cspi/spi_event.c:
+ (AccessibleEvent_getContextString):
+ (AccessibleEvent_getContextObject):
+ Implementations of new methods, for obtaining
+ additional context information from some event types.
+
+ * cspi/spi_registry.c:
+ (SPI_registerGlobalEventListener):
+ Added mention of active-descendant-changed event in docs.
+
+ * cspi/cspi-bonobo-listener.c:
+ (cspi_event):
+ Marshal the any into the AccessibleEvent via
+ InternalEvent.
+
+ * libspi/spi-private.h:
+ #include <orbit/orbit.h>
+ (spi_init_any_nil):
+ (spi_init_any_string):
+ (spi_init_any_object):
+ New convenience function declarations.
+
+ * libspi/util.c:
+ (spi_init_any_nil):
+ (spi_init_any_string):
+ (spi_init_any_object):
+ New convenience function implementations.
+
+ * registryd/deviceeventcontroller.c:
+ (spi_poll_dec_mouse_moved):
+ (spi_device_event_controller_forward_mous_event):
+ Initialize any_data member of event.
+ (spi_deregister_controller_device_listener):
+ Fix incorrect param pass which was preventing deregistration.
+
+ * registryd/registry.c:
+ (desktop_add_application):
+ (desktop_remove_application):
+ Add object data to event's any_data before dispatch.
+ (parse_event_type):
+ Fix for error messages from GAIL.
+
+ * test/event-listener-test.c:
+ Test new ContextString and "any_data" API:
+ (report_text_event): New method query and output context string.
+ (main): register a new text listener with report_text_event
+ callback.
+
2002-11-19 Darren Kenny <darren.kenny@sun.com>
Fixes for bugs 98127 and 97914.
* idl/Accessibility_Accessible.idl:
Added four empty slots to Accessible interface.
- * idl/Accessibility_Accessible.idl:
- Added four empty slots to Accessible interface.
-
2002-11-15 Bill Haneman <bill.haneman@sun.com>
* idl/Accessibility_Registry.idl:
static gboolean registry_died = FALSE;
static guint toplevel_handler;
+/* NOT YET USED
+ static GQuark atk_quark_property_changed_name;
+ static GQuark atk_quark_property_changed_description;
+ static GQuark atk_quark_property_changed_parent;
+ static GQuark atk_quark_property_changed_role;
+ static GQuark atk_quark_property_changed_table_caption;
+ static GQuark atk_quark_property_changed_table_column_description;
+ static GQuark atk_quark_property_changed_table_row_description;
+ static guint atk_signal_property_changed;
+*/
+
+static guint atk_signal_text_changed;
+static guint atk_signal_child_changed;
+
+/* NOT YET USED
+ static guint atk_signal_text_selection_changed;
+ static guint atk_signal_active_descendant_changed;
+ static guint atk_signal_row_reordered;
+ static guint atk_signal_row_inserted;
+ static guint atk_signal_row_deleted;
+ static guint atk_signal_column_reordered;
+ static guint atk_signal_column_inserted;
+ static guint atk_signal_column_deleted;
+*/
+
+#define ATK_BRIDGE_RESERVED_CONTEXT_SIZE 16
+
+typedef enum {
+ ATK_BRIDGE_CONTEXT_TYPE_NONE = 0,
+ ATK_BRIDGE_CONTEXT_TYPE_STRING,
+ ATK_BRIDGE_CONTEXT_TYPE_OBJECT
+} AtkBridgeEventContextType;
+
+typedef union {
+ gchar *string;
+ AtkObject *object;
+ gpointer *foo;
+} AtkBridgeEventContextData;
+
+typedef struct {
+ AtkBridgeEventContextType _type;
+ AtkBridgeEventContextData _data;
+} AtkBridgeEventContext;
+
static Accessibility_Registry spi_atk_bridge_get_registry (void);
static void spi_atk_bridge_do_registration (void);
static void spi_atk_bridge_toplevel_added (AtkObject *object,
extern void gnome_accessibility_module_init (void);
extern void gnome_accessibility_module_shutdown (void);
+static void
+atk_bridge_init_event_type_consts ()
+{
+ atk_signal_child_changed = g_signal_lookup ("child_changed",
+ ATK_TYPE_OBJECT);
+ atk_signal_text_changed = g_signal_lookup ("text_changed",
+ ATK_TYPE_TEXT);
+}
+
static int
atk_bridge_init (gint *argc, gchar **argv[])
{
{
spi_atk_bridge_do_registration ();
}
+
+ atk_bridge_init_event_type_consts ();
return 0;
}
}
static void
+atk_bridge_event_context_init (CORBA_any *any,
+ AtkBridgeEventContext *ctx)
+{
+ SpiAccessible *accessible;
+ if (ctx)
+ {
+ switch (ctx->_type)
+ {
+ /* FIXME
+ case ATK_BRIDGE_CONTEXT_TYPE_OBJECT:
+ accessible = spi_accessible_new (ctx->_data.object);
+ spi_init_any_object (any, BONOBO_OBJREF (accessible));
+ break;
+ */
+ case ATK_BRIDGE_CONTEXT_TYPE_STRING:
+ spi_init_any_string (any, &ctx->_data.string);
+ break;
+ default:
+ spi_init_any_nil (any);
+ }
+ }
+ else
+ {
+ spi_init_any_nil (any);
+ }
+}
+
+static void
spi_atk_bridge_focus_tracker (AtkObject *object)
{
SpiAccessible *source;
e.source = BONOBO_OBJREF (source);
e.detail1 = 0;
e.detail2 = 0;
-
+ spi_init_any_nil (&e.any_data);
Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), &e, &ev);
if (BONOBO_EX (&ev)) registry_died = TRUE;
CORBA_exception_free (&ev);
}
+static
+AtkBridgeEventContext *
+spi_atk_bridge_event_context_create (GObject *gobject,
+ long detail1,
+ long detail2,
+ GSignalQuery *signal_query,
+ const gchar *detail)
+{
+ AtkBridgeEventContext *ctx = g_new0 (AtkBridgeEventContext, 1);
+ /*
+ if (signal_query->signal_id == atk_signal_child_changed)
+ {
+ ctx->_type = ATK_BRIDGE_CONTEXT_TYPE_OBJECT;
+ ctx->_data.object = atk_object_ref_accessible_child (ATK_OBJECT (gobject),
+ (gint) detail1);
+ }
+ else */ if (signal_query->signal_id == atk_signal_text_changed)
+ {
+ ctx->_type = ATK_BRIDGE_CONTEXT_TYPE_STRING;
+ ctx->_data.string = atk_text_get_text (ATK_TEXT (gobject),
+ (gint) detail1,
+ (gint) detail1+detail2);
+ }
+ else
+ {
+ ctx->_type = ATK_BRIDGE_CONTEXT_TYPE_NONE;
+ }
+ return ctx;
+}
+
+static void
+spi_atk_bridge_event_context_free (AtkBridgeEventContext *ctx)
+{
+ if (ctx->_type == ATK_BRIDGE_CONTEXT_TYPE_OBJECT)
+ g_object_unref (ctx->_data.object);
+ g_free (ctx);
+}
+
static void
-spi_atk_emit_eventv (GObject *gobject,
- unsigned long detail1,
- unsigned long detail2,
+spi_atk_emit_eventv (GObject *gobject,
+ unsigned long detail1,
+ unsigned long detail2,
+ AtkBridgeEventContext *context,
const char *format, ...)
{
va_list args;
e.source = BONOBO_OBJREF (source);
e.detail1 = detail1;
e.detail2 = detail2;
-
#ifdef SPI_BRIDGE_DEBUG
s = Accessibility_Accessible__get_name (BONOBO_OBJREF (source), &ev);
g_warning ("Emitting event '%s' (%lu, %lu) on %s",
e.type, e.detail1, e.detail2, s);
CORBA_free (s);
#endif
-
+ CORBA_exception_init (&ev);
+ atk_bridge_event_context_init (&e.any_data, context);
Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), &e, &ev);
+ /* I haven't freed any_data._value when it's a char*, does it leak ? */
#ifdef SPI_BRIDGE_DEBUG
if (ev._major != CORBA_NO_EXCEPTION)
g_warning ("error emitting event %s, (%d) %s",
gobject = g_value_get_object (param_values + 0);
values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1);
- spi_atk_emit_eventv (gobject, 0, 0, "object:property-change:%s", values->property_name);
+ spi_atk_emit_eventv (gobject, 0, 0, NULL,
+ "object:property-change:%s", values->property_name);
return TRUE;
}
spi_atk_emit_eventv (gobject,
detail1,
0,
+ NULL,
type);
g_free (property_name);
g_free (type);
GSignalQuery signal_query;
const gchar *name;
const gchar *detail;
+ AtkBridgeEventContext *ctx = NULL;
gint detail1 = 0, detail2 = 0;
#ifdef SPI_BRIDGE_DEBUG
detail1 = g_value_get_int (param_values + 1);
if (G_VALUE_TYPE (param_values + 2) == G_TYPE_INT)
detail2 = g_value_get_int (param_values + 2);
-
+
+ /* build some event context data, depending on the type */
+ ctx = spi_atk_bridge_event_context_create (gobject,
+ detail1, detail2,
+ &signal_query,
+ detail);
+
if (detail)
- spi_atk_emit_eventv (gobject, detail1, detail2, "object:%s:%s", name, detail);
+ spi_atk_emit_eventv (gobject, detail1, detail2, ctx,
+ "object:%s:%s", name, detail);
else
- spi_atk_emit_eventv (gobject, detail1, detail2, "object:%s", name);
+ spi_atk_emit_eventv (gobject, detail1, detail2, ctx,
+ "object:%s", name);
+
+ if (ctx)
+ spi_atk_bridge_event_context_free (ctx);
return TRUE;
}
{
GObject *gobject;
GSignalQuery signal_query;
- const gchar *name;
+ AtkBridgeEventContext ctx;
+
+ const gchar *name, *s;
#ifdef SPI_BRIDGE_DEBUG
- const gchar *s, *s2;
+ const gchar *s2;
#endif
g_signal_query (signal_hint->signal_id, &signal_query);
fprintf (stderr, "Received signal %s:%s from object %s (gail %s)\n",
g_type_name (signal_query.itype), name, s ? s : "<NULL>" , s2);
#endif
-
+
gobject = g_value_get_object (param_values + 0);
- spi_atk_emit_eventv (gobject, 0, 0, "window:%s", name);
-
+ ctx._type = ATK_BRIDGE_CONTEXT_TYPE_STRING;
+ s = atk_object_get_name (ATK_OBJECT (gobject));
+ ctx._data.string = (gchar *) s;
+ /* cast from const silences compiler */
+ spi_atk_emit_eventv (gobject, 0, 0, &ctx, "window:%s", name);
+ /* don't free the context, it's on the stack */
return TRUE;
}
AT_SPI_MAJOR_VERSION=1
AT_SPI_MINOR_VERSION=1
-AT_SPI_MICRO_VERSION=3
+AT_SPI_MICRO_VERSION=4
AT_SPI_INTERFACE_AGE=0
-AT_SPI_BINARY_AGE=3
+AT_SPI_BINARY_AGE=4
AT_SPI_VERSION="$AT_SPI_MAJOR_VERSION.$AT_SPI_MINOR_VERSION.$AT_SPI_MICRO_VERSION"
AM_INIT_AUTOMAKE(at-spi, $AT_SPI_VERSION)
AC_SUBST(AT_SPI_MAJOR_VERSION)
{
GList *l;
CSpiEventListener *clistener = (CSpiEventListener *) listener;
- AccessibleEvent aevent;
+ InternalEvent aevent;
Accessible *source = cspi_object_borrow (event->source);
- aevent.type = event->type;
- aevent.source = source;
- aevent.detail1 = event->detail1;
- aevent.detail2 = event->detail2;
+ aevent.event.type = event->type;
+ aevent.event.source = source;
+ aevent.event.detail1 = event->detail1;
+ aevent.event.detail2 = event->detail2;
+ aevent.data = &event->any_data;
/* FIXME: re-enterancy hazard on this list */
for (l = clistener->callbacks; l; l = l->next)
{
EventHandler *eh = l->data;
-
- eh->cb.event (&aevent, eh->user_data);
+ /* cast hides our private stuff from client handlers */
+ eh->cb.event ((AccessibleEvent *) &aevent, eh->user_data);
}
cspi_object_return (source);
long detail1;
long detail2;
} AccessibleEvent;
+
+/*
+ * For internal use by CSPI implementation only
+ */
+typedef struct {
+ AccessibleEvent event;
+ void *data;
+} InternalEvent;
typedef enum {
SPI_KEY_PRESSED = 1<<0,
#include <cspi/spi-impl.h>
/*
* Definitions for AccessibleRole, AccessibleState,
- * AccessibleEvent, and event listeners.
+ * and event listeners.
*/
#include <cspi/spi-roletypes.h>
#include <cspi/spi-statetypes.h>
SPIBoolean AccessibleValue_setCurrentValue (AccessibleValue *obj,
double newValue);
+/*
+ * Prototypes for accessor functions, to obtain context
+ * information for accessible events.
+ */
+
+char* AccessibleEvent_getContextString (const AccessibleEvent *e);
+Accessible * AccessibleEvent_getContextObject (const AccessibleEvent *e);
+
/* Misc methods */
void SPI_freeString (char *s);
{
cspi_device_listener_unref (listener);
}
+
+/**
+ * AccessibleEvent_getContextString:
+ * @event: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent for a string whose meaning depends
+ * on the event's context, that is, the event type and details.
+ * Not all events have context strings, in which case this
+ * query returns NULL.
+ * Context strings may be returned by:
+ * object:text-changed events,
+ * in which case they represent the text inserted or deleted;
+ * window: events, in which case they indicate the window title,
+ * or other events.
+ *
+ * Returns: the context string for the event, or %NULL if
+ * there is no context string for the event.
+ **/
+char *
+AccessibleEvent_getContextString (const AccessibleEvent *e)
+{
+ InternalEvent *foo = (InternalEvent *) e;
+ CORBA_any *any;
+ g_return_val_if_fail (foo, NULL);
+ g_return_val_if_fail (foo->data, NULL);
+ any = (CORBA_any *) foo->data;
+ if (CORBA_TypeCode_equivalent (any->_type, TC_CORBA_string, NULL))
+ {
+ return * (char **) any->_value;
+ }
+ else
+ {
+#ifdef EVENT_CONTEXT_DEBUG
+ fprintf (stderr, "requested string, TC is not TC_CORBA_string! (%u)\n",
+ (unsigned) any->_type);
+#endif
+ return NULL;
+ }
+}
+
+/**
+ * AccessibleEvent_getContextObject:
+ * @event: a pointer to the #AccessibleEvent being queried.
+ *
+ * Queries an #AccessibleEvent for an #Accessible whose meaning depends
+ * on the event's context, that is, the event type and details.
+ * Not all events have context strings, in which case this
+ * query returns NULL.
+ * Context #Accessible objects may be returned by, for instance:
+ * object:child-changed events,
+ * in which case they represent the child added or deleted.
+ * Note that context #Accessibles are not guaranteed to outlive
+ * event delivery, in which case this call may return %NULL
+ * even if the object existed at the time of dispatch.
+ *
+ * Returns: the context #Accessible for the event, or %NULL if
+ * there is no context #Accessible object for the event.
+ **/
+Accessible *
+AccessibleEvent_getContextObject (const AccessibleEvent *e)
+{
+ InternalEvent *foo = (InternalEvent *) e;
+ CORBA_any *any;
+ g_return_val_if_fail (foo, NULL);
+ g_return_val_if_fail (foo->data, NULL);
+ any = (CORBA_any *) foo->data;
+ if (any->_type == TC_CORBA_Object)
+ return cspi_object_add (* (CORBA_Object *) any->_value);
+ else
+ return NULL;
+}
+
* object:column-reordered
* object:column-deleted
* object:model-changed
+ * object:active-descendant-changed
*
* (window events)
*
Accessibility_ControllerEventMask controller_event_mask;
Accessibility_DeviceEventController device_event_controller;
Accessibility_EventTypeSeq event_types;
+ Accessibility_EventType event_type_buff[2];
if (!listener)
{
cspi_return_val_if_ev ("getting keystroke listener", FALSE);
- event_types._buffer = Accessibility_EventTypeSeq_allocbuf (2);
+ event_types._buffer = event_type_buff;
event_types._length = 2;
event_types._buffer[0] = Accessibility_BUTTON_PRESSED_EVENT;
event_types._buffer[1] = Accessibility_BUTTON_RELEASED_EVENT;
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
*/
void unImplemented_ ();
void unImplemented2_ ();
+ void unImplemented3_ ();
+ void unImplemented4_ ();
};
};
boolean deleteText (in long startPos, in long endPos);
boolean pasteText (in long position);
/**
- * unImplemented5:
+ * unImplemented7:
*
* placeholders for future expansion. Note that these are named
* 'unimplemented5 and unimplemented6' to avoid conflict with
*/
void unImplemented5 ();
void unImplemented6 ();
+ void unImplemented9 ();
+ void unImplemented10 ();
+ void unImplemented11 ();
+ void unImplemented12 ();
};
};
Accessible source;
long detail1;
long detail2;
+ any any_data;
};
interface EventListener : Bonobo::Unknown {
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
+ void unImplemented5 ();
+ void unImplemented6 ();
};
/* Deprecated, DO NOT USE! */
void unImplemented_2_ ();
void unImplemented_3_ ();
void unImplemented_4_ ();
+ void unImplemented_5_ ();
+ void unImplemented_6_ ();
};
interface DeviceEventController : Bonobo::Unknown {
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
/* placeholders for future expansion */
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
void unImplemented2 ();
void unImplemented3 ();
void unImplemented4 ();
+ void unImplemented5 ();
+ void unImplemented6 ();
+ void unImplemented7 ();
+ void unImplemented8 ();
};
};
void unImplemented2 ();
void unImplemented3 ();
void unImplemented4 ();
+ void unImplemented7 ();
+ void unImplemented8 ();
};
};
*/
void unImplemented ();
void unImplemented2 ();
+ void unImplemented3 ();
+ void unImplemented4 ();
};
};
e.source = CORBA_OBJECT_NIL;
e.detail1 = 0;
e.detail2 = 0;
-
+ spi_init_any_nil (&e.any_data);
notify_listeners (the_app->toolkit_listeners, source, &e);
bonobo_object_unref (BONOBO_OBJECT (source));
e.source = CORBA_OBJECT_NIL;
e.detail1 = 0;
e.detail2 = 0;
+ spi_init_any_nil (&e.any_data);
notify_listeners (the_app->toolkit_listeners, source, &e);
bonobo_object_unref (BONOBO_OBJECT (source));
+++ /dev/null
-/*
- * AT-SPI - Assistive Technology Service Provider Interface
- * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
- *
- * Copyright 2001, 2002 Sun Microsystems Inc.,
- * Copyright 2001, 2002 Ximian, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* keystrokelistener.c: implement the KeystrokeListener interface */
-
-#include <config.h>
-#ifdef SPI_DEBUG
-# include <stdio.h>
-#endif
-#include <libspi/listener.h>
-#include <libspi/keystrokelistener.h>
-
-/* Our parent Gtk object type */
-#define PARENT_TYPE BONOBO_TYPE_OBJECT
-
-enum {
- KEY_EVENT,
- LAST_SIGNAL
-};
-static guint signals [LAST_SIGNAL];
-
-/*
- * CORBA Accessibility::KeystrokeListener::keyEvent method implementation
- */
-static CORBA_boolean
-impl_key_event (PortableServer_Servant servant,
- const Accessibility_DeviceEvent *key,
- CORBA_Environment *ev)
-{
- gboolean was_consumed = FALSE;
- SpiKeystrokeListener *listener = SPI_KEYSTROKE_LISTENER (
- bonobo_object_from_servant (servant));
-
- g_signal_emit (G_OBJECT (listener), signals [KEY_EVENT], 0, key, &was_consumed);
-
- return was_consumed;
-}
-
-static gboolean
-boolean_handled_accumulator (GSignalInvocationHint *ihint,
- GValue *return_accu,
- const GValue *handler_return,
- gpointer dummy)
-{
- gboolean continue_emission;
- gboolean signal_handled;
-
- signal_handled = g_value_get_boolean (handler_return);
- g_value_set_boolean (return_accu, signal_handled);
- continue_emission = !signal_handled;
-
- return continue_emission;
-}
-
-void
-marshal_BOOLEAN__POINTER (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data)
-{
- typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER) (gpointer data1,
- gpointer arg_1,
- gpointer data2);
- register GMarshalFunc_BOOLEAN__POINTER callback;
- register GCClosure *cc = (GCClosure*) closure;
- register gpointer data1, data2;
- gboolean v_return;
-
- g_return_if_fail (return_value != NULL);
- g_return_if_fail (n_param_values == 2);
-
- if (G_CCLOSURE_SWAP_DATA (closure))
- {
- data1 = closure->data;
- data2 = g_value_peek_pointer (param_values + 0);
- }
- else
- {
- data1 = g_value_peek_pointer (param_values + 0);
- data2 = closure->data;
- }
- callback = (GMarshalFunc_BOOLEAN__POINTER) (marshal_data ? marshal_data : cc->callback);
-
- v_return = callback (data1,
- g_value_get_pointer (param_values + 1),
- data2);
-
- g_value_set_boolean (return_value, v_return);
-}
-
-static void
-spi_keystroke_listener_class_init (SpiKeystrokeListenerClass *klass)
-{
- POA_Accessibility_DeviceEventListener__epv *epv = &klass->epv;
-
- signals [KEY_EVENT] = g_signal_new (
- "key_event",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (SpiKeystrokeListenerClass, key_event),
- boolean_handled_accumulator, NULL,
- marshal_BOOLEAN__POINTER,
- G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
-
- epv->notifyEvent = impl_key_event;
-}
-
-static void
-spi_keystroke_listener_init (SpiKeystrokeListener *keystroke_listener)
-{
-}
-
-BONOBO_TYPE_FUNC_FULL (SpiKeystrokeListener,
- Accessibility_DeviceEventListener,
- BONOBO_TYPE_OBJECT,
- spi_keystroke_listener);
-
-SpiKeystrokeListener *
-spi_keystroke_listener_new (void)
-{
- SpiKeystrokeListener *retval = g_object_new (
- SPI_KEYSTROKE_LISTENER_TYPE, NULL);
- return retval;
-}
#define SPI_PRIVATE_H_
#include <glib/glist.h>
+#include <orbit/orbit.h>
G_BEGIN_DECLS
void spi_re_entrant_list_foreach (GList **list,
SpiReEntrantFn func,
gpointer user_data);
+void spi_init_any_nil (CORBA_any *any);
+void spi_init_any_string (CORBA_any *any, char **string);
+void spi_init_any_object (CORBA_any *any, CORBA_Object o);
G_END_DECLS
static GSList *working_list = NULL; /* of Iteration */
+static char *spi_atk_bridge_null_string = "";
+
/*
* deletes an element from the list - in a re-entrant
* safe fashion; advances the element pointer to the next
{
Iteration i;
- if (!list)
+ if (!list || !*list)
{
return;
}
working_list = g_slist_remove (working_list, &i);
}
+
+void
+spi_init_any_nil (CORBA_any *any)
+{
+ any->_type = TC_null;
+ any->_value = NULL;
+ any->_release = FALSE;
+}
+
+void
+spi_init_any_object (CORBA_any *any, CORBA_Object o)
+{
+ CORBA_Environment ev;
+ CORBA_exception_init (&ev);
+ any->_type = TC_CORBA_Object;
+ any->_value = CORBA_Object_duplicate (o, &ev);
+ any->_release = FALSE;
+ CORBA_exception_free (&ev);
+}
+
+void
+spi_init_any_string (CORBA_any *any, char **string_pointer)
+{
+ any->_type = (CORBA_TypeCode) TC_CORBA_string;
+ if (string_pointer && *string_pointer)
+ any->_value = string_pointer;
+ else
+ any->_value = &spi_atk_bridge_null_string;
+ any->_release = FALSE;
+}
/* A pointer to our parent object class */
static GObjectClass *spi_device_event_controller_parent_class;
static int spi_error_code = 0;
-static GdkPoint *last_mouse_pos = NULL;
+static GdkPoint last_mouse_pos_static = {0, 0};
+static GdkPoint *last_mouse_pos = &last_mouse_pos_static;
static unsigned int mouse_mask_state = 0;
static unsigned int mouse_button_mask =
Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask;
mouse_e.modifiers = (CORBA_unsigned_short)
mouse_mask_state;
mouse_e.timestamp = 0;
- mouse_e.event_string = CORBA_string_dup ("");
+ mouse_e.event_string = "";
mouse_e.is_text = CORBA_FALSE;
is_consumed =
spi_controller_notify_mouselisteners (controller,
&mouse_e,
&ev);
- CORBA_free (mouse_e.event_string);
-
e.type = event_name;
e.source = BONOBO_OBJREF (registry->desktop);
e.detail1 = last_mouse_pos->x;
e.detail2 = last_mouse_pos->y;
+ spi_init_any_nil (&e.any_data);
CORBA_exception_init (&ev);
if (!is_consumed)
Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
e.source = BONOBO_OBJREF (registry->desktop);
e.detail1 = mouse_mask_state;
e.detail2 = mask_return;
+ spi_init_any_nil (&e.any_data);
CORBA_exception_init (&ev);
Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
&e,
}
mouse_mask_state = mask_return;
}
- if (last_mouse_pos == NULL) {
- last_mouse_pos = g_new0 (GdkPoint, 1);
- last_mouse_pos->x = 0;
- last_mouse_pos->y = 0;
- }
if (poll_count++ == poll_count_modulus) {
poll_count = 0;
e.type = "mouse:abs";
e.source = BONOBO_OBJREF (registry->desktop);
e.detail1 = x;
e.detail2 = y;
+ spi_init_any_nil (&e.any_data);
CORBA_exception_init (&ev);
Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
&e,
e.source = BONOBO_OBJREF (registry->desktop);
e.detail1 = x - last_mouse_pos->x;
e.detail2 = y - last_mouse_pos->y;
+ spi_init_any_nil (&e.any_data);
CORBA_exception_init (&ev);
last_mouse_pos->x = x;
last_mouse_pos->y = y;
spi_dec_ungrab_mouse (gpointer data)
{
Display *display = spi_get_display ();
- fprintf (stderr, "mouse ungrab : display = %p\n", display);
if (display)
{
XUngrabButton (spi_get_display (), AnyButton, AnyModifier,
XDefaultRootWindow (spi_get_display ()));
- fprintf (stderr, "mouse grab released\n");
}
return FALSE;
}
DEControllerListener *listener = l2->data;
Accessibility_DeviceEventListener ls = listener->object;
- fprintf (stderr, "notifying mouse listener\n");
CORBA_exception_init (ev);
is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, event, ev);
- fprintf (stderr, "%sconsumed\n", is_consumed ? "" : "not ");
-
if (BONOBO_EX (ev))
{
is_consumed = FALSE;
mouse_e.hw_code = button;
mouse_e.modifiers = (CORBA_unsigned_short) xbutton_event->state;
mouse_e.timestamp = (CORBA_unsigned_long) xbutton_event->time;
- mouse_e.event_string = CORBA_string_dup ("");
+ mouse_e.event_string = "";
mouse_e.is_text = CORBA_FALSE;
is_consumed = spi_controller_notify_mouselisteners (controller, &mouse_e, &ev);
- CORBA_free (mouse_e.event_string);
e.type = CORBA_string_dup (event_name);
e.source = BONOBO_OBJREF (controller->registry->desktop);
e.detail1 = last_mouse_pos->x;
e.detail2 = last_mouse_pos->y;
+ spi_init_any_nil (&e.any_data);
CORBA_exception_init (&ev);
Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
if (priv->pending_xkb_mod_relatch_mask)
{
unsigned int feedback_mask;
+#ifdef SPI_XKB_DEBUG
fprintf (stderr, "relatching %x\n",
priv->pending_xkb_mod_relatch_mask);
+#endif
/* temporarily turn off the latch bell, if it's on */
XkbGetControls (display,
XkbAccessXFeedbackMask,
priv->xkb_desc->ctrls->ax_options = feedback_mask;
XkbChangeControls (display, priv->xkb_desc, &changes);
}
+#ifdef SPI_XKB_DEBUG
fprintf (stderr, "relatched %x\n",
priv->pending_xkb_mod_relatch_mask);
+#endif
priv->pending_xkb_mod_relatch_mask = 0;
}
}
DEControllerListener *listener,
CORBA_Environment *ev)
{
+ RemoveListenerClosure ctx;
+
+ ctx.ev = ev;
+ ctx.listener = listener;
+
spi_re_entrant_list_foreach (&controller->mouse_listeners,
- remove_listener_cb, listener);
+ remove_listener_cb, &ctx);
}
static void
#endif
}
}
- fprintf (stderr, "press %d\n", (int) keycode);
XTestFakeKeyEvent (spi_get_display (), keycode, True, time);
priv->last_press_keycode = keycode;
XSync (spi_get_display (), False);
#endif
}
}
- fprintf (stderr, "release %d\n", (int) keycode);
XTestFakeKeyEvent (spi_get_display (), keycode, False, time);
priv->last_release_keycode = keycode;
XSync (spi_get_display (), False);
fprintf (stderr, "generating mouse %s event at %ld, %ld\n",
eventName, (long int) x, (long int) y);
#endif
- g_message ("mouse event synthesis\n");
switch (eventName[0])
{
case 'b':
BonoboObject *registry = BONOBO_OBJECT (data);
Accessibility_Event e;
CORBA_Environment ev;
+ Accessibility_Accessible a;
+ CORBA_exception_init (&ev);
e.type = "object:children-changed:add";
e.source = BONOBO_OBJREF (desktop);
e.detail1 = index;
e.detail2 = 0;
- CORBA_exception_init (&ev);
+ a = Accessibility_Accessible_getChildAtIndex (BONOBO_OBJREF (desktop),
+ index, &ev);
+ /* FIXME
+ spi_init_any_object (&e.any_data, a);
+ */
+ spi_init_any_nil (&e.any_data);
+ Accessibility_Accessible_unref (a, &ev);
Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
&e, &ev);
Accessibility_Desktop_unref (e.source, &ev);
{
BonoboObject *registry = BONOBO_OBJECT (data);
Accessibility_Event e;
+ Accessibility_Accessible a;
CORBA_Environment ev;
+ CORBA_exception_init (&ev);
+
e.type = "object:children-changed:remove";
e.source = BONOBO_OBJREF (desktop);
e.detail1 = index;
e.detail2 = 0;
- CORBA_exception_init (&ev);
+ a = Accessibility_Accessible_getChildAtIndex (BONOBO_OBJREF (desktop),
+ index, &ev);
+ /* FIXME
+ spi_init_any_object (&e.any_data, a);
+ */
+ spi_init_any_nil (&e.any_data);
+ Accessibility_Accessible_unref (a, &ev);
Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
&e, &ev);
Accessibility_Desktop_unref (e.source, &ev);
{
etype->type_cat = ETYPE_WINDOW;
}
+ else if (!g_ascii_strncasecmp (event_name, "keyboard:", 9))
+ {
+ etype->type_cat = ETYPE_KEYBOARD;
+ }
else
{
etype->type_cat = ETYPE_TOOLKIT;
GList **list;
#ifdef SPI_LISTENER_DEBUG
- fprintf (stderr, "registering");
fprintf (stderr, "registering for events of type %s\n", event_name);
#endif
#endif
ctx->e_out.source = CORBA_Object_duplicate (ctx->source, ctx->ev);
-
if (BONOBO_EX (ctx->ev))
{
return SPI_RE_ENTRANT_CONTINUE;
list = get_listener_list (registry, ctx.etype.type_cat);
- if (list)
+ if (list && *list)
{
ctx.ev = ev;
ctx.e_out = *e;
+ CORBA_any__copy (&ctx.e_out.any_data, &e->any_data);
ctx.source = e->source;
-
spi_re_entrant_list_foreach (list, notify_listeners_cb, &ctx);
}
-
}
static void
static void
spi_registry_init (SpiRegistry *registry)
{
+ fprintf (stderr, "REGISTRY INITIALIZED: toolkit list = %p\n",
+ ®istry->toolkit_listeners);
registry->object_listeners = NULL;
registry->window_listeners = NULL;
registry->toolkit_listeners = NULL;
static void report_event (const AccessibleEvent *event, void *user_data);
static void report_detail_event (const AccessibleEvent *event, void *user_data);
+static void report_text_event (const AccessibleEvent *event, void *user_data);
static void timing_test_event (const AccessibleEvent *event, void *user_data);
static SPIBoolean report_mouse_event (const AccessibleDeviceEvent *event, void *user_data);
static AccessibleEventListener *generic_listener;
static AccessibleEventListener *specific_listener;
static AccessibleEventListener *test_listener;
+static AccessibleEventListener *text_listener;
static AccessibleDeviceListener *mouse_device_listener;
static gint n_elements_traversed = 0;
static GTimer *timer;
}
}
+ fprintf (stderr, "RUNNING\n");
+
SPI_init ();
generic_listener = SPI_createAccessibleEventListener (
report_event, NULL);
specific_listener = SPI_createAccessibleEventListener (
report_detail_event, NULL);
+ text_listener = SPI_createAccessibleEventListener (
+ report_text_event, NULL);
test_listener = SPI_createAccessibleEventListener (
timing_test_event, NULL);
mouse_device_listener = SPI_createAccessibleDeviceListener (
SPI_registerGlobalEventListener (generic_listener,
"object:text-caret-moved");
- SPI_registerGlobalEventListener (generic_listener,
+ SPI_registerGlobalEventListener (text_listener,
"object:text-changed");
SPI_registerGlobalEventListener (generic_listener,
"object:column-inserted");
if (s) SPI_freeString (s);
}
+void
+report_text_event (const AccessibleEvent *event, void *user_data)
+{
+ char *s = Accessible_getName (event->source);
+ fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
+ event->detail1, event->detail2);
+ if (s) SPI_freeString (s);
+ s = AccessibleEvent_getContextString (event);
+ fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
+}
+
SPIBoolean
report_mouse_event (const AccessibleDeviceEvent *event, void *user_data)
{