layout/base/nsCaret.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:a63dc17a18b1
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=78: */
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/. */
6
7 /* the caret is the text cursor used, e.g., when editing */
8
9 #ifndef nsCaret_h__
10 #define nsCaret_h__
11
12 #include "nsCoord.h"
13 #include "nsISelectionListener.h"
14 #include "nsIWeakReferenceUtils.h"
15 #include "nsFrameSelection.h"
16
17 class nsRenderingContext;
18 class nsDisplayListBuilder;
19 class nsITimer;
20
21 //-----------------------------------------------------------------------------
22 class nsCaret : public nsISelectionListener
23 {
24 public:
25
26 nsCaret();
27 virtual ~nsCaret();
28
29 enum EViewCoordinates {
30 eTopLevelWindowCoordinates,
31 eRenderingViewCoordinates,
32 eClosestViewCoordinates
33 };
34
35 public:
36
37 NS_DECL_ISUPPORTS
38
39 nsresult Init(nsIPresShell *inPresShell);
40 void Terminate();
41
42 nsISelection* GetCaretDOMSelection();
43 nsresult SetCaretDOMSelection(nsISelection *inDOMSel);
44
45 /** GetCaretVisible will get the visibility of the caret
46 * This function is virtual so that it can be used by nsCaretAccessible
47 * without linking
48 * @param inMakeVisible true it is shown, false it is hidden
49 * @return false if and only if inMakeVisible is null, otherwise true
50 */
51 virtual nsresult GetCaretVisible(bool *outMakeVisible);
52
53 /** SetCaretVisible will set the visibility of the caret
54 * @param inMakeVisible true to show the caret, false to hide it
55 */
56 void SetCaretVisible(bool intMakeVisible);
57
58 /** SetCaretReadOnly set the appearance of the caret
59 * @param inMakeReadonly true to show the caret in a 'read only' state,
60 * false to show the caret in normal, editing state
61 */
62 void SetCaretReadOnly(bool inMakeReadonly);
63
64 /** GetCaretReadOnly get the appearance of the caret
65 * @return true if the caret is in 'read only' state, otherwise,
66 * returns false
67 */
68 bool GetCaretReadOnly()
69 {
70 return mReadOnly;
71 }
72
73 /**
74 * Gets the position and size of the caret that would be drawn for
75 * the focus node/offset of aSelection (assuming it would be drawn,
76 * i.e., disregarding blink status). The geometry is stored in aRect,
77 * and we return the frame aRect is relative to.
78 * @param aRect must be non-null
79 * @param aBidiIndicatorSize if non-null, set to the bidi indicator size.
80 */
81 virtual nsIFrame* GetGeometry(nsISelection* aSelection,
82 nsRect* aRect,
83 nscoord* aBidiIndicatorSize = nullptr);
84
85 /** EraseCaret
86 * this will erase the caret if its drawn and reset drawn status
87 */
88 void EraseCaret();
89
90 void SetVisibilityDuringSelection(bool aVisibility);
91
92 /** DrawAtPosition
93 *
94 * Draw the caret explicitly, at the specified node and offset.
95 * To avoid drawing glitches, you should call EraseCaret()
96 * after each call to DrawAtPosition().
97 *
98 * Note: This call breaks the caret's ability to blink at all.
99 **/
100 nsresult DrawAtPosition(nsIDOMNode* aNode, int32_t aOffset);
101
102 /** GetCaretFrame
103 * Get the current frame that the caret should be drawn in. If the caret is
104 * not currently visible (i.e., it is between blinks), then this will
105 * return null.
106 *
107 * @param aOffset is result of the caret offset in the content.
108 */
109 nsIFrame* GetCaretFrame(int32_t *aOffset = nullptr);
110
111 /** GetCaretRect
112 * Get the current caret rect. Only call this when GetCaretFrame returns
113 * non-null.
114 */
115 nsRect GetCaretRect()
116 {
117 nsRect r;
118 r.UnionRect(mCaretRect, GetHookRect());
119 return r;
120 }
121
122 /** InvalidateOutsideCaret
123 * Invalidate the area that the caret currently occupies if the caret is
124 * outside of its frame's overflow area. This is used when the content that
125 * the caret is currently drawn is is being deleted or reflowed.
126 */
127 void InvalidateOutsideCaret();
128
129 /** UpdateCaretPosition
130 * Update the caret's current frame and rect, but don't draw yet. This is
131 * useful for flickerless moving of the caret (e.g., when the frame the
132 * caret is in reflows and is moved).
133 */
134 void UpdateCaretPosition();
135
136 /** PaintCaret
137 * Actually paint the caret onto the given rendering context.
138 */
139 void PaintCaret(nsDisplayListBuilder *aBuilder,
140 nsRenderingContext *aCtx,
141 nsIFrame *aForFrame,
142 const nsPoint &aOffset);
143 /**
144 * Sets whether the caret should only be visible in nodes that are not
145 * user-modify: read-only, or whether it should be visible in all nodes.
146 *
147 * @param aIgnoreUserModify true to have the cursor visible in all nodes,
148 * false to have it visible in all nodes except
149 * those with user-modify: read-only
150 */
151
152 void SetIgnoreUserModify(bool aIgnoreUserModify);
153
154 //nsISelectionListener interface
155 NS_DECL_NSISELECTIONLISTENER
156
157 static void CaretBlinkCallback(nsITimer *aTimer, void *aClosure);
158
159 nsresult GetCaretFrameForNodeOffset(nsIContent* aContentNode,
160 int32_t aOffset,
161 nsFrameSelection::HINT aFrameHint,
162 uint8_t aBidiLevel,
163 nsIFrame** aReturnFrame,
164 int32_t* aReturnOffset);
165
166 void CheckCaretDrawingState();
167
168 protected:
169
170 void KillTimer();
171 nsresult PrimeTimer();
172
173 void StartBlinking();
174 void StopBlinking();
175
176 bool DrawAtPositionWithHint(nsIDOMNode* aNode,
177 int32_t aOffset,
178 nsFrameSelection::HINT aFrameHint,
179 uint8_t aBidiLevel,
180 bool aInvalidate);
181
182 struct Metrics {
183 nscoord mBidiIndicatorSize; // width and height of bidi indicator
184 nscoord mCaretWidth; // full caret width including bidi indicator
185 };
186 Metrics ComputeMetrics(nsIFrame* aFrame, int32_t aOffset, nscoord aCaretHeight);
187 nsresult GetGeometryForFrame(nsIFrame* aFrame,
188 int32_t aFrameOffset,
189 nsRect* aRect,
190 nscoord* aBidiIndicatorSize);
191
192 // Returns true if the caret should be drawn. When |mDrawn| is true,
193 // this returns true, so that we erase the drawn caret. If |aIgnoreDrawnState|
194 // is true, we don't take into account whether the caret is currently
195 // drawn or not. This can be used to determine if the caret is drawn when
196 // it shouldn't be.
197 bool MustDrawCaret(bool aIgnoreDrawnState);
198
199 void DrawCaret(bool aInvalidate);
200 void DrawCaretAfterBriefDelay();
201 bool UpdateCaretRects(nsIFrame* aFrame, int32_t aFrameOffset);
202 nsRect GetHookRect()
203 {
204 return mHookRect;
205 }
206 void ToggleDrawnStatus() { mDrawn = !mDrawn; }
207
208 nsFrameSelection* GetFrameSelection();
209
210 // Returns true if we should not draw the caret because of XUL menu popups.
211 // The caret should be hidden if:
212 // 1. An open popup contains the caret, but a menu popup exists before the
213 // caret-owning popup in the popup list (i.e. a menu is in front of the
214 // popup with the caret). If the menu itself contains the caret we don't
215 // hide it.
216 // 2. A menu popup is open, but there is no caret present in any popup.
217 // 3. The caret selection is empty.
218 bool IsMenuPopupHidingCaret();
219
220 protected:
221
222 nsWeakPtr mPresShell;
223 nsWeakPtr mDomSelectionWeak;
224
225 nsCOMPtr<nsITimer> mBlinkTimer;
226
227 // XXX these fields should go away and the values be acquired as needed,
228 // probably by ComputeMetrics.
229 uint32_t mBlinkRate; // time for one cyle (on then off), in milliseconds
230 nscoord mCaretWidthCSSPx; // caret width in CSS pixels
231 float mCaretAspectRatio; // caret width/height aspect ratio
232
233 bool mVisible; // is the caret blinking
234
235 bool mDrawn; // Denotes when the caret is physically drawn on the screen.
236 bool mPendingDraw; // True when the last on-state draw was suppressed.
237
238 bool mReadOnly; // it the caret in readonly state (draws differently)
239 bool mShowDuringSelection; // show when text is selected
240
241 bool mIgnoreUserModify;
242
243 bool mKeyboardRTL; // is the keyboard language right-to-left
244 bool mBidiUI; // is bidi UI turned on
245 nsRect mHookRect; // directional hook on the caret
246 uint8_t mLastBidiLevel; // saved bidi level of the last draw request, to use when we erase
247 nsRect mCaretRect; // the last caret rect, in the coodinates of the last frame.
248
249 nsCOMPtr<nsIContent> mLastContent; // store the content the caret was last requested to be drawn
250 // in (by DrawAtPosition()/DrawCaret()),
251 // note that this can be different than where it was
252 // actually drawn (anon <BR> in text control)
253 int32_t mLastContentOffset; // the offset for the last request
254
255 nsFrameSelection::HINT mLastHint; // the hint associated with the last request, see also
256 // mLastBidiLevel below
257
258 };
259
260 #endif //nsCaret_h__

mercurial