Added new, more efficient screen review API to AccessibleText.
authorbillh <billh@e2bd861d-eb25-0410-b326-f6ed22b6b98c>
Wed, 18 Dec 2002 15:28:41 +0000 (15:28 +0000)
committerbillh <billh@e2bd861d-eb25-0410-b326-f6ed22b6b98c>
Wed, 18 Dec 2002 15:28:41 +0000 (15:28 +0000)
See bug 100944.

git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@390 e2bd861d-eb25-0410-b326-f6ed22b6b98c

ChangeLog
NEWS
configure.in
cspi/spi.h
cspi/spi_text.c
idl/Accessibility_Text.idl
libspi/text.c
registryd/deviceeventcontroller.c

index 10f872b..e383dee 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/NEWS b/NEWS
index b73df4d..6e7869b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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 cc4e46c..2148189 100644 (file)
@@ -2,9 +2,9 @@ AC_INIT(idl/Accessibility.idl)
 
 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 2b3a511..ac93bcf 100644 (file)
@@ -59,6 +59,17 @@ typedef enum
 } 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 @@ typedef enum {
 
 
 /**
+ * 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:
@@ -752,6 +779,29 @@ AccessibleText_getCharacterExtents (AccessibleText *obj,
                                     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,
                                  long int x,
index e1b57ad..7579bd0 100644 (file)
@@ -62,6 +62,50 @@ get_accessible_text_boundary_type (AccessibleTextBoundaryType type)
   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:
@@ -539,6 +583,135 @@ AccessibleText_getOffsetAtPoint (AccessibleText *obj,
 }
 
 /**
+ * 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);
+}
+
+/**
  * AccessibleText_getNSelections:
  * @obj: a pointer to the #AccessibleText object on which to operate.
  *
index 268eb35..49fe577 100644 (file)
@@ -32,7 +32,31 @@ module Accessibility {
     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;
+      any  data;
+    };
+    
+    typedef sequence<Range> RangeList;
+    
     readonly attribute long characterCount;
     readonly attribute long caretOffset;
     string getText (in long startOffset, in long endOffset);
@@ -48,13 +72,21 @@ module Accessibility {
                                                           */
     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 +96,5 @@ module Accessibility {
     void unImplemented2 ();
     void unImplemented3 ();
     void unImplemented4 ();
-    void unImplemented7 ();
-    void unImplemented8 ();
   };
 };
index 8aa5764..c8e6d1c 100644 (file)
 /* 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,165 @@ impl_setCaretOffset (PortableServer_Servant servant,
   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));
+      spi_init_any_nil (&rangeList->_buffer[i].data);
+      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 +629,8 @@ spi_text_class_init (SpiTextClass *klass)
   epv->removeSelection = impl_removeSelection;
   epv->setSelection = impl_setSelection;
   epv->setCaretOffset = impl_setCaretOffset;
+  epv->getRangeExtents = impl_getRangeExtents;
+  epv->getBoundedRanges = impl_getBoundedRanges;
 }
 
 static void
index c51fff3..f872562 100644 (file)
@@ -190,8 +190,6 @@ spi_dec_set_unlatch_pending (SpiDEController *controller, unsigned mask)
   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 @@ spi_dec_mouse_check (SpiDEController *controller,
   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 @@ spi_dec_mouse_check (SpiDEController *controller,
       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;