зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
c302defdcd
Коммит
b90fd2dc64
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче