orca r4268 - in branches/phase2/src/orca: . plugins



Author: wwalker
Date: Mon Sep 29 17:01:09 2008
New Revision: 4268
URL: http://svn.gnome.org/viewvc/orca?rev=4268&view=rev

Log:
Turn script into a GObject and add some signals.


Modified:
   branches/phase2/src/orca/default.py
   branches/phase2/src/orca/plugins/automatic.py
   branches/phase2/src/orca/script.py

Modified: branches/phase2/src/orca/default.py
==============================================================================
--- branches/phase2/src/orca/default.py	(original)
+++ branches/phase2/src/orca/default.py	Mon Sep 29 17:01:09 2008
@@ -29,6 +29,8 @@
 
 import brlapi
 
+import pyatspi
+
 import input_binding
 import input_event
 import settings
@@ -97,16 +99,46 @@
         # Lacking scripts, I'm putting it here and uncommenting it as I
         # work. :-)
         #
-        try:
-            import plugins.structural_navigation
-            pluginClasses.append(plugins.structural_navigation.Plugin)
-        except:
-            log.exception("handled exception while importing module:")
+        #try:
+        #    import plugins.structural_navigation
+        #    pluginClasses.append(plugins.structural_navigation.Plugin)
+        #except:
+        #    log.exception("handled exception while importing module:")
 
         return script.Script._getPluginClasses(self) + pluginClasses
 
     ####################################################################
     #                                                                  #
+    # UTILITIES TO HELP NORMALIZE ACCESS TO THE AT-SPI.  SUBSCRIPTS    #
+    # SHOULD OVERRIDE THESE IF THEY NEED TO DO DIFFERENT THINGS TO GET #
+    # THE DESIRED RESULTS.                                             #
+    #                                                                  #
+    ####################################################################
+
+    def getTopLevel(self, accessible):
+        """Returns the top-level object (frame, dialog ...) containing this
+        object, or None if this object is not inside a top-level object.
+
+        Arguments:
+        - accessible: the Accessible object
+        """
+        while accessible \
+            and accessible.parent \
+            and (accessible != accessible.parent) \
+            and (accessible.parent.getRole() != pyatspi.ROLE_APPLICATION):
+            accessible = accessible.parent
+
+        if accessible \
+            and accessible.parent \
+            and (accessible.parent.getRole() == pyatspi.ROLE_APPLICATION):
+            pass
+        else:
+            accessible = None
+
+        return accessible
+
+    ####################################################################
+    #                                                                  #
     # AT-SPI OBJECT EVENT HANDLERS                                     #
     #                                                                  #
     ####################################################################
@@ -115,6 +147,32 @@
         """Called on AT-SPI focus events.
         """
         log.debug("_focusListener: %s" % str(event).replace("\n", " "))
+
+        # [[[TODO: WDW - HACK to deal with quirky GTK+ menu behavior.
+        # The problem is that when moving to submenus in a menu, the
+        # menu gets focus first and then the submenu gets focus all
+        # with a single keystroke.  So...focus in menus really means
+        # that the object has focus *and* it is selected.  Now, this
+        # assumes the selected state will be set before focus is given,
+        # which appears to be the case from empirical analysis of the
+        # event stream.  But of course, all menu items and menus in
+        # the complete menu path will have their selected state set,
+        # so, we really only care about the leaf menu or menu item
+        # that it selected.]]]
+        #
+        if event.source.getRole() in (pyatspi.ROLE_MENU,
+                                      pyatspi.ROLE_MENU_ITEM,
+                                      pyatspi.ROLE_CHECK_MENU_ITEM,
+                                      pyatspi.ROLE_RADIO_MENU_ITEM):
+            try:
+                if event.source.querySelection().nSelectedChildren > 0:
+                    return
+            except:
+                pass
+
+        oldFocus = self.focus
+        self.focus = event.source
+        self.emit("focus-changed", oldFocus, self.focus)
     _focusListener.events = ["focus:"]
 
     def _activeDescendantChangedListener(self, event):
