Skip to content

Commit

Permalink
Support for the Modern IME candidate list UI (used in Windows 8 and a…
Browse files Browse the repository at this point in the history
…bove for such input methods as Chinese Simplified Microsoft Pinyin).

Fixes nvaccess#4145
Fixes nvaccess#4011
  • Loading branch information
michaelDCurran authored and jiangtiandao committed Aug 11, 2018
1 parent d58e1cd commit 999850f
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
6 changes: 5 additions & 1 deletion source/IAccessibleHandler.py
Expand Up @@ -569,6 +569,9 @@ def winEventCallback(handle,eventID,window,objectID,childID,threadID,timestamp):
window=tempWindow

windowClassName=winUser.getClassName(window)
# Modern IME candidate list windows fire menu events which confuse us and can't be used properly inconjunction with input composition support
if windowClassName=="Microsoft.IME.UIManager.CandidateWindow.Host" and eventID in MENU_EVENTIDS:
return
#At the moment we can't handle show, hide or reorder events on Mozilla Firefox Location bar,as there are just too many of them
#Ignore show, hide and reorder on MozillaDropShadowWindowClass windows.
if windowClassName.startswith('Mozilla') and eventID in (winUser.EVENT_OBJECT_SHOW,winUser.EVENT_OBJECT_HIDE,winUser.EVENT_OBJECT_REORDER) and childID<0:
Expand Down Expand Up @@ -781,7 +784,8 @@ def processDestroyWinEvent(window,objectID,childID):
# so can't use generic focus correction. (#2695)
focus=api.getFocusObject()
from NVDAObjects.IAccessible.mscandui import BaseCandidateItem
if objectID==0 and childID==0 and isinstance(focus,BaseCandidateItem) and window==focus.windowHandle and not eventHandler.isPendingEvents("gainFocus"):
windowClassName=winUser.getClassName(window)
if childID==0 and isinstance(focus,BaseCandidateItem) and window==focus.windowHandle and not eventHandler.isPendingEvents("gainFocus"):
obj=focus.container
if obj:
eventHandler.queueEvent("gainFocus",obj)
Expand Down
2 changes: 1 addition & 1 deletion source/NVDAObjects/IAccessible/__init__.py
Expand Up @@ -436,7 +436,7 @@ def findOverlayClasses(self,clsList):
parentWindow=winUser.getAncestor(self.windowHandle,winUser.GA_PARENT)
if parentWindow and winUser.getClassName(parentWindow)=="Frame Notification Bar":
clsList.append(IENotificationBar)
if windowClassName.lower().startswith('mscandui'):
if windowClassName.lower().startswith('mscandui') or windowClassName in ("Microsoft.IME.CandidateWindow.View","Microsoft.IME.UIManager.CandidateWindow.Host"):
import mscandui
mscandui.findExtraOverlayClasses(self,clsList)
elif windowClassName=="GeckoPluginWindow" and self.event_objectID==0 and self.IAccessibleChildID==0:
Expand Down
34 changes: 33 additions & 1 deletion source/NVDAObjects/IAccessible/mscandui.py
Expand Up @@ -212,10 +212,42 @@ def event_show(self):
item=MSCandUIWindow_candidateListItem(IAccessibleObject=self.IAccessibleObject,IAccessibleChildID=3)
reportSelectedCandidate(item)

class ModernCandidateUICandidateItem(BaseCandidateItem):

def _get_candidateCharacters(self):
return super(BaseCandidateItem,self).name

_candidateNumber=""

def _get_candidateNumber(self):
# The following property call sets candidateNumber
self.visibleCandidateItemsText
return self._candidateNumber

def _get_visibleCandidateItemsText(self):
textList=[]
index=1
for child in super(ModernCandidateUICandidateItem,self).parent.children:
if not isinstance(child,ModernCandidateUICandidateItem) or controlTypes.STATE_SELECTABLE not in child.states: continue
child.candidateNumber=index
textList.append(child.name)
if child.candidateCharacters==self.candidateCharacters:
self._candidateNumber=index
index+=1
if len(textList)<=1: return None
self.visibleCandidateItemsText=(u", ".join(textList))+u", "
return self.visibleCandidateItemsText

def event_stateChange(self):
if controlTypes.STATE_SELECTED in self.states:
reportSelectedCandidate(self)

def findExtraOverlayClasses(obj,clsList):
windowClassName=obj.windowClassName
role=obj.IAccessibleRole
if windowClassName=="MSCandUIWindow_Candidate":
if windowClassName=="Microsoft.IME.CandidateWindow.View" and obj.role==controlTypes.ROLE_BUTTON:
clsList.append(ModernCandidateUICandidateItem)
elif windowClassName=="MSCandUIWindow_Candidate":
if role==oleacc.ROLE_SYSTEM_CLIENT:
clsList.append(MSCandUIWindow)
elif role==oleacc.ROLE_SYSTEM_LISTITEM:
Expand Down
1 change: 1 addition & 0 deletions source/_UIAHandler.py
Expand Up @@ -44,6 +44,7 @@
]

badUIAWindowClassNames=[
"Microsoft.IME.CandidateWindow.View",
"SysTreeView32",
"WuDuiListView",
"ComboBox",
Expand Down

0 comments on commit 999850f

Please sign in to comment.