Skip to content

Commit

Permalink
Merge branch 'master' into beta
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelDCurran committed Dec 5, 2019
2 parents 78edc09 + eb38157 commit 55acd1f
Show file tree
Hide file tree
Showing 61 changed files with 115,134 additions and 233 deletions.
2 changes: 1 addition & 1 deletion include/espeak
Submodule espeak updated 87 files
+1 −1 .gitignore
+6 −1 CHANGELOG.md
+12 −4 Makefile.am
+59 −358 README.md
+1 −1 android/jni/include/config.h
+25 −7 android/res/values-es-rUS/strings.xml
+1 −1 configure.ac
+82 −0 dictsource/ba_list
+133 −0 dictsource/ba_rules
+0 −1 dictsource/de_list
+1 −0 dictsource/de_rules
+0 −0 dictsource/extra/zhy_listx
+26 −14 dictsource/fa_list
+22 −18 dictsource/fa_rules
+21 −1 dictsource/it_list
+7 −2 dictsource/it_listx
+7 −1 dictsource/it_rules
+60 −3 dictsource/sd_list
+34 −32 dictsource/sd_rules
+30 −9 dictsource/shn_list
+268 −135 dictsource/shn_rules
+8 −9 dictsource/tr_rules
+112 −7 dictsource/ur_list
+115 −3 dictsource/ur_rules
+132 −0 dictsource/uz_list
+139 −0 dictsource/uz_rules
+1 −1 dictsource/zh_list
+3,815 −0 dictsource/zhy_list
+0 −85 docs/README.md
+338 −0 docs/building.md
+58 −0 docs/contributing.md
+19 −6 docs/dictionary.md
+30 −0 docs/index.md
+3 −1 docs/languages.md
+8 −3 docs/mbrola.md
+1 −1 emscripten/Makefile
+6 −2 emscripten/js/demo.js
+4 −2 emscripten/post.js
+2 −0 espeak-ng-data/lang/trk/ba
+4 −0 espeak-ng-data/lang/trk/uz
+20 −0 espeak-ng-data/voices/!v/Andrea
+22 −0 espeak-ng-data/voices/!v/Diogo
+22 −0 espeak-ng-data/voices/!v/Henrique
+22 −0 espeak-ng-data/voices/!v/Hugo
+16 −0 espeak-ng-data/voices/!v/RicishayMax
+25 −0 espeak-ng-data/voices/!v/RicishayMax2
+25 −0 espeak-ng-data/voices/!v/RicishayMax3
+25 −0 espeak-ng-data/voices/!v/anika
+26 −0 espeak-ng-data/voices/!v/anikaRobot
+21 −0 espeak-ng-data/voices/!v/antonio
+21 −0 espeak-ng-data/voices/!v/belinda
+17 −0 espeak-ng-data/voices/!v/ed
+11 −0 espeak-ng-data/voices/!v/fast
+17 −0 espeak-ng-data/voices/!v/grandma
+14 −0 espeak-ng-data/voices/!v/grandpa
+17 −0 espeak-ng-data/voices/!v/gustave
+17 −0 espeak-ng-data/voices/!v/marcelo
+22 −0 espeak-ng-data/voices/!v/miguel
+48 −0 espeak-ng-data/voices/!v/pablo
+48 −0 espeak-ng-data/voices/!v/pablo2
+17 −0 espeak-ng-data/voices/!v/paul
+23 −0 espeak-ng-data/voices/!v/pedro
+26 −0 espeak-ng-data/voices/!v/robosoft3
+25 −0 espeak-ng-data/voices/!v/robosoft4
+25 −0 espeak-ng-data/voices/!v/robosoft5
+15 −0 espeak-ng-data/voices/!v/robosoft6
+25 −0 espeak-ng-data/voices/!v/robosoft7
+16 −0 espeak-ng-data/voices/!v/robosoft8
+18 −0 espeak-ng-data/voices/!v/shelby
+16 −0 espeak-ng-data/voices/!v/victor
+163 −0 phsource/ph_bashkir
+4 −1 phsource/ph_german
+34 −33 phsource/ph_shan
+2 −0 phsource/ph_uzbek
+206 −193 phsource/phonemes
+1 −2 src/libespeak-ng/compiledata.c
+5 −2 src/libespeak-ng/dictionary.c
+8 −0 src/libespeak-ng/readclause.c
+5 −1 src/libespeak-ng/readclause.h
+1 −1 src/libespeak-ng/translate.c
+7 −6 src/libespeak-ng/voices.c
+1 −1 src/windows/config.h
+1 −1 src/windows/data.vcxproj
+1 −1 src/windows/installer/Product.wxs
+1 −1 tests/language-phonemes.test
+1 −1 tests/language-pronunciation.test
+1 −1 tests/language-replace.test
54 changes: 54 additions & 0 deletions nvdaHelper/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## NVDA Helper

