зеркало из https://github.com/mozilla/gecko-dev.git
Fix 51747 -- caret not drawing at the end of a line. Fix offset of clip. r=kin
This commit is contained in:
Родитель
b6249a8f38
Коммит
323042d90a
|
@ -49,6 +49,11 @@
|
||||||
|
|
||||||
#include "nsCaret.h"
|
#include "nsCaret.h"
|
||||||
|
|
||||||
|
// Because of drawing issues, we currently always make a new RC. See bug 28068
|
||||||
|
// Before removing this, stuff will need to be fixed and tested on all platforms.
|
||||||
|
// For example, turning this off on Mac right now causes drawing problems on pages
|
||||||
|
// with form elements.
|
||||||
|
#define DONT_REUSE_RENDERING_CONTEXT
|
||||||
|
|
||||||
static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
||||||
|
|
||||||
|
@ -63,6 +68,7 @@ nsCaret::nsCaret()
|
||||||
, mReadOnly(PR_TRUE)
|
, mReadOnly(PR_TRUE)
|
||||||
, mDrawn(PR_FALSE)
|
, mDrawn(PR_FALSE)
|
||||||
, mLastCaretFrame(nsnull)
|
, mLastCaretFrame(nsnull)
|
||||||
|
, mLastCaretView(nsnull)
|
||||||
, mLastContentOffset(0)
|
, mLastContentOffset(0)
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
|
@ -326,6 +332,7 @@ NS_IMETHODIMP nsCaret::ClearFrameRefs(nsIFrame* aFrame)
|
||||||
if (mLastCaretFrame == aFrame)
|
if (mLastCaretFrame == aFrame)
|
||||||
{
|
{
|
||||||
mLastCaretFrame = nsnull; // frames are not refcounted.
|
mLastCaretFrame = nsnull; // frames are not refcounted.
|
||||||
|
mLastCaretView = nsnull;
|
||||||
mLastContentOffset = 0;
|
mLastContentOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,63 +439,76 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
|
||||||
{
|
{
|
||||||
if (!mDomSelectionWeak)
|
if (!mDomSelectionWeak)
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
nsCOMPtr<nsIDOMSelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
|
||||||
PRBool isCollapsed;
|
nsCOMPtr<nsIDOMSelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||||
|
if (!domSelection) return PR_FALSE;
|
||||||
|
|
||||||
|
PRBool isCollapsed = PR_FALSE;
|
||||||
|
domSelection->GetIsCollapsed(&isCollapsed);
|
||||||
|
if (!isCollapsed) return PR_FALSE;
|
||||||
|
|
||||||
if (domSelection && NS_SUCCEEDED(domSelection->GetIsCollapsed(&isCollapsed)) && isCollapsed)
|
// start and end parent should be the same since we are collapsed
|
||||||
{
|
nsCOMPtr<nsIDOMNode> focusNode;
|
||||||
// start and end parent should be the same since we are collapsed
|
domSelection->GetFocusNode(getter_AddRefs(focusNode));
|
||||||
nsCOMPtr<nsIDOMNode> focusNode;
|
if (!focusNode) return PR_FALSE;
|
||||||
PRInt32 contentOffset;
|
|
||||||
|
PRInt32 contentOffset;
|
||||||
if (NS_SUCCEEDED(domSelection->GetFocusNode(getter_AddRefs(focusNode))) && focusNode &&
|
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
|
||||||
NS_SUCCEEDED(domSelection->GetFocusOffset(&contentOffset)))
|
return PR_FALSE;
|
||||||
{
|
|
||||||
nsCOMPtr<nsIContent>contentNode = do_QueryInterface(focusNode);
|
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(focusNode);
|
||||||
|
if (!contentNode) return PR_FALSE;
|
||||||
|
|
||||||
if (contentNode)
|
//get frame selection and find out what frame to use...
|
||||||
{
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||||
nsIFrame* theFrame = nsnull;
|
if (!presShell)
|
||||||
PRInt32 theFrameOffset = 0;
|
return PR_FALSE;
|
||||||
nsresult err;
|
|
||||||
//get frame selection and find out what frame to use...
|
nsCOMPtr<nsIFrameSelection> frameSelection;
|
||||||
nsCOMPtr<nsIFrameSelection> frameSelection;
|
presShell->GetFrameSelection(getter_AddRefs(frameSelection));
|
||||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
if (!frameSelection)
|
||||||
if (!presShell)
|
return PR_FALSE;
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
err = presShell->GetFrameSelection(getter_AddRefs(frameSelection));
|
|
||||||
if (NS_FAILED(err) || !frameSelection)
|
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
PRBool hintRight;
|
PRBool hintRight;
|
||||||
domSelection->GetHint(&hintRight);//translate hint.
|
domSelection->GetHint(&hintRight);//translate hint.
|
||||||
nsIFrameSelection::HINT hint;
|
nsIFrameSelection::HINT hint;
|
||||||
if (hintRight)
|
hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
|
||||||
hint = nsIFrameSelection::HINTRIGHT;
|
|
||||||
else
|
|
||||||
hint = nsIFrameSelection::HINTLEFT;
|
|
||||||
|
|
||||||
err = frameSelection->GetFrameForNodeOffset(contentNode, contentOffset, hint, &theFrame, &theFrameOffset);
|
nsIFrame* theFrame = nsnull;
|
||||||
if (NS_FAILED(err))
|
PRInt32 theFrameOffset = 0;
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
// mark the frame, so we get notified on deletion.
|
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, contentOffset, hint, &theFrame, &theFrameOffset);
|
||||||
// frames are never unmarked, which means that we'll touch every frame we visit.
|
if (NS_FAILED(rv) || !theFrame)
|
||||||
// this is not ideal.
|
return PR_FALSE;
|
||||||
nsFrameState frameState;
|
|
||||||
theFrame->GetFrameState(&frameState);
|
// now we have a frame, check whether it's appropriate to show the caret here
|
||||||
frameState |= NS_FRAME_EXTERNAL_REFERENCE;
|
const nsStyleUserInterface* userinterface;
|
||||||
theFrame->SetFrameState(frameState);
|
theFrame->GetStyleData(eStyleStruct_UserInterface, (const nsStyleStruct*&)userinterface);
|
||||||
|
if (userinterface)
|
||||||
mLastCaretFrame = theFrame;
|
{
|
||||||
mLastContentOffset = theFrameOffset;
|
if (
|
||||||
return PR_TRUE;
|
#ifdef SUPPORT_USER_MODIFY
|
||||||
}
|
// editable content still defaults to NS_STYLE_USER_MODIFY_READ_ONLY at present. See bug 15284
|
||||||
}
|
(userinterface->mUserModify == NS_STYLE_USER_MODIFY_READ_ONLY) ||
|
||||||
|
#endif
|
||||||
|
(userinterface->mUserInput == NS_STYLE_USER_INPUT_NONE) ||
|
||||||
|
(userinterface->mUserInput == NS_STYLE_USER_INPUT_DISABLED))
|
||||||
|
{
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return PR_FALSE;
|
// mark the frame, so we get notified on deletion.
|
||||||
|
// frames are never unmarked, which means that we'll touch every frame we visit.
|
||||||
|
// this is not ideal.
|
||||||
|
nsFrameState frameState;
|
||||||
|
theFrame->GetFrameState(&frameState);
|
||||||
|
frameState |= NS_FRAME_EXTERNAL_REFERENCE;
|
||||||
|
theFrame->SetFrameState(frameState);
|
||||||
|
|
||||||
|
mLastCaretFrame = theFrame;
|
||||||
|
mLastContentOffset = theFrameOffset;
|
||||||
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -510,9 +530,11 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy
|
||||||
|
|
||||||
viewOffset.x = 0;
|
viewOffset.x = 0;
|
||||||
viewOffset.y = 0;
|
viewOffset.y = 0;
|
||||||
|
|
||||||
|
nsPoint withinViewOffset(0, 0);
|
||||||
// get the offset of this frame from its parent view (walks up frame hierarchy)
|
// get the offset of this frame from its parent view (walks up frame hierarchy)
|
||||||
nsIView* theView = nsnull;
|
nsIView* theView = nsnull;
|
||||||
caretFrame->GetOffsetFromView(presContext, viewOffset, &theView);
|
caretFrame->GetOffsetFromView(presContext, withinViewOffset, &theView);
|
||||||
if (theView == nsnull) return;
|
if (theView == nsnull) return;
|
||||||
|
|
||||||
nsIView* returnView = nsnull; // views are not refcounted
|
nsIView* returnView = nsnull; // views are not refcounted
|
||||||
|
@ -525,6 +547,8 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy
|
||||||
nsIView* startingView = theView;
|
nsIView* startingView = theView;
|
||||||
nsIScrollableView* scrollableView = nsnull;
|
nsIScrollableView* scrollableView = nsnull;
|
||||||
|
|
||||||
|
nsPoint drawViewOffset(0, 0); // offset to the view we are using to draw
|
||||||
|
|
||||||
// walk up to the first view with a widget
|
// walk up to the first view with a widget
|
||||||
do {
|
do {
|
||||||
theView->GetPosition(&x, &y);
|
theView->GetPosition(&x, &y);
|
||||||
|
@ -535,19 +559,20 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy
|
||||||
|
|
||||||
PRBool hasWidget;
|
PRBool hasWidget;
|
||||||
theView->HasWidget(&hasWidget);
|
theView->HasWidget(&hasWidget);
|
||||||
|
|
||||||
if (hasWidget)
|
if (hasWidget)
|
||||||
{
|
{
|
||||||
returnView = theView;
|
returnView = theView;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
viewOffset.x += x;
|
drawViewOffset.x += x;
|
||||||
viewOffset.y += y;
|
drawViewOffset.y += y;
|
||||||
|
|
||||||
theView->GetParent(theView);
|
theView->GetParent(theView);
|
||||||
} while (theView);
|
} while (theView);
|
||||||
|
|
||||||
|
viewOffset = withinViewOffset;
|
||||||
|
viewOffset += drawViewOffset;
|
||||||
|
|
||||||
if (scrollableView)
|
if (scrollableView)
|
||||||
{
|
{
|
||||||
const nsIView* clipView = nsnull;
|
const nsIView* clipView = nsnull;
|
||||||
|
@ -558,7 +583,7 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy
|
||||||
clipView->GetBounds(bounds);
|
clipView->GetBounds(bounds);
|
||||||
scrollableView->GetScrollPosition(bounds.x, bounds.y);
|
scrollableView->GetScrollPosition(bounds.x, bounds.y);
|
||||||
|
|
||||||
bounds += viewOffset; // offset to coords of returned view
|
bounds += drawViewOffset; // offset to coords of returned view
|
||||||
outClipRect = bounds;
|
outClipRect = bounds;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -626,14 +651,22 @@ PRBool nsCaret::MustDrawCaret()
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
DrawCaretWithContext
|
DrawCaret
|
||||||
|
|
||||||
By this point, the caret rect should have been set up.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------- */
|
----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void nsCaret::DrawCaretWithContext(nsIRenderingContext* inRendContext)
|
void nsCaret::DrawCaret()
|
||||||
{
|
{
|
||||||
|
// do we need to draw the caret at all?
|
||||||
|
if (!MustDrawCaret())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if we are drawing, not erasing, then set up the frame etc.
|
||||||
|
if (!mDrawn)
|
||||||
|
{
|
||||||
|
if (!SetupDrawingFrameAndOffset())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
|
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
|
||||||
|
|
||||||
|
@ -658,37 +691,44 @@ void nsCaret::DrawCaretWithContext(nsIRenderingContext* inRendContext)
|
||||||
|
|
||||||
frameRect += viewOffset;
|
frameRect += viewOffset;
|
||||||
|
|
||||||
nsCOMPtr<nsIPresContext> presContext;
|
|
||||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||||
if (presShell)
|
if (!presShell) return;
|
||||||
{
|
|
||||||
if (NS_FAILED(presShell->GetPresContext(getter_AddRefs(presContext))))
|
nsCOMPtr<nsIPresContext> presContext;
|
||||||
return;
|
if (NS_FAILED(presShell->GetPresContext(getter_AddRefs(presContext))))
|
||||||
}
|
|
||||||
else
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// make a rendering context, if we didn't get passed one
|
// if the view changed, or we don't have a rendering context, make one
|
||||||
nsCOMPtr<nsIRenderingContext> localRC = do_QueryInterface(inRendContext); // OK if inRendContext is null
|
// because of drawing issues, always make a new RC at the momemt. See bug 28068
|
||||||
if (!localRC)
|
if (
|
||||||
|
#ifdef DONT_REUSE_RENDERING_CONTEXT
|
||||||
|
PR_TRUE ||
|
||||||
|
#endif
|
||||||
|
(mLastCaretView != drawingView) || !mRendContext)
|
||||||
{
|
{
|
||||||
|
mRendContext = nsnull; // free existing one if we have one
|
||||||
|
|
||||||
nsCOMPtr<nsIDeviceContext> dx;
|
nsCOMPtr<nsIDeviceContext> dx;
|
||||||
|
|
||||||
if (NS_FAILED(presContext->GetDeviceContext(getter_AddRefs(dx))) || !dx)
|
if (NS_FAILED(presContext->GetDeviceContext(getter_AddRefs(dx))) || !dx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (NS_FAILED(dx->CreateRenderingContext(drawingView, *getter_AddRefs(localRC))) || !localRC)
|
if (NS_FAILED(dx->CreateRenderingContext(drawingView, *getter_AddRefs(mRendContext))) || !mRendContext)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// push a known good state
|
||||||
|
mRendContext->PushState();
|
||||||
|
|
||||||
|
// views are not refcounted
|
||||||
|
mLastCaretView = drawingView;
|
||||||
|
|
||||||
if (!mDrawn)
|
if (!mDrawn)
|
||||||
{
|
{
|
||||||
nsPoint framePos(0, 0);
|
nsPoint framePos(0, 0);
|
||||||
nsRect caretRect = frameRect;
|
nsRect caretRect = frameRect;
|
||||||
|
|
||||||
mLastCaretFrame->GetPointFromOffset(presContext, localRC, mLastContentOffset, &framePos);
|
mLastCaretFrame->GetPointFromOffset(presContext, mRendContext, mLastContentOffset, &framePos);
|
||||||
caretRect += framePos;
|
caretRect += framePos;
|
||||||
|
|
||||||
|
|
||||||
//printf("Content offset %ld, frame offset %ld\n", focusOffset, framePos.x);
|
//printf("Content offset %ld, frame offset %ld\n", focusOffset, framePos.x);
|
||||||
if(mCaretTwipsWidth < 0)
|
if(mCaretTwipsWidth < 0)
|
||||||
|
@ -721,52 +761,17 @@ void nsCaret::DrawCaretWithContext(nsIRenderingContext* inRendContext)
|
||||||
inRendContext.SetColor(NS_RGB(85, 85, 85)); // we are drawing it; gray
|
inRendContext.SetColor(NS_RGB(85, 85, 85)); // we are drawing it; gray
|
||||||
*/
|
*/
|
||||||
|
|
||||||
localRC->SetColor(NS_RGB(255,255,255));
|
mRendContext->SetColor(NS_RGB(255,255,255));
|
||||||
localRC->InvertRect(mCaretRect);
|
mRendContext->InvertRect(mCaretRect);
|
||||||
|
|
||||||
|
PRBool emptyClip; // I know what you're thinking. "Did he fire six shots or only five?"
|
||||||
|
mRendContext->PopState(emptyClip);
|
||||||
|
|
||||||
ToggleDrawnStatus();
|
ToggleDrawnStatus();
|
||||||
|
|
||||||
}
|
#ifdef DONT_REUSE_RENDERING_CONTEXT
|
||||||
|
mRendContext = nsnull;
|
||||||
//-----------------------------------------------------------------------------
|
#endif
|
||||||
void nsCaret::DrawCaret()
|
|
||||||
{
|
|
||||||
// do we need to draw the caret at all?
|
|
||||||
if (!MustDrawCaret())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// if we are drawing, not erasing, then set up the frame etc.
|
|
||||||
if (!mDrawn)
|
|
||||||
{
|
|
||||||
if (! SetupDrawingFrameAndOffset())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawCaretWithContext(nsnull);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void nsCaret::RefreshDrawCaret(nsIView *aView, nsIRenderingContext& inRendContext, const nsRect& aDirtyRect)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (! SetupDrawingFrameAndOffset())
|
|
||||||
return;
|
|
||||||
|
|
||||||
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
|
|
||||||
|
|
||||||
nsPoint viewOffset(0, 0);
|
|
||||||
nsIView *drawingView;
|
|
||||||
//GetViewForRendering(viewOffset, drawingView);
|
|
||||||
|
|
||||||
mLastCaretFrame->GetOffsetFromView(viewOffset, &drawingView);
|
|
||||||
|
|
||||||
// are we in the view that is being painted?
|
|
||||||
if (drawingView == nsnull || drawingView != aView)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mDrawn = PR_FALSE; // we're rendering to a view that is being redrawn
|
|
||||||
DrawCaretWithContext(inRendContext);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_MAC
|
#ifdef XP_MAC
|
||||||
|
|
|
@ -24,12 +24,13 @@
|
||||||
|
|
||||||
#include "nsCoord.h"
|
#include "nsCoord.h"
|
||||||
#include "nsIDOMSelectionListener.h"
|
#include "nsIDOMSelectionListener.h"
|
||||||
|
#include "nsIRenderingContext.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
#include "nsICaret.h"
|
#include "nsICaret.h"
|
||||||
#include "nsWeakPtr.h"
|
#include "nsWeakPtr.h"
|
||||||
|
|
||||||
class nsITimer;
|
|
||||||
class nsIView;
|
class nsIView;
|
||||||
class nsIRenderingContext;
|
|
||||||
class nsISelectionController;
|
class nsISelectionController;
|
||||||
|
|
||||||
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
|
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
|
||||||
|
@ -83,30 +84,28 @@ class nsCaret : public nsICaret,
|
||||||
void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView* &outView);
|
void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView* &outView);
|
||||||
PRBool SetupDrawingFrameAndOffset();
|
PRBool SetupDrawingFrameAndOffset();
|
||||||
PRBool MustDrawCaret();
|
PRBool MustDrawCaret();
|
||||||
void RefreshDrawCaret(nsIView *aView, nsIRenderingContext& inRendContext, const nsRect& aDirtyRect);
|
|
||||||
void DrawCaretWithContext(nsIRenderingContext* inRendContext);
|
|
||||||
|
|
||||||
void DrawCaret();
|
void DrawCaret();
|
||||||
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
|
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
|
||||||
|
|
||||||
nsCOMPtr<nsIWeakReference> mPresShell;
|
protected:
|
||||||
|
|
||||||
nsCOMPtr<nsITimer> mBlinkTimer;
|
nsWeakPtr mPresShell;
|
||||||
|
nsWeakPtr mDomSelectionWeak;
|
||||||
|
|
||||||
PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
|
nsCOMPtr<nsITimer> mBlinkTimer;
|
||||||
nscoord mCaretTwipsWidth; // caret width in twips
|
nsCOMPtr<nsIRenderingContext> mRendContext;
|
||||||
nscoord mCaretPixelsWidth; // caret width in pixels
|
|
||||||
|
PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
|
||||||
|
nscoord mCaretTwipsWidth; // caret width in twips
|
||||||
|
nscoord mCaretPixelsWidth; // caret width in pixels
|
||||||
|
|
||||||
PRBool mVisible; // is the caret blinking
|
PRPackedBool mVisible; // is the caret blinking
|
||||||
PRBool mReadOnly; // it the caret in readonly state (draws differently)
|
PRPackedBool mDrawn; // this should be mutable
|
||||||
|
PRPackedBool mReadOnly; // it the caret in readonly state (draws differently)
|
||||||
private:
|
|
||||||
|
|
||||||
PRBool mDrawn; // this should be mutable
|
|
||||||
|
|
||||||
nsRect mCaretRect; // the last caret rect
|
nsRect mCaretRect; // the last caret rect
|
||||||
nsIFrame* mLastCaretFrame; // store the frame the caret was last drawn in.
|
nsIFrame* mLastCaretFrame; // store the frame the caret was last drawn in.
|
||||||
|
nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC
|
||||||
PRInt32 mLastContentOffset;
|
PRInt32 mLastContentOffset;
|
||||||
nsWeakPtr mDomSelectionWeak;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,11 @@
|
||||||
|
|
||||||
#include "nsCaret.h"
|
#include "nsCaret.h"
|
||||||
|
|
||||||
|
// Because of drawing issues, we currently always make a new RC. See bug 28068
|
||||||
|
// Before removing this, stuff will need to be fixed and tested on all platforms.
|
||||||
|
// For example, turning this off on Mac right now causes drawing problems on pages
|
||||||
|
// with form elements.
|
||||||
|
#define DONT_REUSE_RENDERING_CONTEXT
|
||||||
|
|
||||||
static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
||||||
|
|
||||||
|
@ -63,6 +68,7 @@ nsCaret::nsCaret()
|
||||||
, mReadOnly(PR_TRUE)
|
, mReadOnly(PR_TRUE)
|
||||||
, mDrawn(PR_FALSE)
|
, mDrawn(PR_FALSE)
|
||||||
, mLastCaretFrame(nsnull)
|
, mLastCaretFrame(nsnull)
|
||||||
|
, mLastCaretView(nsnull)
|
||||||
, mLastContentOffset(0)
|
, mLastContentOffset(0)
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
|
@ -326,6 +332,7 @@ NS_IMETHODIMP nsCaret::ClearFrameRefs(nsIFrame* aFrame)
|
||||||
if (mLastCaretFrame == aFrame)
|
if (mLastCaretFrame == aFrame)
|
||||||
{
|
{
|
||||||
mLastCaretFrame = nsnull; // frames are not refcounted.
|
mLastCaretFrame = nsnull; // frames are not refcounted.
|
||||||
|
mLastCaretView = nsnull;
|
||||||
mLastContentOffset = 0;
|
mLastContentOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,63 +439,76 @@ PRBool nsCaret::SetupDrawingFrameAndOffset()
|
||||||
{
|
{
|
||||||
if (!mDomSelectionWeak)
|
if (!mDomSelectionWeak)
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
nsCOMPtr<nsIDOMSelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
|
||||||
PRBool isCollapsed;
|
nsCOMPtr<nsIDOMSelection> domSelection = do_QueryReferent(mDomSelectionWeak);
|
||||||
|
if (!domSelection) return PR_FALSE;
|
||||||
|
|
||||||
|
PRBool isCollapsed = PR_FALSE;
|
||||||
|
domSelection->GetIsCollapsed(&isCollapsed);
|
||||||
|
if (!isCollapsed) return PR_FALSE;
|
||||||
|
|
||||||
if (domSelection && NS_SUCCEEDED(domSelection->GetIsCollapsed(&isCollapsed)) && isCollapsed)
|
// start and end parent should be the same since we are collapsed
|
||||||
{
|
nsCOMPtr<nsIDOMNode> focusNode;
|
||||||
// start and end parent should be the same since we are collapsed
|
domSelection->GetFocusNode(getter_AddRefs(focusNode));
|
||||||
nsCOMPtr<nsIDOMNode> focusNode;
|
if (!focusNode) return PR_FALSE;
|
||||||
PRInt32 contentOffset;
|
|
||||||
|
PRInt32 contentOffset;
|
||||||
if (NS_SUCCEEDED(domSelection->GetFocusNode(getter_AddRefs(focusNode))) && focusNode &&
|
if (NS_FAILED(domSelection->GetFocusOffset(&contentOffset)))
|
||||||
NS_SUCCEEDED(domSelection->GetFocusOffset(&contentOffset)))
|
return PR_FALSE;
|
||||||
{
|
|
||||||
nsCOMPtr<nsIContent>contentNode = do_QueryInterface(focusNode);
|
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(focusNode);
|
||||||
|
if (!contentNode) return PR_FALSE;
|
||||||
|
|
||||||
if (contentNode)
|
//get frame selection and find out what frame to use...
|
||||||
{
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||||
nsIFrame* theFrame = nsnull;
|
if (!presShell)
|
||||||
PRInt32 theFrameOffset = 0;
|
return PR_FALSE;
|
||||||
nsresult err;
|
|
||||||
//get frame selection and find out what frame to use...
|
nsCOMPtr<nsIFrameSelection> frameSelection;
|
||||||
nsCOMPtr<nsIFrameSelection> frameSelection;
|
presShell->GetFrameSelection(getter_AddRefs(frameSelection));
|
||||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
if (!frameSelection)
|
||||||
if (!presShell)
|
return PR_FALSE;
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
err = presShell->GetFrameSelection(getter_AddRefs(frameSelection));
|
|
||||||
if (NS_FAILED(err) || !frameSelection)
|
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
PRBool hintRight;
|
PRBool hintRight;
|
||||||
domSelection->GetHint(&hintRight);//translate hint.
|
domSelection->GetHint(&hintRight);//translate hint.
|
||||||
nsIFrameSelection::HINT hint;
|
nsIFrameSelection::HINT hint;
|
||||||
if (hintRight)
|
hint = (hintRight) ? nsIFrameSelection::HINTRIGHT : nsIFrameSelection::HINTLEFT;
|
||||||
hint = nsIFrameSelection::HINTRIGHT;
|
|
||||||
else
|
|
||||||
hint = nsIFrameSelection::HINTLEFT;
|
|
||||||
|
|
||||||
err = frameSelection->GetFrameForNodeOffset(contentNode, contentOffset, hint, &theFrame, &theFrameOffset);
|
nsIFrame* theFrame = nsnull;
|
||||||
if (NS_FAILED(err))
|
PRInt32 theFrameOffset = 0;
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
// mark the frame, so we get notified on deletion.
|
nsresult rv = frameSelection->GetFrameForNodeOffset(contentNode, contentOffset, hint, &theFrame, &theFrameOffset);
|
||||||
// frames are never unmarked, which means that we'll touch every frame we visit.
|
if (NS_FAILED(rv) || !theFrame)
|
||||||
// this is not ideal.
|
return PR_FALSE;
|
||||||
nsFrameState frameState;
|
|
||||||
theFrame->GetFrameState(&frameState);
|
// now we have a frame, check whether it's appropriate to show the caret here
|
||||||
frameState |= NS_FRAME_EXTERNAL_REFERENCE;
|
const nsStyleUserInterface* userinterface;
|
||||||
theFrame->SetFrameState(frameState);
|
theFrame->GetStyleData(eStyleStruct_UserInterface, (const nsStyleStruct*&)userinterface);
|
||||||
|
if (userinterface)
|
||||||
mLastCaretFrame = theFrame;
|
{
|
||||||
mLastContentOffset = theFrameOffset;
|
if (
|
||||||
return PR_TRUE;
|
#ifdef SUPPORT_USER_MODIFY
|
||||||
}
|
// editable content still defaults to NS_STYLE_USER_MODIFY_READ_ONLY at present. See bug 15284
|
||||||
}
|
(userinterface->mUserModify == NS_STYLE_USER_MODIFY_READ_ONLY) ||
|
||||||
|
#endif
|
||||||
|
(userinterface->mUserInput == NS_STYLE_USER_INPUT_NONE) ||
|
||||||
|
(userinterface->mUserInput == NS_STYLE_USER_INPUT_DISABLED))
|
||||||
|
{
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return PR_FALSE;
|
// mark the frame, so we get notified on deletion.
|
||||||
|
// frames are never unmarked, which means that we'll touch every frame we visit.
|
||||||
|
// this is not ideal.
|
||||||
|
nsFrameState frameState;
|
||||||
|
theFrame->GetFrameState(&frameState);
|
||||||
|
frameState |= NS_FRAME_EXTERNAL_REFERENCE;
|
||||||
|
theFrame->SetFrameState(frameState);
|
||||||
|
|
||||||
|
mLastCaretFrame = theFrame;
|
||||||
|
mLastContentOffset = theFrameOffset;
|
||||||
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -510,9 +530,11 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy
|
||||||
|
|
||||||
viewOffset.x = 0;
|
viewOffset.x = 0;
|
||||||
viewOffset.y = 0;
|
viewOffset.y = 0;
|
||||||
|
|
||||||
|
nsPoint withinViewOffset(0, 0);
|
||||||
// get the offset of this frame from its parent view (walks up frame hierarchy)
|
// get the offset of this frame from its parent view (walks up frame hierarchy)
|
||||||
nsIView* theView = nsnull;
|
nsIView* theView = nsnull;
|
||||||
caretFrame->GetOffsetFromView(presContext, viewOffset, &theView);
|
caretFrame->GetOffsetFromView(presContext, withinViewOffset, &theView);
|
||||||
if (theView == nsnull) return;
|
if (theView == nsnull) return;
|
||||||
|
|
||||||
nsIView* returnView = nsnull; // views are not refcounted
|
nsIView* returnView = nsnull; // views are not refcounted
|
||||||
|
@ -525,6 +547,8 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy
|
||||||
nsIView* startingView = theView;
|
nsIView* startingView = theView;
|
||||||
nsIScrollableView* scrollableView = nsnull;
|
nsIScrollableView* scrollableView = nsnull;
|
||||||
|
|
||||||
|
nsPoint drawViewOffset(0, 0); // offset to the view we are using to draw
|
||||||
|
|
||||||
// walk up to the first view with a widget
|
// walk up to the first view with a widget
|
||||||
do {
|
do {
|
||||||
theView->GetPosition(&x, &y);
|
theView->GetPosition(&x, &y);
|
||||||
|
@ -535,19 +559,20 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy
|
||||||
|
|
||||||
PRBool hasWidget;
|
PRBool hasWidget;
|
||||||
theView->HasWidget(&hasWidget);
|
theView->HasWidget(&hasWidget);
|
||||||
|
|
||||||
if (hasWidget)
|
if (hasWidget)
|
||||||
{
|
{
|
||||||
returnView = theView;
|
returnView = theView;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
viewOffset.x += x;
|
drawViewOffset.x += x;
|
||||||
viewOffset.y += y;
|
drawViewOffset.y += y;
|
||||||
|
|
||||||
theView->GetParent(theView);
|
theView->GetParent(theView);
|
||||||
} while (theView);
|
} while (theView);
|
||||||
|
|
||||||
|
viewOffset = withinViewOffset;
|
||||||
|
viewOffset += drawViewOffset;
|
||||||
|
|
||||||
if (scrollableView)
|
if (scrollableView)
|
||||||
{
|
{
|
||||||
const nsIView* clipView = nsnull;
|
const nsIView* clipView = nsnull;
|
||||||
|
@ -558,7 +583,7 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy
|
||||||
clipView->GetBounds(bounds);
|
clipView->GetBounds(bounds);
|
||||||
scrollableView->GetScrollPosition(bounds.x, bounds.y);
|
scrollableView->GetScrollPosition(bounds.x, bounds.y);
|
||||||
|
|
||||||
bounds += viewOffset; // offset to coords of returned view
|
bounds += drawViewOffset; // offset to coords of returned view
|
||||||
outClipRect = bounds;
|
outClipRect = bounds;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -626,14 +651,22 @@ PRBool nsCaret::MustDrawCaret()
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
DrawCaretWithContext
|
DrawCaret
|
||||||
|
|
||||||
By this point, the caret rect should have been set up.
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------- */
|
----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void nsCaret::DrawCaretWithContext(nsIRenderingContext* inRendContext)
|
void nsCaret::DrawCaret()
|
||||||
{
|
{
|
||||||
|
// do we need to draw the caret at all?
|
||||||
|
if (!MustDrawCaret())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if we are drawing, not erasing, then set up the frame etc.
|
||||||
|
if (!mDrawn)
|
||||||
|
{
|
||||||
|
if (!SetupDrawingFrameAndOffset())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
|
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
|
||||||
|
|
||||||
|
@ -658,37 +691,44 @@ void nsCaret::DrawCaretWithContext(nsIRenderingContext* inRendContext)
|
||||||
|
|
||||||
frameRect += viewOffset;
|
frameRect += viewOffset;
|
||||||
|
|
||||||
nsCOMPtr<nsIPresContext> presContext;
|
|
||||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||||
if (presShell)
|
if (!presShell) return;
|
||||||
{
|
|
||||||
if (NS_FAILED(presShell->GetPresContext(getter_AddRefs(presContext))))
|
nsCOMPtr<nsIPresContext> presContext;
|
||||||
return;
|
if (NS_FAILED(presShell->GetPresContext(getter_AddRefs(presContext))))
|
||||||
}
|
|
||||||
else
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// make a rendering context, if we didn't get passed one
|
// if the view changed, or we don't have a rendering context, make one
|
||||||
nsCOMPtr<nsIRenderingContext> localRC = do_QueryInterface(inRendContext); // OK if inRendContext is null
|
// because of drawing issues, always make a new RC at the momemt. See bug 28068
|
||||||
if (!localRC)
|
if (
|
||||||
|
#ifdef DONT_REUSE_RENDERING_CONTEXT
|
||||||
|
PR_TRUE ||
|
||||||
|
#endif
|
||||||
|
(mLastCaretView != drawingView) || !mRendContext)
|
||||||
{
|
{
|
||||||
|
mRendContext = nsnull; // free existing one if we have one
|
||||||
|
|
||||||
nsCOMPtr<nsIDeviceContext> dx;
|
nsCOMPtr<nsIDeviceContext> dx;
|
||||||
|
|
||||||
if (NS_FAILED(presContext->GetDeviceContext(getter_AddRefs(dx))) || !dx)
|
if (NS_FAILED(presContext->GetDeviceContext(getter_AddRefs(dx))) || !dx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (NS_FAILED(dx->CreateRenderingContext(drawingView, *getter_AddRefs(localRC))) || !localRC)
|
if (NS_FAILED(dx->CreateRenderingContext(drawingView, *getter_AddRefs(mRendContext))) || !mRendContext)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// push a known good state
|
||||||
|
mRendContext->PushState();
|
||||||
|
|
||||||
|
// views are not refcounted
|
||||||
|
mLastCaretView = drawingView;
|
||||||
|
|
||||||
if (!mDrawn)
|
if (!mDrawn)
|
||||||
{
|
{
|
||||||
nsPoint framePos(0, 0);
|
nsPoint framePos(0, 0);
|
||||||
nsRect caretRect = frameRect;
|
nsRect caretRect = frameRect;
|
||||||
|
|
||||||
mLastCaretFrame->GetPointFromOffset(presContext, localRC, mLastContentOffset, &framePos);
|
mLastCaretFrame->GetPointFromOffset(presContext, mRendContext, mLastContentOffset, &framePos);
|
||||||
caretRect += framePos;
|
caretRect += framePos;
|
||||||
|
|
||||||
|
|
||||||
//printf("Content offset %ld, frame offset %ld\n", focusOffset, framePos.x);
|
//printf("Content offset %ld, frame offset %ld\n", focusOffset, framePos.x);
|
||||||
if(mCaretTwipsWidth < 0)
|
if(mCaretTwipsWidth < 0)
|
||||||
|
@ -721,52 +761,17 @@ void nsCaret::DrawCaretWithContext(nsIRenderingContext* inRendContext)
|
||||||
inRendContext.SetColor(NS_RGB(85, 85, 85)); // we are drawing it; gray
|
inRendContext.SetColor(NS_RGB(85, 85, 85)); // we are drawing it; gray
|
||||||
*/
|
*/
|
||||||
|
|
||||||
localRC->SetColor(NS_RGB(255,255,255));
|
mRendContext->SetColor(NS_RGB(255,255,255));
|
||||||
localRC->InvertRect(mCaretRect);
|
mRendContext->InvertRect(mCaretRect);
|
||||||
|
|
||||||
|
PRBool emptyClip; // I know what you're thinking. "Did he fire six shots or only five?"
|
||||||
|
mRendContext->PopState(emptyClip);
|
||||||
|
|
||||||
ToggleDrawnStatus();
|
ToggleDrawnStatus();
|
||||||
|
|
||||||
}
|
#ifdef DONT_REUSE_RENDERING_CONTEXT
|
||||||
|
mRendContext = nsnull;
|
||||||
//-----------------------------------------------------------------------------
|
#endif
|
||||||
void nsCaret::DrawCaret()
|
|
||||||
{
|
|
||||||
// do we need to draw the caret at all?
|
|
||||||
if (!MustDrawCaret())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// if we are drawing, not erasing, then set up the frame etc.
|
|
||||||
if (!mDrawn)
|
|
||||||
{
|
|
||||||
if (! SetupDrawingFrameAndOffset())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawCaretWithContext(nsnull);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void nsCaret::RefreshDrawCaret(nsIView *aView, nsIRenderingContext& inRendContext, const nsRect& aDirtyRect)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (! SetupDrawingFrameAndOffset())
|
|
||||||
return;
|
|
||||||
|
|
||||||
NS_ASSERTION(mLastCaretFrame != nsnull, "Should have a frame here");
|
|
||||||
|
|
||||||
nsPoint viewOffset(0, 0);
|
|
||||||
nsIView *drawingView;
|
|
||||||
//GetViewForRendering(viewOffset, drawingView);
|
|
||||||
|
|
||||||
mLastCaretFrame->GetOffsetFromView(viewOffset, &drawingView);
|
|
||||||
|
|
||||||
// are we in the view that is being painted?
|
|
||||||
if (drawingView == nsnull || drawingView != aView)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mDrawn = PR_FALSE; // we're rendering to a view that is being redrawn
|
|
||||||
DrawCaretWithContext(inRendContext);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_MAC
|
#ifdef XP_MAC
|
||||||
|
|
|
@ -24,12 +24,13 @@
|
||||||
|
|
||||||
#include "nsCoord.h"
|
#include "nsCoord.h"
|
||||||
#include "nsIDOMSelectionListener.h"
|
#include "nsIDOMSelectionListener.h"
|
||||||
|
#include "nsIRenderingContext.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
#include "nsICaret.h"
|
#include "nsICaret.h"
|
||||||
#include "nsWeakPtr.h"
|
#include "nsWeakPtr.h"
|
||||||
|
|
||||||
class nsITimer;
|
|
||||||
class nsIView;
|
class nsIView;
|
||||||
class nsIRenderingContext;
|
|
||||||
class nsISelectionController;
|
class nsISelectionController;
|
||||||
|
|
||||||
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
|
// {E14B66F6-BFC5-11d2-B57E-00105AA83B2F}
|
||||||
|
@ -83,30 +84,28 @@ class nsCaret : public nsICaret,
|
||||||
void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView* &outView);
|
void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView* &outView);
|
||||||
PRBool SetupDrawingFrameAndOffset();
|
PRBool SetupDrawingFrameAndOffset();
|
||||||
PRBool MustDrawCaret();
|
PRBool MustDrawCaret();
|
||||||
void RefreshDrawCaret(nsIView *aView, nsIRenderingContext& inRendContext, const nsRect& aDirtyRect);
|
|
||||||
void DrawCaretWithContext(nsIRenderingContext* inRendContext);
|
|
||||||
|
|
||||||
void DrawCaret();
|
void DrawCaret();
|
||||||
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
|
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
|
||||||
|
|
||||||
nsCOMPtr<nsIWeakReference> mPresShell;
|
protected:
|
||||||
|
|
||||||
nsCOMPtr<nsITimer> mBlinkTimer;
|
nsWeakPtr mPresShell;
|
||||||
|
nsWeakPtr mDomSelectionWeak;
|
||||||
|
|
||||||
PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
|
nsCOMPtr<nsITimer> mBlinkTimer;
|
||||||
nscoord mCaretTwipsWidth; // caret width in twips
|
nsCOMPtr<nsIRenderingContext> mRendContext;
|
||||||
nscoord mCaretPixelsWidth; // caret width in pixels
|
|
||||||
|
PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds
|
||||||
|
nscoord mCaretTwipsWidth; // caret width in twips
|
||||||
|
nscoord mCaretPixelsWidth; // caret width in pixels
|
||||||
|
|
||||||
PRBool mVisible; // is the caret blinking
|
PRPackedBool mVisible; // is the caret blinking
|
||||||
PRBool mReadOnly; // it the caret in readonly state (draws differently)
|
PRPackedBool mDrawn; // this should be mutable
|
||||||
|
PRPackedBool mReadOnly; // it the caret in readonly state (draws differently)
|
||||||
private:
|
|
||||||
|
|
||||||
PRBool mDrawn; // this should be mutable
|
|
||||||
|
|
||||||
nsRect mCaretRect; // the last caret rect
|
nsRect mCaretRect; // the last caret rect
|
||||||
nsIFrame* mLastCaretFrame; // store the frame the caret was last drawn in.
|
nsIFrame* mLastCaretFrame; // store the frame the caret was last drawn in.
|
||||||
|
nsIView* mLastCaretView; // last view that we used for drawing. Cached so we can tell when we need to make a new RC
|
||||||
PRInt32 mLastContentOffset;
|
PRInt32 mLastContentOffset;
|
||||||
nsWeakPtr mDomSelectionWeak;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче