|
Module IAccessibleHandler
|
|
1
2
3
4
5
6
7 from __future__ import with_statement
8 import oleacc
9
10 MAX_WINEVENTS=500
11 MAX_WINEVENTS_PER_THREAD=10
12
13
14
15 REGCLS_SINGLEUSE = 0
16 REGCLS_MULTIPLEUSE = 1
17 REGCLS_MULTI_SEPARATE = 2
18 REGCLS_SUSPENDED = 4
19 REGCLS_SURROGATE = 8
20
21 CLSCTX_INPROC_SERVER=1
22 CLSCTX_LOCAL_SERVER=4
23
24
25 NAVRELATION_LABEL_FOR=0x1002
26 NAVRELATION_LABELLED_BY=0x1003
27 NAVRELATION_NODE_CHILD_OF=0x1005
28 NAVRELATION_EMBEDS=0x1009
29
30
31 IA2_RELATION_FLOWS_FROM = "flowsFrom"
32 IA2_RELATION_FLOWS_TO = "flowsTo"
33
34 import UIAHandler
35 import heapq
36 import itertools
37 import time
38 import struct
39 import weakref
40 from ctypes import *
41 from ctypes.wintypes import *
42 from comtypes.automation import *
43 from comtypes.server import *
44 from comtypes import GUID, IServiceProvider
45 import comtypes.client
46 import comtypes.client.lazybind
47 import Queue
48 from comInterfaces.Accessibility import *
49 from comInterfaces.IAccessible2Lib import *
50 import tones
51 import globalVars
52 from logHandler import log
53 import JABHandler
54 import eventHandler
55 import winKernel
56 import winUser
57 import speech
58 import sayAllHandler
59 import api
60 import queueHandler
61 import NVDAObjects.IAccessible
62 import NVDAObjects.window
63 import appModuleHandler
64 import config
65 import mouseHandler
66 import controlTypes
67
68 MENU_EVENTIDS=(winUser.EVENT_SYSTEM_MENUSTART,winUser.EVENT_SYSTEM_MENUEND,winUser.EVENT_SYSTEM_MENUPOPUPSTART,winUser.EVENT_SYSTEM_MENUPOPUPEND)
69
71 """Collects and limits winEvents based on whether they are focus changes, or just generic (all other ones).
72
73 Only allow a max of L{maxFocusItems}, if more are added then the oldest focus event is removed to make room.
74 Only allow one event for one specific object at a time, though push it further forward in time if a duplicate tries to get added. This is true for both generic and focus events.
75 """
76
78 """
79 @param maxFocusItems: the amount of focus changed events allowed to be queued.
80 @type maxFocusItems: integer
81 """
82 self.maxFocusItems=maxFocusItems
83 self._focusEventCache={}
84 self._genericEventCache={}
85 self._eventHeap=[]
86 self._eventCounter=itertools.count()
87 self._lastMenuEvent=None
88
89 - def addEvent(self,eventID,window,objectID,childID,threadID):
90 """Adds a winEvent to the limiter.
91 @param eventID: the winEvent type
92 @type eventID: integer
93 @param window: the window handle of the winEvent
94 @type window: integer
95 @param objectID: the objectID of the winEvent
96 @type objectID: integer
97 @param childID: the childID of the winEvent
98 @type childID: integer
99 @param threadID: the threadID of the winEvent
100 @type threadID: integer
101 """
102 if eventID==winUser.EVENT_OBJECT_FOCUS:
103 if objectID in (winUser.OBJID_SYSMENU,winUser.OBJID_MENU) and childID==0:
104
105 return
106
107 if (winUser.EVENT_SYSTEM_FOREGROUND,window,objectID,childID,threadID) in self._focusEventCache:
108 return
109 self._focusEventCache[(eventID,window,objectID,childID,threadID)]=next(self._eventCounter)
110 return
111 elif eventID==winUser.EVENT_SYSTEM_FOREGROUND:
112 self._focusEventCache.pop((winUser.EVENT_OBJECT_FOCUS,window,objectID,childID,threadID),None)
113 self._focusEventCache[(eventID,window,objectID,childID,threadID)]=next(self._eventCounter)
114 elif eventID==winUser.EVENT_OBJECT_SHOW:
115 k=(winUser.EVENT_OBJECT_HIDE,window,objectID,childID,threadID)
116 if k in self._genericEventCache:
117 del self._genericEventCache[k]
118 return
119 elif eventID==winUser.EVENT_OBJECT_HIDE:
120 k=(winUser.EVENT_OBJECT_SHOW,window,objectID,childID,threadID)
121 if k in self._genericEventCache:
122 del self._genericEventCache[k]
123 return
124 elif eventID==winUser.EVENT_OBJECT_DESTROY:
125 k=(winUser.EVENT_OBJECT_CREATE,window,objectID,childID,threadID)
126 if k in self._genericEventCache:
127 del self._genericEventCache[k]
128 return
129 elif eventID in MENU_EVENTIDS:
130 self._lastMenuEvent=(next(self._eventCounter),eventID,window,objectID,childID,threadID)
131 return
132 self._genericEventCache[(eventID,window,objectID,childID,threadID)]=next(self._eventCounter)
133
135 """Returns a list of winEvents (tuples of eventID,window,objectID,childID) that have been added, though due to limiting, it will not necessarily be all the winEvents that were originally added. They are definitely garenteed to be in the correct order though.
136 """
137 if self._lastMenuEvent is not None:
138 heapq.heappush(self._eventHeap,self._lastMenuEvent)
139 self._lastMenuEvent=None
140 g=self._genericEventCache
141 self._genericEventCache={}
142 threadCounters={}
143 for k,v in sorted(g.iteritems(),key=lambda item: item[1],reverse=True):
144 threadCount=threadCounters.get(k[-1],0)
145 if threadCount>MAX_WINEVENTS_PER_THREAD:
146 continue
147 heapq.heappush(self._eventHeap,(v,)+k)
148 threadCounters[k[-1]]=threadCount+1
149 f=self._focusEventCache
150 self._focusEventCache={}
151 for k,v in sorted(f.iteritems(),key=lambda item: item[1])[0-self.maxFocusItems:]:
152 heapq.heappush(self._eventHeap,(v,)+k)
153 e=self._eventHeap
154 self._eventHeap=[]
155 r=[]
156 for count in xrange(len(e)):
157 event=heapq.heappop(e)[1:-1]
158 r.append(event)
159 return r
160
161
162 winEventLimiter=OrderedWinEventLimiter()
163
164
165 liveNVDAObjectTable=weakref.WeakValueDictionary()
166
167 IAccessibleRolesToNVDARoles={
168 oleacc.ROLE_SYSTEM_WINDOW:controlTypes.ROLE_WINDOW,
169 oleacc.ROLE_SYSTEM_CLIENT:controlTypes.ROLE_PANE,
170 oleacc.ROLE_SYSTEM_TITLEBAR:controlTypes.ROLE_TITLEBAR,
171 oleacc.ROLE_SYSTEM_DIALOG:controlTypes.ROLE_DIALOG,
172 oleacc.ROLE_SYSTEM_PANE:controlTypes.ROLE_PANE,
173 oleacc.ROLE_SYSTEM_CHECKBUTTON:controlTypes.ROLE_CHECKBOX,
174 oleacc.ROLE_SYSTEM_RADIOBUTTON:controlTypes.ROLE_RADIOBUTTON,
175 oleacc.ROLE_SYSTEM_STATICTEXT:controlTypes.ROLE_STATICTEXT,
176 oleacc.ROLE_SYSTEM_TEXT:controlTypes.ROLE_EDITABLETEXT,
177 oleacc.ROLE_SYSTEM_PUSHBUTTON:controlTypes.ROLE_BUTTON,
178 oleacc.ROLE_SYSTEM_MENUBAR:controlTypes.ROLE_MENUBAR,
179 oleacc.ROLE_SYSTEM_MENUITEM:controlTypes.ROLE_MENUITEM,
180 oleacc.ROLE_SYSTEM_MENUPOPUP:controlTypes.ROLE_POPUPMENU,
181 oleacc.ROLE_SYSTEM_COMBOBOX:controlTypes.ROLE_COMBOBOX,
182 oleacc.ROLE_SYSTEM_LIST:controlTypes.ROLE_LIST,
183 oleacc.ROLE_SYSTEM_LISTITEM:controlTypes.ROLE_LISTITEM,
184 oleacc.ROLE_SYSTEM_GRAPHIC:controlTypes.ROLE_GRAPHIC,
185 oleacc.ROLE_SYSTEM_HELPBALLOON:controlTypes.ROLE_HELPBALLOON,
186 oleacc.ROLE_SYSTEM_TOOLTIP:controlTypes.ROLE_TOOLTIP,
187 oleacc.ROLE_SYSTEM_LINK:controlTypes.ROLE_LINK,
188 oleacc.ROLE_SYSTEM_OUTLINE:controlTypes.ROLE_TREEVIEW,
189 oleacc.ROLE_SYSTEM_OUTLINEITEM:controlTypes.ROLE_TREEVIEWITEM,
190 oleacc.ROLE_SYSTEM_OUTLINEBUTTON:controlTypes.ROLE_TREEVIEWITEM,
191 oleacc.ROLE_SYSTEM_PAGETAB:controlTypes.ROLE_TAB,
192 oleacc.ROLE_SYSTEM_PAGETABLIST:controlTypes.ROLE_TABCONTROL,
193 oleacc.ROLE_SYSTEM_SLIDER:controlTypes.ROLE_SLIDER,
194 oleacc.ROLE_SYSTEM_PROGRESSBAR:controlTypes.ROLE_PROGRESSBAR,
195 oleacc.ROLE_SYSTEM_SCROLLBAR:controlTypes.ROLE_SCROLLBAR,
196 oleacc.ROLE_SYSTEM_STATUSBAR:controlTypes.ROLE_STATUSBAR,
197 oleacc.ROLE_SYSTEM_TABLE:controlTypes.ROLE_TABLE,
198 oleacc.ROLE_SYSTEM_CELL:controlTypes.ROLE_TABLECELL,
199 oleacc.ROLE_SYSTEM_COLUMN:controlTypes.ROLE_TABLECOLUMN,
200 oleacc.ROLE_SYSTEM_ROW:controlTypes.ROLE_TABLEROW,
201 oleacc.ROLE_SYSTEM_TOOLBAR:controlTypes.ROLE_TOOLBAR,
202 oleacc.ROLE_SYSTEM_COLUMNHEADER:controlTypes.ROLE_TABLECOLUMNHEADER,
203 oleacc.ROLE_SYSTEM_ROWHEADER:controlTypes.ROLE_TABLEROWHEADER,
204 oleacc.ROLE_SYSTEM_SPLITBUTTON:controlTypes.ROLE_SPLITBUTTON,
205 oleacc.ROLE_SYSTEM_BUTTONDROPDOWN:controlTypes.ROLE_DROPDOWNBUTTON,
206 oleacc.ROLE_SYSTEM_SEPARATOR:controlTypes.ROLE_SEPARATOR,
207 oleacc.ROLE_SYSTEM_DOCUMENT:controlTypes.ROLE_DOCUMENT,
208 oleacc.ROLE_SYSTEM_ANIMATION:controlTypes.ROLE_ANIMATION,
209 oleacc.ROLE_SYSTEM_APPLICATION:controlTypes.ROLE_APPLICATION,
210 oleacc.ROLE_SYSTEM_GROUPING:controlTypes.ROLE_GROUPING,
211 oleacc.ROLE_SYSTEM_PROPERTYPAGE:controlTypes.ROLE_PROPERTYPAGE,
212 oleacc.ROLE_SYSTEM_ALERT:controlTypes.ROLE_ALERT,
213 oleacc.ROLE_SYSTEM_BORDER:controlTypes.ROLE_BORDER,
214 oleacc.ROLE_SYSTEM_BUTTONDROPDOWNGRID:controlTypes.ROLE_DROPDOWNBUTTONGRID,
215 oleacc.ROLE_SYSTEM_CARET:controlTypes.ROLE_CARET,
216 oleacc.ROLE_SYSTEM_CHARACTER:controlTypes.ROLE_CHARACTER,
217 oleacc.ROLE_SYSTEM_CHART:controlTypes.ROLE_CHART,
218 oleacc.ROLE_SYSTEM_CURSOR:controlTypes.ROLE_CURSOR,
219 oleacc.ROLE_SYSTEM_DIAGRAM:controlTypes.ROLE_DIAGRAM,
220 oleacc.ROLE_SYSTEM_DIAL:controlTypes.ROLE_DIAL,
221 oleacc.ROLE_SYSTEM_DROPLIST:controlTypes.ROLE_DROPLIST,
222 oleacc.ROLE_SYSTEM_BUTTONMENU:controlTypes.ROLE_MENUBUTTON,
223 oleacc.ROLE_SYSTEM_EQUATION:controlTypes.ROLE_EQUATION,
224 oleacc.ROLE_SYSTEM_GRIP:controlTypes.ROLE_GRIP,
225 oleacc.ROLE_SYSTEM_HOTKEYFIELD:controlTypes.ROLE_HOTKEYFIELD,
226 oleacc.ROLE_SYSTEM_INDICATOR:controlTypes.ROLE_INDICATOR,
227 oleacc.ROLE_SYSTEM_SPINBUTTON:controlTypes.ROLE_SPINBUTTON,
228 oleacc.ROLE_SYSTEM_SOUND:controlTypes.ROLE_SOUND,
229 oleacc.ROLE_SYSTEM_WHITESPACE:controlTypes.ROLE_WHITESPACE,
230 oleacc.ROLE_SYSTEM_IPADDRESS:controlTypes.ROLE_IPADDRESS,
231 oleacc.ROLE_SYSTEM_OUTLINEBUTTON:controlTypes.ROLE_TREEVIEWBUTTON,
232 oleacc.ROLE_SYSTEM_CLOCK:controlTypes.ROLE_CLOCK,
233
234 IA2_ROLE_UNKNOWN:controlTypes.ROLE_UNKNOWN,
235 IA2_ROLE_CANVAS:controlTypes.ROLE_CANVAS,
236 IA2_ROLE_CAPTION:controlTypes.ROLE_CAPTION,
237 IA2_ROLE_CHECK_MENU_ITEM:controlTypes.ROLE_CHECKMENUITEM,
238 IA2_ROLE_COLOR_CHOOSER:controlTypes.ROLE_COLORCHOOSER,
239 IA2_ROLE_DATE_EDITOR:controlTypes.ROLE_DATEEDITOR,
240 IA2_ROLE_DESKTOP_ICON:controlTypes.ROLE_DESKTOPICON,
241 IA2_ROLE_DESKTOP_PANE:controlTypes.ROLE_DESKTOPPANE,
242 IA2_ROLE_DIRECTORY_PANE:controlTypes.ROLE_DIRECTORYPANE,
243 IA2_ROLE_EDITBAR:controlTypes.ROLE_EDITBAR,
244 IA2_ROLE_EMBEDDED_OBJECT:controlTypes.ROLE_EMBEDDEDOBJECT,
245 IA2_ROLE_ENDNOTE:controlTypes.ROLE_ENDNOTE,
246 IA2_ROLE_FILE_CHOOSER:controlTypes.ROLE_FILECHOOSER,
247 IA2_ROLE_FONT_CHOOSER:controlTypes.ROLE_FONTCHOOSER,
248 IA2_ROLE_FOOTER:controlTypes.ROLE_FOOTER,
249 IA2_ROLE_FOOTNOTE:controlTypes.ROLE_FOOTNOTE,
250 IA2_ROLE_FORM:controlTypes.ROLE_FORM,
251 IA2_ROLE_FRAME:controlTypes.ROLE_FRAME,
252 IA2_ROLE_GLASS_PANE:controlTypes.ROLE_GLASSPANE,
253 IA2_ROLE_HEADER:controlTypes.ROLE_HEADER,
254 IA2_ROLE_HEADING:controlTypes.ROLE_HEADING,
255 IA2_ROLE_ICON:controlTypes.ROLE_ICON,
256 IA2_ROLE_IMAGE_MAP:controlTypes.ROLE_IMAGEMAP,
257 IA2_ROLE_INPUT_METHOD_WINDOW:controlTypes.ROLE_INPUTWINDOW,
258 IA2_ROLE_INTERNAL_FRAME:controlTypes.ROLE_INTERNALFRAME,
259 IA2_ROLE_LABEL:controlTypes.ROLE_LABEL,
260 IA2_ROLE_LAYERED_PANE:controlTypes.ROLE_LAYEREDPANE,
261 IA2_ROLE_NOTE:controlTypes.ROLE_NOTE,
262 IA2_ROLE_OPTION_PANE:controlTypes.ROLE_OPTIONPANE,
263 IA2_ROLE_PAGE:controlTypes.ROLE_PAGE,
264 IA2_ROLE_PARAGRAPH:controlTypes.ROLE_PARAGRAPH,
265 IA2_ROLE_RADIO_MENU_ITEM:controlTypes.ROLE_RADIOMENUITEM,
266 IA2_ROLE_REDUNDANT_OBJECT:controlTypes.ROLE_REDUNDANTOBJECT,
267 IA2_ROLE_ROOT_PANE:controlTypes.ROLE_ROOTPANE,
268 IA2_ROLE_RULER:controlTypes.ROLE_RULER,
269 IA2_ROLE_SCROLL_PANE:controlTypes.ROLE_SCROLLPANE,
270 IA2_ROLE_SECTION:controlTypes.ROLE_SECTION,
271 IA2_ROLE_SHAPE:controlTypes.ROLE_SHAPE,
272 IA2_ROLE_SPLIT_PANE:controlTypes.ROLE_SPLITPANE,
273 IA2_ROLE_TEAR_OFF_MENU:controlTypes.ROLE_TEAROFFMENU,
274 IA2_ROLE_TERMINAL:controlTypes.ROLE_TERMINAL,
275 IA2_ROLE_TEXT_FRAME:controlTypes.ROLE_TEXTFRAME,
276 IA2_ROLE_TOGGLE_BUTTON:controlTypes.ROLE_TOGGLEBUTTON,
277 IA2_ROLE_VIEW_PORT:controlTypes.ROLE_VIEWPORT,
278
279 "frame":controlTypes.ROLE_FRAME,
280 "iframe":controlTypes.ROLE_INTERNALFRAME,
281 "page":controlTypes.ROLE_PAGE,
282 "form":controlTypes.ROLE_FORM,
283 "div":controlTypes.ROLE_SECTION,
284 "li":controlTypes.ROLE_LISTITEM,
285 "ul":controlTypes.ROLE_LIST,
286 "tbody":controlTypes.ROLE_TABLEBODY,
287 "browser":controlTypes.ROLE_WINDOW,
288 "h1":controlTypes.ROLE_HEADING1,
289 "h2":controlTypes.ROLE_HEADING2,
290 "h3":controlTypes.ROLE_HEADING3,
291 "h4":controlTypes.ROLE_HEADING4,
292 "h5":controlTypes.ROLE_HEADING5,
293 "h6":controlTypes.ROLE_HEADING6,
294 "p":controlTypes.ROLE_PARAGRAPH,
295 "hbox":controlTypes.ROLE_BOX,
296 "embed":controlTypes.ROLE_EMBEDDEDOBJECT,
297 "object":controlTypes.ROLE_EMBEDDEDOBJECT,
298 "applet":controlTypes.ROLE_EMBEDDEDOBJECT,
299 }
300
301 IAccessibleStatesToNVDAStates={
302 oleacc.STATE_SYSTEM_TRAVERSED:controlTypes.STATE_VISITED,
303 oleacc.STATE_SYSTEM_UNAVAILABLE:controlTypes.STATE_UNAVAILABLE,
304 oleacc.STATE_SYSTEM_FOCUSED:controlTypes.STATE_FOCUSED,
305 oleacc.STATE_SYSTEM_SELECTED:controlTypes.STATE_SELECTED,
306 oleacc.STATE_SYSTEM_BUSY:controlTypes.STATE_BUSY,
307 oleacc.STATE_SYSTEM_PRESSED:controlTypes.STATE_PRESSED,
308 oleacc.STATE_SYSTEM_CHECKED:controlTypes.STATE_CHECKED,
309 oleacc.STATE_SYSTEM_MIXED:controlTypes.STATE_HALFCHECKED,
310 oleacc.STATE_SYSTEM_READONLY:controlTypes.STATE_READONLY,
311 oleacc.STATE_SYSTEM_EXPANDED:controlTypes.STATE_EXPANDED,
312 oleacc.STATE_SYSTEM_COLLAPSED:controlTypes.STATE_COLLAPSED,
313 oleacc.STATE_SYSTEM_OFFSCREEN:controlTypes.STATE_OFFSCREEN,
314 oleacc.STATE_SYSTEM_INVISIBLE:controlTypes.STATE_INVISIBLE,
315 oleacc.STATE_SYSTEM_TRAVERSED:controlTypes.STATE_VISITED,
316 oleacc.STATE_SYSTEM_LINKED:controlTypes.STATE_LINKED,
317 oleacc.STATE_SYSTEM_HASPOPUP:controlTypes.STATE_HASPOPUP,
318 oleacc.STATE_SYSTEM_PROTECTED:controlTypes.STATE_PROTECTED,
319 oleacc.STATE_SYSTEM_SELECTABLE:controlTypes.STATE_SELECTABLE,
320 oleacc.STATE_SYSTEM_FOCUSABLE:controlTypes.STATE_FOCUSABLE,
321 }
322
323 IAccessible2StatesToNVDAStates={
324 IA2_STATE_REQUIRED:controlTypes.STATE_REQUIRED,
325 IA2_STATE_DEFUNCT:controlTypes.STATE_DEFUNCT,
326
327 IA2_STATE_INVALID_ENTRY:controlTypes.STATE_INVALID_ENTRY,
328 IA2_STATE_MODAL:controlTypes.STATE_MODAL,
329 IA2_STATE_SUPPORTS_AUTOCOMPLETION:controlTypes.STATE_AUTOCOMPLETE,
330 IA2_STATE_MULTI_LINE:controlTypes.STATE_MULTILINE,
331 IA2_STATE_ICONIFIED:controlTypes.STATE_ICONIFIED,
332 IA2_STATE_EDITABLE:controlTypes.STATE_EDITABLE,
333 }
334
335
336 winEventHookIDs=[]
337
339 if not isinstance(pacc,IAccessible):
340 try:
341 pacc=pacc.QueryInterface(IAccessible)
342 except COMError:
343 raise RuntimeError("%s Not an IAccessible"%pacc)
344 if not isinstance(pacc,IAccessible2):
345 try:
346 s=pacc.QueryInterface(IServiceProvider)
347 pacc2=s.QueryService(IAccessible._iid_,IAccessible2)
348 if not pacc2:
349
350
351 raise ValueError
352 pacc=pacc2
353 except:
354 pass
355 return pacc
356
364
371
377
379 children=oleacc.AccessibleChildren(ia,startIndex,numChildren)
380 for childNum in xrange(len(children)):
381 if isinstance(children[childNum],comtypes.client.lazybind.Dispatch) or isinstance(children[childNum],comtypes.client.dynamic._Dispatch) or isinstance(children[childNum],IUnknown):
382 children[childNum]=(normalizeIAccessible(children[childNum]),0)
383 elif isinstance(children[childNum],int):
384 children[childNum]=(ia,children[childNum])
385 return children
386
388 try:
389 res=ia.accFocus
390 if isinstance(res,comtypes.client.lazybind.Dispatch) or isinstance(res,comtypes.client.dynamic._Dispatch) or isinstance(res,IUnknown):
391 new_ia=normalizeIAccessible(res)
392 new_child=0
393 elif isinstance(res,int):
394 try:
395 new_ia=ia.accChild(res)
396 except:
397 new_ia=None
398 if new_ia:
399 new_ia=normalizeIAccessible(new_ia)
400 new_child=0
401 else:
402 new_ia=ia
403 new_child=res
404 else:
405 return None
406 return (new_ia,new_child)
407 except:
408 return None
409
411 try:
412 res=ia.accHitTest(x,y)
413 except COMError:
414 return None
415 if isinstance(res,comtypes.client.lazybind.Dispatch) or isinstance(res,comtypes.client.dynamic._Dispatch) or isinstance(res,IUnknown):
416 return accHitTest(normalizeIAccessible(res),x,y),0
417 elif isinstance(res,int):
418 return ia,res
419 return None
420
422 try:
423 res=ia.accChild(child)
424 if isinstance(res,comtypes.client.lazybind.Dispatch) or isinstance(res,comtypes.client.dynamic._Dispatch) or isinstance(res,IUnknown):
425 new_ia=normalizeIAccessible(res)
426 new_child=0
427 elif isinstance(res,int):
428 new_ia=ia
429 new_child=res
430 return (new_ia,new_child)
431 except:
432 return None
433
435 try:
436 if not child:
437 res=ia.accParent
438 if isinstance(res,comtypes.client.lazybind.Dispatch) or isinstance(res,comtypes.client.dynamic._Dispatch) or isinstance(res,IUnknown):
439 new_ia=normalizeIAccessible(res)
440 new_child=0
441 else:
442 raise ValueError("no IAccessible interface")
443 else:
444 new_ia=ia
445 new_child=0
446 return (new_ia,new_child)
447 except:
448 return None
449
451 res=None
452 try:
453 res=ia.accNavigate(direction,child)
454 if isinstance(res,int):
455 new_ia=ia
456 new_child=res
457 elif isinstance(res,comtypes.client.lazybind.Dispatch) or isinstance(res,comtypes.client.dynamic._Dispatch) or isinstance(res,IUnknown):
458 new_ia=normalizeIAccessible(res)
459 new_child=0
460 else:
461 raise RuntimeError
462 return (new_ia,new_child)
463 except:
464 pass
465
466
467 winEventIDsToNVDAEventNames={
468 winUser.EVENT_SYSTEM_DESKTOPSWITCH:"desktopSwitch",
469 winUser.EVENT_SYSTEM_FOREGROUND:"gainFocus",
470 winUser.EVENT_SYSTEM_ALERT:"alert",
471 winUser.EVENT_SYSTEM_MENUSTART:"menuStart",
472 winUser.EVENT_SYSTEM_MENUEND:"menuEnd",
473 winUser.EVENT_SYSTEM_MENUPOPUPSTART:"menuStart",
474 winUser.EVENT_SYSTEM_MENUPOPUPEND:"menuEnd",
475 winUser.EVENT_SYSTEM_SCROLLINGSTART:"scrollingStart",
476
477 winUser.EVENT_SYSTEM_SWITCHEND:"switchEnd",
478 winUser.EVENT_OBJECT_FOCUS:"gainFocus",
479 winUser.EVENT_OBJECT_SHOW:"show",
480 winUser.EVENT_OBJECT_DESTROY:"destroy",
481 winUser.EVENT_OBJECT_DESCRIPTIONCHANGE:"descriptionChange",
482 winUser.EVENT_OBJECT_LOCATIONCHANGE:"locationChange",
483 winUser.EVENT_OBJECT_NAMECHANGE:"nameChange",
484
485 winUser.EVENT_OBJECT_SELECTION:"selection",
486 winUser.EVENT_OBJECT_SELECTIONADD:"selectionAdd",
487 winUser.EVENT_OBJECT_SELECTIONREMOVE:"selectionRemove",
488 winUser.EVENT_OBJECT_SELECTIONWITHIN:"selectionWithIn",
489 winUser.EVENT_OBJECT_STATECHANGE:"stateChange",
490 winUser.EVENT_OBJECT_VALUECHANGE:"valueChange",
491 IA2_EVENT_TEXT_CARET_MOVED:"caret",
492 IA2_EVENT_DOCUMENT_LOAD_COMPLETE:"documentLoadComplete",
493 IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED:"IA2AttributeChange",
494 }
495
497 """Tries to convert a win event ID to an NVDA event name, and instanciate or fetch an NVDAObject for the win event parameters.
498 @param eventID: the win event ID (type)
499 @type eventID: integer
500 @param window: the win event's window handle
501 @type window: integer
502 @param objectID: the win event's object ID
503 @type objectID: integer
504 @param childID: the win event's childID
505 @type childID: the win event's childID
506 @param useCache: C{True} to use the L{liveNVDAObjectTable} cache when retrieving an NVDAObject, C{False} if the cache should not be used.
507 @type useCache: boolean
508 @returns: the NVDA event name and the NVDAObject the event is for
509 @rtype: tuple of string and L{NVDAObjects.IAccessible.IAccessible}
510 """
511
512 if eventID == winUser.EVENT_OBJECT_CREATE:
513 return None
514
515 NVDAEventName=winEventIDsToNVDAEventNames.get(eventID,None)
516 if not NVDAEventName:
517 return None
518
519 if not window or not winUser.isWindow(window):
520 return None
521
522 if NVDAObjects.window.GhostWindowFromHungWindow and NVDAObjects.window.GhostWindowFromHungWindow(window):
523 return None
524
525 if UIAHandler.handler and UIAHandler.handler.isUIAWindow(window):
526 return None
527 obj=None
528 if useCache:
529
530 obj=liveNVDAObjectTable.get((window,objectID,childID),None)
531
532 if not obj:
533 obj=NVDAObjects.IAccessible.getNVDAObjectFromEvent(window,objectID,childID)
534
535 if not obj:
536 return None
537
538
539 if 'bosa_sdm' in obj.windowClassName:
540 SDMChild=getattr(obj,'SDMChild',None)
541 if SDMChild: obj=SDMChild
542 return (NVDAEventName,obj)
543
544 -def winEventCallback(handle,eventID,window,objectID,childID,threadID,timestamp):
545 try:
546
547 if objectID<=winUser.OBJID_ALERT:
548 return
549
550 if eventID==winUser.EVENT_OBJECT_LOCATIONCHANGE and objectID!=winUser.OBJID_CARET:
551 return
552
553 if (objectID==0) and (childID==0):
554 objectID=winUser.OBJID_CLIENT
555
556 isWindow = winUser.isWindow(window) if window else 0
557 if window==0 or (not isWindow and eventID in (winUser.EVENT_SYSTEM_SWITCHSTART,winUser.EVENT_SYSTEM_SWITCHEND,winUser.EVENT_SYSTEM_MENUEND,winUser.EVENT_SYSTEM_MENUPOPUPEND)):
558 window=winUser.getDesktopWindow()
559 elif not isWindow:
560 return
561
562 if childID<0:
563 tempWindow=window
564 while tempWindow and not winUser.getWindowStyle(tempWindow)&winUser.WS_POPUP and winUser.getClassName(tempWindow)=="MozillaWindowClass":
565 tempWindow=winUser.getAncestor(tempWindow,winUser.GA_PARENT)
566 if tempWindow and winUser.getClassName(tempWindow).startswith('Mozilla'):
567 window=tempWindow
568
569 windowClassName=winUser.getClassName(window)
570
571
572 if windowClassName.startswith('Mozilla') and eventID in (winUser.EVENT_OBJECT_SHOW,winUser.EVENT_OBJECT_HIDE,winUser.EVENT_OBJECT_REORDER) and childID<0:
573
574
575 if winUser.getClassName(window)=='MozillaDropShadowWindowClass':
576 return
577
578 if eventID==winUser.EVENT_SYSTEM_FOREGROUND and windowClassName in ("Progman","Shell_TrayWnd"):
579 return
580 if windowClassName=="MSNHiddenWindowClass":
581
582
583
584 return
585 winEventLimiter.addEvent(eventID,window,objectID,childID,threadID)
586 except:
587 log.error("winEventCallback", exc_info=True)
588
621
623 """checks to see if the focus win event is not the same as the existing focus,
624 then converts the win event to an NVDA event (instanciating an NVDA Object) then calls processFocusNVDAEvent. If all is ok it returns True.
625 @type window: integer
626 @param objectID: a win event's object ID
627 @type objectID: integer
628 @param childID: a win event's child ID
629 @type childID: integer
630 @param force: If True, the shouldAllowIAccessibleFocusEvent property of the object is ignored.
631 @type force: boolean
632 @returns: True if the focus is valid and was handled, False otherwise.
633 @rtype: boolean
634 """
635 windowClassName=winUser.getClassName(window)
636
637
638
639 if childID==0 and not windowClassName.startswith('bosa_sdm') and winUser.getClassName(winUser.getAncestor(window,winUser.GA_PARENT)).startswith('bosa_sdm'):
640 return False
641 rootWindow=winUser.getAncestor(window,winUser.GA_ROOT)
642
643 if not winUser.isDescendantWindow(winUser.getForegroundWindow(),window) and not (winUser.getWindowStyle(window) & winUser.WS_POPUP or winUser.getWindowStyle(rootWindow)&winUser.WS_POPUP) and winUser.getPreviousWindow(rootWindow)!=0:
644
645 return False
646
647 appModuleHandler.update(winUser.getWindowThreadProcessID(window)[0])
648
649 if JABHandler.isRunning and JABHandler.isJavaWindow(window):
650 JABHandler.event_enterJavaWindow(window)
651 return True
652
653 NVDAEvent=winEventToNVDAEvent(winUser.EVENT_OBJECT_FOCUS,window,objectID,childID,useCache=False)
654 if not NVDAEvent:
655 return False
656 eventName,obj=NVDAEvent
657 if (childID==0 and obj.IAccessibleRole==oleacc.ROLE_SYSTEM_LIST) or (objectID==winUser.OBJID_CLIENT and "SysListView32" in obj.windowClassName):
658
659 try:
660 realChildID=obj.IAccessibleObject.accFocus
661 except:
662 realChildID=None
663 if isinstance(realChildID,int) and realChildID>0 and realChildID!=childID:
664 realObj=NVDAObjects.IAccessible.IAccessible(IAccessibleObject=obj.IAccessibleObject,IAccessibleChildID=realChildID,event_windowHandle=window,event_objectID=objectID,event_childID=realChildID)
665 if realObj:
666 obj=realObj
667 return processFocusNVDAEvent(obj,force=force)
668
687
689
693
695 return _("Secure Desktop")
696
699
712
715
752
760
762 """Process a destroy win event.
763 This removes the object associated with the event parameters from L{liveNVDAObjectTable} if such an object exists.
764 """
765 try:
766 del liveNVDAObjectTable[(window,objectID,childID)]
767 except KeyError:
768 pass
769
787
789 """Process a fake focus win event.
790 @postcondition: The focus will be found and an event generated for it if appropriate.
791 """
792
793
794 import wx
795 wx.CallLater(50, _fakeFocus, api.getFocusObject())
796
805
806
807 cWinEventCallback=WINFUNCTYPE(None,c_int,c_int,c_int,c_int,c_int,c_int,c_int)(winEventCallback)
808
809 accPropServices=None
810
823
866
870
872 IAccIdentityObject=pacc.QueryInterface(IAccIdentity)
873 stringPtr,stringSize=IAccIdentityObject.getIdentityString(childID)
874 try:
875 if accPropServices:
876 hwnd,objectID,childID=accPropServices.DecomposeHwndIdentityString(stringPtr,stringSize)
877 return dict(windowHandle=hwnd,objectID=c_int(objectID).value,childID=childID)
878 stringPtr=cast(stringPtr,POINTER(c_char*stringSize))
879 fields=struct.unpack('IIiI',stringPtr.contents.raw)
880 d={}
881 d['childID']=fields[3]
882 if fields[0]&2:
883 d['menuHandle']=fields[2]
884 else:
885 d['objectID']=fields[2]
886 d['windowHandle']=fields[1]
887 return d
888 finally:
889 windll.ole32.CoTaskMemFree(stringPtr)
890
891
905
907 if not isinstance(obj,IAccessibleText):
908 try:
909 textObject=obj.QueryInterface(IAccessibleText)
910 except:
911 textObject=None
912 else:
913 textObject=obj
914 if not isinstance(obj,IAccessible):
915 try:
916 accObject=obj.QueryInterface(IAccessible)
917 except:
918 return ""
919 else:
920 accObject=obj
921 try:
922 text=textObject.text(startOffset,endOffset)
923 except:
924 text=None
925 if not text or text.isspace():
926 try:
927 name=accObject.accName(0)
928 except:
929 name=None
930 try:
931 value=accObject.accValue(0)
932 except:
933 value=None
934 try:
935 description=accObject.accDescription(0)
936 except:
937 description=None
938 return " ".join([x for x in [name,value,description] if x and not x.isspace()])
939 try:
940 hypertextObject=accObject.QueryInterface(IAccessibleHypertext)
941 except:
942 return text
943 textList=[]
944 for i in range(len(text)):
945 t=text[i]
946 if ord(t)==0xFFFC:
947 try:
948 childTextObject=hypertextObject.hyperlink(hypertextObject.hyperlinkIndex(i+startOffset)).QueryInterface(IAccessible)
949 t=" %s "%getRecursiveTextFromIAccessibleTextObject(childTextObject)
950 except:
951 pass
952 textList.append(t)
953 return "".join(textList).replace(' ',' ')
954
956 """Split an IAccessible2 attributes string into a dict of attribute keys and values.
957 An invalid attributes string does not cause an error, but strange results may be returned.
958 Subattributes are handled. Subattribute keys and values are placed into a dict which becomes the value of the attribute.
959 @param attribsString: The IAccessible2 attributes string to convert.
960 @type attribsString: str
961 @return: A dict of the attribute keys and values, where values are strings or dicts.
962 @rtype: {str: str or {str: str}}
963 """
964 attribsDict = {}
965 tmp = ""
966 key = ""
967 subkey = ""
968 subattr = {}
969 inEscape = False
970 for char in attribsString:
971 if inEscape:
972 tmp += char
973 inEscape = False
974 elif char == "\\":
975 inEscape = True
976 elif char == ":":
977
978 key = tmp
979 tmp = ""
980 elif char == "=":
981
982
983 subkey = tmp
984 tmp = ""
985 elif char == ",":
986
987
988 if subkey:
989 subattr[subkey] = tmp
990 subkey = ""
991 tmp = ""
992 elif char == ";":
993
994 if subkey:
995
996 subattr[subkey] = tmp
997 subkey = ""
998 if subattr:
999
1000
1001 attribsDict[key] = subattr
1002 subattr = {}
1003 elif key:
1004
1005 attribsDict[key] = tmp
1006 key = ""
1007 tmp = ""
1008 else:
1009 tmp += char
1010
1011 if subkey:
1012
1013 subattr[subkey] = tmp
1014 if subattr:
1015
1016
1017 attribsDict[key] = subattr
1018 elif key:
1019
1020 attribsDict[key] = tmp
1021 return attribsDict
1022
1024 """Looks at the location of the first function in the IAccessible object's vtable (IUnknown::AddRef) to see if it was implemented in oleacc.dll (its local) or ole32.dll (its marshalled)."""
1025 if not isinstance(IAccessibleObject,IAccessible):
1026 raise TypeError("object should be of type IAccessible, not %s"%IAccessibleObject)
1027 buf=create_unicode_buffer(1024)
1028 from comtypes import _compointer_base
1029 addr=POINTER(c_void_p).from_address(super(_compointer_base,IAccessibleObject).value).contents.value
1030 handle=HANDLE()
1031 windll.kernel32.GetModuleHandleExW(6,addr,byref(handle))
1032 windll.kernel32.GetModuleFileNameW(handle,buf,1024)
1033 return not buf.value.lower().endswith('oleacc.dll')
1034