? at-spi-1.1.6.tar.gz
? at-spi-1.1.7.tar.gz
? at-spi-text-api-patch1.diff
? autom4te.cache
? cspi-object-events.diff
? cspi.diff
? new-screen-review-api.diff
? new-text-screen-review-api.diff
? docs/reference/cspi/tmpl/at-spi-cspi-unused.sgml
? docs/reference/cspi/tmpl/spi_streamable_content.sgml
? test/event-listener-test
? test/screen-review-test
? test/stress-test
? test/visual-bell
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/at-spi/ChangeLog,v
retrieving revision 1.271
diff -u -r1.271 ChangeLog
--- ChangeLog	16 Dec 2002 18:03:45 -0000	1.271
+++ ChangeLog	18 Dec 2002 13:18:46 -0000
@@ -1,3 +1,59 @@
+2002-12-17  Bill Haneman <bill.haneman@sun.com
+
+        Fix for 100944, [API addition approved by Gman and murrayc].
+	
+	* NEWS: updated.
+	
+	* configure.in:
+	Revved to 1.1.8.
+
+	* idl/Accessibility_Text.idl:
+	(Text::Range, Text::RangeList, TEXT_CLIP_TYPE): New typedefs
+	(Text::getRangeExtents): New method for efficient 
+	bounds query of a text range.
+	(Text::getBoundedRanges): New method for efficient
+	clipping of text to bounding boxes.
+	(unImplemented7, unImplemented8): 
+	Removed these padding methods to preserve bincompat.
+
+	* libspi/text.c:
+	(impl_getRangeExtents): implementation of new IDL.
+	(impl_getBoundedRanges): implementation of new IDL.
+	(SpiTextRect): Internal use struct.
+	(_spi_text_rect_union): internal method, calculates union of two
+	SpiTextRect bounding rects.
+	(_spi_text_range_seq_from_gslist): internal method, allows us
+	to build our sequence efficiently as a gslist then convert it
+	to a CORBA seq.
+	(_spi_bounds_contain): internal method, determines whether
+	a text character is "in" or "out" of a clip rect according to
+	values of TEXT_CLIP_TYPE.
+	(spi_text_class_init): Initialize the new methods in the epv.
+	
+	* cspi/spi.h:
+	(AccessibleTextClipType): New enum used by screen review api.
+	(AccessibleTextRange): New struct used by screen review api.
+	(AccessibleText_getRangeExtents): 
+	cspi binding for Accessibility_Text_getRangeExtents.
+	(AccessibleText_getBoundedRanges):
+	cspi binding for Accessibility_Text_getBoundedRanges.
+	(AccessibleTextRange_freeRanges): convenience method.
+	
+	* cspi/spi_text.c:
+	(AccessibleText_getRangeExtents): 
+	cspi binding for Accessibility_Text_getRangeExtents.
+	(AccessibleText_getBoundedRanges):
+	cspi binding for Accessibility_Text_getBoundedRanges.
+	(AccessibleTextRange_freeRanges): convenience method.
+	(get_accessible_text_clip_type): internal conversion method.
+	(get_accessible_text_ranges_from_range_seq): internal conversion method.
+
+	* registryd/deviceeventcontroller.c:
+	(spi_dec_mouse_check):
+	Improved behavior for mouse:abs events 
+	[same granularity as mouse:rel events, and no
+	events when mouse is idle].	
+	
 2002-12-16  Michael Meeks  <michael@ximian.com>
 
 	* cspi/spi_accessible.c (spi_state_to_corba): rename.
Index: NEWS
===================================================================
RCS file: /cvs/gnome/at-spi/NEWS,v
retrieving revision 1.9
diff -u -r1.9 NEWS
--- NEWS	6 Dec 2002 17:33:30 -0000	1.9
+++ NEWS	18 Dec 2002 13:18:47 -0000
@@ -1,5 +1,14 @@
 (top)
 in HEAD:
