diff --git a/accessible/base/AccEvent.cpp b/accessible/base/AccEvent.cpp index 6fc646184359b..b0046f2ff4553 100644 --- a/accessible/base/AccEvent.cpp +++ b/accessible/base/AccEvent.cpp @@ -187,13 +187,14 @@ AccVCChangeEvent:: int32_t aOldStart, int32_t aOldEnd, Accessible* aNewAccessible, int32_t aNewStart, int32_t aNewEnd, - int16_t aReason, EIsFromUserInput aIsFromUserInput) : + int16_t aReason, int16_t aBoundaryType, + EIsFromUserInput aIsFromUserInput) : AccEvent(::nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED, aAccessible, aIsFromUserInput), mOldAccessible(aOldAccessible), mNewAccessible(aNewAccessible), mOldStart(aOldStart), mNewStart(aNewStart), mOldEnd(aOldEnd), mNewEnd(aNewEnd), - mReason(aReason) + mReason(aReason), mBoundaryType(aBoundaryType) { } @@ -258,7 +259,8 @@ a11y::MakeXPCEvent(AccEvent* aEvent) ToXPC(vcc->NewAccessible()), vcc->NewStartOffset(), vcc->NewEndOffset(), - vcc->Reason()); + vcc->Reason(), + vcc->BoundaryType()); return xpEvent.forget(); } diff --git a/accessible/base/AccEvent.h b/accessible/base/AccEvent.h index 3e91c2e9edf25..f446bcb45b0e2 100644 --- a/accessible/base/AccEvent.h +++ b/accessible/base/AccEvent.h @@ -488,6 +488,7 @@ class AccVCChangeEvent : public AccEvent Accessible* aNewAccessible, int32_t aNewStart, int32_t aNewEnd, int16_t aReason, + int16_t aBoundaryType, EIsFromUserInput aIsFromUserInput = eFromUserInput); virtual ~AccVCChangeEvent() { } @@ -507,6 +508,7 @@ class AccVCChangeEvent : public AccEvent int32_t NewStartOffset() const { return mNewStart; } int32_t NewEndOffset() const { return mNewEnd; } int32_t Reason() const { return mReason; } + int32_t BoundaryType() const { return mBoundaryType; } private: RefPtr mOldAccessible; @@ -516,6 +518,7 @@ class AccVCChangeEvent : public AccEvent int32_t mOldEnd; int32_t mNewEnd; int16_t mReason; + int16_t mBoundaryType; }; /** diff --git a/accessible/base/Platform.h b/accessible/base/Platform.h index 0246704378a94..980ed3f7d72f0 100644 --- a/accessible/base/Platform.h +++ b/accessible/base/Platform.h @@ -111,7 +111,8 @@ void ProxyVirtualCursorChangeEvent(ProxyAccessible* aTarget, ProxyAccessible* aNewPosition, int32_t aNewStartOffset, int32_t aNewEndOffset, - uint16_t aReason, bool aFromUser); + int16_t aReason, int16_t aBoundaryType, + bool aFromUser); #endif } // namespace a11y } // namespace mozilla diff --git a/accessible/base/nsAccessiblePivot.cpp b/accessible/base/nsAccessiblePivot.cpp index 9733a0852edc5..6a5ce3e979f69 100644 --- a/accessible/base/nsAccessiblePivot.cpp +++ b/accessible/base/nsAccessiblePivot.cpp @@ -103,7 +103,8 @@ nsAccessiblePivot::SetPosition(nsIAccessible* aPosition) int32_t oldStart = mStartOffset, oldEnd = mEndOffset; mStartOffset = mEndOffset = -1; NotifyOfPivotChange(position, oldStart, oldEnd, - nsIAccessiblePivot::REASON_NONE, false); + nsIAccessiblePivot::REASON_NONE, + nsIAccessiblePivot::NO_BOUNDARY, false); return NS_OK; } @@ -186,7 +187,8 @@ nsAccessiblePivot::SetTextRange(nsIAccessibleText* aTextAccessible, mPosition.swap(acc); NotifyOfPivotChange(acc, oldStart, oldEnd, - nsIAccessiblePivot::REASON_TEXT, + nsIAccessiblePivot::REASON_NONE, + nsIAccessiblePivot::NO_BOUNDARY, (aArgc > 0) ? aIsFromUserInput : true); return NS_OK; @@ -378,6 +380,10 @@ nsAccessiblePivot::MoveNextByText(TextBoundaryType aBoundary, startBoundary = nsIAccessibleText::BOUNDARY_WORD_START; endBoundary = nsIAccessibleText::BOUNDARY_WORD_END; break; + case LINE_BOUNDARY: + startBoundary = nsIAccessibleText::BOUNDARY_LINE_START; + endBoundary = nsIAccessibleText::BOUNDARY_LINE_END; + break; default: return NS_ERROR_INVALID_ARG; } @@ -418,7 +424,7 @@ nsAccessiblePivot::MoveNextByText(TextBoundaryType aBoundary, mStartOffset = tempStart; mEndOffset = tempEnd; NotifyOfPivotChange(startPosition, oldStart, oldEnd, - nsIAccessiblePivot::REASON_TEXT, + nsIAccessiblePivot::REASON_NEXT, aBoundary, (aArgc > 0) ? aIsFromUserInput : true); return NS_OK; } @@ -452,14 +458,13 @@ nsAccessiblePivot::MovePreviousByText(TextBoundaryType aBoundary, } // If the search led to the parent of the node we started on (e.g. when - // starting on a text leaf), start the text movement from the end of that - // node, otherwise we just default to 0. + // starting on a text leaf), start the text movement from the end offset + // of that node. Otherwise we just default to the last offset in the parent. if (tempStart == -1) { - if (tempPosition != curPosition) - tempStart = text == curPosition->Parent() ? - text->GetChildOffset(curPosition) : text->CharacterCount(); + if (tempPosition != curPosition && text == curPosition->Parent()) + tempStart = text->GetChildOffset(curPosition) + nsAccUtils::TextLength(curPosition); else - tempStart = 0; + tempStart = text->CharacterCount(); } // If there's no more text on the current node, try to find the previous @@ -505,6 +510,10 @@ nsAccessiblePivot::MovePreviousByText(TextBoundaryType aBoundary, startBoundary = nsIAccessibleText::BOUNDARY_WORD_START; endBoundary = nsIAccessibleText::BOUNDARY_WORD_END; break; + case LINE_BOUNDARY: + startBoundary = nsIAccessibleText::BOUNDARY_LINE_START; + endBoundary = nsIAccessibleText::BOUNDARY_LINE_END; + break; default: return NS_ERROR_INVALID_ARG; } @@ -551,7 +560,7 @@ nsAccessiblePivot::MovePreviousByText(TextBoundaryType aBoundary, mEndOffset = tempEnd; NotifyOfPivotChange(startPosition, oldStart, oldEnd, - nsIAccessiblePivot::REASON_TEXT, + nsIAccessiblePivot::REASON_PREV, aBoundary, (aArgc > 0) ? aIsFromUserInput : true); return NS_OK; } @@ -651,7 +660,7 @@ nsAccessiblePivot::MovePivotInternal(Accessible* aPosition, mStartOffset = mEndOffset = -1; return NotifyOfPivotChange(oldPosition, oldStart, oldEnd, aReason, - aIsFromUserInput); + nsIAccessiblePivot::NO_BOUNDARY, aIsFromUserInput); } Accessible* @@ -825,13 +834,17 @@ nsAccessiblePivot::SearchForText(Accessible* aAccessible, bool aBackward) if (temp == root) break; + // Unlike traditional pre-order traversal we revisit the parent + // nodes when we go up the tree. This is because our starting point + // may be a subtree or a leaf. If it's parent matches, it should + // take precedent over a sibling. if (temp != aAccessible && temp->IsHyperText()) return temp->AsHyperText(); - sibling = aBackward ? temp->PrevSibling() : temp->NextSibling(); - if (sibling) break; + + sibling = aBackward ? temp->PrevSibling() : temp->NextSibling(); } while ((temp = temp->Parent())); if (!sibling) @@ -849,7 +862,8 @@ nsAccessiblePivot::SearchForText(Accessible* aAccessible, bool aBackward) bool nsAccessiblePivot::NotifyOfPivotChange(Accessible* aOldPosition, int32_t aOldStart, int32_t aOldEnd, - int16_t aReason, bool aIsFromUserInput) + int16_t aReason, int16_t aBoundaryType, + bool aIsFromUserInput) { if (aOldPosition == mPosition && aOldStart == mStartOffset && aOldEnd == mEndOffset) @@ -862,7 +876,7 @@ nsAccessiblePivot::NotifyOfPivotChange(Accessible* aOldPosition, obs->OnPivotChanged(this, xpcOldPos, aOldStart, aOldEnd, ToXPC(mPosition), mStartOffset, mEndOffset, - aReason, aIsFromUserInput); + aReason, aBoundaryType, aIsFromUserInput); } return true; diff --git a/accessible/base/nsAccessiblePivot.h b/accessible/base/nsAccessiblePivot.h index 9467e36bf0db1..79f89fefd1cb2 100644 --- a/accessible/base/nsAccessiblePivot.h +++ b/accessible/base/nsAccessiblePivot.h @@ -53,6 +53,7 @@ class nsAccessiblePivot final : public nsIAccessiblePivot bool NotifyOfPivotChange(Accessible* aOldAccessible, int32_t aOldStart, int32_t aOldEnd, PivotMoveReason aReason, + TextBoundaryType aBoundaryType, bool aIsFromUserInput); /* diff --git a/accessible/generic/Accessible.cpp b/accessible/generic/Accessible.cpp index 40d0d53fed057..eb8e521330eb3 100644 --- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -937,7 +937,8 @@ Accessible::HandleAccEvent(AccEvent* aEvent) vcEvent->OldStartOffset(), vcEvent->OldEndOffset(), position ? reinterpret_cast(position->UniqueID()) : 0, vcEvent->NewStartOffset(), vcEvent->NewEndOffset(), - vcEvent->Reason(), vcEvent->IsFromUserInput()); + vcEvent->Reason(), vcEvent->BoundaryType(), + vcEvent->IsFromUserInput()); break; } #if defined(XP_WIN) diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index 8fe107c7f2b76..166d0b37862c4 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -683,6 +683,7 @@ DocAccessible::OnPivotChanged(nsIAccessiblePivot* aPivot, nsIAccessible* aNewAccessible, int32_t aNewStart, int32_t aNewEnd, PivotMoveReason aReason, + TextBoundaryType aBoundaryType, bool aIsFromUserInput) { RefPtr event = @@ -691,7 +692,8 @@ DocAccessible::OnPivotChanged(nsIAccessiblePivot* aPivot, aOldStart, aOldEnd, (aNewAccessible ? aNewAccessible->ToInternalAccessible() : nullptr), aNewStart, aNewEnd, - aReason, aIsFromUserInput ? eFromUserInput : eNoUserInput); + aReason, aBoundaryType, + aIsFromUserInput ? eFromUserInput : eNoUserInput); nsEventShell::FireEvent(event); return NS_OK; diff --git a/accessible/interfaces/nsIAccessiblePivot.idl b/accessible/interfaces/nsIAccessiblePivot.idl index 32f7f635b5f8a..88639b7ff037e 100644 --- a/accessible/interfaces/nsIAccessiblePivot.idl +++ b/accessible/interfaces/nsIAccessiblePivot.idl @@ -23,6 +23,7 @@ interface nsIAccessiblePivotObserver; [scriptable, uuid(81fe5144-059b-42db-bd3a-f6ce3158d5e9)] interface nsIAccessiblePivot : nsISupports { + const TextBoundaryType NO_BOUNDARY = -1; const TextBoundaryType CHAR_BOUNDARY = 0; const TextBoundaryType WORD_BOUNDARY = 1; const TextBoundaryType LINE_BOUNDARY = 2; @@ -33,8 +34,7 @@ interface nsIAccessiblePivot : nsISupports const PivotMoveReason REASON_PREV = 2; const PivotMoveReason REASON_FIRST = 3; const PivotMoveReason REASON_LAST = 4; - const PivotMoveReason REASON_TEXT = 5; - const PivotMoveReason REASON_POINT = 6; + const PivotMoveReason REASON_POINT = 5; /** * The accessible the pivot is currently pointed at. @@ -212,6 +212,7 @@ interface nsIAccessiblePivotObserver : nsISupports in nsIAccessible aNewAccessible, in long aNewStart, in long aNewEnd, in PivotMoveReason aReason, + in TextBoundaryType aBoundaryType, in boolean aIsFromUserInput); }; diff --git a/accessible/interfaces/nsIAccessibleVirtualCursorChangeEvent.idl b/accessible/interfaces/nsIAccessibleVirtualCursorChangeEvent.idl index d5decbc8a67b0..8023f85a91cd4 100644 --- a/accessible/interfaces/nsIAccessibleVirtualCursorChangeEvent.idl +++ b/accessible/interfaces/nsIAccessibleVirtualCursorChangeEvent.idl @@ -46,4 +46,9 @@ interface nsIAccessibleVirtualCursorChangeEvent : nsIAccessibleEvent * Reason for virtual cursor move. */ readonly attribute short reason; + + /** + * Text boundary type for movement, NO_BOUNDARY if none. + */ + readonly attribute short boundaryType; }; diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp index 7390cb28bc8c2..4a49b3acee8a0 100644 --- a/accessible/ipc/DocAccessibleParent.cpp +++ b/accessible/ipc/DocAccessibleParent.cpp @@ -397,6 +397,7 @@ DocAccessibleParent::RecvVirtualCursorChangeEvent(const uint64_t& aID, const int32_t& aNewStartOffset, const int32_t& aNewEndOffset, const int16_t& aReason, + const int16_t& aBoundaryType, const bool& aFromUser) { ProxyAccessible* target = GetAccessible(aID); @@ -407,7 +408,7 @@ DocAccessibleParent::RecvVirtualCursorChangeEvent(const uint64_t& aID, ProxyVirtualCursorChangeEvent(target, newPosition, aOldStartOffset, aOldEndOffset, oldPosition, aNewStartOffset, aNewEndOffset, - aReason, aFromUser); + aReason, aBoundaryType, aFromUser); #endif xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); @@ -419,7 +420,7 @@ DocAccessibleParent::RecvVirtualCursorChangeEvent(const uint64_t& aID, aOldStartOffset, aOldEndOffset, GetXPCAccessible(newPosition), aNewStartOffset, aNewEndOffset, - aReason); + aBoundaryType, aReason); nsCoreUtils::DispatchAccEvent(std::move(event)); return IPC_OK(); diff --git a/accessible/ipc/DocAccessibleParent.h b/accessible/ipc/DocAccessibleParent.h index ffe9870dbfa62..ce5d3dccc4b7f 100644 --- a/accessible/ipc/DocAccessibleParent.h +++ b/accessible/ipc/DocAccessibleParent.h @@ -114,6 +114,7 @@ class DocAccessibleParent : public ProxyAccessible, const int32_t& aNewStartOffset, const int32_t& aNewEndOffset, const int16_t& aReason, + const int16_t& aBoundaryType, const bool& aFromUser) override; mozilla::ipc::IPCResult RecvRoleChangedEvent(const a11y::role& aRole) final; diff --git a/accessible/ipc/other/PDocAccessible.ipdl b/accessible/ipc/other/PDocAccessible.ipdl index c90b997e03cdf..392f41f1596cb 100644 --- a/accessible/ipc/other/PDocAccessible.ipdl +++ b/accessible/ipc/other/PDocAccessible.ipdl @@ -70,7 +70,8 @@ parent: int32_t aOldStartOffset, int32_t aOldEndOffset, uint64_t aPosition, int32_t aStartOffset, int32_t aEndOffset, - int16_t aReason, bool aFromUservcEvent); + int16_t aReason, int16_t aBoundaryType, + bool aFromUservcEvent); /* * Tell the parent document to bind the existing document as a new child diff --git a/accessible/ipc/win/PDocAccessible.ipdl b/accessible/ipc/win/PDocAccessible.ipdl index d8345cd607917..f2816861a3e62 100644 --- a/accessible/ipc/win/PDocAccessible.ipdl +++ b/accessible/ipc/win/PDocAccessible.ipdl @@ -68,7 +68,8 @@ parent: int32_t aOldStartOffset, int32_t aOldEndOffset, uint64_t aPosition, int32_t aStartOffset, int32_t aEndOffset, - int16_t aReason, bool aFromUservcEvent); + int16_t aReason, int16_t aBoundaryType, + bool aFromUservcEvent); /* * Tell the parent document to bind the existing document as a new child diff --git a/accessible/jsat/ContentControl.jsm b/accessible/jsat/ContentControl.jsm index f5414263b4507..0a3ffcbad35dd 100644 --- a/accessible/jsat/ContentControl.jsm +++ b/accessible/jsat/ContentControl.jsm @@ -22,6 +22,7 @@ var EXPORTED_SYMBOLS = ["ContentControl"]; const MOVEMENT_GRANULARITY_CHARACTER = 1; const MOVEMENT_GRANULARITY_WORD = 2; +const MOVEMENT_GRANULARITY_LINE = 4; const CLIPBOARD_COPY = 0x4000; const CLIPBOARD_PASTE = 0x8000; @@ -326,6 +327,9 @@ this.ContentControl.prototype = { case MOVEMENT_GRANULARITY_WORD: pivotGranularity = Ci.nsIAccessiblePivot.WORD_BOUNDARY; break; + case MOVEMENT_GRANULARITY_LINE: + pivotGranularity = Ci.nsIAccessiblePivot.LINE_BOUNDARY; + break; default: return; } @@ -474,8 +478,9 @@ this.ContentControl.prototype = { if (aOptions.forcePresent) { this._contentScope.get().sendAsyncMessage( "AccessFu:Present", Presentation.pivotChanged( - vc.position, null, Ci.nsIAccessiblePivot.REASON_NONE, - vc.startOffset, vc.endOffset)); + vc.position, null, vc.startOffset, vc.endOffset, + Ci.nsIAccessiblePivot.REASON_NONE, + Ci.nsIAccessiblePivot.NO_BOUNDARY)); } }; diff --git a/accessible/jsat/EventManager.jsm b/accessible/jsat/EventManager.jsm index 6634e416a4271..b3cd3338f3a49 100644 --- a/accessible/jsat/EventManager.jsm +++ b/accessible/jsat/EventManager.jsm @@ -155,8 +155,9 @@ this.EventManager.prototype = { } this.present( - Presentation.pivotChanged(position, event.oldAccessible, event.reason, - event.newStartOffset, event.newEndOffset)); + Presentation.pivotChanged(position, event.oldAccessible, + event.newStartOffset, event.newEndOffset, + event.reason, event.boundaryType)); break; } diff --git a/accessible/jsat/Presentation.jsm b/accessible/jsat/Presentation.jsm index aff5432dbd5e5..baf787ff0682c 100644 --- a/accessible/jsat/Presentation.jsm +++ b/accessible/jsat/Presentation.jsm @@ -36,9 +36,10 @@ class AndroidPresentor { * position. * @param {int} aReason the reason for the pivot change. * See nsIAccessiblePivot. - * @param {bool} aIsFromUserInput the pivot change was invoked by the user + * @param {bool} aBoundaryType the boundary type for the text movement + * or NO_BOUNDARY if it was not a text movement. See nsIAccessiblePivot. */ - pivotChanged(aPosition, aOldPosition, aReason, aStartOffset, aEndOffset) { + pivotChanged(aPosition, aOldPosition, aStartOffset, aEndOffset, aReason, aBoundaryType) { let context = new PivotContext( aPosition, aOldPosition, aStartOffset, aEndOffset); if (!context.accessible) { @@ -55,7 +56,20 @@ class AndroidPresentor { androidEvents.push({eventType: AndroidEvents.VIEW_HOVER_EXIT, text: []}); } - if (aReason === Ci.nsIAccessiblePivot.REASON_TEXT) { + if (aPosition != aOldPosition) { + let info = this._infoFromContext(context); + let eventType = isExploreByTouch ? + AndroidEvents.VIEW_HOVER_ENTER : + AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED; + androidEvents.push({...info, eventType}); + + try { + context.accessibleForBounds.scrollTo( + Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE); + } catch (e) {} + } + + if (aBoundaryType != Ci.nsIAccessiblePivot.NO_BOUNDARY) { const adjustedText = context.textAndAdjustedOffsets; androidEvents.push({ @@ -64,18 +78,11 @@ class AndroidPresentor { fromIndex: adjustedText.startOffset, toIndex: adjustedText.endOffset }); - } else { - let info = this._infoFromContext(context); - let eventType = isExploreByTouch ? - AndroidEvents.VIEW_HOVER_ENTER : - AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED; - androidEvents.push({...info, eventType}); - } - try { - context.accessibleForBounds.scrollTo( + aPosition.QueryInterface(Ci.nsIAccessibleText).scrollSubstringTo( + aStartOffset, aEndOffset, Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE); - } catch (e) {} + } if (context.accessible) { this.displayedAccessibles.set(context.accessible.document.window, context); @@ -205,17 +212,6 @@ class AndroidPresentor { UtteranceGenerator.genForTabStateChange(aDocObj, aPageState)); } - /** - * The current tab has changed. - * @param {PivotContext} aDocContext context object for tab's - * document. - * @param {PivotContext} aVCContext context object for tab's current - * virtual cursor position. - */ - tabSelected(aDocContext, aVCContext) { - return this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE); - } - /** * The viewport has changed, either a scroll, pan, zoom, or * landscape/portrait toggle. diff --git a/accessible/other/Platform.cpp b/accessible/other/Platform.cpp index f0aac04ab30aa..f58f29577b782 100644 --- a/accessible/other/Platform.cpp +++ b/accessible/other/Platform.cpp @@ -64,7 +64,7 @@ a11y::ProxySelectionEvent(ProxyAccessible*, ProxyAccessible*, uint32_t) void a11y::ProxyVirtualCursorChangeEvent(ProxyAccessible*, ProxyAccessible*, int32_t, int32_t, ProxyAccessible*, - int32_t, int32_t, uint16_t, bool) + int32_t, int32_t, int16_t, int16_t, bool) { } #endif diff --git a/accessible/tests/mochitest/pivot.js b/accessible/tests/mochitest/pivot.js index 776d29664d743..f69272fb74c22 100644 --- a/accessible/tests/mochitest/pivot.js +++ b/accessible/tests/mochitest/pivot.js @@ -8,6 +8,7 @@ const PREFILTER_TRANSPARENT = nsIAccessibleTraversalRule.PREFILTER_TRANSPARENT; const FILTER_MATCH = nsIAccessibleTraversalRule.FILTER_MATCH; const FILTER_IGNORE = nsIAccessibleTraversalRule.FILTER_IGNORE; const FILTER_IGNORE_SUBTREE = nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE; +const NO_BOUNDARY = nsIAccessiblePivot.NO_BOUNDARY; const CHAR_BOUNDARY = nsIAccessiblePivot.CHAR_BOUNDARY; const WORD_BOUNDARY = nsIAccessiblePivot.WORD_BOUNDARY; @@ -71,7 +72,7 @@ var ObjectTraversalRule = * A checker for virtual cursor changed events. */ function VCChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets, aPivotMoveMethod, - aIsFromUserInput) { + aIsFromUserInput, aBoundaryType = NO_BOUNDARY) { this.__proto__ = new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc); this.match = function VCChangedChecker_match(aEvent) { @@ -85,7 +86,8 @@ function VCChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets, aPivotMoveMetho var expectedReason = VCChangedChecker.methodReasonMap[aPivotMoveMethod] || nsIAccessiblePivot.REASON_NONE; - return event.reason == expectedReason; + return event.reason == expectedReason && + event.boundaryType == aBoundaryType; }; this.check = function VCChangedChecker_check(aEvent) { @@ -104,7 +106,7 @@ function VCChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets, aPivotMoveMetho var accMatches = position == aIdOrNameOrAcc; SimpleTest.ok(idMatches || nameMatches || accMatches, "id or name matches", - "expecting " + aIdOrNameOrAcc + ", got '" + + "expecting " + prettyName(aIdOrNameOrAcc) + ", got '" + prettyName(position)); SimpleTest.is(aEvent.isFromUserInput, aIsFromUserInput, @@ -158,9 +160,9 @@ VCChangedChecker.methodReasonMap = { "movePrevious": nsIAccessiblePivot.REASON_PREV, "moveFirst": nsIAccessiblePivot.REASON_FIRST, "moveLast": nsIAccessiblePivot.REASON_LAST, - "setTextRange": nsIAccessiblePivot.REASON_TEXT, - "moveNextByText": nsIAccessiblePivot.REASON_TEXT, - "movePreviousByText": nsIAccessiblePivot.REASON_TEXT, + "setTextRange": nsIAccessiblePivot.REASON_NONE, + "moveNextByText": nsIAccessiblePivot.REASON_NEXT, + "movePreviousByText": nsIAccessiblePivot.REASON_PREV, "moveToPoint": nsIAccessiblePivot.REASON_POINT }; @@ -288,7 +290,7 @@ function setVCTextInvoker(aDocAcc, aPivotMoveMethod, aBoundary, aTextOffsets, if (expectMove) { this.eventSeq = [ new VCChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets, aPivotMoveMethod, - aIsFromUserInput === undefined ? true : aIsFromUserInput) + aIsFromUserInput === undefined ? true : aIsFromUserInput, aBoundary) ]; } else { this.eventSeq = []; diff --git a/accessible/tests/mochitest/pivot/doc_virtualcursor_text.html b/accessible/tests/mochitest/pivot/doc_virtualcursor_text.html index aba87bbd8a7da..78df9a7be1236 100644 --- a/accessible/tests/mochitest/pivot/doc_virtualcursor_text.html +++ b/accessible/tests/mochitest/pivot/doc_virtualcursor_text.html @@ -24,6 +24,7 @@
Endless fun!

Objectsadjacentto eachother should be separate.

+

Hello real world

End!
diff --git a/accessible/tests/mochitest/pivot/test_virtualcursor_text.html b/accessible/tests/mochitest/pivot/test_virtualcursor_text.html index 94545f987ed65..bff0fcee43804 100644 --- a/accessible/tests/mochitest/pivot/test_virtualcursor_text.html +++ b/accessible/tests/mochitest/pivot/test_virtualcursor_text.html @@ -99,8 +99,7 @@ gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [0, 1], getAccessible(doc.getElementById("section-1"), nsIAccessibleText))); - gQueue.push(new setVCPosInvoker(docAcc, null, null, - getAccessible(doc.getElementById("s1-link-1")))); + gQueue.push(new setVCRangeInvoker(docAcc, getAccessible(doc.getElementById("s1-link-1")), [0, 0])); gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [1, 2], getAccessible(doc.getElementById("section-1"), nsIAccessibleText))); gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [0, 1], @@ -119,8 +118,8 @@ getAccessible(doc.getElementById("section-1"), nsIAccessibleText))); gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [13, 14], getAccessible(doc.getElementById("s1-link-1"), nsIAccessibleText))); - gQueue.push(new setVCPosInvoker(docAcc, null, null, - getAccessible(doc.getElementById("section-2")))); + + gQueue.push(new setVCRangeInvoker(docAcc, getAccessible(doc.getElementById("section-2")), [0, 0])); gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", CHAR_BOUNDARY, [27, 28], getAccessible(doc.getElementById("section-1"), nsIAccessibleText))); gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", CHAR_BOUNDARY, [0, 1], @@ -209,10 +208,34 @@ getAccessible(doc.getElementById("start-block"), nsIAccessibleText))); gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, null, false)); gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, null, false)); - gQueue.push(new setVCPosInvoker(docAcc, null, null, - getAccessible(doc.getElementById("start-block")))); + gQueue.push(new setVCRangeInvoker(docAcc, getAccessible(doc.getElementById("start-block")), [0, 0])); gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, null, false)); + gQueue.push(new setVCPosInvoker(docAcc, null, null, + getAccessible(doc.getElementById("paragraph-3")).firstChild)); + gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [0, 7], + getAccessible(doc.getElementById("paragraph-3"), nsIAccessibleText))); + + gQueue.push(new setVCPosInvoker(docAcc, null, null, + getAccessible(doc.getElementById("s1-link-1")).nextSibling)); + gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [4, 6], + getAccessible(doc.getElementById("section-1"), nsIAccessibleText))); + + gQueue.push(new setVCPosInvoker(docAcc, null, null, + getAccessible(doc.getElementById("paragraph-4")).firstChild.nextSibling)); + gQueue.push(new setVCTextInvoker(docAcc, "moveNextByText", WORD_BOUNDARY, [6, 10], + getAccessible(doc.getElementById("paragraph-4"), nsIAccessibleText))); + + gQueue.push(new setVCPosInvoker(docAcc, null, null, + getAccessible(doc.getElementById("section-1")))); + gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [20, 28], + getAccessible(doc.getElementById("section-1"), nsIAccessibleText))); + + gQueue.push(new setVCPosInvoker(docAcc, null, null, + getAccessible(doc.getElementById("section-1")).lastChild)); + gQueue.push(new setVCTextInvoker(docAcc, "movePreviousByText", WORD_BOUNDARY, [20, 28], + getAccessible(doc.getElementById("section-1"), nsIAccessibleText))); + gQueue.invoke(); } diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure index 2bd7dd4fe8642..272547fe535f8 100755 --- a/build/moz.configure/toolchain.configure +++ b/build/moz.configure/toolchain.configure @@ -1323,13 +1323,17 @@ js_option('--enable-lto', help='Enable LTO') -@depends('--enable-lto', c_compiler) +@depends('--enable-lto', 'MOZ_PGO', c_compiler) @imports('multiprocessing') -def lto(value, c_compiler): +def lto(value, pgo, c_compiler): cflags = [] ldflags = [] enabled = None + # MSVC's implementation of PGO implies LTO. Make clang-cl match this. + if c_compiler.type == 'clang-cl' and pgo and value.origin == 'default': + value = ['thin'] + if value: enabled = True if c_compiler.type == 'clang': diff --git a/dom/plugins/base/nsPluginNativeWindowWin.cpp b/dom/plugins/base/nsPluginNativeWindowWin.cpp index 570b99e52610b..3ff2bbe2445ef 100644 --- a/dom/plugins/base/nsPluginNativeWindowWin.cpp +++ b/dom/plugins/base/nsPluginNativeWindowWin.cpp @@ -475,6 +475,7 @@ nsPluginNativeWindowWin::nsPluginNativeWindowWin() : nsPluginNativeWindow() y = 0; width = 0; height = 0; + type = NPWindowTypeWindow; mPrevWinProc = nullptr; mPluginWinProc = nullptr; diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h index 1a575d9c99cfa..4ab2e4ecb5ec8 100644 --- a/js/src/vm/Scope.h +++ b/js/src/vm/Scope.h @@ -587,6 +587,20 @@ class FunctionScope : public Scope // or having defaults will have a nullptr name in the name array to // advance the argument slot. // + // Rest parameter binding is also included in positional formals. + // This also becomes nullptr if destructuring. + // + // The number of positional formals is equal to function.length if + // there's no rest, function.length+1 otherwise. + // + // Destructuring parameters and destructuring rest are included in + // "other formals" below. + // + // "vars" contains the following: + // * function's top level vars if !script()->hasParameterExprs() + // * special internal names (arguments, .this, .generator) if + // they're used. + // // positional formals - [0, nonPositionalFormalStart) // other formals - [nonPositionalParamStart, varStart) // vars - [varStart, length) diff --git a/mobile/android/geckoview/src/androidTest/assets/www/loremIpsum.html b/mobile/android/geckoview/src/androidTest/assets/www/loremIpsum.html index 6479482f91795..c1a8274e6aa40 100644 --- a/mobile/android/geckoview/src/androidTest/assets/www/loremIpsum.html +++ b/mobile/android/geckoview/src/androidTest/assets/www/loremIpsum.html @@ -1,13 +1,13 @@ Lorem ipsum -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt - mollit anim id est laborum. + mollit anim id est laborum.

