11/*
22This file is a part of the NVDA project.
33URL: http://www.nvda-project.org/
4- Copyright 2006-2015 NVDA contributers.
4+ Copyright 2006-2020 NV Access Limited, Google LLC, Leonard de Ruijter
55 This program is free software: you can redistribute it and/or modify
66 it under the terms of the GNU General Public License version 2.0, as published by
77 the Free Software Foundation.
@@ -20,7 +20,7 @@ This license can be found at:
2020#include < mshtmdid.h>
2121#include < common/log.h>
2222#include " mshtml.h"
23- #include < remote/nvdaController .h>
23+ #include < remote/nvdaControllerInternal .h>
2424#include < common/xml.h>
2525#include " node.h"
2626
@@ -124,7 +124,15 @@ class CDispatchChangeSink : public IDispatch {
124124 if (dispIdMember==DISPID_EVMETH_ONPROPERTYCHANGE||dispIdMember==DISPID_EVMETH_ONLOAD) {
125125 this ->storageNode ->backend ->invalidateSubtree (this ->storageNode );
126126 // Force the update to happen with no delay if we happen to be in a live region
127- if (this ->storageNode ->ariaLiveNode &&this ->storageNode ->ariaLiveNode !=this ->storageNode &&!this ->storageNode ->ariaLiveIsBusy &&(this ->storageNode ->ariaLiveIsTextRelevant ||this ->storageNode ->ariaLiveIsAdditionsRelevant )) {
127+ if (
128+ this ->storageNode ->ariaLiveNode
129+ && this ->storageNode ->ariaLiveNode != this ->storageNode
130+ && !this ->storageNode ->ariaLiveIsBusy
131+ && (
132+ this ->storageNode ->ariaLiveIsTextRelevant
133+ || this ->storageNode ->ariaLiveIsAdditionsRelevant
134+ )
135+ ) {
128136 this ->storageNode ->backend ->forceUpdate ();
129137 }
130138 return S_OK;
@@ -266,7 +274,15 @@ class CHTMLChangeSink : public IHTMLChangeSink {
266274 this ->storageNode ->backend ->invalidateSubtree (invalidNode);
267275 MshtmlVBufStorage_controlFieldNode_t* invalidMshtmlNode=(MshtmlVBufStorage_controlFieldNode_t*)invalidNode;
268276 // Force the update to happen with no delay if we happen to be in a live region
269- if (invalidMshtmlNode->ariaLiveNode &&invalidMshtmlNode->ariaLiveNode !=invalidMshtmlNode&&!invalidMshtmlNode->ariaLiveIsBusy &&(invalidMshtmlNode->ariaLiveIsTextRelevant ||invalidMshtmlNode->ariaLiveIsAdditionsRelevant )) {
277+ if (
278+ invalidMshtmlNode->ariaLiveNode
279+ && invalidMshtmlNode->ariaLiveNode != invalidMshtmlNode
280+ && !invalidMshtmlNode->ariaLiveIsBusy
281+ && (
282+ invalidMshtmlNode->ariaLiveIsTextRelevant
283+ || invalidMshtmlNode->ariaLiveIsAdditionsRelevant
284+ )
285+ ) {
270286 this ->storageNode ->backend ->forceUpdate ();
271287 }
272288 }
@@ -353,11 +369,18 @@ MshtmlVBufStorage_controlFieldNode_t::~MshtmlVBufStorage_controlFieldNode_t() {
353369}
354370
355371void MshtmlVBufStorage_controlFieldNode_t::preProcessLiveRegion (const MshtmlVBufStorage_controlFieldNode_t* parent, const std::map<std::wstring,std::wstring>& attribsMap) {
356- auto i=attribsMap.find (L" HTMLAttrib::aria-live" );
372+ auto i=attribsMap.find (L" HTMLAttrib::aria-live" );
357373 if (i!=attribsMap.end ()&&!i->second .empty ()) {
358- this ->ariaLiveNode =((i->second .compare (L" polite" )==0 )||(i->second .compare (L" assertive" )==0 ))?this :NULL ;
374+ bool isAriaLiveEnabled = i->second == L" polite" || i->second == L" assertive" ;
375+ this ->ariaLiveNode = isAriaLiveEnabled ? this : nullptr ;
376+ this ->ariaLivePoliteness = i->second ;
359377 } else {
360- this ->ariaLiveNode =parent?parent->ariaLiveNode :NULL ;
378+ this ->ariaLiveNode = parent? parent->ariaLiveNode : nullptr ;
379+ if (this ->ariaLiveNode ) {
380+ this ->ariaLivePoliteness = this ->ariaLiveNode ->ariaLivePoliteness ;
381+ } else {
382+ this ->ariaLivePoliteness = nullptr ;
383+ }
361384 }
362385 i=attribsMap.find (L" HTMLAttrib::aria-relevant" );
363386 if (i!=attribsMap.end ()&&!i->second .empty ()) {
@@ -384,13 +407,13 @@ void MshtmlVBufStorage_controlFieldNode_t::preProcessLiveRegion(const MshtmlVBuf
384407 } else {
385408 this ->ariaLiveAtomicNode =parent?parent->ariaLiveAtomicNode :NULL ;
386409 }
387- // LOG_INFO (L"preProcessLiveRegion: ariaLiveNode "<<ariaLiveNode<<L", ariaLiveIsTextRelevant "<<ariaLiveIsTextRelevant<<L", ariaLiveIsAdditionsRelevant "<<ariaLiveIsAdditionsRelevant<<L", ariaLiveIsBusy "<<ariaLiveIsBusy<<L", ariaLiveAtomicNode "<<ariaLiveAtomicNode);
410+ LOG_DEBUG (L" preProcessLiveRegion: ariaLiveNode " <<ariaLiveNode<<L" , ariaLiveIsTextRelevant " <<ariaLiveIsTextRelevant<<L" , ariaLiveIsAdditionsRelevant " <<ariaLiveIsAdditionsRelevant<<L" , ariaLiveIsBusy " <<ariaLiveIsBusy<<L" , ariaLiveAtomicNode " <<ariaLiveAtomicNode);
388411}
389412
390- void MshtmlVBufStorage_controlFieldNode_t::reportLiveText (wstring& text) {
413+ void MshtmlVBufStorage_controlFieldNode_t::reportLiveText (wstring& text, wstring& politeness ) {
391414 for (auto c: text) {
392415 if (!iswspace (c)) {
393- nvdaController_speakText (text.c_str ());
416+ nvdaControllerInternal_reportLiveRegion (text. c_str (), politeness .c_str ());
394417 break ;
395418 }
396419 }
@@ -399,21 +422,23 @@ void MshtmlVBufStorage_controlFieldNode_t::reportLiveText(wstring& text) {
399422bool isNodeInLiveRegion (VBufStorage_fieldNode_t* node) {
400423 if (!node) return false ;
401424 if (node->getFirstChild ()) {
402- return ((MshtmlVBufStorage_controlFieldNode_t*)node)->ariaLiveNode != NULL ;
425+ return ((MshtmlVBufStorage_controlFieldNode_t*)node)->ariaLiveNode != nullptr ;
403426 }
404427 return true ;
405428}
406429
407430void MshtmlVBufStorage_controlFieldNode_t::reportLiveAddition () {
408431 wstring text; // =(this->ariaLiveAtomicNode==this)?L"atomic: ":L"additions: ";
409432 this ->getTextInRange (0 ,this ->getLength (),text,false ,isNodeInLiveRegion);
410- this ->reportLiveText (text);
433+ this ->reportLiveText (text, this -> ariaLivePoliteness );
411434}
412435
413436void MshtmlVBufStorage_controlFieldNode_t::postProcessLiveRegion (VBufStorage_controlFieldNode_t* oldNode, set<VBufStorage_controlFieldNode_t*>& atomicNodes) {
414- // LOG_INFO(L"preProcessLiveRegion: ariaLiveNode "<<ariaLiveNode<<L", ariaLiveIsTextRelevant "<<ariaLiveIsTextRelevant<<L", ariaLiveIsAdditionsRelevant "<<ariaLiveIsAdditionsRelevant<<L", ariaLiveIsBusy "<<ariaLiveIsBusy<<L", ariaLiveAtomicNode "<<ariaLiveAtomicNode);
415- if (!this ->ariaLiveNode ||this ->ariaLiveIsBusy ) return ;
416- bool reportNode=!oldNode&&this ->ariaLiveIsAdditionsRelevant &&this ->ariaLiveNode !=this ;
437+ LOG_DEBUG (L" postProcessLiveRegion: ariaLiveNode " <<ariaLiveNode<<L" , ariaLiveIsTextRelevant " <<ariaLiveIsTextRelevant<<L" , ariaLiveIsAdditionsRelevant " <<ariaLiveIsAdditionsRelevant<<L" , ariaLiveIsBusy " <<ariaLiveIsBusy<<L" , ariaLiveAtomicNode " <<ariaLiveAtomicNode);
438+ if (!this ->ariaLiveNode || this ->ariaLiveIsBusy ) {
439+ return ;
440+ }
441+ bool reportNode=!oldNode && this ->ariaLiveIsAdditionsRelevant && this ->ariaLiveNode != this ;
417442 wstring newChildrenText;
418443 if (!reportNode&&oldNode&&ariaLiveIsTextRelevant) {
419444 // Find the first new text child
@@ -469,7 +494,7 @@ void MshtmlVBufStorage_controlFieldNode_t::postProcessLiveRegion(VBufStorage_con
469494 } else if (reportNode) {
470495 this ->reportLiveAddition ();
471496 } else if (!newChildrenText.empty ()) {
472- this ->reportLiveText (newChildrenText);
497+ this ->reportLiveText (newChildrenText, this -> ariaLivePoliteness );
473498 }
474499}
475500
0 commit comments