|
39 | 39 | import controlTypes |
40 | 40 | from logHandler import log |
41 | 41 | import mouseHandler |
42 | | -from NVDAHelper.localLib import VBuf_getTextInRange |
| 42 | +import NVDAObjects.IAccessible |
| 43 | +import NVDAHelper |
| 44 | + |
| 45 | +# NVDA <= 2025.x: source/NVDAHelper.py exposes VBuf_getTextInRange directly. |
| 46 | +# NVDA >= 2026.1 (commit 9cc7ed6a6): NVDAHelper is a package and localLib contains declarations. |
| 47 | +if hasattr(NVDAHelper, "VBuf_getTextInRange"): |
| 48 | + VBuf_getTextInRange = NVDAHelper.VBuf_getTextInRange |
| 49 | +elif hasattr(NVDAHelper, "localLib") and hasattr(NVDAHelper.localLib, "VBuf_getTextInRange"): |
| 50 | + VBuf_getTextInRange = NVDAHelper.localLib.VBuf_getTextInRange |
| 51 | +else: |
| 52 | + from NVDAHelper.localLib import VBuf_getTextInRange |
43 | 53 | import textInfos |
44 | 54 | import treeInterceptorHandler |
45 | 55 | import ui |
@@ -521,13 +531,16 @@ def url(self): |
521 | 531 | return None |
522 | 532 | url = None |
523 | 533 | obj = self.getNVDAObject() |
524 | | - while obj.role != self.role: |
| 534 | + while obj is not None and obj.role != self.role: |
525 | 535 | try: |
526 | 536 | obj = obj.parent |
527 | 537 | except Exception: |
528 | | - break |
529 | | - else: |
530 | | - url = obj.IAccessibleObject.accValue(obj.IAccessibleChildID) |
| 538 | + obj = None |
| 539 | + if obj is not None: |
| 540 | + try: |
| 541 | + url = obj.IAccessibleObject.accValue(obj.IAccessibleChildID) |
| 542 | + except Exception: |
| 543 | + url = None |
531 | 544 | self._url = url |
532 | 545 | return url |
533 | 546 |
|
@@ -888,7 +901,28 @@ def sayAll(self): |
888 | 901 | def getNVDAObject(self): |
889 | 902 | if not self.isReady(): |
890 | 903 | return None |
891 | | - return self.getTextInfo().NVDAObjectAtStart |
| 904 | + info = self.getTextInfo() |
| 905 | + if info is None: |
| 906 | + return None |
| 907 | + obj = info.NVDAObjectAtStart |
| 908 | + if obj is not None: |
| 909 | + return obj |
| 910 | + try: |
| 911 | + docHandle, objId = self.controlIdentifier |
| 912 | + except Exception: |
| 913 | + return None |
| 914 | + if not docHandle or not objId: |
| 915 | + return None |
| 916 | + try: |
| 917 | + # NVDA commit 9afb6fc5b (introduced in 2024.3) changed Gecko IA2 object |
| 918 | + # resolution for iframes, and NVDAObjectAtStart can be None in some cases. |
| 919 | + # Legacy pre-2024.3 fallback path: event-based resolution. |
| 920 | + # This keeps URL-based matching retrocompatible for iframe-driven submodules. |
| 921 | + return NVDAObjects.IAccessible.getNVDAObjectFromEvent( |
| 922 | + docHandle, winUser.OBJID_CLIENT, objId |
| 923 | + ) |
| 924 | + except Exception: |
| 925 | + return None |
892 | 926 |
|
893 | 927 | def mouseMove(self): |
894 | 928 | if not self.checkNodeManager(): |
|
0 commit comments