Bug 368760, r=mats, sr=roc, a=blocking1.9+

This commit is contained in:
Olli.Pettay@helsinki.fi 2007-11-22 12:47:33 -08:00
Родитель 135a92dada
Коммит a0a74f16e7
14 изменённых файлов: 247 добавлений и 139 удалений

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

@ -1209,7 +1209,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
}
// disable selection mousedown state on activation
shell->FrameSelection()->SetMouseDownState(PR_FALSE);
nsCOMPtr<nsFrameSelection> frameSelection = shell->FrameSelection();
frameSelection->SetMouseDownState(PR_FALSE);
}
}
}
@ -1713,7 +1714,8 @@ nsEventStateManager::FireContextClick()
// stop selection tracking, we're in control now
if (mCurrentTarget)
{
nsFrameSelection* frameSel = mCurrentTarget->GetFrameSelection();
nsCOMPtr<nsFrameSelection> frameSel =
mCurrentTarget->GetFrameSelection();
if (frameSel && frameSel->GetMouseDownState()) {
// note that this can cause selection changed events to fire if we're in
@ -1849,7 +1851,7 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
// don't interfere!
if (mCurrentTarget)
{
nsFrameSelection* frameSel = mCurrentTarget->GetFrameSelection();
nsCOMPtr<nsFrameSelection> frameSel = mCurrentTarget->GetFrameSelection();
if (frameSel && frameSel->GetMouseDownState()) {
StopTrackingDragGesture();
return;
@ -2386,7 +2388,8 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
viewMan->GrabMouseEvents(nsnull, result);
}
}
shell->FrameSelection()->SetMouseDownState(PR_FALSE);
nsCOMPtr<nsFrameSelection> frameSelection = shell->FrameSelection();
frameSelection->SetMouseDownState(PR_FALSE);
}
}
break;
@ -4945,7 +4948,7 @@ nsEventStateManager::GetDocSelectionLocation(nsIContent **aStartContent,
nsIPresShell *shell;
shell = mPresContext->GetPresShell();
nsFrameSelection *frameSelection = nsnull;
nsCOMPtr<nsFrameSelection> frameSelection;
if (shell)
frameSelection = shell->FrameSelection();
@ -5296,7 +5299,8 @@ nsEventStateManager::MoveCaretToFocus()
nsCOMPtr<nsIDOMDocumentRange> rangeDoc(do_QueryInterface(mDocument));
if (rangeDoc) {
nsCOMPtr<nsISelection> domSelection = shell->FrameSelection()->
nsCOMPtr<nsFrameSelection> frameSelection = shell->FrameSelection();
nsCOMPtr<nsISelection> domSelection = frameSelection->
GetSelection(nsISelectionController::SELECTION_NORMAL);
if (domSelection) {
nsCOMPtr<nsIDOMNode> currentFocusNode(do_QueryInterface(mCurrentFocus));
@ -5355,7 +5359,7 @@ nsEventStateManager::SetContentCaretVisible(nsIPresShell* aPresShell,
nsCOMPtr<nsICaret> caret;
aPresShell->GetCaret(getter_AddRefs(caret));
nsFrameSelection* frameSelection = nsnull;
nsCOMPtr<nsFrameSelection> frameSelection;
if (aFocusedContent) {
nsIFrame *focusFrame = aPresShell->GetPrimaryFrameFor(aFocusedContent);
@ -5363,7 +5367,7 @@ nsEventStateManager::SetContentCaretVisible(nsIPresShell* aPresShell,
frameSelection = focusFrame->GetFrameSelection();
}
nsFrameSelection *docFrameSelection = aPresShell->FrameSelection();
nsCOMPtr<nsFrameSelection> docFrameSelection = aPresShell->FrameSelection();
if (docFrameSelection && caret &&
(frameSelection == docFrameSelection || !aFocusedContent)) {

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

@ -299,7 +299,7 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType,
nsIFrame* theFrame = nsnull;
PRInt32 theFrameOffset = 0;
nsFrameSelection* frameSelection = GetFrameSelection();
nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection();
if (!frameSelection)
return NS_ERROR_FAILURE;
PRUint8 bidiLevel = frameSelection->GetCaretBidiLevel();
@ -379,7 +379,7 @@ NS_IMETHODIMP nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset)
NS_ENSURE_ARG(aNode);
PRUint8 bidiLevel;
nsFrameSelection* frameSelection = GetFrameSelection();
nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection();
if (!frameSelection)
return NS_ERROR_FAILURE;
bidiLevel = frameSelection->GetCaretBidiLevel();
@ -591,7 +591,7 @@ nsCaret::DrawAtPositionWithHint(nsIDOMNode* aNode,
// If there has been a reflow, set the caret Bidi level to the level of the current frame
if (aBidiLevel & BIDI_LEVEL_UNDEFINED) {
nsFrameSelection* frameSelection = GetFrameSelection();
nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection();
if (!frameSelection)
return PR_FALSE;
frameSelection->SetCaretBidiLevel(NS_GET_EMBEDDING_LEVEL(theFrame));
@ -687,7 +687,7 @@ nsCaret::GetCaretFrameForNodeOffset(nsIContent* aContentNode,
if (!presShell)
return NS_ERROR_FAILURE;
nsFrameSelection* frameSelection = GetFrameSelection();
nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection();
if (!frameSelection)
return NS_ERROR_FAILURE;
@ -1009,7 +1009,7 @@ void nsCaret::DrawCaret(PRBool aInvalidate)
if (NS_FAILED(domSelection->GetFocusOffset(&offset)))
return;
nsFrameSelection* frameSelection = GetFrameSelection();
nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection();
if (!frameSelection)
return;
bidiLevel = frameSelection->GetCaretBidiLevel();
@ -1203,12 +1203,14 @@ void nsCaret::CaretBlinkCallback(nsITimer *aTimer, void *aClosure)
//-----------------------------------------------------------------------------
nsFrameSelection* nsCaret::GetFrameSelection() {
already_AddRefed<nsFrameSelection>
nsCaret::GetFrameSelection()
{
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryReferent(mDomSelectionWeak));
if (!privateSelection)
return nsnull;
nsCOMPtr<nsFrameSelection> frameSelection;
privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
nsFrameSelection* frameSelection = nsnull;
privateSelection->GetFrameSelection(&frameSelection);
return frameSelection;
}

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

@ -155,7 +155,7 @@ class nsCaret : public nsICaret,
}
void ToggleDrawnStatus() { mDrawn = !mDrawn; }
nsFrameSelection* GetFrameSelection();
already_AddRefed<nsFrameSelection> GetFrameSelection();
protected:

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

@ -102,10 +102,10 @@ class gfxContext;
typedef short SelectionType;
typedef PRUint32 nsFrameState;
// 4BE324F2-FB22-47CD-A653-19C70EE55E3F
// ff2bdd39-75ed-4392-92b8-8b650c4db574
#define NS_IPRESSHELL_IID \
{ 0x4BE324F2, 0xFB22, 0x47CD, \
{ 0xA6, 0x53, 0x19, 0xC7, 0x0E, 0xE5, 0x5E, 0x3F } }
{ 0xff2bdd39, 0x75ed, 0x4392, \
{ 0x92, 0xb8, 0x8b, 0x65, 0x0c, 0x4d, 0xb5, 0x74 } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
@ -252,7 +252,13 @@ public:
* You cannot go back and forth anymore with QI between nsIDOM sel and
* nsIFrame sel.
*/
nsFrameSelection* FrameSelection() { return mSelection; }
already_AddRefed<nsFrameSelection> FrameSelection();
/**
* ConstFrameSelection returns an object which methods are safe to use for
* example in nsIFrame code.
*/
const nsFrameSelection* ConstFrameSelection() { return mSelection; }
// Make shell be a document observer. If called after Destroy() has
// been called on the shell, this will be ignored.

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

@ -1352,6 +1352,13 @@ nsIPresShell::RemoveWeakFrame(nsWeakFrame* aWeakFrame)
}
}
already_AddRefed<nsFrameSelection>
nsIPresShell::FrameSelection()
{
NS_IF_ADDREF(mSelection);
return mSelection;
}
//----------------------------------------------------------------------
nsresult
@ -1412,7 +1419,10 @@ PresShell::~PresShell()
NS_IF_RELEASE(mPresContext);
NS_IF_RELEASE(mDocument);
NS_IF_RELEASE(mSelection);
if (mSelection) {
mSelection->DisconnectFromPresShell();
NS_RELEASE(mSelection);
}
}
/**

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

@ -2716,9 +2716,10 @@ nsTextControlFrame::SetValue(const nsAString& aValue)
selPriv->StartBatchChanges();
}
nsCOMPtr<nsISelectionController> kungFuDeathGrip = mSelCon;
mSelCon->SelectAll();
nsCOMPtr<nsIPlaintextEditor> plaintextEditor = do_QueryInterface(editor);
if (!plaintextEditor) {
if (!plaintextEditor || !weakFrame.IsAlive()) {
NS_WARNING("Somehow not a plaintext editor?");
if (pushed) {
JSContext* cx;

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

@ -816,7 +816,7 @@ nsFrame::DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
if (!(displaySelection & aContentType))
return NS_OK;
nsFrameSelection* frameSelection = GetFrameSelection();
const nsFrameSelection* frameSelection = GetConstFrameSelection();
PRInt16 selectionValue = frameSelection->GetDisplaySelection();
if (selectionValue <= nsISelectionController::SELECTION_HIDDEN)
@ -1516,7 +1516,7 @@ nsFrame::HandleEvent(nsPresContext* aPresContext,
}
NS_IMETHODIMP
nsFrame::GetDataForTableSelection(nsFrameSelection *aFrameSelection,
nsFrame::GetDataForTableSelection(const nsFrameSelection *aFrameSelection,
nsIPresShell *aPresShell, nsMouseEvent *aMouseEvent,
nsIContent **aParentContent, PRInt32 *aContentOffset, PRInt32 *aTarget)
{
@ -1775,11 +1775,11 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
// XXX This is screwy; it really should use the selection frame, not the
// event frame
nsFrameSelection* frameselection;
const nsFrameSelection* frameselection = nsnull;
if (useFrameSelection)
frameselection = GetFrameSelection();
frameselection = GetConstFrameSelection();
else
frameselection = shell->FrameSelection();
frameselection = shell->ConstFrameSelection();
if (frameselection->GetDisplaySelection() == nsISelectionController::SELECTION_OFF)
return NS_OK;//nothing to do we cannot affect selection from here
@ -1790,11 +1790,13 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
if (me->isControl)
return NS_OK;//short ciruit. hard coded for mac due to time restraints.
#endif
nsCOMPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
if (me->clickCount >1 )
{
frameselection->SetMouseDownState(PR_TRUE);
frameselection->SetMouseDoubleDown(PR_TRUE);
// These methods aren't const but can't actually delete anything,
// so no need for nsWeakFrame.
fc->SetMouseDownState(PR_TRUE);
fc->SetMouseDoubleDown(PR_TRUE);
return HandleMultiplePress(aPresContext, aEvent, aEventStatus);
}
@ -1811,11 +1813,11 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
rv = GetDataForTableSelection(frameselection, shell, me, getter_AddRefs(parentContent), &contentOffset, &target);
if (NS_SUCCEEDED(rv) && parentContent)
{
frameselection->SetMouseDownState(PR_TRUE);
return frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
fc->SetMouseDownState(PR_TRUE);
return fc->HandleTableSelection(parentContent, contentOffset, target, me);
}
frameselection->SetDelayedCaretData(0);
fc->SetDelayedCaretData(0);
// Check if any part of this frame is selected, and if the
// user clicked inside the selected region. If so, we delay
@ -1852,8 +1854,8 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
offsets.EndOffset() <= curDetail->mEnd)
{
delete details;
frameselection->SetMouseDownState(PR_FALSE);
frameselection->SetDelayedCaretData(me);
fc->SetMouseDownState(PR_FALSE);
fc->SetDelayedCaretData(me);
return NS_OK;
}
@ -1864,7 +1866,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
}
}
frameselection->SetMouseDownState(PR_TRUE);
fc->SetMouseDownState(PR_TRUE);
#ifdef XP_MACOSX
PRBool control = me->isMeta;
@ -1872,15 +1874,17 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
PRBool control = me->isControl;
#endif
rv = frameselection->HandleClick(offsets.content, offsets.StartOffset(),
offsets.EndOffset(), me->isShift, control,
offsets.associateWithNext);
// Do not touch any nsFrame members after this point without adding
// weakFrame checks.
rv = fc->HandleClick(offsets.content, offsets.StartOffset(),
offsets.EndOffset(), me->isShift, control,
offsets.associateWithNext);
if (NS_FAILED(rv))
return rv;
if (offsets.offset != offsets.secondaryOffset)
frameselection->MaintainSelection();
fc->MaintainSelection();
if (isEditor && !me->isShift &&
(offsets.EndOffset() - offsets.StartOffset()) == 1)
@ -1890,7 +1894,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
// -moz-user-select: all or a non-text node without children).
// Therefore, disable selection extension during mouse moves.
// XXX This is a bit hacky; shouldn't editor be able to deal with this?
frameselection->SetMouseDownState(PR_FALSE);
fc->SetMouseDownState(PR_FALSE);
}
return rv;
@ -1945,7 +1949,9 @@ nsFrame::HandleMultiplePress(nsPresContext* aPresContext,
nsIFrame* theFrame;
PRInt32 offset;
// Maybe make this a static helper?
theFrame = PresContext()->GetPresShell()->FrameSelection()->
const nsFrameSelection* frameSelection =
PresContext()->GetPresShell()->ConstFrameSelection();
theFrame = frameSelection->
GetFrameForNodeOffset(offsets.content, offsets.offset,
nsFrameSelection::HINT(offsets.associateWithNext),
&offset);
@ -3972,7 +3978,17 @@ nsFrame::GetSelectionController(nsPresContext *aPresContext, nsISelectionControl
return CallQueryInterface(aPresContext->GetPresShell(), aSelCon);
}
nsFrameSelection* nsIFrame::GetFrameSelection()
already_AddRefed<nsFrameSelection>
nsIFrame::GetFrameSelection()
{
nsFrameSelection* fs =
const_cast<nsFrameSelection*>(GetConstFrameSelection());
NS_IF_ADDREF(fs);
return fs;
}
const nsFrameSelection*
nsIFrame::GetConstFrameSelection()
{
nsIFrame *frame = this;
while (frame && (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION)) {
@ -3983,7 +3999,7 @@ nsFrameSelection* nsIFrame::GetFrameSelection()
frame = frame->GetParent();
}
return PresContext()->PresShell()->FrameSelection();
return PresContext()->PresShell()->ConstFrameSelection();
}
#ifdef NS_DEBUG

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

@ -579,7 +579,7 @@ protected:
// of the enclosing cell or table (if not inside a cell)
// aTarget tells us what table element to select (currently only cell and table supported)
// (enums for this are defined in nsIFrame.h)
NS_IMETHOD GetDataForTableSelection(nsFrameSelection *aFrameSelection,
NS_IMETHOD GetDataForTableSelection(const nsFrameSelection *aFrameSelection,
nsIPresShell *aPresShell, nsMouseEvent *aMouseEvent,
nsIContent **aParentContent, PRInt32 *aContentOffset,
PRInt32 *aTarget);

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

@ -48,10 +48,10 @@
#include "nsGUIEvent.h"
// IID for the nsFrameSelection interface
// 6c2c1a4c-47ec-42be-a790-00417bf4c241
// d78edc5a-28d0-48f0-8abb-1597b1591556
#define NS_FRAME_SELECTION_IID \
{ 0x6c2c1a4c, 0x47ec, 0x42be, \
{ 0xa7, 0x90, 0x00, 0x41, 0x7b, 0xf4, 0xc2, 0x41 } }
{ 0xd78edc5a, 0x28d0, 0x48f0, \
{ 0x8a, 0xbb, 0x15, 0x97, 0xb1, 0x59, 0x15, 0x56 } }
#ifdef IBMBIDI // Constant for Set/Get CaretBidiLevel
#define BIDI_LEVEL_UNDEFINED 0x80
@ -194,6 +194,12 @@ struct nsPrevNextBidiLevels
class nsTypedSelection;
class nsIScrollableView;
/**
* Methods which are marked with *unsafe* should be handled with special care.
* They may cause nsFrameSelection to be deleted, if strong pointer isn't used,
* or they may cause other objects to be deleted.
*/
class nsFrameSelection : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAME_SELECTION_IID)
@ -221,7 +227,7 @@ public:
/**
* GetScrollableView returns the current scroll view.
*/
nsIScrollableView* GetScrollableView()
nsIScrollableView* GetScrollableView() const
{
return mScrollableViewProvider
? mScrollableViewProvider->GetScrollableView()
@ -241,6 +247,7 @@ public:
* @param aHint will tell the selection which direction geometrically to actually show the caret on.
* 1 = end of this line 0 = beginning of this line
*/
/*unsafe*/
nsresult HandleClick(nsIContent *aNewFocus,
PRUint32 aContentOffset,
PRUint32 aContentEndOffset,
@ -253,6 +260,7 @@ public:
* @param aFrame is the parent of all frames to use when searching for the closest frame to the point.
* @param aPoint is relative to aFrame
*/
/*unsafe*/
void HandleDrag(nsIFrame *aFrame, nsPoint aPoint);
/** HandleTableSelection will set selection to a table, cell, etc
@ -267,6 +275,7 @@ public:
* TABLESELECTION_ALLCELLS We should select all cells (content points to any cell in table)
* @param aMouseEvent passed in so we can get where event occurred and what keys are pressed
*/
/*unsafe*/
nsresult HandleTableSelection(nsIContent *aParentContent,
PRInt32 aContentOffset,
PRInt32 aTarget,
@ -299,31 +308,32 @@ public:
SelectionDetails* LookUpSelection(nsIContent *aContent,
PRInt32 aContentOffset,
PRInt32 aContentLength,
PRBool aSlowCheck);
PRBool aSlowCheck) const;
/** SetMouseDownState(PRBool);
* sets the mouse state to aState for resons of drag state.
* @param aState is the new state of mousedown
*/
/*unsafe*/
void SetMouseDownState(PRBool aState);
/** GetMouseDownState(PRBool *);
* gets the mouse state to aState for resons of drag state.
* @param aState will hold the state of mousedown
*/
PRBool GetMouseDownState() { return mMouseDownState; }
PRBool GetMouseDownState() const { return mMouseDownState; }
/**
if we are in table cell selection mode. aka ctrl click in table cell
*/
PRBool GetTableCellSelection() { return mSelectingTableCellMode != 0; }
void ClearTableCellSelection(){ mSelectingTableCellMode = 0; }
PRBool GetTableCellSelection() const { return mSelectingTableCellMode != 0; }
void ClearTableCellSelection() { mSelectingTableCellMode = 0; }
/** GetSelection
* no query interface for selection. must use this method now.
* @param aSelectionType enum value defined in nsISelection for the seleciton you want.
*/
nsISelection* GetSelection(SelectionType aType);
nsISelection* GetSelection(SelectionType aType) const;
/**
* ScrollSelectionIntoView scrolls a region of the selection,
@ -336,13 +346,13 @@ public:
*/
nsresult ScrollSelectionIntoView(SelectionType aType,
SelectionRegion aRegion,
PRBool aIsSynchronous);
PRBool aIsSynchronous) const;
/** RepaintSelection repaints the selected frames that are inside the selection
* specified by aSelectionType.
* @param aSelectionType enum value defined in nsISelection for the seleciton you want.
*/
nsresult RepaintSelection(SelectionType aType);
nsresult RepaintSelection(SelectionType aType) const;
/** GetFrameForNodeOffset given a node and its child offset, return the nsIFrame and
* the offset into that frame.
@ -353,7 +363,7 @@ public:
nsIFrame* GetFrameForNodeOffset(nsIContent *aNode,
PRInt32 aOffset,
HINT aHint,
PRInt32 *aReturnOffset);
PRInt32 *aReturnOffset) const;
/**
* Scrolling then moving caret placement code in common to text areas and
@ -367,12 +377,13 @@ public:
* @param aExtend if PR_TRUE, extend selection to the new point
* @param aScrollableView the view that needs the scrolling
*/
/*unsafe*/
void CommonPageMove(PRBool aForward,
PRBool aExtend,
nsIScrollableView *aScrollableView);
void SetHint(HINT aHintRight) { mHint = aHintRight; }
HINT GetHint() { return mHint; }
HINT GetHint() const { return mHint; }
#ifdef IBMBIDI
/** SetCaretBidiLevel sets the caret bidi level
@ -383,7 +394,7 @@ public:
/** GetCaretBidiLevel gets the caret bidi level
* This method is virtual since it gets called from outside of layout.
*/
virtual PRUint8 GetCaretBidiLevel();
virtual PRUint8 GetCaretBidiLevel() const;
/** UndefineCaretBidiLevel sets the caret bidi level to "undefined"
* This method is virtual since it gets called from outside of layout.
*/
@ -395,6 +406,7 @@ public:
* @param aForward move forward in document.
* @param aExtend continue selection
*/
/*unsafe*/
nsresult CharacterMove(PRBool aForward, PRBool aExtend);
/** WordMove will generally be called from the nsiselectioncontroller implementations.
@ -402,12 +414,14 @@ public:
* @param aForward move forward in document.
* @param aExtend continue selection
*/
/*unsafe*/
nsresult WordMove(PRBool aForward, PRBool aExtend);
/** WordExtendForDelete extends the selection backward or forward (logically) to the
* next word boundary, so that the selected word can be deleted.
* @param aForward select forward in document.
*/
/*unsafe*/
nsresult WordExtendForDelete(PRBool aForward);
/** LineMove will generally be called from the nsiselectioncontroller implementations.
@ -415,6 +429,7 @@ public:
* @param aForward move forward in document.
* @param aExtend continue selection
*/
/*unsafe*/
nsresult LineMove(PRBool aForward, PRBool aExtend);
/** IntraLineMove will generally be called from the nsiselectioncontroller implementations.
@ -422,17 +437,19 @@ public:
* @param aForward move forward in document.
* @param aExtend continue selection
*/
/*unsafe*/
nsresult IntraLineMove(PRBool aForward, PRBool aExtend);
/** Select All will generally be called from the nsiselectioncontroller implementations.
* it will select the whole doc
*/
/*unsafe*/
nsresult SelectAll();
/** Sets/Gets The display selection enum.
*/
void SetDisplaySelection(PRInt16 aState) { mDisplaySelection = aState; }
PRInt16 GetDisplaySelection() { return mDisplaySelection; }
PRInt16 GetDisplaySelection() const { return mDisplaySelection; }
/** This method can be used to store the data received during a MouseDown
* event so that we can place the caret during the MouseUp event.
@ -455,9 +472,10 @@ public:
* in an browser page, we must stop at this node else we reach into the
* parent page, which is very bad!
*/
nsIContent* GetLimiter() { return mLimiter; }
nsIContent* GetLimiter() const { return mLimiter; }
nsIContent* GetAncestorLimiter() { return mAncestorLimiter; }
nsIContent* GetAncestorLimiter() const { return mAncestorLimiter; }
/*unsafe*/
void SetAncestorLimiter(nsIContent *aLimiter);
/** This will tell the frame selection that a double click has been pressed
@ -469,7 +487,7 @@ public:
/** This will return whether the double down flag was set.
* @return whether the double down flag was set
*/
PRBool GetMouseDoubleDown() { return mMouseDoubleDownState; }
PRBool GetMouseDoubleDown() const { return mMouseDoubleDownState; }
/** GetPrevNextBidiLevels will return the frames and associated Bidi levels of the characters
* logically before and after a (collapsed) selection.
@ -489,7 +507,7 @@ public:
*/
virtual nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode,
PRUint32 aContentOffset,
PRBool aJumpLines);
PRBool aJumpLines) const;
/** GetFrameFromLevel will scan in a given direction
* until it finds a frame with a Bidi level less than or equal to a given level.
@ -503,7 +521,7 @@ public:
nsresult GetFrameFromLevel(nsIFrame *aFrameIn,
nsDirection aDirection,
PRUint8 aBidiLevel,
nsIFrame **aFrameOut);
nsIFrame **aFrameOut) const;
/**
* MaintainSelection will track the current selection as being "sticky".
@ -521,10 +539,12 @@ public:
void StartBatchChanges();
void EndBatchChanges();
/*unsafe*/
nsresult DeleteFromDocument();
nsIPresShell *GetShell() {return mShell;}
nsIPresShell *GetShell()const { return mShell; }
void DisconnectFromPresShell() { mShell = nsnull; }
private:
nsresult TakeFocus(nsIContent *aNewFocus,
PRUint32 aContentOffset,
@ -541,7 +561,7 @@ private:
nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode,
PRUint32 aContentOffset,
HINT aHint,
PRBool aJumpLines);
PRBool aJumpLines) const;
#ifdef VISUALSELECTION
NS_IMETHOD VisualSelectFrames(nsIFrame* aCurrentFrame,
nsPeekOffsetStruct aPos);
@ -591,18 +611,20 @@ private:
nsresult GetRootForContentSubtree(nsIContent *aContent, nsIContent **aParent);
nsresult ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame, nsPoint& aPoint, nsIFrame **aRetFrame, nsPoint& aRetPoint);
PRUint32 GetBatching(){return mBatching;}
PRBool GetNotifyFrames(){return mNotifyFrames;}
PRUint32 GetBatching() const {return mBatching; }
PRBool GetNotifyFrames() const { return mNotifyFrames; }
void SetDirty(PRBool aDirty=PR_TRUE){if (mBatching) mChangesDuringBatching = aDirty;}
// nsFrameSelection may get deleted when calling this,
// so remember to use nsCOMPtr when needed.
nsresult NotifySelectionListeners(SelectionType aType); // add parameters to say collapsed etc?
nsTypedSelection *mDomSelections[nsISelectionController::NUM_SELECTIONTYPES];
// Table selection support.
// Interfaces that let us get info based on cellmap locations
nsITableLayout* GetTableLayout(nsIContent *aTableContent);
nsITableCellLayout* GetCellLayout(nsIContent *aCellContent);
nsITableLayout* GetTableLayout(nsIContent *aTableContent) const;
nsITableCellLayout* GetCellLayout(nsIContent *aCellContent) const;
nsresult SelectBlockOfCells(nsIContent *aStartNode, nsIContent *aEndNode);
nsresult SelectRowOrColumn(nsIContent *aCellContent, PRUint32 aTarget);
@ -610,10 +632,13 @@ private:
nsresult GetFirstSelectedCellAndRange(nsIDOMNode **aCell, nsIDOMRange **aRange);
nsresult GetNextSelectedCellAndRange(nsIDOMNode **aCell, nsIDOMRange **aRange);
nsresult GetFirstCellNodeInRange(nsIDOMRange *aRange, nsIDOMNode **aCellNode);
nsresult GetFirstCellNodeInRange(nsIDOMRange *aRange,
nsIDOMNode **aCellNode) const;
// aTableNode may be null if table isn't needed to be returned
PRBool IsInSameTable(nsIContent *aContent1, nsIContent *aContent2, nsIContent **aTableNode);
nsresult GetParentTable(nsIContent *aCellNode, nsIContent **aTableNode);
PRBool IsInSameTable(nsIContent *aContent1, nsIContent *aContent2,
nsIContent **aTableNode) const;
nsresult GetParentTable(nsIContent *aCellNode,
nsIContent **aTableNode) const;
nsresult SelectCellElement(nsIDOMElement* aCellElement);
nsresult CreateAndAddRange(nsIDOMNode *aParentNode, PRInt32 aOffset);
nsresult ClearNormalSelection();

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

@ -104,10 +104,10 @@ struct nsMargin;
typedef class nsIFrame nsIBox;
// IID for the nsIFrame interface
// 39681dd7-5db6-4e38-b84c-5d9a163c987a
// 95f75c0a-de85-437a-a195-0304df3f62ce
#define NS_IFRAME_IID \
{ 0x39681dd7, 0x5db6, 0x4e38, \
{ 0xb8, 0x4c, 0x5d, 0x9a, 0x16, 0x3c, 0x98, 0x7a } }
{ 0x95f75c0a, 0xde85, 0x437a, \
{ 0xa1, 0x95, 0x03, 0x04, 0xdf, 0x3f, 0x62, 0xce } }
/**
* Indication of how the frame can be split. This is used when doing runaround
@ -1726,9 +1726,15 @@ public:
NS_IMETHOD GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) = 0;
/**
* Call to get nsFrameSelection for this frame; does not addref
* Call to get nsFrameSelection for this frame.
*/
nsFrameSelection* GetFrameSelection();
already_AddRefed<nsFrameSelection> GetFrameSelection();
/**
* GetConstFrameSelection returns an object which methods are safe to use for
* example in nsIFrame code.
*/
const nsFrameSelection* GetConstFrameSelection();
/** EndSelection related calls
*/

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

@ -112,10 +112,6 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#include "nsIBidiKeyboard.h"
#endif // IBMBIDI
#define STATUS_CHECK_RETURN_MACRO() {if (!mShell) return NS_ERROR_FAILURE;}
//#define DEBUG_TABLE 1
static NS_DEFINE_IID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
@ -188,6 +184,13 @@ struct RangeData
PRInt32 mEndIndex; // index into mRangeEndings of this item
};
// Note, the ownership of nsTypedSelection depends on which way the object is
// created. When nsFrameSelection has created nsTypedSelection,
// addreffing/releasing nsTypedSelection object is aggregated to
// nsFrameSelection. Otherwise normal addref/release is used.
// This ensures that nsFrameSelection is never deleted before its
// nsTypedSelections.
class nsTypedSelection : public nsISelection2,
public nsISelectionPrivate,
public nsSupportsWeakReference
@ -279,8 +282,6 @@ public:
nsresult NotifySelectionListeners();
void DetachFromPresentation();
private:
friend class nsSelectionIterator;
@ -555,12 +556,14 @@ public:
nsIView* captureView = capturingFrame->GetMouseCapturer();
nsIFrame* viewFrame = static_cast<nsIFrame*>(captureView->GetClientData());
NS_ASSERTION(viewFrame, "View must have a client frame");
nsWeakFrame viewFrame = static_cast<nsIFrame*>(captureView->GetClientData());
NS_ASSERTION(viewFrame.GetFrame(), "View must have a client frame");
mFrameSelection->HandleDrag(viewFrame, mPoint);
mSelection->DoAutoScrollView(mPresContext, captureView, mPoint, PR_TRUE);
mSelection->DoAutoScrollView(mPresContext,
viewFrame.IsAlive() ? captureView : nsnull,
mPoint, PR_TRUE);
}
return NS_OK;
}
@ -824,7 +827,6 @@ nsFrameSelection::nsFrameSelection()
mDomSelections[i] = new nsTypedSelection(this);
if (!mDomSelections[i])
return;
NS_ADDREF(mDomSelections[i]);
mDomSelections[i]->SetType(GetSelectionTypeFromIndex(i));
}
mBatching = 0;
@ -869,8 +871,7 @@ nsFrameSelection::~nsFrameSelection()
PRInt32 i;
for (i = 0;i<nsISelectionController::NUM_SELECTIONTYPES;i++){
if (mDomSelections[i]) {
mDomSelections[i]->DetachFromPresentation();
NS_RELEASE(mDomSelections[i]);
delete mDomSelections[i];
}
}
}
@ -1078,6 +1079,7 @@ nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame,
// find the closest frame aPoint.
//
NS_ENSURE_STATE(mShell);
*aRetFrame = mShell->GetPrimaryFrameFor(anchorRoot);
if (! *aRetFrame)
@ -1109,7 +1111,7 @@ nsFrameSelection::SetCaretBidiLevel(PRUint8 aLevel)
}
PRUint8
nsFrameSelection::GetCaretBidiLevel()
nsFrameSelection::GetCaretBidiLevel() const
{
return mCaretBidiLevel;
}
@ -1218,20 +1220,15 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode,
PRBool aContinueSelection,
nsSelectionAmount aAmount)
{
{
// Make sure that if our presshell gets Destroy() called when we
// flush we don't die.
nsRefPtr<nsFrameSelection> kungFuDeathGrip(this);
NS_ENSURE_STATE(mShell);
// Flush out layout, since we need it to be up to date to do caret
// positioning.
mShell->FlushPendingNotifications(Flush_Layout);
// Flush out layout, since we need it to be up to date to do caret
// positioning.
mShell->FlushPendingNotifications(Flush_Layout);
if (!mShell) {
return NS_OK;
}
if (!mShell) {
return NS_OK;
}
nsPresContext *context = mShell->GetPresContext();
if (!context)
return NS_ERROR_FAILURE;
@ -1945,7 +1942,7 @@ nsFrameSelection::VisualSelectFrames(nsIFrame* aCurrentFrame,
nsPrevNextBidiLevels
nsFrameSelection::GetPrevNextBidiLevels(nsIContent *aNode,
PRUint32 aContentOffset,
PRBool aJumpLines)
PRBool aJumpLines) const
{
return GetPrevNextBidiLevels(aNode, aContentOffset, mHint, aJumpLines);
}
@ -1954,7 +1951,7 @@ nsPrevNextBidiLevels
nsFrameSelection::GetPrevNextBidiLevels(nsIContent *aNode,
PRUint32 aContentOffset,
HINT aHint,
PRBool aJumpLines)
PRBool aJumpLines) const
{
// Get the level of the frames on each side
nsIFrame *currentFrame;
@ -2024,8 +2021,9 @@ nsresult
nsFrameSelection::GetFrameFromLevel(nsIFrame *aFrameIn,
nsDirection aDirection,
PRUint8 aBidiLevel,
nsIFrame **aFrameOut)
nsIFrame **aFrameOut) const
{
NS_ENSURE_STATE(mShell);
PRUint8 foundLevel = 0;
nsIFrame *foundFrame = aFrameIn;
@ -2268,7 +2266,7 @@ nsFrameSelection::HandleClick(nsIContent *aNewFocus,
void
nsFrameSelection::HandleDrag(nsIFrame *aFrame, nsPoint aPoint)
{
if (!aFrame)
if (!aFrame || !mShell)
return;
nsresult result;
@ -2351,6 +2349,7 @@ nsFrameSelection::StartAutoScrollTimer(nsIView *aView,
nsPoint aPoint,
PRUint32 aDelay)
{
NS_ENSURE_STATE(mShell);
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
return mDomSelections[index]->StartAutoScrollTimer(mShell->GetPresContext(),
aView, aPoint, aDelay);
@ -2376,7 +2375,7 @@ nsFrameSelection::TakeFocus(nsIContent *aNewFocus,
if (!aNewFocus)
return NS_ERROR_NULL_POINTER;
STATUS_CHECK_RETURN_MACRO();
NS_ENSURE_STATE(mShell);
if (!IsValidSelectionPoint(this,aNewFocus))
return NS_ERROR_FAILURE;
@ -2428,6 +2427,7 @@ nsFrameSelection::TakeFocus(nsIContent *aNewFocus,
//if we are no longer inside same table ,cell then switch to table selection mode.
// BUT only do this in an editor
NS_ENSURE_STATE(mShell);
PRInt16 displaySelection;
nsresult result = mShell->GetSelectionFlags(&displaySelection);
if (NS_FAILED(result))
@ -2502,8 +2502,10 @@ printf(" * TakeFocus - moving into new cell\n");
SelectionDetails*
nsFrameSelection::LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset,
PRInt32 aContentLength, PRBool aSlowCheck)
nsFrameSelection::LookUpSelection(nsIContent *aContent,
PRInt32 aContentOffset,
PRInt32 aContentLength,
PRBool aSlowCheck) const
{
if (!aContent || !mShell)
return nsnull;
@ -2536,7 +2538,7 @@ nsFrameSelection::SetMouseDownState(PRBool aState)
}
nsISelection*
nsFrameSelection::GetSelection(SelectionType aType)
nsFrameSelection::GetSelection(SelectionType aType) const
{
PRInt8 index = GetIndexFromSelectionType(aType);
if (index < 0)
@ -2548,7 +2550,7 @@ nsFrameSelection::GetSelection(SelectionType aType)
nsresult
nsFrameSelection::ScrollSelectionIntoView(SelectionType aType,
SelectionRegion aRegion,
PRBool aIsSynchronous)
PRBool aIsSynchronous) const
{
PRInt8 index = GetIndexFromSelectionType(aType);
if (index < 0)
@ -2562,13 +2564,14 @@ nsFrameSelection::ScrollSelectionIntoView(SelectionType aType,
}
nsresult
nsFrameSelection::RepaintSelection(SelectionType aType)
nsFrameSelection::RepaintSelection(SelectionType aType) const
{
PRInt8 index = GetIndexFromSelectionType(aType);
if (index < 0)
return NS_ERROR_INVALID_ARG;
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
NS_ENSURE_STATE(mShell);
return mDomSelections[index]->Repaint(mShell->GetPresContext());
}
@ -2576,9 +2579,9 @@ nsIFrame*
nsFrameSelection::GetFrameForNodeOffset(nsIContent *aNode,
PRInt32 aOffset,
HINT aHint,
PRInt32 *aReturnOffset)
PRInt32 *aReturnOffset) const
{
if (!aNode || !aReturnOffset)
if (!aNode || !aReturnOffset || !mShell)
return nsnull;
if (aOffset < 0)
@ -2818,6 +2821,7 @@ nsFrameSelection::SelectAll()
}
else
{
NS_ENSURE_STATE(mShell);
nsIDocument *doc = mShell->GetDocument();
if (!doc)
return NS_ERROR_FAILURE;
@ -2871,8 +2875,9 @@ static PRBool IsCell(nsIContent *aContent)
}
nsITableCellLayout*
nsFrameSelection::GetCellLayout(nsIContent *aCellContent)
nsFrameSelection::GetCellLayout(nsIContent *aCellContent) const
{
NS_ENSURE_TRUE(mShell, nsnull);
// Get frame for cell
nsIFrame *cellFrame = mShell->GetPrimaryFrameFor(aCellContent);
if (!cellFrame)
@ -2885,8 +2890,9 @@ nsFrameSelection::GetCellLayout(nsIContent *aCellContent)
}
nsITableLayout*
nsFrameSelection::GetTableLayout(nsIContent *aTableContent)
nsFrameSelection::GetTableLayout(nsIContent *aTableContent) const
{
NS_ENSURE_TRUE(mShell, nsnull);
// Get frame for table
nsIFrame *tableFrame = mShell->GetPrimaryFrameFor(aTableContent);
if (!tableFrame)
@ -3046,6 +3052,7 @@ printf("HandleTableSelection: Mouse down event\n");
// We have at least 1 other selected cell
// Check if new cell is already selected
NS_ENSURE_STATE(mShell);
nsIFrame *cellFrame = mShell->GetPrimaryFrameFor(childContent);
if (!cellFrame) return NS_ERROR_NULL_POINTER;
result = cellFrame->GetSelected(&isSelected);
@ -3253,10 +3260,8 @@ nsFrameSelection::SelectBlockOfCells(nsIContent *aStartCell, nsIContent *aEndCel
result = GetCellIndexes(aEndCell, endRowIndex, endColIndex);
if(NS_FAILED(result)) return result;
// Get TableLayout interface to access cell data based on cellmap location
// frames are not ref counted, so don't use an nsCOMPtr
nsITableLayout *tableLayoutObject = GetTableLayout(table);
if (!tableLayoutObject) return NS_ERROR_FAILURE;
// Check that |table| is a table.
if (!GetTableLayout(table)) return NS_ERROR_FAILURE;
PRInt32 curRowIndex, curColIndex;
@ -3311,6 +3316,11 @@ printf("SelectBlockOfCells -- range is null\n");
PRInt32 col = startColIndex;
while(PR_TRUE)
{
// Get TableLayout interface to access cell data based on cellmap location
// frames are not ref counted, so don't use an nsCOMPtr
nsITableLayout *tableLayoutObject = GetTableLayout(table);
if (!tableLayoutObject) return NS_ERROR_FAILURE;
result = tableLayoutObject->GetCellDataAt(row, col, *getter_AddRefs(cellElement),
curRowIndex, curColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
@ -3462,7 +3472,7 @@ nsFrameSelection::SelectRowOrColumn(nsIContent *aCellContent, PRUint32 aTarget)
nsresult
nsFrameSelection::GetFirstCellNodeInRange(nsIDOMRange *aRange,
nsIDOMNode **aCellNode)
nsIDOMNode **aCellNode) const
{
if (!aRange || !aCellNode) return NS_ERROR_NULL_POINTER;
@ -3602,7 +3612,7 @@ nsFrameSelection::GetCellIndexes(nsIContent *aCell,
PRBool
nsFrameSelection::IsInSameTable(nsIContent *aContent1,
nsIContent *aContent2,
nsIContent **aTable)
nsIContent **aTable) const
{
if (!aContent1 || !aContent2) return PR_FALSE;
@ -3631,7 +3641,7 @@ nsFrameSelection::IsInSameTable(nsIContent *aContent1,
}
nsresult
nsFrameSelection::GetParentTable(nsIContent *aCell, nsIContent **aTable)
nsFrameSelection::GetParentTable(nsIContent *aCell, nsIContent **aTable) const
{
if (!aCell || !aTable) {
return NS_ERROR_NULL_POINTER;
@ -3992,10 +4002,6 @@ nsTypedSelection::nsTypedSelection()
nsTypedSelection::~nsTypedSelection()
{
DetachFromPresentation();
}
void nsTypedSelection::DetachFromPresentation() {
setAnchorFocusRange(-1);
if (mAutoScrollTimer) {
@ -4025,9 +4031,36 @@ NS_INTERFACE_MAP_BEGIN(nsTypedSelection)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsTypedSelection)
NS_IMPL_RELEASE(nsTypedSelection)
NS_IMETHODIMP_(nsrefcnt)
nsTypedSelection::AddRef()
{
if (mFrameSelection) {
return mFrameSelection->AddRef();
}
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
NS_ASSERT_OWNINGTHREAD(nsTypedSelection);
++mRefCnt;
NS_LOG_ADDREF(this, mRefCnt, "nsTypedSelection", sizeof(*this));
return mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt)
nsTypedSelection::Release()
{
if (mFrameSelection) {
return mFrameSelection->Release();
}
NS_PRECONDITION(0 != mRefCnt, "dup release");
NS_ASSERT_OWNINGTHREAD(nsTypedSelection);
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "nsTypedSelection");
if (mRefCnt == 0) {
mRefCnt = 1; /* stabilize */
NS_DELETEXPCOM(this);
return 0;
}
return mRefCnt;
}
NS_IMETHODIMP
nsTypedSelection::SetPresShell(nsIPresShell *aPresShell)

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

@ -3485,10 +3485,11 @@ GetGeneratedContentOwner(nsIFrame* aFrame, PRBool* aIsBefore)
SelectionDetails*
nsTextFrame::GetSelectionDetails()
{
const nsFrameSelection* frameSelection = GetConstFrameSelection();
if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
SelectionDetails* details =
GetFrameSelection()->LookUpSelection(mContent, GetContentOffset(),
GetContentLength(), PR_FALSE);
frameSelection->LookUpSelection(mContent, GetContentOffset(),
GetContentLength(), PR_FALSE);
SelectionDetails* sd;
for (sd = details; sd; sd = sd->mNext) {
sd->mStart += mContentOffset;
@ -3505,7 +3506,7 @@ nsTextFrame::GetSelectionDetails()
return nsnull;
SelectionDetails* details =
GetFrameSelection()->LookUpSelection(owner->GetContent(),
frameSelection->LookUpSelection(owner->GetContent(),
isBefore ? 0 : owner->GetContent()->GetChildCount(), 0, PR_FALSE);
SelectionDetails* sd;
for (sd = details; sd; sd = sd->mNext) {

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

@ -98,8 +98,9 @@ nsMathMLmoFrame::IsFrameInSelection(nsIFrame* aFrame)
if (!isSelected)
return PR_FALSE;
SelectionDetails* details = aFrame->GetFrameSelection()->
LookUpSelection(aFrame->GetContent(), 0, 1, PR_TRUE);
const nsFrameSelection* frameSelection = aFrame->GetConstFrameSelection();
SelectionDetails* details =
frameSelection->LookUpSelection(aFrame->GetContent(), 0, 1, PR_TRUE);
if (!details)
return PR_FALSE;

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

@ -296,7 +296,8 @@ nsTableCellFrame::DecorateForSelection(nsIRenderingContext& aRenderingContext,
nsPresContext* presContext = PresContext();
displaySelection = DisplaySelection(presContext);
if (displaySelection) {
nsFrameSelection *frameSelection = presContext->PresShell()->FrameSelection();
nsCOMPtr<nsFrameSelection> frameSelection =
presContext->PresShell()->FrameSelection();
if (frameSelection->GetTableCellSelection()) {
nscolor bordercolor;
@ -492,7 +493,9 @@ nsTableCellFrame::SetSelected(nsPresContext* aPresContext,
// only this frame is considered
nsFrame::SetSelected(aPresContext, aRange, aSelected, aSpread);
if (aPresContext->PresShell()->FrameSelection()->GetTableCellSelection()) {
nsCOMPtr<nsFrameSelection> frameSelection =
aPresContext->PresShell()->FrameSelection();
if (frameSelection->GetTableCellSelection()) {
// Selection can affect content, border and outline
Invalidate(GetOverflowRect(), PR_FALSE);
}