Parts of NVDA Helper are used to capture and cache information, in-process, within web browsers and other applications.
This cache is called a virtual buffer.
While virtual buffers apply to several different application types, it may first be easiest to think about how they
work with browsers, the rest of this document will take a web browser centric view unless specified otherwise.

### Configuring Visual Studio
The following steps won't prepare a buildable solution, but it will enable intellisense.
You should still build on the command line to verify errors.

- Ensure you have built NVDA on the command line first.
- Create a new project from existing code
- Type: Visual C++
- Set the `<repo root>/nvdaHelper/` directory as the project file location.
- Project name: "nvdaHelper"
- Add files to the project from these folders: checked.
- Other defaults are fine
- Includes: `../include;../miscdeps/include;./;../build\x86_64;%(AdditionalIncludeDirectories)`
- Defines: `WIN32;_WINDOWS;_USRDLL;NVDAHELPER_EXPORTS;UNICODE;_CRT_SECURE_NO_DEPRECATE;LOGLEVEL;_WIN32_WINNT;_WIN32_WINNT_WIN7;`
- Force Includes: `winuser.h`
- Create the project.
- Open the project settings and change the following:
- General -> Windows SDK: 10.0.17763.0 (or whatever is the latest on your system)
- C/C++ -> Language -> C++ Language Standard -> ISO C++14 Standard (/std:c++14)

### Virtual Buffer Backends

This code runs within the target applications process, it is responsible for building the virtual buffer.
The base classes are in the `storage.h` and `storage.cpp`.
The `storage` classes are implementation agnostic, they don't use the accessibility APIs directly and thus don't have
the same performance concerns as the code that directly interacts with the accessibility APIs,
such as the code in `gecko_ia2.cpp`.
A buffer (`VBufStorage_buffer_t`) has many `Nodes` that make up the document.
The `VBufStorage_buffer_t` class owns the *Node instances, such as `controlFieldNode` and `textFieldNode`.
The buffer (`VBufStorage_buffer_t`) is responsible for creating (in `fillVBuf`) and caching the nodes that make up the
document.
An element in a HTML document becomes a `controlFieldNode`.
The inner text of a HTML element would become a `textFieldNode`.
Extra information that we want to be able to present to the user is collected as these nodes are created.
For instance the name, description, role, and many other pieces of information.
A Node has a pointer to its parent node, child nodes, and sibling nodes, we have a graph of the virtual buffer.
Each `controlFieldNode` (like an element, remember?) has an identifier (`VBufStorage_controlFieldNodeIdentifier_t`).
Given an identifier, a `controlFieldNode` can be looked up using `controlFieldNodesByIdentifier`.
Though, take care, looking up nodes is only possible after that part of the tree has been rendered.
The `controlFieldNode`s are added to the buffer via `addControlFieldNode`, which also adds these nodes to the map.

### Gecko IA2

This is a virtual buffer backend implementation used for Firefox and Chrome.
When `fillVBuf` is called, it recursively descends through the child elements that we care about, creating either
`controlFieldNode`s or `textFieldNode`s for them.
This code is responsible for interacting with the IA2 accessibility API, these calls should be minimised for
performance reasons.
157 changes: 125 additions & 32 deletions nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ This license can be found at:

#include <memory>
#include <functional>
#include <vector>
#include <map>
#include <boost/optional.hpp>
#include <windows.h>
#include <set>
Expand All @@ -24,6 +26,7 @@ This license can be found at:
#include <common/ia2utils.h>
#include <remote/nvdaHelperRemote.h>
#include <vbufBase/backend.h>
#include <vbufBase/storage.h>
#include <common/log.h>
#include <vbufBase/utils.h>
#include "gecko_ia2.h"
Expand Down Expand Up @@ -284,21 +287,37 @@ void GeckoVBufBackend_t::versionSpecificInit(IAccessible2* pacc) {
SysFreeString(toolkitVersion);
}