+What's new in at-spi-1.1.8:
+
+* Added getRangeExtents() and getBoundedRanges() API for more
+  efficient screen review [100944].
+
+What's new in at-spi-1.1.7:
+
+* Added spi_keymask values for Mod4 and Mod5.
+* Performance improvements and bugfixes from Michael.
 
 What's new in at-spi-1.1.6:
 
Index: configure.in
===================================================================
RCS file: /cvs/gnome/at-spi/configure.in,v
retrieving revision 1.59
diff -u -r1.59 configure.in
--- configure.in	13 Dec 2002 13:58:39 -0000	1.59
+++ configure.in	18 Dec 2002 13:18:47 -0000
@@ -2,9 +2,9 @@
 
 AT_SPI_MAJOR_VERSION=1
 AT_SPI_MINOR_VERSION=1
-AT_SPI_MICRO_VERSION=7
+AT_SPI_MICRO_VERSION=8
 AT_SPI_INTERFACE_AGE=0
-AT_SPI_BINARY_AGE=7
+AT_SPI_BINARY_AGE=8
 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)
Index: cspi/spi.h
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi.h,v
retrieving revision 1.55
diff -u -r1.55 spi.h
--- cspi/spi.h	6 Dec 2002 17:33:32 -0000	1.55
+++ cspi/spi.h	18 Dec 2002 13:18:47 -0000
@@ -59,6 +59,17 @@
 } AccessibleTextBoundaryType;
 
 /*
+ * Enumerated type for text bounds clipping types
+ */
+typedef enum
+{
+  SPI_TEXT_CLIP_NONE,
+  SPI_TEXT_CLIP_MIN,
+  SPI_TEXT_CLIP_MAX,
+  SPI_TEXT_CLIP_BOTH
+} AccessibleTextClipType;
+
+/*
  *
  * Enumerated type for relation types
  *
@@ -138,6 +149,22 @@
 
 
 /**
+ * AccessibleTextRange:
+ * @start: the first nominal character position within the range.
+ * @end: the first nominal character position following the range.
+ * @content: The actual text content between @start and @end, as a UTF-8 string.
+ *
+ * Structure which encapsulates a text range - must be associated with an
+ *          AccessibleText-implementing object.
+ **/
+typedef struct _AccessibleTextRange
+{
+  long int        start;
+  long int        end;
+  char           *contents;
+} AccessibleTextRange;
+
+/**
  * AccessibleKeySet:
  * @keysyms:
  * @keycodes:
@@ -751,6 +778,29 @@
                                     long int *width,
                                     long int *height,
 				    AccessibleCoordType type);
+
+void
+AccessibleText_getRangeExtents (AccessibleText *obj,
+				long int startOffset,
+				long int endOffset,
+				long int *x,
+				long int *y,
+				long int *width,
+				long int *height,
+				AccessibleCoordType type);
+
+AccessibleTextRange **
+AccessibleText_getBoundedRanges (AccessibleText *obj,
+				 long int x,
+				 long int y,
+				 long int width,
+				 long int height,
+				 AccessibleCoordType type,
+				 AccessibleTextClipType clipTypeX,
+				 AccessibleTextClipType clipTypeY);
+
+void
+AccessibleTextRange_freeRanges (AccessibleTextRange **ranges);
 
 long
 AccessibleText_getOffsetAtPoint (AccessibleText *obj,
Index: cspi/spi_text.c
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi_text.c,v
retrieving revision 1.22
diff -u -r1.22 spi_text.c
--- cspi/spi_text.c	16 Dec 2002 18:04:12 -0000	1.22
+++ cspi/spi_text.c	18 Dec 2002 13:18:48 -0000
@@ -62,6 +62,50 @@
   return Accessibility_TEXT_BOUNDARY_CHAR;
 }
 
+static Accessibility_TEXT_CLIP_TYPE
+get_accessible_text_clip_type (AccessibleTextClipType type)
+{
+  switch (type)
+    {
+    case SPI_TEXT_CLIP_NONE:
+      return Accessibility_TEXT_CLIP_NONE;
+      break;
+    case SPI_TEXT_CLIP_MIN:
+      return Accessibility_TEXT_CLIP_MIN;
+      break;
+    case SPI_TEXT_CLIP_MAX:
+      return Accessibility_TEXT_CLIP_MAX;
+      break;
+    }
+  return Accessibility_TEXT_CLIP_BOTH;
+}
+
+static AccessibleTextRange **
+get_accessible_text_ranges_from_range_seq (Accessibility_Text_RangeList *range_seq)
+{
+  AccessibleTextRange **ranges = NULL;
+  AccessibleTextRange *array = NULL;
+  int i;
+  if (range_seq && range_seq->_length > 0) 
+    {
+      ranges = g_new0 (AccessibleTextRange *, range_seq->_length + 1);
+    }
+  array = g_new0 (AccessibleTextRange, range_seq->_length);
+  for (i = 0; i < range_seq->_length; i++) 
+    {
+      AccessibleTextRange *range;
+      range = &array[i];
+      range->start = range_seq->_buffer[i].startOffset;
+      range->end = range_seq->_buffer[i].endOffset;
+      range->contents = CORBA_string_dup (range_seq->_buffer[i].content);
+      ranges[i] = range;
+    }
+  ranges[i] = NULL; /* null-terminated list! */
+  CORBA_free (range_seq);
+
+  return ranges;
+}
+
 
 /**
  * AccessibleText_ref:
@@ -536,6 +580,135 @@
   cspi_return_val_if_ev ("getOffsetAtPoint", -1);
 
   return retval;
+}
+
+/**
+ * AccessibleText_getRangeExtents:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @startOffset: an integer indicating the offset of the first text character for
+ *        whom boundary information is requested.
+ * @endOffset: an integer indicating the offset of the text character 
+ *        after the last character for whom boundary information is requested.
+ * @x: a pointer to a long integer into which the nominal x coordinate
+ *     of the corresponding bounding box will be returned.
+ * @y:a pointer to a long integer into which the nominal y coordinate
+ *     of the corresponding bounding box will be returned.
+ * @width:a pointer to a long integer into which the width
+ *     of the corresponding bounding box will be returned.
+ * @height: a pointer to a long integer into which the height
+ *     of the corresponding bounding box will be returned.
+ * @type: an #AccessibleCoordType indicating the coordinate system to use
+ *        for the returned values.
+ *
+ * Get the bounding box for text within a range in an  #AccessibleText object.
+ *
+ * Returns: the bounding-box extents of the specified text range,
+ *       in the specified coordinate system.
+ *
+ **/
+void
+AccessibleText_getRangeExtents (AccessibleText *obj,
+				long int startOffset,
+				long int endOffset,
+				long int *x,
+				long int *y,
+				long int *width,
+				long int *height,
+				AccessibleCoordType type)
+{
+  CORBA_long retX, retY, retWidth, retHeight;
+
+  if (obj == NULL)
+    {
+      *x = *y = -1;
+      *width = *height = -1;
+      return;
+    }
+
+  Accessibility_Text_getRangeExtents (CSPI_OBJREF (obj),
+				      startOffset,
+				      endOffset,
+				      &retX,
+				      &retY,
+				      &retWidth,
+				      &retHeight,
+				      type, cspi_ev ());
+
+  if (!cspi_check_ev ("getRangeExtents"))
+    {
+      *x = *y = -1;
+      *width = *height = -1;
+    }
+  else
+    {
+      *x = retX;
+      *y = retY;
+      *width = retWidth;
+      *height = retHeight;
+    }
+}
+
+/**
+ * AccessibleText_getBoundedRanges:
+ * @obj: a pointer to the #AccessibleText object on which to operate.
+ * @x: the 'starting' x coordinate of the bounding box.
+ * @y: the 'starting' y coordinate of the bounding box.
+ * @width: the x extent of the bounding box.
+ * @height: the y extent of the bounding box.
+ * @type: an #AccessibleCoordType indicating the coordinate system to use
+ *        for the returned values.
+ * @clipTypeX: an #AccessibleTextClipType indicating how to treat characters that
+ *        intersect the bounding box's x extents.
+ * @clipTypeY: an #AccessibleTextClipType indicating how to treat characters that
+ *        intersect the bounding box's y extents.
+ *
+ * Get the ranges of text from an #AccessibleText object which lie within the
+ *          bounds defined by (@x, @y) and (@x+@width, @y+@height).  
+ *
+ * Returns: a null-terminated list of pointers to AccessibleTextRange structs 
+ *          detailing the bounded text.
+ **/
+AccessibleTextRange **
+AccessibleText_getBoundedRanges (AccessibleText *obj,
+				 long int x,
+				 long int y,
+				 long int width,
+				 long int height,
+				 AccessibleCoordType type,
+				 AccessibleTextClipType clipTypeX,
+				 AccessibleTextClipType clipTypeY)
+{
+  Accessibility_Text_RangeList *range_seq;
+
+  cspi_return_val_if_fail (obj != NULL, NULL);
+
+  range_seq =
+    Accessibility_Text_getBoundedRanges (CSPI_OBJREF (obj), 
+					 x, y, width, height,
+					 type, 
+					 get_accessible_text_clip_type (clipTypeX), 
+					 get_accessible_text_clip_type (clipTypeY),
+					 cspi_ev ());
+
+  cspi_return_val_if_ev ("getBoundedRanges", NULL); 
+ 
+  return get_accessible_text_ranges_from_range_seq (range_seq);
+}
+
+/**
+ * AccessibleTextRange_freeRanges:
+ * @ranges: a pointer to an array of AccessibleTextRange structs.
+ *
+ * Free the memory used by a list of AccessibleTextRange structs.
+ * The argument passed in should be an array of pointers 
+ * AccessibleTextRange structs.  
+ **/
+void
+AccessibleTextRange_freeRanges (AccessibleTextRange **ranges)
+{
+  /* this was a contiguously allocated block, only free the first element */
+  g_free (ranges[0]); 
+  g_free (ranges);
 }
 
 /**
Index: idl/Accessibility_Text.idl
===================================================================
RCS file: /cvs/gnome/at-spi/idl/Accessibility_Text.idl,v
retrieving revision 1.8
diff -u -r1.8 Accessibility_Text.idl
--- idl/Accessibility_Text.idl	19 Nov 2002 20:04:19 -0000	1.8
+++ idl/Accessibility_Text.idl	18 Dec 2002 13:18:48 -0000
@@ -32,7 +32,30 @@
     TEXT_BOUNDARY_LINE_END
   };
 
+  /**
+   * TEXT_CLIP_TYPE:
+   * CLIP_MIN means text clipped by min coordinate is omitted,
+   * CLIP_MAX clips text interescted by the max coord, and CLIP_BOTH
+   * will retain only text falling fully within the min/max bounds.
+   *
+   **/
+  enum TEXT_CLIP_TYPE {
+    TEXT_CLIP_NONE,
+    TEXT_CLIP_MIN,
+    TEXT_CLIP_MAX,
+    TEXT_CLIP_BOTH
+  };
+
   interface Text : Bonobo::Unknown {
+
+    struct Range {
+      long startOffset;
+      long endOffset; 
+      string content;
+    };
+    
+    typedef sequence<Range> RangeList;
+    
     readonly attribute long characterCount;
     readonly attribute long caretOffset;
     string getText (in long startOffset, in long endOffset);
@@ -48,13 +71,21 @@
 							   */
     string getAttributes (in long offset,
 			  out long startOffset, out long endOffset);
-    void getCharacterExtents (in long offset, out long x, out long y, out long length, out long width, in short coordType);
+    void getCharacterExtents (in long offset, out long x, out long y, out long width, out long height, in short coordType);
     long getOffsetAtPoint (in long x, in long y, in short coordType);
     long getNSelections ();
     void getSelection (in long selectionNum, out long startOffset, out long endOffset);
     boolean addSelection (in long startOffset, in long endOffset);
     boolean removeSelection (in long selectionNum);
     boolean setSelection (in long selectionNum, in long startOffset, in long endOffset);
+    void    getRangeExtents (in long startOffset, in long endOffset, 
+			     out long x, out long y, 
+			     out long width, out long height, in short coordType);
+    RangeList getBoundedRanges (in long x, in long y, 
+				in long width, in long height, 
+				in short coordType, 
+				in TEXT_CLIP_TYPE xClipType, 
+				in TEXT_CLIP_TYPE yClipType);
     /**
      * unImplemented:
      *
@@ -64,7 +95,5 @@
     void unImplemented2 ();
     void unImplemented3 ();
     void unImplemented4 ();
-    void unImplemented7 ();
-    void unImplemented8 ();
   };
 };
Index: libspi/text.c
===================================================================
RCS file: /cvs/gnome/at-spi/libspi/text.c,v
retrieving revision 1.17
diff -u -r1.17 text.c
--- libspi/text.c	17 Nov 2002 13:53:56 -0000	1.17
+++ libspi/text.c	18 Dec 2002 13:18:49 -0000
@@ -32,6 +32,63 @@
 /* Our parent Gtk object type */
 #define PARENT_TYPE SPI_TYPE_BASE
 
+typedef struct {
+  gint x;
+  gint y;
+  gint w;
+  gint h;
+} SpiTextRect;
+
+static SpiTextRect *
+_spi_text_rect_union (SpiTextRect *aggregate, SpiTextRect *subrect)
+{
+  if (subrect != NULL)
+    {
+      /* 'normalize' subrect */
+      if (subrect->w < 0)
+	{
+	  subrect->x += subrect->w;
+	  subrect->w *= -1;
+	}
+      if (subrect->h < 0)
+	{
+	  subrect->y += subrect->h;
+	  subrect->h *= -1;
+	}
+      if (aggregate == NULL)
+	{
+	  aggregate = g_new (SpiTextRect, 1);
+	  memcpy (aggregate, subrect, sizeof (SpiTextRect));
+	}
+      else
+	{
+	  gint ax2 = aggregate->x + aggregate->w;
+	  gint ay2 = aggregate->y + aggregate->h; 
+	  gint sx2 = subrect->x + subrect->w; 
+	  gint sy2 = subrect->y + subrect->h;
+	  if (subrect->x < aggregate->x)
+	    {
+	      aggregate->w += (aggregate->x - subrect->x);
+	      aggregate->x = subrect->x;
+	    }
+	  if (sx2 > ax2)
+	    {
+	      aggregate->w += (sx2 - ax2);
+	    }
+	  if (subrect->y < aggregate->y)
+	    {
+	      aggregate->h += (aggregate->y - subrect->y);
+	      aggregate->y = subrect->y;
+	    }
+	  if (sy2 > ay2)
+	    {
+	      aggregate->h += (sy2 - ay2);
+	    }
+	}
+    }
+  return aggregate;
+}
+
 static AtkText *
 get_text_from_servant (PortableServer_Servant servant)
 {
@@ -390,6 +447,164 @@
   return atk_text_set_caret_offset (text, value);
 }
 
+#define SPI_TEXT_MIN_RANGE_FOR_LINE_CHECK 6
+
+static void
+impl_getRangeExtents(PortableServer_Servant servant,
+		     const CORBA_long startOffset,
+		     const CORBA_long endOffset,
+		     CORBA_long * x, CORBA_long * y,
+		     CORBA_long * width,
+		     CORBA_long * height,
+		     const CORBA_short coordType,
+		     CORBA_Environment * ev)
+{
+  AtkText *text = get_text_from_servant (servant);
+  SpiTextRect cbounds, bounds;
+  int i;
+
+  g_return_if_fail (text != NULL);
+  
+  /* no equivalent ATK API yet, must do the hard way. :-( */
+  for (i = startOffset; i > endOffset; i++) 
+    {
+      atk_text_get_character_extents (text, i,
+				      &cbounds.x, &cbounds.y, &cbounds.w, &cbounds.h,
+				      (AtkCoordType) coordType);
+      _spi_text_rect_union (&bounds, &cbounds);
+    }
+
+  *x = bounds.x;
+  *y = bounds.y;
+  *width = bounds.w;
+  *height = bounds.h;
+}
+
+static Accessibility_Text_RangeList *
+_spi_text_range_seq_from_gslist (GSList *range_list) 
+{ 
+  Accessibility_Text_RangeList *rangeList = 
+    Accessibility_Text_RangeList__alloc ();
+  int i, len = g_slist_length (range_list);
+  GSList *list = range_list;
+
+  rangeList->_length = len;
+  rangeList->_buffer = Accessibility_Text_RangeList_allocbuf (len);
+  for (i = 0; i < len; ++i) 
+    {
+      memcpy (&rangeList->_buffer[i], list->data, sizeof (Accessibility_Text_Range));
+      g_free (list->data);
+      list = g_slist_next (range_list);
+    }
+  g_slist_free (range_list);
+
+  return rangeList;
+}
+
+static gboolean
+_spi_bounds_contain (SpiTextRect *clip, SpiTextRect *cbounds, 
+		     Accessibility_TEXT_CLIP_TYPE xClipType, 
+		     Accessibility_TEXT_CLIP_TYPE yClipType)
+{
+  gint clipx2 = clip->x + clip->w;
+  gint clipy2 = clip->y + clip->h;
+  gint charx2 = cbounds->x + cbounds->w;
+  gint chary2 = cbounds->y + cbounds->h;
+  gboolean x_min_ok, y_min_ok, x_max_ok, y_max_ok;
+
+  x_min_ok = (cbounds->x >= clip->x) || 
+    ((charx2 >= clip->x) && 
+     ((xClipType == Accessibility_TEXT_CLIP_NONE) || 
+      (xClipType == Accessibility_TEXT_CLIP_MAX)));
+  x_max_ok = (charx2 <= clipx2) || 
+    ((cbounds->x <= clipx2) && 
+     ((xClipType == Accessibility_TEXT_CLIP_NONE) || 
+      (xClipType == Accessibility_TEXT_CLIP_MIN)));
+  y_min_ok = (cbounds->y >= clip->y) || 
+    ((chary2 >= clip->y) && 
+     ((yClipType == Accessibility_TEXT_CLIP_NONE) || 
+      (yClipType == Accessibility_TEXT_CLIP_MAX)));
+  y_max_ok = (chary2 <= clipy2) || 
+    ((cbounds->y <= clipy2) && 
+     ((yClipType == Accessibility_TEXT_CLIP_NONE) || 
+      (yClipType == Accessibility_TEXT_CLIP_MIN)));
+  
+  if (x_min_ok && y_min_ok && x_max_ok && y_max_ok)
+    return TRUE;
+  else 
+    return FALSE;
+}
+
+Accessibility_Text_RangeList *
+impl_getBoundedRanges(PortableServer_Servant servant,
+		      const CORBA_long x,
+		      const CORBA_long y,
+		      const CORBA_long width,
+		      const CORBA_long height,
+		      const CORBA_short coordType,
+		      const Accessibility_TEXT_CLIP_TYPE xClipType,
+		      const Accessibility_TEXT_CLIP_TYPE yClipType, 
+		      CORBA_Environment * ev)
+{
+  AtkText *text = get_text_from_servant (servant);
+  GSList *range_list = NULL;
+  SpiTextRect clip;
+  int startOffset = 0, endOffset = atk_text_get_character_count (text);
+  int curr_offset;
+  gint minLineStart, minLineEnd, maxLineStart, maxLineEnd;
+  long bounds_min_offset;
+
+  clip.x = x;
+  clip.y = y;
+  clip.w = width;
+  clip.h = height;
+
+  /* for horizontal text layouts, at least, the following check helps. */
+  bounds_min_offset =  atk_text_get_offset_at_point (text, x, y, 
+						     (AtkCoordType) coordType);
+  atk_text_get_text_at_offset (text, bounds_min_offset, 
+			       ATK_TEXT_BOUNDARY_LINE_START,
+			       &minLineStart, &minLineEnd);
+  atk_text_get_text_at_offset (text, bounds_min_offset, 
+			       ATK_TEXT_BOUNDARY_LINE_START,
+			       &maxLineStart, &maxLineEnd);
+  startOffset = MIN (minLineStart, maxLineStart);
+  endOffset  = MIN (minLineEnd, maxLineEnd);
+
+  curr_offset = startOffset;
+
+  while (curr_offset < endOffset) 
+    {
+      int offset = startOffset;
+      SpiTextRect cbounds;
+      while (curr_offset < endOffset) 
+	{
+	  atk_text_get_character_extents (text, curr_offset, 
+					  &cbounds.x, &cbounds.y, 
+					  &cbounds.w, &cbounds.h, 
+					  (AtkCoordType) coordType);
+	  if (!_spi_bounds_contain (&clip, &cbounds, xClipType, yClipType))
+	    break;
+	  curr_offset++;
+	}
+      /* add the range to our list */
+      if (curr_offset > offset) 
+	{
+	  Accessibility_Text_Range *range = g_malloc (sizeof (Accessibility_Text_Range));
+	  char *s;
+	  range->startOffset = offset;
+	  range->endOffset = curr_offset;
+	  s = atk_text_get_text (text, offset, curr_offset);
+	  range->content = CORBA_string_dup (s ? s : "");
+	  range_list = g_slist_append (range_list, range);
+	  offset = curr_offset;
+	}
+      offset++;
+    }  
+  return _spi_text_range_seq_from_gslist (range_list); /* frees the GSList too */
+}
+
+
 static void
 spi_text_class_init (SpiTextClass *klass)
 {
@@ -413,6 +628,8 @@
   epv->removeSelection = impl_removeSelection;
   epv->setSelection = impl_setSelection;
   epv->setCaretOffset = impl_setCaretOffset;
+  epv->getRangeExtents = impl_getRangeExtents;
+  epv->getBoundedRanges = impl_getBoundedRanges;
 }
 
 static void
Index: registryd/deviceeventcontroller.c
===================================================================
RCS file: /cvs/gnome/at-spi/registryd/deviceeventcontroller.c,v
retrieving revision 1.58
diff -u -r1.58 deviceeventcontroller.c
--- registryd/deviceeventcontroller.c	6 Dec 2002 14:35:11 -0000	1.58
+++ registryd/deviceeventcontroller.c	18 Dec 2002 13:18:50 -0000
@@ -190,8 +190,6 @@
   priv->pending_xkb_mod_relatch_mask |= priv->xkb_latch_mask; 
 }
  
