44
45
class AcrobatNode(IAccessible):
46
def _get_virtualBufferClass(self):
47
if self.role in (controlTypes.ROLE_DOCUMENT,controlTypes.ROLE_PAGE):
48
import virtualBuffers.adobeAcrobat
49
return virtualBuffers.adobeAcrobat.AdobeAcrobat
50
return super(AcrobatNode,self).virtualBufferClass
52
47
def initOverlayClass(self):
54
49
serv = self.IAccessibleObject.QueryInterface(IServiceProvider)
56
51
log.debugWarning("Could not get IServiceProvider")
59
if self.event_objectID is None:
60
# This object does not have real event parameters.
61
# Get the real child ID using IAccID.
54
if self.event_objectID > 0:
55
self.accID = self.event_objectID
56
elif self.event_childID > 0:
57
self.accID = self.event_childID
63
self.event_childID = serv.QueryService(SID_AccID, IAccID).get_accID()
60
self.accID = serv.QueryService(SID_AccID, IAccID).get_accID()
65
62
log.debugWarning("Failed to get ID from IAccID", exc_info=True)
67
65
# Get the IPDDomNode.
96
88
role = controlTypes.ROLE_TEXTFRAME
99
def event_valueChange(self):
100
if self.event_childID==0 and self.event_objectID == winUser.OBJID_CLIENT and winUser.isDescendantWindow(winUser.getForegroundWindow(),self.windowHandle):
101
# Acrobat has indicated that a page has died and been replaced by a new one.
102
# The new page has the same event params, so we must bypass NVDA's IAccessible caching.
103
obj = getNVDAObjectFromEvent(self.windowHandle, -4, 0)
106
eventHandler.queueEvent("gainFocus",obj)
108
91
def scrollIntoView(self):
110
93
self.pdDomNode.ScrollTo()
111
94
except (AttributeError, COMError):
112
95
log.debugWarning("IPDDomNode::ScrollTo failed", exc_info=True)
97
def _isEqual(self, other):
98
if self.windowHandle == other.windowHandle and self.accID and other.accID:
99
return self.accID == other.accID
100
return super(AcrobatNode, self)._isEqual(other)
102
class RootNode(AcrobatNode):
103
shouldAllowIAccessibleFocusEvent = True
105
def event_valueChange(self):
106
# Acrobat has indicated that a page has died and been replaced by a new one.
107
if not self.isInForeground:
108
# If this isn't in the foreground, it doesn't matter,
109
# as focus will be fired on the correct object when it is in the foreground again.
111
# The new page has the same event params, so we must bypass NVDA's IAccessible caching.
112
obj = getNVDAObjectFromEvent(self.windowHandle, winUser.OBJID_CLIENT, 0)
115
eventHandler.queueEvent("gainFocus",obj)
117
class Document(RootNode):
119
def _get_treeInterceptorClass(self):
120
import virtualBuffers.adobeAcrobat
121
return virtualBuffers.adobeAcrobat.AdobeAcrobat
123
def _get_shouldAllowIAccessibleFocusEvent(self):
124
# HACK: #1659: When moving the focus, Acrobat sometimes fires focus on the document before firing it on the real focus;
125
# e.g. when tabbing through a multi-page form.
126
# This causes extraneous verbosity.
127
# Therefore, if already focused inside this document, only allow focus on the document if it has no active descendant.
128
if api.getFocusObject().windowHandle == self.windowHandle:
130
return self.IAccessibleObject.accFocus in (None, 0)
133
return super(Document, self).shouldAllowIAccessibleFocusEvent
135
class RootTextNode(RootNode):
136
"""The message text node that appears instead of the document when the document is not available.
139
def _get_parent(self):
140
#hack: This code should be taken out once the crash is fixed in Adobe Reader X.
141
#If going parent on a root text node after saying ok to the accessibility options (untagged) and before the processing document dialog appears, Reader X will crash.
142
return api.getDesktopObject()
114
144
class AcrobatTextInfo(NVDAObjectTextInfo):
116
146
def _getStoryText(self):
125
155
except (ValueError, TypeError):
126
156
raise RuntimeError("Bad caret index")
128
class AcrobatTextNode(EditableText, AcrobatNode):
158
class EditableTextNode(EditableText, AcrobatNode):
129
159
TextInfo = AcrobatTextInfo
161
def event_valueChange(self):
131
164
class AcrobatSDIWindowClient(IAccessible):
133
166
def __init__(self, **kwargs):
138
171
# The unnamed object's parent is the named object, but when descending into the named object, the unnamed object is skipped.
139
172
# Given the brokenness of the unnamed object, just skip it completely and use the parent when it is encountered.
140
173
self.IAccessibleObject = self.IAccessibleObject.accParent
175
def findExtraOverlayClasses(obj, clsList):
176
"""Determine the most appropriate class(es) for Acrobat objects.
177
This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses} except that it never calls any other findOverlayClasses method.
180
if obj.event_childID == 0 and obj.event_objectID == winUser.OBJID_CLIENT:
182
if role in (controlTypes.ROLE_DOCUMENT,controlTypes.ROLE_PAGE):
183
clsList.append(Document)
184
elif role == controlTypes.ROLE_EDITABLETEXT:
185
clsList.append(RootTextNode)
187
clsList.append(RootNode)
189
elif role == controlTypes.ROLE_EDITABLETEXT and controlTypes.STATE_FOCUSABLE in obj.states:
190
clsList.append(EditableTextNode)
192
clsList.append(AcrobatNode)