Index: src/orca/scripts/gedit.py
===================================================================
--- src/orca/scripts/gedit.py	(revision 2824)
+++ src/orca/scripts/gedit.py	(working copy)
@@ -533,7 +533,7 @@
         # from the text area when it regains focus.
         # (See bug #350854 for more details).
         #
-        if (event.type == "object:state-changed:focused") \
+        if event.type.startswith("object:state-changed:focused") \
            and (event.detail1):
             orca.setLocusOfFocus(event, event.source)
 
Index: src/orca/scripts/gnome-panel.py
===================================================================
--- src/orca/scripts/gnome-panel.py	(revision 2824)
+++ src/orca/scripts/gnome-panel.py	(working copy)
@@ -77,7 +77,7 @@
         # Handle tooltip popups.
         #
         if obj.role == rolenames.ROLE_TOOL_TIP:
-            if event.type == "object:state-changed:showing" and \
+            if event.type.startswith("object:state-changed:showing") and \
                event.detail1 == 1:
                 braille.displayMessage(obj.name)
                 speech.speak(obj.name)
@@ -95,7 +95,7 @@
         # and updates the braille display to "panel."
         #
         elif obj.role == rolenames.ROLE_PANEL and \
-             event.type == "object:state-changed:focused" and \
+             event.type.startswith("object:state-changed:focused") and \
              event.detail1 == 1 and not \
              event.source.state.count(atspi.Accessibility.STATE_FOCUSED):
             return
Index: src/orca/scripts/metacity.py
===================================================================
--- src/orca/scripts/metacity.py	(revision 2824)
+++ src/orca/scripts/metacity.py	(working copy)
@@ -126,7 +126,7 @@
         #
         if event.source.role != rolenames.ROLE_STATUSBAR:
             default.Script.onStateChanged(self, event)
-        elif (event.type == "object:state-changed:showing") \
+        elif (event.type.startswith("object:state-changed:showing")) \
             and event.detail1:
             self.presentStatusBar(event.source)
 
