diff --git a/accessible/generic/HyperTextAccessible.cpp b/accessible/generic/HyperTextAccessible.cpp index c77be0cc81e1..5e8718e432bb 100644 --- a/accessible/generic/HyperTextAccessible.cpp +++ b/accessible/generic/HyperTextAccessible.cpp @@ -508,7 +508,7 @@ HyperTextAccessible::FindOffset(uint32_t aOffset, nsDirection aDirection, const bool kIsKeyboardSelect = true; // is keyboard selection const bool kIsVisualBidi = false; // use visual order for bidi text nsPeekOffsetStruct pos(aAmount, aDirection, innerContentOffset, - 0, kIsJumpLinesOk, kIsScrollViewAStop, + nsPoint(0, 0), kIsJumpLinesOk, kIsScrollViewAStop, kIsKeyboardSelect, kIsVisualBidi, aWordMovementType); nsresult rv = frameAtOffset->PeekOffset(&pos); diff --git a/layout/base/SelectionCarets.cpp b/layout/base/SelectionCarets.cpp index 8e640550e220..c4a21011c6e4 100644 --- a/layout/base/SelectionCarets.cpp +++ b/layout/base/SelectionCarets.cpp @@ -635,7 +635,7 @@ CompareRangeWithContentOffset(nsRange* aRange, nsPeekOffsetStruct pos(eSelectCluster, dir, offset, - 0, + nsPoint(0, 0), true, true, //limit on scrolled views false, diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index 5d2d30609ef0..3a596d942650 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -700,7 +700,9 @@ nsCaret::GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection, nsBidiLevel baseLevel = NS_GET_BASE_LEVEL(frameAfter); if (baseLevel != levelAfter) { - nsPeekOffsetStruct pos(eSelectBeginLine, eDirPrevious, 0, 0, false, true, false, true); + nsPeekOffsetStruct pos(eSelectBeginLine, eDirPrevious, 0, + nsPoint(0, 0), false, true, false, + true); if (NS_SUCCEEDED(frameAfter->PeekOffset(&pos))) { theFrame = pos.mResultFrame; theFrameOffset = pos.mContentOffset; @@ -733,7 +735,9 @@ nsCaret::GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection, nsBidiLevel baseLevel = NS_GET_BASE_LEVEL(frameBefore); if (baseLevel != levelBefore) { - nsPeekOffsetStruct pos(eSelectEndLine, eDirNext, 0, 0, false, true, false, true); + nsPeekOffsetStruct pos(eSelectEndLine, eDirNext, 0, + nsPoint(0, 0), false, true, false, + true); if (NS_SUCCEEDED(frameBefore->PeekOffset(&pos))) { theFrame = pos.mResultFrame; theFrameOffset = pos.mContentOffset; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 7a13d7e17fa4..1434a1c257f9 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -3091,7 +3091,7 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack, nsPeekOffsetStruct pos(eSelectCharacter, eDirNext, aStartPos, - 0, + nsPoint(0, 0), aJumpLines, true, //limit on scrolled views false, @@ -3107,7 +3107,7 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack, nsPeekOffsetStruct startpos(aAmountBack, eDirPrevious, baseOffset, - 0, + nsPoint(0, 0), aJumpLines, true, //limit on scrolled views false, @@ -3119,7 +3119,7 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack, nsPeekOffsetStruct endpos(aAmountForward, eDirNext, aStartPos, - 0, + nsPoint(0, 0), aJumpLines, true, //limit on scrolled views false, @@ -6084,8 +6084,10 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext, nsPoint offset; nsView * view; //used for call of get offset from view aBlockFrame->GetOffsetFromView(offset,&view); - nscoord newDesiredX = aPos->mDesiredX - offset.x;//get desired x into blockframe coordinates! - result = it->FindFrameAt(searchingLine, newDesiredX, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame); + nsPoint newDesiredPos = + aPos->mDesiredPos - offset; //get desired position into blockframe coords + result = it->FindFrameAt(searchingLine, newDesiredPos, &resultFrame, + &isBeforeFirstFrame, &isAfterLastFrame); if(NS_FAILED(result)) continue; } @@ -6116,8 +6118,6 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext, nsIFrame *storeOldResultFrame = resultFrame; while ( !found ){ nsPoint point; - point.x = aPos->mDesiredX; - nsRect tempRect = resultFrame->GetRect(); nsPoint offset; nsView * view; //used for call of get offset from view @@ -6125,7 +6125,13 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext, if (!view) { return NS_ERROR_FAILURE; } - point.y = tempRect.height + offset.y; + if (resultFrame->GetWritingMode().IsVertical()) { + point.y = aPos->mDesiredPos.y; + point.x = tempRect.width + offset.x; + } else { + point.y = tempRect.height + offset.y; + point.x = aPos->mDesiredPos.x; + } //special check. if we allow non-text selection then we can allow a hit location to fall before a table. //otherwise there is no way to get and click signal to fall before a table (it being a line iterator itself) @@ -6208,7 +6214,7 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext, ); } while ( !found ){ - nsPoint point(aPos->mDesiredX, 0); + nsPoint point = aPos->mDesiredPos; nsView* view; nsPoint offset; resultFrame->GetOffsetFromView(offset, &view); diff --git a/layout/generic/nsFrameSelection.h b/layout/generic/nsFrameSelection.h index 7931397f479b..c14bc603d70a 100644 --- a/layout/generic/nsFrameSelection.h +++ b/layout/generic/nsFrameSelection.h @@ -63,7 +63,7 @@ struct MOZ_STACK_CLASS nsPeekOffsetStruct nsPeekOffsetStruct(nsSelectionAmount aAmount, nsDirection aDirection, int32_t aStartOffset, - nscoord aDesiredX, + nsPoint aDesiredPos, bool aJumpLines, bool aScrollViewStop, bool aIsKeyboardSelect, @@ -96,9 +96,10 @@ struct MOZ_STACK_CLASS nsPeekOffsetStruct // Used with: eSelectCharacter, eSelectWord int32_t mStartOffset; - // mDesiredX: The desired x coordinate for the caret. - // Used with: eSelectLine. - nscoord mDesiredX; + // mDesiredPos: The desired inline coordinate for the caret + // (one of .x or .y will be used, depending on line's writing mode) + // Used with: eSelectLine. + nsPoint mDesiredPos; // mWordMovementType: An enum that determines whether to prefer the start or end of a word // or to use the default beahvior, which is a combination of @@ -645,9 +646,9 @@ private: nsSelectionAmount aAmount, CaretMovementStyle aMovementStyle); - nsresult FetchDesiredX(nscoord &aDesiredX); //the x position requested by the Key Handling for up down - void InvalidateDesiredX(); //do not listen to mDesiredX you must get another. - void SetDesiredX(nscoord aX); //set the mDesiredX + nsresult FetchDesiredPos(nsPoint &aDesiredPos); //the position requested by the Key Handling for up down + void InvalidateDesiredPos(); //do not listen to mDesiredPos you must get another. + void SetDesiredPos(nsPoint aPos); //set the mDesiredPos uint32_t GetBatching() const {return mBatching; } bool GetNotifyFrames() const { return mNotifyFrames; } @@ -714,7 +715,7 @@ private: CaretAssociateHint mHint; //hint to tell if the selection is at the end of this line or beginning of next nsBidiLevel mCaretBidiLevel; - int32_t mDesiredX; + nsPoint mDesiredPos; uint32_t mDelayedMouseEventClickCount; bool mDelayedMouseEventIsShift; bool mDelayedMouseEventValid; @@ -724,7 +725,7 @@ private: bool mDragSelectingCells; bool mDragState; //for drag purposes bool mMouseDoubleDownState; //has the doubleclick down happened - bool mDesiredXSet; + bool mDesiredPosSet; int8_t mCaretMovementStyle; }; diff --git a/layout/generic/nsILineIterator.h b/layout/generic/nsILineIterator.h index 7019e71933d4..65a0243782e0 100644 --- a/layout/generic/nsILineIterator.h +++ b/layout/generic/nsILineIterator.h @@ -6,7 +6,7 @@ #define nsILineIterator_h___ #include "nscore.h" -#include "nsCoord.h" +#include "nsPoint.h" #include "mozilla/Attributes.h" class nsIFrame; @@ -82,15 +82,16 @@ public: virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) = 0; - // Given a line number and an X coordinate, find the frame on the - // line that is nearest to the X coordinate. The - // aXIsBeforeFirstFrame and aXIsAfterLastFrame flags are updated + // Given a line number and a coordinate, find the frame on the line + // that is nearest to aPos along the inline axis. (The block-axis coord + // of aPos is irrelevant.) + // The aPosIsBeforeFirstFrame and aPosIsAfterLastFrame flags are updated // appropriately. NS_IMETHOD FindFrameAt(int32_t aLineNumber, - nscoord aX, + nsPoint aPos, nsIFrame** aFrameFound, - bool* aXIsBeforeFirstFrame, - bool* aXIsAfterLastFrame) = 0; + bool* aPosIsBeforeFirstFrame, + bool* aPosIsAfterLastFrame) = 0; // Give the line iterator implementor a chance todo something more complicated than // nsIFrame::GetNextSibling() diff --git a/layout/generic/nsLineBox.cpp b/layout/generic/nsLineBox.cpp index eb3e7ac803fe..85a90439aff4 100644 --- a/layout/generic/nsLineBox.cpp +++ b/layout/generic/nsLineBox.cpp @@ -711,14 +711,14 @@ nsLineIterator::CheckLineOrder(int32_t aLine, NS_IMETHODIMP nsLineIterator::FindFrameAt(int32_t aLineNumber, - nscoord aX, + nsPoint aPos, nsIFrame** aFrameFound, - bool* aXIsBeforeFirstFrame, - bool* aXIsAfterLastFrame) + bool* aPosIsBeforeFirstFrame, + bool* aPosIsAfterLastFrame) { - NS_PRECONDITION(aFrameFound && aXIsBeforeFirstFrame && aXIsAfterLastFrame, + NS_PRECONDITION(aFrameFound && aPosIsBeforeFirstFrame && aPosIsAfterLastFrame, "null OUT ptr"); - if (!aFrameFound || !aXIsBeforeFirstFrame || !aXIsAfterLastFrame) { + if (!aFrameFound || !aPosIsBeforeFirstFrame || !aPosIsAfterLastFrame) { return NS_ERROR_NULL_POINTER; } if ((aLineNumber < 0) || (aLineNumber >= mNumLines)) { @@ -728,8 +728,8 @@ nsLineIterator::FindFrameAt(int32_t aLineNumber, nsLineBox* line = mLines[aLineNumber]; if (!line) { *aFrameFound = nullptr; - *aXIsBeforeFirstFrame = true; - *aXIsAfterLastFrame = false; + *aPosIsBeforeFirstFrame = true; + *aPosIsAfterLastFrame = false; return NS_OK; } @@ -737,51 +737,58 @@ nsLineIterator::FindFrameAt(int32_t aLineNumber, return NS_ERROR_FAILURE; nsIFrame* frame = line->mFirstChild; - nsIFrame* closestFromLeft = nullptr; - nsIFrame* closestFromRight = nullptr; + nsIFrame* closestFromStart = nullptr; + nsIFrame* closestFromEnd = nullptr; + + WritingMode wm = line->mWritingMode; + nscoord cw = line->mContainerWidth; + + LogicalPoint pos(wm, aPos, cw); + int32_t n = line->GetChildCount(); while (n--) { - nsRect rect = frame->GetRect(); - if (rect.width > 0) { - // If aX is inside this frame - this is it - if (rect.x <= aX && rect.XMost() > aX) { - closestFromLeft = closestFromRight = frame; + LogicalRect rect = frame->GetLogicalRect(wm, cw); + if (rect.ISize(wm) > 0) { + // If pos.I() is inside this frame - this is it + if (rect.IStart(wm) <= pos.I(wm) && rect.IEnd(wm) > pos.I(wm)) { + closestFromStart = closestFromEnd = frame; break; } - if (rect.x < aX) { - if (!closestFromLeft || - rect.XMost() > closestFromLeft->GetRect().XMost()) - closestFromLeft = frame; + if (rect.IStart(wm) < pos.I(wm)) { + if (!closestFromStart || + rect.IEnd(wm) > closestFromStart->GetLogicalRect(wm, cw).IEnd(wm)) + closestFromStart = frame; } else { - if (!closestFromRight || - rect.x < closestFromRight->GetRect().x) - closestFromRight = frame; + if (!closestFromEnd || + rect.IStart(wm) < closestFromEnd->GetLogicalRect(wm, cw).IStart(wm)) + closestFromEnd = frame; } } frame = frame->GetNextSibling(); } - if (!closestFromLeft && !closestFromRight) { + if (!closestFromStart && !closestFromEnd) { // All frames were zero-width. Just take the first one. - closestFromLeft = closestFromRight = line->mFirstChild; + closestFromStart = closestFromEnd = line->mFirstChild; } - *aXIsBeforeFirstFrame = mRightToLeft ? !closestFromRight : !closestFromLeft; - *aXIsAfterLastFrame = mRightToLeft ? !closestFromLeft : !closestFromRight; - if (closestFromLeft == closestFromRight) { - *aFrameFound = closestFromLeft; + *aPosIsBeforeFirstFrame = mRightToLeft ? !closestFromEnd : !closestFromStart; + *aPosIsAfterLastFrame = mRightToLeft ? !closestFromStart : !closestFromEnd; + if (closestFromStart == closestFromEnd) { + *aFrameFound = closestFromStart; } - else if (!closestFromLeft) { - *aFrameFound = closestFromRight; + else if (!closestFromStart) { + *aFrameFound = closestFromEnd; } - else if (!closestFromRight) { - *aFrameFound = closestFromLeft; + else if (!closestFromEnd) { + *aFrameFound = closestFromStart; } else { // we're between two frames - nscoord delta = closestFromRight->GetRect().x - closestFromLeft->GetRect().XMost(); - if (aX < closestFromLeft->GetRect().XMost() + delta/2) - *aFrameFound = closestFromLeft; + nscoord delta = closestFromEnd->GetLogicalRect(wm, cw).IStart(wm) - + closestFromStart->GetLogicalRect(wm, cw).IEnd(wm); + if (pos.I(wm) < closestFromStart->GetLogicalRect(wm, cw).IEnd(wm) + delta/2) + *aFrameFound = closestFromStart; else - *aFrameFound = closestFromRight; + *aFrameFound = closestFromEnd; } return NS_OK; } diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h index 2f650adb8c38..f20b3a27c455 100644 --- a/layout/generic/nsLineBox.h +++ b/layout/generic/nsLineBox.h @@ -1705,10 +1705,10 @@ public: uint32_t* aLineFlags) MOZ_OVERRIDE; virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) MOZ_OVERRIDE; NS_IMETHOD FindFrameAt(int32_t aLineNumber, - nscoord aX, + nsPoint aPos, nsIFrame** aFrameFound, - bool* aXIsBeforeFirstFrame, - bool* aXIsAfterLastFrame) MOZ_OVERRIDE; + bool* aPosIsBeforeFirstFrame, + bool* aPosIsAfterLastFrame) MOZ_OVERRIDE; NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) MOZ_OVERRIDE; NS_IMETHOD CheckLineOrder(int32_t aLine, diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index ce6c09d78283..425d3a7dd224 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -48,7 +48,6 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID); #include "mozilla/Preferences.h" #include "nsDOMClassInfoID.h" -//included for desired x position; #include "nsPresContext.h" #include "nsIPresShell.h" #include "nsCaret.h" @@ -108,7 +107,7 @@ static void printRange(nsRange *aDomRange); nsPeekOffsetStruct::nsPeekOffsetStruct(nsSelectionAmount aAmount, nsDirection aDirection, int32_t aStartOffset, - nscoord aDesiredX, + nsPoint aDesiredPos, bool aJumpLines, bool aScrollViewStop, bool aIsKeyboardSelect, @@ -117,7 +116,7 @@ nsPeekOffsetStruct::nsPeekOffsetStruct(nsSelectionAmount aAmount, : mAmount(aAmount) , mDirection(aDirection) , mStartOffset(aStartOffset) - , mDesiredX(aDesiredX) + , mDesiredPos(aDesiredPos) , mWordMovementType(aWordMovementType) , mJumpLines(aJumpLines) , mScrollViewStop(aScrollViewStop) @@ -436,57 +435,55 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsFrameSelection, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsFrameSelection, Release) - +// Get the x (or y, in vertical writing mode) position requested +// by the Key Handling for line-up/down nsresult -nsFrameSelection::FetchDesiredX(nscoord &aDesiredX) //the x position requested by the Key Handling for up down +nsFrameSelection::FetchDesiredPos(nsPoint &aDesiredPos) { - if (!mShell) - { - NS_ERROR("fetch desired X failed"); + if (!mShell) { + NS_ERROR("fetch desired position failed"); return NS_ERROR_FAILURE; } - if (mDesiredXSet) - { - aDesiredX = mDesiredX; + if (mDesiredPosSet) { + aDesiredPos = mDesiredPos; return NS_OK; } nsRefPtr caret = mShell->GetCaret(); - if (!caret) + if (!caret) { return NS_ERROR_NULL_POINTER; + } int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); caret->SetSelection(mDomSelections[index]); nsRect coord; nsIFrame* caretFrame = caret->GetGeometry(&coord); - if (!caretFrame) + if (!caretFrame) { return NS_ERROR_FAILURE; + } nsPoint viewOffset(0, 0); nsView* view = nullptr; caretFrame->GetOffsetFromView(viewOffset, &view); - if (view) - coord.x += viewOffset.x; - - aDesiredX = coord.x; + if (view) { + coord += viewOffset; + } + aDesiredPos = coord.TopLeft(); return NS_OK; } - - void -nsFrameSelection::InvalidateDesiredX() //do not listen to mDesiredX you must get another. +nsFrameSelection::InvalidateDesiredPos() // do not listen to mDesiredPos; + // you must get another. { - mDesiredXSet = false; + mDesiredPosSet = false; } - - void -nsFrameSelection::SetDesiredX(nscoord aX) //set the mDesiredX +nsFrameSelection::SetDesiredPos(nsPoint aPos) { - mDesiredX = aX; - mDesiredXSet = true; + mDesiredPos = aPos; + mDesiredPosSet = true; } nsresult @@ -718,7 +715,7 @@ nsFrameSelection::Init(nsIPresShell *aShell, nsIContent *aLimiter) { mShell = aShell; mDragState = false; - mDesiredXSet = false; + mDesiredPosSet = false; mLimiter = aLimiter; mCaretMovementStyle = Preferences::GetInt("bidi.edit.caret_movement_style", 2); @@ -766,7 +763,7 @@ nsFrameSelection::MoveCaret(nsDirection aDirection, return NS_ERROR_FAILURE; bool isCollapsed; - nscoord desiredX = 0; //we must keep this around and revalidate it when its just UP/DOWN + nsPoint desiredPos(0, 0); //we must keep this around and revalidate it when its just UP/DOWN int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); nsRefPtr sel = mDomSelections[index]; @@ -786,13 +783,15 @@ nsFrameSelection::MoveCaret(nsDirection aDirection, } nsresult result = sel->GetIsCollapsed(&isCollapsed); - if (NS_FAILED(result)) + if (NS_FAILED(result)) { return result; + } if (aAmount == eSelectLine) { - result = FetchDesiredX(desiredX); - if (NS_FAILED(result)) + result = FetchDesiredPos(desiredPos); + if (NS_FAILED(result)) { return result; - SetDesiredX(desiredX); + } + SetDesiredPos(desiredPos); } int32_t caretStyle = Preferences::GetInt("layout.selection.caret_style", 0); @@ -850,7 +849,7 @@ nsFrameSelection::MoveCaret(nsDirection aDirection, //set data using mLimiter to stop on scroll views. If we have a limiter then we stop peeking //when we hit scrollable views. If no limiter then just let it go ahead - nsPeekOffsetStruct pos(aAmount, eDirPrevious, offsetused, desiredX, + nsPeekOffsetStruct pos(aAmount, eDirPrevious, offsetused, desiredPos, true, mLimiter != nullptr, true, visualMovement); nsBidiDirection paraDir = nsBidiPresUtils::ParagraphDirection(frame); @@ -861,7 +860,7 @@ nsFrameSelection::MoveCaret(nsDirection aDirection, case eSelectCluster: case eSelectWord: case eSelectWordNoSpace: - InvalidateDesiredX(); + InvalidateDesiredPos(); pos.mAmount = aAmount; pos.mDirection = (visualMovement && paraDir == NSBIDI_RTL) ? nsDirection(1 - aDirection) : aDirection; @@ -872,7 +871,7 @@ nsFrameSelection::MoveCaret(nsDirection aDirection, break; case eSelectBeginLine: case eSelectEndLine: - InvalidateDesiredX(); + InvalidateDesiredPos(); pos.mAmount = aAmount; pos.mDirection = (visualMovement && paraDir == NSBIDI_RTL) ? nsDirection(1 - aDirection) : aDirection; @@ -1369,7 +1368,7 @@ nsFrameSelection::HandleClick(nsIContent* aNewFocus, if (!aNewFocus) return NS_ERROR_INVALID_ARG; - InvalidateDesiredX(); + InvalidateDesiredPos(); if (!aContinueSelection) { mMaintainRange = nullptr; @@ -1441,15 +1440,16 @@ nsFrameSelection::HandleDrag(nsIFrame *aFrame, nsPoint aPoint) if (frame && amount == eSelectWord && direction == eDirPrevious) { // To avoid selecting the previous word when at start of word, // first move one character forward. - nsPeekOffsetStruct charPos(eSelectCharacter, eDirNext, offset, 0, - false, mLimiter != nullptr, false, false); + nsPeekOffsetStruct charPos(eSelectCharacter, eDirNext, offset, + nsPoint(0, 0), false, mLimiter != nullptr, + false, false); if (NS_SUCCEEDED(frame->PeekOffset(&charPos))) { frame = charPos.mResultFrame; offset = charPos.mContentOffset; } } - nsPeekOffsetStruct pos(amount, direction, offset, 0, + nsPeekOffsetStruct pos(amount, direction, offset, nsPoint(0, 0), false, mLimiter != nullptr, false, false); if (frame && NS_SUCCEEDED(frame->PeekOffset(&pos)) && pos.mResultContent) { @@ -1538,17 +1538,16 @@ nsFrameSelection::TakeFocus(nsIContent* aNewFocus, mDomSelections[index]->AddRange(newRange); mBatching = batching; mChangesDuringBatching = changes; - } - else - { - bool oldDesiredXSet = mDesiredXSet; //need to keep old desired X if it was set. + } else { + bool oldDesiredPosSet = mDesiredPosSet; //need to keep old desired position if it was set. mDomSelections[index]->Collapse(aNewFocus, aContentOffset); - mDesiredXSet = oldDesiredXSet; //now reset desired X back. + mDesiredPosSet = oldDesiredPosSet; //now reset desired pos back. mBatching = batching; mChangesDuringBatching = changes; } - if (aContentEndOffset != aContentOffset) + if (aContentEndOffset != aContentOffset) { mDomSelections[index]->Extend(aNewFocus, aContentEndOffset); + } //find out if we are inside a table. if so, find out which one and which cell //once we do that, the next time we get a takefocus, check the parent tree. @@ -1857,10 +1856,11 @@ nsFrameSelection::CommonPageMove(bool aForward, return; // find out where the caret is. - // we should know mDesiredX value of nsFrameSelection, but I havent seen that behavior in other windows applications yet. + // we should know mDesiredPos value of nsFrameSelection, but I havent seen that behavior in other windows applications yet. nsISelection* domSel = GetSelection(nsISelectionController::SELECTION_NORMAL); - if (!domSel) + if (!domSel) { return; + } nsRect caretPos; nsIFrame* caretFrame = nsCaret::GetGeometry(domSel, &caretPos); @@ -4592,7 +4592,7 @@ Selection::Collapse(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) nsCOMPtr kungfuDeathGrip = &aParentNode; - mFrameSelection->InvalidateDesiredX(); + mFrameSelection->InvalidateDesiredPos(); if (!IsValidSelectionPoint(mFrameSelection, &aParentNode)) { aRv.Throw(NS_ERROR_FAILURE); return; @@ -5887,9 +5887,9 @@ Selection::SelectionLanguageChange(bool aLangRTL) mFrameSelection->SetCaretBidiLevel(levelAfter); } - // The caret might have moved, so invalidate the desired X position + // The caret might have moved, so invalidate the desired position // for future usages of up-arrow or down-arrow - mFrameSelection->InvalidateDesiredX(); + mFrameSelection->InvalidateDesiredPos(); return NS_OK; } diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index afc13285e6d2..33d2a60eff82 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -1732,84 +1732,89 @@ nsTableRowGroupFrame::CheckLineOrder(int32_t aLine, NS_IMETHODIMP nsTableRowGroupFrame::FindFrameAt(int32_t aLineNumber, - nscoord aX, + nsPoint aPos, nsIFrame** aFrameFound, - bool* aXIsBeforeFirstFrame, - bool* aXIsAfterLastFrame) + bool* aPosIsBeforeFirstFrame, + bool* aPosIsAfterLastFrame) { - nsTableFrame* table = nsTableFrame::GetTableFrame(this); - nsTableCellMap* cellMap = table->GetCellMap(); - - *aFrameFound = nullptr; - *aXIsBeforeFirstFrame = true; - *aXIsAfterLastFrame = false; + nsTableFrame* table = nsTableFrame::GetTableFrame(this); + nsTableCellMap* cellMap = table->GetCellMap(); - aLineNumber += GetStartRowIndex(); - int32_t numCells = cellMap->GetNumCellsOriginatingInRow(aLineNumber); - if (numCells == 0) { - return NS_OK; - } + WritingMode wm = table->GetWritingMode(); + nscoord cw = table->GetRect().width; + LogicalPoint pos(wm, aPos, cw); - nsIFrame* frame = nullptr; - int32_t colCount = table->GetColCount(); - for (int32_t i = 0; i < colCount; i++) { - CellData* data = cellMap->GetDataAt(aLineNumber, i); - if (data && data->IsOrig()) { - frame = (nsIFrame*)data->GetCellFrame(); - break; - } - } - NS_ASSERTION(frame, "cellmap is lying"); - bool isRTL = (NS_STYLE_DIRECTION_RTL == - table->StyleVisibility()->mDirection); - - nsIFrame* closestFromLeft = nullptr; - nsIFrame* closestFromRight = nullptr; - int32_t n = numCells; - nsIFrame* firstFrame = frame; - while (n--) { - nsRect rect = frame->GetRect(); - if (rect.width > 0) { - // If aX is inside this frame - this is it - if (rect.x <= aX && rect.XMost() > aX) { - closestFromLeft = closestFromRight = frame; - break; - } - if (rect.x < aX) { - if (!closestFromLeft || - rect.XMost() > closestFromLeft->GetRect().XMost()) - closestFromLeft = frame; - } - else { - if (!closestFromRight || - rect.x < closestFromRight->GetRect().x) - closestFromRight = frame; - } - } - frame = frame->GetNextSibling(); - } - if (!closestFromLeft && !closestFromRight) { - // All frames were zero-width. Just take the first one. - closestFromLeft = closestFromRight = firstFrame; - } - *aXIsBeforeFirstFrame = isRTL ? !closestFromRight : !closestFromLeft; - *aXIsAfterLastFrame = isRTL ? !closestFromLeft : !closestFromRight; - if (closestFromLeft == closestFromRight) { - *aFrameFound = closestFromLeft; - } - else if (!closestFromLeft) { - *aFrameFound = closestFromRight; - } - else if (!closestFromRight) { - *aFrameFound = closestFromLeft; - } - else { // we're between two frames - nscoord delta = closestFromRight->GetRect().x - - closestFromLeft->GetRect().XMost(); - if (aX < closestFromLeft->GetRect().XMost() + delta/2) - *aFrameFound = closestFromLeft; - else - *aFrameFound = closestFromRight; + *aFrameFound = nullptr; + *aPosIsBeforeFirstFrame = true; + *aPosIsAfterLastFrame = false; + + aLineNumber += GetStartRowIndex(); + int32_t numCells = cellMap->GetNumCellsOriginatingInRow(aLineNumber); + if (numCells == 0) { + return NS_OK; + } + + nsIFrame* frame = nullptr; + int32_t colCount = table->GetColCount(); + for (int32_t i = 0; i < colCount; i++) { + CellData* data = cellMap->GetDataAt(aLineNumber, i); + if (data && data->IsOrig()) { + frame = (nsIFrame*)data->GetCellFrame(); + break; + } + } + NS_ASSERTION(frame, "cellmap is lying"); + bool isRTL = (NS_STYLE_DIRECTION_RTL == + table->StyleVisibility()->mDirection); + + nsIFrame* closestFromStart = nullptr; + nsIFrame* closestFromEnd = nullptr; + int32_t n = numCells; + nsIFrame* firstFrame = frame; + while (n--) { + LogicalRect rect = frame->GetLogicalRect(wm, cw); + if (rect.ISize(wm) > 0) { + // If pos.I() is inside this frame - this is it + if (rect.IStart(wm) <= pos.I(wm) && rect.IEnd(wm) > pos.I(wm)) { + closestFromStart = closestFromEnd = frame; + break; + } + if (rect.IStart(wm) < pos.I(wm)) { + if (!closestFromStart || + rect.IEnd(wm) > closestFromStart->GetLogicalRect(wm, cw).IEnd(wm)) + closestFromStart = frame; + } + else { + if (!closestFromEnd || + rect.IStart(wm) < closestFromEnd->GetLogicalRect(wm, cw).IStart(wm)) + closestFromEnd = frame; + } + } + frame = frame->GetNextSibling(); + } + if (!closestFromStart && !closestFromEnd) { + // All frames were zero-width. Just take the first one. + closestFromStart = closestFromEnd = firstFrame; + } + *aPosIsBeforeFirstFrame = isRTL ? !closestFromEnd : !closestFromStart; + *aPosIsAfterLastFrame = isRTL ? !closestFromStart : !closestFromEnd; + if (closestFromStart == closestFromEnd) { + *aFrameFound = closestFromStart; + } + else if (!closestFromStart) { + *aFrameFound = closestFromEnd; + } + else if (!closestFromEnd) { + *aFrameFound = closestFromStart; + } + else { // we're between two frames + nscoord delta = closestFromEnd->GetLogicalRect(wm, cw).IStart(wm) - + closestFromStart->GetLogicalRect(wm, cw).IEnd(wm); + if (pos.I(wm) < closestFromStart->GetLogicalRect(wm, cw).IEnd(wm) + delta/2) { + *aFrameFound = closestFromStart; + } else { + *aFrameFound = closestFromEnd; + } } return NS_OK; } diff --git a/layout/tables/nsTableRowGroupFrame.h b/layout/tables/nsTableRowGroupFrame.h index e4864d8295cc..06345a8f7713 100644 --- a/layout/tables/nsTableRowGroupFrame.h +++ b/layout/tables/nsTableRowGroupFrame.h @@ -228,21 +228,21 @@ public: virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) MOZ_OVERRIDE; /** Find the orginating cell frame on a row that is the nearest to the - * coordinate X. + * inline-dir coordinate of aPos. * @param aLineNumber - the index of the row relative to the row group - * @param aX - X coordinate in twips relative to the + * @param aPos - coordinate in twips relative to the * origin of the row group * @param aFrameFound - pointer to the cellframe - * @param aXIsBeforeFirstFrame - the point is before the first originating + * @param aPosIsBeforeFirstFrame - the point is before the first originating * cellframe - * @param aXIsAfterLastFrame - the point is after the last originating + * @param aPosIsAfterLastFrame - the point is after the last originating * cellframe */ NS_IMETHOD FindFrameAt(int32_t aLineNumber, - nscoord aX, + nsPoint aPos, nsIFrame** aFrameFound, - bool* aXIsBeforeFirstFrame, - bool* aXIsAfterLastFrame) MOZ_OVERRIDE; + bool* aPosIsBeforeFirstFrame, + bool* aPosIsAfterLastFrame) MOZ_OVERRIDE; /** Check whether visual and logical order of cell frames within a line are * identical. As the layout will reorder them this is always the case