Fix bug 74404: show caret drag feedback. r=brade, sr=kin

This commit is contained in:
sfraser%netscape.com 2003-02-27 23:09:51 +00:00
Родитель 81e95afad3
Коммит 0fce5c3a3b
13 изменённых файлов: 421 добавлений и 307 удалений

Просмотреть файл

@ -385,6 +385,8 @@ nsHTMLEditor::InstallEventListeners()
NS_ASSERTION(mDocWeak, "no document set on this editor");
if (!mDocWeak) return NS_ERROR_NOT_INITIALIZED;
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsresult result;
// get a key listener
result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
@ -421,7 +423,8 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n");
}
// get a drag listener
result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), this);
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShellWeak);
result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), presShell, this);
if (NS_FAILED(result)) {
HandleEventListenerError();
return result;
@ -4216,7 +4219,8 @@ nsHTMLEditor::SetCompositionString(const nsAString& aCompositionString, nsIPriva
mIMEBufferLength = aCompositionString.Length();
ps->GetCaret(getter_AddRefs(caretP));
caretP->SetCaretDOMSelection(selection);
if (caretP)
caretP->SetCaretDOMSelection(selection);
// second part of 23558 fix:
if (aCompositionString.IsEmpty())

Просмотреть файл

@ -52,6 +52,7 @@
#include "nsIEditor.h"
#include "nsIPlaintextEditor.h"
#include "nsICaret.h"
/** The nsTextEditorKeyListener public nsIDOMKeyListener
* This class will delegate events to its editor according to the translation
@ -207,7 +208,8 @@ public:
/** SetEditor gives an address to the editor that will be accessed
* @param aEditor the editor this listener calls for editing operations
*/
void SetEditor(nsIEditor *aEditor){mEditor = aEditor;}
void SetEditor(nsIEditor *aEditor) { mEditor = aEditor; }
void SetPresShell(nsIPresShell *aPresShell) { mPresShell = aPresShell; }
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
@ -222,7 +224,16 @@ public:
/*END implementations of dragevent handler interface*/
protected:
PRBool CanDrop(nsIDOMEvent* aEvent);
protected:
nsIEditor* mEditor;
nsIPresShell* mPresShell;
nsCOMPtr<nsICaret> mCaret;
PRBool mCaretDrawn;
};
@ -272,7 +283,8 @@ extern nsresult NS_NewEditorTextListener(nsIDOMEventListener** aInstancePtrResul
/** factory for the editor drag listener
*/
extern nsresult NS_NewEditorDragListener(nsIDOMEventListener ** aInstancePtrResult, nsIEditor *aEditor);
extern nsresult NS_NewEditorDragListener(nsIDOMEventListener ** aInstancePtrResult, nsIPresShell* aPresShell,
nsIEditor *aEditor);
/** factory for the editor composition listener
*/

Просмотреть файл

@ -361,6 +361,8 @@ nsPlaintextEditor::InstallEventListeners()
NS_ASSERTION(mDocWeak, "no document set on this editor");
if (!mDocWeak) return NS_ERROR_NOT_INITIALIZED;
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsresult result;
// get a key listener
result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
@ -397,7 +399,8 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n");
}
// get a drag listener
result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), this);
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShellWeak);
result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), presShell, this);
if (NS_FAILED(result)) {
HandleEventListenerError();
return result;
@ -1958,7 +1961,8 @@ nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsI
mIMEBufferLength = aCompositionString.Length();
ps->GetCaret(getter_AddRefs(caretP));
caretP->SetCaretDOMSelection(selection);
if (caretP)
caretP->SetCaretDOMSelection(selection);
// second part of 23558 fix:
if (aCompositionString.IsEmpty())

Просмотреть файл

@ -96,6 +96,9 @@ nsCaret::nsCaret()
, mLastCaretFrame(nsnull)
, mLastCaretView(nsnull)
, mLastContentOffset(0)
#ifdef IBMBIDI
, mKeyboardRTL(PR_FALSE)
#endif
{
}
@ -109,52 +112,56 @@ nsCaret::~nsCaret()
//-----------------------------------------------------------------------------
NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell)
{
if (!inPresShell)
return NS_ERROR_NULL_POINTER;
NS_ENSURE_ARG(inPresShell);
mPresShell = getter_AddRefs(NS_GetWeakReference(inPresShell)); // the presshell owns us, so no addref
NS_ASSERTION(mPresShell, "Hey, pres shell should support weak refs");
nsILookAndFeel* touchyFeely;
if (NS_SUCCEEDED(nsComponentManager::CreateInstance(kLookAndFeelCID, nsnull, NS_GET_IID(nsILookAndFeel), (void**)&touchyFeely)))
// get nsILookAndFeel from the pres context, which has one cached.
nsCOMPtr<nsILookAndFeel> lookAndFeel;
nsCOMPtr<nsIPresContext> presContext;
inPresShell->GetPresContext(getter_AddRefs(presContext));
if (presContext)
presContext->GetLookAndFeel(getter_AddRefs(lookAndFeel));
if (lookAndFeel)
{
PRInt32 tempInt;
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, tempInt)))
mCaretTwipsWidth = (nscoord)tempInt;
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt)))
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, tempInt)))
mCaretPixelsWidth = (nscoord)tempInt;
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt)))
mBlinkRate = (PRUint32)tempInt;
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt)))
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt)))
mShowDuringSelection = tempInt ? PR_TRUE : PR_FALSE;
NS_RELEASE(touchyFeely);
}
// get the selection from the pres shell, and set ourselves up as a selection
// listener
nsCOMPtr<nsISelection> domSelection;
nsCOMPtr<nsISelectionPrivate> privateSelection;
nsCOMPtr<nsISelectionController> selCon = do_QueryReferent(mPresShell);
if (selCon)
{
if (NS_SUCCEEDED(selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection))))
{
privateSelection = do_QueryInterface(domSelection);
privateSelection->AddSelectionListener(this);
mDomSelectionWeak = getter_AddRefs( NS_GetWeakReference(domSelection) );
}
}
else
if (!selCon)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISelection> domSelection;
nsresult rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection));
if (NS_FAILED(rv))
return rv;
if (!domSelection)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISelectionPrivate> privateSelection = do_QueryInterface(domSelection);
if (privateSelection)
privateSelection->AddSelectionListener(this);
mDomSelectionWeak = getter_AddRefs(NS_GetWeakReference(domSelection));
// set up the blink timer
if (mVisible)
{
nsresult err = StartBlinking();
if (NS_FAILED(err))
return err;
rv = StartBlinking();
if (NS_FAILED(rv))
return rv;
}
#ifdef IBMBIDI
PRBool isRTL;
mBidiKeyboard = do_GetService("@mozilla.org/widget/bidikeyboard;1");
@ -166,43 +173,39 @@ NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell)
}
//-----------------------------------------------------------------------------
NS_IMPL_ADDREF(nsCaret);
NS_IMPL_RELEASE(nsCaret);
//-----------------------------------------------------------------------------
NS_IMETHODIMP nsCaret::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
NS_IMETHODIMP nsCaret::Terminate()
{
// this doesn't erase the caret if it's drawn. Should it? We might not have a good
// drawing environment during teardown.
KillTimer();
mBlinkTimer = nsnull;
mRendContext = nsnull;
NS_PRECONDITION(aInstancePtrResult, "null pointer");
if (!aInstancePtrResult)
return NS_ERROR_NULL_POINTER;
// unregiser ourselves as a selection listener
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
if (privateSelection)
privateSelection->RemoveSelectionListener(this);
mDomSelectionWeak = nsnull;
mPresShell = nsnull;
nsISupports* foundInterface;
mLastCaretFrame = nsnull;
mLastCaretView = nsnull;
#ifdef IBMBIDI
mBidiKeyboard = nsnull;
#endif
if (aIID.Equals(NS_GET_IID(nsISupports)))
foundInterface = (nsISupports*)(nsICaret*)this; // whoo boy
else if (aIID.Equals(NS_GET_IID(nsICaret)))
foundInterface = (nsICaret*)this;
else if (aIID.Equals(NS_GET_IID(nsISelectionListener)))
foundInterface = (nsISelectionListener*)this;
else
foundInterface = nsnull;
nsresult status;
if (! foundInterface)
status = NS_NOINTERFACE;
else
{
NS_ADDREF(foundInterface);
status = NS_OK;
}
*aInstancePtrResult = foundInterface;
return status;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS2(nsCaret, nsICaret, nsISelectionListener);
//-----------------------------------------------------------------------------
NS_IMETHODIMP nsCaret::GetCaretDOMSelection(nsISelection **aDOMSel)
{
@ -236,6 +239,8 @@ NS_IMETHODIMP nsCaret::SetCaretVisible(PRBool inMakeVisible)
return err;
}
//-----------------------------------------------------------------------------
NS_IMETHODIMP nsCaret::GetCaretVisible(PRBool *outMakeVisible)
{
NS_ENSURE_ARG_POINTER(outMakeVisible);
@ -259,11 +264,10 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
return NS_ERROR_NOT_INITIALIZED;
if (!outCoordinates || !outIsCollapsed)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsISelection> domSelection = aDOMSel;
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
nsresult err;
if (!domSelection)
nsCOMPtr<nsISelection> domSelection = aDOMSel;
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
if (!privateSelection)
return NS_ERROR_NOT_INITIALIZED; // no selection
if (outView)
@ -276,7 +280,7 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
outCoordinates->height = -1;
*outIsCollapsed = PR_FALSE;
err = domSelection->GetIsCollapsed(outIsCollapsed);
nsresult err = domSelection->GetIsCollapsed(outIsCollapsed);
if (NS_FAILED(err))
return err;
@ -333,7 +337,6 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
nsRect clipRect;
nsIView *drawingView; // views are not refcounted
GetViewForRendering(theFrame, aRelativeToType, viewOffset, clipRect, &drawingView, outView);
if (!drawingView)
return NS_ERROR_UNEXPECTED;
@ -411,6 +414,37 @@ NS_IMETHODIMP nsCaret::EraseCaret()
return NS_OK;
}
NS_IMETHODIMP nsCaret::SetCaretWidth(nscoord aPixels)
{
if (aPixels <= 0)
return NS_ERROR_FAILURE;
// no need to optimize this, but if it gets too slow, we can check for
// case aPixels==mCaretPixelsWidth
mCaretPixelsWidth = aPixels;
mCaretTwipsWidth = -1;
return NS_OK;
}
NS_IMETHODIMP nsCaret::SetVisibilityDuringSelection(PRBool aVisibility)
{
mShowDuringSelection = aVisibility;
return NS_OK;
}
NS_IMETHODIMP nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset)
{
NS_ENSURE_ARG(aNode);
// XXX we need to do more work here to get the correct hint.
if (!SetupDrawingFrameAndOffset(aNode, aOffset, nsIFrameSelection::HINTLEFT))
return NS_ERROR_FAILURE;
GetCaretRectAndInvert();
return NS_OK;
}
#ifdef XP_MAC
#pragma mark -
@ -511,30 +545,9 @@ nsresult nsCaret::StopBlinking()
// Get the nsIFrame and the content offset for the current caret position.
// Returns PR_TRUE if we should go ahead and draw, PR_FALSE otherwise.
//
PRBool nsCaret::SetupDrawingFrameAndOffset()
{
if (!mDomSelectionWeak)
return PR_FALSE;
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
if (!domSelection) return PR_FALSE;
PRBool isCollapsed = PR_FALSE;
domSelection->GetIsCollapsed(&isCollapsed);
if (!mShowDuringSelection && !isCollapsed) return PR_FALSE;
// start and end parent should be the same since we are collapsed
nsCOMPtr<nsIDOMNode> focusNode;
domSelection->GetFocusNode(getter_AddRefs(focusNode));
if (!focusNode) return PR_FALSE;
PRInt32 contentOffset;
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
return PR_FALSE;
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(focusNode);
PRBool nsCaret::SetupDrawingFrameAndOffset(nsIDOMNode* aNode, PRInt32 aOffset, nsIFrameSelection::HINT aFrameHint)
{
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(aNode);
if (!contentNode) return PR_FALSE;
//get frame selection and find out what frame to use...
@ -547,15 +560,11 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
if (!frameSelection)
return PR_FALSE;
PRBool hintRight;
privateSelection->GetInterlinePosition(&hintRight);//translate hint.
nsIFrameSelection::HINT hint;
hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
nsIFrame* theFrame = nsnull;
PRInt32 theFrameOffset = 0;
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, contentOffset, hint, &theFrame, &theFrameOffset);
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, aOffset, aFrameHint, &theFrame, &theFrameOffset);
if (NS_FAILED(rv) || !theFrame)
return PR_FALSE;
@ -608,7 +617,7 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
if (start == 0 || end == 0 || start == theFrameOffset || end == theFrameOffset)
{
/* Boundary condition, we need to know the Bidi levels of the characters before and after the cursor */
if (NS_SUCCEEDED(frameSelection->GetPrevNextBidiLevels(presContext, contentNode, contentOffset,
if (NS_SUCCEEDED(frameSelection->GetPrevNextBidiLevels(presContext, contentNode, aOffset,
&frameBefore, &frameAfter,
&levelBefore, &levelAfter)))
{
@ -915,10 +924,10 @@ PRBool nsCaret::MustDrawCaret()
return PR_FALSE;
}
if (mDrawn)
return PR_TRUE;
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
if (mDrawn)
return PR_TRUE;
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
if (!domSelection)
return PR_FALSE;
PRBool isCollapsed;
@ -948,10 +957,38 @@ void nsCaret::DrawCaret()
// if we are drawing, not erasing, then set up the frame etc.
if (!mDrawn)
{
if (!SetupDrawingFrameAndOffset())
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
if (!privateSelection) return;
PRBool isCollapsed = PR_FALSE;
domSelection->GetIsCollapsed(&isCollapsed);
if (!mShowDuringSelection && !isCollapsed)
return;
PRBool hintRight;
privateSelection->GetInterlinePosition(&hintRight);//translate hint.
nsIFrameSelection::HINT hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
// get the node and offset, which is where we want the caret to draw
nsCOMPtr<nsIDOMNode> focusNode;
domSelection->GetFocusNode(getter_AddRefs(focusNode));
if (!focusNode)
return;
PRInt32 contentOffset;
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
return;
if (!SetupDrawingFrameAndOffset(focusNode, contentOffset, hint))
return;
}
GetCaretRectAndInvert();
}
void nsCaret::GetCaretRectAndInvert()
{
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
nsRect frameRect;
@ -978,7 +1015,7 @@ void nsCaret::DrawCaret()
return;
// if the view changed, or we don't have a rendering context, make one
// because of drawing issues, always make a new RC at the momemt. See bug 28068
// because of drawing issues, always make a new RC at the moment. See bug 28068
if (
#ifdef DONT_REUSE_RENDERING_CONTEXT
PR_TRUE ||
@ -1045,9 +1082,8 @@ void nsCaret::DrawCaret()
caretRect += mCachedFrameOffset;
//printf("Content offset %ld, frame offset %ld\n", focusOffset, framePos.x);
if(mCaretTwipsWidth < 0)
{// need to re-compute the pixel width
if (mCaretTwipsWidth < 0) // need to re-compute the pixel width
{
float tDevUnitsToTwips = 15;
nsCOMPtr<nsIDeviceContext> dx;
presContext->GetDeviceContext(getter_AddRefs(dx));
@ -1151,6 +1187,7 @@ void nsCaret::DrawCaret()
mRendContext->SetColor(NS_RGB(85, 85, 85)); // we are drawing it; gray
else
mRendContext->SetColor(NS_RGB(255,255,255));
mRendContext->InvertRect(mCaretRect);
// Ensure the buffer is flushed (Cocoa needs this), since we're drawing
@ -1162,7 +1199,7 @@ void nsCaret::DrawCaret()
mRendContext->InvertRect(mHookRect);
#endif
PRBool emptyClip; // I know what you're thinking. "Did he fire six shots or only five?"
PRBool emptyClip;
mRendContext->PopState(emptyClip);
ToggleDrawnStatus();
@ -1199,20 +1236,3 @@ nsresult NS_NewCaret(nsICaret** aInstancePtrResult)
return caret->QueryInterface(NS_GET_IID(nsICaret), (void**) aInstancePtrResult);
}
NS_IMETHODIMP nsCaret::SetCaretWidth(nscoord aPixels)
{
if(!aPixels)
return NS_ERROR_FAILURE;
else
{ //no need to optimize this, but if it gets too slow, we can check for case aPixels==mCaretPixelsWidth
mCaretPixelsWidth = aPixels;
mCaretTwipsWidth = -1;
}
return NS_OK;
}
NS_IMETHODIMP nsCaret::SetVisibilityDuringSelection(PRBool aVisibility)
{
mShowDuringSelection = aVisibility;
return NS_OK;
}

Просмотреть файл

@ -34,12 +34,6 @@
class nsIView;
class nsISelectionController;
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
#define NS_CARET_CID \
{ 0xe14b66f6, 0xbfc5, 0x11d2, { 0xb5, 0x7e, 0x0, 0x10, 0x5a, 0xa8, 0x3b, 0x2f } };
//-----------------------------------------------------------------------------
class nsCaret : public nsICaret,
@ -56,6 +50,7 @@ class nsCaret : public nsICaret,
// nsICaret interface
NS_IMETHOD Init(nsIPresShell *inPresShell);
NS_IMETHOD Terminate();
NS_IMETHOD GetCaretDOMSelection(nsISelection **outDOMSel);
NS_IMETHOD SetCaretDOMSelection(nsISelection *inDOMSel);
@ -68,6 +63,7 @@ class nsCaret : public nsICaret,
NS_IMETHOD SetCaretWidth(nscoord aPixels);
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibility);
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset);
//nsISelectionListener interface
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason);
@ -83,9 +79,10 @@ class nsCaret : public nsICaret,
nsresult StopBlinking();
void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView **outRenderingView, nsIView **outRelativeView);
PRBool SetupDrawingFrameAndOffset();
PRBool SetupDrawingFrameAndOffset(nsIDOMNode* aNode, PRInt32 aOffset, nsIFrameSelection::HINT aFrameHint);
PRBool MustDrawCaret();
void DrawCaret();
void GetCaretRectAndInvert();
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
protected:
@ -98,7 +95,7 @@ protected:
PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
nscoord mCaretTwipsWidth; // caret width in twips
nscoord mCaretTwipsWidth; // caret width in twips. this gets calculated laziiy
nscoord mCaretPixelsWidth; // caret width in pixels
PRPackedBool mVisible; // is the caret blinking
@ -114,11 +111,9 @@ protected:
nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC
PRInt32 mLastContentOffset;
#ifdef IBMBIDI
//---------------------------------------IBMBIDI----------------------------------------------
nsRect mHookRect; // directional hook on the caret
nsCOMPtr<nsIBidiKeyboard> mBidiKeyboard; // Bidi keyboard object to set and query keyboard language
PRPackedBool mKeyboardRTL; // is the keyboard language right-to-left
//-------------------------------------END OF IBM BIDI----------------------------------------
#endif
};

Просмотреть файл

@ -42,13 +42,15 @@
#include "nsCOMPtr.h"
#include "nsCoord.h"
struct nsRect;
struct nsPoint;
class nsIRenderingContext;
class nsIFrame;
class nsIView;
class nsIPresShell;
struct nsRect;
struct nsPoint;
class nsISelection;
class nsIDOMNode;
// IID for the nsICaret interface
#define NS_ICARET_IID \
@ -59,14 +61,15 @@ class nsICaret: public nsISupports
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICARET_IID)
typedef enum EViewCoordinates {
enum EViewCoordinates {
eTopLevelWindowCoordinates,
eRenderingViewCoordinates,
eClosestViewCoordinates,
eIMECoordinates
} EViewCoordinates;
};
NS_IMETHOD Init(nsIPresShell *inPresShell) = 0;
NS_IMETHOD Terminate() = 0;
NS_IMETHOD GetCaretDOMSelection(nsISelection **aDOMSel) = 0;
NS_IMETHOD SetCaretDOMSelection(nsISelection *aDOMSel) = 0;
@ -112,6 +115,16 @@ public:
NS_IMETHOD SetCaretWidth(nscoord aPixels) = 0;
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibilityDuringSelection) = 0;
/** DrawAtPosition
*
* Draw the caret explicitly, at the specified node and offset.
* To avoid drawing glitches, you should call EraseCaret()
* after each call to DrawAtPosition().
*
**/
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) = 0;
};
extern nsresult NS_NewCaret(nsICaret** aInstancePtrResult);

