Index: src/orca/default.py
===================================================================
--- src/orca/default.py	(revision 3494)
+++ src/orca/default.py	(working copy)
@@ -2434,6 +2434,22 @@
                 #
                 utterances.append(_("tree level %d") % (newNodeLevel + 1))
 
+            # If this is a table cell within a tree table and the item
+            # is focused but not selected, let the user know. See
+            # bug #486908 for more details.
+            #
+            state = newLocusOfFocus.getState()
+            if newLocusOfFocus.getRole() == pyatspi.ROLE_TABLE_CELL and \
+               (newLocusOfFocus.parent.getRole() == pyatspi.ROLE_TREE_TABLE or \
+                newLocusOfFocus.parent.getRole() == pyatspi.ROLE_TABLE) and \
+               not state.contains(pyatspi.STATE_SELECTED):
+                 # Translators: this is in reference to a table cell being
+                 # selected or not.
+                 #
+                 # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+                 #
+                 utterances.append(Q_("tablecell| not selected"))
+
             # We might be automatically speaking the unbound labels
             # in a dialog box as the result of the dialog box suddenly
             # appearing.  If so, don't interrupt this because of a
@@ -3228,6 +3244,36 @@
         if not event or not event.source:
             return
 
+        # If this event is for a tree table and that tree table is the same
+        # as the parent of the object that currently has focus and the last
+        # keyboard event wasn't a Return, let the user know the current 
+        # selection state. See bug #486908 for more details.
+        #
+        if (event.source.getRole() == pyatspi.ROLE_TREE_TABLE or \
+            event.source.getRole() == pyatspi.ROLE_TABLE) and \
+           self.isSameObject(event.source, orca_state.locusOfFocus.parent):
+            if isinstance(orca_state.lastInputEvent, input_event.KeyboardEvent):
+                keyString = orca_state.lastNonModifierKeyEvent.event_string
+                if keyString != "Return":
+                    state = orca_state.locusOfFocus.getState()
+                    locusOfFocusSelected = \
+                                 state.contains(pyatspi.STATE_SELECTED)
+
+                    if locusOfFocusSelected:
+                        # Translators: this object is now selected.
+                        # Let the user know this.
+                        #
+                        # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+                        #
+                        speech.speak(Q_("text|selected"), None, False)
+                    else:
+                        # Translators: this object is now unselected.
+                        # Let the user know this.
+                        #
+                        # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+                        #
+                        speech.speak(Q_("text|unselected"), None, False)
+
         # Avoid doing this with objects that manage their descendants
         # because they'll issue a descendant changed event.
         #
