OSDN Git Service

Fix for #574 (Freeze when opening Windows Live Mail Move to and Copy to dialogs)...
authorMichael Curran <mick@kulgan.net>
Thu, 7 Jul 2011 04:07:59 +0000 (14:07 +1000)
committerMichael Curran <mick@kulgan.net>
Thu, 7 Jul 2011 04:07:59 +0000 (14:07 +1000)
* Move the special code in IAccessible NVDAObject's next, previous and parent properties that did something specific for the windowRoot (i.e. used Window NVDAObject's navigation properties instead) to newly implemented navigation properties on the WindowRoot IAccessible NVDAObject class.
* IAccessible NVDAObject's children property: when checking if a child is a WindowRoot IAccessible object, instead of just using accRole, instead use IAccIdentity to check for an objectID of 0 and childID of 0.
* IAccessible NVDAObject's findOverlayClasses:  only choose to use WindowRoot if the objectID is 0 (previously it checked for either 0 or None).

These changes make sure that WindowRoot code is only used for real windowRoot IAccessibles provided by oleacc, as opposed to also any IAccessible that happened to have a role of window.
In the Windows Live Mail dialog case: there were one or more client IAccessibles with an accRole of ROLE_SYSTEM_WINDOW and therefore object navigation was getting confused and looping back to a parents next/previous, and getDialogText was going in to endless recursion as children kept returning children of that window's client.

source/NVDAObjects/IAccessible/__init__.py

index e9310fe..2c8ef36 100644 (file)
@@ -447,7 +447,7 @@ the NVDAObject for IAccessible
                                clsList.append(Edit)\r
 \r
                #Window root IAccessibles\r
-               if self.event_objectID in (None,winUser.OBJID_WINDOW) and self.event_childID==0 and self.IAccessibleRole==oleacc.ROLE_SYSTEM_WINDOW:\r
+               if self.event_objectID==winUser.OBJID_WINDOW and self.event_childID==0 and self.IAccessibleRole==oleacc.ROLE_SYSTEM_WINDOW:\r
                        clsList.append(WindowRoot)\r
 \r
                if self.event_objectID==winUser.OBJID_TITLEBAR and self.event_childID==0:\r
@@ -850,13 +850,9 @@ the NVDAObject for IAccessible
                except:\r
                        return None\r
 \r
-       parentUsesSuperOnWindowRootIAccessible=True #: on a window root IAccessible, super should be used instead of accParent\r
-\r
        def _get_parent(self):\r
                if self.IAccessibleChildID>0:\r
                        return IAccessible(windowHandle=self.windowHandle,IAccessibleObject=self.IAccessibleObject,IAccessibleChildID=0,event_windowHandle=self.event_windowHandle,event_objectID=self.event_objectID,event_childID=0) or super(IAccessible,self).parent\r
-               if self.parentUsesSuperOnWindowRootIAccessible and self.IAccessibleRole==oleacc.ROLE_SYSTEM_WINDOW:\r
-                       return super(IAccessible,self).parent\r
                res=IAccessibleHandler.accParent(self.IAccessibleObject,self.IAccessibleChildID)\r
                if res:\r
                        parentObj=IAccessible(IAccessibleObject=res[0],IAccessibleChildID=res[1])\r
@@ -870,8 +866,6 @@ the NVDAObject for IAccessible
                return super(IAccessible,self).parent\r
 \r
        def _get_next(self):\r
-               if self.IAccessibleRole==oleacc.ROLE_SYSTEM_WINDOW:\r
-                       return super(IAccessible,self).next \r
                res=IAccessibleHandler.accNavigate(self.IAccessibleObject,self.IAccessibleChildID,oleacc.NAVDIR_NEXT)\r
                if not res:\r
                        return None\r
@@ -883,8 +877,6 @@ the NVDAObject for IAccessible
                        return self.correctAPIForRelation(IAccessible(IAccessibleObject=res[0],IAccessibleChildID=res[1]))\r
 \r
        def _get_previous(self):\r
-               if self.IAccessibleRole==oleacc.ROLE_SYSTEM_WINDOW:\r
-                       return super(IAccessible,self).previous\r
                res=IAccessibleHandler.accNavigate(self.IAccessibleObject,self.IAccessibleChildID,oleacc.NAVDIR_PREVIOUS)\r
                if not res:\r
                        return None\r
@@ -945,17 +937,13 @@ the NVDAObject for IAccessible
                                children.append(IAccessible(windowHandle=self.windowHandle,IAccessibleObject=self.IAccessibleObject,IAccessibleChildID=IAccessibleChildID,event_windowHandle=self.event_windowHandle,event_objectID=self.event_objectID,event_childID=IAccessibleChildID))\r
                                continue\r
                        try:\r
-                               accRole=IAccessibleObject.accRole(0)\r
+                               identity=IAccessibleHandler.getIAccIdentity(IAccessibleObject,0)\r
                        except COMError:\r
-                               accRole=0\r
+                               identity=None\r
                        #For Window root IAccessibles, we just want to use the new window handle, but use the best API for that window, rather than IAccessible\r
                        #If it does happen to be IAccessible though, we only want the client, not the window root IAccessible\r
-                       if accRole==oleacc.ROLE_SYSTEM_WINDOW:\r
-                               try:\r
-                                       windowHandle=oleacc.WindowFromAccessibleObject(IAccessibleObject)\r
-                               except WindowsError as e:\r
-                                       log.debugWarning("WindowFromAccessibleObject failed: %s" % e)\r
-                                       windowHandle=None\r
+                       if identity and identity['objectID']==0 and identity['childID']==0:\r
+                               windowHandle=identity.get('windowHandle',None)\r
                                if windowHandle:\r
                                        kwargs=dict(windowHandle=windowHandle)\r
                                        APIClass=Window.findBestAPIClass(kwargs,relation="parent") #Need a better relation type for this, but parent works ok -- gives the client\r
@@ -1304,6 +1292,19 @@ class WindowRoot(IAccessible):
 \r
        TextInfo=displayModel.DisplayModelTextInfo\r
 \r
+       parentUsesSuperOnWindowRootIAccessible=True #: on a window root IAccessible, super should be used instead of accParent\r
+\r
+       def _get_parent(self):\r
+               if self.parentUsesSuperOnWindowRootIAccessible:\r
+                       return super(IAccessible,self).parent\r
+               return super(WindowRoot,self).parent\r
+\r
+       def _get_next(self):\r
+               return super(IAccessible,self).next \r
+\r
+       def _get_previous(self):\r
+               return super(IAccessible,self).previous\r
+\r
        def _get_container(self):\r
                #Support for groupbox windows\r
                groupboxObj=IAccessibleHandler.findGroupboxObject(self)\r
@@ -1311,7 +1312,6 @@ class WindowRoot(IAccessible):
                        return groupboxObj\r
                return super(WindowRoot,self).container\r
 \r
-\r
 class ShellDocObjectView(IAccessible):\r
 \r
        def event_gainFocus(self):\r