mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 758179. Part 3: Support SKIP_HIDDEN flag. r=mats
This commit is contained in:
parent
05d68e6828
commit
6b23199749
@ -3091,12 +3091,17 @@ struct FrameTarget {
|
||||
};
|
||||
|
||||
// See function implementation for information
|
||||
static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint);
|
||||
static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint,
|
||||
PRUint32 aFlags);
|
||||
|
||||
static bool SelfIsSelectable(nsIFrame* aFrame)
|
||||
static bool SelfIsSelectable(nsIFrame* aFrame, PRUint32 aFlags)
|
||||
{
|
||||
return !(aFrame->IsGeneratedContentFrame() ||
|
||||
aFrame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_NONE);
|
||||
if ((aFlags & nsIFrame::SKIP_HIDDEN) &&
|
||||
!aFrame->GetStyleVisibility()->IsVisible()) {
|
||||
return false;
|
||||
}
|
||||
return !aFrame->IsGeneratedContentFrame() &&
|
||||
aFrame->GetStyleUIReset()->mUserSelect != NS_STYLE_USER_SELECT_NONE;
|
||||
}
|
||||
|
||||
static bool SelectionDescendToKids(nsIFrame* aFrame) {
|
||||
@ -3118,12 +3123,13 @@ static bool SelectionDescendToKids(nsIFrame* aFrame) {
|
||||
}
|
||||
|
||||
static FrameTarget GetSelectionClosestFrameForChild(nsIFrame* aChild,
|
||||
nsPoint aPoint)
|
||||
nsPoint aPoint,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
nsIFrame* parent = aChild->GetParent();
|
||||
if (SelectionDescendToKids(aChild)) {
|
||||
nsPoint pt = aPoint - aChild->GetOffsetTo(parent);
|
||||
return GetSelectionClosestFrame(aChild, pt);
|
||||
return GetSelectionClosestFrame(aChild, pt, aFlags);
|
||||
}
|
||||
return FrameTarget(aChild, false, false);
|
||||
}
|
||||
@ -3134,12 +3140,12 @@ static FrameTarget GetSelectionClosestFrameForChild(nsIFrame* aChild,
|
||||
// blocks, because that's not where it's expected.
|
||||
// Note that this method is guaranteed to succeed.
|
||||
static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame,
|
||||
bool aEndFrame) {
|
||||
bool aEndFrame, PRUint32 aFlags) {
|
||||
if (SelectionDescendToKids(aFrame)) {
|
||||
nsIFrame* result = nsnull;
|
||||
nsIFrame *frame = aFrame->GetFirstPrincipalChild();
|
||||
if (!aEndFrame) {
|
||||
while (frame && (!SelfIsSelectable(frame) ||
|
||||
while (frame && (!SelfIsSelectable(frame, aFlags) ||
|
||||
frame->IsEmpty()))
|
||||
frame = frame->GetNextSibling();
|
||||
if (frame)
|
||||
@ -3150,13 +3156,13 @@ static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame,
|
||||
// XXX I have a feeling this could be slow for long blocks, although
|
||||
// I can't find any slowdowns
|
||||
while (frame) {
|
||||
if (!frame->IsEmpty() && SelfIsSelectable(frame))
|
||||
if (!frame->IsEmpty() && SelfIsSelectable(frame, aFlags))
|
||||
result = frame;
|
||||
frame = frame->GetNextSibling();
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
return DrillDownToSelectionFrame(result, aEndFrame);
|
||||
return DrillDownToSelectionFrame(result, aEndFrame, aFlags);
|
||||
}
|
||||
// If the current frame has no targetable children, target the current frame
|
||||
return FrameTarget(aFrame, true, aEndFrame);
|
||||
@ -3167,23 +3173,24 @@ static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame,
|
||||
static FrameTarget GetSelectionClosestFrameForLine(
|
||||
nsBlockFrame* aParent,
|
||||
nsBlockFrame::line_iterator aLine,
|
||||
nsPoint aPoint)
|
||||
nsPoint aPoint,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
nsIFrame *frame = aLine->mFirstChild;
|
||||
// Account for end of lines (any iterator from the block is valid)
|
||||
if (aLine == aParent->end_lines())
|
||||
return DrillDownToSelectionFrame(aParent, true);
|
||||
return DrillDownToSelectionFrame(aParent, true, aFlags);
|
||||
nsIFrame *closestFromLeft = nsnull, *closestFromRight = nsnull;
|
||||
nsRect rect = aLine->mBounds;
|
||||
nscoord closestLeft = rect.x, closestRight = rect.XMost();
|
||||
for (PRInt32 n = aLine->GetChildCount(); n;
|
||||
--n, frame = frame->GetNextSibling()) {
|
||||
if (!SelfIsSelectable(frame) || frame->IsEmpty())
|
||||
if (!SelfIsSelectable(frame, aFlags) || frame->IsEmpty())
|
||||
continue;
|
||||
nsRect frameRect = frame->GetRect();
|
||||
if (aPoint.x >= frameRect.x) {
|
||||
if (aPoint.x < frameRect.XMost()) {
|
||||
return GetSelectionClosestFrameForChild(frame, aPoint);
|
||||
return GetSelectionClosestFrameForChild(frame, aPoint, aFlags);
|
||||
}
|
||||
if (frameRect.XMost() >= closestLeft) {
|
||||
closestFromLeft = frame;
|
||||
@ -3204,9 +3211,9 @@ static FrameTarget GetSelectionClosestFrameForLine(
|
||||
if (closestFromLeft &&
|
||||
(!closestFromRight ||
|
||||
(abs(aPoint.x - closestLeft) <= abs(aPoint.x - closestRight)))) {
|
||||
return GetSelectionClosestFrameForChild(closestFromLeft, aPoint);
|
||||
return GetSelectionClosestFrameForChild(closestFromLeft, aPoint, aFlags);
|
||||
}
|
||||
return GetSelectionClosestFrameForChild(closestFromRight, aPoint);
|
||||
return GetSelectionClosestFrameForChild(closestFromRight, aPoint, aFlags);
|
||||
}
|
||||
|
||||
// This method is for the special handling we do for block frames; they're
|
||||
@ -3215,7 +3222,8 @@ static FrameTarget GetSelectionClosestFrameForLine(
|
||||
// frame tree. Returns a null FrameTarget for frames which are not
|
||||
// blocks or blocks with no lines except editable one.
|
||||
static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
|
||||
nsPoint aPoint)
|
||||
nsPoint aPoint,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(aFrame); // used only for QI
|
||||
if (!bf)
|
||||
@ -3265,11 +3273,11 @@ static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
|
||||
|
||||
if (prevLine == end) {
|
||||
if (dragOutOfFrame == 1 || nextLine == end)
|
||||
return DrillDownToSelectionFrame(aFrame, false);
|
||||
return DrillDownToSelectionFrame(aFrame, false, aFlags);
|
||||
closestLine = nextLine;
|
||||
} else if (nextLine == end) {
|
||||
if (dragOutOfFrame == 1)
|
||||
return DrillDownToSelectionFrame(aFrame, true);
|
||||
return DrillDownToSelectionFrame(aFrame, true, aFlags);
|
||||
closestLine = prevLine;
|
||||
} else { // Figure out which line is closer
|
||||
if (aPoint.y - prevLine->mBounds.YMost() < nextLine->mBounds.y - aPoint.y)
|
||||
@ -3281,13 +3289,13 @@ static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
|
||||
|
||||
do {
|
||||
FrameTarget target = GetSelectionClosestFrameForLine(bf, closestLine,
|
||||
aPoint);
|
||||
aPoint, aFlags);
|
||||
if (!target.IsNull())
|
||||
return target;
|
||||
++closestLine;
|
||||
} while (closestLine != end);
|
||||
// Fall back to just targeting the last targetable place
|
||||
return DrillDownToSelectionFrame(aFrame, true);
|
||||
return DrillDownToSelectionFrame(aFrame, true, aFlags);
|
||||
}
|
||||
|
||||
// GetSelectionClosestFrame is the helper function that calculates the closest
|
||||
@ -3297,11 +3305,12 @@ static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
|
||||
// Cannot handle overlapping frames correctly, so it should receive the output
|
||||
// of GetFrameForPoint
|
||||
// Guaranteed to return a valid FrameTarget
|
||||
static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint)
|
||||
static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
{
|
||||
// Handle blocks; if the frame isn't a block, the method fails
|
||||
FrameTarget target = GetSelectionClosestFrameForBlock(aFrame, aPoint);
|
||||
FrameTarget target = GetSelectionClosestFrameForBlock(aFrame, aPoint, aFlags);
|
||||
if (!target.IsNull())
|
||||
return target;
|
||||
}
|
||||
@ -3318,7 +3327,7 @@ static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint)
|
||||
nsIFrame *closestFrame = nsnull;
|
||||
|
||||
for (; kid; kid = kid->GetNextSibling()) {
|
||||
if (!SelfIsSelectable(kid) || kid->IsEmpty())
|
||||
if (!SelfIsSelectable(kid, aFlags) || kid->IsEmpty())
|
||||
continue;
|
||||
|
||||
nsRect rect = kid->GetRect();
|
||||
@ -3356,7 +3365,7 @@ static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint)
|
||||
}
|
||||
}
|
||||
if (closestFrame)
|
||||
return GetSelectionClosestFrameForChild(closestFrame, aPoint);
|
||||
return GetSelectionClosestFrameForChild(closestFrame, aPoint, aFlags);
|
||||
}
|
||||
return FrameTarget(aFrame, false, false);
|
||||
}
|
||||
@ -3447,7 +3456,8 @@ nsIFrame::ContentOffsets nsIFrame::GetContentOffsetsFromPoint(nsPoint aPoint,
|
||||
|
||||
nsPoint adjustedPoint = aPoint + this->GetOffsetTo(adjustedFrame);
|
||||
|
||||
FrameTarget closest = GetSelectionClosestFrame(adjustedFrame, adjustedPoint);
|
||||
FrameTarget closest =
|
||||
GetSelectionClosestFrame(adjustedFrame, adjustedPoint, aFlags);
|
||||
|
||||
if (closest.emptyBlock) {
|
||||
ContentOffsets offsets;
|
||||
@ -5833,7 +5843,7 @@ nsIFrame::GetExtremeCaretPosition(bool aStart)
|
||||
{
|
||||
CaretPosition result;
|
||||
|
||||
FrameTarget targetFrame = DrillDownToSelectionFrame(this, !aStart);
|
||||
FrameTarget targetFrame = DrillDownToSelectionFrame(this, !aStart, 0);
|
||||
FrameContentRange range = GetRangeForFrame(targetFrame.frame);
|
||||
result.mResultContent = range.content;
|
||||
result.mContentOffset = aStart ? range.start : range.end;
|
||||
@ -6284,7 +6294,7 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos)
|
||||
if (!baseFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
FrameTarget targetFrame = DrillDownToSelectionFrame(baseFrame,
|
||||
endOfLine);
|
||||
endOfLine, 0);
|
||||
FrameContentRange range = GetRangeForFrame(targetFrame.frame);
|
||||
aPos->mResultContent = range.content;
|
||||
aPos->mContentOffset = endOfLine ? range.end : range.start;
|
||||
|
Loading…
Reference in New Issue
Block a user