Skip to content

Commit

Permalink
Re-introduce new live region announcement implementation for mshtml (PR
Browse files Browse the repository at this point in the history
#11875)

This reverts (the reversion) commit 53cecfd.

* Set to an empty string instead of trying to construct a string from a nullptr
  • Loading branch information
LeonarddeR committed Nov 30, 2020
1 parent 559ce07 commit 874230a
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 24 deletions.
62 changes: 42 additions & 20 deletions nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
Copyright 2006-2015 NVDA contributers.
Copyright 2006-2020 NV Access Limited, Google LLC, Leonard de Ruijter
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as published by
the Free Software Foundation.
Expand All @@ -20,7 +20,7 @@ This license can be found at:
#include <mshtmdid.h>
#include <common/log.h>
#include "mshtml.h"
#include <remote/nvdaController.h>
#include <remote/nvdaControllerInternal.h>
#include <common/xml.h>
#include "node.h"

Expand Down Expand Up @@ -124,7 +124,15 @@ class CDispatchChangeSink : public IDispatch {
if(dispIdMember==DISPID_EVMETH_ONPROPERTYCHANGE||dispIdMember==DISPID_EVMETH_ONLOAD) {
this->storageNode->backend->invalidateSubtree(this->storageNode);
// Force the update to happen with no delay if we happen to be in a live region
if(this->storageNode->ariaLiveNode&&this->storageNode->ariaLiveNode!=this->storageNode&&!this->storageNode->ariaLiveIsBusy&&(this->storageNode->ariaLiveIsTextRelevant||this->storageNode->ariaLiveIsAdditionsRelevant)) {
if (
this->storageNode->ariaLiveNode
&& this->storageNode->ariaLiveNode != this->storageNode
&& !this->storageNode->ariaLiveIsBusy
&& (
this->storageNode->ariaLiveIsTextRelevant
|| this->storageNode->ariaLiveIsAdditionsRelevant
)
) {
this->storageNode->backend->forceUpdate();
}
return S_OK;
Expand Down Expand Up @@ -266,7 +274,15 @@ class CHTMLChangeSink : public IHTMLChangeSink {
this->storageNode->backend->invalidateSubtree(invalidNode);
MshtmlVBufStorage_controlFieldNode_t* invalidMshtmlNode=(MshtmlVBufStorage_controlFieldNode_t*)invalidNode;
// Force the update to happen with no delay if we happen to be in a live region
if(invalidMshtmlNode->ariaLiveNode&&invalidMshtmlNode->ariaLiveNode!=invalidMshtmlNode&&!invalidMshtmlNode->ariaLiveIsBusy&&(invalidMshtmlNode->ariaLiveIsTextRelevant||invalidMshtmlNode->ariaLiveIsAdditionsRelevant)) {
if (
invalidMshtmlNode->ariaLiveNode
&& invalidMshtmlNode->ariaLiveNode != invalidMshtmlNode
&& !invalidMshtmlNode->ariaLiveIsBusy
&& (
invalidMshtmlNode->ariaLiveIsTextRelevant
|| invalidMshtmlNode->ariaLiveIsAdditionsRelevant
)
) {
this->storageNode->backend->forceUpdate();
}
}
Expand Down Expand Up @@ -353,11 +369,18 @@ MshtmlVBufStorage_controlFieldNode_t::~MshtmlVBufStorage_controlFieldNode_t() {
}

void MshtmlVBufStorage_controlFieldNode_t::preProcessLiveRegion(const MshtmlVBufStorage_controlFieldNode_t* parent, const std::map<std::wstring,std::wstring>& attribsMap) {
auto i=attribsMap.find(L"HTMLAttrib::aria-live");
auto i=attribsMap.find(L"HTMLAttrib::aria-live");
if(i!=attribsMap.end()&&!i->second.empty()) {
this->ariaLiveNode=((i->second.compare(L"polite")==0)||(i->second.compare(L"assertive")==0))?this:NULL;
bool isAriaLiveEnabled = i->second == L"polite" || i->second == L"assertive";
this->ariaLiveNode = isAriaLiveEnabled ? this : nullptr;
this->ariaLivePoliteness = i->second;
} else {
this->ariaLiveNode=parent?parent->ariaLiveNode:NULL;
this->ariaLiveNode = parent? parent->ariaLiveNode : nullptr;
if (this->ariaLiveNode) {
this->ariaLivePoliteness = this->ariaLiveNode->ariaLivePoliteness;
} else {
this->ariaLivePoliteness = L"";
}
}
i=attribsMap.find(L"HTMLAttrib::aria-relevant");
if(i!=attribsMap.end()&&!i->second.empty()) {
Expand All @@ -384,36 +407,35 @@ void MshtmlVBufStorage_controlFieldNode_t::preProcessLiveRegion(const MshtmlVBuf
} else {
this->ariaLiveAtomicNode=parent?parent->ariaLiveAtomicNode:NULL;
}
//LOG_INFO(L"preProcessLiveRegion: ariaLiveNode "<<ariaLiveNode<<L", ariaLiveIsTextRelevant "<<ariaLiveIsTextRelevant<<L", ariaLiveIsAdditionsRelevant "<<ariaLiveIsAdditionsRelevant<<L", ariaLiveIsBusy "<<ariaLiveIsBusy<<L", ariaLiveAtomicNode "<<ariaLiveAtomicNode);
LOG_DEBUG(L"preProcessLiveRegion: ariaLiveNode "<<ariaLiveNode<<L", ariaLiveIsTextRelevant "<<ariaLiveIsTextRelevant<<L", ariaLiveIsAdditionsRelevant "<<ariaLiveIsAdditionsRelevant<<L", ariaLiveIsBusy "<<ariaLiveIsBusy<<L", ariaLiveAtomicNode "<<ariaLiveAtomicNode);
}

void MshtmlVBufStorage_controlFieldNode_t::reportLiveText(wstring& text) {
for(auto c: text) {
if(!iswspace(c)) {
nvdaController_speakText(text.c_str());
break;
}
void MshtmlVBufStorage_controlFieldNode_t::reportLiveText(wstring& text, wstring& politeness) {
if(!all_of(text.cbegin(), text.cend(), iswspace)) {
nvdaControllerInternal_reportLiveRegion(text.c_str(), politeness.c_str());
}
}

bool isNodeInLiveRegion(VBufStorage_fieldNode_t* node) {
if(!node) return false;
if(node->getFirstChild()) {
return ((MshtmlVBufStorage_controlFieldNode_t*)node)->ariaLiveNode!=NULL;
return ((MshtmlVBufStorage_controlFieldNode_t*)node)->ariaLiveNode != nullptr;
}
return true;
}

void MshtmlVBufStorage_controlFieldNode_t::reportLiveAddition() {
wstring text; //=(this->ariaLiveAtomicNode==this)?L"atomic: ":L"additions: ";
this->getTextInRange(0,this->getLength(),text,false,isNodeInLiveRegion);
this->reportLiveText(text);
this->reportLiveText(text, this->ariaLivePoliteness);
}

void MshtmlVBufStorage_controlFieldNode_t::postProcessLiveRegion(VBufStorage_controlFieldNode_t* oldNode, set<VBufStorage_controlFieldNode_t*>& atomicNodes) {
//LOG_INFO(L"preProcessLiveRegion: ariaLiveNode "<<ariaLiveNode<<L", ariaLiveIsTextRelevant "<<ariaLiveIsTextRelevant<<L", ariaLiveIsAdditionsRelevant "<<ariaLiveIsAdditionsRelevant<<L", ariaLiveIsBusy "<<ariaLiveIsBusy<<L", ariaLiveAtomicNode "<<ariaLiveAtomicNode);
if(!this->ariaLiveNode||this->ariaLiveIsBusy) return;
bool reportNode=!oldNode&&this->ariaLiveIsAdditionsRelevant&&this->ariaLiveNode!=this;
LOG_DEBUG(L"postProcessLiveRegion: ariaLiveNode "<<ariaLiveNode<<L", ariaLiveIsTextRelevant "<<ariaLiveIsTextRelevant<<L", ariaLiveIsAdditionsRelevant "<<ariaLiveIsAdditionsRelevant<<L", ariaLiveIsBusy "<<ariaLiveIsBusy<<L", ariaLiveAtomicNode "<<ariaLiveAtomicNode);
if (!this->ariaLiveNode || this->ariaLiveIsBusy) {
return;
}
bool reportNode=!oldNode && this->ariaLiveIsAdditionsRelevant && this->ariaLiveNode != this;
wstring newChildrenText;
if(!reportNode&&oldNode&&ariaLiveIsTextRelevant) {
// Find the first new text child
Expand Down Expand Up @@ -469,7 +491,7 @@ void MshtmlVBufStorage_controlFieldNode_t::postProcessLiveRegion(VBufStorage_con
} else if(reportNode) {
this->reportLiveAddition();
} else if(!newChildrenText.empty()) {
this->reportLiveText(newChildrenText);
this->reportLiveText(newChildrenText, this->ariaLivePoliteness);
}
}

Expand Down
7 changes: 4 additions & 3 deletions nvdaHelper/vbufBackends/mshtml/node.h
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
Copyright 2006-2015 NVDA contributers.
Copyright 2006-2020 NV Access Limited, Google LLC, Leonard de Ruijter
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as published by
the Free Software Foundation.
Expand Down Expand Up @@ -31,13 +31,14 @@ class MshtmlVBufStorage_controlFieldNode_t : public VBufStorage_controlFieldNode
IHTMLChangeSink* pHTMLChangeSink;
DWORD HTMLChangeSinkCookey;
std::wstring language;
VBufStorage_controlFieldNode_t* ariaLiveNode;
MshtmlVBufStorage_controlFieldNode_t* ariaLiveNode;
std::wstring ariaLivePoliteness;
unsigned int formatState;
bool ariaLiveIsTextRelevant;
bool ariaLiveIsAdditionsRelevant;
bool ariaLiveIsBusy;
VBufStorage_controlFieldNode_t* ariaLiveAtomicNode;
void reportLiveText(std::wstring& text);
void reportLiveText(std::wstring& text, std::wstring& politeness);
void reportLiveAddition();
void preProcessLiveRegion(const MshtmlVBufStorage_controlFieldNode_t* parent, const std::map<std::wstring,std::wstring>& attribsMap);
void postProcessLiveRegion(VBufStorage_controlFieldNode_t* oldNode, std::set<VBufStorage_controlFieldNode_t*>& atomicNodes);
Expand Down
2 changes: 1 addition & 1 deletion user_docs/en/changes.t2t
Expand Up @@ -24,7 +24,7 @@ What's New in NVDA
- For HIMS braille displays F3 has been remapped to Space + dots 148. (#11710)
- Improvements to the UX of the "braille message timeout" and "Show messages indefinitely" options. (#11602)
- In web browsers and other applications that support browse mode, the Elements List dialog (NVDA+F7) can now be invoked when in focus mode. (#10453)
- In Mozilla Firefox and Chromium based browsers, updates to ARIA live regions are now suppressed when reporting of dynamic content changes is disabled. (#9077)
- Updates to ARIA live regions are now suppressed when reporting of dynamic content changes is disabled. (#9077)
- NVDA will now report "Copied to clipboard" before the copied text. (#6757)
- Presentation of graphical view table in disk management has been improved. (#10048)
- Labels for controls are now disabled (greyed out) when the control is disabled. (#11809)
Expand Down

0 comments on commit 874230a

Please sign in to comment.