Просмотреть файл

@ -1184,7 +1184,7 @@ public:
// caret handling
NS_IMETHOD GetCaret(nsICaret **aOutCaret);
NS_IMETHOD SetCaretEnabled(PRBool aInEnable);
NS_IMETHOD SetCaretWidth(PRInt16 twips);
NS_IMETHOD SetCaretWidth(PRInt16 aPixels);
NS_IMETHOD SetCaretReadOnly(PRBool aReadOnly);
NS_IMETHOD GetCaretEnabled(PRBool *aOutEnabled);
@ -1776,6 +1776,11 @@ PresShell::Destroy()
mPaintSuppressionTimer = nsnull;
}
if (mCaret) {
mCaret->Terminate();
mCaret = nsnull;
}
// release our pref style sheet, if we have one still
ClearPreferenceStyleRules();
@ -2725,8 +2730,8 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
// notice that we ignore the result
NotifyReflowObservers(NS_PRESSHELL_INITIAL_REFLOW);
mCaret->EraseCaret();
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
if (mCaret)
mCaret->EraseCaret();
WillCauseReflow();
@ -2901,8 +2906,9 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
NotifyReflowObservers(NS_PRESSHELL_RESIZE_REFLOW);
mViewManager->CacheWidgetChanges(PR_TRUE);
mCaret->EraseCaret();
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
if (mCaret)
mCaret->EraseCaret();
WillCauseReflow();
if (mPresContext) {
@ -3100,11 +3106,14 @@ PresShell::GetFrameManager(nsIFrameManager** aFrameManager) const
return NS_OK;
}
// note that this can return a null caret, but NS_OK
NS_IMETHODIMP PresShell::GetCaret(nsICaret **outCaret)
{
if (!outCaret || !mCaret)
return NS_ERROR_NULL_POINTER;
return mCaret->QueryInterface(NS_GET_IID(nsICaret), (void **)outCaret);
NS_ENSURE_ARG_POINTER(outCaret);
*outCaret = mCaret;
NS_IF_ADDREF(*outCaret);
return NS_OK;
}
NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
@ -3129,17 +3138,21 @@ NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
NS_IMETHODIMP PresShell::SetCaretWidth(PRInt16 pixels)
{
return mCaret->SetCaretWidth(pixels);
if (mCaret)
mCaret->SetCaretWidth(pixels);
return NS_OK;
}
NS_IMETHODIMP PresShell::SetCaretReadOnly(PRBool aReadOnly)
{
return mCaret->SetCaretReadOnly(aReadOnly);
if (mCaret)
mCaret->SetCaretReadOnly(aReadOnly);
return NS_OK;
}
NS_IMETHODIMP PresShell::GetCaretEnabled(PRBool *aOutEnabled)
{
if (!aOutEnabled) { return NS_ERROR_INVALID_ARG; }
NS_ENSURE_ARG_POINTER(aOutEnabled);
*aOutEnabled = mCaretEnabled;
return NS_OK;
}
@ -5755,8 +5768,8 @@ PresShell::Paint(nsIView *aView,
if (nsnull != frame)
{
mCaret->EraseCaret();
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
if (mCaret)
mCaret->EraseCaret();
// If the frame is absolutely positioned, then the 'clip' property
// applies

Просмотреть файл

@ -42,13 +42,15 @@
#include "nsCOMPtr.h"
#include "nsCoord.h"
struct nsRect;
struct nsPoint;
class nsIRenderingContext;
class nsIFrame;
class nsIView;
class nsIPresShell;
struct nsRect;
struct nsPoint;
class nsISelection;
class nsIDOMNode;
// IID for the nsICaret interface
#define NS_ICARET_IID \
@ -59,14 +61,15 @@ class nsICaret: public nsISupports
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICARET_IID)
typedef enum EViewCoordinates {
enum EViewCoordinates {
eTopLevelWindowCoordinates,
eRenderingViewCoordinates,
eClosestViewCoordinates,
eIMECoordinates
} EViewCoordinates;
};
NS_IMETHOD Init(nsIPresShell *inPresShell) = 0;
NS_IMETHOD Terminate() = 0;
NS_IMETHOD GetCaretDOMSelection(nsISelection **aDOMSel) = 0;
NS_IMETHOD SetCaretDOMSelection(nsISelection *aDOMSel) = 0;
@ -112,6 +115,16 @@ public:
NS_IMETHOD SetCaretWidth(nscoord aPixels) = 0;
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibilityDuringSelection) = 0;
/** DrawAtPosition
*
* Draw the caret explicitly, at the specified node and offset.
* To avoid drawing glitches, you should call EraseCaret()
* after each call to DrawAtPosition().
*
**/
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) = 0;
};
extern nsresult NS_NewCaret(nsICaret** aInstancePtrResult);

