Index: src/orca/atspi.py
===================================================================
--- src/orca/atspi.py	(revision 2946)
+++ src/orca/atspi.py	(working copy)
@@ -91,7 +91,8 @@
             # http://bugzilla.gnome.org/show_bug.cgi?id=395749 for
             # more information.
             #
-            if self.type.startswith("object:active-descendant-changed"):
+            if self.type.startswith("object:active-descendant-changed") \
+               or self.type.startswith("object:children-changed"):
                 self.any_data = Accessible.makeAccessible(
                     self.any_data.value())
             elif self.type.startswith("object:text-changed:insert"):
Index: src/orca/default.py
===================================================================
--- src/orca/default.py	(revision 2946)
+++ src/orca/default.py	(working copy)
@@ -1911,6 +1911,48 @@
 
         self.speakTextSelectionState(obj, startOffset, endOffset)
 
+    def handleTooltip(self, obj, visible=True):
+        """
+        Handles the appearance/disappearance of tooltips.
+
+        Arguments:
+        - obj: the object of interest
+        - visible: Whether or not the tooltip is visible.
+        """
+
+        if not obj:
+            return
+        
+        # We only want to present tooltips if the user preference
+        # indicates we should do so, or if the user caused the
+        # tooltip to appear/disappear via the keyboard (Control+F1)
+        #
+        lastKey = orca_state.lastNonModifierKeyEvent
+        usedCommand = lastKey and lastKey.event_string == "F1" \
+                      and isinstance(orca_state.lastInputEvent,
+                                     input_event.KeyboardEvent)
+        if orca.settings.presentToolTips or usedCommand:
+            if visible:
+                self.presentTooltip(obj)
+            elif orca_state.locusOfFocus:
+                # If the tooltip disappeared, we want to clear the
+                # display regardless of whether a command was used
+                # or not.  If a command was used, we should also
+                # speak the locusOfFocus.
+                #
+                self.updateBraille(orca_state.locusOfFocus)
+                if usedCommand:
+                    speech.speakUtterances( \
+                        self.speechGenerator.getSpeech( \
+                        orca_state.locusOfFocus,
+                        False))
+
+        # Delete the cached accessible to force the AT-SPI to update
+        # the accessible cache. Otherwise, the event references the
+        # previous popup object.
+        #
+        atspi.Accessible.deleteAccessible(obj._acc)
+
     def presentTooltip(self, obj):
         """
         Speaks the tooltip for the current object of interest.
@@ -3001,27 +3043,26 @@
 
         # Handle tooltip popups.
         #
-        if event.source.role == rolenames.ROLE_TOOL_TIP:
+        if event.source.role == rolenames.ROLE_TOOL_TIP \
+           and event.type.startswith("object:state-changed:showing"):
+            self.handleTooltip(event.source, event.detail1)
+
+        # It seems that the original GTK tooltips have been deprecated.
+        # Now when we GTK tooltips, they are windows with a number of
+        # descendants.  At the bottom is an icon whose sibling is a
+        # label which contains the tooltip.
+        #
+        elif event.source.role == rolenames.ROLE_WINDOW \
+             and event.type.startswith("object:state-changed:visible"):
             obj = event.source
+            text = self.getDisplayedText(obj)
+            while obj.childCount:
+                obj = obj.child(0)
+            if obj.role == rolenames.ROLE_ICON and obj.parent.childCount > 1:
+                obj = obj.parent.child(1)
+                if obj.role == rolenames.ROLE_LABEL:
+                    self.handleTooltip(obj, event.detail1)
 
-            if event.type.startswith("object:state-changed:showing"):
-                if event.detail1 == 1:
-                    self.presentTooltip(obj)
-                elif orca_state.locusOfFocus \
-                    and isinstance(orca_state.lastInputEvent,
-                                   input_event.KeyboardEvent) \
-                    and (orca_state.lastNonModifierKeyEvent.event_string == "F1"):
-                    self.updateBraille(orca_state.locusOfFocus)
-                    speech.speakUtterances(self.speechGenerator.getSpeech(
-                        orca_state.locusOfFocus,
-                        False))
-
-            # Delete the cached accessible to force the AT-SPI to update
-            # the accessible cache. Otherwise, the event references the
-            # previous popup object.
-            atspi.Accessible.deleteAccessible(obj._acc)
-            return
-
         if state_change_notifiers.has_key(event.source.role):
             notifiers = state_change_notifiers[event.source.role]
             found = False
Index: src/orca/Gecko.py
===================================================================
--- src/orca/Gecko.py	(revision 2946)
+++ src/orca/Gecko.py	(working copy)
@@ -2195,6 +2195,8 @@
             self.onDocumentLoadStopped
         listeners["object:visible-data-changed"]            = \
             self.onVisibleDataChanged
+        listeners["object:children-changed:"]               = \
+            self.onChildrenChanged
 
         # [[[TODO: HACK - WDW we need to accomodate Gecko's incorrect
         # use of underscores instead of dashes until they fix their bug.
@@ -3454,6 +3456,15 @@
         except:
             pass
 
+        # Handle tooltips.  [[[TODO - JD:  Currently we don't get this
+        # event to let us know that a tooltip has vanished until another
+        # tooltip has taken its place. In the spirit of hoping this gets
+        # fixed soon and not wanting to forget to add it later....]]]
+        #
+        if event.source.role == rolenames.ROLE_LABEL:
+            self.handleTooltip(event.source, False)
+            return
+
         # The search entries in Firefox's and Thunderbird's top toolbars
         # contain text which functions as the label (Yahoo, Entire Message)
         # and which gets deleted just prior to the entry gaining focus.  If
@@ -3490,6 +3501,12 @@
         except:
             pass
 
+        # Handle tooltips.
+        #
+        if event.source.role == rolenames.ROLE_LABEL:
+            self.handleTooltip(event.source, True)
+            return
+
         default.Script.onTextInserted(self, event)
 
     def onDocumentReload(self, event):
@@ -3527,6 +3544,19 @@
         #
         return
 
+    def onChildrenChanged(self, event):
+        """Called whenever a child object changes in some way.
+
+        Arguments:
+        - event: the Event
+        """
+
+        anyData = event.any_data
+        if anyData and anyData.role \
+           and anyData.role == rolenames.ROLE_TOOL_TIP:
+            visible = (event.type.find("add") >= 0)
+            self.handleTooltip(anyData, visible)
+
     def onFocus(self, event):
 
         # If this event is the result of our calling grabFocus() on
