+2002-12-06 Bill Haneman <bill.haneman@sun.com>
+
+ * configure.in:
+ Revved to 1.1.6.
+
+ * cspi/spi.h:
+ (AccessibleEvent_ref, AccessibleEvent_unref):
+ New methods, for persisting an event outside the emission context.
+ Must be used if the new accessor methods are to be called
+ outside of the event listener's callback.
+
+ * cspi/bonobo/cspi-bonobo.c:
+ (cspi_dup_ref): Pass 'ev' to bonobo_object_dup_ref
+ as second parameter instead of NULL, so we can call
+ cspi_check_ev afterwards.
+
+ * cspi/spi_main.c:
+ (cspi_object_take): New internal method,
+ converts a CORBA_Object reference to a hard ref on
+ an Accessible if possible, returning NULL if the object
+ reference is invalid or an Accessible * otherwise.
+
+ * cspi/spi_event.c:
+ (AccessibleEvent_ref):
+ Increment the event's internal private refcount, and
+ add the event's internal struct to an internal cache
+ if it's not already there.
+ (AccessibleEvent_unref):
+ Decrement the event's refcount and remove it from
+ the cspi event cache if refcount==0.
+ (cspi_event_compare): New private method.
+ Compares two event structs via their ids. Used
+ for queue lookup.
+ (cspi_internal_event_lookup): New private method.
+ (cspi_internal_event_check): New private method,
+ a 0-order sanity check for events to make sure their
+ private data is intact.
+ (cspi_internal_event_add, cspi_internal_event_remove):
+ New private methods for managiing the event cache.
+
+ * cspi/bonobo/cspi-bonobo-listener.c:
+ (cspi_event):
+ Initialize the new private data elements (id, magic, ref_count).
+
+ * atk-bridge/bridge.c:
+ (spi_atk_bridge_signal_listener):
+ Fixed bug #100530, passing wrong params to emission func.
+
+ * registryd/deviceeventcontroller.c:
+ (spi_dec_button_update_and_emit):
+ Fixed type in mask bit operations; fix for #99799.
+
2002-12-02 Bill Haneman <bill.haneman@sun.com>
Removed some of the more dangerous workarounds from
(top)
in HEAD:
-What's new in at-spi-1.1.5:
+What's new in at-spi-1.1.6:
+
+* Fixes for #99799, #10530.
+
+* New methods in cspi:
+ 'AccessibleEvent_ref' and 'AccessibleEvent_unref'
+ to allow lifecycle management of AccessibleEvents outside of
+ the emission handler.
+
+What's new in at-spi-1.1.6:
* event struct in libspi is bigger, increased unimplemented
slot count for sufficient future bincompatible expansion.
AT_SPI_MAJOR_VERSION=1
AT_SPI_MINOR_VERSION=1
-AT_SPI_MICRO_VERSION=5
+AT_SPI_MICRO_VERSION=6
AT_SPI_INTERFACE_AGE=0
-AT_SPI_BINARY_AGE=5
+AT_SPI_BINARY_AGE=6
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)
GObjectClass *event_parent_class;
GObjectClass *device_parent_class;
+static guint32 _e_id = 0;
+
/*
* Misc. helpers.
*/
aevent.event.source = source;
aevent.event.detail1 = event->detail1;
aevent.event.detail2 = event->detail2;
+ aevent.id = _e_id++;
+ aevent.magic = SPI_INTERNAL_EVENT_MAGIC;
+ aevent.ref_count = 0;
aevent.data = &event->any_data;
/* FIXME: re-enterancy hazard on this list */
CORBA_Object
cspi_dup_ref (CORBA_Object object)
{
- return bonobo_object_dup_ref (object, NULL);
+ return bonobo_object_dup_ref (object, cspi_ev ());
}
void
guint ref_count : 30;
};
+#define SPI_INTERNAL_EVENT_MAGIC 0xc3
/*
* For internal use by CSPI implementation only
*/
typedef struct {
AccessibleEvent event;
+ guint id;
+ guchar magic;
+ guchar type;
+ guint16 ref_count;
void *data;
} InternalEvent;
void cspi_object_ref (Accessible *accessible);
void cspi_object_unref (Accessible *accessible);
Accessible *cspi_object_borrow (CORBA_Object corba_object);
+Accessible *cspi_object_take (CORBA_Object corba_object);
void cspi_object_return (Accessible *accessible);
SPIBoolean cspi_accessible_is_a (Accessible *accessible,
const char *interface_name);
SPIBoolean AccessibleValue_setCurrentValue (AccessibleValue *obj,
double newValue);
+/* Persistance and lifecycle control for AccessibleEvents. */
+SPIBoolean AccessibleEvent_ref (const AccessibleEvent *e);
+void AccessibleEvent_unref (const AccessibleEvent *e);
+
/*
* Prototypes for accessor functions, to obtain context
* information for accessible events.
#include <cspi/spi-private.h>
#include <cspi/bonobo/cspi-bonobo-listener.h>
+static GSList *_cspi_event_queue = NULL;
+
/**
* SPI_freeAccessibleKeySet:
* @keyset: An AccessibleKeyset to free.
cspi_internal_event_get_object (const InternalEvent *e)
{
CORBA_any *any;
+ Accessible *accessible;
g_return_val_if_fail (e, NULL);
g_return_val_if_fail (e->data, NULL);
any = (CORBA_any *) e->data;
if (any->_type == TC_CORBA_Object)
- return cspi_object_add (* (CORBA_Object *) any->_value);
+ return cspi_object_take (* (CORBA_Object *) any->_value);
else
return NULL;
}
return NULL;
}
+static gint
+cspi_event_compare (gconstpointer p1, gconstpointer p2)
+{
+ const InternalEvent *e1 = p1, *e2 = p2;
+ return (gint) ((long) e2->id - (long) e1->id);
+}
+
+static InternalEvent *
+cspi_internal_event_lookup (const InternalEvent *e)
+{
+ InternalEvent *internal = NULL;
+ GSList *p =
+ g_slist_find_custom (_cspi_event_queue, e, cspi_event_compare);
+ if (p)
+ internal = p->data;
+ return internal;
+}
+
+static const InternalEvent *
+cspi_internal_event_check (const AccessibleEvent *e)
+{
+ InternalEvent *internal = (InternalEvent *) e;
+ if (internal->magic == SPI_INTERNAL_EVENT_MAGIC)
+ return internal;
+ else
+ return NULL;
+}
+
+static InternalEvent *
+cspi_internal_event_add (const InternalEvent *e)
+{
+ _cspi_event_queue = g_slist_prepend (_cspi_event_queue, e);
+ return (InternalEvent *) e;
+}
+
+static void
+cspi_internal_event_remove (const InternalEvent *e)
+{
+ GSList *link = g_slist_find_custom (_cspi_event_queue, e, cspi_event_compare);
+ if (link)
+ _cspi_event_queue = g_slist_remove_link (_cspi_event_queue, link);
+}
+
char *
AccessibleNameChangedEvent_getNameString (const AccessibleEvent *e)
{
return NULL;
}
+SPIBoolean
+AccessibleEvent_ref (const AccessibleEvent *e)
+{
+ const InternalEvent *private = cspi_internal_event_check (e);
+ if (private)
+ {
+ InternalEvent *event = cspi_internal_event_lookup (private);
+ /*
+ * put event in the cache if it's not there already,
+ * and increment refcount
+ */
+ if (!event)
+ {
+ event = cspi_internal_event_add (private);
+ }
+ event->ref_count++;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void
+AccessibleEvent_unref (const AccessibleEvent *e)
+{
+ const InternalEvent *private = cspi_internal_event_check (e);
+ /* decrement refcount and remove if appropriate */
+ if (private)
+ {
+ InternalEvent *event = cspi_internal_event_lookup (private);
+ if (event)
+ {
+ event->ref_count--;
+ if (event->ref_count < 1)
+ cspi_internal_event_remove (event);
+ }
+ }
+}
}
}
+Accessible *
+cspi_object_take (CORBA_Object corba_object)
+{
+ Accessible *accessible;
+ accessible = cspi_object_borrow (corba_object);
+ cspi_object_ref (accessible->objref);
+ /*
+ * if the remote object is dead,
+ * cspi_object_return will throw an exception.
+ */
+ cspi_object_return (accessible->objref);
+ if (cspi_exception ())
+ {
+ cspi_object_unref (accessible->objref);
+ accessible = NULL;
+ }
+ return accessible;
+}
+
void
cspi_object_ref (Accessible *accessible)
{