Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use auto select detection for UIA when listening for TextChanged and TextSelectionChanged events #9660

Merged
merged 12 commits into from
Sep 10, 2019
Merged
17 changes: 14 additions & 3 deletions source/NVDAObjects/UIA/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,15 @@
from UIAUtils import shouldUseUIAConsole
from NVDAObjects.window import Window
from NVDAObjects import NVDAObjectTextInfo, InvalidNVDAObject
from NVDAObjects.behaviors import ProgressBar, EditableTextWithoutAutoSelectDetection, Dialog, Notification, EditableTextWithSuggestions, ToolTip
from NVDAObjects.behaviors import (
ProgressBar,
EditableTextWithoutAutoSelectDetection,
EditableTextWithAutoSelectDetection,
Dialog,
Notification,
EditableTextWithSuggestions,
ToolTip
)
import braille
import locationHelper
import ui
Expand Down Expand Up @@ -878,7 +886,10 @@ def findOverlayClasses(self,clsList):
winConsoleUIA.findExtraOverlayClasses(self, clsList)
# Add editableText support if UIA supports a text pattern
if self.TextInfo==UIATextInfo:
clsList.append(EditableTextWithoutAutoSelectDetection)
if UIAHandler.autoSelectDetectionAvailable:
clsList.append(EditableTextWithAutoSelectDetection)
else:
clsList.append(EditableTextWithoutAutoSelectDetection)

clsList.append(UIA)

Expand Down Expand Up @@ -1462,7 +1473,7 @@ def event_UIA_elementSelected(self):
self.event_stateChange()

def event_valueChange(self):
if isinstance(self, EditableTextWithoutAutoSelectDetection):
if issubclass(self.TextInfo, UIATextInfo):
return
return super(UIA, self).event_valueChange()

Expand Down
11 changes: 7 additions & 4 deletions source/NVDAObjects/window/winword.py
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,13 @@ def script_changeLineSpacing(self,gesture):
# Translators: a message when switching to 1.5 line spaceing in Microsoft word
ui.message(_("1.5 line spacing"))

def initOverlayClass(self):
if isinstance(self, EditableTextWithoutAutoSelectDetection):
self.bindGesture("kb:alt+shift+home", "caret_changeSelection")
self.bindGesture("kb:alt+shift+end", "caret_changeSelection")
self.bindGesture("kb:alt+shift+pageUp", "caret_changeSelection",)
self.bindGesture("kb:alt+shift+pageDown", "caret_changeSelection",)

__gestures = {
"kb:control+[":"increaseDecreaseFontSize",
"kb:control+]":"increaseDecreaseFontSize",
Expand Down Expand Up @@ -1459,10 +1466,6 @@ def script_changeLineSpacing(self,gesture):
"kb:control+5":"changeLineSpacing",
"kb:tab": "tab",
"kb:shift+tab": "tab",
"kb:alt+shift+home":"caret_changeSelection",
"kb:alt+shift+end":"caret_changeSelection",
"kb:alt+shift+pageUp":"caret_changeSelection",
"kb:alt+shift+pageDown":"caret_changeSelection",
"kb:control+pageUp": "caret_moveByLine",
"kb:control+pageDown": "caret_moveByLine",
}
Expand Down
5 changes: 0 additions & 5 deletions source/UIABrowseMode.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,3 @@ def __contains__(self,obj):
except LookupError:
return False
return True

def event_caret(self,obj,nextHandler):
pass


40 changes: 27 additions & 13 deletions source/_UIAHandler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#_UIAHandler.py
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2011-2019 NV Access Limited, Joseph Lee, Babbage B.V.
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
# _UIAHandler.py
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2011-2019 NV Access Limited, Joseph Lee, Babbage B.V., Leonard de Ruijter
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

from ctypes import *
from ctypes.wintypes import *
Expand All @@ -25,6 +25,7 @@
import eventHandler
from logHandler import log
import UIAUtils
from comtypes.gen import UIAutomationClient as UIA
from comtypes.gen.UIAutomationClient import *

#Some newer UIA constants that could be missing
Expand Down Expand Up @@ -144,16 +145,19 @@
UIA_SelectionItem_ElementAddedToSelectionEventId:"stateChange",
UIA_SelectionItem_ElementRemovedFromSelectionEventId:"stateChange",
#UIA_MenuModeEndEventId:"menuModeEnd",
#UIA_Text_TextSelectionChangedEventId:"caret",
UIA_ToolTipOpenedEventId:"UIA_toolTipOpened",
#UIA_AsyncContentLoadedEventId:"documentLoadComplete",
#UIA_ToolTipClosedEventId:"hide",
UIA_Window_WindowOpenedEventId:"UIA_window_windowOpen",
UIA_SystemAlertEventId:"UIA_systemAlert",
}

autoSelectDetectionAvailable = False
if winVersion.isWin10():
UIAEventIdsToNVDAEventNames[UIA_Text_TextChangedEventId] = "textChange"
UIAEventIdsToNVDAEventNames.update({
UIA.UIA_Text_TextChangedEventId: "textChange",
UIA.UIA_Text_TextSelectionChangedEventId: "caret", })
autoSelectDetectionAvailable = True

ignoreWinEventsMap = {
UIA_AutomationPropertyChangedEventId: list(UIAPropertyIdsToNVDAEventNames.keys()),
Expand Down Expand Up @@ -273,20 +277,25 @@ def IUIAutomationEventHandler_HandleAutomationEvent(self,sender,eventID):
NVDAEventName=UIAEventIdsToNVDAEventNames.get(eventID,None)
if not NVDAEventName:
return
if not self.isNativeUIAElement(sender):
focus = api.getFocusObject()
import NVDAObjects.UIA
if (
isinstance(focus, NVDAObjects.UIA.UIA)
and self.clientObject.compareElements(focus.UIAElement, sender)
):
pass
elif not self.isNativeUIAElement(sender):
return
window=self.getNearestWindowHandle(sender)
if window and not eventHandler.shouldAcceptEvent(NVDAEventName,windowHandle=window):
return
import NVDAObjects.UIA
obj=NVDAObjects.UIA.UIA(UIAElement=sender)
if (
not obj
or (NVDAEventName=="gainFocus" and not obj.shouldAllowUIAFocusEvent)
or (NVDAEventName=="liveRegionChange" and not obj._shouldAllowUIALiveRegionChangeEvent)
):
return
focus=api.getFocusObject()
if obj==focus:
obj=focus
eventHandler.queueEvent(NVDAEventName,obj)
Expand Down Expand Up @@ -328,16 +337,21 @@ def IUIAutomationPropertyChangedEventHandler_HandlePropertyChangedEvent(self,sen
NVDAEventName=UIAPropertyIdsToNVDAEventNames.get(propertyId,None)
if not NVDAEventName:
return
if not self.isNativeUIAElement(sender):
focus = api.getFocusObject()
import NVDAObjects.UIA
if (
isinstance(focus, NVDAObjects.UIA.UIA)
and self.clientObject.compareElements(focus.UIAElement, sender)
):
pass
elif not self.isNativeUIAElement(sender):
return
window=self.getNearestWindowHandle(sender)
if window and not eventHandler.shouldAcceptEvent(NVDAEventName,windowHandle=window):
return
import NVDAObjects.UIA
obj=NVDAObjects.UIA.UIA(UIAElement=sender)
if not obj:
return
focus=api.getFocusObject()
if obj==focus:
obj=focus
eventHandler.queueEvent(NVDAEventName,obj)
Expand Down