@@ -174,11 +232,20 @@
         log.debug("_linkSelectedListener: %s" % str(event).replace("\n", " "))
     _linkSelectedListener.events = ["object:link-selected"]
 
-    def _stateChangedListener(self, event):
+    def _stateChangedFocusedListener(self, event):
         """Called on AT-SPI object:state-changed events.
         """
-        log.debug("_stateChangedListener: %s" % str(event).replace("\n", " "))
-    _stateChangedListener.events = ["object:state-changed"]
+        log.debug("_stateChangedFocusedListener: %s" \
+                      % str(event).replace("\n", " "))
+        iconified = False
+        try:
+            window = self.getTopLevel(event.source)
+            iconified = window.getState().contains(pyatspi.STATE_ICONIFIED)
+        except:
+            log.exception("exception handled getting frame of focused item:")
+        if not iconified and  event.detail1:
+            self._focusListener(event)
+    _stateChangedFocusedListener.events = ["object:state-changed:focused"]
 
     def _valueChangedListener(self, event):
         """Called on AT-SPI object:value-changed and

Modified: branches/phase2/src/orca/plugins/automatic.py
==============================================================================
--- branches/phase2/src/orca/plugins/automatic.py	(original)
+++ branches/phase2/src/orca/plugins/automatic.py	Mon Sep 29 17:01:09 2008
@@ -51,6 +51,7 @@
         - scriptSettings: the Settings for the script
         """
         plugin.Plugin.__init__(self, owner, scriptSettings)
+        self._script.connect('focus-changed', self.focusChangedCallback)
 
     def floopyDooHandler(self, inputEvent=None):
         """The floopy doo handler.
@@ -77,6 +78,14 @@
             2)
     ]
 
+    def focusChangedCallback(self, owner, oldFocus, newFocus):
+        print "HERE"
+        print self
+        print owner
+        print self._script
+        print oldFocus
+        print newFocus
+
 if __name__ == "__main__":
     logging.basicConfig(format="%(name)s %(message)s")
     log.setLevel(logging.DEBUG)

Modified: branches/phase2/src/orca/script.py
==============================================================================
--- branches/phase2/src/orca/script.py	(original)
+++ branches/phase2/src/orca/script.py	Mon Sep 29 17:01:09 2008
@@ -39,6 +39,8 @@
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
+import gobject
+
 import logging
 log = logging.getLogger('orca.script')
 
@@ -53,9 +55,24 @@
 #
 settingsPackage = "script_settings"
 
-class Script:
+class Script(gobject.GObject):
     """The specific focus tracking scripts for applications.
     """
+    __gsignals__ = {
+        'focus-changed' : (
+            gobject.SIGNAL_RUN_LAST, 
+            gobject.TYPE_NONE,
+            (gobject.TYPE_PYOBJECT,  # old focus
+             gobject.TYPE_PYOBJECT,)  # new focus
+        ),
+        'locus-changed' : (
+            gobject.SIGNAL_RUN_LAST, 
+            gobject.TYPE_NONE,
+            (gobject.TYPE_PYOBJECT,  # old locus
+             gobject.TYPE_PYOBJECT,)  # new locus
+        ),
+    }
+
     def __init__(self, application, userSettings):
         """Creates a script for the given application.
         This method should not be called by anyone except the
@@ -65,6 +82,8 @@
         - application: the Python Accessible application to create a script for
         - userSettings: the Settings to use
         """
+        gobject.GObject.__init__(self)
+
         self.application = application
 
         self._isActive = False
@@ -83,8 +102,19 @@
         self.focus = None
 
         # The object of interest.  It might be the same as self.focus,
-        # but it might also be something else, such as an active 
-        # descendant.
+        # but it contains useful information for use by plugins.  The
+        # keys include:
+        #
+        # accessible
+        # name
+        # value
+        # caretOffset
+        # startOffset
+        # endOffset
+        # row
+        # column
+        # activeDescendantInfo 
+        # textSelections
         #
         self.locus = {}
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]