2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef FrameSelection_h
27 #define FrameSelection_h
29 #include "core/CoreExport.h"
30 #include "core/dom/Range.h"
31 #include "core/editing/CaretBase.h"
32 #include "core/editing/EditingStyle.h"
33 #include "core/editing/EphemeralRange.h"
34 #include "core/editing/VisiblePosition.h"
35 #include "core/editing/VisibleSelection.h"
36 #include "core/layout/ScrollAlignment.h"
37 #include "platform/Timer.h"
38 #include "platform/geometry/IntRect.h"
39 #include "platform/geometry/LayoutRect.h"
40 #include "platform/heap/Handle.h"
41 #include "wtf/Noncopyable.h"
47 class GranularityStrategy
;
48 class GraphicsContext
;
49 class HTMLFormElement
;
50 class SelectionEditor
;
51 class PendingSelection
;
54 enum class CursorAlignOnScroll
{ IfNeeded
, Always
};
56 enum EUserTriggered
{ NotUserTriggered
= 0, UserTriggered
= 1 };
58 enum RevealExtentOption
{
63 enum class SelectionDirectionalMode
{ NonDirectional
, Directional
};
65 class CORE_EXPORT FrameSelection final
: public NoBaseWillBeGarbageCollectedFinalized
<FrameSelection
>, private CaretBase
{
66 WTF_MAKE_NONCOPYABLE(FrameSelection
);
67 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED(FrameSelection
);
69 static PassOwnPtrWillBeRawPtr
<FrameSelection
> create(LocalFrame
* frame
= nullptr)
71 return adoptPtrWillBeNoop(new FrameSelection(frame
));
75 enum EAlteration
{ AlterationMove
, AlterationExtend
};
76 enum SetSelectionOption
{
77 // 1 << 0 is reserved for EUserTriggered
79 ClearTypingStyle
= 1 << 2,
80 SpellCorrectionTriggered
= 1 << 3,
81 DoNotSetFocus
= 1 << 4,
82 DoNotUpdateAppearance
= 1 << 5,
83 DoNotClearStrategy
= 1 << 6,
85 typedef unsigned SetSelectionOptions
; // Union of values in SetSelectionOption and EUserTriggered
86 static inline EUserTriggered
selectionOptionsToUserTriggered(SetSelectionOptions options
)
88 return static_cast<EUserTriggered
>(options
& UserTriggered
);
91 enum ResetCaretBlinkOption
{
96 LocalFrame
* frame() const { return m_frame
; }
97 Element
* rootEditableElement() const { return selection().rootEditableElement(); }
98 Element
* rootEditableElementOrDocumentElement() const;
99 ContainerNode
* rootEditableElementOrTreeScopeRootNode() const;
101 bool hasEditableStyle() const { return selection().hasEditableStyle(); }
102 bool isContentEditable() const { return selection().isContentEditable(); }
103 bool isContentRichlyEditable() const { return selection().isContentRichlyEditable(); }
105 void moveTo(const VisiblePosition
&, EUserTriggered
= NotUserTriggered
, CursorAlignOnScroll
= CursorAlignOnScroll::IfNeeded
);
106 void moveTo(const VisiblePosition
&, const VisiblePosition
&, EUserTriggered
= NotUserTriggered
);
107 void moveTo(const Position
&, TextAffinity
, EUserTriggered
= NotUserTriggered
);
109 template <typename Strategy
>
110 VisibleSelectionTemplate
<Strategy
> visibleSelection() const;
112 const VisibleSelection
& selection() const;
113 void setSelection(const VisibleSelection
&, SetSelectionOptions
= CloseTyping
| ClearTypingStyle
, CursorAlignOnScroll
= CursorAlignOnScroll::IfNeeded
, TextGranularity
= CharacterGranularity
);
114 void setSelection(const VisibleSelection
& selection
, TextGranularity granularity
) { setSelection(selection
, CloseTyping
| ClearTypingStyle
, CursorAlignOnScroll::IfNeeded
, granularity
); }
115 // TODO(yosin) We should get rid of |Range| version of |setSelectedRagne()|
117 bool setSelectedRange(Range
*, TextAffinity
, SelectionDirectionalMode
= SelectionDirectionalMode::NonDirectional
, SetSelectionOptions
= CloseTyping
| ClearTypingStyle
);
118 bool setSelectedRange(const EphemeralRange
&, TextAffinity
, SelectionDirectionalMode
= SelectionDirectionalMode::NonDirectional
, FrameSelection::SetSelectionOptions
= CloseTyping
| ClearTypingStyle
);
121 void prepareForDestruction();
123 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
124 void selectFrameElementInParentIfFullySelected();
126 bool contains(const LayoutPoint
&);
128 SelectionType
selectionType() const { return selection().selectionType(); }
130 TextAffinity
affinity() const { return selection().affinity(); }
132 bool modify(EAlteration
, SelectionDirection
, TextGranularity
, EUserTriggered
= NotUserTriggered
);
133 enum VerticalDirection
{ DirectionUp
, DirectionDown
};
134 bool modify(EAlteration
, unsigned verticalDistance
, VerticalDirection
, EUserTriggered
= NotUserTriggered
, CursorAlignOnScroll
= CursorAlignOnScroll::IfNeeded
);
136 // Moves the selection extent based on the selection granularity strategy.
137 // This function does not allow the selection to collapse. If the new
138 // extent is resolved to the same position as the current base, this
139 // function will do nothing.
140 void moveRangeSelectionExtent(const IntPoint
&);
141 void moveRangeSelection(const VisiblePosition
& base
, const VisiblePosition
& extent
, TextGranularity
);
143 TextGranularity
granularity() const { return m_granularity
; }
145 void setStart(const VisiblePosition
&, EUserTriggered
= NotUserTriggered
);
146 void setEnd(const VisiblePosition
&, EUserTriggered
= NotUserTriggered
);
148 void setBase(const VisiblePosition
&, EUserTriggered
= NotUserTriggered
);
149 void setExtent(const VisiblePosition
&, EUserTriggered
= NotUserTriggered
);
151 Position
base() const { return selection().base(); }
152 Position
extent() const { return selection().extent(); }
153 Position
start() const { return selection().start(); }
154 Position
end() const { return selection().end(); }
156 // Return the layoutObject that is responsible for painting the caret (in the selection start node)
157 LayoutBlock
* caretLayoutObject() const;
159 // Bounds of (possibly transformed) caret in absolute coords
160 IntRect
absoluteCaretBounds();
162 void didChangeFocus();
164 bool isNone() const { return selection().isNone(); }
165 bool isCaret() const { return selection().isCaret(); }
166 bool isRange() const { return selection().isRange(); }
167 bool isCaretOrRange() const { return selection().isCaretOrRange(); }
168 bool isInPasswordField() const;
169 bool isDirectional() const { return selection().isDirectional(); }
171 // If this FrameSelection has a logical range which is still valid, this function return its clone. Otherwise,
172 // the return value from underlying VisibleSelection's firstRange() is returned.
173 PassRefPtrWillBeRawPtr
<Range
> firstRange() const;
175 void nodeWillBeRemoved(Node
&);
176 void didUpdateCharacterData(CharacterData
*, unsigned offset
, unsigned oldLength
, unsigned newLength
);
177 void didMergeTextNodes(const Text
& oldNode
, unsigned offset
);
178 void didSplitTextNode(const Text
& oldNode
);
180 bool isApperanceDirty() const;
181 void commitAppearanceIfNeeded(LayoutView
&);
182 void updateAppearance(ResetCaretBlinkOption
= None
);
183 void setCaretVisible(bool caretIsVisible
) { setCaretVisibility(caretIsVisible
? Visible
: Hidden
); }
184 bool isCaretBoundsDirty() const { return m_caretRectDirty
; }
185 void setCaretRectNeedsUpdate();
186 void scheduleVisualUpdate() const;
187 void invalidateCaretRect();
188 void paintCaret(GraphicsContext
*, const LayoutPoint
&, const LayoutRect
& clipRect
);
189 bool ShouldPaintCaretForTesting() const { return m_shouldPaintCaret
; }
191 // Used to suspend caret blinking while the mouse is down.
192 void setCaretBlinkingSuspended(bool suspended
) { m_isCaretBlinkingSuspended
= suspended
; }
193 bool isCaretBlinkingSuspended() const { return m_isCaretBlinkingSuspended
; }
196 void setFocused(bool);
197 bool isFocused() const { return m_focused
; }
198 bool isFocusedAndActive() const;
199 void pageActivationChanged();
201 void updateSecureKeyboardEntryIfActive();
203 // Returns true if a word is selected.
204 bool selectWordAroundPosition(const VisiblePosition
&);
207 void formatForDebugger(char* buffer
, unsigned length
) const;
208 void showTreeForThis() const;
211 enum EndPointsAdjustmentMode
{ AdjustEndpointsAtBidiBoundary
, DoNotAdjsutEndpoints
};
212 void setNonDirectionalSelectionIfNeeded(const VisibleSelection
&, TextGranularity
, EndPointsAdjustmentMode
= DoNotAdjsutEndpoints
);
213 void setFocusedNodeIfNeeded();
214 void notifyLayoutObjectOfSelectionChange(EUserTriggered
);
216 EditingStyle
* typingStyle() const;
217 void setTypingStyle(PassRefPtrWillBeRawPtr
<EditingStyle
>);
218 void clearTypingStyle();
220 String
selectedHTMLForClipboard() const;
221 String
selectedText() const;
222 String
selectedTextForClipboard() const;
224 // The bounds are clipped to the viewport as this is what callers expect.
225 LayoutRect
bounds() const;
226 LayoutRect
unclippedBounds() const;
228 HTMLFormElement
* currentForm() const;
230 void revealSelection(const ScrollAlignment
& = ScrollAlignment::alignCenterIfNeeded
, RevealExtentOption
= DoNotRevealExtent
);
231 void setSelectionFromNone();
233 bool shouldShowBlockCursor() const { return m_shouldShowBlockCursor
; }
234 void setShouldShowBlockCursor(bool);
236 DECLARE_VIRTUAL_TRACE();
239 explicit FrameSelection(LocalFrame
*);
241 template <typename Strategy
>
242 VisiblePositionTemplate
<Strategy
> originalBase() const;
243 void setOriginalBase(const VisiblePosition
& newBase
) { m_originalBase
= newBase
; }
244 void setOriginalBase(const VisiblePositionInComposedTree
&);
246 template <typename Strategy
>
247 bool containsAlgorithm(const LayoutPoint
&);
249 template <typename Strategy
>
250 void setNonDirectionalSelectionIfNeededAlgorithm(const VisibleSelectionTemplate
<Strategy
>&, TextGranularity
, EndPointsAdjustmentMode
);
252 void respondToNodeModification(Node
&, bool baseRemoved
, bool extentRemoved
, bool startRemoved
, bool endRemoved
);
254 void notifyAccessibilityForSelectionChange();
255 void notifyCompositorForSelectionChange();
256 void notifyEventHandlerForSelectionChange();
258 void focusedOrActiveStateChanged();
260 void caretBlinkTimerFired(Timer
<FrameSelection
>*);
262 void setUseSecureKeyboardEntry(bool);
264 void setCaretVisibility(CaretVisibility
);
265 bool shouldBlinkCaret() const;
267 void updateSelectionIfNeeded(const Position
& base
, const Position
& extent
, const Position
& start
, const Position
& end
);
269 VisibleSelection
validateSelection(const VisibleSelection
&);
271 GranularityStrategy
* granularityStrategy();
273 RawPtrWillBeMember
<LocalFrame
> m_frame
;
274 const OwnPtrWillBeMember
<PendingSelection
> m_pendingSelection
;
275 const OwnPtrWillBeMember
<SelectionEditor
> m_selectionEditor
;
277 VisiblePosition m_originalBase
; // Used to store base before the adjustment at bidi boundary
278 TextGranularity m_granularity
;
280 RefPtrWillBeMember
<Node
> m_previousCaretNode
; // The last node which painted the caret. Retained for clearing the old caret when it moves.
281 LayoutRect m_previousCaretRect
;
282 CaretVisibility m_previousCaretVisibility
;
284 RefPtrWillBeMember
<EditingStyle
> m_typingStyle
;
286 Timer
<FrameSelection
> m_caretBlinkTimer
;
288 bool m_caretRectDirty
: 1;
289 bool m_shouldPaintCaret
: 1;
290 bool m_isCaretBlinkingSuspended
: 1;
292 bool m_shouldShowBlockCursor
: 1;
294 // Controls text granularity used to adjust the selection's extent in moveRangeSelectionExtent.
295 OwnPtr
<GranularityStrategy
> m_granularityStrategy
;
298 inline EditingStyle
* FrameSelection::typingStyle() const
300 return m_typingStyle
.get();
303 inline void FrameSelection::clearTypingStyle()
305 m_typingStyle
.clear();
308 inline void FrameSelection::setTypingStyle(PassRefPtrWillBeRawPtr
<EditingStyle
> style
)
310 m_typingStyle
= style
;
315 // Outside the WebCore namespace for ease of invocation from gdb.
316 void showTree(const blink::FrameSelection
&);
317 void showTree(const blink::FrameSelection
*);
320 #endif // FrameSelection_h