Bug 297508. Allow native theme drawing to overflow the frame bounds in a reliable way by setting the frame's overflow area. Use this to work around drawing errors in some GTK2 themes. r=bryner,sr=blizzard

This commit is contained in:
roc+%cs.cmu.edu 2005-08-31 21:00:52 +00:00
Родитель 859785cbe3
Коммит 38e777c0c6
8 изменённых файлов: 104 добавлений и 4 удалений

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

@ -81,12 +81,20 @@ public:
// This method can return PR_FALSE to indicate that the CSS padding value
// should be used. Otherwise, it will fill in aResult with the desired
// padding and return PR_TRUE.
virtual PRBool GetWidgetPadding(nsIDeviceContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
nsMargin* aResult) = 0;
// This method can return PR_FALSE to indicate that no special overflow
// area is required by the native widget. Otherwise it will fill in
// aResult with the desired overflow area and return PR_TRUE.
virtual PRBool GetWidgetOverflow(nsIDeviceContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
nsRect* aResult)
{ return PR_FALSE; }
NS_IMETHOD GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame,
PRUint8 aWidgetType,
nsSize* aResult,

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

@ -866,7 +866,8 @@ nsBox::SyncLayout(nsBoxLayoutState& aState)
nsRect bounds;
if (box->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
nsRect* overflowArea = box->GetOverflowAreaProperty();
NS_ASSERTION(overflowArea, "Should have created property for overflowing frame");
NS_ASSERTION(overflowArea,
"Should have created property for overflowing frame");
bounds = *overflowArea + box->GetPosition();
} else {
bounds = box->GetRect();
@ -877,6 +878,18 @@ nsBox::SyncLayout(nsBoxLayoutState& aState)
}
}
const nsStyleDisplay* disp = GetStyleDisplay();
if (disp->mAppearance && gTheme) {
// Add in the theme's desired overflow
if (gTheme->ThemeSupportsWidget(presContext, this, disp->mAppearance)) {
nsRect r;
if (gTheme->GetWidgetOverflow(presContext->DeviceContext(), this,
disp->mAppearance, &r)) {
rect.UnionRect(rect, r);
}
}
}
FinishAndStoreOverflow(&rect, GetSize());
}

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

@ -659,9 +659,11 @@ nsSliderFrame::CurrentPositionChanged(nsPresContext* aPresContext)
// set the rect
thumbFrame->SetRect(newThumbRect);
// figure out the union of the rect so we know what to redraw
// Figure out the union of the rect so we know what to redraw.
// Combine the old and new thumb overflow areas.
nsRect changeRect;
changeRect.UnionRect(thumbRect, newThumbRect);
changeRect.UnionRect(thumbFrame->GetOverflowRect() + thumbRect.TopLeft(),
thumbFrame->GetOverflowRect() + newThumbRect.TopLeft());
// redraw just the change
Invalidate(changeRect, mRedrawImmediate);

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

@ -535,6 +535,37 @@ nsNativeThemeGTK::GetWidgetPadding(nsIDeviceContext* aContext,
return PR_FALSE;
}
PRBool
nsNativeThemeGTK::GetWidgetOverflow(nsIDeviceContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,
nsRect* aResult)
{
nsIntMargin extraSize(0,0,0,0);
// Allow an extra one pixel above and below the thumb for certain
// GTK2 themes (Ximian Industrial, Bluecurve, Misty, at least);
// see moz_gtk_scrollbar_thumb_paint in gtk2drawing.c
switch (aWidgetType) {
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
extraSize.top = extraSize.bottom = 1;
break;
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
extraSize.left = extraSize.right = 1;
break;
default:
return PR_FALSE;
}
float p2t = aContext->DevUnitsToAppUnits();
nsMargin m(NSIntPixelsToTwips(extraSize.left, p2t),
NSIntPixelsToTwips(extraSize.top, p2t),
NSIntPixelsToTwips(extraSize.right, p2t),
NSIntPixelsToTwips(extraSize.bottom, p2t));
nsRect r(nsPoint(0, 0), aFrame->GetSize());
r.Inflate(m);
*aResult = r;
return PR_TRUE;
}
NS_IMETHODIMP
nsNativeThemeGTK::GetMinimumWidgetSize(nsIRenderingContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,

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

@ -67,6 +67,11 @@ public:
PRUint8 aWidgetType,
nsMargin* aResult);
virtual NS_HIDDEN_(PRBool) GetWidgetOverflow(nsIDeviceContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
nsRect* aResult);
NS_IMETHOD GetMinimumWidgetSize(nsIRenderingContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,
nsSize* aResult, PRBool* aIsOverridable);

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

@ -741,6 +741,11 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
surrounding the scrollbar if the theme thinks that it's butted
up against the scrollbar arrows. Note the increases of the
clip rect below. */
/* Changing the cliprect is pretty bogus. This lets themes draw
outside the frame, which means we don't invalidate them
correctly. See bug 297508. But some themes do seem to need
it. So we modify the frame's overflow area to account for what
we're doing here; see nsNativeThemeGTK::GetWidgetOverflow. */
adj = gtk_range_get_adjustment(GTK_RANGE(scrollbar));
if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) {

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

@ -535,6 +535,37 @@ nsNativeThemeGTK::GetWidgetPadding(nsIDeviceContext* aContext,
return PR_FALSE;
}
PRBool
nsNativeThemeGTK::GetWidgetOverflow(nsIDeviceContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,
nsRect* aResult)
{
nsIntMargin extraSize(0,0,0,0);
// Allow an extra one pixel above and below the thumb for certain
// GTK2 themes (Ximian Industrial, Bluecurve, Misty, at least);
// see moz_gtk_scrollbar_thumb_paint in gtk2drawing.c
switch (aWidgetType) {
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
extraSize.top = extraSize.bottom = 1;
break;
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
extraSize.left = extraSize.right = 1;
break;
default:
return PR_FALSE;
}
float p2t = aContext->DevUnitsToAppUnits();
nsMargin m(NSIntPixelsToTwips(extraSize.left, p2t),
NSIntPixelsToTwips(extraSize.top, p2t),
NSIntPixelsToTwips(extraSize.right, p2t),
NSIntPixelsToTwips(extraSize.bottom, p2t));
nsRect r(nsPoint(0, 0), aFrame->GetSize());
r.Inflate(m);
*aResult = r;
return PR_TRUE;
}
NS_IMETHODIMP
nsNativeThemeGTK::GetMinimumWidgetSize(nsIRenderingContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,

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

@ -67,6 +67,11 @@ public:
PRUint8 aWidgetType,
nsMargin* aResult);
virtual NS_HIDDEN_(PRBool) GetWidgetOverflow(nsIDeviceContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
nsRect* aResult);
NS_IMETHOD GetMinimumWidgetSize(nsIRenderingContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,
nsSize* aResult, PRBool* aIsOverridable);