Просмотреть файл

@ -96,6 +96,9 @@ nsCaret::nsCaret()
, mLastCaretFrame(nsnull)
, mLastCaretView(nsnull)
, mLastContentOffset(0)
#ifdef IBMBIDI
, mKeyboardRTL(PR_FALSE)
#endif
{
}
@ -109,52 +112,56 @@ nsCaret::~nsCaret()
//-----------------------------------------------------------------------------
NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell)
{
if (!inPresShell)
return NS_ERROR_NULL_POINTER;
NS_ENSURE_ARG(inPresShell);
mPresShell = getter_AddRefs(NS_GetWeakReference(inPresShell)); // the presshell owns us, so no addref
NS_ASSERTION(mPresShell, "Hey, pres shell should support weak refs");
nsILookAndFeel* touchyFeely;
if (NS_SUCCEEDED(nsComponentManager::CreateInstance(kLookAndFeelCID, nsnull, NS_GET_IID(nsILookAndFeel), (void**)&touchyFeely)))
// get nsILookAndFeel from the pres context, which has one cached.
nsCOMPtr<nsILookAndFeel> lookAndFeel;
nsCOMPtr<nsIPresContext> presContext;
inPresShell->GetPresContext(getter_AddRefs(presContext));
if (presContext)
presContext->GetLookAndFeel(getter_AddRefs(lookAndFeel));
if (lookAndFeel)
{
PRInt32 tempInt;
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, tempInt)))
mCaretTwipsWidth = (nscoord)tempInt;
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt)))
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, tempInt)))
mCaretPixelsWidth = (nscoord)tempInt;
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt)))
mBlinkRate = (PRUint32)tempInt;
if (NS_SUCCEEDED(touchyFeely->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt)))
if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt)))
mShowDuringSelection = tempInt ? PR_TRUE : PR_FALSE;
NS_RELEASE(touchyFeely);
}
// get the selection from the pres shell, and set ourselves up as a selection
// listener
nsCOMPtr<nsISelection> domSelection;
nsCOMPtr<nsISelectionPrivate> privateSelection;
nsCOMPtr<nsISelectionController> selCon = do_QueryReferent(mPresShell);
if (selCon)
{
if (NS_SUCCEEDED(selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection))))
{
privateSelection = do_QueryInterface(domSelection);
privateSelection->AddSelectionListener(this);
mDomSelectionWeak = getter_AddRefs( NS_GetWeakReference(domSelection) );
}
}
else
if (!selCon)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISelection> domSelection;
nsresult rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection));
if (NS_FAILED(rv))
return rv;
if (!domSelection)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISelectionPrivate> privateSelection = do_QueryInterface(domSelection);
if (privateSelection)
privateSelection->AddSelectionListener(this);
mDomSelectionWeak = getter_AddRefs(NS_GetWeakReference(domSelection));
// set up the blink timer
if (mVisible)
{
nsresult err = StartBlinking();
if (NS_FAILED(err))
return err;
rv = StartBlinking();
if (NS_FAILED(rv))
return rv;
}
#ifdef IBMBIDI
PRBool isRTL;
mBidiKeyboard = do_GetService("@mozilla.org/widget/bidikeyboard;1");
@ -166,43 +173,39 @@ NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell)
}
//-----------------------------------------------------------------------------
NS_IMPL_ADDREF(nsCaret);
NS_IMPL_RELEASE(nsCaret);
//-----------------------------------------------------------------------------
NS_IMETHODIMP nsCaret::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
NS_IMETHODIMP nsCaret::Terminate()
{
// this doesn't erase the caret if it's drawn. Should it? We might not have a good
// drawing environment during teardown.
KillTimer();
mBlinkTimer = nsnull;
mRendContext = nsnull;
NS_PRECONDITION(aInstancePtrResult, "null pointer");
if (!aInstancePtrResult)
return NS_ERROR_NULL_POINTER;
// unregiser ourselves as a selection listener
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
if (privateSelection)
privateSelection->RemoveSelectionListener(this);
mDomSelectionWeak = nsnull;
mPresShell = nsnull;
nsISupports* foundInterface;
mLastCaretFrame = nsnull;
mLastCaretView = nsnull;
#ifdef IBMBIDI
mBidiKeyboard = nsnull;
#endif
if (aIID.Equals(NS_GET_IID(nsISupports)))
foundInterface = (nsISupports*)(nsICaret*)this; // whoo boy
else if (aIID.Equals(NS_GET_IID(nsICaret)))
foundInterface = (nsICaret*)this;
else if (aIID.Equals(NS_GET_IID(nsISelectionListener)))
foundInterface = (nsISelectionListener*)this;
else
foundInterface = nsnull;
nsresult status;
if (! foundInterface)
status = NS_NOINTERFACE;
else
{
NS_ADDREF(foundInterface);
status = NS_OK;
}
*aInstancePtrResult = foundInterface;
return status;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS2(nsCaret, nsICaret, nsISelectionListener);
//-----------------------------------------------------------------------------
NS_IMETHODIMP nsCaret::GetCaretDOMSelection(nsISelection **aDOMSel)
{
@ -236,6 +239,8 @@ NS_IMETHODIMP nsCaret::SetCaretVisible(PRBool inMakeVisible)
return err;
}
//-----------------------------------------------------------------------------
NS_IMETHODIMP nsCaret::GetCaretVisible(PRBool *outMakeVisible)
{
NS_ENSURE_ARG_POINTER(outMakeVisible);
@ -259,11 +264,10 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
return NS_ERROR_NOT_INITIALIZED;
if (!outCoordinates || !outIsCollapsed)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsISelection> domSelection = aDOMSel;
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
nsresult err;
if (!domSelection)
nsCOMPtr<nsISelection> domSelection = aDOMSel;
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
if (!privateSelection)
return NS_ERROR_NOT_INITIALIZED; // no selection
if (outView)
@ -276,7 +280,7 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
outCoordinates->height = -1;
*outIsCollapsed = PR_FALSE;
err = domSelection->GetIsCollapsed(outIsCollapsed);
nsresult err = domSelection->GetIsCollapsed(outIsCollapsed);
if (NS_FAILED(err))
return err;
@ -333,7 +337,6 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI
nsRect clipRect;
nsIView *drawingView; // views are not refcounted
GetViewForRendering(theFrame, aRelativeToType, viewOffset, clipRect, &drawingView, outView);
if (!drawingView)
return NS_ERROR_UNEXPECTED;
@ -411,6 +414,37 @@ NS_IMETHODIMP nsCaret::EraseCaret()
return NS_OK;
}
NS_IMETHODIMP nsCaret::SetCaretWidth(nscoord aPixels)
{
if (aPixels <= 0)
return NS_ERROR_FAILURE;
// no need to optimize this, but if it gets too slow, we can check for
// case aPixels==mCaretPixelsWidth
mCaretPixelsWidth = aPixels;
mCaretTwipsWidth = -1;
return NS_OK;
}
NS_IMETHODIMP nsCaret::SetVisibilityDuringSelection(PRBool aVisibility)
{
mShowDuringSelection = aVisibility;
return NS_OK;
}
NS_IMETHODIMP nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset)
{
NS_ENSURE_ARG(aNode);
// XXX we need to do more work here to get the correct hint.
if (!SetupDrawingFrameAndOffset(aNode, aOffset, nsIFrameSelection::HINTLEFT))
return NS_ERROR_FAILURE;
GetCaretRectAndInvert();
return NS_OK;
}
#ifdef XP_MAC
#pragma mark -
@ -511,30 +545,9 @@ nsresult nsCaret::StopBlinking()
// Get the nsIFrame and the content offset for the current caret position.
// Returns PR_TRUE if we should go ahead and draw, PR_FALSE otherwise.
//
PRBool nsCaret::SetupDrawingFrameAndOffset()
{
if (!mDomSelectionWeak)
return PR_FALSE;
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
if (!domSelection) return PR_FALSE;
PRBool isCollapsed = PR_FALSE;
domSelection->GetIsCollapsed(&isCollapsed);
if (!mShowDuringSelection && !isCollapsed) return PR_FALSE;
// start and end parent should be the same since we are collapsed
nsCOMPtr<nsIDOMNode> focusNode;
domSelection->GetFocusNode(getter_AddRefs(focusNode));
if (!focusNode) return PR_FALSE;
PRInt32 contentOffset;
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
return PR_FALSE;
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(focusNode);
PRBool nsCaret::SetupDrawingFrameAndOffset(nsIDOMNode* aNode, PRInt32 aOffset, nsIFrameSelection::HINT aFrameHint)
{
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(aNode);
if (!contentNode) return PR_FALSE;
//get frame selection and find out what frame to use...
@ -547,15 +560,11 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
if (!frameSelection)
return PR_FALSE;
PRBool hintRight;
privateSelection->GetInterlinePosition(&hintRight);//translate hint.
nsIFrameSelection::HINT hint;
hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
nsIFrame* theFrame = nsnull;
PRInt32 theFrameOffset = 0;
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, contentOffset, hint, &theFrame, &theFrameOffset);
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, aOffset, aFrameHint, &theFrame, &theFrameOffset);
if (NS_FAILED(rv) || !theFrame)
return PR_FALSE;
@ -608,7 +617,7 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
if (start == 0 || end == 0 || start == theFrameOffset || end == theFrameOffset)
{
/* Boundary condition, we need to know the Bidi levels of the characters before and after the cursor */
if (NS_SUCCEEDED(frameSelection->GetPrevNextBidiLevels(presContext, contentNode, contentOffset,
if (NS_SUCCEEDED(frameSelection->GetPrevNextBidiLevels(presContext, contentNode, aOffset,
&frameBefore, &frameAfter,
&levelBefore, &levelAfter)))
{
@ -915,10 +924,10 @@ PRBool nsCaret::MustDrawCaret()
return PR_FALSE;
}
if (mDrawn)
return PR_TRUE;
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
if (mDrawn)
return PR_TRUE;
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
if (!domSelection)
return PR_FALSE;
PRBool isCollapsed;
@ -948,10 +957,38 @@ void nsCaret::DrawCaret()
// if we are drawing, not erasing, then set up the frame etc.
if (!mDrawn)
{
if (!SetupDrawingFrameAndOffset())
nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection));
if (!privateSelection) return;
PRBool isCollapsed = PR_FALSE;
domSelection->GetIsCollapsed(&isCollapsed);
if (!mShowDuringSelection && !isCollapsed)
return;
PRBool hintRight;
privateSelection->GetInterlinePosition(&hintRight);//translate hint.
nsIFrameSelection::HINT hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
// get the node and offset, which is where we want the caret to draw
nsCOMPtr<nsIDOMNode> focusNode;
domSelection->GetFocusNode(getter_AddRefs(focusNode));
if (!focusNode)
return;
PRInt32 contentOffset;
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
return;
if (!SetupDrawingFrameAndOffset(focusNode, contentOffset, hint))
return;
}
GetCaretRectAndInvert();
}
void nsCaret::GetCaretRectAndInvert()
{
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
nsRect frameRect;
@ -978,7 +1015,7 @@ void nsCaret::DrawCaret()
return;
// if the view changed, or we don't have a rendering context, make one
// because of drawing issues, always make a new RC at the momemt. See bug 28068
// because of drawing issues, always make a new RC at the moment. See bug 28068
if (
#ifdef DONT_REUSE_RENDERING_CONTEXT
PR_TRUE ||
@ -1045,9 +1082,8 @@ void nsCaret::DrawCaret()
caretRect += mCachedFrameOffset;
//printf("Content offset %ld, frame offset %ld\n", focusOffset, framePos.x);
if(mCaretTwipsWidth < 0)
{// need to re-compute the pixel width
if (mCaretTwipsWidth < 0) // need to re-compute the pixel width
{
float tDevUnitsToTwips = 15;
nsCOMPtr<nsIDeviceContext> dx;
presContext->GetDeviceContext(getter_AddRefs(dx));
@ -1151,6 +1187,7 @@ void nsCaret::DrawCaret()
mRendContext->SetColor(NS_RGB(85, 85, 85)); // we are drawing it; gray
else
mRendContext->SetColor(NS_RGB(255,255,255));
mRendContext->InvertRect(mCaretRect);
// Ensure the buffer is flushed (Cocoa needs this), since we're drawing
@ -1162,7 +1199,7 @@ void nsCaret::DrawCaret()
mRendContext->InvertRect(mHookRect);
#endif
PRBool emptyClip; // I know what you're thinking. "Did he fire six shots or only five?"
PRBool emptyClip;
mRendContext->PopState(emptyClip);
ToggleDrawnStatus();
@ -1199,20 +1236,3 @@ nsresult NS_NewCaret(nsICaret** aInstancePtrResult)
return caret->QueryInterface(NS_GET_IID(nsICaret), (void**) aInstancePtrResult);
}
NS_IMETHODIMP nsCaret::SetCaretWidth(nscoord aPixels)
{
if(!aPixels)
return NS_ERROR_FAILURE;
else
{ //no need to optimize this, but if it gets too slow, we can check for case aPixels==mCaretPixelsWidth
mCaretPixelsWidth = aPixels;
mCaretTwipsWidth = -1;
}
return NS_OK;
}
NS_IMETHODIMP nsCaret::SetVisibilityDuringSelection(PRBool aVisibility)
{
mShowDuringSelection = aVisibility;
return NS_OK;
}

Просмотреть файл

@ -34,12 +34,6 @@
class nsIView;
class nsISelectionController;
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
#define NS_CARET_CID \
{ 0xe14b66f6, 0xbfc5, 0x11d2, { 0xb5, 0x7e, 0x0, 0x10, 0x5a, 0xa8, 0x3b, 0x2f } };
//-----------------------------------------------------------------------------
class nsCaret : public nsICaret,
@ -56,6 +50,7 @@ class nsCaret : public nsICaret,
// nsICaret interface
NS_IMETHOD Init(nsIPresShell *inPresShell);
NS_IMETHOD Terminate();
NS_IMETHOD GetCaretDOMSelection(nsISelection **outDOMSel);
NS_IMETHOD SetCaretDOMSelection(nsISelection *inDOMSel);
@ -68,6 +63,7 @@ class nsCaret : public nsICaret,
NS_IMETHOD SetCaretWidth(nscoord aPixels);
NS_IMETHOD SetVisibilityDuringSelection(PRBool aVisibility);
NS_IMETHOD DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset);
//nsISelectionListener interface
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason);
@ -83,9 +79,10 @@ class nsCaret : public nsICaret,
nsresult StopBlinking();
void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView **outRenderingView, nsIView **outRelativeView);
PRBool SetupDrawingFrameAndOffset();
PRBool SetupDrawingFrameAndOffset(nsIDOMNode* aNode, PRInt32 aOffset, nsIFrameSelection::HINT aFrameHint);
PRBool MustDrawCaret();
void DrawCaret();
void GetCaretRectAndInvert();
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
protected:
@ -98,7 +95,7 @@ protected:
PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
nscoord mCaretTwipsWidth; // caret width in twips
nscoord mCaretTwipsWidth; // caret width in twips. this gets calculated laziiy
nscoord mCaretPixelsWidth; // caret width in pixels
PRPackedBool mVisible; // is the caret blinking
@ -114,11 +111,9 @@ protected:
nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC
PRInt32 mLastContentOffset;
#ifdef IBMBIDI
//---------------------------------------IBMBIDI----------------------------------------------
nsRect mHookRect; // directional hook on the caret
nsCOMPtr<nsIBidiKeyboard> mBidiKeyboard; // Bidi keyboard object to set and query keyboard language
PRPackedBool mKeyboardRTL; // is the keyboard language right-to-left
//-------------------------------------END OF IBM BIDI----------------------------------------
#endif
};

