Multiple Layout Tests (e.g. fast/repaint/japanese-rl-selection-clear.html) is failing...
[WebKit-https.git] / Source / WebCore / editing / FrameSelection.h
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #ifndef FrameSelection_h
27 #define FrameSelection_h
28
29 #include "EditingStyle.h"
30 #include "IntRect.h"
31 #include "LayoutRect.h"
32 #include "Range.h"
33 #include "ScrollBehavior.h"
34 #include "Timer.h"
35 #include "VisibleSelection.h"
36 #include <wtf/Noncopyable.h>
37
38 namespace WebCore {
39
40 class CharacterData;
41 class Frame;
42 class GraphicsContext;
43 class HTMLFormElement;
44 class RenderObject;
45 class RenderView;
46 class Settings;
47 class StylePropertySet;
48 class VisiblePosition;
49
50 enum EUserTriggered { NotUserTriggered = 0, UserTriggered = 1 };
51
52 enum RevealExtentOption {
53     RevealExtent,
54     DoNotRevealExtent
55 };
56
57 class CaretBase {
58     WTF_MAKE_NONCOPYABLE(CaretBase);
59     WTF_MAKE_FAST_ALLOCATED;
60 protected:
61     enum CaretVisibility { Visible, Hidden };
62     explicit CaretBase(CaretVisibility = Hidden);
63
64     void invalidateCaretRect(Node*, bool caretRectChanged = false);
65     void clearCaretRect();
66     bool updateCaretRect(Document*, const VisiblePosition& caretPosition);
67     IntRect absoluteBoundsForLocalRect(Node*, const LayoutRect&) const;
68     IntRect caretRepaintRect(Node*) const;
69     bool shouldRepaintCaret(const RenderView*, bool isContentEditable) const;
70     void paintCaret(Node*, GraphicsContext*, const LayoutPoint&, const LayoutRect& clipRect) const;
71     RenderObject* caretRenderer(Node*) const;
72
73     const LayoutRect& localCaretRectWithoutUpdate() const { return m_caretLocalRect; }
74
75     bool shouldUpdateCaretRect() const { return m_caretRectNeedsUpdate; }
76     void setCaretRectNeedsUpdate() { m_caretRectNeedsUpdate = true; }
77
78     void setCaretVisibility(CaretVisibility visibility) { m_caretVisibility = visibility; }
79     bool caretIsVisible() const { return m_caretVisibility == Visible; }
80     CaretVisibility caretVisibility() const { return m_caretVisibility; }
81
82 private:
83     LayoutRect m_caretLocalRect; // caret rect in coords local to the renderer responsible for painting the caret
84     bool m_caretRectNeedsUpdate; // true if m_caretRect (and m_absCaretBounds in FrameSelection) need to be calculated
85     CaretVisibility m_caretVisibility;
86 };
87
88 class DragCaretController : private CaretBase {
89     WTF_MAKE_NONCOPYABLE(DragCaretController);
90     WTF_MAKE_FAST_ALLOCATED;
91 public:
92     static PassOwnPtr<DragCaretController> create();
93
94     RenderObject* caretRenderer() const;
95     void paintDragCaret(Frame*, GraphicsContext*, const LayoutPoint&, const LayoutRect& clipRect) const;
96
97     bool isContentEditable() const { return m_position.rootEditableElement(); }
98     bool isContentRichlyEditable() const;
99
100     bool hasCaret() const { return m_position.isNotNull(); }
101     const VisiblePosition& caretPosition() { return m_position; }
102     void setCaretPosition(const VisiblePosition&);
103     void clear() { setCaretPosition(VisiblePosition()); }
104
105     void nodeWillBeRemoved(Node*);
106
107 private:
108     DragCaretController();
109
110     VisiblePosition m_position;
111 };
112
113 class FrameSelection : private CaretBase {
114     WTF_MAKE_NONCOPYABLE(FrameSelection);
115     WTF_MAKE_FAST_ALLOCATED;
116 public:
117     enum EAlteration { AlterationMove, AlterationExtend };
118     enum CursorAlignOnScroll { AlignCursorOnScrollIfNeeded,
119                                AlignCursorOnScrollAlways };
120     enum SetSelectionOption {
121         // 1 << 0 is reserved for EUserTriggered
122         CloseTyping = 1 << 1,
123         ClearTypingStyle = 1 << 2,
124         SpellCorrectionTriggered = 1 << 3,
125         DoNotSetFocus = 1 << 4,
126         DictationTriggered = 1 << 5,
127         DoNotUpdateAppearance = 1 << 6,
128     };
129     typedef unsigned SetSelectionOptions; // Union of values in SetSelectionOption and EUserTriggered
130     static inline EUserTriggered selectionOptionsToUserTriggered(SetSelectionOptions options)
131     {
132         return static_cast<EUserTriggered>(options & UserTriggered);
133     }
134
135     explicit FrameSelection(Frame* = 0);
136
137     Element* rootEditableElement() const { return m_selection.rootEditableElement(); }
138     Element* rootEditableElementOrDocumentElement() const;
139     Element* rootEditableElementRespectingShadowTree() const;
140
141     bool rendererIsEditable() const { return m_selection.rendererIsEditable(); }
142     bool isContentEditable() const { return m_selection.isContentEditable(); }
143     bool isContentRichlyEditable() const { return m_selection.isContentRichlyEditable(); }
144      
145     void moveTo(const Range*, EAffinity, EUserTriggered = NotUserTriggered);
146     void moveTo(const VisiblePosition&, EUserTriggered = NotUserTriggered, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded);
147     void moveTo(const VisiblePosition&, const VisiblePosition&, EUserTriggered = NotUserTriggered);
148     void moveTo(const Position&, EAffinity, EUserTriggered = NotUserTriggered);
149     void moveTo(const Position&, const Position&, EAffinity, EUserTriggered = NotUserTriggered);
150
151     const VisibleSelection& selection() const { return m_selection; }
152     void setSelection(const VisibleSelection&, SetSelectionOptions = CloseTyping | ClearTypingStyle, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded, TextGranularity = CharacterGranularity);
153     void setSelection(const VisibleSelection& selection, TextGranularity granularity) { setSelection(selection, CloseTyping | ClearTypingStyle, AlignCursorOnScrollIfNeeded, granularity); }
154     bool setSelectedRange(Range*, EAffinity, bool closeTyping);
155     void selectAll();
156     void clear();
157     void prepareForDestruction();
158
159     // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
160     void selectFrameElementInParentIfFullySelected();
161
162     bool contains(const LayoutPoint&);
163
164     VisibleSelection::SelectionType selectionType() const { return m_selection.selectionType(); }
165
166     EAffinity affinity() const { return m_selection.affinity(); }
167
168     bool modify(EAlteration, SelectionDirection, TextGranularity, EUserTriggered = NotUserTriggered);
169     enum VerticalDirection { DirectionUp, DirectionDown };
170     bool modify(EAlteration, unsigned verticalDistance, VerticalDirection, EUserTriggered = NotUserTriggered, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded);
171
172     TextGranularity granularity() const { return m_granularity; }
173
174     void setStart(const VisiblePosition &, EUserTriggered = NotUserTriggered);
175     void setEnd(const VisiblePosition &, EUserTriggered = NotUserTriggered);
176     
177     void setBase(const VisiblePosition&, EUserTriggered = NotUserTriggered);
178     void setBase(const Position&, EAffinity, EUserTriggered = NotUserTriggered);
179     void setExtent(const VisiblePosition&, EUserTriggered = NotUserTriggered);
180     void setExtent(const Position&, EAffinity, EUserTriggered = NotUserTriggered);
181
182     Position base() const { return m_selection.base(); }
183     Position extent() const { return m_selection.extent(); }
184     Position start() const { return m_selection.start(); }
185     Position end() const { return m_selection.end(); }
186
187     // Return the renderer that is responsible for painting the caret (in the selection start node)
188     RenderObject* caretRenderer() const;
189
190     // Caret rect local to the caret's renderer
191     LayoutRect localCaretRect();
192
193     // Bounds of (possibly transformed) caret in absolute coords
194     IntRect absoluteCaretBounds();
195     void setCaretRectNeedsUpdate() { CaretBase::setCaretRectNeedsUpdate(); }
196
197     void willBeModified(EAlteration, SelectionDirection);
198
199     bool isNone() const { return m_selection.isNone(); }
200     bool isCaret() const { return m_selection.isCaret(); }
201     bool isRange() const { return m_selection.isRange(); }
202     bool isCaretOrRange() const { return m_selection.isCaretOrRange(); }
203     bool isInPasswordField() const;
204     bool isAll(EditingBoundaryCrossingRule rule = CannotCrossEditingBoundary) const { return m_selection.isAll(rule); }
205     
206     PassRefPtr<Range> toNormalizedRange() const { return m_selection.toNormalizedRange(); }
207
208     void debugRenderer(RenderObject*, bool selected) const;
209
210     void nodeWillBeRemoved(Node*);
211     void textWasReplaced(CharacterData*, unsigned offset, unsigned oldLength, unsigned newLength);
212
213     void setCaretVisible(bool caretIsVisible) { setCaretVisibility(caretIsVisible ? Visible : Hidden); }
214     bool recomputeCaretRect();
215     void invalidateCaretRect();
216     void paintCaret(GraphicsContext*, const LayoutPoint&, const LayoutRect& clipRect);
217
218     // Used to suspend caret blinking while the mouse is down.
219     void setCaretBlinkingSuspended(bool suspended) { m_isCaretBlinkingSuspended = suspended; }
220     bool isCaretBlinkingSuspended() const { return m_isCaretBlinkingSuspended; }
221
222     // Focus
223     void setFocused(bool);
224     bool isFocused() const { return m_focused; }
225     bool isFocusedAndActive() const;
226     void pageActivationChanged();
227
228     // Painting.
229     void updateAppearance();
230
231     void updateSecureKeyboardEntryIfActive();
232
233 #ifndef NDEBUG
234     void formatForDebugger(char* buffer, unsigned length) const;
235     void showTreeForThis() const;
236 #endif
237
238     bool shouldChangeSelection(const VisibleSelection&) const;
239     bool shouldDeleteSelection(const VisibleSelection&) const;
240     enum EndPointsAdjustmentMode { AdjustEndpointsAtBidiBoundary, DoNotAdjsutEndpoints };
241     void setNonDirectionalSelectionIfNeeded(const VisibleSelection&, TextGranularity, EndPointsAdjustmentMode = DoNotAdjsutEndpoints);
242     void setFocusedNodeIfNeeded();
243     void notifyRendererOfSelectionChange(EUserTriggered);
244
245     void paintDragCaret(GraphicsContext*, const LayoutPoint&, const LayoutRect& clipRect) const;
246
247     EditingStyle* typingStyle() const;
248     PassRefPtr<StylePropertySet> copyTypingStyle() const;
249     void setTypingStyle(PassRefPtr<EditingStyle>);
250     void clearTypingStyle();
251
252     FloatRect bounds(bool clipToVisibleContent = true) const;
253
254     void getClippedVisibleTextRectangles(Vector<FloatRect>&) const;
255
256     HTMLFormElement* currentForm() const;
257
258     void revealSelection(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);
259     void setSelectionFromNone();
260
261 private:
262     enum EPositionType { START, END, BASE, EXTENT };
263
264     void respondToNodeModification(Node*, bool baseRemoved, bool extentRemoved, bool startRemoved, bool endRemoved);
265     TextDirection directionOfEnclosingBlock();
266     TextDirection directionOfSelection();
267
268     VisiblePosition positionForPlatform(bool isGetStart) const;
269     VisiblePosition startForPlatform() const;
270     VisiblePosition endForPlatform() const;
271
272     VisiblePosition modifyExtendingRight(TextGranularity);
273     VisiblePosition modifyExtendingForward(TextGranularity);
274     VisiblePosition modifyMovingRight(TextGranularity);
275     VisiblePosition modifyMovingForward(TextGranularity);
276     VisiblePosition modifyExtendingLeft(TextGranularity);
277     VisiblePosition modifyExtendingBackward(TextGranularity);
278     VisiblePosition modifyMovingLeft(TextGranularity);
279     VisiblePosition modifyMovingBackward(TextGranularity);
280
281     LayoutUnit lineDirectionPointForBlockDirectionNavigation(EPositionType);
282     
283     void notifyAccessibilityForSelectionChange();
284
285     void focusedOrActiveStateChanged();
286
287     void caretBlinkTimerFired(Timer<FrameSelection>*);
288
289     void setUseSecureKeyboardEntry(bool);
290
291     void setCaretVisibility(CaretVisibility);
292
293     bool dispatchSelectStart();
294   
295     bool visualWordMovementEnabled() const;
296
297     Frame* m_frame;
298
299     LayoutUnit m_xPosForVerticalArrowNavigation;
300
301     VisibleSelection m_selection;
302     VisiblePosition m_originalBase; // Used to store base before the adjustment at bidi boundary
303     TextGranularity m_granularity;
304
305     RefPtr<EditingStyle> m_typingStyle;
306
307     Timer<FrameSelection> m_caretBlinkTimer;
308     // The painted bounds of the caret in absolute coordinates
309     IntRect m_absCaretBounds;
310     // Similar to above, but inflated to ensure proper repaint (see https://bugs.webkit.org/show_bug.cgi?id=19086)
311     IntRect m_absoluteCaretRepaintBounds;
312     bool m_absCaretBoundsDirty : 1;
313     bool m_caretPaint : 1;
314     bool m_isCaretBlinkingSuspended : 1;
315     bool m_focused : 1;
316 };
317
318 inline EditingStyle* FrameSelection::typingStyle() const
319 {
320     return m_typingStyle.get();
321 }
322
323 inline void FrameSelection::clearTypingStyle()
324 {
325     m_typingStyle.clear();
326 }
327
328 inline void FrameSelection::setTypingStyle(PassRefPtr<EditingStyle> style)
329 {
330     m_typingStyle = style;
331 }
332
333 #if !(PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(CHROMIUM))
334 inline void FrameSelection::notifyAccessibilityForSelectionChange()
335 {
336 }
337 #endif
338
339 } // namespace WebCore
340
341 #ifndef NDEBUG
342 // Outside the WebCore namespace for ease of invocation from gdb.
343 void showTree(const WebCore::FrameSelection&);
344 void showTree(const WebCore::FrameSelection*);
345 #endif
346
347 #endif // FrameSelection_h