Reported by jteh on 2009-11-16 23:46
There are two accessibility implementations in Adobe Acrobat/Reader: static PDF (probably the majority of PDFs) and XFA PDF. For the static PDF implementation, the unique ID is specified as the IAccessible child ID (which is what NVDA does). For the XFA PDF implementation, the unique ID is specified as the IAccessible object ID. NVDA has problems with these PDFs for this reason.
The !AdobeAcrobat vbuf backend must handle events for positive obj IDs and update the appropriate node.
getNVDAObjectFromIdentifier() in the !AdobeAcrobat buffer needs to specify the unique ID as the obj ID when working with an XFA PDF.
There doesn't seem to be any elegant way to detect an XFA PDF.
We will need to use the non-existence of the read-only state on the document and page objects to determine that this is an XFA PDF.
Similarly, the !AcrobatNode NVDAObject must correctly set the event parameters on the object for XFA PDFs.
The text was updated successfully, but these errors were encountered:
Comment 1 by jteh on 2009-11-19 22:58
I've hit a rather nasty snag. It seems that !AccessibleObjectFromEvent doesn't work for objects in XFA PDFs unless:
A real event happens for the object. This isn't good enough for us, as we often need to retrieve an object before an event happens for it.
!WindowFromAccessibleObject is called on the object before you try to call !AccessibleObjectFromEvent. That is, you have to navigate to the object by other means (e.g. !AccessibleChildren or accNavigate) and call !WindowFromAccessibleObject on it. Once this is done, !AccessibleObjectFromEvent will always work for that object, even in other processes. I don't understand why this is the case.
Interestingly enough, once one of these happens, you can actually retrieve the object by specifying OBJID_CLIENT for the object ID and the unique ID for the child ID, just as we do for static PDFs, which is useful, if a bit hackish.
Comment 3 by jteh on 2009-12-08 05:54
I've confirmed my findings regarding !AccessibleObjectFromEvent() with Adobe. Reader doesn't expect anyone to use that function on an object which hasn't yet received an event.
Calling !WindowFromAccessibleObject() in the backend for every node as we render it does fix the problem, but it also causes rendering ot take almost twice as long, which is a problem for large documents.
It is possible that calling IOleWindow::!GetWindow directly might be faster; we have no idea what !WindowFromAccessibleObject is really doing behind the scenes. This is worth a try.
Failing that, the only solution on our end is to hold the IAccessible for all nodes in the backend and provide a way for NVDA to retrieve it. This will involve using ObjectFromLResult and LResultFromObject.
Comment 4 by jteh on 2010-02-03 06:00
IOleWindow::!GetWindow() is no faster than !WindowFromAccessibleObject(). On a document that takes about 2 seconds to load normally, using either !GetWindow or !WindowFromAccessibleObject causes it to take about 5 seconds. Interestingly, on a document that takes about 11 seconds to load normally, perf degrades to about 15 seconds.
In any case, there is a noticeable regression in performance, particularly for the smaller document. We're not going to get the !ObjFromLResult thing for 2010.1 and I'm thinking we'd probably prefer not to regress performance for the majority of PDFs.
One other option might be to only do this for XFA PDFs (check the read-only state on the document). This would involve modifying the backend somewhat so that we can store this info as a boolean on the backend and use it in fillVBuf. However, this is still pretty hacky.