Fix calculation of scrollbar widths for laying out fixed-position frames. Also make sure that the fixed frames are reflowed if scrollbar widths change. Fix for bug 5195. r=evaughan,sr=attinasi

This commit is contained in:
roc+%cs.cmu.edu 2001-04-17 01:45:38 +00:00
Родитель c302defdcd
Коммит b90fd2dc64
5 изменённых файлов: 141 добавлений и 64 удалений

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

@ -1134,7 +1134,8 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
if (mHasVerticalScrollbar)
AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight);
nsRect oldScrollAreaBounds;
mScrollAreaBox->GetClientRect(oldScrollAreaBounds);
// layout our the scroll area
LayoutBox(aState, mScrollAreaBox, scrollAreaRect);
@ -1347,7 +1348,34 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
needsLayout = PR_FALSE;
}
// may need to update fixed position children of the viewport,
// if the client area changed size because of some dirty reflow
// (if the reflow is initial or resize, the fixed children will
// be re-laid out anyway)
if ((oldScrollAreaBounds.width != scrollAreaRect.width
|| oldScrollAreaBounds.height != scrollAreaRect.height)
&& nsBoxLayoutState::Dirty == aState.GetLayoutReason()) {
nsIFrame* parentFrame;
mOuter->GetParent(&parentFrame);
if (parentFrame) {
nsCOMPtr<nsIAtom> parentFrameType;
parentFrame->GetFrameType(getter_AddRefs(parentFrameType));
if (parentFrameType.get() == nsLayoutAtoms::viewportFrame) {
// Usually there are no fixed children, so don't do anything unless there's
// at least one fixed child
nsIFrame* child;
if (NS_SUCCEEDED(parentFrame->FirstChild(mOuter->mPresContext,
nsLayoutAtoms::fixedList, &child)) && child) {
nsCOMPtr<nsIPresShell> presShell;
mOuter->mPresContext->GetShell(getter_AddRefs(presShell));
// force a reflow of the fixed children
nsFrame::CreateAndPostReflowCommand(presShell, parentFrame,
nsIReflowCommand::UserDefined, nsnull, nsnull, nsLayoutAtoms::fixedList);
}
}
}
}
return NS_OK;
}

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

