From 49bce20292efff8cbdf419c86e0ae539657b1fbc Mon Sep 17 00:00:00 2001 From: Lorien Hu Date: Wed, 5 Aug 2015 21:55:13 -0400 Subject: [PATCH] Bug 1187995 - Add proxy handling to mozTextAccessible r=tbsaunde --- accessible/ipc/DocAccessibleChild.cpp | 27 ++++ accessible/ipc/DocAccessibleChild.h | 7 + accessible/ipc/PDocAccessible.ipdl | 2 + accessible/ipc/ProxyAccessible.cpp | 14 ++ accessible/ipc/ProxyAccessible.h | 6 +- accessible/mac/mozTextAccessible.mm | 198 ++++++++++++++++++++------ 6 files changed, 206 insertions(+), 48 deletions(-) diff --git a/accessible/ipc/DocAccessibleChild.cpp b/accessible/ipc/DocAccessibleChild.cpp index c77764d4a96..575c43d8eef 100644 --- a/accessible/ipc/DocAccessibleChild.cpp +++ b/accessible/ipc/DocAccessibleChild.cpp @@ -10,6 +10,7 @@ #include "ProxyAccessible.h" #include "Relation.h" #include "HyperTextAccessible-inl.h" +#include "TextLeafAccessible.h" #include "ImageAccessible.h" #include "TableAccessible.h" #include "TableCellAccessible.h" @@ -97,6 +98,13 @@ DocAccessibleChild::IdToHyperTextAccessible(const uint64_t& aID) const return acc && acc->IsHyperText() ? acc->AsHyperText() : nullptr; } +TextLeafAccessible* +DocAccessibleChild::IdToTextLeafAccessible(const uint64_t& aID) const +{ + Accessible* acc = IdToAccessible(aID); + return acc && acc->IsTextLeaf() ? acc->AsTextLeaf() : nullptr; +} + ImageAccessible* DocAccessibleChild::IdToImageAccessible(const uint64_t& aID) const { @@ -342,6 +350,14 @@ DocAccessibleChild::RecvARIARoleAtom(const uint64_t& aID, nsString* aRole) return true; } +bool +DocAccessibleChild::RecvCaretLineNumber(const uint64_t& aID, int32_t* aLineNumber) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + *aLineNumber = acc && acc->IsTextRole() ? acc->CaretLineNumber() : 0; + return true; +} + bool DocAccessibleChild::RecvCaretOffset(const uint64_t& aID, int32_t* aOffset) { @@ -636,6 +652,17 @@ DocAccessibleChild::RecvScrollSubstringToPoint(const uint64_t& aID, return true; } +bool +DocAccessibleChild::RecvText(const uint64_t& aID, + nsString* aText) +{ + TextLeafAccessible* acc = IdToTextLeafAccessible(aID); + if (acc) { + *aText = acc->Text(); + } + + return true; +} bool DocAccessibleChild::RecvReplaceText(const uint64_t& aID, diff --git a/accessible/ipc/DocAccessibleChild.h b/accessible/ipc/DocAccessibleChild.h index 5aae0ead9f2..938c353fb01 100644 --- a/accessible/ipc/DocAccessibleChild.h +++ b/accessible/ipc/DocAccessibleChild.h @@ -15,6 +15,7 @@ namespace mozilla { namespace a11y { class Accessible; class HyperTextAccessible; +class TextLeafAccessible; class ImageAccessible; class TableAccessible; class TableCellAccessible; @@ -96,6 +97,8 @@ public: virtual bool RecvAttributes(const uint64_t& aID, nsTArray *aAttributes) override; + virtual bool RecvCaretLineNumber(const uint64_t& aID, int32_t* aLineNumber) + override; virtual bool RecvCaretOffset(const uint64_t& aID, int32_t* aOffset) override; virtual bool RecvSetCaretOffset(const uint64_t& aID, const int32_t& aOffset, @@ -194,6 +197,9 @@ public: const int32_t& aX, const int32_t& aY) override; + virtual bool RecvText(const uint64_t& aID, + nsString* aText) override; + virtual bool RecvReplaceText(const uint64_t& aID, const nsString& aText) override; @@ -460,6 +466,7 @@ private: Accessible* IdToAccessibleLink(const uint64_t& aID) const; Accessible* IdToAccessibleSelect(const uint64_t& aID) const; HyperTextAccessible* IdToHyperTextAccessible(const uint64_t& aID) const; + TextLeafAccessible* IdToTextLeafAccessible(const uint64_t& aID) const; ImageAccessible* IdToImageAccessible(const uint64_t& aID) const; TableCellAccessible* IdToTableCellAccessible(const uint64_t& aID) const; TableAccessible* IdToTableAccessible(const uint64_t& aID) const; diff --git a/accessible/ipc/PDocAccessible.ipdl b/accessible/ipc/PDocAccessible.ipdl index 2e705dc4de0..2fe7787cdbb 100644 --- a/accessible/ipc/PDocAccessible.ipdl +++ b/accessible/ipc/PDocAccessible.ipdl @@ -89,6 +89,7 @@ child: // AccessibleText // TextSubstring is getText in IDL. + prio(high) sync CaretLineNumber(uint64_t aID) returns(int32_t aLineNumber); prio(high) sync CaretOffset(uint64_t aID) returns(int32_t aOffset); prio(high) sync SetCaretOffset(uint64_t aID, int32_t aOffset) returns (bool aValid); prio(high) sync CharacterCount(uint64_t aID) returns(int32_t aCount); @@ -135,6 +136,7 @@ child: uint32_t aCoordinateType, int32_t aX, int32_t aY); + prio(high) sync Text(uint64_t aID) returns(nsString aText); prio(high) sync ReplaceText(uint64_t aID, nsString aText); prio(high) sync InsertText(uint64_t aID, nsString aText, int32_t aPosition) returns(bool aValid); diff --git a/accessible/ipc/ProxyAccessible.cpp b/accessible/ipc/ProxyAccessible.cpp index 68e634c0659..6d394f56493 100644 --- a/accessible/ipc/ProxyAccessible.cpp +++ b/accessible/ipc/ProxyAccessible.cpp @@ -191,6 +191,14 @@ ProxyAccessible::ARIARoleAtom() const return NS_GetStaticAtom(role); } +int32_t +ProxyAccessible::CaretLineNumber() +{ + int32_t line = -1; + unused << mDoc->SendCaretOffset(mID, &line); + return line; +} + int32_t ProxyAccessible::CaretOffset() { @@ -371,6 +379,12 @@ ProxyAccessible::ScrollSubstringToPoint(int32_t aStartOffset, aCoordinateType, aX, aY); } +void +ProxyAccessible::Text(nsString* aText) +{ + unused << mDoc->SendText(mID, aText); +} + void ProxyAccessible::ReplaceText(const nsString& aText) { diff --git a/accessible/ipc/ProxyAccessible.h b/accessible/ipc/ProxyAccessible.h index b81dc9c7118..2e2809b7f77 100644 --- a/accessible/ipc/ProxyAccessible.h +++ b/accessible/ipc/ProxyAccessible.h @@ -9,6 +9,7 @@ #include "mozilla/a11y/Role.h" #include "nsIAccessibleText.h" +#include "nsIAccessibleTypes.h" #include "Accessible.h" #include "nsString.h" #include "nsTArray.h" @@ -126,6 +127,7 @@ public: nsIAtom* ARIARoleAtom() const; + int32_t CaretLineNumber(); int32_t CaretOffset(); bool SetCaretOffset(int32_t aOffset); @@ -160,7 +162,7 @@ public: void DefaultTextAttributes(nsTArray* aAttrs); nsIntRect TextBounds(int32_t aStartOffset, int32_t aEndOffset, - uint32_t aCoordType); + uint32_t aCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE); nsIntRect CharBounds(int32_t aOffset, uint32_t aCoordType); @@ -188,6 +190,8 @@ public: uint32_t aCoordinateType, int32_t aX, int32_t aY); + void Text(nsString* aText); + void ReplaceText(const nsString& aText); bool InsertText(const nsString& aText, int32_t aPosition); diff --git a/accessible/mac/mozTextAccessible.mm b/accessible/mac/mozTextAccessible.mm index e007fd10d13..3f413341fd7 100644 --- a/accessible/mac/mozTextAccessible.mm +++ b/accessible/mac/mozTextAccessible.mm @@ -114,13 +114,23 @@ ToNSString(id aValue) return [self text]; } - AccessibleWrap* accWrap = [self getGeckoAccessible]; + if (AccessibleWrap* accWrap = [self getGeckoAccessible]) { + if ([attribute isEqualToString:@"AXRequired"]) { + return [NSNumber numberWithBool:!!(accWrap->State() & states::REQUIRED)]; + } - if ([attribute isEqualToString:@"AXRequired"]) - return [NSNumber numberWithBool:!!(accWrap->State() & states::REQUIRED)]; + if ([attribute isEqualToString:@"AXInvalid"]) { + return [NSNumber numberWithBool:!!(accWrap->State() & states::INVALID)]; + } + } else if (ProxyAccessible* proxy = [self getProxyAccessible]) { + if ([attribute isEqualToString:@"AXRequired"]) { + return [NSNumber numberWithBool:!!(proxy->State() & states::REQUIRED)]; + } - if ([attribute isEqualToString:@"AXInvalid"]) - return [NSNumber numberWithBool:!!(accWrap->State() & states::INVALID)]; + if ([attribute isEqualToString:@"AXInvalid"]) { + return [NSNumber numberWithBool:!!(proxy->State() & states::INVALID)]; + } + } if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) return [self visibleCharacterRange]; @@ -157,8 +167,10 @@ ToNSString(id aValue) - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter { AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; + HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; - if (!textAcc) + if (!textAcc && !proxy) return nil; if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) { @@ -206,7 +218,12 @@ ToNSString(id aValue) int32_t start = range.location; int32_t end = start + range.length; - nsIntRect bounds = textAcc->TextBounds(start, end); + nsIntRect bounds; + if (textAcc) { + bounds = textAcc->TextBounds(start, end); + } else if (proxy) { + bounds = proxy->TextBounds(start, end); + } return [NSValue valueWithRect:nsCocoaUtils::GeckoRectToCocoaRect(bounds)]; } @@ -240,8 +257,10 @@ ToNSString(id aValue) NS_OBJC_BEGIN_TRY_ABORT_BLOCK; AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; + HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; - if (!textAcc) + if (!textAcc && !proxy) return; if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { @@ -256,12 +275,19 @@ ToNSString(id aValue) return; int32_t start = 0, end = 0; - textAcc->SelectionBoundsAt(0, &start, &end); - textAcc->DeleteText(start, end - start); - nsString text; - nsCocoaUtils::GetStringForNSString(stringValue, text); - textAcc->InsertText(text, start); + if (textAcc) { + textAcc->SelectionBoundsAt(0, &start, &end); + textAcc->DeleteText(start, end - start); + nsCocoaUtils::GetStringForNSString(stringValue, text); + textAcc->InsertText(text, start); + } else if (proxy) { + nsString data; + proxy->SelectionBoundsAt(0, data, &start, &end); + proxy->DeleteText(start, end - start); + nsCocoaUtils::GetStringForNSString(stringValue, text); + proxy->InsertText(text, start); + } } if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { @@ -269,8 +295,13 @@ ToNSString(id aValue) if (!ToNSRange(value, &range)) return; - textAcc->SetSelectionBoundsAt(0, range.location, + if (textAcc) { + textAcc->SetSelectionBoundsAt(0, range.location, + range.location + range.length); + } else if (proxy) { + proxy->SetSelectionBoundsAt(0, range.location, range.location + range.length); + } return; } @@ -279,8 +310,13 @@ ToNSString(id aValue) if (!ToNSRange(value, &range)) return; - textAcc->ScrollSubstringTo(range.location, range.location + range.length, + if (textAcc) { + textAcc->ScrollSubstringTo(range.location, range.location + range.length, + nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE); + } else if (proxy) { + proxy->ScrollSubstringTo(range.location, range.location + range.length, nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE); + } return; } @@ -311,6 +347,9 @@ ToNSString(id aValue) if (textAcc) return (accWrap->State() & states::READONLY) == 0; + if (ProxyAccessible* proxy = [self getProxyAccessible]) + return (proxy->State() & states::READONLY) == 0; + return NO; NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); @@ -320,8 +359,13 @@ ToNSString(id aValue) { AccessibleWrap* accWrap = [self getGeckoAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; - int32_t lineNumber = textAcc ? - textAcc->CaretLineNumber() - 1 : -1; + + int32_t lineNumber = -1; + if (textAcc) { + lineNumber = textAcc->CaretLineNumber() - 1; + } else if (ProxyAccessible* proxy = [self getProxyAccessible]) { + lineNumber = proxy->CaretLineNumber() - 1; + } return (lineNumber >= 0) ? [NSNumber numberWithInt:lineNumber] : nil; } @@ -332,10 +376,13 @@ ToNSString(id aValue) AccessibleWrap* accWrap = [self getGeckoAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; + + nsString text; + nsCocoaUtils::GetStringForNSString(aNewString, text); if (textAcc) { - nsString text; - nsCocoaUtils::GetStringForNSString(aNewString, text); textAcc->ReplaceText(text); + } else if (ProxyAccessible* proxy = [self getProxyAccessible]) { + proxy->ReplaceText(text); } NS_OBJC_END_TRY_ABORT_BLOCK; @@ -344,8 +391,9 @@ ToNSString(id aValue) - (NSString*)text { AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; - if (!accWrap || !textAcc) + if (!textAcc && !proxy) return nil; // A password text field returns an empty value @@ -353,7 +401,12 @@ ToNSString(id aValue) return @""; nsAutoString text; - textAcc->TextSubstring(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, text); + if (textAcc) { + textAcc->TextSubstring(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, text); + } else if (proxy) { + proxy->TextSubstring(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, text); + } + return nsCocoaUtils::ToNSString(text); } @@ -362,11 +415,12 @@ ToNSString(id aValue) NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; - if (!accWrap || !textAcc) + if (!textAcc && !proxy) return 0; - return textAcc ? textAcc->CharacterCount() : 0; + return textAcc ? textAcc->CharacterCount() : proxy->CharacterCount(); NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); } @@ -376,13 +430,19 @@ ToNSString(id aValue) NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; + if (!textAcc && !proxy) + return 0; + + int32_t start = 0, end = 0; if (textAcc) { - int32_t start = 0, end = 0; textAcc->SelectionBoundsAt(0, &start, &end); - return (end - start); + } else if (proxy) { + nsString data; + proxy->SelectionBoundsAt(0, data, &start, &end); } - return 0; + return (end - start); NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); } @@ -392,17 +452,23 @@ ToNSString(id aValue) NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; + if (!textAcc && !proxy) + return nil; + + int32_t start = 0, end = 0; + nsAutoString selText; if (textAcc) { - int32_t start = 0, end = 0; textAcc->SelectionBoundsAt(0, &start, &end); if (start != end) { - nsAutoString selText; textAcc->TextSubstring(start, end, selText); - return nsCocoaUtils::ToNSString(selText); } + } else if (proxy) { + proxy->SelectionBoundsAt(0, selText, &start, &end); } - return nil; + + return nsCocoaUtils::ToNSString(selText); NS_OBJC_END_TRY_ABORT_BLOCK_NIL; } @@ -412,20 +478,35 @@ ToNSString(id aValue) NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; - if (textAcc) { - int32_t start = 0; - int32_t end = 0; - int32_t count = textAcc->SelectionCount(); + int32_t start = 0; + int32_t end = 0; + int32_t count = 0; + if (textAcc) { + count = textAcc->SelectionCount(); if (count) { textAcc->SelectionBoundsAt(0, &start, &end); return [NSValue valueWithRange:NSMakeRange(start, end - start)]; } start = textAcc->CaretOffset(); - return [NSValue valueWithRange:NSMakeRange(start != -1 ? start : 0, 0)]; + return [NSValue valueWithRange:NSMakeRange(start != -1 ? start : 0, 0)]; } + + if (proxy) { + count = proxy->SelectionCount(); + if (count) { + nsString data; + proxy->SelectionBoundsAt(0, data, &start, &end); + return [NSValue valueWithRange:NSMakeRange(start, end - start)]; + } + + start = proxy->CaretOffset(); + return [NSValue valueWithRange:NSMakeRange(start != -1 ? start : 0, 0)]; + } + return [NSValue valueWithRange:NSMakeRange(0, 0)]; NS_OBJC_END_TRY_ABORT_BLOCK_NIL; @@ -436,10 +517,14 @@ ToNSString(id aValue) // XXX this won't work with Textarea and such as we actually don't give // the visible character range. AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; + if (!textAcc && !proxy) + return 0; + return [NSValue valueWithRange: NSMakeRange(0, textAcc ? - textAcc->CharacterCount() : 0)]; + textAcc->CharacterCount() : proxy->CharacterCount())]; } - (void)valueDidChange @@ -463,13 +548,20 @@ ToNSString(id aValue) NS_PRECONDITION(range, "no range"); AccessibleWrap* accWrap = [self getGeckoAccessible]; + ProxyAccessible* proxy = [self getProxyAccessible]; HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr; - if (!textAcc) + if (!textAcc && !proxy) return nil; nsAutoString text; - textAcc->TextSubstring(range->location, - range->location + range->length, text); + if (textAcc) { + textAcc->TextSubstring(range->location, + range->location + range->length, text); + } else if (proxy) { + proxy->TextSubstring(range->location, + range->location + range->length, text); + } + return nsCocoaUtils::ToNSString(text); } @@ -501,20 +593,32 @@ ToNSString(id aValue) - (NSString*)text { - AccessibleWrap* accWrap = [self getGeckoAccessible]; - if (!accWrap) - return nil; + if (AccessibleWrap* accWrap = [self getGeckoAccessible]) { + return nsCocoaUtils::ToNSString(accWrap->AsTextLeaf()->Text()); + } - return nsCocoaUtils::ToNSString(accWrap->AsTextLeaf()->Text()); + if (ProxyAccessible* proxy = [self getProxyAccessible]) { + nsString text; + proxy->Text(&text); + return nsCocoaUtils::ToNSString(text); + } + + return nil; } - (long)textLength { - AccessibleWrap* accWrap = [self getGeckoAccessible]; - if (!accWrap) - return 0; + if (AccessibleWrap* accWrap = [self getGeckoAccessible]) { + return accWrap->AsTextLeaf()->Text().Length(); + } - return accWrap->AsTextLeaf()->Text().Length(); + if (ProxyAccessible* proxy = [self getProxyAccessible]) { + nsString text; + proxy->Text(&text); + return text.Length(); + } + + return 0; } @end