Просмотреть файл

@ -254,4 +254,9 @@
#define NS_SELECTIONIMAGESERVICE_CID \
{ 0x9d1001b1, 0xe59a, 0x456b, { 0x99, 0xdc, 0xcc, 0x3f, 0x12, 0x83, 0x23, 0x6e } }
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
#define NS_CARET_CID \
{ 0xe14b66f6, 0xbfc5, 0x11d2, { 0xb5, 0x7e, 0x0, 0x10, 0x5a, 0xa8, 0x3b, 0x2f } }
#endif /* nsLayoutCID_h__ */

Просмотреть файл

@ -102,6 +102,7 @@
#include "nsITextContent.h"
#include "nsIXBLService.h"
#include "nsIFrameLoader.h"
#include "nsICaret.h"
#include "nsLayoutAtoms.h"
#include "nsPlainTextSerializer.h"
#include "mozSanitizingSerializer.h"
@ -412,6 +413,7 @@ MAKE_CTOR(CreateNewScrollBoxObject, nsIBoxObject, NS_NewScrollBoxO
MAKE_CTOR(CreateNewTreeBoxObject, nsIBoxObject, NS_NewTreeBoxObject)
MAKE_CTOR(CreateNewAutoCopyService, nsIAutoCopyService, NS_NewAutoCopyService)
MAKE_CTOR(CreateSelectionImageService, nsISelectionImageService,NS_NewSelectionImageService)
MAKE_CTOR(CreateCaret, nsICaret, NS_NewCaret)
MAKE_CTOR(CreateNameSpaceManager, nsINameSpaceManager, NS_GetNameSpaceManager)
MAKE_CTOR(CreateEventListenerManager, nsIEventListenerManager, NS_NewEventListenerManager)
@ -618,7 +620,12 @@ static const nsModuleComponentInfo gComponents[] = {
{ "selection image storage",
NS_SELECTIONIMAGESERVICE_CID,
nsnull,
CreateSelectionImageService},
CreateSelectionImageService },
{ "caret",
NS_CARET_CID,
"@mozilla.org/layout/caret;1",
CreateCaret },
// XXX ick
{ "Presentation shell",

Просмотреть файл

@ -1184,7 +1184,7 @@ public:
// caret handling
NS_IMETHOD GetCaret(nsICaret **aOutCaret);
NS_IMETHOD SetCaretEnabled(PRBool aInEnable);
NS_IMETHOD SetCaretWidth(PRInt16 twips);
NS_IMETHOD SetCaretWidth(PRInt16 aPixels);
NS_IMETHOD SetCaretReadOnly(PRBool aReadOnly);
NS_IMETHOD GetCaretEnabled(PRBool *aOutEnabled);
@ -1776,6 +1776,11 @@ PresShell::Destroy()
mPaintSuppressionTimer = nsnull;
}
if (mCaret) {
mCaret->Terminate();
mCaret = nsnull;
}
// release our pref style sheet, if we have one still
ClearPreferenceStyleRules();
@ -2725,8 +2730,8 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
// notice that we ignore the result
NotifyReflowObservers(NS_PRESSHELL_INITIAL_REFLOW);
mCaret->EraseCaret();
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
if (mCaret)
mCaret->EraseCaret();
WillCauseReflow();
@ -2901,8 +2906,9 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
NotifyReflowObservers(NS_PRESSHELL_RESIZE_REFLOW);
mViewManager->CacheWidgetChanges(PR_TRUE);
mCaret->EraseCaret();
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
if (mCaret)
mCaret->EraseCaret();
WillCauseReflow();
if (mPresContext) {
@ -3100,11 +3106,14 @@ PresShell::GetFrameManager(nsIFrameManager** aFrameManager) const
return NS_OK;
}
// note that this can return a null caret, but NS_OK
NS_IMETHODIMP PresShell::GetCaret(nsICaret **outCaret)
{
if (!outCaret || !mCaret)
return NS_ERROR_NULL_POINTER;
return mCaret->QueryInterface(NS_GET_IID(nsICaret), (void **)outCaret);
NS_ENSURE_ARG_POINTER(outCaret);
*outCaret = mCaret;
NS_IF_ADDREF(*outCaret);
return NS_OK;
}
NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
@ -3129,17 +3138,21 @@ NS_IMETHODIMP PresShell::SetCaretEnabled(PRBool aInEnable)
NS_IMETHODIMP PresShell::SetCaretWidth(PRInt16 pixels)
{
return mCaret->SetCaretWidth(pixels);
if (mCaret)
mCaret->SetCaretWidth(pixels);
return NS_OK;
}
NS_IMETHODIMP PresShell::SetCaretReadOnly(PRBool aReadOnly)
{
return mCaret->SetCaretReadOnly(aReadOnly);
if (mCaret)
mCaret->SetCaretReadOnly(aReadOnly);
return NS_OK;
}
NS_IMETHODIMP PresShell::GetCaretEnabled(PRBool *aOutEnabled)
{
if (!aOutEnabled) { return NS_ERROR_INVALID_ARG; }
NS_ENSURE_ARG_POINTER(aOutEnabled);
*aOutEnabled = mCaretEnabled;
return NS_OK;
}
@ -5755,8 +5768,8 @@ PresShell::Paint(nsIView *aView,
if (nsnull != frame)
{
mCaret->EraseCaret();
//StCaretHider caretHider(mCaret); // stack-based class hides caret until dtor.
if (mCaret)
mCaret->EraseCaret();
// If the frame is absolutely positioned, then the 'clip' property
// applies