[orca] More work on trying to handle bogus/duplicate accessible application instances



commit 21ee52ff7309c23685004b65ef2a723b2dda2c0f
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Thu Feb 23 10:46:53 2017 -0500

    More work on trying to handle bogus/duplicate accessible application instances

 src/orca/event_manager.py                |    9 ++++
 src/orca/script_manager.py               |   63 ++++++++++++++++++++++++++++++
 src/orca/scripts/web/script_utilities.py |   32 ---------------
 3 files changed, 72 insertions(+), 32 deletions(-)
---
diff --git a/src/orca/event_manager.py b/src/orca/event_manager.py
index 70876cf..5bc9dcf 100644
--- a/src/orca/event_manager.py
+++ b/src/orca/event_manager.py
@@ -630,6 +630,15 @@ class EventManager:
         if eType.startswith("window"):
             _scriptManager.reclaimScripts()
 
+        if eType.startswith("object:state-changed:active"):
+            try:
+                role = event.source.getRole()
+            except:
+                pass
+            else:
+                if role == pyatspi.ROLE_FRAME:
+                    _scriptManager.reclaimScripts()
+
         # Clean up any flat review context so that Orca does not get
         # confused (see bgo#609633)
         #
diff --git a/src/orca/script_manager.py b/src/orca/script_manager.py
index 77b8115..631e760 100644
--- a/src/orca/script_manager.py
+++ b/src/orca/script_manager.py
@@ -58,6 +58,7 @@ class ScriptManager:
 
         self.setActiveScript(None, "__init__")
         self._desktop = pyatspi.Registry.getDesktop(0)
+        self._active = False
         debug.println(debug.LEVEL_INFO, 'SCRIPT MANAGER: Initialized', True)
 
     def activate(self):
@@ -67,6 +68,7 @@ class ScriptManager:
         self._defaultScript = self.getScript(None)
         self._defaultScript.registerEventListeners()
         self.setActiveScript(self._defaultScript, "activate")
+        self._active = True
         debug.println(debug.LEVEL_INFO, 'SCRIPT MANAGER: Activated', True)
 
     def deactivate(self):
@@ -80,6 +82,7 @@ class ScriptManager:
         self.appScripts = {}
         self.toolkitScripts = {}
         self.customScripts = {}
+        self._active = False
         debug.println(debug.LEVEL_INFO, 'SCRIPT MANAGER: Deactivated', True)
 
     def getModuleName(self, app):
@@ -212,6 +215,31 @@ class ScriptManager:
 
         return script
 
+    def sanityCheckScript(self, script):
+        if not self._active:
+            return script
+
+        try:
+            appInDesktop = script.app in self._desktop
+        except:
+            appInDesktop = False
+
+        if appInDesktop:
+            return script
+
+        msg = "WARNING: %s is not in the registry's desktop" % script.app
+        debug.println(debug.LEVEL_INFO, msg, True)
+
+        newScript = self._getScriptForAppReplicant(script.app)
+        if newScript:
+            msg = "SCRIPT MANAGER: Script for app replicant found: %s" % newScript
+            debug.println(debug.LEVEL_INFO, msg, True)
+            return newScript
+
+        msg = "WARNING: Failed to get a replacement script for %s" % script.app
+        debug.println(debug.LEVEL_INFO, msg, True)
+        return script
+
     def getScript(self, app, obj=None):
         """Get a script for an app (and make it if necessary).  This is used
         instead of a simple calls to Script's constructor.
@@ -274,6 +302,9 @@ class ScriptManager:
            and not issubclass(appScript.__class__, toolkitScript.__class__):
             return toolkitScript
 
+        if app:
+            appScript = self.sanityCheckScript(appScript)
+
         return appScript
 
     def setActiveScript(self, newScript, reason=None):
@@ -298,6 +329,27 @@ class ScriptManager:
               (newScript.name, reason)
         debug.println(debug.LEVEL_INFO, msg, True)
 
+    def _getScriptForAppReplicant(self, app):
+        if not self._active:
+            return None
+
+        def _pid(app):
+            try:
+                return app.get_process_id()
+            except:
+                return -1
+
+        pid = _pid(app)
+        if pid == -1:
+            return None
+
+        items = self.appScripts.items()
+        for a, script in items:
+            if a != app and _pid(a) == pid and a in self._desktop:
+                return script
+
+        return None
+
     def reclaimScripts(self):
         """Compares the list of known scripts to the list of known apps,
         deleting any scripts as necessary.
@@ -315,6 +367,17 @@ class ScriptManager:
             debug.println(debug.LEVEL_INFO, msg, True)
 
             appScript = self.appScripts.pop(app)
+            newScript = self._getScriptForAppReplicant(app)
+            if newScript:
+                msg = "SCRIPT MANAGER: Script for app replicant found: %s" % newScript
+                debug.println(debug.LEVEL_INFO, msg, True)
+
+                attrs = appScript.getTransferableAttributes()
+                for attr, value in attrs.items():
+                    msg = "SCRIPT MANAGER: Setting %s to %s" % (attr, value)
+                    debug.println(debug.LEVEL_INFO, msg, True)
+                    setattr(newScript, attr, value)
+
             del appScript
 
             try:
diff --git a/src/orca/scripts/web/script_utilities.py b/src/orca/scripts/web/script_utilities.py
index 229b020..ef68b0e 100644
--- a/src/orca/scripts/web/script_utilities.py
+++ b/src/orca/scripts/web/script_utilities.py
@@ -217,39 +217,7 @@ class Utilities(script_utilities.Utilities):
 
         return list(filter(self.isDocument, targets))
 
-    def sanityCheckApplication(self):
-        try:
-            appInDesktop = self._script.app in pyatspi.Registry.getDesktop(0)
-        except:
-            appInDesktop = False
-
-        if appInDesktop:
-            return True
-
-        msg = "WARNING: %s is not in the registry's desktop" % self._script.app
-        debug.println(debug.LEVEL_INFO, msg, True)
-
-        try:
-            app = orca_state.activeWindow.getApplication()
-        except:
-            msg = "ERROR: Exception getting application for active window"
-            debug.println(debug.LEVEL_INFO, msg, True)
-            return False
-
-        msg = "WEB: Application for active window is %s" % app
-        debug.println(debug.LEVEL_INFO, msg, True)
-
-        if app in pyatspi.Registry.getDesktop(0):
-            self._script.app = app
-            return True
-
-        msg = "WARNING: App for window is not in the registry's desktop"
-        debug.println(debug.LEVEL_INFO, msg, True)
-        return False
-
     def sanityCheckActiveWindow(self):
-        self.sanityCheckApplication()
-
         app = self._script.app
         try:
             windowInApp = orca_state.activeWindow in app


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