forked from nvaccess/nvda
/
mscandui.py
executable file
·227 lines (193 loc) · 7.53 KB
/
mscandui.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
import time
import oleacc
import queueHandler
import eventHandler
import controlTypes
import characterProcessing
import config
import api
import ui
import speech
import winUser
from . import IAccessible
from NVDAObjects.behaviors import CandidateItem as CandidateItemBehavior
def reportSelectedCandidate(candidateObject,allowDuplicate=False,newList=False):
if not eventHandler.isPendingEvents("gainFocus") and (allowDuplicate or candidateObject!=api.getFocusObject()):
if not isinstance(api.getFocusObject(),BaseCandidateItem):
oldCandidateItemsText=None
candidateObject.container=api.getFocusObject()
eventHandler.queueEvent("foreground",candidateObject)
else:
oldCandidateItemsText=api.getFocusObject().visibleCandidateItemsText
candidateObject.container=api.getFocusObject().container
if config.conf["inputComposition"]["autoReportAllCandidates"] and (newList or candidateObject.visibleCandidateItemsText!=oldCandidateItemsText):
queueHandler.queueFunction(queueHandler.eventQueue,ui.message,candidateObject.visibleCandidateItemsText)
eventHandler.queueEvent("gainFocus",candidateObject)
class BaseCandidateItem(CandidateItemBehavior,IAccessible):
role=controlTypes.ROLE_LISTITEM
keyboardShortcut=""
def _get_candidateNumber(self):
number=super(BaseCandidateItem,self).keyboardShortcut
try:
number=int(number)
except (ValueError,TypeError):
pass
return number
def _get_parent(self):
parent=super(BaseCandidateItem,self).parent
# Translators: A label for a 'candidate' list which contains symbols the user can choose from when typing east-asian characters into a document.
parent.name=_("Candidate")
parent.description=None
return parent
def _get_name(self):
try:
number=int(self.candidateNumber)
except (TypeError,ValueError):
return super(BaseCandidateItem,self).name
candidate=super(BaseCandidateItem,self).name
return self.getFormattedCandidateName(number,candidate)
def _get_description(self):
candidate=super(BaseCandidateItem,self).name
return self.getFormattedCandidateDescription(candidate)
def _get_basicText(self):
return super(BaseCandidateItem,self).name
class MSCandUI_candidateListItem(BaseCandidateItem):
def _get_states(self):
states=super(MSCandUI_candidateListItem,self).states
states.add(controlTypes.STATE_SELECTABLE)
return states
def event_stateChange(self):
if controlTypes.STATE_SELECTED in self.states:
reportSelectedCandidate(self)
class MSCandUI21_candidateMenuItem(BaseCandidateItem):
def _get_previous(self):
item=super(MSCandUI21_candidateMenuItem,self).previous
if not item or controlTypes.STATE_INVISIBLE in item.states: return
return MSCandUI21_candidateMenuItem(IAccessibleObject=item.IAccessibleObject,IAccessibleChildID=item.IAccessibleChildID)
def _get_next(self):
item=super(MSCandUI21_candidateMenuItem,self).next
if not item or controlTypes.STATE_INVISIBLE in item.states: return
return MSCandUI21_candidateMenuItem(IAccessibleObject=item.IAccessibleObject,IAccessibleChildID=item.IAccessibleChildID)
def doAction(self,index=None):
if not index:
l=self.location
if l:
x=l[0]
y=l[1]
oldX,oldY=winUser.getCursorPos()
winUser.setCursorPos(x,y)
winUser.mouse_event(winUser.MOUSEEVENTF_LEFTDOWN,0,0,None,None)
time.sleep(0.2)
winUser.mouse_event(winUser.MOUSEEVENTF_LEFTUP,0,0,None,None)
winUser.setCursorPos(oldX,oldY)
return
raise NotImplementedError
def script_nextItem(self,gesture):
item=self.next
if not item or not isinstance(item.candidateNumber,int): return
reportSelectedCandidate(item)
def script_previousItem(self,gesture):
item=self.previous
if not item or not isinstance(item.candidateNumber,int): return
reportSelectedCandidate(item)
def script_changePage(self,gesture):
try:
del self.__dict__['visibleCandidateItemsText']
except KeyError:
pass
gesture.send()
api.processPendingEvents()
oldItem=item=self
while item and isinstance(item.candidateNumber,int):
oldItem=item
item=item.previous
if oldItem and isinstance(oldItem.candidateNumber,int) and oldItem.name:
reportSelectedCandidate(oldItem,allowDuplicate=True,newList=True)
def script_activate(self,gesture):
self.doAction()
api.processPendingEvents()
oldItem=item=self
while item and isinstance(item.candidateNumber,int):
oldItem=item
item=item.previous
if oldItem and isinstance(oldItem.candidateNumber,int) and oldItem.name:
reportSelectedCandidate(oldItem,allowDuplicate=True,newList=True)
__gestures={
"kb:downArrow":"nextItem",
"kb:upArrow":"previousItem",
"kb:pageDown":"changePage",
"kb:pageUp":"changePage",
"kb:leftArrow":"changePage",
"kb:rightArrow":"changePage",
"kb:space":"activate",
"kb:enter":"activate",
}
class MSCandUI21(IAccessible):
def _get_isPresentableFocusAncestor(self):
return False
def event_show(self):
candidateList=self.simpleFirstChild
if not candidateList: return
role=candidateList.role
if role==controlTypes.ROLE_LIST:
item=candidateList.firstChild
while item and controlTypes.STATE_SELECTED not in item.states:
item=item.next
if item:
reportSelectedCandidate(item)
return
elif config.conf["reviewCursor"]["followFocus"]:
api.setNavigatorObject(candidateList, isFocus=True)
elif role==controlTypes.ROLE_MENUBUTTON:
item=candidateList.firstChild.next.next
item=MSCandUI21_candidateMenuItem(IAccessibleObject=item.IAccessibleObject,IAccessibleChildID=item.IAccessibleChildID)
if item and isinstance(item.candidateNumber,int) and item.name:
reportSelectedCandidate(item)
###IME 2002
class MSCandUIWindow_candidateListItem(MSCandUI_candidateListItem):
def _get_isValidCandidate(self):
if self.IAccessibleRole!=oleacc.ROLE_SYSTEM_LISTITEM:
return False
name=super(BaseCandidateItem,self).name
if not name:
return False
return True
def _get_candidateNumber(self):
index=self.IAccessibleChildID-2
if index>0:
return index
def _get_next(self):
childID=self.IAccessibleChildID+1
item=self.__class__(IAccessibleObject=self.IAccessibleObject,IAccessibleChildID=childID)
if item.isValidCandidate:
return item
def _get_previous(self):
childID=self.IAccessibleChildID-1
if childID>=3:
item=self.__class__(IAccessibleObject=self.IAccessibleObject,IAccessibleChildID=childID)
if item.isValidCandidate:
return item
class MSCandUIWindow(IAccessible):
# Translators: A label for a 'candidate' list which contains symbols the user can choose from when typing east-asian characters into a document.
name=_("Candidate")
role=controlTypes.ROLE_LIST
def _get_states(self):
states=super(MSCandUIWindow,self).states
states.discard(controlTypes.STATE_UNAVAILABLE)
return states
def event_show(self):
item=MSCandUIWindow_candidateListItem(IAccessibleObject=self.IAccessibleObject,IAccessibleChildID=3)
reportSelectedCandidate(item)
def findExtraOverlayClasses(obj,clsList):
windowClassName=obj.windowClassName
role=obj.IAccessibleRole
if windowClassName=="MSCandUIWindow_Candidate":
if role==oleacc.ROLE_SYSTEM_CLIENT:
clsList.append(MSCandUIWindow)
elif role==oleacc.ROLE_SYSTEM_LISTITEM:
clsList.append(MSCandUIWindow_candidateListItem)
elif windowClassName in ("mscandui21.candidate","mscandui40.candidate"):
if role==oleacc.ROLE_SYSTEM_LISTITEM:
clsList.append(MSCandUI_candidateListItem)
elif role==oleacc.ROLE_SYSTEM_CLIENT:
clsList.append(MSCandUI21)