#NVDAObjects/IAccessible/adobeFlash.py #A part of NonVisual Desktop Access (NVDA) #Copyright (C) 2009 NVDA Contributors #This file is covered by the GNU General Public License. #See the file COPYING for more details. import winUser import oleacc from . import IAccessible, getNVDAObjectFromEvent from NVDAObjects import NVDAObjectTextInfo from NVDAObjects.behaviors import EditableTextWithoutAutoSelectDetection from comtypes import COMError, IServiceProvider, hresult from comtypes.gen.FlashAccessibility import ISimpleTextSelection, IFlashAccessibility from logHandler import log class InputTextFieldTextInfo(NVDAObjectTextInfo): def _getStoryText(self): return self.obj.value or "" def _getRawSelectionOffsets(self): try: return self.obj.ISimpleTextSelectionObject.GetSelection() except COMError, e: if e.hresult == hresult.E_FAIL: # The documentation says that an empty field should return 0 for both values, but instead, we seem to get E_FAIL. # An empty field still has a valid caret. return 0, 0 else: raise RuntimeError except AttributeError: raise RuntimeError def _getCaretOffset(self): # We want the active (moving) end of the selection. return self._getRawSelectionOffsets()[1] def _getSelectionOffsets(self): # This might be a backwards selection, but for now, we should always return the values in ascending order. return sorted(self._getRawSelectionOffsets()) class InputTextField(EditableTextWithoutAutoSelectDetection, IAccessible): TextInfo = InputTextFieldTextInfo class Root(IAccessible): def _get_presentationType(self): return self.presType_content def _get_treeInterceptorClass(self): import virtualBuffers.adobeFlash return virtualBuffers.adobeFlash.AdobeFlash #Flash root client has broken accParent, force to return the flash root window root IAccessible def _get_parent(self): return getNVDAObjectFromEvent(self.windowHandle,0,0) class PluginClientWithBrokenFocus(IAccessible): """The client of a Flash plugin with broken focus behaviour. #2546: In Flash protected mode, the Flash content is in another window beneath the plugin window. Unfortunately, Flash doesn't bother to set focus to this window. To work around this, when focus hits this object, focus is forced to the child. """ def event_gainFocus(self): try: self.firstChild.firstChild.setFocus() except AttributeError: super(PluginClientWithBrokenFocus, self).event_gainFocus() def findExtraOverlayClasses(obj, clsList): """Determine the most appropriate class if this is a Flash object. This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses} except that it never calls any other findOverlayClasses method. """ iaRole = obj.IAccessibleRole if obj.windowClassName == "GeckoPluginWindow" and iaRole == oleacc.ROLE_SYSTEM_CLIENT and obj.childCount == 1 and obj.firstChild.windowClassName == "GeckoFPSandboxChildWindow": clsList.append(PluginClientWithBrokenFocus) return try: servProv = obj.IAccessibleObject.QueryInterface(IServiceProvider) except COMError: return # Check whether this is the Flash root accessible. if iaRole == oleacc.ROLE_SYSTEM_CLIENT: try: servProv.QueryService(IFlashAccessibility._iid_, IFlashAccessibility) clsList.append(Root) except COMError: pass # If this is a client and IFlashAccessibility wasn't present, this is not a Flash object. return # Check whether this is a Flash input text field. try: # We have to fetch ISimpleTextSelectionObject in order to check whether this is an input text field, so store it on the instance. obj.ISimpleTextSelectionObject = servProv.QueryService(ISimpleTextSelection._iid_, ISimpleTextSelection) clsList.append(InputTextField) except COMError: pass