bool GeckoVBufBackend_t::isLabelVisible(IAccessible2* pacc2) {
experimental::optional<int>
getIAccessible2UniqueID(IAccessible2* targetAcc) {
int ID = 0;
//Get ID -- IAccessible2 uniqueID
if (targetAcc->get_uniqueID((long*)&ID) != S_OK) {
LOG_DEBUG(L"pacc->get_uniqueID failed");
return experimental::optional<int>();
}
return ID;
}

class LabelInfo {
public:
bool isVisible;
std::experimental::optional<int> ID;
};

using OptionalLabelInfo = std::experimental::optional< LabelInfo >;
OptionalLabelInfo GeckoVBufBackend_t::getLabelInfo(IAccessible2* pacc2) {
CComQIPtr<IAccessible2_2> pacc2_2=pacc2;
if(!pacc2_2) return false;
if (!pacc2_2) return OptionalLabelInfo();
auto targetAcc=getLabelElement(pacc2_2);
if(!targetAcc) return false;
if(!targetAcc) return OptionalLabelInfo();
CComVariant child;
child.vt = VT_I4;
child.lVal = 0;
CComVariant state;
HRESULT res = targetAcc->get_accState(child, &state);
if (res != S_OK)
return false;
if (state.lVal & STATE_SYSTEM_INVISIBLE)
return false;
return true;
bool isVisible = res == S_OK && !(state.lVal & STATE_SYSTEM_INVISIBLE);
auto ID = getIAccessible2UniqueID(targetAcc);
return LabelInfo { isVisible, ID } ;
}

long getChildCount(const bool isAriaHidden, IAccessible2 * const pacc){
Expand Down Expand Up @@ -403,9 +422,15 @@ CComPtr<IAccessible2> getTextBoxInComboBox(
const vector<wstring>ATTRLIST_ROLES(1, L"IAccessible2::attribute_xml-roles");
const wregex REGEX_PRESENTATION_ROLE(L"IAccessible2\\\\:\\\\:attribute_xml-roles:.*\\bpresentation\\b.*;");

VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
VBufStorage_buffer_t* buffer, VBufStorage_controlFieldNode_t* parentNode, VBufStorage_fieldNode_t* previousNode,
IAccessibleTable* paccTable, IAccessibleTable2* paccTable2, long tableID, const wchar_t* parentPresentationalRowNumber,
VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(
IAccessible2* pacc,
VBufStorage_buffer_t* buffer,
VBufStorage_controlFieldNode_t* parentNode,
VBufStorage_fieldNode_t* previousNode,
IAccessibleTable* paccTable,
IAccessibleTable2* paccTable2,
long tableID,
const wchar_t* parentPresentationalRowNumber,
bool ignoreInteractiveUnlabelledGraphics
) {
nhAssert(buffer); //buffer can't be NULL
Expand All @@ -431,9 +456,12 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
}
//Get ID -- IAccessible2 uniqueID
int ID;
if(pacc->get_uniqueID((long*)&ID)!=S_OK) {
LOG_DEBUG(L"pacc->get_uniqueID failed");
return NULL;
{
auto opt_id = getIAccessible2UniqueID(pacc);
if (!opt_id){
return nullptr;
}
ID = opt_id.value();
}

//Make sure that we don't already know about this object -- protect from loops
Expand Down Expand Up @@ -629,13 +657,27 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
// Whether the name of this node has been explicitly set (as opposed to calculated by descendant)
const bool nameIsExplicit = IA2AttribsMapIt != IA2AttribsMap.end() && IA2AttribsMapIt->second == L"true";
// Whether the name is the content of this node.
std::experimental::optional<bool> isLabelVisibleVal_;
// A version of the isLabelVisible function that caches its result
auto isLabelVisibleCached=[&]() {
if(!isLabelVisibleVal_) {
isLabelVisibleVal_=isLabelVisible(pacc);
std::experimental::optional<LabelInfo> labelInfo_;
// A version of the getIdForVisibleLabel function that caches its result
auto isLabelVisibleCached = [&]() {
if (!labelInfo_) {
labelInfo_ = getLabelInfo(pacc);
}
bool isVisible = false;
if (labelInfo_) {
isVisible = labelInfo_->isVisible;
}
return *isLabelVisibleVal_;
return isVisible;
};
auto getLabelIDCached = [&]() {
if (!labelInfo_) {
labelInfo_ = getLabelInfo(pacc);
}
experimental::optional<int> id;
if (labelInfo_) {
id = labelInfo_->ID;
}
return id;
};
const bool nameIsContent = isEmbeddedApp
|| role == ROLE_SYSTEM_LINK
Expand Down Expand Up @@ -942,7 +984,18 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
if(!childPacc) {
continue;
}
if (tempNode = this->fillVBuf(childPacc, buffer, parentNode, previousNode, paccTable, paccTable2, tableID, presentationalRowNumber, ignoreInteractiveUnlabelledGraphics)) {
tempNode = this->fillVBuf(
childPacc,
buffer,
parentNode,
previousNode,
paccTable,
paccTable2,
tableID,
presentationalRowNumber,
ignoreInteractiveUnlabelledGraphics
);
if (tempNode) {
previousNode=tempNode;
} else {
LOG_DEBUG(L"Error in fillVBuf");
Expand Down Expand Up @@ -973,8 +1026,20 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
VariantClear(&(varChildren[i]));
continue;
}
if (tempNode = this->fillVBuf(childPacc, buffer, parentNode, previousNode, paccTable, paccTable2, tableID, presentationalRowNumber, ignoreInteractiveUnlabelledGraphics))
previousNode=tempNode;
tempNode = this->fillVBuf(
childPacc,
buffer,
parentNode,
previousNode,
paccTable,
paccTable2,
tableID,
presentationalRowNumber,
ignoreInteractiveUnlabelledGraphics
);
if (tempNode) {
previousNode = tempNode;
}
else
LOG_DEBUG(L"Error in calling fillVBuf");
childPacc->Release();
Expand All @@ -985,10 +1050,18 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
} else if (renderSelectedItemOnly) {
CComPtr<IAccessible2> item = this->getSelectedItem(pacc, IA2AttribsMap);
if (item) {
if (tempNode = this->fillVBuf(item, buffer, parentNode, previousNode,
paccTable, paccTable2, tableID, presentationalRowNumber,
ignoreInteractiveUnlabelledGraphics)
) {
tempNode = this->fillVBuf(
item,
buffer,
parentNode,
previousNode,
paccTable,
paccTable2,
tableID,
presentationalRowNumber,
ignoreInteractiveUnlabelledGraphics
);
if (tempNode) {
previousNode=tempNode;
// The container itself might not always fire selection events.
// Therefore, we rely on a stateChange event on the item (since
Expand All @@ -1004,10 +1077,18 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
CComPtr<IAccessible2> textBox = getTextBoxInComboBox(pacc);
if (textBox) {
// ARIA 1.1 combobox. Render the text box child.
if (tempNode = this->fillVBuf(textBox, buffer, parentNode, previousNode,
paccTable, paccTable2, tableID, presentationalRowNumber,
ignoreInteractiveUnlabelledGraphics)
) {
tempNode = this->fillVBuf(
textBox,
buffer,
parentNode,
previousNode,
paccTable,
paccTable2,
tableID,
presentationalRowNumber,
ignoreInteractiveUnlabelledGraphics
);
if (tempNode) {
previousNode=tempNode;
} else {
LOG_DEBUG(L"Error in calling fillVBuf");
Expand Down Expand Up @@ -1073,6 +1154,18 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
}
}

auto labelId = getLabelIDCached();
if (labelId) {
auto labelControlFieldNode = buffer->getControlFieldNodeWithIdentifier(docHandle, labelId.value());
if (labelControlFieldNode) {
bool isDescendant = buffer->isDescendantNode(parentNode, labelControlFieldNode);
if (isDescendant) {
parentNode->addAttribute(L"labelledByContent", L"true");
}
}
}


// Clean up.
if(name)
SysFreeString(name);
Expand Down Expand Up @@ -1168,7 +1261,7 @@ void GeckoVBufBackend_t::render(VBufStorage_buffer_t* buffer, int docHandle, int
// This is the root node.
this->versionSpecificInit(pacc);
}
if(!this->fillVBuf(pacc, buffer, NULL, NULL)) {
if(!this->fillVBuf(pacc, buffer, nullptr, nullptr)) {
if(oldNode) {
LOG_DEBUGWARNING(L"No content rendered in update");
} else {
Expand Down
16 changes: 12 additions & 4 deletions nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@ This license can be found at:
#define VIRTUALBUFFER_BACKENDS_EXAMPLE_H

#include <vbufBase/backend.h>
#include <boost/optional.hpp>

class LabelInfo;

class GeckoVBufBackend_t: public VBufBackend_t {
private:

VBufStorage_fieldNode_t* fillVBuf(IAccessible2* pacc,
VBufStorage_buffer_t* buffer, VBufStorage_controlFieldNode_t* parentNode, VBufStorage_fieldNode_t* previousNode,
IAccessibleTable* paccTable=NULL, IAccessibleTable2* paccTable2=NULL, long tableID=0, const wchar_t* parentPresentationalRowNumber=NULL,
VBufStorage_fieldNode_t* fillVBuf(
IAccessible2* pacc,
VBufStorage_buffer_t* buffer,
VBufStorage_controlFieldNode_t* parentNode,
VBufStorage_fieldNode_t* previousNode,
IAccessibleTable* paccTable=NULL,
IAccessibleTable2* paccTable2=NULL,
long tableID=0, const wchar_t* parentPresentationalRowNumber=NULL,
bool ignoreInteractiveUnlabelledGraphics=false
);

Expand All @@ -34,7 +42,7 @@ class GeckoVBufBackend_t: public VBufBackend_t {
bool hasEncodedAccDescription;
std::wstring toolkitName;

bool isLabelVisible(IAccessible2* pacc2);
std::experimental::optional< LabelInfo > getLabelInfo(IAccessible2* pacc2);
CComPtr<IAccessible2> getLabelElement(IAccessible2_2* element);
CComPtr<IAccessible2> getSelectedItem(IAccessible2* container,
const std::map<std::wstring, std::wstring>& attribs);
Expand Down
1 change: 0 additions & 1 deletion nvdaHelper/vbufBase/storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ class VBufStorage_controlFieldNodeIdentifier_t {
bool operator<(const VBufStorage_controlFieldNodeIdentifier_t&) const;
bool operator!=(const VBufStorage_controlFieldNodeIdentifier_t&) const;
bool operator==(const VBufStorage_controlFieldNodeIdentifier_t&) const;

};

/**
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ For reference, the following run time dependencies are included in Git submodule

* [comtypes](https://github.com/enthought/comtypes), version 1.1.7
* [wxPython](https://www.wxpython.org/), version 4.0.3
* [eSpeak NG](https://github.com/espeak-ng/espeak-ng), commit 86e67a
* [eSpeak NG](https://github.com/espeak-ng/espeak-ng), version 1.51-dev commit ca65812a
* [Sonic](https://github.com/waywardgeek/sonic), commit 4f8c1d11
* [IAccessible2](https://wiki.linuxfoundation.org/accessibility/iaccessible2/start), commit 21bbb176
* [ConfigObj](https://github.com/DiffSK/configobj), commit 5b5de48
Expand Down
4 changes: 2 additions & 2 deletions source/COMRegistrationFixes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def registerServer(fileName,wow64=False):
"""
Registers the COM proxy dll with the given file name
Using regsvr32.
@ param fileName: the path to the dll
@param fileName: the path to the dll
@type fileName: str
@param wow64: If true then the 32 bit (wow64) version of regsvr32 will be used.
@type wow64: bool
Expand All @@ -40,7 +40,7 @@ def applyRegistryPatch(fileName,wow64=False):
"""
Applies the registry patch with the given file name
using regedit.
@ param fileName: the path to the dll
@param fileName: the path to the dll
@type fileName: str
"""
regedit=os.path.join(sysWow64 if wow64 else systemRoot,'regedit.exe')
Expand Down
2 changes: 1 addition & 1 deletion source/NVDAObjects/IAccessible/sysTreeView32.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import speech
import UIAHandler
from . import IAccessible
if UIAHandler.isUIAAvailable: from ..UIA import UIA
from ..UIA import UIA
from .. import NVDAObject
from logHandler import log
import watchdog
Expand Down
Loading

0 comments on commit 55acd1f

Please sign in to comment.