Package virtualBuffers :: Module gecko_ia2
[hide private]
[frames] | no frames]

Source Code for Module virtualBuffers.gecko_ia2

  1  from . import VirtualBuffer, VirtualBufferTextInfo, VBufStorage_findMatch_word 
  2  import treeInterceptorHandler 
  3  import controlTypes 
  4  import NVDAObjects.IAccessible.mozilla 
  5  import NVDAObjects.behaviors 
  6  import winUser 
  7  import IAccessibleHandler 
  8  import oleacc 
  9  from logHandler import log 
 10  import textInfos 
 11  from comtypes.gen.IAccessible2Lib import IAccessible2 
 12  from comtypes import COMError 
 13  import aria 
 14  import config 
 15  from NVDAObjects.IAccessible import normalizeIA2TextFormatField 
 16   
17 -class Gecko_ia2_TextInfo(VirtualBufferTextInfo):
18
19 - def _normalizeControlField(self,attrs):
20 accRole=attrs['IAccessible::role'] 21 accRole=int(accRole) if accRole.isdigit() else accRole 22 role=IAccessibleHandler.IAccessibleRolesToNVDARoles.get(accRole,controlTypes.ROLE_UNKNOWN) 23 if attrs.get('IAccessible2::attribute_tag',"").lower()=="blockquote": 24 role=controlTypes.ROLE_BLOCKQUOTE 25 states=set(IAccessibleHandler.IAccessibleStatesToNVDAStates[x] for x in [1<<y for y in xrange(32)] if int(attrs.get('IAccessible::state_%s'%x,0)) and x in IAccessibleHandler.IAccessibleStatesToNVDAStates) 26 states|=set(IAccessibleHandler.IAccessible2StatesToNVDAStates[x] for x in [1<<y for y in xrange(32)] if int(attrs.get('IAccessible2::state_%s'%x,0)) and x in IAccessibleHandler.IAccessible2StatesToNVDAStates) 27 defaultAction=attrs.get('defaultAction','') 28 if defaultAction=="click": 29 states.add(controlTypes.STATE_CLICKABLE) 30 grabbed = attrs.get("IAccessible2::attribute_grabbed") 31 if grabbed == "false": 32 states.add(controlTypes.STATE_DRAGGABLE) 33 elif grabbed == "true": 34 states.add(controlTypes.STATE_DRAGGING) 35 sorted = attrs.get("IAccessible2::attribute_sort") 36 if sorted=="ascending": 37 states.add(controlTypes.STATE_SORTED_ASCENDING) 38 elif sorted=="descending": 39 states.add(controlTypes.STATE_SORTED_DESCENDING) 40 elif sorted=="other": 41 states.add(controlTypes.STATE_SORTED) 42 if attrs.get("IAccessible2::attribute_dropeffect", "none") != "none": 43 states.add(controlTypes.STATE_DROPTARGET) 44 if role==controlTypes.ROLE_LINK and controlTypes.STATE_LINKED not in states: 45 # This is a named link destination, not a link which can be activated. The user doesn't care about these. 46 role=controlTypes.ROLE_TEXTFRAME 47 level=attrs.get('IAccessible2::attribute_level',"") 48 xmlRoles=attrs.get("IAccessible2::attribute_xml-roles", "").split(" ") 49 # Get the first landmark role, if any. 50 landmark=next((xr for xr in xmlRoles if xr in aria.landmarkRoles),None) 51 52 attrs['role']=role 53 attrs['states']=states 54 if level is not "" and level is not None: 55 attrs['level']=level 56 if landmark: 57 attrs["landmark"]=landmark 58 return super(Gecko_ia2_TextInfo,self)._normalizeControlField(attrs)
59
60 - def _normalizeFormatField(self, attrs):
61 normalizeIA2TextFormatField(attrs) 62 return attrs
63
64 -class Gecko_ia2(VirtualBuffer):
65 66 TextInfo=Gecko_ia2_TextInfo 67
68 - def __init__(self,rootNVDAObject):
69 super(Gecko_ia2,self).__init__(rootNVDAObject,backendName="gecko_ia2") 70 self._initialScrollObj = None
71
72 - def _get_shouldPrepare(self):
73 if not super(Gecko_ia2, self).shouldPrepare: 74 return False 75 if isinstance(self.rootNVDAObject, NVDAObjects.IAccessible.mozilla.Gecko1_9) and controlTypes.STATE_BUSY in self.rootNVDAObject.states: 76 # If the document is busy in Gecko 1.9, it isn't safe to create a buffer yet. 77 return False 78 return True
79
80 - def __contains__(self,obj):
81 #Special code to handle Mozilla combobox lists 82 if obj.windowClassName.startswith('Mozilla') and winUser.getWindowStyle(obj.windowHandle)&winUser.WS_POPUP: 83 parent=obj.parent 84 while parent and parent.windowHandle==obj.windowHandle: 85 parent=parent.parent 86 if parent: 87 obj=parent.parent 88 if not (isinstance(obj,NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject,IAccessibleHandler.IAccessible2)) or not obj.windowClassName.startswith('Mozilla') or not winUser.isDescendantWindow(self.rootNVDAObject.windowHandle,obj.windowHandle): 89 return False 90 if self.rootNVDAObject.windowHandle==obj.windowHandle: 91 ID=obj.IA2UniqueID 92 try: 93 self.rootNVDAObject.IAccessibleObject.accChild(ID) 94 except COMError: 95 return ID==self.rootNVDAObject.IA2UniqueID 96 97 return not self._isNVDAObjectInApplication(obj)
98
99 - def _get_isAlive(self):
100 if self.isLoading: 101 return True 102 root=self.rootNVDAObject 103 if not root: 104 return False 105 states=root.states 106 if not winUser.isWindow(root.windowHandle) or controlTypes.STATE_DEFUNCT in states or controlTypes.STATE_READONLY not in states: 107 return False 108 try: 109 if not NVDAObjects.IAccessible.getNVDAObjectFromEvent(root.windowHandle,winUser.OBJID_CLIENT,root.IA2UniqueID): 110 return False 111 except: 112 return False 113 return True
114
115 - def getNVDAObjectFromIdentifier(self, docHandle, ID):
117
118 - def getIdentifierFromNVDAObject(self,obj):
119 docHandle=obj.windowHandle 120 ID=obj.IA2UniqueID 121 return docHandle,ID
122
123 - def _shouldIgnoreFocus(self, obj):
124 if obj.role == controlTypes.ROLE_DOCUMENT and controlTypes.STATE_EDITABLE not in obj.states: 125 return True 126 return super(Gecko_ia2, self)._shouldIgnoreFocus(obj)
127
128 - def _postGainFocus(self, obj):
129 if isinstance(obj, NVDAObjects.behaviors.EditableText): 130 # We aren't passing this event to the NVDAObject, so we need to do this ourselves. 131 obj.initAutoSelectDetection() 132 super(Gecko_ia2, self)._postGainFocus(obj)
133
134 - def _shouldSetFocusToObj(self, obj):
135 if obj.role == controlTypes.ROLE_GRAPHIC and controlTypes.STATE_LINKED in obj.states: 136 return True 137 return super(Gecko_ia2,self)._shouldSetFocusToObj(obj) and obj.role!=controlTypes.ROLE_EMBEDDEDOBJECT
138
139 - def _activateNVDAObject(self, obj):
140 try: 141 obj.doAction() 142 except: 143 log.debugWarning("could not programmatically activate field, trying mouse") 144 while obj and controlTypes.STATE_OFFSCREEN in obj.states and obj!=self.rootNVDAObject: 145 obj=obj.parent 146 l=obj.location 147 if l: 148 x=(l[0]+l[2]/2) 149 y=l[1]+(l[3]/2) 150 oldX,oldY=winUser.getCursorPos() 151 winUser.setCursorPos(x,y) 152 winUser.mouse_event(winUser.MOUSEEVENTF_LEFTDOWN,0,0,None,None) 153 winUser.mouse_event(winUser.MOUSEEVENTF_LEFTUP,0,0,None,None) 154 winUser.setCursorPos(oldX,oldY) 155 else: 156 log.debugWarning("no location for field")
157
158 - def _searchableAttribsForNodeType(self,nodeType):
159 if nodeType.startswith('heading') and nodeType[7:].isdigit(): 160 attrs={"IAccessible::role":[IAccessibleHandler.IA2_ROLE_HEADING],"IAccessible2::attribute_level":[nodeType[7:]]} 161 elif nodeType=="heading": 162 attrs={"IAccessible::role":[IAccessibleHandler.IA2_ROLE_HEADING]} 163 elif nodeType=="table": 164 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TABLE]} 165 if not config.conf["documentFormatting"]["includeLayoutTables"]: 166 attrs["table-layout"]=[None] 167 elif nodeType=="link": 168 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LINK],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_LINKED:[1]} 169 elif nodeType=="visitedLink": 170 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LINK],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_TRAVERSED:[1]} 171 elif nodeType=="unvisitedLink": 172 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LINK],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_LINKED:[1],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_TRAVERSED:[None]} 173 elif nodeType=="formField": 174 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON,oleacc.ROLE_SYSTEM_RADIOBUTTON,oleacc.ROLE_SYSTEM_CHECKBUTTON,oleacc.ROLE_SYSTEM_COMBOBOX,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_OUTLINE,oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None]} 175 elif nodeType=="list": 176 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LIST]} 177 elif nodeType=="listItem": 178 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LISTITEM]} 179 elif nodeType=="button": 180 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON]} 181 elif nodeType=="edit": 182 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None]} 183 elif nodeType=="frame": 184 attrs={"IAccessible::role":[IAccessibleHandler.IA2_ROLE_INTERNAL_FRAME]} 185 elif nodeType=="separator": 186 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_SEPARATOR]} 187 elif nodeType=="radioButton": 188 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_RADIOBUTTON]} 189 elif nodeType=="comboBox": 190 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_COMBOBOX]} 191 elif nodeType=="checkBox": 192 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_CHECKBUTTON]} 193 elif nodeType=="graphic": 194 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_GRAPHIC]} 195 elif nodeType=="blockQuote": 196 attrs={"IAccessible2::attribute_tag":["BLOCKQUOTE"]} 197 elif nodeType=="focusable": 198 attrs={"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]} 199 elif nodeType=="landmark": 200 attrs={"IAccessible2::attribute_xml-roles":[VBufStorage_findMatch_word(lr) for lr in aria.landmarkRoles]} 201 elif nodeType=="embeddedObject": 202 attrs={"IAccessible2::attribute_tag":["EMBED","OBJECT","APPLET"]} 203 else: 204 return None 205 return attrs
206
207 - def event_stateChange(self,obj,nextHandler):
208 if not self.isAlive: 209 return treeInterceptorHandler.killTreeInterceptor(self) 210 return nextHandler()
211
212 - def event_scrollingStart(self, obj, nextHandler):
213 if not self.isReady: 214 self._initialScrollObj = obj 215 return nextHandler() 216 if not self._handleScrollTo(obj): 217 return nextHandler()
218 event_scrollingStart.ignoreIsReady = True 219
220 - def _getNearestTableCell(self, tableID, startPos, origRow, origCol, origRowSpan, origColSpan, movement, axis):
221 if not axis: 222 # First or last. 223 return super(Gecko_ia2, self)._getNearestTableCell(tableID, startPos, origRow, origCol, origRowSpan, origColSpan, movement, axis) 224 225 # Determine destination row and column. 226 destRow = origRow 227 destCol = origCol 228 if axis == "row": 229 destRow += origRowSpan if movement == "next" else -1 230 elif axis == "column": 231 destCol += origColSpan if movement == "next" else -1 232 233 if destCol < 1: 234 # Optimisation: We're definitely at the edge of the column. 235 raise LookupError 236 237 # For Gecko, we can use the table object to directly retrieve the cell with the exact destination coordinates. 238 docHandle = startPos.NVDAObjectAtStart.windowHandle 239 table = self.getNVDAObjectFromIdentifier(docHandle, tableID) 240 try: 241 cell = table.IAccessibleTableObject.accessibleAt(destRow - 1, destCol - 1).QueryInterface(IAccessible2) 242 cell = NVDAObjects.IAccessible.IAccessible(IAccessibleObject=cell, IAccessibleChildID=0) 243 return self.makeTextInfo(cell) 244 except (COMError, RuntimeError): 245 raise LookupError
246
248 try: 249 return self.rootNVDAObject.IAccessibleObject.accValue(0) 250 except COMError: 251 return None
252
253 - def _getInitialCaretPos(self):
254 initialPos = super(Gecko_ia2,self)._getInitialCaretPos() 255 if initialPos: 256 return initialPos 257 return self._initialScrollObj
258