\ No newline at end of file diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt index b6a29a7a7f9a6..69dd427e91384 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt @@ -65,6 +65,7 @@ class AccessibilityTest : BaseSessionTest() { fun onFocused(event: AccessibilityEvent) { } fun onTextSelectionChanged(event: AccessibilityEvent) { } fun onTextChanged(event: AccessibilityEvent) { } + fun onTextTraversal(event: AccessibilityEvent) { } } @Before fun setup() { @@ -89,6 +90,7 @@ class AccessibilityTest : BaseSessionTest() { AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED -> newDelegate.onAccessibilityFocused(event) AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED -> newDelegate.onTextSelectionChanged(event) AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED -> newDelegate.onTextChanged(event) + AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY -> newDelegate.onTextTraversal(event) else -> {} } return false @@ -183,6 +185,16 @@ class AccessibilityTest : BaseSessionTest() { } while (fromIndex != eventFromIndex || toIndex != eventToIndex) } + private fun waitUntilTextTraversed(fromIndex: Int, toIndex: Int) { + sessionRule.waitUntilCalled(object : EventDelegate { + @AssertCalled(count = 1) + override fun onTextTraversal(event: AccessibilityEvent) { + assertThat("fromIndex matches", event.fromIndex, equalTo(fromIndex)) + assertThat("toIndex matches", event.toIndex, equalTo(toIndex)) + } + }) + } + private fun setSelectionArguments(start: Int, end: Int): Bundle { val arguments = Bundle(2) arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, start) @@ -190,6 +202,13 @@ class AccessibilityTest : BaseSessionTest() { return arguments } + private fun moveByGranularityArguments(granularity: Int, extendSelection: Boolean = false): Bundle { + val arguments = Bundle(2) + arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, granularity) + arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, extendSelection) + return arguments + } + @Test fun testClipboard() { var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID; sessionRule.session.loadString("", "text/html") @@ -240,4 +259,103 @@ class AccessibilityTest : BaseSessionTest() { } }) } + + @Test fun testMoveByCharacter() { + var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID + sessionRule.session.loadTestPath(LOREM_IPSUM_HTML_PATH) + sessionRule.waitForPageStop() + + provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID, + AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null) + + sessionRule.waitUntilCalled(object : EventDelegate { + @AssertCalled(count = 1) + override fun onAccessibilityFocused(event: AccessibilityEvent) { + nodeId = getSourceId(event) + val node = provider.createAccessibilityNodeInfo(nodeId) + assertThat("Accessibility focus on first paragraph", node.text as String, startsWith("Lorem ipsum")) + } + }) + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER)) + waitUntilTextTraversed(0, 1) // "L" + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER)) + waitUntilTextTraversed(1, 2) // "o" + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER)) + waitUntilTextTraversed(0, 1) // "L" + } + + @Test fun testMoveByWord() { + var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID + sessionRule.session.loadTestPath(LOREM_IPSUM_HTML_PATH) + sessionRule.waitForPageStop() + + provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID, + AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null) + + sessionRule.waitUntilCalled(object : EventDelegate { + @AssertCalled(count = 1) + override fun onAccessibilityFocused(event: AccessibilityEvent) { + nodeId = getSourceId(event) + val node = provider.createAccessibilityNodeInfo(nodeId) + assertThat("Accessibility focus on first paragraph", node.text as String, startsWith("Lorem ipsum")) + } + }) + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD)) + waitUntilTextTraversed(0, 5) // "Lorem" + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD)) + waitUntilTextTraversed(6, 11) // "ipsum" + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD)) + waitUntilTextTraversed(0, 5) // "Lorem" + } + + @Test fun testMoveByLine() { + var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID + sessionRule.session.loadTestPath(LOREM_IPSUM_HTML_PATH) + sessionRule.waitForPageStop() + + provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID, + AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null) + + sessionRule.waitUntilCalled(object : EventDelegate { + @AssertCalled(count = 1) + override fun onAccessibilityFocused(event: AccessibilityEvent) { + nodeId = getSourceId(event) + val node = provider.createAccessibilityNodeInfo(nodeId) + assertThat("Accessibility focus on first paragraph", node.text as String, startsWith("Lorem ipsum")) + } + }) + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE)) + waitUntilTextTraversed(0, 18) // "Lorem ipsum dolor " + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE)) + waitUntilTextTraversed(18, 28) // "sit amet, " + + provider.performAction(nodeId, + AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, + moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE)) + waitUntilTextTraversed(0, 18) // "Lorem ipsum dolor " + } } diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/FinderTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/FinderTest.kt index ce56169ed36ec..8d038cdd65ca2 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/FinderTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/FinderTest.kt @@ -141,7 +141,7 @@ class FinderTest : BaseSessionTest() { mainSession.waitForPageStop() val result = sessionRule.waitForResult(mainSession.finder.find( - "lore", GeckoSession.FINDER_FIND_LINKS_ONLY)) + "nim", GeckoSession.FINDER_FIND_LINKS_ONLY)) assertThat("Total count should be correct", result.total, equalTo(1)) assertThat("Flags should be correct", @@ -167,4 +167,4 @@ class FinderTest : BaseSessionTest() { mainSession.evaluateJS("window.getSelection().isCollapsed") as Boolean, equalTo(true)) } -} \ No newline at end of file +} diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java index 30fbf0eb661a1..56b0a9dbc4ba4 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java @@ -140,8 +140,7 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualDescendantId info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT); info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD | - AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE | - AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH); + AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE); break; } return info; diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 15dace0cb3210..beb8d9d83ef70 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -13823,7 +13823,7 @@ "description": "Total number of http:// and https:// doc groups per tab group, including docgroups fully in bfcache. Collected at the point when the top level document of the tab group is unloaded." }, "HIDDEN_VIEWPORT_OVERFLOW_TYPE": { - "record_in_processes": ["content"], + "record_in_processes": ["main", "content"], "alert_emails": ["xquan@mozilla.com", "botond@mozilla.com"], "bug_numbers": [1423013, 1423017], "expires_in_version": "65",