1
1
#NVDAObjects/IAccessible/mozilla.py
2
2
#A part of NonVisual Desktop Access (NVDA)
3
#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
4
3
#This file is covered by the GNU General Public License.
5
4
#See the file COPYING for more details.
5
#Copyright (C) 2006-2010 Michael Curran <mick@kulgan.net>, James Teh <jamie@jantrid.net>
7
7
import IAccessibleHandler
10
from comtypes import IServiceProvider, COMError
10
12
import controlTypes
11
from . import IAccessible
13
from . import IAccessible, Dialog
13
14
from logHandler import log
15
16
class Mozilla(IAccessible):
22
23
return super(Mozilla,self).beTransparentToMouse
25
def _get_parent(self):
26
#Special code to support Mozilla node_child_of relation (for comboboxes)
27
res=IAccessibleHandler.accNavigate(self.IAccessibleObject,self.IAccessibleChildID,IAccessibleHandler.NAVRELATION_NODE_CHILD_OF)
28
if res and res!=(self.IAccessibleObject,self.IAccessibleChildID):
29
#Gecko can sometimes give back a broken application node with a windowHandle of 0
30
#The application node is annoying, even if it wasn't broken
31
#So only use the node_child_of object if it has a valid IAccessible2 windowHandle
33
windowHandle=res[0].windowHandle
34
except (COMError,AttributeError):
37
newObj=IAccessible(windowHandle=windowHandle,IAccessibleObject=res[0],IAccessibleChildID=res[1])
40
return super(Mozilla,self).parent
42
def _get_states(self):
43
states = super(Mozilla, self).states
44
if self.IAccessibleStates & oleacc.STATE_SYSTEM_MARQUEED:
45
states.add(controlTypes.STATE_CHECKABLE)
48
def _get_presentationType(self):
49
presType=super(Mozilla,self).presentationType
50
if presType==self.presType_content:
51
if self.role==controlTypes.ROLE_TABLE and self.IA2Attributes.get('layout-guess')=='true':
52
presType=self.presType_layout
53
elif self.table and self.table.presentationType==self.presType_layout:
54
presType=self.presType_layout
57
def _get_positionInfo(self):
58
info=super(Mozilla,self).positionInfo
59
level=info.get('level',None)
61
level=self.IA2Attributes.get('level',None)
66
class Gecko1_9(Mozilla):
24
68
def _get_description(self):
25
69
rawDescription=super(Mozilla,self).description
26
70
if isinstance(rawDescription,basestring) and rawDescription.startswith('Description: '):
31
def _get_parent(self):
32
#Special code to support Mozilla node_child_of relation (for comboboxes)
33
res=IAccessibleHandler.accNavigate(self.IAccessibleObject,self.IAccessibleChildID,IAccessibleHandler.NAVRELATION_NODE_CHILD_OF)
34
if res and res!=(self.IAccessibleObject,self.IAccessibleChildID):
35
newObj=IAccessible(IAccessibleObject=res[0],IAccessibleChildID=res[1])
38
return super(Mozilla,self).parent
40
75
def event_scrollingStart(self):
41
76
#Firefox 3.6 fires scrollingStart on leaf nodes which is not useful to us.
42
77
#Bounce the event up to the node's parent so that any possible virtualBuffers will detect it.
43
78
if self.role==controlTypes.ROLE_EDITABLETEXT and controlTypes.STATE_READONLY in self.states:
44
79
eventHandler.queueEvent("scrollingStart",self.parent)
46
def _get_states(self):
47
states = super(Mozilla, self).states
48
if self.IAccessibleStates & oleacc.STATE_SYSTEM_MARQUEED:
49
states.add(controlTypes.STATE_CHECKABLE)
81
class BrokenFocusedState(Mozilla):
82
shouldAllowIAccessibleFocusEvent=True
84
class RootApplication(Mozilla):
85
"""Mozilla exposes a root application accessible as the parent of all top level frames.
86
See MozillaBug:555861.
87
This is non-standard; the top level accessible should be the top level window.
88
NVDA expects the standard behaviour, so we never want to see this object.
91
def __nonzero__(self):
92
# As far as NVDA is concerned, this is a useless object.
52
95
class Document(Mozilla):
54
shouldAllowIAccessibleFocusEvent=True
56
def _get_virtualBufferClass(self):
99
def _get_treeInterceptorClass(self):
57
100
states=self.states
58
if isinstance(self.IAccessibleObject,IAccessibleHandler.IAccessible2) and controlTypes.STATE_READONLY in states and controlTypes.STATE_BUSY not in states and self.windowClassName=="MozillaContentWindowClass":
101
ver=_getGeckoVersion(self)
102
if (not ver or ver.startswith('1.9')) and self.windowClassName!="MozillaContentWindowClass":
103
return super(Document,self).treeInterceptorClass
104
if controlTypes.STATE_READONLY in states:
59
105
import virtualBuffers.gecko_ia2
60
106
return virtualBuffers.gecko_ia2.Gecko_ia2
61
return super(Document,self).virtualBufferClass
107
return super(Document,self).treeInterceptorClass
66
109
class ListItem(Mozilla):
68
shouldAllowIAccessibleFocusEvent=True
70
111
def _get_name(self):
71
112
name=super(ListItem,self)._get_name()
72
113
if self.IAccessibleStates&oleacc.STATE_SYSTEM_READONLY:
84
class ComboBox(Mozilla):
86
shouldAllowIAccessibleFocusEvent=True
90
shouldAllowIAccessibleFocusEvent=True
93
shouldAllowIAccessibleFocusEvent=True
96
shouldAllowIAccessibleFocusEvent=True
125
class EmbeddedObject(Mozilla):
127
def _get_shouldAllowIAccessibleFocusEvent(self):
128
focusWindow = winUser.getGUIThreadInfo(self.windowThreadID).hwndFocus
129
if self.windowHandle != focusWindow:
130
# This window doesn't have the focus, which means the embedded object's window probably already has the focus.
131
# We don't want to override the focus event fired by the embedded object.
133
return super(EmbeddedObject, self).shouldAllowIAccessibleFocusEvent
135
def _getGeckoVersion(obj):
136
appMod = obj.appModule
138
return appMod._geckoVersion
139
except AttributeError:
142
ver = obj.IAccessibleObject.QueryInterface(IServiceProvider).QueryService(IAccessibleHandler.IAccessibleApplication._iid_, IAccessibleHandler.IAccessibleApplication).toolkitVersion
145
appMod._geckoVersion = ver
148
class GeckoPluginWindowRoot(IAccessible):
150
def _get_parent(self):
151
parent=super(GeckoPluginWindowRoot,self).parent
152
ver=_getGeckoVersion(parent)
153
if ver and not ver.startswith('1.'):
154
res=IAccessibleHandler.accNavigate(parent.IAccessibleObject,0,IAccessibleHandler.NAVRELATION_EMBEDS)
156
obj=IAccessible(IAccessibleObject=res[0],IAccessibleChildID=res[1])
157
if obj and controlTypes.STATE_OFFSCREEN not in obj.states:
162
def findExtraOverlayClasses(obj, clsList):
163
"""Determine the most appropriate class if this is a Mozilla object.
164
This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses} except that it never calls any other findOverlayClasses method.
166
if not isinstance(obj.IAccessibleObject, IAccessibleHandler.IAccessible2):
167
# We require IAccessible2; i.e. Gecko >= 1.9.
170
iaRole = obj.IAccessibleRole
172
if iaRole == oleacc.ROLE_SYSTEM_APPLICATION:
174
if not obj.IAccessibleObject.windowHandle:
175
cls = RootApplication
179
cls = _IAccessibleRolesToOverlayClasses.get(iaRole)
182
if iaRole in _IAccessibleRolesWithBrokenFocusedState:
183
clsList.append(BrokenFocusedState)
185
ver = _getGeckoVersion(obj)
186
if ver and ver.startswith("1.9"):
187
clsList.append(Gecko1_9)
189
clsList.append(Mozilla)
191
#: Maps IAccessible roles to NVDAObject overlay classes.
192
_IAccessibleRolesToOverlayClasses = {
193
oleacc.ROLE_SYSTEM_ALERT: Dialog,
194
oleacc.ROLE_SYSTEM_LISTITEM: ListItem,
195
oleacc.ROLE_SYSTEM_DOCUMENT: Document,
196
IAccessibleHandler.IA2_ROLE_EMBEDDED_OBJECT: EmbeddedObject,
197
"embed": EmbeddedObject,
198
"object": EmbeddedObject,
201
#: Roles that mightn't set the focused state when they are focused.
202
_IAccessibleRolesWithBrokenFocusedState = frozenset((
203
oleacc.ROLE_SYSTEM_COMBOBOX,
204
oleacc.ROLE_SYSTEM_LIST,
205
oleacc.ROLE_SYSTEM_LISTITEM,
206
oleacc.ROLE_SYSTEM_DOCUMENT,
207
oleacc.ROLE_SYSTEM_APPLICATION,
208
oleacc.ROLE_SYSTEM_TABLE,
209
oleacc.ROLE_SYSTEM_OUTLINE,