mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 626660 - cache rendered text on a11y side, r=davidb, f=marcoz, a=betaN
This commit is contained in:
parent
86117cb12b
commit
e32b030dea
@ -279,7 +279,7 @@ AccStateChangeEvent::CreateXPCOMObject()
|
||||
// XXX revisit this when coalescence is faster (eCoalesceFromSameSubtree)
|
||||
AccTextChangeEvent::
|
||||
AccTextChangeEvent(nsAccessible* aAccessible, PRInt32 aStart,
|
||||
nsAString& aModifiedText, PRBool aIsInserted,
|
||||
const nsAString& aModifiedText, PRBool aIsInserted,
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
: AccEvent(aIsInserted ?
|
||||
static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_INSERTED) :
|
||||
|
@ -206,7 +206,7 @@ class AccTextChangeEvent: public AccEvent
|
||||
{
|
||||
public:
|
||||
AccTextChangeEvent(nsAccessible* aAccessible, PRInt32 aStart,
|
||||
nsAString& aModifiedText, PRBool aIsInserted,
|
||||
const nsAString& aModifiedText, PRBool aIsInserted,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
// AccEvent
|
||||
|
@ -36,16 +36,15 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsEventShell.h"
|
||||
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsDocAccessible.h"
|
||||
|
||||
#include "NotificationController.h"
|
||||
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsDocAccessible.h"
|
||||
#include "nsEventShell.h"
|
||||
#include "nsTextAccessible.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NotificationCollector
|
||||
@ -574,6 +573,290 @@ NotificationController::CreateTextChangeEventFor(AccMutationEvent* aEvent)
|
||||
aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Notification controller: text leaf accessible text update
|
||||
|
||||
/**
|
||||
* Used to find a difference between old and new text and fire text change
|
||||
* events.
|
||||
*/
|
||||
class TextUpdater
|
||||
{
|
||||
public:
|
||||
TextUpdater(nsDocAccessible* aDocument, nsTextAccessible* aTextLeaf) :
|
||||
mDocument(aDocument), mTextLeaf(aTextLeaf) { }
|
||||
~TextUpdater() { mDocument = nsnull; mTextLeaf = nsnull; }
|
||||
|
||||
/**
|
||||
* Update text of the text leaf accessible, fire text change events for its
|
||||
* container hypertext accessible.
|
||||
*/
|
||||
void Run(const nsAString& aNewText);
|
||||
|
||||
private:
|
||||
TextUpdater();
|
||||
TextUpdater(const TextUpdater&);
|
||||
TextUpdater& operator = (const TextUpdater&);
|
||||
|
||||
/**
|
||||
* Fire text change events based on difference between strings.
|
||||
*/
|
||||
void FindDiffNFireEvents(const nsDependentSubstring& aStr1,
|
||||
const nsDependentSubstring& aStr2,
|
||||
PRUint32** aMatrix,
|
||||
PRUint32 aStartOffset);
|
||||
|
||||
/**
|
||||
* Change type used to describe the diff between strings.
|
||||
*/
|
||||
enum ChangeType {
|
||||
eNoChange,
|
||||
eInsertion,
|
||||
eRemoval,
|
||||
eSubstitution
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to fire text change events.
|
||||
*/
|
||||
inline void MayFireEvent(nsAString* aInsertedText, nsAString* aRemovedText,
|
||||
PRUint32 aOffset, ChangeType* aChange)
|
||||
{
|
||||
if (*aChange == eNoChange)
|
||||
return;
|
||||
|
||||
if (*aChange == eRemoval || *aChange == eSubstitution) {
|
||||
FireEvent(*aRemovedText, aOffset, PR_FALSE);
|
||||
aRemovedText->Truncate();
|
||||
}
|
||||
|
||||
if (*aChange == eInsertion || *aChange == eSubstitution) {
|
||||
FireEvent(*aInsertedText, aOffset, PR_TRUE);
|
||||
aInsertedText->Truncate();
|
||||
}
|
||||
|
||||
*aChange = eNoChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire text change event.
|
||||
*/
|
||||
void FireEvent(const nsAString& aModText, PRUint32 aOffset, PRBool aType);
|
||||
|
||||
private:
|
||||
nsDocAccessible* mDocument;
|
||||
nsTextAccessible* mTextLeaf;
|
||||
};
|
||||
|
||||
void
|
||||
TextUpdater::Run(const nsAString& aNewText)
|
||||
{
|
||||
NS_ASSERTION(mTextLeaf, "No text leaf accessible?");
|
||||
|
||||
const nsString& oldText = mTextLeaf->Text();
|
||||
PRUint32 oldLen = oldText.Length(), newLen = aNewText.Length();
|
||||
PRUint32 minLen = oldLen < newLen ? oldLen : newLen;
|
||||
|
||||
// Skip coinciding begin substrings.
|
||||
PRUint32 skipIdx = 0;
|
||||
for (; skipIdx < minLen; skipIdx++) {
|
||||
if (aNewText[skipIdx] != oldText[skipIdx])
|
||||
break;
|
||||
}
|
||||
|
||||
// No change, text append or removal to/from the end.
|
||||
if (skipIdx == minLen) {
|
||||
if (oldLen == newLen)
|
||||
return;
|
||||
|
||||
// If text has been appended to the end, fire text inserted event.
|
||||
if (oldLen < newLen) {
|
||||
FireEvent(Substring(aNewText, oldLen), oldLen, PR_TRUE);
|
||||
mTextLeaf->SetText(aNewText);
|
||||
return;
|
||||
}
|
||||
|
||||
// Text has been removed from the end, fire text removed event.
|
||||
FireEvent(Substring(oldText, newLen), newLen, PR_FALSE);
|
||||
mTextLeaf->SetText(aNewText);
|
||||
return;
|
||||
}
|
||||
|
||||
// Trim coinciding substrings from the end.
|
||||
PRUint32 endIdx = minLen;
|
||||
if (oldLen < newLen) {
|
||||
PRUint32 delta = newLen - oldLen;
|
||||
for (; endIdx > skipIdx; endIdx--) {
|
||||
if (aNewText[endIdx + delta] != oldText[endIdx])
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
PRUint32 delta = oldLen - newLen;
|
||||
for (; endIdx > skipIdx; endIdx--) {
|
||||
if (aNewText[endIdx] != oldText[endIdx + delta])
|
||||
break;
|
||||
}
|
||||
}
|
||||
PRUint32 oldEndIdx = oldLen - minLen + endIdx;
|
||||
PRUint32 newEndIdx = newLen - minLen + endIdx;
|
||||
|
||||
// Find the difference starting from start character, we can skip initial and
|
||||
// final coinciding characters since they don't affect on the Levenshtein
|
||||
// distance.
|
||||
|
||||
const nsDependentSubstring& str1 =
|
||||
Substring(oldText, skipIdx, oldEndIdx - skipIdx);
|
||||
const nsDependentSubstring& str2 =
|
||||
Substring(aNewText, skipIdx, newEndIdx - skipIdx);
|
||||
|
||||
// Compute the matrix.
|
||||
PRUint32 len1 = str1.Length() + 1, len2 = str2.Length() + 1;
|
||||
|
||||
PRUint32** matrix = new PRUint32*[len1];
|
||||
for (PRUint32 i = 0; i < len1; i++)
|
||||
matrix[i] = new PRUint32[len2];
|
||||
|
||||
matrix[0][0] = 0;
|
||||
|
||||
for (PRUint32 i = 1; i < len1; i++)
|
||||
matrix[i][0] = i;
|
||||
|
||||
for (PRUint32 j = 1; j < len2; j++)
|
||||
matrix[0][j] = j;
|
||||
|
||||
for (PRUint32 i = 1; i < len1; i++) {
|
||||
for (PRUint32 j = 1; j < len2; j++) {
|
||||
if (str1[i - 1] != str2[j - 1]) {
|
||||
PRUint32 left = matrix[i - 1][j];
|
||||
PRUint32 up = matrix[i][j - 1];
|
||||
|
||||
PRUint32 upleft = matrix[i - 1][j - 1];
|
||||
matrix[i][j] =
|
||||
(left < up ? (upleft < left ? upleft : left) :
|
||||
(upleft < up ? upleft : up)) + 1;
|
||||
} else {
|
||||
matrix[i][j] = matrix[i - 1][j - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FindDiffNFireEvents(str1, str2, matrix, skipIdx);
|
||||
|
||||
for (PRUint32 i = 0; i < len1; i++)
|
||||
delete[] matrix[i];
|
||||
delete[] matrix;
|
||||
|
||||
mTextLeaf->SetText(aNewText);
|
||||
}
|
||||
|
||||
void
|
||||
TextUpdater::FindDiffNFireEvents(const nsDependentSubstring& aStr1,
|
||||
const nsDependentSubstring& aStr2,
|
||||
PRUint32** aMatrix,
|
||||
PRUint32 aStartOffset)
|
||||
{
|
||||
// Find the difference.
|
||||
ChangeType change = eNoChange;
|
||||
nsAutoString insertedText;
|
||||
nsAutoString removedText;
|
||||
PRUint32 offset = 0;
|
||||
|
||||
PRInt32 i = aStr1.Length(), j = aStr2.Length();
|
||||
while (i >= 0 && j >= 0) {
|
||||
if (aMatrix[i][j] == 0) {
|
||||
MayFireEvent(&insertedText, &removedText, offset + aStartOffset, &change);
|
||||
return;
|
||||
}
|
||||
|
||||
// move up left
|
||||
if (i >= 1 && j >= 1) {
|
||||
// no change
|
||||
if (aStr1[i - 1] == aStr2[j - 1]) {
|
||||
MayFireEvent(&insertedText, &removedText, offset + aStartOffset, &change);
|
||||
|
||||
i--; j--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// substitution
|
||||
if (aMatrix[i][j] == aMatrix[i - 1][j - 1] + 1) {
|
||||
if (change != eSubstitution)
|
||||
MayFireEvent(&insertedText, &removedText, offset + aStartOffset, &change);
|
||||
|
||||
offset = j - 1;
|
||||
insertedText.Append(aStr1[i - 1]);
|
||||
removedText.Append(aStr2[offset]);
|
||||
change = eSubstitution;
|
||||
|
||||
i--; j--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// move up, insertion
|
||||
if (j >= 1 && aMatrix[i][j] == aMatrix[i][j - 1] + 1) {
|
||||
if (change != eInsertion)
|
||||
MayFireEvent(&insertedText, &removedText, offset + aStartOffset, &change);
|
||||
|
||||
offset = j - 1;
|
||||
insertedText.Insert(aStr2[offset], 0);
|
||||
change = eInsertion;
|
||||
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// move left, removal
|
||||
if (i >= 1 && aMatrix[i][j] == aMatrix[i - 1][j] + 1) {
|
||||
if (change != eRemoval) {
|
||||
MayFireEvent(&insertedText, &removedText, offset + aStartOffset, &change);
|
||||
|
||||
offset = j;
|
||||
}
|
||||
|
||||
removedText.Insert(aStr1[i - 1], 0);
|
||||
change = eRemoval;
|
||||
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Huh?");
|
||||
return;
|
||||
}
|
||||
|
||||
MayFireEvent(&insertedText, &removedText, offset + aStartOffset, &change);
|
||||
}
|
||||
|
||||
void
|
||||
TextUpdater::FireEvent(const nsAString& aModText, PRUint32 aOffset,
|
||||
PRBool aIsInserted)
|
||||
{
|
||||
nsAccessible* parent = mTextLeaf->GetParent();
|
||||
NS_ASSERTION(parent, "No parent for text leaf!");
|
||||
|
||||
nsHyperTextAccessible* hyperText = parent->AsHyperText();
|
||||
NS_ASSERTION(hyperText, "Text leaf parnet is not hyper text!");
|
||||
|
||||
PRInt32 textLeafOffset = hyperText->GetChildOffset(mTextLeaf, PR_TRUE);
|
||||
NS_ASSERTION(textLeafOffset != -1,
|
||||
"Text leaf hasn't offset within hyper text!");
|
||||
|
||||
// Fire text change event.
|
||||
nsRefPtr<AccEvent> textChangeEvent =
|
||||
new AccTextChangeEvent(hyperText, textLeafOffset + aOffset, aModText,
|
||||
aIsInserted);
|
||||
mDocument->FireDelayedAccessibleEvent(textChangeEvent);
|
||||
|
||||
// Fire value change event.
|
||||
if (hyperText->Role() == nsIAccessibleRole::ROLE_ENTRY) {
|
||||
nsRefPtr<AccEvent> valueChangeEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, hyperText,
|
||||
eAutoDetect, AccEvent::eRemoveDupes);
|
||||
mDocument->FireDelayedAccessibleEvent(valueChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
NotificationController::TextEnumerator(nsCOMPtrHashKey<nsIContent>* aEntry,
|
||||
void* aUserArg)
|
||||
@ -601,12 +884,12 @@ NotificationController::TextEnumerator(nsCOMPtrHashKey<nsIContent>* aEntry,
|
||||
nsIContent* containerElm = containerNode->IsElement() ?
|
||||
containerNode->AsElement() : nsnull;
|
||||
|
||||
nsAutoString renderedText;
|
||||
textFrame->GetRenderedText(&renderedText);
|
||||
nsAutoString text;
|
||||
textFrame->GetRenderedText(&text);
|
||||
|
||||
// Remove text accessible if rendered text is empty.
|
||||
if (textAcc) {
|
||||
if (renderedText.IsEmpty()) {
|
||||
if (text.IsEmpty()) {
|
||||
#ifdef DEBUG_NOTIFICATIONS
|
||||
PRUint32 index = containerNode->IndexOf(textNode);
|
||||
|
||||
@ -624,13 +907,36 @@ NotificationController::TextEnumerator(nsCOMPtrHashKey<nsIContent>* aEntry,
|
||||
#endif
|
||||
|
||||
document->ContentRemoved(containerElm, textNode);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// Update text of the accessible and fire text change events.
|
||||
#ifdef DEBUG_TEXTCHANGE
|
||||
PRUint32 index = containerNode->IndexOf(textNode);
|
||||
|
||||
nsCAutoString tag;
|
||||
nsCAutoString id;
|
||||
if (containerElm) {
|
||||
containerElm->Tag()->ToUTF8String(tag);
|
||||
nsIAtom* atomid = containerElm->GetID();
|
||||
if (atomid)
|
||||
atomid->ToUTF8String(id);
|
||||
}
|
||||
|
||||
printf("\ntext may be changed: container: %s@id='%s', index in container: %d, old text '%s', new text: '%s'\n\n",
|
||||
tag.get(), id.get(), index,
|
||||
NS_ConvertUTF16toUTF8(textAcc->AsTextLeaf()->Text()).get(),
|
||||
NS_ConvertUTF16toUTF8(text).get());
|
||||
#endif
|
||||
|
||||
TextUpdater updater(document, textAcc->AsTextLeaf());
|
||||
updater.Run(text);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// Append an accessible if rendered text is not empty.
|
||||
if (!renderedText.IsEmpty()) {
|
||||
if (!text.IsEmpty()) {
|
||||
#ifdef DEBUG_NOTIFICATIONS
|
||||
PRUint32 index = containerNode->IndexOf(textNode);
|
||||
|
||||
@ -722,3 +1028,4 @@ NotificationController::ContentInsertion::Process()
|
||||
mContainer = nsnull;
|
||||
mInsertedContent.Clear();
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ class nsIContent;
|
||||
|
||||
#ifdef DEBUG_NOTIFICATIONS
|
||||
#define DEBUG_CONTENTMUTATION
|
||||
#define DEBUG_TEXTCHANGE
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -913,27 +913,24 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
|
||||
// Attempt to create an accessible based on what we know.
|
||||
nsRefPtr<nsAccessible> newAcc;
|
||||
if (content->IsNodeOfType(nsINode::eTEXT)) {
|
||||
// --- Create HTML for visible text frames ---
|
||||
nsIFrame* f = weakFrame.GetFrame();
|
||||
if (f && f->IsEmpty()) {
|
||||
nsAutoString renderedWhitespace;
|
||||
f->GetRenderedText(&renderedWhitespace, nsnull, nsnull, 0, 1);
|
||||
if (renderedWhitespace.IsEmpty()) {
|
||||
// Really empty -- nothing is rendered
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
if (weakFrame.IsAlive()) {
|
||||
newAcc = weakFrame.GetFrame()->CreateAccessible();
|
||||
if (docAcc->BindToDocument(newAcc, nsnull))
|
||||
return newAcc.forget();
|
||||
// Create accessible for visible text frames.
|
||||
if (content->IsNodeOfType(nsINode::eTEXT)) {
|
||||
nsAutoString text;
|
||||
weakFrame->GetRenderedText(&text, nsnull, nsnull, 0, PR_UINT32_MAX);
|
||||
if (text.IsEmpty()) {
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
newAcc = weakFrame->CreateAccessible();
|
||||
if (docAcc->BindToDocument(newAcc, nsnull)) {
|
||||
newAcc->AsTextLeaf()->SetText(text);
|
||||
return newAcc.forget();
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
@ -1248,14 +1248,12 @@ void nsDocAccessible::CharacterDataWillChange(nsIDocument *aDocument,
|
||||
nsIContent* aContent,
|
||||
CharacterDataChangeInfo* aInfo)
|
||||
{
|
||||
FireTextChangeEventForText(aContent, aInfo, PR_FALSE);
|
||||
}
|
||||
|
||||
void nsDocAccessible::CharacterDataChanged(nsIDocument *aDocument,
|
||||
nsIContent* aContent,
|
||||
CharacterDataChangeInfo* aInfo)
|
||||
{
|
||||
FireTextChangeEventForText(aContent, aInfo, PR_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1684,81 +1682,6 @@ nsDocAccessible::UpdateAccessibleOnAttrChange(dom::Element* aElement,
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocAccessible::FireValueChangeForTextFields(nsAccessible *aAccessible)
|
||||
{
|
||||
if (aAccessible->Role() != nsIAccessibleRole::ROLE_ENTRY)
|
||||
return;
|
||||
|
||||
// Dependent value change event for text changes in textfields
|
||||
nsRefPtr<AccEvent> valueChangeEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible,
|
||||
eAutoDetect, AccEvent::eRemoveDupes);
|
||||
FireDelayedAccessibleEvent(valueChangeEvent);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocAccessible::FireTextChangeEventForText(nsIContent *aContent,
|
||||
CharacterDataChangeInfo* aInfo,
|
||||
PRBool aIsInserted)
|
||||
{
|
||||
if (!IsContentLoaded())
|
||||
return;
|
||||
|
||||
PRInt32 contentOffset = aInfo->mChangeStart;
|
||||
PRUint32 contentLength = aIsInserted ?
|
||||
aInfo->mReplaceLength: // text has been added
|
||||
aInfo->mChangeEnd - contentOffset; // text has been removed
|
||||
|
||||
if (contentLength == 0)
|
||||
return;
|
||||
|
||||
nsAccessible *accessible = GetAccService()->GetAccessible(aContent);
|
||||
if (!accessible)
|
||||
return;
|
||||
|
||||
nsAccessible* parent = accessible->GetParent();
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
nsHyperTextAccessible* textAccessible = parent->AsHyperText();
|
||||
if (!textAccessible)
|
||||
return;
|
||||
|
||||
// Get offset within hypertext accessible and invalidate cached offsets after
|
||||
// this child accessible.
|
||||
PRInt32 offset = textAccessible->GetChildOffset(accessible, PR_TRUE);
|
||||
|
||||
// Get added or removed text.
|
||||
nsIFrame* frame = aContent->GetPrimaryFrame();
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
PRUint32 textOffset = 0;
|
||||
nsresult rv = textAccessible->ContentToRenderedOffset(frame, contentOffset,
|
||||
&textOffset);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
nsAutoString text;
|
||||
rv = accessible->AppendTextTo(text, textOffset, contentLength);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
if (text.IsEmpty())
|
||||
return;
|
||||
|
||||
// Normally we only fire delayed events created from the node, not an
|
||||
// accessible object. See the AccTextChangeEvent constructor for details
|
||||
// about this exceptional case.
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccTextChangeEvent(textAccessible, offset + textOffset, text,
|
||||
aIsInserted);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
|
||||
FireValueChangeForTextFields(textAccessible);
|
||||
}
|
||||
|
||||
// nsDocAccessible public member
|
||||
nsresult
|
||||
nsDocAccessible::FireDelayedAccessibleEvent(PRUint32 aEventType, nsINode *aNode,
|
||||
|
@ -415,25 +415,6 @@ protected:
|
||||
*/
|
||||
void ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute);
|
||||
|
||||
/**
|
||||
* Fire text changed event for character data changed. The method is used
|
||||
* from nsIMutationObserver methods.
|
||||
*
|
||||
* @param aContent the text node holding changed data
|
||||
* @param aInfo info structure describing how the data was changed
|
||||
* @param aIsInserted the flag pointed whether removed or inserted
|
||||
* characters should be cause of event
|
||||
*/
|
||||
void FireTextChangeEventForText(nsIContent *aContent,
|
||||
CharacterDataChangeInfo* aInfo,
|
||||
PRBool aIsInserted);
|
||||
|
||||
/**
|
||||
* Fire a value change event for the the given accessible if it is a text
|
||||
* field (has a ROLE_ENTRY).
|
||||
*/
|
||||
void FireValueChangeForTextFields(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Process the event when the queue of pending events is untwisted. Fire
|
||||
* accessible events as result of the processing.
|
||||
|
@ -54,10 +54,16 @@ public:
|
||||
virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
|
||||
PRUint32 aLength);
|
||||
|
||||
protected:
|
||||
// nsTextAccessible
|
||||
void SetText(const nsAString& aText) { mText = aText; }
|
||||
const nsString& Text() const { return mText; }
|
||||
|
||||
protected:
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
|
||||
protected:
|
||||
nsString mText;
|
||||
};
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ function editableTextTest(aID)
|
||||
/**
|
||||
* setTextContents test.
|
||||
*/
|
||||
this.setTextContents = function setTextContents(aStr)
|
||||
this.setTextContents = function setTextContents(aStr, aResValue)
|
||||
{
|
||||
var testID = "setTextContents '" + aStr + "' for " + prettyName(aID);
|
||||
|
||||
@ -46,15 +46,15 @@ function editableTextTest(aID)
|
||||
acc.setTextContents(aStr);
|
||||
}
|
||||
|
||||
this.sheduleTest(aID, null, [0, aStr.length, aStr],
|
||||
setTextContentsInvoke, getValueChecker(aID, aResValue),
|
||||
testID);
|
||||
this.scheduleTest(aID, null, [0, aStr.length, aStr],
|
||||
setTextContentsInvoke, getValueChecker(aID, aResValue),
|
||||
testID);
|
||||
}
|
||||
|
||||
/**
|
||||
* insertText test.
|
||||
*/
|
||||
this.insertText = function insertText(aStr, aPos, aResStr)
|
||||
this.insertText = function insertText(aStr, aPos, aResStr, aResPos)
|
||||
{
|
||||
var testID = "insertText '" + aStr + "' at " + aPos + " for " +
|
||||
prettyName(aID);
|
||||
@ -65,7 +65,8 @@ function editableTextTest(aID)
|
||||
acc.insertText(aStr, aPos);
|
||||
}
|
||||
|
||||
this.scheduleTest(aID, null, [aPos, aPos + aStr.length, aStr],
|
||||
var resPos = (aResPos != undefined) ? aResPos : aPos;
|
||||
this.scheduleTest(aID, null, [resPos, resPos + aStr.length, aStr],
|
||||
insertTextInvoke, getValueChecker(aID, aResStr), testID);
|
||||
}
|
||||
|
||||
@ -110,7 +111,8 @@ function editableTextTest(aID)
|
||||
/**
|
||||
* cutText test.
|
||||
*/
|
||||
this.cutText = function cutText(aStartPos, aEndPos, aResStr)
|
||||
this.cutText = function cutText(aStartPos, aEndPos, aResStr,
|
||||
aResStartPos, aResEndPos)
|
||||
{
|
||||
var testID = "cutText from " + aStartPos + " to " + aEndPos + " for " +
|
||||
prettyName(aID);
|
||||
@ -121,7 +123,9 @@ function editableTextTest(aID)
|
||||
acc.cutText(aStartPos, aEndPos);
|
||||
}
|
||||
|
||||
this.scheduleTest(aID, [aStartPos, aEndPos, getTextFromClipboard], null,
|
||||
var resStartPos = (aResStartPos != undefined) ? aResStartPos : aStartPos;
|
||||
var resEndPos = (aResEndPos != undefined) ? aResEndPos : aEndPos;
|
||||
this.scheduleTest(aID, [resStartPos, resEndPos, getTextFromClipboard], null,
|
||||
cutTextInvoke, getValueChecker(aID, aResStr), testID);
|
||||
}
|
||||
|
||||
|
@ -64,12 +64,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452161
|
||||
aTestRun.add(et);
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true; // debug stuff
|
||||
|
||||
function runTest()
|
||||
{
|
||||
var testRun = new editableTextTestRun();
|
||||
|
||||
addTestEditable("input", testRun);
|
||||
// addTestEditable("div"); XXX: bug 452599
|
||||
addTestEditable("div", testRun);
|
||||
addTestEditable(getNode("frame").contentDocument, testRun);
|
||||
|
||||
testRun.run(); // Will call SimpleTest.finish();
|
||||
@ -94,6 +96,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452161
|
||||
<a target="_blank"
|
||||
title="nsIAccessibleEditableText chrome tests"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=452161">Mozilla Bug 452161</a>
|
||||
<a target="_blank"
|
||||
title="Cache rendered text on a11y side"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=626660">
|
||||
Mozilla Bug 626660
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
@ -101,7 +108,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452161
|
||||
|
||||
<input id="input"/>
|
||||
|
||||
<div id="div" contentEditable="true"/>
|
||||
<div id="div" contentEditable="true"></div>
|
||||
|
||||
<iframe id="frame"/>
|
||||
</body>
|
||||
|
@ -22,9 +22,14 @@
|
||||
{
|
||||
var et = new editableTextTest("input");
|
||||
|
||||
et.insertText("ee", 1, "heeello");
|
||||
// 'ee' insertion/removal at 1 or 2 offset of 'hello'/'heeello' string
|
||||
// reports 'ee' text was inserted/removed at 2 offset.
|
||||
et.insertText("ee", 1, "heeello", 2);
|
||||
et.copyText(1, 3, "ee");
|
||||
et.cutText(1, 3, "hello");
|
||||
et.cutText(1, 3, "hello", 2, 4);
|
||||
et.insertText("ee", 2, "heeello", 2);
|
||||
et.cutText(2, 4, "hello", 2, 4);
|
||||
|
||||
et.deleteText(1, 3, "hlo");
|
||||
et.pasteText(1, "heelo");
|
||||
|
||||
@ -44,6 +49,11 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=524115">
|
||||
Mozilla Bug 524115
|
||||
</a>
|
||||
<a target="_blank"
|
||||
title="Cache rendered text on a11y side"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=626660">
|
||||
Mozilla Bug 626660
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -90,6 +90,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true; // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
|
@ -73,8 +73,7 @@
|
||||
// Note: if input have label elements then the name isn't calculated
|
||||
// from them.
|
||||
testName("btn_labelledby_mixed_input",
|
||||
"Submit Query Reset Submit Query");
|
||||
// XXX Bug 567203 "input button Submit Query Reset Submit Query");
|
||||
"input button Submit Query Reset Submit Query");
|
||||
|
||||
// Gets the name from the title of object element.
|
||||
testName("btn_labelledby_mixed_object", "object");
|
||||
|
@ -52,11 +52,7 @@
|
||||
children: [
|
||||
{
|
||||
role: ROLE_ENTRY,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF // Text node for the node's value
|
||||
}
|
||||
]
|
||||
children: [ ] // no text leaf accessible for text node
|
||||
},
|
||||
{
|
||||
role: ROLE_COMBOBOX_LIST, // context menu
|
||||
@ -94,7 +90,8 @@
|
||||
role: ROLE_ENTRY,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF
|
||||
role: ROLE_TEXT_LEAF,
|
||||
name: "http://mochi.test:8888/redirect-a11y.html"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -122,11 +119,7 @@
|
||||
},
|
||||
{
|
||||
role: ROLE_ENTRY,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF // Text node for the node's value
|
||||
}
|
||||
]
|
||||
children: [ ] // no text leaf accessible for text node
|
||||
},
|
||||
{
|
||||
role: ROLE_COMBOBOX_LIST, // context menu popup
|
||||
@ -150,6 +143,11 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
|
||||
title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
|
||||
Mozilla Bug 249292
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=626660"
|
||||
title="Cache rendered text on a11y side">
|
||||
Mozilla Bug 626660
|
||||
</a><br/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
@ -29,9 +29,7 @@
|
||||
] }
|
||||
] },
|
||||
{ TEXT_LEAF: [ ] }, // body text
|
||||
{ ENTRY: [ // input under document element
|
||||
{ TEXT_LEAF: [ ] }
|
||||
] },
|
||||
{ ENTRY: [ ] }, // input under document element
|
||||
{ PARAGRAPH: [ // link under document element
|
||||
{ TEXT_LEAF: [ ] }, // link content
|
||||
{ STATICTEXT: [ ] }, // generated content
|
||||
|
@ -47,9 +47,7 @@
|
||||
|
||||
// input@type="text", no value
|
||||
accTree =
|
||||
{ ENTRY: [
|
||||
{ TEXT_LEAF: [ ] }
|
||||
] };
|
||||
{ ENTRY: [ ] };
|
||||
|
||||
testAccessibleTree("txc3", accTree);
|
||||
|
||||
|
@ -323,9 +323,7 @@
|
||||
{
|
||||
var tree =
|
||||
{ DOCUMENT: [
|
||||
{ ENTRY: [
|
||||
{ TEXT_LEAF: [ ] }
|
||||
] }
|
||||
{ ENTRY: [ ] }
|
||||
] };
|
||||
testAccessibleTree(this.docNode, tree);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user