@ -25,7 +25,7 @@
#include "nsHTMLIIDs.h"
#include "nsLayoutAtoms.h"
#include "nsIViewManager.h"
#include "nsIScrollableView.h"
#include "nsIScrollableFrame.h"
#include "nsIDeviceContext.h"
#include "nsIPresContext.h"
#include "nsIReflowCommand.h"
@ -310,30 +310,18 @@ ViewportFrame::CalculateFixedContainingBlockSize(nsIPresContext* aPresC
// Get our prinicpal child frame and see if we're scrollable
nsIFrame* kidFrame = mFrames.FirstChild();
nsIView* kidView;
nsCOMPtr<nsIScrollableFrame> scrollingFrame(do_QueryInterface(kidFrame));
kidFrame->GetView(aPresContext, &kidView);
if (nsnull != kidView) {
nsIScrollableView* scrollingView;
if (NS_SUCCEEDED(kidView->QueryInterface(NS_GET_IID(nsIScrollableView), (void**)&scrollingView))) {
// Get the scrollbar dimensions
float sbWidth, sbHeight;
nsCOMPtr<nsIDeviceContext> dc;
aPresContext->GetDeviceContext(getter_AddRefs(dc));
dc->GetScrollBarDimensions(sbWidth, sbHeight);
// See if the scrollbars are visible
PRBool vertSBVisible, horzSBVisible;
scrollingView->GetScrollbarVisibility(&vertSBVisible, &horzSBVisible);
if (vertSBVisible) {
aWidth -= NSToCoordRound(sbWidth);
}
if (horzSBVisible) {
aHeight -= NSToCoordRound(sbHeight);
}
if (scrollingFrame) {
nscoord sbWidth = 0, sbHeight = 0;
PRBool sbHVisible = PR_FALSE, sbVVisible = PR_FALSE;
scrollingFrame->GetScrollbarSizes(aPresContext, &sbWidth, &sbHeight);
scrollingFrame->GetScrollbarVisibility(aPresContext, &sbVVisible, &sbHVisible);
if (sbVVisible) {
aWidth -= sbWidth;
}
if (sbHVisible) {
aHeight -= sbHeight;
}
}
}
@ -402,9 +390,6 @@ void
ViewportFrame::ReflowFixedFrames(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState) const
{
NS_PRECONDITION(eReflowReason_Incremental != aReflowState.reason,
"unexpected reflow reason");
// Calculate how much room is available for the fixed items. That means
// determining if the viewport is scrollable and whether the vertical and/or
// horizontal scrollbars are visible
@ -490,8 +475,17 @@ ViewportFrame::Reflow(nsIPresContext* aPresContext,
nsIFrame* nextFrame = nsnull;
PRBool isHandled = PR_FALSE;
// Check for an incremental reflow
if (eReflowReason_Incremental == aReflowState.reason) {
nsIReflowCommand::ReflowType reflowType = nsIReflowCommand::ContentChanged;
if (aReflowState.reflowCommand) {
aReflowState.reflowCommand->GetType(reflowType);
}
if (reflowType == nsIReflowCommand::UserDefined) {
// Reflow the fixed frames to account for changed scrolled area size
ReflowFixedFrames(aPresContext, aReflowState);
isHandled = PR_TRUE;
// Otherwise check for an incremental reflow
} else if (eReflowReason_Incremental == aReflowState.reason) {
// See if we're the target frame
nsIFrame* targetFrame;
aReflowState.reflowCommand->GetTarget(targetFrame);

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

@ -1134,7 +1134,8 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
if (mHasVerticalScrollbar)
AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight);
nsRect oldScrollAreaBounds;
mScrollAreaBox->GetClientRect(oldScrollAreaBounds);
// layout our the scroll area
LayoutBox(aState, mScrollAreaBox, scrollAreaRect);
@ -1347,7 +1348,34 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
needsLayout = PR_FALSE;
}
// may need to update fixed position children of the viewport,
// if the client area changed size because of some dirty reflow
// (if the reflow is initial or resize, the fixed children will
// be re-laid out anyway)
if ((oldScrollAreaBounds.width != scrollAreaRect.width
|| oldScrollAreaBounds.height != scrollAreaRect.height)
&& nsBoxLayoutState::Dirty == aState.GetLayoutReason()) {
nsIFrame* parentFrame;
mOuter->GetParent(&parentFrame);
if (parentFrame) {
nsCOMPtr<nsIAtom> parentFrameType;
parentFrame->GetFrameType(getter_AddRefs(parentFrameType));
if (parentFrameType.get() == nsLayoutAtoms::viewportFrame) {
// Usually there are no fixed children, so don't do anything unless there's
// at least one fixed child
nsIFrame* child;
if (NS_SUCCEEDED(parentFrame->FirstChild(mOuter->mPresContext,
nsLayoutAtoms::fixedList, &child)) && child) {
nsCOMPtr<nsIPresShell> presShell;
mOuter->mPresContext->GetShell(getter_AddRefs(presShell));
// force a reflow of the fixed children
nsFrame::CreateAndPostReflowCommand(presShell, parentFrame,
nsIReflowCommand::UserDefined, nsnull, nsnull, nsLayoutAtoms::fixedList);
}
}
}
}
return NS_OK;
}

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

@ -646,6 +646,9 @@ nsScrollFrame::Reflow(nsIPresContext* aPresContext,
nsIFrame* targetFrame;
nsIFrame* nextFrame;
nsRect oldKidBounds;
kidFrame->GetRect(oldKidBounds);
// Special handling for incremental reflow
if (eReflowReason_Incremental == aReflowState.reason) {
// See whether we're the target of the reflow command
@ -859,6 +862,36 @@ nsScrollFrame::Reflow(nsIPresContext* aPresContext,
}
}
nsRect newKidBounds;
kidFrame->GetRect(newKidBounds);
// may need to update fixed position children of the viewport,
// if the client area changed size
if ((oldKidBounds.width != newKidBounds.width
|| oldKidBounds.height != newKidBounds.height)
&& eReflowReason_Incremental == aReflowState.reason) {
nsIFrame* parentFrame;
GetParent(&parentFrame);
if (parentFrame) {
nsCOMPtr<nsIAtom> parentFrameType;
parentFrame->GetFrameType(getter_AddRefs(parentFrameType));
if (parentFrameType.get() == nsLayoutAtoms::viewportFrame) {
// Usually there are no fixed children, so don't do anything unless there's
// at least one fixed child
nsIFrame* child;
if (NS_SUCCEEDED(parentFrame->FirstChild(aPresContext,
nsLayoutAtoms::fixedList, &child)) && child) {
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
// force a reflow of the fixed children
nsFrame::CreateAndPostReflowCommand(presShell, parentFrame,
nsIReflowCommand::UserDefined, nsnull, nsnull, nsLayoutAtoms::fixedList);
}
}
}
}
if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL)
{

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

@ -25,7 +25,7 @@
#include "nsHTMLIIDs.h"
#include "nsLayoutAtoms.h"
#include "nsIViewManager.h"
#include "nsIScrollableView.h"
#include "nsIScrollableFrame.h"
#include "nsIDeviceContext.h"
#include "nsIPresContext.h"
#include "nsIReflowCommand.h"
@ -310,30 +310,18 @@ ViewportFrame::CalculateFixedContainingBlockSize(nsIPresContext* aPresC
// Get our prinicpal child frame and see if we're scrollable
nsIFrame* kidFrame = mFrames.FirstChild();
nsIView* kidView;
nsCOMPtr<nsIScrollableFrame> scrollingFrame(do_QueryInterface(kidFrame));
kidFrame->GetView(aPresContext, &kidView);
if (nsnull != kidView) {
nsIScrollableView* scrollingView;
if (NS_SUCCEEDED(kidView->QueryInterface(NS_GET_IID(nsIScrollableView), (void**)&scrollingView))) {
// Get the scrollbar dimensions
float sbWidth, sbHeight;
nsCOMPtr<nsIDeviceContext> dc;
aPresContext->GetDeviceContext(getter_AddRefs(dc));
dc->GetScrollBarDimensions(sbWidth, sbHeight);
// See if the scrollbars are visible
PRBool vertSBVisible, horzSBVisible;
scrollingView->GetScrollbarVisibility(&vertSBVisible, &horzSBVisible);
if (vertSBVisible) {
aWidth -= NSToCoordRound(sbWidth);
}
if (horzSBVisible) {
aHeight -= NSToCoordRound(sbHeight);
}
if (scrollingFrame) {
nscoord sbWidth = 0, sbHeight = 0;
PRBool sbHVisible = PR_FALSE, sbVVisible = PR_FALSE;
scrollingFrame->GetScrollbarSizes(aPresContext, &sbWidth, &sbHeight);
scrollingFrame->GetScrollbarVisibility(aPresContext, &sbVVisible, &sbHVisible);
if (sbVVisible) {
aWidth -= sbWidth;
}
if (sbHVisible) {
aHeight -= sbHeight;
}
}
}
@ -402,9 +390,6 @@ void
ViewportFrame::ReflowFixedFrames(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState) const
{
NS_PRECONDITION(eReflowReason_Incremental != aReflowState.reason,
"unexpected reflow reason");
// Calculate how much room is available for the fixed items. That means
// determining if the viewport is scrollable and whether the vertical and/or
// horizontal scrollbars are visible
@ -490,8 +475,17 @@ ViewportFrame::Reflow(nsIPresContext* aPresContext,
nsIFrame* nextFrame = nsnull;
PRBool isHandled = PR_FALSE;
// Check for an incremental reflow
if (eReflowReason_Incremental == aReflowState.reason) {
nsIReflowCommand::ReflowType reflowType = nsIReflowCommand::ContentChanged;
if (aReflowState.reflowCommand) {
aReflowState.reflowCommand->GetType(reflowType);
}
if (reflowType == nsIReflowCommand::UserDefined) {
// Reflow the fixed frames to account for changed scrolled area size
ReflowFixedFrames(aPresContext, aReflowState);
isHandled = PR_TRUE;
// Otherwise check for an incremental reflow
} else if (eReflowReason_Incremental == aReflowState.reason) {
// See if we're the target frame
nsIFrame* targetFrame;
aReflowState.reflowCommand->GetTarget(targetFrame);