-static gint poll_count = 0;
-
 static gboolean
 spi_dec_button_update_and_emit (SpiDEController *controller, 
 				guint mask_return)
@@ -327,7 +325,6 @@
   Accessibility_Event e;
   CORBA_Environment ev;
   int win_x_return,win_y_return;
-  int poll_count_modulus = 10;
   unsigned int mask_return;
   Window root_return, child_return;
   Display *display = spi_get_display ();
@@ -349,20 +346,17 @@
       while (spi_dec_button_update_and_emit (controller, mask_return));
     }
 
-  if (poll_count++ == poll_count_modulus) {
-    poll_count = 0;
-    e.type = "mouse:abs";  
-    e.source = BONOBO_OBJREF (controller->registry->desktop);
-    e.detail1 = *x;
-    e.detail2 = *y;
-    spi_init_any_nil (&e.any_data);
-    CORBA_exception_init (&ev);
-    Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
-					&e,
-					&ev);
-  }
   if (*x != last_mouse_pos->x || *y != last_mouse_pos->y) 
     {
+      e.type = "mouse:abs";  
+      e.source = BONOBO_OBJREF (controller->registry->desktop);
+      e.detail1 = *x;
+      e.detail2 = *y;
+      spi_init_any_nil (&e.any_data);
+      CORBA_exception_init (&ev);
+      Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
+					  &e,
+					  &ev);
       e.type = "mouse:rel";  
       e.source = BONOBO_OBJREF (controller->registry->desktop);
       e.detail1 = *x - last_mouse_pos->x;
