1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/base/nsCaret.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,260 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 sw=2 et tw=78: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* the caret is the text cursor used, e.g., when editing */ 1.11 + 1.12 +#ifndef nsCaret_h__ 1.13 +#define nsCaret_h__ 1.14 + 1.15 +#include "nsCoord.h" 1.16 +#include "nsISelectionListener.h" 1.17 +#include "nsIWeakReferenceUtils.h" 1.18 +#include "nsFrameSelection.h" 1.19 + 1.20 +class nsRenderingContext; 1.21 +class nsDisplayListBuilder; 1.22 +class nsITimer; 1.23 + 1.24 +//----------------------------------------------------------------------------- 1.25 +class nsCaret : public nsISelectionListener 1.26 +{ 1.27 + public: 1.28 + 1.29 + nsCaret(); 1.30 + virtual ~nsCaret(); 1.31 + 1.32 + enum EViewCoordinates { 1.33 + eTopLevelWindowCoordinates, 1.34 + eRenderingViewCoordinates, 1.35 + eClosestViewCoordinates 1.36 + }; 1.37 + 1.38 + public: 1.39 + 1.40 + NS_DECL_ISUPPORTS 1.41 + 1.42 + nsresult Init(nsIPresShell *inPresShell); 1.43 + void Terminate(); 1.44 + 1.45 + nsISelection* GetCaretDOMSelection(); 1.46 + nsresult SetCaretDOMSelection(nsISelection *inDOMSel); 1.47 + 1.48 + /** GetCaretVisible will get the visibility of the caret 1.49 + * This function is virtual so that it can be used by nsCaretAccessible 1.50 + * without linking 1.51 + * @param inMakeVisible true it is shown, false it is hidden 1.52 + * @return false if and only if inMakeVisible is null, otherwise true 1.53 + */ 1.54 + virtual nsresult GetCaretVisible(bool *outMakeVisible); 1.55 + 1.56 + /** SetCaretVisible will set the visibility of the caret 1.57 + * @param inMakeVisible true to show the caret, false to hide it 1.58 + */ 1.59 + void SetCaretVisible(bool intMakeVisible); 1.60 + 1.61 + /** SetCaretReadOnly set the appearance of the caret 1.62 + * @param inMakeReadonly true to show the caret in a 'read only' state, 1.63 + * false to show the caret in normal, editing state 1.64 + */ 1.65 + void SetCaretReadOnly(bool inMakeReadonly); 1.66 + 1.67 + /** GetCaretReadOnly get the appearance of the caret 1.68 + * @return true if the caret is in 'read only' state, otherwise, 1.69 + * returns false 1.70 + */ 1.71 + bool GetCaretReadOnly() 1.72 + { 1.73 + return mReadOnly; 1.74 + } 1.75 + 1.76 + /** 1.77 + * Gets the position and size of the caret that would be drawn for 1.78 + * the focus node/offset of aSelection (assuming it would be drawn, 1.79 + * i.e., disregarding blink status). The geometry is stored in aRect, 1.80 + * and we return the frame aRect is relative to. 1.81 + * @param aRect must be non-null 1.82 + * @param aBidiIndicatorSize if non-null, set to the bidi indicator size. 1.83 + */ 1.84 + virtual nsIFrame* GetGeometry(nsISelection* aSelection, 1.85 + nsRect* aRect, 1.86 + nscoord* aBidiIndicatorSize = nullptr); 1.87 + 1.88 + /** EraseCaret 1.89 + * this will erase the caret if its drawn and reset drawn status 1.90 + */ 1.91 + void EraseCaret(); 1.92 + 1.93 + void SetVisibilityDuringSelection(bool aVisibility); 1.94 + 1.95 + /** DrawAtPosition 1.96 + * 1.97 + * Draw the caret explicitly, at the specified node and offset. 1.98 + * To avoid drawing glitches, you should call EraseCaret() 1.99 + * after each call to DrawAtPosition(). 1.100 + * 1.101 + * Note: This call breaks the caret's ability to blink at all. 1.102 + **/ 1.103 + nsresult DrawAtPosition(nsIDOMNode* aNode, int32_t aOffset); 1.104 + 1.105 + /** GetCaretFrame 1.106 + * Get the current frame that the caret should be drawn in. If the caret is 1.107 + * not currently visible (i.e., it is between blinks), then this will 1.108 + * return null. 1.109 + * 1.110 + * @param aOffset is result of the caret offset in the content. 1.111 + */ 1.112 + nsIFrame* GetCaretFrame(int32_t *aOffset = nullptr); 1.113 + 1.114 + /** GetCaretRect 1.115 + * Get the current caret rect. Only call this when GetCaretFrame returns 1.116 + * non-null. 1.117 + */ 1.118 + nsRect GetCaretRect() 1.119 + { 1.120 + nsRect r; 1.121 + r.UnionRect(mCaretRect, GetHookRect()); 1.122 + return r; 1.123 + } 1.124 + 1.125 + /** InvalidateOutsideCaret 1.126 + * Invalidate the area that the caret currently occupies if the caret is 1.127 + * outside of its frame's overflow area. This is used when the content that 1.128 + * the caret is currently drawn is is being deleted or reflowed. 1.129 + */ 1.130 + void InvalidateOutsideCaret(); 1.131 + 1.132 + /** UpdateCaretPosition 1.133 + * Update the caret's current frame and rect, but don't draw yet. This is 1.134 + * useful for flickerless moving of the caret (e.g., when the frame the 1.135 + * caret is in reflows and is moved). 1.136 + */ 1.137 + void UpdateCaretPosition(); 1.138 + 1.139 + /** PaintCaret 1.140 + * Actually paint the caret onto the given rendering context. 1.141 + */ 1.142 + void PaintCaret(nsDisplayListBuilder *aBuilder, 1.143 + nsRenderingContext *aCtx, 1.144 + nsIFrame *aForFrame, 1.145 + const nsPoint &aOffset); 1.146 + /** 1.147 + * Sets whether the caret should only be visible in nodes that are not 1.148 + * user-modify: read-only, or whether it should be visible in all nodes. 1.149 + * 1.150 + * @param aIgnoreUserModify true to have the cursor visible in all nodes, 1.151 + * false to have it visible in all nodes except 1.152 + * those with user-modify: read-only 1.153 + */ 1.154 + 1.155 + void SetIgnoreUserModify(bool aIgnoreUserModify); 1.156 + 1.157 + //nsISelectionListener interface 1.158 + NS_DECL_NSISELECTIONLISTENER 1.159 + 1.160 + static void CaretBlinkCallback(nsITimer *aTimer, void *aClosure); 1.161 + 1.162 + nsresult GetCaretFrameForNodeOffset(nsIContent* aContentNode, 1.163 + int32_t aOffset, 1.164 + nsFrameSelection::HINT aFrameHint, 1.165 + uint8_t aBidiLevel, 1.166 + nsIFrame** aReturnFrame, 1.167 + int32_t* aReturnOffset); 1.168 + 1.169 + void CheckCaretDrawingState(); 1.170 + 1.171 +protected: 1.172 + 1.173 + void KillTimer(); 1.174 + nsresult PrimeTimer(); 1.175 + 1.176 + void StartBlinking(); 1.177 + void StopBlinking(); 1.178 + 1.179 + bool DrawAtPositionWithHint(nsIDOMNode* aNode, 1.180 + int32_t aOffset, 1.181 + nsFrameSelection::HINT aFrameHint, 1.182 + uint8_t aBidiLevel, 1.183 + bool aInvalidate); 1.184 + 1.185 + struct Metrics { 1.186 + nscoord mBidiIndicatorSize; // width and height of bidi indicator 1.187 + nscoord mCaretWidth; // full caret width including bidi indicator 1.188 + }; 1.189 + Metrics ComputeMetrics(nsIFrame* aFrame, int32_t aOffset, nscoord aCaretHeight); 1.190 + nsresult GetGeometryForFrame(nsIFrame* aFrame, 1.191 + int32_t aFrameOffset, 1.192 + nsRect* aRect, 1.193 + nscoord* aBidiIndicatorSize); 1.194 + 1.195 + // Returns true if the caret should be drawn. When |mDrawn| is true, 1.196 + // this returns true, so that we erase the drawn caret. If |aIgnoreDrawnState| 1.197 + // is true, we don't take into account whether the caret is currently 1.198 + // drawn or not. This can be used to determine if the caret is drawn when 1.199 + // it shouldn't be. 1.200 + bool MustDrawCaret(bool aIgnoreDrawnState); 1.201 + 1.202 + void DrawCaret(bool aInvalidate); 1.203 + void DrawCaretAfterBriefDelay(); 1.204 + bool UpdateCaretRects(nsIFrame* aFrame, int32_t aFrameOffset); 1.205 + nsRect GetHookRect() 1.206 + { 1.207 + return mHookRect; 1.208 + } 1.209 + void ToggleDrawnStatus() { mDrawn = !mDrawn; } 1.210 + 1.211 + nsFrameSelection* GetFrameSelection(); 1.212 + 1.213 + // Returns true if we should not draw the caret because of XUL menu popups. 1.214 + // The caret should be hidden if: 1.215 + // 1. An open popup contains the caret, but a menu popup exists before the 1.216 + // caret-owning popup in the popup list (i.e. a menu is in front of the 1.217 + // popup with the caret). If the menu itself contains the caret we don't 1.218 + // hide it. 1.219 + // 2. A menu popup is open, but there is no caret present in any popup. 1.220 + // 3. The caret selection is empty. 1.221 + bool IsMenuPopupHidingCaret(); 1.222 + 1.223 +protected: 1.224 + 1.225 + nsWeakPtr mPresShell; 1.226 + nsWeakPtr mDomSelectionWeak; 1.227 + 1.228 + nsCOMPtr<nsITimer> mBlinkTimer; 1.229 + 1.230 + // XXX these fields should go away and the values be acquired as needed, 1.231 + // probably by ComputeMetrics. 1.232 + uint32_t mBlinkRate; // time for one cyle (on then off), in milliseconds 1.233 + nscoord mCaretWidthCSSPx; // caret width in CSS pixels 1.234 + float mCaretAspectRatio; // caret width/height aspect ratio 1.235 + 1.236 + bool mVisible; // is the caret blinking 1.237 + 1.238 + bool mDrawn; // Denotes when the caret is physically drawn on the screen. 1.239 + bool mPendingDraw; // True when the last on-state draw was suppressed. 1.240 + 1.241 + bool mReadOnly; // it the caret in readonly state (draws differently) 1.242 + bool mShowDuringSelection; // show when text is selected 1.243 + 1.244 + bool mIgnoreUserModify; 1.245 + 1.246 + bool mKeyboardRTL; // is the keyboard language right-to-left 1.247 + bool mBidiUI; // is bidi UI turned on 1.248 + nsRect mHookRect; // directional hook on the caret 1.249 + uint8_t mLastBidiLevel; // saved bidi level of the last draw request, to use when we erase 1.250 + nsRect mCaretRect; // the last caret rect, in the coodinates of the last frame. 1.251 + 1.252 + nsCOMPtr<nsIContent> mLastContent; // store the content the caret was last requested to be drawn 1.253 + // in (by DrawAtPosition()/DrawCaret()), 1.254 + // note that this can be different than where it was 1.255 + // actually drawn (anon <BR> in text control) 1.256 + int32_t mLastContentOffset; // the offset for the last request 1.257 + 1.258 + nsFrameSelection::HINT mLastHint; // the hint associated with the last request, see also 1.259 + // mLastBidiLevel below 1.260 + 1.261 +}; 1.262 + 1.263 +#endif //nsCaret_h__