| Trees | Indices | Help |
|---|
|
|
1 #NVDAObjects/MSHTML.py
2 #A part of NonVisual Desktop Access (NVDA)
3 #Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
4 #This file is covered by the GNU General Public License.
5 #See the file COPYING for more details.
6
7 import time
8 from comtypes import COMError
9 import comtypes.client
10 import comtypes.automation
11 from comtypes import IServiceProvider
12 import contextlib
13 import winUser
14 import oleacc
15 import IAccessibleHandler
16 import aria
17 from keyboardHandler import KeyboardInputGesture
18 import api
19 import textInfos
20 from logHandler import log
21 import controlTypes
22 from . import IAccessible
23 from ..behaviors import EditableTextWithoutAutoSelectDetection
24 from .. import InvalidNVDAObject
25 from ..window import Window
26
27 IID_IHTMLElement=comtypes.GUID('{3050F1FF-98B5-11CF-BB82-00AA00BDCE0B}')
46
47 nodeNamesToNVDARoles={
48 "FRAME":controlTypes.ROLE_FRAME,
49 "IFRAME":controlTypes.ROLE_FRAME,
50 "FRAMESET":controlTypes.ROLE_DOCUMENT,
51 "BODY":controlTypes.ROLE_DOCUMENT,
52 "TH":controlTypes.ROLE_TABLECELL,
53 "IMG":controlTypes.ROLE_GRAPHIC,
54 "A":controlTypes.ROLE_LINK,
55 "LABEL":controlTypes.ROLE_LABEL,
56 "#text":controlTypes.ROLE_STATICTEXT,
57 "H1":controlTypes.ROLE_HEADING,
58 "H2":controlTypes.ROLE_HEADING,
59 "H3":controlTypes.ROLE_HEADING,
60 "H4":controlTypes.ROLE_HEADING,
61 "H5":controlTypes.ROLE_HEADING,
62 "H6":controlTypes.ROLE_HEADING,
63 "DIV":controlTypes.ROLE_SECTION,
64 "P":controlTypes.ROLE_PARAGRAPH,
65 "FORM":controlTypes.ROLE_FORM,
66 "UL":controlTypes.ROLE_LIST,
67 "OL":controlTypes.ROLE_LIST,
68 "DL":controlTypes.ROLE_LIST,
69 "LI":controlTypes.ROLE_LISTITEM,
70 "DD":controlTypes.ROLE_LISTITEM,
71 "DT":controlTypes.ROLE_LISTITEM,
72 "TR":controlTypes.ROLE_TABLEROW,
73 "THEAD":controlTypes.ROLE_TABLEHEADER,
74 "TBODY":controlTypes.ROLE_TABLEBODY,
75 "HR":controlTypes.ROLE_SEPARATOR,
76 "OBJECT":controlTypes.ROLE_EMBEDDEDOBJECT,
77 "APPLET":controlTypes.ROLE_EMBEDDEDOBJECT,
78 "EMBED":controlTypes.ROLE_EMBEDDEDOBJECT,
79 "FIELDSET":controlTypes.ROLE_GROUPING,
80 "OPTION":controlTypes.ROLE_LISTITEM,
81 }
84 try:
85 s=HTMLNode.QueryInterface(IServiceProvider)
86 return s.QueryService(oleacc.IAccessible._iid_,oleacc.IAccessible)
87 except COMError:
88 raise NotImplementedError
89
91 try:
92 s=IAccessibleObject.QueryInterface(IServiceProvider)
93 i=s.QueryService(IID_IHTMLElement,comtypes.automation.IDispatch)
94 if not i:
95 # QueryService should fail if IHTMLElement is not supported, but some applications misbehave and return a null COM pointer.
96 raise NotImplementedError
97 return comtypes.client.dynamic.Dispatch(i)
98 except COMError:
99 raise NotImplementedError
100
102 try:
103 element=document.getElementsByName(ID).item(0)
104 except COMError as e:
105 log.debugWarning("document.getElementsByName failed with COMError %s"%e)
106 element=None
107 if element:
108 return element
109 try:
110 nodeName=document.body.nodeName
111 except COMError as e:
112 log.debugWarning("document.body.nodeName failed with COMError %s"%e)
113 return None
114 if nodeName=="FRAMESET":
115 tag="frame"
116 else:
117 tag="iframe"
118 try:
119 frames=document.getElementsByTagName(tag)
120 except COMError as e:
121 log.debugWarning("document.getElementsByTagName failed with COMError %s"%e)
122 return None
123 for frame in frames:
124 try:
125 pacc=IAccessibleFromHTMLNode(frame)
126 except NotImplementedError:
127 # #1569: It's not possible to get an IAccessible from frames marked with an ARIA role of presentation.
128 # In this case, just skip this frame.
129 continue
130 res=IAccessibleHandler.accChild(pacc,1)
131 if not res: continue
132 childElement=HTMLNodeFromIAccessible(res[0])
133 if not childElement: continue
134 childElement=locateHTMLElementByID(childElement.document,ID)
135 if not childElement: continue
136 return childElement
137
139
141 #Try to calculate the line range by finding screen coordinates and using moveToPoint
142 parent=textRange.parentElement()
143 if not parent.isMultiline: #fastest solution for single line edits (<input type="text">)
144 textRange.expand("textEdit")
145 return
146 parentRect=parent.getBoundingClientRect()
147 #This can be simplified when comtypes is fixed
148 lineTop=comtypes.client.dynamic._Dispatch(textRange._comobj).offsetTop
149 lineLeft=parentRect.left+parent.clientLeft
150 #editable documents have a different right most boundary to <textarea> elements.
151 if self.obj.HTMLNode.document.body.isContentEditable:
152 lineRight=parentRect.right
153 else:
154 lineRight=parentRect.left+parent.clientWidth
155 tempRange=textRange.duplicate()
156 try:
157 tempRange.moveToPoint(lineLeft,lineTop)
158 textRange.setEndPoint("startToStart",tempRange)
159 tempRange.moveToPoint(lineRight,lineTop)
160 textRange.setEndPoint("endToStart",tempRange)
161 return
162 except COMError:
163 pass
164 #MoveToPoint fails on Some (possibly floated) textArea elements.
165 #Instead use the physical selection, by moving it with key presses, to work out the line.
166 #This approach is somewhat slower, and less accurate.
167 with self.obj.suspendCaretEvents():
168 selObj=parent.document.selection
169 oldSelRange=selObj.createRange().duplicate()
170 # #1566: Calling textRange.select() sometimes throws focus onto the document,
171 # so create a new range from the selection and move the selection using that.
172 selObj.createRange().moveToBookmark(textRange.getBookmark())
173 KeyboardInputGesture.fromName("home").send()
174 api.processPendingEvents(False)
175 newSelStartMark=selObj.createRange().getBookmark()
176 KeyboardInputGesture.fromName("end").send()
177 api.processPendingEvents(False)
178 newSelEndMark=selObj.createRange().getBookmark()
179 tempRange.moveToBookmark(newSelStartMark)
180 textRange.setEndPoint("startToStart",tempRange)
181 tempRange.moveToBookmark(newSelEndMark)
182 textRange.setEndPoint("endToStart",tempRange)
183 oldSelRange.select()
184
186 super(MSHTMLTextInfo,self).__init__(obj,position)
187 if _rangeObj:
188 self._rangeObj=_rangeObj.duplicate()
189 return
190 try:
191 editableBody=self.obj.HTMLNodeName=="BODY" and self.obj.isContentEditable
192 except:
193 editableBody=False
194 if editableBody:
195 self._rangeObj=self.obj.HTMLNode.document.selection.createRange()
196 else:
197 self._rangeObj=self.obj.HTMLNode.createTextRange()
198 if position in (textInfos.POSITION_CARET,textInfos.POSITION_SELECTION):
199 activeElement=self.obj.HTMLNode.document.activeElement
200 if not activeElement or self.obj.HTMLNode.uniqueNumber!=activeElement.uniqueNumber:
201 raise RuntimeError("Only works with currently selected element")
202 if not editableBody:
203 mark=self.obj.HTMLNode.document.selection.createRange().GetBookmark()
204 self._rangeObj.MoveToBookmark(mark)
205 if position==textInfos.POSITION_CARET:
206 self._rangeObj.collapse()
207 return
208 if position==textInfos.POSITION_FIRST:
209 self._rangeObj.collapse()
210 elif position==textInfos.POSITION_LAST:
211 self._rangeObj.expand("textedit")
212 self.collapse(True)
213 self._rangeObj.move("character",-1)
214 elif position==textInfos.POSITION_ALL:
215 self._rangeObj.expand("textedit")
216 elif isinstance(position,textInfos.Bookmark):
217 if position.infoClass==self.__class__:
218 self._rangeObj.moveToBookmark(position.data)
219 else:
220 raise TypeError("Bookmark was for %s type, not for %s type"%(position.infoClass.__name__,self.__class__.__name__))
221 else:
222 raise NotImplementedError("position: %s"%position)
223
225 if unit==textInfos.UNIT_PARAGRAPH:
226 unit=textInfos.UNIT_LINE
227 if unit==textInfos.UNIT_LINE and self.basePosition not in [textInfos.POSITION_SELECTION,textInfos.POSITION_CARET]:
228 unit=textInfos.UNIT_SENTENCE
229 if unit==textInfos.UNIT_READINGCHUNK:
230 unit=textInfos.UNIT_SENTENCE
231 if unit==textInfos.UNIT_CHARACTER:
232 self._rangeObj.expand("character")
233 elif unit==textInfos.UNIT_WORD:
234 #Expand to word at the start of a control is broken in MSHTML
235 #Unless we expand to character first.
236 self._rangeObj.expand("character")
237 self._rangeObj.expand("word")
238 elif unit==textInfos.UNIT_SENTENCE:
239 self._rangeObj.expand("sentence")
240 elif unit==textInfos.UNIT_LINE:
241 self._expandToLine(self._rangeObj)
242 elif unit==textInfos.UNIT_STORY:
243 self._rangeObj.expand("textedit")
244 else:
245 raise NotImplementedError("unit: %s"%unit)
246
248 if self._rangeObj.compareEndPoints("startToEnd",self._rangeObj)==0:
249 return True
250 else:
251 return False
252
254 self._rangeObj.collapse(not end)
255
258
260 return self._rangeObj.compareEndPoints(which,other._rangeObj)
261
263 self._rangeObj.setEndPoint(which,other._rangeObj)
264
266 text=self._rangeObj.text
267 if not text:
268 text=u""
269 if controlTypes.STATE_PROTECTED in self.obj.states:
270 text=u'*'*len(text)
271 return text
272
274 if unit in [textInfos.UNIT_READINGCHUNK,textInfos.UNIT_LINE]:
275 unit=textInfos.UNIT_SENTENCE
276 if unit==textInfos.UNIT_STORY:
277 unit="textedit"
278 if endPoint=="start":
279 moveFunc=self._rangeObj.moveStart
280 elif endPoint=="end":
281 moveFunc=self._rangeObj.moveEnd
282 else:
283 moveFunc=self._rangeObj.move
284 if direction<0:
285 # #1605: If at the end of a line, moving back seems to land on a blank unit,
286 # which breaks backspacing.
287 # Expanding first seems to fix this.
288 self._rangeObj.expand("character")
289 res=moveFunc(unit,direction)
290 return res
291
294
297
300
302
303 HTMLNodeNameNavSkipList=['#comment','SCRIPT','HEAD','HTML','PARAM','STYLE']
304 HTMLNodeNameEmbedList=['OBJECT','EMBED','APPLET','FRAME','IFRAME']
305
306 _ignoreCaretEvents=False #:Set to true when moving the caret to calculate lines, event_caret will be disabled.
307
308 @contextlib.contextmanager
310 """Suspends caret events while you need to move the caret to calculate things."""
311 oldVal=self._ignoreCaretEvents
312 self._ignoreCaretEvents=True
313 yield oldVal
314 self._ignoreCaretEvents=oldVal
315
317 if self._ignoreCaretEvents: return
318 if self.TextInfo is not MSHTMLTextInfo:
319 return
320 try:
321 newCaretBookmark=self.makeTextInfo(textInfos.POSITION_CARET).bookmark
322 except RuntimeError: #caret events can be fired on the object (focus) when its not the real MSHTML selection
323 newCaretBookmark=None
324 if not newCaretBookmark or newCaretBookmark==getattr(self,'_oldCaretBookmark',None):
325 return
326 self._oldCaretBookmark=newCaretBookmark
327 return super(MSHTML,self).event_caret()
328
329 @classmethod
331 IAccessibleObject=kwargs['IAccessibleObject']
332 HTMLNode=None
333 try:
334 HTMLNode=HTMLNodeFromIAccessible(IAccessibleObject)
335 except NotImplementedError:
336 pass
337 if not HTMLNode:
338 return False
339
340 if relation=="focus":
341 try:
342 HTMLNode=HTMLNode.document.activeElement
343 # The IAccessibleObject may be incorrect now, so let the constructor recalculate it.
344 del kwargs['IAccessibleObject']
345 except:
346 log.exception("Error getting activeElement")
347
348 kwargs['HTMLNode']=HTMLNode
349 return True
350
352 if self.TextInfo == MSHTMLTextInfo:
353 clsList.append(EditableTextWithoutAutoSelectDetection)
354 nodeName = self.HTMLNodeName
355 if nodeName:
356 if nodeName=="SELECT" and self.windowStyle&winUser.WS_POPUP:
357 clsList.append(PopupList)
358 elif nodeNamesToNVDARoles.get(nodeName) == controlTypes.ROLE_DOCUMENT:
359 clsList.append(Body)
360 elif nodeName == "OBJECT":
361 clsList.append(Object)
362 elif nodeName=="FIELDSET":
363 clsList.append(Fieldset)
364 clsList.append(MSHTML)
365 if not self.HTMLNodeHasAncestorIAccessible:
366 # The IAccessibleObject is for this node (not an ancestor), so IAccessible overlay classes are relevant.
367 super(MSHTML,self).findOverlayClasses(clsList)
368
370 if self.role==controlTypes.ROLE_DOCUMENT and not self.isContentEditable:
371 import virtualBuffers.MSHTML
372 return virtualBuffers.MSHTML.MSHTML
373 return super(MSHTML,self).treeInterceptorClass
374
376 return HTMLAttribCache(self.HTMLNode)
377
379 self.HTMLNodeHasAncestorIAccessible=False
380 if not IAccessibleObject:
381 # Find an IAccessible for HTMLNode and determine whether it is for an ancestor.
382 tempNode=HTMLNode
383 while tempNode:
384 try:
385 IAccessibleObject=IAccessibleFromHTMLNode(tempNode)
386 except NotImplementedError:
387 IAccessibleObject=None
388 if IAccessibleObject:
389 IAccessibleChildID=0
390 if tempNode is not HTMLNode:
391 self.HTMLNodeHasAncestorIAccessible=True
392 break
393 try:
394 tempNode=tempNode.parentNode
395 except COMError:
396 tempNode=None
397
398 if not IAccessibleObject:
399 raise InvalidNVDAObject("Couldn't get IAccessible, probably dead object")
400
401 super(MSHTML,self).__init__(IAccessibleObject=IAccessibleObject,IAccessibleChildID=IAccessibleChildID,**kwargs)
402 self.HTMLNode=HTMLNode
403
404 #object and embed nodes give back an incorrect IAccessible via queryService, so we must treet it as an ancestor IAccessible
405 if self.HTMLNodeName in ("OBJECT","EMBED"):
406 self.HTMLNodeHasAncestorIAccessible=True
407
409 if not hasattr(self,'_HTMLNodeSupportsTextRanges'):
410 try:
411 self.HTMLNode.createTextRange()
412 self._HTMLNodeSupportsTextRanges=True
413 except (COMError,NameError):
414 self._HTMLNodeSupportsTextRanges=False
415 if self._HTMLNodeSupportsTextRanges:
416 return MSHTMLTextInfo
417 return super(MSHTML,self).TextInfo
418
420 if not super(MSHTML,self).isDuplicateIAccessibleEvent(obj):
421 return False
422 #MSHTML winEvents can't be trusted for uniqueness, so just do normal object comparison.
423 return self==obj
424
425
427 if self.HTMLNode and other.HTMLNode:
428 try:
429 return self.windowHandle == other.windowHandle and self.HTMLNodeUniqueNumber == other.HTMLNodeUniqueNumber
430 except (COMError,NameError):
431 pass
432 return super(MSHTML, self)._isEqual(other)
433
435 presType=super(MSHTML,self).presentationType
436 if presType==self.presType_content and self.HTMLAttributes['role']=="presentation":
437 presType=self.presType_layout
438 if presType==self.presType_content and self.role in (controlTypes.ROLE_TABLECELL,controlTypes.ROLE_TABLEROW,controlTypes.ROLE_TABLE,controlTypes.ROLE_TABLEBODY) and self.treeInterceptor and self.treeInterceptor.isNVDAObjectPartOfLayoutTable(self):
439 presType=self.presType_layout
440 return presType
441
442
444 ariaRole=self.HTMLAttributes['aria-role']
445 if ariaRole=="gridcell":
446 return True
447 return super(MSHTML,self).shouldAllowIAccessibleFocusEvent
448
450 ariaLabel=self.HTMLAttributes['aria-label']
451 if ariaLabel:
452 return ariaLabel
453 ariaLabelledBy=self.HTMLAttributes['aria-labelledBy']
454 if ariaLabelledBy:
455 try:
456 labelNode=self.HTMLNode.document.getElementById(ariaLabelledBy)
457 except (COMError,NameError):
458 labelNode=None
459 if labelNode:
460 try:
461 return labelNode.innerText
462 except (COMError,NameError):
463 pass
464 title=self.HTMLAttributes['title']
465 if title:
466 return title
467 if self.IAccessibleRole==oleacc.ROLE_SYSTEM_TABLE:
468 summary=self.HTMLAttributes['summary']
469 if summary:
470 return summary
471 if self.HTMLNodeHasAncestorIAccessible:
472 return ""
473 #IE inappropriately generates the name from descendants on some controls
474 if self.IAccessibleRole in (oleacc.ROLE_SYSTEM_MENUBAR,oleacc.ROLE_SYSTEM_TOOLBAR,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_TABLE,oleacc.ROLE_SYSTEM_DOCUMENT):
475 return ""
476 return super(MSHTML,self).name
477
479 if self.HTMLNodeHasAncestorIAccessible:
480 try:
481 value=self.HTMLNode.data
482 except (COMError,NameError):
483 value=""
484 return value
485 IARole=self.IAccessibleRole
486 if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT):
487 return ""
488 else:
489 return super(MSHTML,self).value
490
492 ariaDescribedBy=self.HTMLAttributes['aria-describedBy']
493 if ariaDescribedBy:
494 try:
495 descNode=self.HTMLNode.document.getElementById(ariaDescribedBy)
496 except (COMError,NameError):
497 descNode=None
498 if descNode:
499 try:
500 return descNode.innerText
501 except (COMError,NameError):
502 pass
503 if self.HTMLNodeHasAncestorIAccessible:
504 return ""
505 return super(MSHTML,self).description
506
508 if self.HTMLNode:
509 try:
510 return self.HTMLNode.data or ""
511 except (COMError, AttributeError, NameError):
512 pass
513 try:
514 return self.HTMLNode.innerText or ""
515 except (COMError, AttributeError, NameError):
516 pass
517 return super(MSHTML,self).basicText
518
520 if self.HTMLNode:
521 ariaRole=self.HTMLAttributes['role']
522 if ariaRole:
523 role=aria.ariaRolesToNVDARoles.get(ariaRole)
524 if role:
525 return role
526 nodeName=self.HTMLNodeName
527 if nodeName:
528 if nodeName in ("OBJECT","EMBED","APPLET"):
529 return controlTypes.ROLE_EMBEDDEDOBJECT
530 if self.HTMLNodeHasAncestorIAccessible or nodeName in ("BODY","FRAMESET","FRAME","IFRAME","LABEL"):
531 return nodeNamesToNVDARoles.get(nodeName,controlTypes.ROLE_TEXTFRAME)
532 if self.IAccessibleChildID>0:
533 states=super(MSHTML,self).states
534 if controlTypes.STATE_LINKED in states:
535 return controlTypes.ROLE_LINK
536 return super(MSHTML,self).role
537
539 if not self.HTMLNodeHasAncestorIAccessible:
540 states=super(MSHTML,self).states
541 else:
542 states=set()
543 ariaSort=self.HTMLAttributes['aria-sort']
544 state=aria.ariaSortValuesToNVDAStates.get(ariaSort)
545 if state is not None:
546 states.add(state)
547 ariaRequired=self.HTMLAttributes['aria-required']
548 if ariaRequired=="true":
549 states.add(controlTypes.STATE_REQUIRED)
550 ariaSelected=self.HTMLAttributes['aria-selected']
551 if ariaSelected=="true":
552 states.add(controlTypes.STATE_SELECTED)
553 elif ariaSelected=="false":
554 states.discard(controlTypes.STATE_SELECTED)
555 ariaExpanded=self.HTMLAttributes['aria-expanded']
556 if ariaExpanded=="true":
557 states.add(controlTypes.STATE_EXPANDED)
558 elif ariaExpanded=="false":
559 states.add(controlTypes.STATE_COLLAPSED)
560 ariaInvalid=self.HTMLAttributes['aria-invalid']
561 if ariaInvalid=="true":
562 states.add(controlTypes.STATE_INVALID)
563 ariaGrabbed=self.HTMLAttributes['aria-grabbed']
564 if ariaGrabbed=="true":
565 states.add(controlTypes.STATE_DRAGGING)
566 elif ariaGrabbed=="false":
567 states.add(controlTypes.STATE_DRAGGABLE)
568 ariaDropeffect=self.HTMLAttributes['aria-dropeffect']
569 if ariaDropeffect and ariaDropeffect!="none":
570 states.add(controlTypes.STATE_DROPTARGET)
571 if self.isContentEditable:
572 states.add(controlTypes.STATE_EDITABLE)
573 states.discard(controlTypes.STATE_READONLY)
574 nodeName=self.HTMLNodeName
575 if nodeName=="TEXTAREA":
576 states.add(controlTypes.STATE_MULTILINE)
577 return states
578
584
586 if self.HTMLNode:
587 try:
588 parentNode=self.HTMLNode.parentElement
589 except (COMError,NameError):
590 parentNode=None
591 if not parentNode and self.HTMLNodeHasAncestorIAccessible:
592 try:
593 parentNode=self.HTMLNode.parentNode
594 except (COMError,NameError):
595 parentNode=None
596 if parentNode:
597 obj=MSHTML(HTMLNode=parentNode)
598 if obj and obj.HTMLNodeName not in self.HTMLNodeNameNavSkipList:
599 return obj
600 return super(MSHTML,self).parent
601
603 if self.HTMLNode:
604 try:
605 previousNode=self.HTMLNode.previousSibling
606 except COMError:
607 previousNode=None
608 if not previousNode:
609 return None
610 obj=MSHTML(HTMLNode=previousNode)
611 if obj and obj.HTMLNodeName in self.HTMLNodeNameNavSkipList:
612 obj=obj.previous
613 return obj
614 return super(MSHTML,self).previous
615
617 if self.HTMLNode:
618 try:
619 nextNode=self.HTMLNode.nextSibling
620 except COMError:
621 nextNode=None
622 if not nextNode:
623 return None
624 obj=MSHTML(HTMLNode=nextNode)
625 if obj and obj.HTMLNodeName in self.HTMLNodeNameNavSkipList:
626 obj=obj.next
627 return obj
628 return super(MSHTML,self).next
629
631 if self.HTMLNode:
632 if self.HTMLNodeName in ("FRAME","IFRAME"):
633 return super(MSHTML,self).firstChild
634 try:
635 childNode=self.HTMLNode.firstChild
636 except COMError:
637 childNode=None
638 if not childNode:
639 return None
640 obj=MSHTML(HTMLNode=childNode)
641 if obj and obj.HTMLNodeName in self.HTMLNodeNameNavSkipList:
642 return obj.next
643 return obj
644 if self.HTMLNodeHasAncestorIAccessible:
645 return None
646 return super(MSHTML,self).firstChild
647
649 if self.HTMLNode:
650 if self.HTMLNodeName in ("FRAME","IFRAME"):
651 return super(MSHTML,self).lastChild
652 try:
653 childNode=self.HTMLNode.lastChild
654 except COMError:
655 childNode=None
656 if not childNode:
657 return None
658 obj=MSHTML(HTMLNode=childNode)
659 if obj and obj.HTMLNodeName in self.HTMLNodeNameNavSkipList:
660 return obj.previous
661 return obj
662 if self.HTMLNodeHasAncestorIAccessible:
663 return None
664 return super(MSHTML,self).lastChild
665
667 if not self.role==controlTypes.ROLE_TABLECELL or not self.HTMLNode:
668 raise NotImplementedError
669 try:
670 return self.HTMLNode.cellIndex+1
671 except:
672 raise NotImplementedError
673
675 if not self.role==controlTypes.ROLE_TABLECELL or not self.HTMLNode:
676 raise NotImplementedError
677 HTMLNode=self.HTMLNode
678 while HTMLNode:
679 try:
680 return HTMLNode.rowIndex+1
681 except:
682 pass
683 HTMLNode=HTMLNode.parentNode
684 raise NotImplementedError
685
687 if self.role!=controlTypes.ROLE_TABLE or not self.HTMLNode:
688 raise NotImplementedError
689 try:
690 return len([x for x in self.HTMLNode.rows])
691 except:
692 raise NotImplementedError
693
695 if not self.HTMLNode:
696 return
697 try:
698 self.HTMLNode.scrollInToView()
699 except (COMError,NameError):
700 pass
701
703 if self.HTMLNode:
704 try:
705 self.HTMLNode.click()
706 return
707 except COMError:
708 return
709 except NameError:
710 pass
711 super(MSHTML,self).doAction(index=index)
712
714 if self.HTMLNodeHasAncestorIAccessible:
715 try:
716 self.HTMLNode.focus()
717 except (COMError, AttributeError, NameError):
718 pass
719 return
720 super(MSHTML,self).setFocus()
721
723 if self.role not in (controlTypes.ROLE_TABLECELL,controlTypes.ROLE_TABLEROW) or not self.HTMLNode:
724 raise NotImplementedError
725 HTMLNode=self.HTMLNode
726 while HTMLNode:
727 if HTMLNode.nodeName=="TABLE": return MSHTML(HTMLNode=HTMLNode)
728 HTMLNode=HTMLNode.parentNode
729 raise NotImplementedError
730
732 if not hasattr(self,'_HTMLNodeUniqueNumber'):
733 self._HTMLNodeUniqueNumber=self.HTMLNode.uniqueNumber
734 return self._HTMLNodeUniqueNumber
735
743
745 """The object which receives value change events for combo boxes in MSHTML/IE 6.
746 """
747
749 focus = api.getFocusObject()
750 if controlTypes.STATE_FOCUSED not in self.states or focus.role != controlTypes.ROLE_COMBOBOX:
751 # This combo box is not focused.
752 return super(V6ComboBox, self).event_valueChange()
753 # This combo box is focused. However, the value change is not fired on the real focus object.
754 # Therefore, redirect this event to the real focus object.
755 focus.event_valueChange()
756
758
760 try:
761 child=self.HTMLNode.children[0]
762 except (COMError,NameError):
763 child=None
764 if not child:
765 return super(Fieldset,self).name
766 try:
767 nodeName=child.nodeName
768 except (COMError,NameError):
769 return super(Fieldset,self).name
770 if nodeName!="LEGEND":
771 return super(Fieldset,self).name
772 try:
773 text=child.innerText
774 except (COMError,NameError):
775 return super(Fieldset,self).name
776 return text
777
779
781 # The parent of the body accessible is an irrelevant client object (description: MSAAHTML Registered Handler).
782 # This object isn't returned when requesting OBJID_CLIENT, nor is it returned as a child of its parent.
783 # Therefore, eliminate it from the ancestry completely.
784 parent = super(Body, self).parent
785 if parent:
786 return parent.parent
787 else:
788 return parent
789
791 # We must override this because we override parent to skip the MSAAHTML Registered Handler client,
792 # which might have the focused state.
793 if controlTypes.STATE_FOCUSED in self.states:
794 return True
795 parent = super(Body, self).parent
796 if not parent:
797 return False
798 return parent.shouldAllowIAccessibleFocusEvent
799
801
803 # We want firstChild to return the accessible for the embedded object.
804 from objidl import IOleWindow
805 # Try to get the window for the embedded object.
806 try:
807 window = self.HTMLNode.object.QueryInterface(IOleWindow).GetWindow()
808 except COMError:
809 window = None
810 if not window or window == self.windowHandle:
811 return super(Object, self).firstChild
812 return Window(windowHandle=window)
813
815 """A window for a plugin.
816 """
817
818 # MSHTML fires focus on this window after the plugin may already have fired a focus event.
819 # We don't want this to override the focus event fired by the plugin.
820 shouldAllowIAccessibleFocusEvent = False
821
823 """
824 Temporary popup lists created when expanding a combo box have a correct accParent which points back to the combobox, so use that. The parentElement points to a temporary document fragment which is not useful.
825 """
826
828 return super(MSHTML,self).parent
829
831 """The top level client of an MSHTML control.
832 """
833
834 # Get rid of the URL.
835 name = None
836 # Get rid of "MSAAHTML Registered Handler".
837 description = None
838
840 """Determine the most appropriate class for MSHTML objects.
841 This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses} except that it never calls any other findOverlayClasses method.
842 """
843 windowClass = obj.windowClassName
844 iaRole = obj.IAccessibleRole
845 if windowClass == "Internet Explorer_TridentCmboBx" and iaRole == oleacc.ROLE_SYSTEM_COMBOBOX:
846 clsList.append(V6ComboBox)
847 return
848
849 if windowClass != "Internet Explorer_Server":
850 return
851
852 if iaRole == oleacc.ROLE_SYSTEM_WINDOW and obj.event_objectID > 0:
853 clsList.append(PluginWindow)
854 elif iaRole == oleacc.ROLE_SYSTEM_CLIENT and obj.event_objectID == winUser.OBJID_CLIENT:
855 clsList.append(RootClient)
856
| Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Fri Nov 18 17:46:10 2011 | http://epydoc.sourceforge.net |