Bug 1879774 [wpt PR 44524] - WebKit export: Implement field-sizing support for input...
[gecko.git] / layout / generic / SelectionMovementUtils.h
blob5d8194948815f80685ace9cf8e462c10732d54e6
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_SelectionMovementUtils_h
8 #define mozilla_SelectionMovementUtils_h
10 #include "mozilla/intl/BidiEmbeddingLevel.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/EnumSet.h"
13 #include "mozilla/Result.h"
14 #include "nsIFrame.h"
16 struct nsPrevNextBidiLevels;
18 namespace mozilla {
20 class PresShell;
21 enum class PeekOffsetOption : uint16_t;
23 namespace intl {
24 class BidiEmbeddingLevel;
27 struct MOZ_STACK_CLASS PrimaryFrameData {
28 // The frame which should be used to layout the caret.
29 nsIFrame* mFrame = nullptr;
30 // The offset in content of mFrame. This is valid only when mFrame is not
31 // nullptr.
32 uint32_t mOffsetInFrameContent = 0;
33 // Whether the caret should be put before or after the point. This is valid
34 // only when mFrame is not nullptr.
35 CaretAssociationHint mHint{0}; // Before
38 struct MOZ_STACK_CLASS CaretFrameData : public PrimaryFrameData {
39 // The frame which is found only from a DOM point. This frame becomes
40 // different from mFrame when the point is around end of a line or
41 // at a bidi text boundary.
42 nsIFrame* mUnadjustedFrame = nullptr;
45 enum class ForceEditableRegion : bool { No, Yes };
47 class SelectionMovementUtils final {
48 public:
49 using PeekOffsetOptions = EnumSet<PeekOffsetOption>;
51 /**
52 * Given a node and its child offset, return the nsIFrame and the offset into
53 * that frame.
55 * @param aNode input parameter for the node to look at
56 * TODO: Make this `const nsIContent*` for `ContentEventHandler`.
57 * @param aOffset offset into above node.
58 * @param aReturnOffset will contain offset into frame.
60 static nsIFrame* GetFrameForNodeOffset(nsIContent* aNode, uint32_t aOffset,
61 CaretAssociationHint aHint,
62 uint32_t* aReturnOffset = nullptr);
64 /**
65 * GetPrevNextBidiLevels will return the frames and associated Bidi levels of
66 * the characters logically before and after a (collapsed) selection.
68 * @param aNode is the node containing the selection
69 * @param aContentOffset is the offset of the selection in the node
70 * @param aJumpLines
71 * If true, look across line boundaries.
72 * If false, behave as if there were base-level frames at line edges.
74 * @return A struct holding the before/after frame and the before/after
75 * level.
77 * At the beginning and end of each line there is assumed to be a frame with
78 * Bidi level equal to the paragraph embedding level.
80 * In these cases the before frame and after frame respectively will be
81 * nullptr.
83 static nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent* aNode,
84 uint32_t aContentOffset,
85 CaretAssociationHint aHint,
86 bool aJumpLines);
88 /**
89 * PeekOffsetForCaretMove() only peek offset for caret move from the specified
90 * point of the normal selection. I.e., won't change selection ranges nor
91 * bidi information.
93 static Result<PeekOffsetStruct, nsresult> PeekOffsetForCaretMove(
94 nsIContent* aContent, uint32_t aOffset, nsDirection aDirection,
95 CaretAssociationHint aHint, intl::BidiEmbeddingLevel aCaretBidiLevel,
96 const nsSelectionAmount aAmount, const nsPoint& aDesiredCaretPos,
97 PeekOffsetOptions aOptions);
99 /**
100 * IsIntraLineCaretMove() is a helper method for PeekOffsetForCaretMove()
101 * and CreateRangeExtendedToSomwhereFromNormalSelection(). This returns
102 * whether aAmount is intra line move or is crossing hard line break.
103 * This returns error if aMount is not supported by the methods.
105 static Result<bool, nsresult> IsIntraLineCaretMove(
106 nsSelectionAmount aAmount) {
107 switch (aAmount) {
108 case eSelectCharacter:
109 case eSelectCluster:
110 case eSelectWord:
111 case eSelectWordNoSpace:
112 case eSelectBeginLine:
113 case eSelectEndLine:
114 return true;
115 case eSelectLine:
116 return false;
117 default:
118 return Err(NS_ERROR_FAILURE);
123 * Return a frame for considering caret geometry.
125 * @param aFrameSelection [optional] If this is specified and selection in
126 * aContent is not managed by the specified
127 * instance, return nullptr.
128 * @param aContentNode The content node where selection is collapsed.
129 * @param aOffset Collapsed position in aContentNode
130 * @param aFrameHint Caret association hint.
131 * @param aBidiLevel
132 * @param aForceEditableRegion Whether selection should be limited in
133 * editable region or not.
135 static CaretFrameData GetCaretFrameForNodeOffset(
136 const nsFrameSelection* aFrameSelection, nsIContent* aContentNode,
137 uint32_t aOffset, CaretAssociationHint aFrameHint,
138 intl::BidiEmbeddingLevel aBidiLevel,
139 ForceEditableRegion aForceEditableRegion);
141 static bool AdjustFrameForLineStart(nsIFrame*& aFrame,
142 uint32_t& aFrameOffset);
145 * Get primary frame and some other data for putting caret or extending
146 * selection at the point.
148 static PrimaryFrameData GetPrimaryFrameForCaret(
149 nsIContent* aContent, uint32_t aOffset, bool aVisual,
150 CaretAssociationHint aHint, intl::BidiEmbeddingLevel aCaretBidiLevel);
152 private:
154 * GetFrameFromLevel will scan in a given direction
155 * until it finds a frame with a Bidi level less than or equal to a given
156 * level. It will return the last frame before this.
158 * @param aPresContext is the context to use
159 * @param aFrameIn is the frame to start from
160 * @param aDirection is the direction to scan
161 * @param aBidiLevel is the level to search for
163 static Result<nsIFrame*, nsresult> GetFrameFromLevel(
164 nsIFrame* aFrameIn, nsDirection aDirection,
165 intl::BidiEmbeddingLevel aBidiLevel);
167 // This is helper method for GetPrimaryFrameForCaret.
168 // If aVisual is true, this returns caret frame.
169 // If false, this returns primary frame.
170 static PrimaryFrameData GetPrimaryOrCaretFrameForNodeOffset(
171 nsIContent* aContent, uint32_t aOffset, bool aVisual,
172 CaretAssociationHint aHint, intl::BidiEmbeddingLevel aCaretBidiLevel);
175 } // namespace mozilla
177 #endif // #ifndef mozilla_SelectionMovementUtils_h