diff --git a/mozilla/accessible/src/base/nsCaretAccessible.cpp b/mozilla/accessible/src/base/nsCaretAccessible.cpp index 7cd874e1542..11d981d64de 100644 --- a/mozilla/accessible/src/base/nsCaretAccessible.cpp +++ b/mozilla/accessible/src/base/nsCaretAccessible.cpp @@ -131,7 +131,7 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns nsRect caretRect; PRBool isCollapsed; - caret->GetCaretCoordinates(nsICaret::eTopLevelWindowCoordinates, domSel, &caretRect, &isCollapsed); + caret->GetCaretCoordinates(nsICaret::eTopLevelWindowCoordinates, domSel, &caretRect, &isCollapsed, nsnull); PRBool visible = (caretRect.x >= 0 && caretRect.y >= 0 && caretRect.width >= 0 && caretRect.height >= 0); if (visible) // Make sure it's visible both by looking at coordinates and visible flag caret->GetCaretVisible(&visible); diff --git a/mozilla/content/base/src/nsSelection.cpp b/mozilla/content/base/src/nsSelection.cpp index b4a84e92a3f..cc93bd96a69 100644 --- a/mozilla/content/base/src/nsSelection.cpp +++ b/mozilla/content/base/src/nsSelection.cpp @@ -364,6 +364,7 @@ public: NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous); NS_IMETHOD RepaintSelection(nsIPresContext* aPresContext, SelectionType aType); NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset); + NS_IMETHOD CommonPageMove(PRBool aForward, PRBool aExtend, nsIScrollableView *aScrollableView, nsIFrameSelection *aFrameSel); NS_IMETHOD AdjustOffsetsFromStyle(nsIFrame *aFrame, PRBool *changeSelection, nsIContent** outContent, PRInt32* outStartOffset, PRInt32* outEndOffset); @@ -974,7 +975,6 @@ nsSelection::nsSelection() mChangesDuringBatching = PR_FALSE; mNotifyFrames = PR_TRUE; mLimiter = nsnull; //no default limiter. - if (sInstanceCount <= 0) { sTableAtom = NS_NewAtom("table"); @@ -1115,7 +1115,7 @@ nsSelection::FetchDesiredX(nscoord &aDesiredX) //the x position requested by the if (NS_FAILED(result)) return result; - result = caret->GetCaretCoordinates(nsICaret::eClosestViewCoordinates, mDomSelections[index], &coord, &collapsed); + result = caret->GetCaretCoordinates(nsICaret::eClosestViewCoordinates, mDomSelections[index], &coord, &collapsed, nsnull); if (NS_FAILED(result)) return result; @@ -3094,6 +3094,132 @@ nsSelection::GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHin return result; } +NS_IMETHODIMP +nsSelection::CommonPageMove(PRBool aForward, + PRBool aExtend, + nsIScrollableView *aScrollableView, + nsIFrameSelection *aFrameSel) +{ + if ( !aScrollableView || !aFrameSel) + return NS_ERROR_NULL_POINTER; + // expected behavior for PageMove is to scroll AND move the caret + // and remain relative position of the caret in view. see Bug 4302. + + nsresult result; + const nsIView* clipView; + nsRect viewRect; + //get the frame from the scrollable view + + void* clientData; + nsIFrame* mainframe = nsnull; + + // The view's client data points back to its frame + nsIView *scrolledView; + result = aScrollableView->GetScrolledView(scrolledView); + + if (NS_FAILED(result)) + return result; + + if (scrolledView && NS_SUCCEEDED(scrolledView->GetClientData(clientData))) + mainframe = (nsIFrame*)clientData; + + if (!mainframe) + return NS_ERROR_FAILURE; + + // find out where we are; determine amount to page up/down + if (NS_FAILED(result = aScrollableView->GetClipView(&clipView))) + return result; + if (NS_FAILED(result = clipView->GetBounds(viewRect))) + return result; + + nsCOMPtr context; + result = mTracker->GetPresContext(getter_AddRefs(context)); + + if (NS_FAILED(result)) + return result; + + if (!context) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr shell; + result = context->GetShell(getter_AddRefs(shell)); + + if (NS_FAILED(result)) + return result; + + if (!shell) + return NS_ERROR_NULL_POINTER; + + // find out where the caret is. + // we should know mDesiredX value of nsSelection, but I havent seen that behavior in other windows applications yet. + nsCOMPtr domSel; + aFrameSel->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel)); + + if (!domSel) + return NS_ERROR_UNEXPECTED; + + nsCOMPtr caret; + nsRect caretPos; + PRBool isCollapsed; + result = shell->GetCaret(getter_AddRefs(caret)); + + if (NS_FAILED(result)) + return result; + + nsIView *caretView; + result = caret->GetCaretCoordinates(nsICaret::eClosestViewCoordinates, domSel, &caretPos, &isCollapsed, &caretView); + + if (NS_FAILED(result)) + return result; + + //need to adjust caret jump by percentage scroll + viewRect.height = (PRInt32) (viewRect.height * PAGE_SCROLL_PERCENT); + + if (aForward) + caretPos.y += viewRect.height; + else + caretPos.y -= viewRect.height; + + + if (caretView) + { + nscoord x,y; + while (caretView != scrolledView) + { + caretView->GetPosition(&x, &y); + caretPos.x += x; + caretPos.y += y; + caretView->GetParent(caretView); + if (!caretView) //how did we miss the scrolled view. something is very wrong + return NS_ERROR_FAILURE; + } + } + + // get a content at desired location + nsCOMPtr content; + PRInt32 startOffset, endOffset; + PRBool beginFrameContent; + nsPoint desiredPoint; + desiredPoint.x = caretPos.x; + desiredPoint.y = caretPos.y + caretPos.height/2; + result = mainframe->GetContentAndOffsetsFromPoint(context, desiredPoint, getter_AddRefs(content), startOffset, endOffset, beginFrameContent); + + if (NS_FAILED(result)) + return result; + + if (!content) + return NS_ERROR_UNEXPECTED; + + // scroll one page + + aScrollableView->ScrollByPages(aForward ? 1 : -1); + + // place the caret + result = aFrameSel->HandleClick(content, startOffset, startOffset, aExtend, PR_FALSE, PR_TRUE); + + return result; +} + NS_IMETHODIMP nsSelection::CharacterMove(PRBool aForward, PRBool aExtend) { @@ -4473,7 +4599,6 @@ nsSelection::GetLimiter(nsIContent **aLimiterContent) return NS_OK; } - //END nsISelection interface implementations #ifdef XP_MAC diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index 2a2efaa1031..c53c0882a8b 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -1862,7 +1862,7 @@ nsEditor::QueryComposition(nsTextEventReply* aReply) // XXX_kin: END HACK! HACK! HACK! result = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, selection, - &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed)); + &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed), nsnull); } } return result; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index 8e267fa2005..9be41d07364 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -3851,7 +3851,7 @@ nsHTMLEditor::SetCompositionString(const nsAString& aCompositionString, nsIPriva // XXX_kin: END HACK! HACK! HACK! result = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, selection, - &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed)); + &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed), nsnull); NS_ASSERTION(NS_SUCCEEDED(result), "cannot get caret position"); diff --git a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp index 7dbd2e386e5..e267287418c 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp @@ -1967,7 +1967,7 @@ nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsI // XXX_kin: END HACK! HACK! HACK! result = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, selection, - &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed)); + &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed), nsnull); NS_ASSERTION(NS_SUCCEEDED(result), "cannot get caret position"); return result; diff --git a/mozilla/layout/base/nsCaret.cpp b/mozilla/layout/base/nsCaret.cpp index a878e355bfb..01f772be008 100644 --- a/mozilla/layout/base/nsCaret.cpp +++ b/mozilla/layout/base/nsCaret.cpp @@ -244,7 +244,7 @@ NS_IMETHODIMP nsCaret::SetCaretReadOnly(PRBool inMakeReadonly) //----------------------------------------------------------------------------- -NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *aDOMSel, nsRect *outCoordinates, PRBool *outIsCollapsed) +NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *aDOMSel, nsRect *outCoordinates, PRBool *outIsCollapsed, nsIView **outView) { if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; @@ -257,6 +257,9 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI if (!domSelection) return NS_ERROR_NOT_INITIALIZED; // no selection + if (outView) + *outView = nsnull; + // fill in defaults for failure outCoordinates->x = -1; outCoordinates->y = -1; @@ -321,18 +324,10 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI nsRect clipRect; nsIView *drawingView; // views are not refcounted - //#59405, on windows and unix, the coordinate for IME need to be view (nearest native window) related. - if (aRelativeToType == eIMECoordinates) -#if defined(XP_MAC) || defined(XP_MACOSX) - aRelativeToType = eTopLevelWindowCoordinates; -#else - aRelativeToType = eRenderingViewCoordinates; -#endif - GetViewForRendering(theFrame, aRelativeToType, viewOffset, clipRect, drawingView); + GetViewForRendering(theFrame, aRelativeToType, viewOffset, clipRect, &drawingView, outView); if (!drawingView) return NS_ERROR_UNEXPECTED; - // ramp up to make a rendering context for measuring text. // First, we get the pres context ... nsCOMPtr presContext; @@ -365,8 +360,11 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI // we don't need drawingView anymore so reuse that; reset viewOffset values for our purposes if (aRelativeToType == eClosestViewCoordinates) + { theFrame->GetOffsetFromView(presContext, viewOffset, &drawingView); - + if (outView) + *outView = drawingView; + } // now add the frame offset to the view offset, and we're done viewOffset += framePos; outCoordinates->x = viewOffset.x; @@ -755,13 +753,24 @@ PRBool nsCaret::SetupDrawingFrameAndOffset() //----------------------------------------------------------------------------- -void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView* &outView) +void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView **outRenderingView, nsIView **outRelativeView) { - outView = nsnull; - - if (!caretFrame) + + if (!caretFrame || !outRenderingView) return; - + + //#59405, on windows and unix, the coordinate for IME need to be view (nearest native window) related. + if (coordType == eIMECoordinates) +#if defined(XP_MAC) || defined(XP_MACOSX) + coordType = eTopLevelWindowCoordinates; +#else + coordType = eRenderingViewCoordinates; +#endif + + *outRenderingView = nsnull; + if (outRelativeView) + *outRelativeView = nsnull; + NS_ASSERTION(caretFrame, "Should have frame here"); nsCOMPtr presShell = do_QueryReferent(mPresShell); if (!presShell) @@ -778,7 +787,10 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy nsIView* theView = nsnull; caretFrame->GetOffsetFromView(presContext, withinViewOffset, &theView); if (theView == nsnull) return; - + + if (outRelativeView && coordType == eClosestViewCoordinates) + *outRelativeView = theView; + nsIView* returnView = nsnull; // views are not refcounted nscoord x, y; @@ -831,7 +843,9 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy { returnView->GetBounds(outClipRect); } - + + if (outRelativeView) + *outRelativeView = returnView; } else { @@ -854,13 +868,16 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy viewOffset.x += x; viewOffset.y += y; + if (outRelativeView && coordType == eTopLevelWindowCoordinates) + *outRelativeView = theView; + theView->GetParent(theView); } while (theView); } - outView = returnView; + *outRenderingView = returnView; } @@ -932,7 +949,7 @@ void nsCaret::DrawCaret() nsPoint viewOffset(0, 0); nsRect clipRect; nsIView *drawingView; - GetViewForRendering(mLastCaretFrame, eRenderingViewCoordinates, viewOffset, clipRect, drawingView); + GetViewForRendering(mLastCaretFrame, eRenderingViewCoordinates, viewOffset, clipRect, &drawingView, nsnull); if (drawingView == nsnull) return; diff --git a/mozilla/layout/base/nsCaret.h b/mozilla/layout/base/nsCaret.h index 6c87dc3d1fa..dbd5489b46c 100644 --- a/mozilla/layout/base/nsCaret.h +++ b/mozilla/layout/base/nsCaret.h @@ -61,7 +61,7 @@ class nsCaret : public nsICaret, NS_IMETHOD GetCaretVisible(PRBool *outMakeVisible); NS_IMETHOD SetCaretVisible(PRBool intMakeVisible); NS_IMETHOD SetCaretReadOnly(PRBool inMakeReadonly); - NS_IMETHOD GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *inDOMSel, nsRect* outCoordinates, PRBool* outIsCollapsed); + NS_IMETHOD GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *inDOMSel, nsRect* outCoordinates, PRBool* outIsCollapsed, nsIView **outView); NS_IMETHOD ClearFrameRefs(nsIFrame* aFrame); NS_IMETHOD EraseCaret(); @@ -81,7 +81,7 @@ class nsCaret : public nsICaret, nsresult StartBlinking(); nsresult StopBlinking(); - void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView* &outView); + void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView **outRenderingView, nsIView **outRelativeView); PRBool SetupDrawingFrameAndOffset(); PRBool MustDrawCaret(); void DrawCaret(); diff --git a/mozilla/layout/base/nsICaret.h b/mozilla/layout/base/nsICaret.h index 9fe95791185..75abde623e4 100644 --- a/mozilla/layout/base/nsICaret.h +++ b/mozilla/layout/base/nsICaret.h @@ -93,7 +93,7 @@ public: * If the selection is not collapsed, this returns the location of the focus pos, * and false in outIsCollapsed. */ - NS_IMETHOD GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *aDOMSel, nsRect *outCoordinates, PRBool *outIsCollapsed) = 0; + NS_IMETHOD GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *aDOMSel, nsRect *outCoordinates, PRBool *outIsCollapsed, nsIView **outView) = 0; /** ClearFrameRefs * The caret stores a reference to the frame that the caret was last drawn in. diff --git a/mozilla/layout/base/nsIFrameSelection.h b/mozilla/layout/base/nsIFrameSelection.h index 3130a184285..d8fc2c450c1 100644 --- a/mozilla/layout/base/nsIFrameSelection.h +++ b/mozilla/layout/base/nsIFrameSelection.h @@ -331,6 +331,29 @@ public: */ NS_IMETHOD IntraLineMove(PRBool aForward, PRBool aExtend)=0; + /** + * Scrolling then moving caret placement code in common to text areas and + * content areas should be located in the implementer + * This method will accept the following parameters and perform the scroll + * and caret movement. It remains for the caller to call the final + * ScrollCaretIntoView if that called wants to be sure the caret is always + * visible. + * + * @param aForward if PR_TRUE, scroll forward if not scroll backward + * + * @param aExtend if PR_TRUE, extend selection to the new point + * + * @param aScrollableView the view that needs the scrolling + * + * @param aFrameSel the nsIFrameSelection of the caller. + * + * @return always NS_OK + */ + NS_IMETHOD CommonPageMove(PRBool aForward, + PRBool aExtend, + nsIScrollableView *aScrollableView, + nsIFrameSelection *aFrameSel)=0; + /** Select All will generally be called from the nsiselectioncontroller implementations. * it will select the whole doc */ diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 197bf4692fb..ec4d2d48abc 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -1031,9 +1031,10 @@ public: NS_IMETHOD EnablePrefStyleRules(PRBool aEnable, PRUint8 aPrefType=0xFF); NS_IMETHOD ArePrefStyleRulesEnabled(PRBool& aEnabled); + NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection); + NS_IMETHOD SetDisplaySelection(PRInt16 aToggle); NS_IMETHOD GetDisplaySelection(PRInt16 *aToggle); - NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection); NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous); NS_IMETHOD RepaintSelection(SelectionType aType); NS_IMETHOD GetFrameSelection(nsIFrameSelection** aSelection); @@ -1047,6 +1048,7 @@ public: NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame** aResult) const; NS_IMETHOD GetPrimaryFrameFor(nsIContent* aContent, nsIFrame** aPrimaryFrame) const; + NS_IMETHOD GetStyleContextFor(nsIFrame* aFrame, nsIStyleContext** aStyleContext) const; NS_IMETHOD GetLayoutObjectFor(nsIContent* aContent, @@ -1285,6 +1287,7 @@ protected: void PostReflowEvent(); PRBool AlreadyInQueue(nsHTMLReflowCommand* aReflowCommand, nsVoidArray& aQueue); + friend struct ReflowEvent; // utility to determine if we're in the middle of a drag @@ -3218,28 +3221,33 @@ PresShell::IntraLineMove(PRBool aForward, PRBool aExtend) return mSelection->IntraLineMove(aForward, aExtend); } + + NS_IMETHODIMP PresShell::PageMove(PRBool aForward, PRBool aExtend) { -#if 1 - return ScrollPage(aForward); -#else - + nsresult result; nsCOMPtr viewManager; - nsresult result = GetViewManager(getter_AddRefs(viewManager)); - if (NS_SUCCEEDED(result) && viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { - - } - } - return result; -#endif //0 + nsIScrollableView *scrollableView; + result = GetViewManager(getter_AddRefs(viewManager)); + if (NS_FAILED(result)) + return result; + if (!viewManager) + return NS_ERROR_UNEXPECTED; + result = viewManager->GetRootScrollableView(&scrollableView); + if (NS_FAILED(result)) + return result; + if (!scrollableView) + return NS_ERROR_UNEXPECTED; + nsIView *scrolledView; + result = scrollableView->GetScrolledView(scrolledView); + mSelection->CommonPageMove(aForward, aExtend, scrollableView, mSelection); + // do ScrollSelectionIntoView() + return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); } + + NS_IMETHODIMP PresShell::ScrollPage(PRBool aForward) { @@ -3334,93 +3342,66 @@ PresShell::CompleteScroll(PRBool aForward) NS_IMETHODIMP PresShell::CompleteMove(PRBool aForward, PRBool aExtend) { - nsCOMPtr document; - if (NS_FAILED(GetDocument(getter_AddRefs(document))) || !document) - return NS_ERROR_FAILURE; - - nsCOMPtrnodeList; - NS_NAMED_LITERAL_STRING(bodyTag, "body"); - - nsCOMPtr doc = do_QueryInterface(document); - if (!doc) - return NS_ERROR_FAILURE; - nsresult result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList)); - if (NS_FAILED(result) ||!nodeList) - return result?result:NS_ERROR_FAILURE; - - - PRUint32 count; - nodeList->GetLength(&count); - - if (count < 1) + nsIScrollableView *scrollableView; + if (!mViewManager) + return NS_ERROR_UNEXPECTED; + nsresult result = mViewManager->GetRootScrollableView(&scrollableView); + if (NS_FAILED(result)) + return result; + if (!scrollableView) + return NS_ERROR_UNEXPECTED; + nsIView *scrolledView; + result = scrollableView->GetScrolledView(scrolledView); + // get a frame + void *clientData; + scrolledView->GetClientData(clientData); + nsIFrame *frame = (nsIFrame *)clientData; + if (!frame) return NS_ERROR_FAILURE; - // Use the first body node in the list: - nsCOMPtr node; - result = nodeList->Item(0, getter_AddRefs(node)); - if (NS_SUCCEEDED(result) && node) + PRInt8 outsideLimit = -1;//search from beginning + nsPeekOffsetStruct pos; + pos.mAmount = eSelectLine; + pos.mTracker = this; + pos.mContentOffset = 0; + pos.mContentOffsetEnd = 0; + pos.mScrollViewStop = PR_FALSE;//dont stop on scrolled views. + if (aForward) { - //return node->QueryInterface(NS_GET_IID(nsIDOMElement), (void **)aBodyElement); - // Is above equivalent to this: - nsCOMPtr bodyElement = do_QueryInterface(node); - if (bodyElement) - { - nsCOMPtr bodyContent = do_QueryInterface(bodyElement); - if (bodyContent) - { - nsIFrame *frame = nsnull; - result = GetPrimaryFrameFor(bodyContent, &frame); - if (frame) - { - PRInt8 outsideLimit = -1;//search from beginning - nsPeekOffsetStruct pos; - pos.mAmount = eSelectLine; - pos.mTracker = this; - pos.mContentOffset = 0; - pos.mContentOffsetEnd = 0; - pos.mScrollViewStop = PR_FALSE;//dont stop on scrolled views. - if (aForward) - { - outsideLimit = 1;//search from end - nsRect rect; - frame->GetRect(rect); - pos.mDesiredX = rect.width * 2;//search way off to right of line - pos.mDirection = eDirPrevious; //seach backwards from the end - } - else - { - pos.mDesiredX = -1; //start before line - pos.mDirection = eDirNext; //search forwards from before beginning - } - - do - { - result = nsFrame::GetNextPrevLineFromeBlockFrame(mPresContext, - &pos, - frame, - 0, //irrelavent since we set outsidelimit - outsideLimit - ); - if (NS_COMFALSE == result) //NS_COMFALSE should ALSO break - break; - if (NS_OK != result || !pos.mResultFrame ) - return result?result:NS_ERROR_FAILURE; - nsCOMPtr newIt; - //check to see if this is ANOTHER blockframe inside the other one if so then call into its lines - result = pos.mResultFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(newIt)); - if (NS_SUCCEEDED(result) && newIt) - frame = pos.mResultFrame; - } - while (NS_SUCCEEDED(result));//end 'do' - - result = mSelection->HandleClick(pos.mResultContent ,pos.mContentOffset ,pos.mContentOffsetEnd ,aExtend, PR_FALSE, pos.mPreferLeft); - } - // if we got this far, attempt to scroll no matter what the above result is - CompleteScroll(aForward); - } - } + outsideLimit = 1;//search from end + nsRect rect; + frame->GetRect(rect); + pos.mDesiredX = rect.width * 2;//search way off to right of line + pos.mDirection = eDirPrevious; //seach backwards from the end } - return result; + else + { + pos.mDesiredX = -1; //start before line + pos.mDirection = eDirNext; //search forwards from before beginning + } + + do + { + result = nsFrame::GetNextPrevLineFromeBlockFrame(mPresContext, + &pos, + frame, + 0, //irrelavent since we set outsidelimit + outsideLimit + ); + if (NS_COMFALSE == result) //NS_COMFALSE should ALSO break + break; + if (NS_OK != result || !pos.mResultFrame ) + return result?result:NS_ERROR_FAILURE; + nsCOMPtr newIt; + //check to see if this is ANOTHER blockframe inside the other one if so then call into its lines + result = pos.mResultFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(newIt)); + if (NS_SUCCEEDED(result) && newIt) + frame = pos.mResultFrame; + } + while (NS_SUCCEEDED(result));//end 'do' + + mSelection->HandleClick(pos.mResultContent ,pos.mContentOffset ,pos.mContentOffsetEnd ,aExtend, PR_FALSE, pos.mPreferLeft); + return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); } NS_IMETHODIMP diff --git a/mozilla/layout/base/public/nsICaret.h b/mozilla/layout/base/public/nsICaret.h index 9fe95791185..75abde623e4 100644 --- a/mozilla/layout/base/public/nsICaret.h +++ b/mozilla/layout/base/public/nsICaret.h @@ -93,7 +93,7 @@ public: * If the selection is not collapsed, this returns the location of the focus pos, * and false in outIsCollapsed. */ - NS_IMETHOD GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *aDOMSel, nsRect *outCoordinates, PRBool *outIsCollapsed) = 0; + NS_IMETHOD GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *aDOMSel, nsRect *outCoordinates, PRBool *outIsCollapsed, nsIView **outView) = 0; /** ClearFrameRefs * The caret stores a reference to the frame that the caret was last drawn in. diff --git a/mozilla/layout/base/public/nsIFrameSelection.h b/mozilla/layout/base/public/nsIFrameSelection.h index 3130a184285..d8fc2c450c1 100644 --- a/mozilla/layout/base/public/nsIFrameSelection.h +++ b/mozilla/layout/base/public/nsIFrameSelection.h @@ -331,6 +331,29 @@ public: */ NS_IMETHOD IntraLineMove(PRBool aForward, PRBool aExtend)=0; + /** + * Scrolling then moving caret placement code in common to text areas and + * content areas should be located in the implementer + * This method will accept the following parameters and perform the scroll + * and caret movement. It remains for the caller to call the final + * ScrollCaretIntoView if that called wants to be sure the caret is always + * visible. + * + * @param aForward if PR_TRUE, scroll forward if not scroll backward + * + * @param aExtend if PR_TRUE, extend selection to the new point + * + * @param aScrollableView the view that needs the scrolling + * + * @param aFrameSel the nsIFrameSelection of the caller. + * + * @return always NS_OK + */ + NS_IMETHOD CommonPageMove(PRBool aForward, + PRBool aExtend, + nsIScrollableView *aScrollableView, + nsIFrameSelection *aFrameSel)=0; + /** Select All will generally be called from the nsiselectioncontroller implementations. * it will select the whole doc */ diff --git a/mozilla/layout/base/src/nsCaret.cpp b/mozilla/layout/base/src/nsCaret.cpp index a878e355bfb..01f772be008 100644 --- a/mozilla/layout/base/src/nsCaret.cpp +++ b/mozilla/layout/base/src/nsCaret.cpp @@ -244,7 +244,7 @@ NS_IMETHODIMP nsCaret::SetCaretReadOnly(PRBool inMakeReadonly) //----------------------------------------------------------------------------- -NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *aDOMSel, nsRect *outCoordinates, PRBool *outIsCollapsed) +NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *aDOMSel, nsRect *outCoordinates, PRBool *outIsCollapsed, nsIView **outView) { if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; @@ -257,6 +257,9 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI if (!domSelection) return NS_ERROR_NOT_INITIALIZED; // no selection + if (outView) + *outView = nsnull; + // fill in defaults for failure outCoordinates->x = -1; outCoordinates->y = -1; @@ -321,18 +324,10 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI nsRect clipRect; nsIView *drawingView; // views are not refcounted - //#59405, on windows and unix, the coordinate for IME need to be view (nearest native window) related. - if (aRelativeToType == eIMECoordinates) -#if defined(XP_MAC) || defined(XP_MACOSX) - aRelativeToType = eTopLevelWindowCoordinates; -#else - aRelativeToType = eRenderingViewCoordinates; -#endif - GetViewForRendering(theFrame, aRelativeToType, viewOffset, clipRect, drawingView); + GetViewForRendering(theFrame, aRelativeToType, viewOffset, clipRect, &drawingView, outView); if (!drawingView) return NS_ERROR_UNEXPECTED; - // ramp up to make a rendering context for measuring text. // First, we get the pres context ... nsCOMPtr presContext; @@ -365,8 +360,11 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, nsI // we don't need drawingView anymore so reuse that; reset viewOffset values for our purposes if (aRelativeToType == eClosestViewCoordinates) + { theFrame->GetOffsetFromView(presContext, viewOffset, &drawingView); - + if (outView) + *outView = drawingView; + } // now add the frame offset to the view offset, and we're done viewOffset += framePos; outCoordinates->x = viewOffset.x; @@ -755,13 +753,24 @@ PRBool nsCaret::SetupDrawingFrameAndOffset() //----------------------------------------------------------------------------- -void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView* &outView) +void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView **outRenderingView, nsIView **outRelativeView) { - outView = nsnull; - - if (!caretFrame) + + if (!caretFrame || !outRenderingView) return; - + + //#59405, on windows and unix, the coordinate for IME need to be view (nearest native window) related. + if (coordType == eIMECoordinates) +#if defined(XP_MAC) || defined(XP_MACOSX) + coordType = eTopLevelWindowCoordinates; +#else + coordType = eRenderingViewCoordinates; +#endif + + *outRenderingView = nsnull; + if (outRelativeView) + *outRelativeView = nsnull; + NS_ASSERTION(caretFrame, "Should have frame here"); nsCOMPtr presShell = do_QueryReferent(mPresShell); if (!presShell) @@ -778,7 +787,10 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy nsIView* theView = nsnull; caretFrame->GetOffsetFromView(presContext, withinViewOffset, &theView); if (theView == nsnull) return; - + + if (outRelativeView && coordType == eClosestViewCoordinates) + *outRelativeView = theView; + nsIView* returnView = nsnull; // views are not refcounted nscoord x, y; @@ -831,7 +843,9 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy { returnView->GetBounds(outClipRect); } - + + if (outRelativeView) + *outRelativeView = returnView; } else { @@ -854,13 +868,16 @@ void nsCaret::GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordTy viewOffset.x += x; viewOffset.y += y; + if (outRelativeView && coordType == eTopLevelWindowCoordinates) + *outRelativeView = theView; + theView->GetParent(theView); } while (theView); } - outView = returnView; + *outRenderingView = returnView; } @@ -932,7 +949,7 @@ void nsCaret::DrawCaret() nsPoint viewOffset(0, 0); nsRect clipRect; nsIView *drawingView; - GetViewForRendering(mLastCaretFrame, eRenderingViewCoordinates, viewOffset, clipRect, drawingView); + GetViewForRendering(mLastCaretFrame, eRenderingViewCoordinates, viewOffset, clipRect, &drawingView, nsnull); if (drawingView == nsnull) return; diff --git a/mozilla/layout/base/src/nsCaret.h b/mozilla/layout/base/src/nsCaret.h index 6c87dc3d1fa..dbd5489b46c 100644 --- a/mozilla/layout/base/src/nsCaret.h +++ b/mozilla/layout/base/src/nsCaret.h @@ -61,7 +61,7 @@ class nsCaret : public nsICaret, NS_IMETHOD GetCaretVisible(PRBool *outMakeVisible); NS_IMETHOD SetCaretVisible(PRBool intMakeVisible); NS_IMETHOD SetCaretReadOnly(PRBool inMakeReadonly); - NS_IMETHOD GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *inDOMSel, nsRect* outCoordinates, PRBool* outIsCollapsed); + NS_IMETHOD GetCaretCoordinates(EViewCoordinates aRelativeToType, nsISelection *inDOMSel, nsRect* outCoordinates, PRBool* outIsCollapsed, nsIView **outView); NS_IMETHOD ClearFrameRefs(nsIFrame* aFrame); NS_IMETHOD EraseCaret(); @@ -81,7 +81,7 @@ class nsCaret : public nsICaret, nsresult StartBlinking(); nsresult StopBlinking(); - void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView* &outView); + void GetViewForRendering(nsIFrame *caretFrame, EViewCoordinates coordType, nsPoint &viewOffset, nsRect& outClipRect, nsIView **outRenderingView, nsIView **outRelativeView); PRBool SetupDrawingFrameAndOffset(); PRBool MustDrawCaret(); void DrawCaret(); diff --git a/mozilla/layout/forms/nsTextControlFrame.cpp b/mozilla/layout/forms/nsTextControlFrame.cpp index 561328f5eff..bde5b2b4977 100644 --- a/mozilla/layout/forms/nsTextControlFrame.cpp +++ b/mozilla/layout/forms/nsTextControlFrame.cpp @@ -623,6 +623,7 @@ public: NS_IMETHOD SetHint(nsIFrameSelection::HINT aHint); NS_IMETHOD SetScrollableView(nsIScrollableView *aScrollableView); NS_IMETHOD GetScrollableView(nsIScrollableView **aScrollableView); + NS_IMETHOD CommonPageMove(PRBool aForward, PRBool aExtend, nsIScrollableView *aScrollableView, nsIFrameSelection *aFrameSel); #ifdef IBMBIDI NS_IMETHOD GetPrevNextBidiLevels(nsIPresContext *aPresContext, nsIContent *aNode, @@ -872,58 +873,24 @@ nsTextInputSelectionImpl::IntraLineMove(PRBool aForward, PRBool aExtend) NS_IMETHODIMP nsTextInputSelectionImpl::PageMove(PRBool aForward, PRBool aExtend) { -#if XXXXX_WORK_TO_BE_COMPLETED_XXXXX - // XXX: this code needs to be finished or rewritten - // expected bahavior for PageMove is to scroll AND move the caret - nsIScrollableView *scrollableView; - nsresult result; - nscoord containerHeight, containerWidth, lineHeight; - nsPoint oldLocation; + // expected behavior for PageMove is to scroll AND move the caret + // and to remain relative position of the caret in view. see Bug 4302. - result = GetScrollableView(&scrollableView); - if (NS_FAILED(result)) - return result; - if (!scrollableView) - return NS_ERROR_NOT_INITIALIZED; - - // find out where we are; determine amount to page up/down - result = scrollableView->GetScrollPosition(oldLocation.x, oldLocation.y); - if (NS_FAILED(result)) - return result; - - result = scrollableView->GetLineHeight(&lineHeight); - if (NS_FAILED(result)) - return result; - - result = scrollableView->GetContainerSize(&containerWidth, &containerHeight); - if (NS_SUCCEEDED(result)) + if (mPresShellWeak) { - // scroll this amount backwards - if (!aForward) - containerHeight = 0 - containerHeight; + nsCOMPtr presShell = do_QueryReferent(mPresShellWeak); + if (!presShell) + return NS_ERROR_NULL_POINTER; - nsPoint desiredLocation(oldLocation.x, oldLocation.y + containerHeight - lineHeight); - result = scrollableView->ScrollTo(desiredLocation.x, desiredLocation.y, NS_VMREFRESH_NO_SYNC); - - // grab the parent / root DIV for this text widget - nsCOMPtr parentDIV; - result = GetLimiter(getter_AddRefs(parentDIV)); + //get the scroll view + nsIScrollableView *scrollableView; + nsresult result = GetScrollableView(&scrollableView); if (NS_FAILED(result)) return result; - if (!parentDIV) - return NS_ERROR_UNEXPECTED; - // now we know how much to move up/down, we need to look into the content and - // figure out where that coordinate is and then place the caret at that location - nsCOMPtr content; - result = frame->GetContentAndOffsetsFromPoint(presContext, desiredLocation, getter_AddRefs(content), startOffset, endOffset, beginFrameContent); - result = GetFrameForNodeOffset(content, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset) + CommonPageMove(aForward, aExtend, scrollableView, this); } - - return result; -#else - return ScrollPage(aForward); -#endif + return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, true); } NS_IMETHODIMP @@ -1223,6 +1190,13 @@ NS_IMETHODIMP nsTextInputSelectionImpl::GetScrollableView(nsIScrollableView **aS return NS_ERROR_FAILURE; } +NS_IMETHODIMP nsTextInputSelectionImpl::CommonPageMove(PRBool aForward, PRBool aExtend, nsIScrollableView *aScrollableView, nsIFrameSelection *aFrameSel) +{ + if(mFrameSelection) + return mFrameSelection->CommonPageMove(aForward, aExtend, aScrollableView, this); + return NS_ERROR_FAILURE; +} + #ifdef IBMBIDI NS_IMETHODIMP nsTextInputSelectionImpl::GetPrevNextBidiLevels(nsIPresContext *aPresContext, nsIContent *aNode, diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index f8a62e00cff..bb06674ab51 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -3590,6 +3590,33 @@ nsFrame::PeekOffset(nsIPresContext* aPresContext, nsPeekOffsetStruct *aPos) { return ((result) ? result : NS_ERROR_FAILURE); } + + nsFrameState state; + thisBlock->GetFrameState(&state); + + if (state & NS_FRAME_OUT_OF_FLOW) + { + //if we are searching for a frame that is not in flow we will not find it. + //we must instead look for its placeholder + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + + if (presShell) + { + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager) + { + result = frameManager->GetPlaceholderFrameFor(thisBlock, &thisBlock); + if (!thisBlock) + return NS_ERROR_FAILURE; + if (NS_FAILED(result)) + return result; + } + } + } + result = iter->FindLineContaining(thisBlock, &thisLine); if (NS_FAILED(result)) diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index fef9f03efd8..65b18d17a1d 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -626,8 +626,29 @@ nsGfxScrollFrame::GetContentAndOffsetsFromPoint(nsIPresContext* aCX, nsIFrame* frame = nsnull; mInner->mScrollAreaBox->GetFrame(&frame); + nsIView *view; + nsPoint point(aPoint); + nsPoint currentPoint; + //we need to translate the coordinates to the inner + nsresult result = GetClosestViewForFrame(aCX, this, &view); + if (NS_FAILED(result)) + return result; + if (!view) + return NS_ERROR_FAILURE; - return frame->GetContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); + nsIView *innerView; + result = GetClosestViewForFrame(aCX, frame, &innerView); + if (NS_FAILED(result)) + return result; + while (view != innerView && innerView) + { + innerView->GetPosition(¤tPoint.x, ¤tPoint.y); + point.x -= currentPoint.x; + point.y -= currentPoint.y; + innerView->GetParent(innerView); + } + + return frame->GetContentAndOffsetsFromPoint(aCX, point, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); } PRIntn diff --git a/mozilla/layout/generic/nsSelection.cpp b/mozilla/layout/generic/nsSelection.cpp index b4a84e92a3f..cc93bd96a69 100644 --- a/mozilla/layout/generic/nsSelection.cpp +++ b/mozilla/layout/generic/nsSelection.cpp @@ -364,6 +364,7 @@ public: NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous); NS_IMETHOD RepaintSelection(nsIPresContext* aPresContext, SelectionType aType); NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset); + NS_IMETHOD CommonPageMove(PRBool aForward, PRBool aExtend, nsIScrollableView *aScrollableView, nsIFrameSelection *aFrameSel); NS_IMETHOD AdjustOffsetsFromStyle(nsIFrame *aFrame, PRBool *changeSelection, nsIContent** outContent, PRInt32* outStartOffset, PRInt32* outEndOffset); @@ -974,7 +975,6 @@ nsSelection::nsSelection() mChangesDuringBatching = PR_FALSE; mNotifyFrames = PR_TRUE; mLimiter = nsnull; //no default limiter. - if (sInstanceCount <= 0) { sTableAtom = NS_NewAtom("table"); @@ -1115,7 +1115,7 @@ nsSelection::FetchDesiredX(nscoord &aDesiredX) //the x position requested by the if (NS_FAILED(result)) return result; - result = caret->GetCaretCoordinates(nsICaret::eClosestViewCoordinates, mDomSelections[index], &coord, &collapsed); + result = caret->GetCaretCoordinates(nsICaret::eClosestViewCoordinates, mDomSelections[index], &coord, &collapsed, nsnull); if (NS_FAILED(result)) return result; @@ -3094,6 +3094,132 @@ nsSelection::GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHin return result; } +NS_IMETHODIMP +nsSelection::CommonPageMove(PRBool aForward, + PRBool aExtend, + nsIScrollableView *aScrollableView, + nsIFrameSelection *aFrameSel) +{ + if ( !aScrollableView || !aFrameSel) + return NS_ERROR_NULL_POINTER; + // expected behavior for PageMove is to scroll AND move the caret + // and remain relative position of the caret in view. see Bug 4302. + + nsresult result; + const nsIView* clipView; + nsRect viewRect; + //get the frame from the scrollable view + + void* clientData; + nsIFrame* mainframe = nsnull; + + // The view's client data points back to its frame + nsIView *scrolledView; + result = aScrollableView->GetScrolledView(scrolledView); + + if (NS_FAILED(result)) + return result; + + if (scrolledView && NS_SUCCEEDED(scrolledView->GetClientData(clientData))) + mainframe = (nsIFrame*)clientData; + + if (!mainframe) + return NS_ERROR_FAILURE; + + // find out where we are; determine amount to page up/down + if (NS_FAILED(result = aScrollableView->GetClipView(&clipView))) + return result; + if (NS_FAILED(result = clipView->GetBounds(viewRect))) + return result; + + nsCOMPtr context; + result = mTracker->GetPresContext(getter_AddRefs(context)); + + if (NS_FAILED(result)) + return result; + + if (!context) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr shell; + result = context->GetShell(getter_AddRefs(shell)); + + if (NS_FAILED(result)) + return result; + + if (!shell) + return NS_ERROR_NULL_POINTER; + + // find out where the caret is. + // we should know mDesiredX value of nsSelection, but I havent seen that behavior in other windows applications yet. + nsCOMPtr domSel; + aFrameSel->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel)); + + if (!domSel) + return NS_ERROR_UNEXPECTED; + + nsCOMPtr caret; + nsRect caretPos; + PRBool isCollapsed; + result = shell->GetCaret(getter_AddRefs(caret)); + + if (NS_FAILED(result)) + return result; + + nsIView *caretView; + result = caret->GetCaretCoordinates(nsICaret::eClosestViewCoordinates, domSel, &caretPos, &isCollapsed, &caretView); + + if (NS_FAILED(result)) + return result; + + //need to adjust caret jump by percentage scroll + viewRect.height = (PRInt32) (viewRect.height * PAGE_SCROLL_PERCENT); + + if (aForward) + caretPos.y += viewRect.height; + else + caretPos.y -= viewRect.height; + + + if (caretView) + { + nscoord x,y; + while (caretView != scrolledView) + { + caretView->GetPosition(&x, &y); + caretPos.x += x; + caretPos.y += y; + caretView->GetParent(caretView); + if (!caretView) //how did we miss the scrolled view. something is very wrong + return NS_ERROR_FAILURE; + } + } + + // get a content at desired location + nsCOMPtr content; + PRInt32 startOffset, endOffset; + PRBool beginFrameContent; + nsPoint desiredPoint; + desiredPoint.x = caretPos.x; + desiredPoint.y = caretPos.y + caretPos.height/2; + result = mainframe->GetContentAndOffsetsFromPoint(context, desiredPoint, getter_AddRefs(content), startOffset, endOffset, beginFrameContent); + + if (NS_FAILED(result)) + return result; + + if (!content) + return NS_ERROR_UNEXPECTED; + + // scroll one page + + aScrollableView->ScrollByPages(aForward ? 1 : -1); + + // place the caret + result = aFrameSel->HandleClick(content, startOffset, startOffset, aExtend, PR_FALSE, PR_TRUE); + + return result; +} + NS_IMETHODIMP nsSelection::CharacterMove(PRBool aForward, PRBool aExtend) { @@ -4473,7 +4599,6 @@ nsSelection::GetLimiter(nsIContent **aLimiterContent) return NS_OK; } - //END nsISelection interface implementations #ifdef XP_MAC diff --git a/mozilla/layout/html/base/src/nsFrame.cpp b/mozilla/layout/html/base/src/nsFrame.cpp index f8a62e00cff..bb06674ab51 100644 --- a/mozilla/layout/html/base/src/nsFrame.cpp +++ b/mozilla/layout/html/base/src/nsFrame.cpp @@ -3590,6 +3590,33 @@ nsFrame::PeekOffset(nsIPresContext* aPresContext, nsPeekOffsetStruct *aPos) { return ((result) ? result : NS_ERROR_FAILURE); } + + nsFrameState state; + thisBlock->GetFrameState(&state); + + if (state & NS_FRAME_OUT_OF_FLOW) + { + //if we are searching for a frame that is not in flow we will not find it. + //we must instead look for its placeholder + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + + if (presShell) + { + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager) + { + result = frameManager->GetPlaceholderFrameFor(thisBlock, &thisBlock); + if (!thisBlock) + return NS_ERROR_FAILURE; + if (NS_FAILED(result)) + return result; + } + } + } + result = iter->FindLineContaining(thisBlock, &thisLine); if (NS_FAILED(result)) diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp index fef9f03efd8..65b18d17a1d 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp @@ -626,8 +626,29 @@ nsGfxScrollFrame::GetContentAndOffsetsFromPoint(nsIPresContext* aCX, nsIFrame* frame = nsnull; mInner->mScrollAreaBox->GetFrame(&frame); + nsIView *view; + nsPoint point(aPoint); + nsPoint currentPoint; + //we need to translate the coordinates to the inner + nsresult result = GetClosestViewForFrame(aCX, this, &view); + if (NS_FAILED(result)) + return result; + if (!view) + return NS_ERROR_FAILURE; - return frame->GetContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); + nsIView *innerView; + result = GetClosestViewForFrame(aCX, frame, &innerView); + if (NS_FAILED(result)) + return result; + while (view != innerView && innerView) + { + innerView->GetPosition(¤tPoint.x, ¤tPoint.y); + point.x -= currentPoint.x; + point.y -= currentPoint.y; + innerView->GetParent(innerView); + } + + return frame->GetContentAndOffsetsFromPoint(aCX, point, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); } PRIntn diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 197bf4692fb..ec4d2d48abc 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -1031,9 +1031,10 @@ public: NS_IMETHOD EnablePrefStyleRules(PRBool aEnable, PRUint8 aPrefType=0xFF); NS_IMETHOD ArePrefStyleRulesEnabled(PRBool& aEnabled); + NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection); + NS_IMETHOD SetDisplaySelection(PRInt16 aToggle); NS_IMETHOD GetDisplaySelection(PRInt16 *aToggle); - NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection); NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous); NS_IMETHOD RepaintSelection(SelectionType aType); NS_IMETHOD GetFrameSelection(nsIFrameSelection** aSelection); @@ -1047,6 +1048,7 @@ public: NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame** aResult) const; NS_IMETHOD GetPrimaryFrameFor(nsIContent* aContent, nsIFrame** aPrimaryFrame) const; + NS_IMETHOD GetStyleContextFor(nsIFrame* aFrame, nsIStyleContext** aStyleContext) const; NS_IMETHOD GetLayoutObjectFor(nsIContent* aContent, @@ -1285,6 +1287,7 @@ protected: void PostReflowEvent(); PRBool AlreadyInQueue(nsHTMLReflowCommand* aReflowCommand, nsVoidArray& aQueue); + friend struct ReflowEvent; // utility to determine if we're in the middle of a drag @@ -3218,28 +3221,33 @@ PresShell::IntraLineMove(PRBool aForward, PRBool aExtend) return mSelection->IntraLineMove(aForward, aExtend); } + + NS_IMETHODIMP PresShell::PageMove(PRBool aForward, PRBool aExtend) { -#if 1 - return ScrollPage(aForward); -#else - + nsresult result; nsCOMPtr viewManager; - nsresult result = GetViewManager(getter_AddRefs(viewManager)); - if (NS_SUCCEEDED(result) && viewManager) - { - nsIScrollableView *scrollView; - result = viewManager->GetRootScrollableView(&scrollView); - if (NS_SUCCEEDED(result) && scrollView) - { - - } - } - return result; -#endif //0 + nsIScrollableView *scrollableView; + result = GetViewManager(getter_AddRefs(viewManager)); + if (NS_FAILED(result)) + return result; + if (!viewManager) + return NS_ERROR_UNEXPECTED; + result = viewManager->GetRootScrollableView(&scrollableView); + if (NS_FAILED(result)) + return result; + if (!scrollableView) + return NS_ERROR_UNEXPECTED; + nsIView *scrolledView; + result = scrollableView->GetScrolledView(scrolledView); + mSelection->CommonPageMove(aForward, aExtend, scrollableView, mSelection); + // do ScrollSelectionIntoView() + return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); } + + NS_IMETHODIMP PresShell::ScrollPage(PRBool aForward) { @@ -3334,93 +3342,66 @@ PresShell::CompleteScroll(PRBool aForward) NS_IMETHODIMP PresShell::CompleteMove(PRBool aForward, PRBool aExtend) { - nsCOMPtr document; - if (NS_FAILED(GetDocument(getter_AddRefs(document))) || !document) - return NS_ERROR_FAILURE; - - nsCOMPtrnodeList; - NS_NAMED_LITERAL_STRING(bodyTag, "body"); - - nsCOMPtr doc = do_QueryInterface(document); - if (!doc) - return NS_ERROR_FAILURE; - nsresult result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList)); - if (NS_FAILED(result) ||!nodeList) - return result?result:NS_ERROR_FAILURE; - - - PRUint32 count; - nodeList->GetLength(&count); - - if (count < 1) + nsIScrollableView *scrollableView; + if (!mViewManager) + return NS_ERROR_UNEXPECTED; + nsresult result = mViewManager->GetRootScrollableView(&scrollableView); + if (NS_FAILED(result)) + return result; + if (!scrollableView) + return NS_ERROR_UNEXPECTED; + nsIView *scrolledView; + result = scrollableView->GetScrolledView(scrolledView); + // get a frame + void *clientData; + scrolledView->GetClientData(clientData); + nsIFrame *frame = (nsIFrame *)clientData; + if (!frame) return NS_ERROR_FAILURE; - // Use the first body node in the list: - nsCOMPtr node; - result = nodeList->Item(0, getter_AddRefs(node)); - if (NS_SUCCEEDED(result) && node) + PRInt8 outsideLimit = -1;//search from beginning + nsPeekOffsetStruct pos; + pos.mAmount = eSelectLine; + pos.mTracker = this; + pos.mContentOffset = 0; + pos.mContentOffsetEnd = 0; + pos.mScrollViewStop = PR_FALSE;//dont stop on scrolled views. + if (aForward) { - //return node->QueryInterface(NS_GET_IID(nsIDOMElement), (void **)aBodyElement); - // Is above equivalent to this: - nsCOMPtr bodyElement = do_QueryInterface(node); - if (bodyElement) - { - nsCOMPtr bodyContent = do_QueryInterface(bodyElement); - if (bodyContent) - { - nsIFrame *frame = nsnull; - result = GetPrimaryFrameFor(bodyContent, &frame); - if (frame) - { - PRInt8 outsideLimit = -1;//search from beginning - nsPeekOffsetStruct pos; - pos.mAmount = eSelectLine; - pos.mTracker = this; - pos.mContentOffset = 0; - pos.mContentOffsetEnd = 0; - pos.mScrollViewStop = PR_FALSE;//dont stop on scrolled views. - if (aForward) - { - outsideLimit = 1;//search from end - nsRect rect; - frame->GetRect(rect); - pos.mDesiredX = rect.width * 2;//search way off to right of line - pos.mDirection = eDirPrevious; //seach backwards from the end - } - else - { - pos.mDesiredX = -1; //start before line - pos.mDirection = eDirNext; //search forwards from before beginning - } - - do - { - result = nsFrame::GetNextPrevLineFromeBlockFrame(mPresContext, - &pos, - frame, - 0, //irrelavent since we set outsidelimit - outsideLimit - ); - if (NS_COMFALSE == result) //NS_COMFALSE should ALSO break - break; - if (NS_OK != result || !pos.mResultFrame ) - return result?result:NS_ERROR_FAILURE; - nsCOMPtr newIt; - //check to see if this is ANOTHER blockframe inside the other one if so then call into its lines - result = pos.mResultFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(newIt)); - if (NS_SUCCEEDED(result) && newIt) - frame = pos.mResultFrame; - } - while (NS_SUCCEEDED(result));//end 'do' - - result = mSelection->HandleClick(pos.mResultContent ,pos.mContentOffset ,pos.mContentOffsetEnd ,aExtend, PR_FALSE, pos.mPreferLeft); - } - // if we got this far, attempt to scroll no matter what the above result is - CompleteScroll(aForward); - } - } + outsideLimit = 1;//search from end + nsRect rect; + frame->GetRect(rect); + pos.mDesiredX = rect.width * 2;//search way off to right of line + pos.mDirection = eDirPrevious; //seach backwards from the end } - return result; + else + { + pos.mDesiredX = -1; //start before line + pos.mDirection = eDirNext; //search forwards from before beginning + } + + do + { + result = nsFrame::GetNextPrevLineFromeBlockFrame(mPresContext, + &pos, + frame, + 0, //irrelavent since we set outsidelimit + outsideLimit + ); + if (NS_COMFALSE == result) //NS_COMFALSE should ALSO break + break; + if (NS_OK != result || !pos.mResultFrame ) + return result?result:NS_ERROR_FAILURE; + nsCOMPtr newIt; + //check to see if this is ANOTHER blockframe inside the other one if so then call into its lines + result = pos.mResultFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(newIt)); + if (NS_SUCCEEDED(result) && newIt) + frame = pos.mResultFrame; + } + while (NS_SUCCEEDED(result));//end 'do' + + mSelection->HandleClick(pos.mResultContent ,pos.mContentOffset ,pos.mContentOffsetEnd ,aExtend, PR_FALSE, pos.mPreferLeft); + return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE); } NS_IMETHODIMP diff --git a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp index 561328f5eff..bde5b2b4977 100644 --- a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp @@ -623,6 +623,7 @@ public: NS_IMETHOD SetHint(nsIFrameSelection::HINT aHint); NS_IMETHOD SetScrollableView(nsIScrollableView *aScrollableView); NS_IMETHOD GetScrollableView(nsIScrollableView **aScrollableView); + NS_IMETHOD CommonPageMove(PRBool aForward, PRBool aExtend, nsIScrollableView *aScrollableView, nsIFrameSelection *aFrameSel); #ifdef IBMBIDI NS_IMETHOD GetPrevNextBidiLevels(nsIPresContext *aPresContext, nsIContent *aNode, @@ -872,58 +873,24 @@ nsTextInputSelectionImpl::IntraLineMove(PRBool aForward, PRBool aExtend) NS_IMETHODIMP nsTextInputSelectionImpl::PageMove(PRBool aForward, PRBool aExtend) { -#if XXXXX_WORK_TO_BE_COMPLETED_XXXXX - // XXX: this code needs to be finished or rewritten - // expected bahavior for PageMove is to scroll AND move the caret - nsIScrollableView *scrollableView; - nsresult result; - nscoord containerHeight, containerWidth, lineHeight; - nsPoint oldLocation; + // expected behavior for PageMove is to scroll AND move the caret + // and to remain relative position of the caret in view. see Bug 4302. - result = GetScrollableView(&scrollableView); - if (NS_FAILED(result)) - return result; - if (!scrollableView) - return NS_ERROR_NOT_INITIALIZED; - - // find out where we are; determine amount to page up/down - result = scrollableView->GetScrollPosition(oldLocation.x, oldLocation.y); - if (NS_FAILED(result)) - return result; - - result = scrollableView->GetLineHeight(&lineHeight); - if (NS_FAILED(result)) - return result; - - result = scrollableView->GetContainerSize(&containerWidth, &containerHeight); - if (NS_SUCCEEDED(result)) + if (mPresShellWeak) { - // scroll this amount backwards - if (!aForward) - containerHeight = 0 - containerHeight; + nsCOMPtr presShell = do_QueryReferent(mPresShellWeak); + if (!presShell) + return NS_ERROR_NULL_POINTER; - nsPoint desiredLocation(oldLocation.x, oldLocation.y + containerHeight - lineHeight); - result = scrollableView->ScrollTo(desiredLocation.x, desiredLocation.y, NS_VMREFRESH_NO_SYNC); - - // grab the parent / root DIV for this text widget - nsCOMPtr parentDIV; - result = GetLimiter(getter_AddRefs(parentDIV)); + //get the scroll view + nsIScrollableView *scrollableView; + nsresult result = GetScrollableView(&scrollableView); if (NS_FAILED(result)) return result; - if (!parentDIV) - return NS_ERROR_UNEXPECTED; - // now we know how much to move up/down, we need to look into the content and - // figure out where that coordinate is and then place the caret at that location - nsCOMPtr content; - result = frame->GetContentAndOffsetsFromPoint(presContext, desiredLocation, getter_AddRefs(content), startOffset, endOffset, beginFrameContent); - result = GetFrameForNodeOffset(content, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset) + CommonPageMove(aForward, aExtend, scrollableView, this); } - - return result; -#else - return ScrollPage(aForward); -#endif + return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, true); } NS_IMETHODIMP @@ -1223,6 +1190,13 @@ NS_IMETHODIMP nsTextInputSelectionImpl::GetScrollableView(nsIScrollableView **aS return NS_ERROR_FAILURE; } +NS_IMETHODIMP nsTextInputSelectionImpl::CommonPageMove(PRBool aForward, PRBool aExtend, nsIScrollableView *aScrollableView, nsIFrameSelection *aFrameSel) +{ + if(mFrameSelection) + return mFrameSelection->CommonPageMove(aForward, aExtend, aScrollableView, this); + return NS_ERROR_FAILURE; +} + #ifdef IBMBIDI NS_IMETHODIMP nsTextInputSelectionImpl::GetPrevNextBidiLevels(nsIPresContext *aPresContext, nsIContent *aNode,