; Copyright 2014-2023 by Freedom Scientific BLV Group, LLC
;Freedom Scientific Script file For Google Chrome
Include "HJConst.jsh"
Include "HJGlobal.jsh"
Include "HJHelp.jsh"
Include "common.jsm"
Include "Chrome.jsh"
Include "Chrome.jsm"
Include "MSAAConst.jsh"
Include "UIA.jsh"
Include "ie.jsm"
Import "UIA.jsd"
Use "IA2Browser.jsb"
Const
Edge="msedge.exe",
ShiftKey = 0x800000,
CTRLKey = 0x10000,
key_LeftArrow = 0x4b,
key_RightArrow = 0x4d,
key_Home = 0x47,
key_End = 0x4f
Globals
IntArray restrictedIDs,
Int gChromeVersion,
Int gChromeMinorVersion,
Int gChromeUpdateVersion,
String appName,
Int lastFocusType,
Int lastKeyWasSelecting,
Int lastKeyWasScripted,
String chromeAutoCompleteAddress
;gbIsBrowserUIDialog accesses the global from IA2Browser:
Globals Int gbIsBrowserUIDialog
Const
scTabSearchTopChromeIdentifyer = "chrome://tab-search.top-chrome/" ;address of the page which gains focus when Control+Shift + A is pressed
Globals
Int gsDocID, ;copied from IA2Browser.jss, used in SayNewDocumentTab
Int gsPrevDocID ;copied from IA2Browser.jss, used in SayNewDocumentTab
;For scheduling announcement of descriptionChangedEvent While typing in the Tab Search edit field:
Const
DescriptionChangedEventAnnouncementWaitTime = 3 ;tenths of a second
Globals
Int ScheduleIDDescriptionChangedEventAnnouncement,
String gsDescriptionChangedEventText
;For scheduling SelectionChangedEvent when typing On the address bar,
;and For detecting when To announce a value change when tabbing:
Const
SayAutoCompleteAddressAfterPauseWaitTime = 6 ;tenths of a second
Globals
Int ScheduleIDSayAutoCompleteAddressAfterPause
;For managing announcement of New tab page in BrowserTabChangedEvent:
Globals
Int gChromeBrowserTabID,
Handle gChromeBrowserTabHWnd
;For detecting radio buttons in the chrome area of Chrome which generate no event when toggled:
Globals
Int ScheduleIDUpdateAndSayNewStateOfRadioButton
Void Function autoStartEvent()
GetFixedProductVersion(GetAppFilePath (), gChromeVersion, gChromeMinorVersion, gChromeUpdateVersion, 0)
appName = GetAppFileName ()
LoadNonJCFOptions ()
lastFocusType = wt_UNKNOWN
lastKeyWasSelecting = False
EndFunction
Int Function ShouldNotifyIfContextHelp()
Return Off
EndFunction
Int Function BrailleCallbackObjectIdentify()
If IsTouchCursor() Return BrailleCallbackObjectIdentify() EndIf
If GetObjectSubtypeCode() == wt_unknown
&& GetObjectRole() == Role_System_PageTabList
Return wt_tabControl
EndIf
Return BrailleCallbackObjectIdentify()
EndFunction
Int Function BrailleAddObjectDescription(Int nSubtypeCode)
If nSubtypeCode == wt_button
&& StringLower(GetObjectname()) == StringLower(GetObjectDescription())
;Avoid information duplication, add nothing.
Return True
ElIf nSubtypeCode == wt_TabControl
&& GetObjectRole() == Role_System_PageTabList
;Description duplicates information from name, add nothing.
Return True
EndIf
Return BrailleAddObjectDescription(nSubtypeCode)
EndFunction
Int Function BrailleAddObjectContextHelp(Int nSubtypeCode)
Return True ; added no String, corrects later versions of Google
EndFunction
Int Function IsBrowserContentWindow(Handle hwnd)
Return GetWindowClass(hwnd) == wc_ChromeWindowClass
EndFunction
Int Function IsBrowserUIDialog()
Return !UserBufferIsActive()
&& GetWindowClass(getFocus()) == wc_Chrome_WidgetWin_1
&& FindAncestorOfType(wt_dialog) != -1
EndFunction
Int Function ShouldUseDoSayObjectFromLevel( Handle focusWindow, Handle prevWindow )
Return !gbIsBrowserUIDialog
&& !IsOnAddressBarEdit()
EndFunction
String Function GetDocumentNameFromRealWindow()
Var
String name
;No dom, so must get document name via RealWindowName (MSAA gets it)
name = GetWindowName(GetRealWindow(GetFocus()))
If StringContains(name, scTrimName_ChromeTitleBar)
Return StringChopRight(name, StringLength(scTrimName_ChromeTitleBar))
EndIf
Return cscNull
EndFunction
String Function GetBrowserName(optional Int includeMaker)
If includeMaker
Return msgGoogleChromeAppName
else
Return msgChromeAppName
EndIf
EndFunction
Script ScreenSensitiveHelp ()
If IsSameScript () Then
AppFileTopic(topic_Chrome)
Return
EndIf
PerformScript ScreenSensitiveHelp()
EndScript
Int Function ShouldHandleParagraphNavigation()
Var Int isVirtualCursorTabSpecific = GetJCFOption(OPT_VirtualCursorIsTabSpecific )
Var Int vCursorSetting
If isVirtualCursorTabSpecific Then
vCursorSetting = GetVirtualCursorSettingForTab(GetTabID())
else
vCursorSetting = GetJCFOption (OPT_VIRTUAL_PC_CURSOR)
EndIf
If (vCursorSetting == 0) Then
Return True
EndIf
If IsFormsModeActive() || IsInsideARIAApplication () Then
Return True
EndIf
Return False
EndFunction
Void Function CaretMovedEvent( Int movementUnit, optional Int source)
;In Chrome multiline edits, movementUnit is reported as 0.
If !movementUnit
&& lastKeyWasScripted
Var String scriptName = GetScriptAssignedTo(GetCurrentScriptKeyName())
If scriptName == "ControlUpArrow"
Return CaretMovedEvent(Unit_Paragraph_Prior, source)
ElIf scriptName == "ControlDownArrow"
Return CaretMovedEvent(Unit_Paragraph_Next, source)
EndIf
EndIf
CaretMovedEvent( movementUnit, source)
EndFunction
Void Function UnitMoveControlNav (Int UnitMovement)
If ShouldHandleParagraphNavigation() Then
Var Int objType=GetObjectSubtypeCode ()
If SupportsEditCallbacks ()
&& objType != wt_multiline_edit
;NextParagraph and PriorParagraph do Not properly navigate in Chrome multiline edits.
If UnitMovement == UnitMove_Next Then
NextParagraph()
ElIf UnitMovement == UnitMove_Prior Then
PriorParagraph()
EndIf
Return
EndIf
If UnitMovement == UnitMove_Next Then
TypeKey(cksControlDownArrow)
ElIf UnitMovement == UnitMove_Prior Then
TypeKey(cksControlUpArrow)
EndIf
pause()
If objType == WT_TABCONTROL Then
sayWord()
EndIf
Return
EndIf
Return UnitMoveControlNav (UnitMovement)
EndFunction
Int Function IsOnAddressBarEdit()
If GetWindowClass(GetFocus()) != wc_Chrome_WidgetWin_1 Return False EndIf
Return lastFocusType == wt_edit
EndFunction
Void Function SayLineFromCaretMovedEvent(Int movementUnit)
If IsOnAddressBarEdit()
;The value change and selection change events will speak the address bar change:
Return
EndIf
SayLineFromCaretMovedEvent(movementUnit)
EndFunction
Int Function ContractedBrailleInputAllowedNow ()
;event Function designed To Return False On controls that would otherwise support contracted input.
;Example would be an application whose edit controls may also support quick navigation keys, once said keys are On Return False from this Function To turn them Off.
;This Function is only called when the item with focus supports contracted input To begin with.
If IsOnAddressBarEdit() Then
Return False
EndIf
Return ContractedBrailleInputAllowedNow () ; Fall back To default.
EndFunction
Void Function ActiveItemChangedEvent (Handle curHwnd, Int curObjectId, Int curChildId,
Handle prevHwnd, Int prevObjectId, Int prevChildId)
If IsBrowserContentWindow(curHwnd) && GetObjectSubtypeCode()==wt_comboBox Then
say(GetObjectValue(), OT_LINE)
Return
EndIf
ActiveItemChangedEvent (curHwnd, curObjectId, curChildId, prevHwnd, prevObjectId, prevChildId)
EndFunction
Void Function SayAutoCompleteAddressAfterPause ()
ScheduleIDSayAutoCompleteAddressAfterPause = 0
Say (chromeAutoCompleteAddress, OT_LINE, True)
SayMessage (ot_select, cmsg215_l)
chromeAutoCompleteAddress = cscNull
EndFunction
Void Function SelectionChangedEvent( String text, Int wasTextSelected, optional Int source )
If ScheduleIDSayAutoCompleteAddressAfterPause
UnscheduleFunction(ScheduleIDSayAutoCompleteAddressAfterPause)
EndIf
If IsOnAddressBarEdit()
&& !lastKeyWasSelecting
If !StringLength(getSelectedText())
;This happens when successive presses of Control+T For a New tab occurs.
;We get an irroneous selection change of text "address and".
Return
EndIf
If wasTextSelected
;When the first letter is entered into the search edit field,
;the SecondaryFocusChangedEvent will probably, but Not reliably, speak when the first letter is entered,
;and at this point announcing the selection here would be spammy.
;however, continuing To type in the search edit results in this event firing and Not the SecondaryFocusChangedEvent.
;We schedule a delay both To avoid spamming While typing,
;and To give SecondaryFocusChangedEvent a chance To unschedule speaking of the selection change If that event fires.
chromeAutoCompleteAddress = text
ScheduleIDSayAutoCompleteAddressAfterPause = ScheduleFunction ("SayAutoCompleteAddressAfterPause", SayAutoCompleteAddressAfterPauseWaitTime, True)
EndIf
;This event fires To remove the selection as you tab from the editable text.
;Do nothing here when this event fires For the deselection, To avoid hearing the deselection when no longer in the editable text.
Return
EndIf
;this is To keep selection event On an address bar from speaking when switching tabs
SelectionChangedEvent( text, wasTextSelected, source )
EndFunction
Void Function SecondaryFocusChangedEvent()
If ScheduleIDSayAutoCompleteAddressAfterPause
UnscheduleFunction(ScheduleIDSayAutoCompleteAddressAfterPause)
EndIf
If IsOnAddressBarEdit()
;Speaking is handled by ValueChangedEvent
Return
EndIf
SecondaryFocusChangedEvent()
EndFunction
Void Function ValueChangedEvent (Handle hwnd, Int objId, Int childId, Int nObjType, String sObjName, String sObjValue, optional Int bIsFocusObject)
If IsOnAddressBarEdit()
&& bIsFocusObject
;We want To announce the value change On the address bar when navigating,
;and Not when typing or deleting text.
;SelectionChangedEvent will announce If the address bar text changes due To typing in New text.
Var String scriptName = GetScriptAssignedTo(GetCurrentScriptKeyName())
If lastKeyWasScripted
&& (scriptName == "SayNextLine"
|| scriptName == "SayPriorLine"
|| scriptName == "Tab"
|| scriptName == "ShiftTab")
Say(sObjValue, ot_line)
EndIf
Return
EndIf
If (gChromeVersion < 69
&& getObjectSubtypeCode()==wt_combobox) Then
Return ;spoken from activeItemChanged event, filter here To avoid multiple speaking.
EndIf
ValueChangedEvent (hwnd, objId, childId, nObjType, sObjName, sObjValue, bIsFocusObject)
EndFunction
Void Function SayLineUnit(Int unitMovement, optional Int bMoved)
If !IsVirtualPCCursor() && GetObjectSubtypeCode()==WT_COMBOBOX Then
Return; ActiveItemChangedEvent will speak this.
EndIf
SayLineUnit(unitMovement, bMoved)
EndFunction
Int Function IsValidForTraverseBrowserUIDialogAndReadControls(String dlgName, Object element)
Return element.name != dlgName
EndFunction
Script readBoxInTabOrder()
If gbIsBrowserUIDialog
;GetTypeAndTextStringsForWindow often retrieves text with duplications,
;so we first try To Use UIA To traverse and read the elements.
If !ReadBrowserUIDialogBox()
Say(GetTypeAndTextStringsForWindow(getFocus()), ot_USER_REQUESTED_INFORMATION)
EndIf
Return
EndIf
performScript ReadBoxInTabOrder()
EndScript
Void Function GetWindowTitleForApplication(Handle hAppWnd, Handle hRealWnd, Handle hCurWnd, Int iTypeCode,
String ByRef sTitle, String ByRef sSubTitle, Int ByRef bHasPage)
If IsBrowserContentWindow(hCurWnd)
&& StringCompare (StringSegment (GetOwningAppName (GetFocus ()), ".", 1), "chrome") == 0
sTitle=GetObjectName(SOURCE_CACHED_DATA, GetAncestorCount ())
EndIf
If StringIsBlank (sTitle)
GetWindowTitleForApplication(hAppWnd, hRealWnd, hCurWnd, iTypeCode, sTitle, sSubTitle, bHasPage)
EndIf
EndFunction
Int Function HandleCustomAppWindows (Handle hWnd)
; Alt tabbing To Chrome.
If getWindowClass(hWnd)==wc_Chrome_WidgetWin_1 Then
say(GetObjectName(SOURCE_CACHED_DATA, GetAncestorCount ()), ot_window_name)
Return True
EndIf
Return HandleCustomAppWindows (hWnd)
EndFunction
Script PictureSmartWithControl (optional Int serviceOptions)
Return PictureSmartWithControlShared (PSServiceOptions_Single | serviceOptions)
EndScript
Script PictureSmartWithControlMultiService (optional Int serviceOptions)
Return PictureSmartWithControlShared (PSServiceOptions_Multi | serviceOptions)
EndScript
Int Function ShouldSpeakItemAtLevel(Int level, Int type, Int parentType, Int focusRole, Int focusType)
Var
Int ancestorRole = GetObjectRole(level),
Int ancestorCount = GetAncestorCount(),
Int dialogAncestor = FindAncestorOfType(wt_dialog),
String ancestorName = cscNull,
String dialogName = cscNull
If (ancestorRole == ROLE_SYSTEM_WINDOW && level == ancestorCount)
If (dialogAncestor != -1)
ancestorName = GetObjectName(SOURCE_CACHED_DATA, level)
dialogName = GetObjectName(SOURCE_CACHED_DATA, dialogAncestor)
If (ancestorName == dialogName)
Return False
EndIf
EndIf
Return True
EndIf
If (ancestorRole == ROLE_SYSTEM_WINDOW || ancestorRole == ROLE_SYSTEM_PANE)
Return False
EndIf
Return ShouldSpeakItemAtLevel(level, type, parentType, focusRole, focusType)
EndFunction
Int Function NewBrowserTabIsNewPage(Handle hWnd)
Return gChromeBrowserTabHWnd != hWnd
EndFunction
Void Function AnnounceNewTabOrPageFromBrowserTabChangedEvent(Handle hWnd)
;When Control+N is used, a New window opens and the focus change will speak the focused Object.
;But when Control+T is used, a New tab is created but the focus does Not change so we should also announce the focused Object.
If !NewBrowserTabIsNewPage(hWnd)
SayFormattedMessage(ot_screen_message, msgNewTabPage)
SayObjectTypeAndText()
else
SayFormattedMessage(ot_screen_message, msgNewWindow)
EndIf
EndFunction
Void Function BrowserTabChangedEvent(Int tabID, Handle hWnd)
;fires when changing browser tabs.
If gChromeBrowserTabID != tabID
;Ensure this announcement only happens If the New tab event is generated While On the address bar:
If GetWindowClass(GlobalPrevFocus) == cwc_Chrome_WidgetWin_1
AnnounceNewTabOrPageFromBrowserTabChangedEvent(hWnd)
EndIf
EndIf
gChromeBrowserTabID = tabID
gChromeBrowserTabHWnd = hWnd
EndFunction
Prototype Int Function GetTabID()
Prototype Int Function GetVirtualCursorSettingForTab(Int tabID)
Prototype Void Function SetVirtualCursorSettingForTab(Int tabID, Int vCursorSetting)
Script VirtualPCCursorToggle ()
Var Int isVirtualCursorTabSpecific = GetJCFOption(OPT_VirtualCursorIsTabSpecific )
If (!isVirtualCursorTabSpecific ) Then
PerformScript VirtualPCCursorToggle()
Return
EndIf
Var Int vCursorSetting = GetVirtualCursorSettingForTab(GetTabID())
If vCursorSetting == 0 Then
vCursorSetting = 1
else
vCursorSetting = 0
EndIf
refresh()
BrailleRefresh()
SetVirtualCursorSettingForTab(GetTabID(), vCursorSetting )
If vCursorSetting Then
SayFormattedMessage(ot_status, cMSG291_L, cmsgOn)
else
SayFormattedMessage(ot_status, cmsg292_L, cmsgOff)
EndIf
EndScript
Int Function SayLineInsteadOfSayAll()
Var
Int type
Let type = GetObjectSubTypeCode(SOURCE_CACHED_DATA, 0)
If IsPcCursor()
&& !IsVirtualPcCursor()
&& DialogActive() Then
If (type == WT_MULTILINE_EDIT) Then
Return False
EndIf
EndIf
Return SayLineInsteadOfSayAll()
EndFunction
Int Function ContextMenuProcessed(Handle hWnd)
If (IsBrowserContentWindow(hwnd))
Return
EndIf
Return ContextMenuProcessed (hwnd )
EndFunction
Void Function HandleUnknownAncestor (Int level, Int focusType, Int pageIsChanging)
If (level < 1) Then
Return
EndIf
If (GetObjectSubtypeCode(SOURCE_CACHED_DATA, level) != WT_UNKNOWN) Then
Return
EndIf
If ( GetObjectName(SOURCE_CACHED_DATA, level) == " " ) Then
Return
EndIf
Var
Int ancestorCount,
String focusedElementName,
String ancestorElementName
focusedElementName = stringStripAllBlanks (GetObjectName(SOURCE_CACHED_DATA, 0))
ancestorElementName = stringStripAllBlanks (GetObjectName(SOURCE_CACHED_DATA, level))
ancestorCount = GetAncestorCount ()
If (level != ancestorCount
&& (StringContains (ancestorElementName, focusedElementName))) Then
Return
EndIf
If GetObjectSubTypeCode(SOURCE_CACHED_DATA, 0) == WT_UNKNOWN
Return ;focused Object and ancestor Object are both unknown types, just speak the focused Object
EndIf
SayObjectTypeAndText (level)
EndFunction
Void Function PreProcessFocusChangedEventEx(
Handle hwndFocus, Int nObject, Int nChild,
Handle hwndPrevFocus, Int nPrevObject, Int nPrevChild,
Int nChangeDepth)
lastFocusType = GetObjectSubTypeCode(False, 0)
If ScheduleIDUpdateAndSayNewStateOfRadioButton
UnscheduleFunction(ScheduleIDUpdateAndSayNewStateOfRadioButton )
ScheduleIDUpdateAndSayNewStateOfRadioButton = 0
EndIf
PreProcessFocusChangedEventEx(hwndFocus, nObject, nChild, hwndPrevFocus, nPrevObject, nPrevChild, nChangeDepth)
EndFunction
Void Function ProcessSayRealWindowOnFocusChange(
Handle AppWindow, Handle RealWindow, String RealWindowName, Handle FocusWindow)
If GetWindowClass(GlobalPrevFocus) !=wc_Chrome_WidgetWin_1
If gbIsBrowserUIDialog
;A dialog from the browser UI has just gained focus.
SayAndCacheBrailleForBrowserUIDialogNameAndText()
Return
EndIf
EndIf
ProcessSayRealWindowOnFocusChange(AppWindow, RealWindow, RealWindowName, FocusWindow)
EndFunction
Int Function IsKeySelectingText(Int keyCode)
Var Int isShiftLeft = (keyCode&~ShiftKey) == key_LeftArrow
Var Int isShiftRight = (keyCode&~ShiftKey) == key_RightArrow
Var Int isShiftCTRLLeft = (keyCode&~(ShiftKey|CTRLKey)) == key_LeftArrow
Var Int isShiftCTRLRight = (keyCode&~(ShiftKey|CTRLKey)) == key_RightArrow
Var Int isShiftHome = (keyCode&~ShiftKey) == key_Home
Var Int isShiftEnd = (keyCode&~ShiftKey) == key_End
Return (isShiftLeft
|| isShiftRight
|| isShiftCTRLLeft
|| isShiftCTRLRight
|| isShiftHome
||IsShiftEnd)
EndFunction
Void Function UpdateAndSayNewStateOfRadioButton()
ScheduleIDUpdateAndSayNewStateOfRadioButton = 0
If GetObjectStateCode() & CTRL_CHECKED
;The toggle was detected:
Return
EndIf
MSAARefresh()
Pause() ;Allow time To update
IndicateControlState(wt_RadioButton, GetObjectStateCode())
EndFunction
Int Function ProcessSpaceBarKeyPressed(Int nKey, String strKeyName, Int nIsBrailleKey, Int nIsScriptKey)
If KeyIsSpacebar(nKey, strKeyName, nIsBrailleKey)
&& GetWindowClass(GetFocus()) == cwc_Chrome_WidgetWin_1
&& GetObjectSubtypeCode() == wt_RadioButton
;We may Not have received any events For updating the state:
ScheduleIDUpdateAndSayNewStateOfRadioButton = ScheduleFunction("UpdateAndSayNewStateOfRadioButton", 3)
Return True
EndIf
Return ProcessSpaceBarKeyPressed(nKey, strKeyName, nIsBrailleKey, nIsScriptKey)
EndFunction
Void Function KeyPressedEvent (Int nKey, String strKeyName, Int nIsBrailleKey, Int nIsScriptKey)
lastKeyWasSelecting = IsKeySelectingText(nKey)
lastKeyWasScripted = nIsScriptKey
KeyPressedEvent (nKey, strKeyName, nIsBrailleKey, nIsScriptKey)
EndFunction
Int Function IsOpenListBoxApplicable(Handle hWnd, Int iSubtype)
If (!IsFormsModeActive())
Return IsOpenListBoxApplicable(hWnd, iSubtype)
EndIf
Return !SupportsEditCallbacks ()
EndFunction
Int Function IsCloseListBoxApplicable(Handle hWnd, Int iSubtype)
If (!IsFormsModeActive())
Return IsCloseListBoxApplicable(hWnd, iSubtype)
EndIf
Return !SupportsEditCallbacks ()
EndFunction
Prototype IntArray Function GetDetailsIDs(Int details)
Prototype String Function GetTextForUniqueIDs(IntArray ids, Int idsCount)
Prototype Void Function RestrictToElementsWithUniqueIDs(IntArray ids, Int idsCount)
Prototype Void Function MoveToElementWithUniqueID(Int id)
Script announceComment ()
Var IntArray ids = GetDetailsIDs(True)
Var Int idsCount = ArrayLength (ids)
If (idsCount == 0)
SayMessage (OT_ERROR, msgNoCommentAvailable)
Return
EndIf
If isSameScript() Then
ResetSpeechMarkupAttributes()
MoveToElementWithUniqueID(ids[1])
RestrictToElementsWithUniqueIDs(ids, idsCount)
restrictedIDs = ids
Return
EndIf
Var String text = GetTextForUniqueIDs(ids, idsCount)
If (StringIsBlank (text))
SayMessage (OT_ERROR, msgNoCommentTextAvailable)
Return
EndIf
text = msgComment + cscSpace + text
SayMessage (OT_JAWS_MESSAGE, text)
EndScript
Int Function IsInsideDetailsFor()
Var IntArray detailsForIDs = GetDetailsIDs(False)
Var Int idsCount = ArrayLength (detailsForIDs )
Return (idsCount > 0)
EndFunction
Script UpALevel()
If (!IsInsideDetailsFor())
PerformScript UpALevel()
Return
EndIf
SayCurrentScriptKeyLabel ()
Var IntArray detailsForIDs = GetDetailsIDs(False)
Refresh() ;used To unrestrict the document before moving back To the commented text.
MoveToElementWithUniqueID(detailsForIDs[1])
EndScript
Void Function FormsModeEvent(Int bEntering, optional Int lastMovementUnit)
Var Int idsCount = ArrayLength (restrictedIDs)
If (bEntering == False
&& idsCount)
ScheduleFunction ("RestrictToSavedIDs", 1)
EndIf
FormsModeEvent(bEntering, lastMovementUnit)
EndFunction
Void Function RestrictToSavedIDs()
Var Int idsCount = ArrayLength (restrictedIDs)
RestrictToElementsWithUniqueIDs(restrictedIDs, idsCount)
EndFunction
Int Function SpeakLiveRegionEvent(String text, Int suggestedOutputType, Int containsSpeechMarkup)
If SayAllInProgress () Then
Return True ; Do Not speak notifications during skimread or sayAll.
EndIf
Return SpeakLiveRegionEvent(text, suggestedOutputType, containsSpeechMarkup)
EndFunction
Int Function InPageTabArea()
If isVirtualPCCursor() Return False EndIf
If GetWindowClass(getFocus()) != wc_Chrome_WidgetWin_1 Return False EndIf
Var
Int i,
Int depth = GetAncestorCount()
For i = 1 To depth
If GetObjectRole(i) == Role_System_PageTabList
Return True
EndIf
EndFor
Return False
EndFunction
Void Function SayObjectTypeAndText(optional Int nLevel, Int includeContainerName)
If nLevel == 0
If InPageTabArea()
;suppress description announcement from builtin SayObjectTypeAndText where the description information duplicates the name:
Var
Int type = GetObjectSubtypeCode(),
String name = GetObjectname()
If type == wt_button
&& StringLower(name) == StringLower(GetObjectDescription())
;The New Tab button differens only by case:
IndicateControlType(wt_button, name, cmsgSilent)
Return
ElIf type == wt_unknown
&& GetObjectRole() == Role_System_PageTabList
;We don't actually have a subtypeCode defined For this type of control yet.
;For now, we will call it a tab control.
IndicateControlType(wt_TabControl, name, cmsgSilent)
IndicateControlState(wt_TabControl, GetObjectStateCode())
Return
EndIf
EndIf
EndIf
SayObjectTypeAndText(nLevel, includeContainerName)
EndFunction
Script SayLine(optional Int drawHighlights)
If IsPCCursor()
&& InPageTabArea()
&& GetObjectSubtypecode() == wt_TabControl
SayLine()
;SayLine does Not Include the position in group of the tab,
;and SayObjectTypeAndText will have out of date information about the position If the tab was shifted and focus has Not yet moved.
Var Object element = FSUIAGetFocusedElement()
If !element Return EndIf
Var
Int x = element.positionInSet,
Int y = element.sizeOfSet
If x && y
Say(FormatString(cmsgPosInGroup1, IntToString(x), IntToString(y)), ot_position)
EndIf
Return
EndIf
PerformScript SayLine()
EndScript
Script SayNextWord()
;Allow shifting page tabs:
If IsPCCursor()
&& InPageTabArea()
&& GetObjectSubtypeCode() == wt_TabControl
TypeKey(cksCtrlRightArrow)
Return
EndIf
PerformScript SayNextWord()
EndScript
Script SayPriorWord()
;Allow shifting page tabs:
If IsPCCursor()
&& InPageTabArea()
&& GetObjectSubtypeCode() == wt_TabControl
TypeKey(cksCtrlLeftArrow)
Return
EndIf
PerformScript SayPriorWord()
EndScript
Script SelectNextWord()
;Allow shifting page tabs:
If IsPCCursor()
&& InPageTabArea()
&& GetObjectSubtypeCode() == wt_TabControl
TypeKey(cksShiftControlRightArrow)
Return
EndIf
PerformScript SelectNextWord()
EndScript
Script SelectPriorWord()
;Allow shifting page tabs:
If IsPCCursor()
&& InPageTabArea()
&& GetObjectSubtypeCode() == wt_TabControl
TypeKey(cksShiftControlLeftArrow)
Return
EndIf
PerformScript SelectPriorWord()
EndScript
Int Function IsFocusedOnTabSearchTopChromePage()
;Control+Shift + A brings up the page chrome://tab-search.top-chrome/
Return !UserBufferIsActive()
&& GetWindowClass(GetFocus()) == wc_ChromeWindowClass
&& GetDocumentPath() == scTabSearchTopChromeIdentifyer
EndFunction
Void Function DescriptionChangedEventAnnouncement()
ScheduleIDDescriptionChangedEventAnnouncement = 0
Say (gsDescriptionChangedEventText, OT_WINDOW_INFORMATION)
gsDescriptionChangedEventText = cscNull
EndFunction
Void Function DescriptionChangedEvent(Handle hwnd, Int objId, Int childId, Int nObjType, String sOldDescription, String sNewDescription, optional Int bFromFocusObject)
If bFromFocusObject
&& IsFocusedOnTabSearchTopChromePage()
;sNewDescription contains text saying how many matches were found For the text in the search edit field.
;This updates For each character typed into the edit field.
;To avoid spamming While typing, the announcement is scheduled rather than spoken immediately.
If ScheduleIDDescriptionChangedEventAnnouncement
UnscheduleFunction(ScheduleIDDescriptionChangedEventAnnouncement)
EndIf
gsDescriptionChangedEventText = sNewDescription
ScheduleIDDescriptionChangedEventAnnouncement = ScheduleFunction("DescriptionChangedEventAnnouncement", DescriptionChangedEventAnnouncementWaitTime)
Return
EndIf
DescriptionChangedEvent(hwnd, objId, childId, nObjType, sOldDescription, sNewDescription, bFromFocusObject)
EndFunction
Int Function InDialogWithDocumentDescendant()
If !dialogActive() Return False EndIf
Var
Int i,
Int type,
Int role,
Int levels
;Start at level 0, just in case the dialog itself has focus.
levels = GetAncestorCount()+1
For i = 0 To levels
type = GetObjectSubtypeCode(False, i)
role = GetObjectRole(i)
If type == wt_dialog
|| role == ROLE_SYSTEM_DIALOG
Return False
ElIf type == WT_DOCUMENT
|| role == ROLE_SYSTEM_DOCUMENT
Return True
EndIf
EndFor
Return False
EndFunction
Int Function SayNewDocumentTab()
If IsFocusedOnTabSearchTopChromePage()
Var Int documentLevel = GetDocumentLevel()
If documentLevel > -1
gsDocID = GetIDAtLevel(documentLevel)
If gsDocID != gsPrevDocID
Say(GetDocumentTitle(), ot_document_name)
SayObjectTypeAndText()
gsPrevDocID = gsDocID
Return True
EndIf
EndIf
EndIf
Return SayNewDocumentTab()
EndFunction
Void Function DoBackSpace()
If !IsOnAddressBarEdit()
DoBackSpace()
Return
EndIf
Var
String sSelectedText = GetSelectedText(),
Int iTextSelected = !StringIsBlank(sSelectedText)
If !iTextSelected
DoBackSpace()
Return
EndIf
TypeKey(cksBackspace)
SayFormattedMessage(OT_MESSAGE, cMsgSelectionDeleted, cmsgSilent)
EndFunction
Void Function MSAAAlertEvent(Handle hwnd, Int nTime, String sText, Int nAlertLevel, String appName)
MSAAAlertEvent(hwnd, nTime, sText, nAlertLevel, appName)
If !nAlertLevel
&& c_BackgroundOCRRect.restrictedToCustomRect
;The zoom level of the browser may have changed.
;Set c_BackgroundOCRRect.shouldUpdateRect To True so the rectangle will be updated.
c_BackgroundOCRRect.shouldUpdateRect = True
EndIf
EndFunction
Void Function GetARIAActionsNameAndIndexes(String ByRef actionsString, IntArray byref actionIndexes)
Var StringArray ariaActions = GetARIAActions()
If (ArrayLength(ariaActions) == 0)
actionsString = " "
Return
EndIf
Var Int i
actionIndexes = New IntArray[ArrayLength(ariaActions)]
For i = 1 To ArrayLength(ariaActions)
Var StringArray actionItem = stringSplit(ariaActions[i], ":", True)
actionsString = StringConcatenate(actionsString, actionItem[1], LIST_ITEM_SEPARATOR)
actionIndexes[i] = StringToInt (actionItem[2])
EndFor
EndFunction
Script DisplayARIAActions ()
Var String actionsString
Var IntArray actionIndexes
GetARIAActionsNameAndIndexes(actionsString, actionIndexes)
If (StringLength (actionsString) == 0)
SayMessage (OT_ERROR, msgNoActionsAvailable)
Return
EndIf
Var Int selectedItem = DlgSelectItemInList (actionsString, msgSelectActionTitle, False)
If (!PerformARIAActionByIndex(actionIndexes[selectedItem]))
SayMessage (OT_ERROR, msgFailedToInvokeAction)
EndIf
EndScript
Void Function DoCloseListBoxKeyStroke()
;Using TypeKey of Alt+UpArrow in Chrome may cause the focus To move To the Chrome menu,
;so we Use Escape To close a listbox For both Chrome and Edge:
EscapeKey()
EndFunction