Index: src/orca/scripts/acroread.py
===================================================================
--- src/orca/scripts/acroread.py	(revision 2824)
+++ src/orca/scripts/acroread.py	(working copy)
@@ -520,7 +520,7 @@
         - event: the Event
         """
 
-        if event.type == "object:state-changed:checked" and \
+        if event.type.startswith("object:state-changed:checked") and \
            event.source.role == rolenames.ROLE_RADIO_BUTTON:
             # Radio buttons in the Search panel are not automatically
             # selected when you arrow to them.  You have to press Space
@@ -529,7 +529,7 @@
             orca.visualAppearanceChanged(event, event.source)
             return
 
-        elif event.type == "object:state-changed:focused" and \
+        elif event.type.startswith("object:state-changed:focused") and \
              event.detail1 == 1:
             if event.source.role == rolenames.ROLE_PUSH_BUTTON:
                 # Try to minimize chattiness in the Search panel
Index: src/orca/scripts/StarOffice.py
===================================================================
--- src/orca/scripts/StarOffice.py	(revision 2824)
+++ src/orca/scripts/StarOffice.py	(working copy)
@@ -1550,7 +1550,7 @@
         # comment #18 of bug #354463.
         #
         if self.findCommandRun and \
-           event.type == "object:state-changed:focused":
+           event.type.startswith("object:state-changed:focused"):
             self.findCommandRun = False
             self.find()
             return
@@ -1944,7 +1944,7 @@
         # If this is a state change "focused" event that we care about, and
         # we are in Writer, check to see if we are entering or leaving a table.
         #
-        if event.type == "object:state-changed:focused" and event.detail1 == 1:
+        if event.type.startswith("object:state-changed:focused") and event.detail1 == 1:
             current = event.source.parent
             while current.role != rolenames.ROLE_APPLICATION:
                 # Translators: this is the title of the window that
@@ -1964,7 +1964,7 @@
         # Prevent  "object:state-changed:active" events from activating
         # the find operation. See comment #18 of bug #354463.
         #
-        if event.type == "object:state-changed:active":
+        if event.type.startswith("object:state-changed:active"):
             if self.findCommandRun:
                 return
 
@@ -1982,7 +1982,7 @@
         # Announce when the toolbar buttons are toggled if we just toggled
         # them; not if we navigated to some text.
         #
-        if event.type == "object:state-changed:checked" and \
+        if event.type.startswith("object:state-changed:checked") and \
            (event.source.role == rolenames.ROLE_TOGGLE_BUTTON or \
             event.source.role == rolenames.ROLE_PUSH_BUTTON):
             weToggledIt = False
@@ -2010,7 +2010,7 @@
         # If we are FOCUSED on a paragraph inside a table cell (in Writer),
         # then speak/braille that parent table cell (see bug #382415).
         #
-        if event.type == "object:state-changed:focused" and \
+        if event.type.startswith("object:state-changed:focused") and \
            event.source.role == rolenames.ROLE_PARAGRAPH and \
            event.source.parent.role == rolenames.ROLE_TABLE_CELL and \
            event.detail1 == 0 and \
@@ -2042,7 +2042,7 @@
         # instead of focus:). The second is a caret-moved
         # event. Just set the locusOfFocus for the first event.
         #
-        if event.type == "object:state-changed:focused" and \
+        if event.type.startswith("object:state-changed:focused") and \
            event.source.role == rolenames.ROLE_PARAGRAPH and \
            event.source != self.currentParagraph:
             self.currentParagraph = event.source
Index: src/orca/settings.py
===================================================================
--- src/orca/settings.py	(revision 2824)
+++ src/orca/settings.py	(working copy)
@@ -527,6 +527,12 @@
 #
 useBonoboMain           = True
 
+# If True, we handle events asynchronously - our normal mode of
+# queueing events and processing them later on the gidle thread.
+# If False, we handle events immediately - helpful for testing.
+#
+asyncMode               = True
+
 # If True, we output debug information for the event queue.  We
 # use this in addition to log level to prevent debug logic from
 # bogging down event handling.
Index: src/orca/mag.py
===================================================================
--- src/orca/mag.py	(revision 2824)
+++ src/orca/mag.py	(working copy)
@@ -454,7 +454,7 @@
 
     if extents:
         [x, y, width, height] = extents
-    elif event and (event.type == "object:text-caret-moved") \
+    elif event and event.type.startswith("object:text-caret-moved") \
        and obj.text and (obj.text.caretOffset >= 0):
         offset = obj.text.caretOffset
         [x, y, width, height] = obj.text.getCharacterExtents(offset,
Index: src/orca/atspi.py
===================================================================
--- src/orca/atspi.py	(revision 2824)
+++ src/orca/atspi.py	(working copy)
@@ -91,12 +91,12 @@
             # http://bugzilla.gnome.org/show_bug.cgi?id=395749 for
             # more information.
             #
-            if self.type == "object:active-descendant-changed":
+            if self.type.startswith("object:active-descendant-changed"):
                 self.any_data = Accessible.makeAccessible(
                     self.any_data.value())
-            elif self.type == "object:text-changed:insert":
+            elif self.type.startswith("object:text-changed:insert"):
                 self.any_data = self.any_data.value()
-            elif self.type == "object:text-changed:delete":
+            elif self.type.startswith("object:text-changed:delete"):
                 self.any_data = self.any_data.value()
         else:
             self.source   = None
@@ -535,7 +535,7 @@
         if Accessible._cache.has_key(e.source):
             # Let's get rid of defunct objects.  We hate them.
             #
-            if e.type == "object:state-changed:defunct":
+            if e.type.startswith("object:state-changed:defunct"):
                 Accessible.deleteAccessible(e.source)
             else:
                 obj = Accessible._cache[e.source]
Index: src/orca/default.py
===================================================================
--- src/orca/default.py	(revision 2824)
+++ src/orca/default.py	(working copy)
@@ -2277,7 +2277,7 @@
             # focus event that occurs when something like the "OK"
             # button gets focus shortly after the window appears.
             #
-            shouldNotInterrupt = (event and event.type == "focus:") \
+            shouldNotInterrupt = (event and event.type.startswith("focus:")) \
                 and self.windowActivateTime \
                 and ((time.time() - self.windowActivateTime) < 1.0)
 
@@ -2956,13 +2956,13 @@
 
         # Do we care?
         #
-        if event.type == "object:state-changed:active":
+        if event.type.startswith("object:state-changed:active"):
             if self.findCommandRun:
                 self.findCommandRun = False
                 self.find()
                 return
 
-        if event.type == "object:state-changed:focused":
+        if event.type.startswith("object:state-changed:focused"):
             iconified = False
             try:
                 window = self.getTopLevel(event.source)
@@ -2988,7 +2988,7 @@
         if event.source.role == rolenames.ROLE_TOOL_TIP:
             obj = event.source
 
-            if event.type == "object:state-changed:showing":
+            if event.type.startswith("object:state-changed:showing"):
                 if event.detail1 == 1:
                     self.presentTooltip(obj)
                 elif orca_state.locusOfFocus \
Index: src/orca/focus_tracking_presenter.py
===================================================================
--- src/orca/focus_tracking_presenter.py	(revision 2824)
+++ src/orca/focus_tracking_presenter.py	(working copy)
@@ -512,7 +512,7 @@
         # generally do not like object:children-changed:remove events,
         # either.
         #
-        if event.type == "object:children-changed:remove":
+        if event.type.startswith("object:children-changed:remove"):
             if event.source == atspi.Accessible.makeAccessible(
                                    self.registry.desktop):
                 self._reclaimScripts()
@@ -601,8 +601,8 @@
                     # in use, and then issues a focus: event on the
                     # main window, which is a frame.]]]
                     #
-                    if (event.type == "window:activate") \
-                       or ((event.type == "focus:") \
+                    if event.type.startswith("window:activate") \
+                       or (event.type.startswith("focus:") \
                            and (event.source.role == rolenames.ROLE_FRAME)):
 
                         # We'll let someone else decide if it's important
@@ -699,7 +699,7 @@
             # We ignore defunct objects and let the atspi module take
             # care of them for us.
             #
-            if (e.type == "object:state-changed:defunct"):
+            if e.type.startswith("object:state-changed:defunct"):
                 if settings.debugEventQueue:
                     self._enqueueEventCount -= 1
                 return
@@ -710,7 +710,7 @@
             # hierarchy, so we just ignore them and let the atspi
             # module take care of it for us.
             #
-            if e.type == "object:property-change:accessible-parent":
+            if e.type.startswith("object:property-change:accessible-parent"):
                 if settings.debugEventQueue:
                     self._enqueueEventCount -= 1
                 return
@@ -718,7 +718,7 @@
             # At this point in time, we only care when objects are
             # removed from the desktop.
             #
-            if (e.type == "object:children-changed:remove") \
+            if e.type.startswith("object:children-changed:remove") \
                 and (e.source != self.registry.desktop):
                 if settings.debugEventQueue:
                     self._enqueueEventCount -= 1
@@ -761,7 +761,7 @@
             if settings.debugEventQueue:
                 debug.println(debug.LEVEL_ALL,
                               "           ...put complete")
-            if not self._gidleId:
+            if settings.asyncMode and (not self._gidleId):
                 if settings.gilSleepTime:
                     time.sleep(settings.gilSleepTime)
                 self._gidleId = gobject.idle_add(self._dequeueEvent)
@@ -773,6 +773,10 @@
             if settings.debugEventQueue:
                 debug.println(debug.LEVEL_ALL,
                               "           ...released")
+
+            if not settings.asyncMode:
+                self._dequeueEvent()
+
         if settings.debugEventQueue:
             self._enqueueEventCount -= 1
 
Index: src/orca/Gecko.py
===================================================================
--- src/orca/Gecko.py	(revision 2824)
+++ src/orca/Gecko.py	(working copy)
@@ -3515,7 +3515,7 @@
         # radio button with the mouse, we'll wind up speaking the
         # state twice because of the focus event.
         #
-        if event.type == "object:state-changed:checked" \
+        if event.type.startswith("object:state-changed:checked") \
            and event.source \
            and (event.source.role == rolenames.ROLE_RADIO_BUTTON) \
            and (event.detail1 == 1) \
@@ -3529,7 +3529,7 @@
         # If an autocomplete appears beneath an entry, we don't want
         # to prevent the user from being able to arrow into it.
         #
-        if event.type == "object:state-changed:showing" \
+        if event.type.startswith("object:state-changed:showing") \
            and event.source \
            and (event.source.role == rolenames.ROLE_WINDOW) \
            and orca_state.locusOfFocus:
@@ -3540,7 +3540,7 @@
         # We care when the document frame changes it's busy state.  That
         # means it has started/stopped loading content.
         #
-        if event.type == "object:state-changed:busy":
+        if event.type.startswith("object:state-changed:busy"):
             if event.source \
                 and (event.source.role == rolenames.ROLE_DOCUMENT_FRAME):
                 finishedLoading = False
Index: src/orca/J2SE-access-bridge.py
===================================================================
--- src/orca/J2SE-access-bridge.py	(revision 2824)
+++ src/orca/J2SE-access-bridge.py	(working copy)
@@ -261,7 +261,7 @@
         # item.
         #
         if event.source.role == rolenames.ROLE_ROOT_PANE and \
-               event.type == "object:state-changed:focused" and \
+               event.type.startswith("object:state-changed:focused") and \
                event.detail1 == 1:
 
             for i in range(0, event.source.childCount):
@@ -281,21 +281,21 @@
         # In java applications the events are comming in other order:
         # "focus:" event comes before "state-changed:focused" event
         #
-        if (event.type == "object:state-changed:focused"):
+        if event.type.startswith("object:state-changed:focused"):
             return
 
         # Hand state changes when JTree labels become expanded
         # or collapsed.
         #
-        if ((event.source.role == rolenames.ROLE_LABEL) and \
-            (event.type == "object:state-changed:expanded")):
+        if (event.source.role == rolenames.ROLE_LABEL) and \
+            event.type.startswith("object:state-changed:expanded"):
             orca.visualAppearanceChanged(event, event.source)
             return
 
         # Present a value change in case of an focused popup menu.
         # Fix for Swing file chooser.
         #
-        if event.type == "object:state-changed:visible" and \
+        if event.type.startswith("object:state-changed:visible") and \
                 event.source.role == rolenames.ROLE_POPUP_MENU and \
                 event.source.parent.state.count(Accessibility.STATE_FOCUSED):
             orca.setLocusOfFocus(event, event.source.parent)
@@ -370,7 +370,7 @@
         # manage check boxes in java application
         #
         if event.source.role == rolenames.ROLE_CHECK_BOX and \
-               event.type == "object:property-change:accessible-value":
+               event.type.startswith("object:property-change:accessible-value"):
             return
 
         default.Script.onValueChanged(self, event)
