зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1384606 - part 4: Make `nsIFrame::GetFrameFromDirection` allow to return content in different native anonymous subtree if the caller wants r=emilio
The a11y module wants to traverse frames in native anonymous subtrees. Therefore, this patch adds new option for allowing it, makes `nsIFrame::GetFrameFromDirection` check it before comparing native anonymous subtree root nodes, and makes `HyperTextAccessible::FindOffset` use the option. Differential Revision: https://phabricator.services.mozilla.com/D172759
This commit is contained in:
Родитель
9cf5036656
Коммит
25e942f2a0
|
@ -534,7 +534,8 @@ uint32_t HyperTextAccessible::FindOffset(uint32_t aOffset,
|
||||||
PeekOffsetStruct pos(
|
PeekOffsetStruct pos(
|
||||||
aAmount, aDirection, innerContentOffset, nsPoint(0, 0),
|
aAmount, aDirection, innerContentOffset, nsPoint(0, 0),
|
||||||
{PeekOffsetOption::JumpLines, PeekOffsetOption::IsKeyboardSelect,
|
{PeekOffsetOption::JumpLines, PeekOffsetOption::IsKeyboardSelect,
|
||||||
PeekOffsetOption::PreserveSpaces},
|
PeekOffsetOption::PreserveSpaces,
|
||||||
|
PeekOffsetOption::AllowContentInDifferentNativeAnonymousSubtreeRoot},
|
||||||
aWordMovementType);
|
aWordMovementType);
|
||||||
nsresult rv = frameAtOffset->PeekOffset(&pos);
|
nsresult rv = frameAtOffset->PeekOffset(&pos);
|
||||||
|
|
||||||
|
|
|
@ -977,10 +977,12 @@ nsPrevNextBidiLevels nsFrameSelection::GetPrevNextBidiLevels(
|
||||||
return levels;
|
return levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PeekOffsetOptions peekOffsetOptions{PeekOffsetOption::ScrollViewStop};
|
||||||
|
if (aJumpLines) {
|
||||||
|
peekOffsetOptions += PeekOffsetOption::JumpLines;
|
||||||
|
}
|
||||||
nsIFrame* newFrame =
|
nsIFrame* newFrame =
|
||||||
currentFrame
|
currentFrame->GetFrameFromDirection(direction, peekOffsetOptions).mFrame;
|
||||||
->GetFrameFromDirection(direction, false, aJumpLines, true, false)
|
|
||||||
.mFrame;
|
|
||||||
|
|
||||||
FrameBidiData currentBidi = currentFrame->GetBidiData();
|
FrameBidiData currentBidi = currentFrame->GetBidiData();
|
||||||
mozilla::intl::BidiEmbeddingLevel currentLevel = currentBidi.embeddingLevel;
|
mozilla::intl::BidiEmbeddingLevel currentLevel = currentBidi.embeddingLevel;
|
||||||
|
|
|
@ -101,6 +101,10 @@ enum class PeekOffsetOption : uint8_t {
|
||||||
// If true, the offset has to end up in an editable node, otherwise we'll keep
|
// If true, the offset has to end up in an editable node, otherwise we'll keep
|
||||||
// searching.
|
// searching.
|
||||||
ForceEditableRegion,
|
ForceEditableRegion,
|
||||||
|
|
||||||
|
// If set, the result's native anonymous subtree root may be different from
|
||||||
|
// the scan start content's root.
|
||||||
|
AllowContentInDifferentNativeAnonymousSubtreeRoot,
|
||||||
};
|
};
|
||||||
|
|
||||||
using PeekOffsetOptions = EnumSet<PeekOffsetOption>;
|
using PeekOffsetOptions = EnumSet<PeekOffsetOption>;
|
||||||
|
|
|
@ -9523,19 +9523,19 @@ Result<bool, nsresult> nsIFrame::IsLogicallyAtLineEdge(
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
||||||
nsDirection aDirection, bool aVisual, bool aJumpLines, bool aScrollViewStop,
|
nsDirection aDirection, const PeekOffsetOptions& aOptions) {
|
||||||
bool aForceEditableRegion) {
|
|
||||||
SelectablePeekReport result;
|
SelectablePeekReport result;
|
||||||
|
|
||||||
nsPresContext* presContext = PresContext();
|
nsPresContext* presContext = PresContext();
|
||||||
bool needsVisualTraversal = aVisual && presContext->BidiEnabled();
|
const bool needsVisualTraversal =
|
||||||
|
aOptions.contains(PeekOffsetOption::Visual) && presContext->BidiEnabled();
|
||||||
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
||||||
MOZ_TRY(NS_NewFrameTraversal(getter_AddRefs(frameTraversal), presContext,
|
MOZ_TRY(NS_NewFrameTraversal(
|
||||||
this, eLeaf, needsVisualTraversal,
|
getter_AddRefs(frameTraversal), presContext, this, eLeaf,
|
||||||
aScrollViewStop,
|
needsVisualTraversal, aOptions.contains(PeekOffsetOption::ScrollViewStop),
|
||||||
true, // aFollowOOFs
|
true, // aFollowOOFs
|
||||||
false // aSkipPopupChecks
|
false // aSkipPopupChecks
|
||||||
));
|
));
|
||||||
|
|
||||||
// Find the prev/next selectable frame
|
// Find the prev/next selectable frame
|
||||||
bool selectable = false;
|
bool selectable = false;
|
||||||
|
@ -9544,8 +9544,8 @@ nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
||||||
const nsIContent* const nativeAnonymousSubtreeContent =
|
const nsIContent* const nativeAnonymousSubtreeContent =
|
||||||
GetClosestNativeAnonymousSubtreeRoot();
|
GetClosestNativeAnonymousSubtreeRoot();
|
||||||
while (!selectable) {
|
while (!selectable) {
|
||||||
auto [blockFrame, lineFrame] =
|
auto [blockFrame, lineFrame] = traversedFrame->GetContainingBlockForLine(
|
||||||
traversedFrame->GetContainingBlockForLine(aScrollViewStop);
|
aOptions.contains(PeekOffsetOption::ScrollViewStop));
|
||||||
if (!blockFrame) {
|
if (!blockFrame) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -9564,7 +9564,7 @@ nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
||||||
: traversedFrame->IsLogicallyAtLineEdge(it, thisLine, aDirection));
|
: traversedFrame->IsLogicallyAtLineEdge(it, thisLine, aDirection));
|
||||||
if (atLineEdge) {
|
if (atLineEdge) {
|
||||||
result.mJumpedLine = true;
|
result.mJumpedLine = true;
|
||||||
if (!aJumpLines) {
|
if (!aOptions.contains(PeekOffsetOption::JumpLines)) {
|
||||||
return result; // we are done. cannot jump lines
|
return result; // we are done. cannot jump lines
|
||||||
}
|
}
|
||||||
int32_t lineToCheckWrap =
|
int32_t lineToCheckWrap =
|
||||||
|
@ -9580,19 +9580,24 @@ nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IsSelectable = [aForceEditableRegion, nativeAnonymousSubtreeContent](
|
auto IsSelectable =
|
||||||
const nsIFrame* aFrame) {
|
[aOptions, nativeAnonymousSubtreeContent](const nsIFrame* aFrame) {
|
||||||
if (!aFrame->IsSelectable(nullptr)) {
|
if (!aFrame->IsSelectable(nullptr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// If the new frame is in a native anonymous subtree, we should treat it
|
// If the new frame is in a native anonymous subtree, we should treat
|
||||||
// as not selectable unless the frame and found frame are in same subtree.
|
// it as not selectable unless the frame and found frame are in same
|
||||||
if (aFrame->GetClosestNativeAnonymousSubtreeRoot() !=
|
// subtree.
|
||||||
nativeAnonymousSubtreeContent) {
|
if (!aOptions.contains(
|
||||||
return false;
|
PeekOffsetOption::
|
||||||
}
|
AllowContentInDifferentNativeAnonymousSubtreeRoot) &&
|
||||||
return !aForceEditableRegion || aFrame->GetContent()->IsEditable();
|
aFrame->GetClosestNativeAnonymousSubtreeRoot() !=
|
||||||
};
|
nativeAnonymousSubtreeContent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !aOptions.contains(PeekOffsetOption::ForceEditableRegion) ||
|
||||||
|
aFrame->GetContent()->IsEditable();
|
||||||
|
};
|
||||||
|
|
||||||
// Skip br frames, but only if we can select something before hitting the
|
// Skip br frames, but only if we can select something before hitting the
|
||||||
// end of the line or a non-selectable region.
|
// end of the line or a non-selectable region.
|
||||||
|
@ -9623,7 +9628,8 @@ nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
||||||
|
|
||||||
result.mOffset = (aDirection == eDirNext) ? 0 : -1;
|
result.mOffset = (aDirection == eDirNext) ? 0 : -1;
|
||||||
|
|
||||||
if (aVisual && nsBidiPresUtils::IsReversedDirectionFrame(traversedFrame)) {
|
if (aOptions.contains(PeekOffsetOption::Visual) &&
|
||||||
|
nsBidiPresUtils::IsReversedDirectionFrame(traversedFrame)) {
|
||||||
// The new frame is reverse-direction, go to the other end
|
// The new frame is reverse-direction, go to the other end
|
||||||
result.mOffset = -1 - result.mOffset;
|
result.mOffset = -1 - result.mOffset;
|
||||||
}
|
}
|
||||||
|
@ -9633,11 +9639,7 @@ nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
||||||
|
|
||||||
nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
||||||
const PeekOffsetStruct& aPos) {
|
const PeekOffsetStruct& aPos) {
|
||||||
return GetFrameFromDirection(
|
return GetFrameFromDirection(aPos.mDirection, aPos.mOptions);
|
||||||
aPos.mDirection, aPos.mOptions.contains(PeekOffsetOption::Visual),
|
|
||||||
aPos.mOptions.contains(PeekOffsetOption::JumpLines),
|
|
||||||
aPos.mOptions.contains(PeekOffsetOption::ScrollViewStop),
|
|
||||||
aPos.mOptions.contains(PeekOffsetOption::ForceEditableRegion));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsView* nsIFrame::GetClosestView(nsPoint* aOffset) const {
|
nsView* nsIFrame::GetClosestView(nsPoint* aOffset) const {
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "mozilla/AspectRatio.h"
|
#include "mozilla/AspectRatio.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/Baseline.h"
|
#include "mozilla/Baseline.h"
|
||||||
|
#include "mozilla/EnumSet.h"
|
||||||
#include "mozilla/EventForwards.h"
|
#include "mozilla/EventForwards.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/RelativeTo.h"
|
#include "mozilla/RelativeTo.h"
|
||||||
|
@ -129,6 +130,7 @@ struct CharacterDataChangeInfo;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
enum class PeekOffsetOption : uint8_t;
|
||||||
enum class PseudoStyleType : uint8_t;
|
enum class PseudoStyleType : uint8_t;
|
||||||
enum class TableSelectionMode : uint32_t;
|
enum class TableSelectionMode : uint32_t;
|
||||||
|
|
||||||
|
@ -3877,17 +3879,14 @@ class nsIFrame : public nsQueryFrame {
|
||||||
* Called to find the previous/next non-anonymous selectable leaf frame.
|
* Called to find the previous/next non-anonymous selectable leaf frame.
|
||||||
*
|
*
|
||||||
* @param aDirection the direction to move in (eDirPrevious or eDirNext)
|
* @param aDirection the direction to move in (eDirPrevious or eDirNext)
|
||||||
* @param aVisual whether bidi caret behavior is visual (true) or logical
|
* @param aOptions the other options which is same as
|
||||||
* (false)
|
* PeekOffsetStruct::mOptions.
|
||||||
* @param aJumpLines whether to allow jumping across line boundaries
|
* FIXME: Due to the include hell, we cannot use the alias, PeekOffsetOptions
|
||||||
* @param aScrollViewStop whether to stop when reaching a scroll frame
|
* is not available in this header file.
|
||||||
* boundary
|
|
||||||
*/
|
*/
|
||||||
SelectablePeekReport GetFrameFromDirection(nsDirection aDirection,
|
SelectablePeekReport GetFrameFromDirection(
|
||||||
bool aVisual, bool aJumpLines,
|
nsDirection aDirection,
|
||||||
bool aScrollViewStop,
|
const mozilla::EnumSet<mozilla::PeekOffsetOption>& aOptions);
|
||||||
bool aForceEditableRegion);
|
|
||||||
|
|
||||||
SelectablePeekReport GetFrameFromDirection(
|
SelectablePeekReport GetFrameFromDirection(
|
||||||
const mozilla::PeekOffsetStruct& aPos);
|
const mozilla::PeekOffsetStruct& aPos);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче