* Decouple local and user clipping into normal local clipping and a user
clipping region pointer. * Provide _ScreenClipping() that only includes local and screen clipping but not user clipping. * Provide ScreenAndUserClipping() that returns screen clipping if no user clipping is present, or returns a combined region that is then cached. * Adapt all places where the former methods are used and decide which one to use depending on the relevance of user clipping. User clipping is now ignored for background clearing and when determining whether or not to call Draw() on a view. This should make Haiku behaviourally compatible with BeOS (confirmed by the ClippingAndRedraw test app) and should also fix the Firefox redraw issues. Stephan please review! git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25854 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+88
-39
@@ -109,7 +109,9 @@ View::View(IntRect frame, IntPoint scrollingOffset, const char* name,
|
|||||||
|
|
||||||
fLocalClipping((BRect)Bounds()),
|
fLocalClipping((BRect)Bounds()),
|
||||||
fScreenClipping(),
|
fScreenClipping(),
|
||||||
fScreenClippingValid(false)
|
fScreenClippingValid(false),
|
||||||
|
fUserClipping(NULL),
|
||||||
|
fScreenAndUserClipping(NULL)
|
||||||
{
|
{
|
||||||
if (fDrawState)
|
if (fDrawState)
|
||||||
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
|
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
|
||||||
@@ -1121,19 +1123,19 @@ View::CopyBits(IntRect src, IntRect dst, BRegion& windowContentClipping)
|
|||||||
// move src rect to destination here for efficiency reasons
|
// move src rect to destination here for efficiency reasons
|
||||||
visibleSrc.OffsetBy(xOffset, yOffset);
|
visibleSrc.OffsetBy(xOffset, yOffset);
|
||||||
|
|
||||||
// we need to interstect the copyRegion too times, onces
|
// we need to interstect the copyRegion two times, onces
|
||||||
// at the source and once at the destination (here done
|
// at the source and once at the destination (here done
|
||||||
// the other way arround but it doesn't matter)
|
// the other way arround but it doesn't matter)
|
||||||
// the reason for this is that we are not supposed to visually
|
// the reason for this is that we are not supposed to visually
|
||||||
// copy children in the source rect and neither to copy onto
|
// copy children in the source rect and neither to copy onto
|
||||||
// children in the destination rect...
|
// children in the destination rect...
|
||||||
copyRegion->Set((clipping_rect)visibleSrc);
|
copyRegion->Set((clipping_rect)visibleSrc);
|
||||||
copyRegion->IntersectWith(&ScreenClipping(&windowContentClipping));
|
copyRegion->IntersectWith(&ScreenAndUserClipping(&windowContentClipping));
|
||||||
// note that fScreenClipping is used directly from hereon
|
// note that fScreenAndUserClipping is used directly from hereon
|
||||||
// because it is now up to date
|
// because it is now up to date
|
||||||
|
|
||||||
copyRegion->OffsetBy(-xOffset, -yOffset);
|
copyRegion->OffsetBy(-xOffset, -yOffset);
|
||||||
copyRegion->IntersectWith(&fScreenClipping);
|
copyRegion->IntersectWith(fScreenAndUserClipping);
|
||||||
|
|
||||||
// do the actual blit
|
// do the actual blit
|
||||||
fWindow->CopyContents(copyRegion, xOffset, yOffset);
|
fWindow->CopyContents(copyRegion, xOffset, yOffset);
|
||||||
@@ -1155,7 +1157,7 @@ View::CopyBits(IntRect src, IntRect dst, BRegion& windowContentClipping)
|
|||||||
// exclude the part that we could copy
|
// exclude the part that we could copy
|
||||||
dirty->Exclude(copyRegion);
|
dirty->Exclude(copyRegion);
|
||||||
|
|
||||||
dirty->IntersectWith(&fScreenClipping);
|
dirty->IntersectWith(fScreenAndUserClipping);
|
||||||
fWindow->MarkContentDirty(*dirty);
|
fWindow->MarkContentDirty(*dirty);
|
||||||
|
|
||||||
fWindow->RecycleRegion(dirty);
|
fWindow->RecycleRegion(dirty);
|
||||||
@@ -1242,7 +1244,8 @@ View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
|||||||
|
|
||||||
if (fViewBitmap != NULL || fViewColor != B_TRANSPARENT_COLOR) {
|
if (fViewBitmap != NULL || fViewColor != B_TRANSPARENT_COLOR) {
|
||||||
// we can only draw within our own area
|
// we can only draw within our own area
|
||||||
BRegion* redraw = fWindow->GetRegion(ScreenClipping(windowContentClipping));
|
BRegion* redraw = fWindow->GetRegion(
|
||||||
|
_ScreenClipping(windowContentClipping));
|
||||||
if (!redraw)
|
if (!redraw)
|
||||||
return;
|
return;
|
||||||
// add the current clipping
|
// add the current clipping
|
||||||
@@ -1478,7 +1481,7 @@ View::AddTokensForViewsInRegion(BMessage* message, BRegion& region,
|
|||||||
if (!fVisible)
|
if (!fVisible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (region.Intersects(ScreenClipping(windowContentClipping).Frame()))
|
if (region.Intersects(_ScreenClipping(windowContentClipping).Frame()))
|
||||||
message->AddInt32("_token", fToken);
|
message->AddInt32("_token", fToken);
|
||||||
|
|
||||||
for (View* child = FirstChild(); child; child = child->NextSibling()) {
|
for (View* child = FirstChild(); child; child = child->NextSibling()) {
|
||||||
@@ -1500,7 +1503,7 @@ View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region,
|
|||||||
if (!region.Intersects((clipping_rect)screenBounds))
|
if (!region.Intersects((clipping_rect)screenBounds))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (region.Intersects(ScreenClipping(windowContentClipping).Frame()))
|
if (region.Intersects(_ScreenClipping(windowContentClipping).Frame()))
|
||||||
link.Attach<int32>(fToken);
|
link.Attach<int32>(fToken);
|
||||||
|
|
||||||
for (View* child = FirstChild(); child; child = child->NextSibling()) {
|
for (View* child = FirstChild(); child; child = child->NextSibling()) {
|
||||||
@@ -1525,6 +1528,19 @@ View::PrintToStream() const
|
|||||||
printf(" fScreenClipping:\n");
|
printf(" fScreenClipping:\n");
|
||||||
fScreenClipping.PrintToStream();
|
fScreenClipping.PrintToStream();
|
||||||
printf(" valid: %d\n", fScreenClippingValid);
|
printf(" valid: %d\n", fScreenClippingValid);
|
||||||
|
|
||||||
|
printf(" fUserClipping:\n");
|
||||||
|
if (fUserClipping != NULL)
|
||||||
|
fUserClipping->PrintToStream();
|
||||||
|
else
|
||||||
|
printf(" none\n");
|
||||||
|
|
||||||
|
printf(" fScreenAndUserClipping:\n");
|
||||||
|
if (fScreenAndUserClipping != NULL)
|
||||||
|
fScreenAndUserClipping->PrintToStream();
|
||||||
|
else
|
||||||
|
printf(" invalid\n");
|
||||||
|
|
||||||
printf(" state:\n");
|
printf(" state:\n");
|
||||||
printf(" user clipping: %d\n", fDrawState->HasClipping());
|
printf(" user clipping: %d\n", fDrawState->HasClipping());
|
||||||
BPoint origin = fDrawState->CombinedOrigin();
|
BPoint origin = fDrawState->CombinedOrigin();
|
||||||
@@ -1572,45 +1588,44 @@ View::RebuildClipping(bool deep)
|
|||||||
// hand, views for which this feature is actually used will
|
// hand, views for which this feature is actually used will
|
||||||
// probably not have any children, so it is not that expensive
|
// probably not have any children, so it is not that expensive
|
||||||
// after all
|
// after all
|
||||||
BRegion* screenUserClipping = fWindow->GetRegion();
|
if (fUserClipping == NULL) {
|
||||||
if (!screenUserClipping)
|
fUserClipping = new (nothrow) BRegion;
|
||||||
return;
|
if (fUserClipping == NULL)
|
||||||
fDrawState->GetCombinedClippingRegion(screenUserClipping);
|
return;
|
||||||
fLocalClipping.IntersectWith(screenUserClipping);
|
}
|
||||||
fWindow->RecycleRegion(screenUserClipping);
|
|
||||||
|
fDrawState->GetCombinedClippingRegion(fUserClipping);
|
||||||
|
} else {
|
||||||
|
delete fUserClipping;
|
||||||
|
fUserClipping = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete fScreenAndUserClipping;
|
||||||
|
fScreenAndUserClipping = NULL;
|
||||||
fScreenClippingValid = false;
|
fScreenClippingValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BRegion&
|
BRegion&
|
||||||
View::ScreenClipping(BRegion* windowContentClipping, bool force) const
|
View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const
|
||||||
{
|
{
|
||||||
if (!fScreenClippingValid || force) {
|
// no user clipping - return screen clipping directly
|
||||||
fScreenClipping = fLocalClipping;
|
if (fUserClipping == NULL)
|
||||||
ConvertToScreen(&fScreenClipping);
|
return _ScreenClipping(windowContentClipping, force);
|
||||||
|
|
||||||
// see if parts of our bounds are hidden underneath
|
// combined screen and user clipping already valid
|
||||||
// the parent, the local clipping does not account for this
|
if (fScreenAndUserClipping != NULL)
|
||||||
IntRect clippedBounds = Bounds();
|
return *fScreenAndUserClipping;
|
||||||
ConvertToVisibleInTopView(&clippedBounds);
|
|
||||||
if (clippedBounds.Width() < fScreenClipping.Frame().Width()
|
|
||||||
|| clippedBounds.Height() < fScreenClipping.Frame().Height()) {
|
|
||||||
BRegion* temp = fWindow->GetRegion();
|
|
||||||
if (temp) {
|
|
||||||
temp->Set((clipping_rect)clippedBounds);
|
|
||||||
fScreenClipping.IntersectWith(temp);
|
|
||||||
fWindow->RecycleRegion(temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fScreenClipping.IntersectWith(windowContentClipping);
|
// build a new combined user and screen clipping
|
||||||
fScreenClippingValid = true;
|
fScreenAndUserClipping = new (nothrow) BRegion(*fUserClipping);
|
||||||
}
|
if (fScreenAndUserClipping == NULL)
|
||||||
//printf("###View(%s)::ScreenClipping():\n", Name());
|
return fScreenClipping;
|
||||||
//fScreenClipping.PrintToStream();
|
|
||||||
return fScreenClipping;
|
ConvertToScreen(fScreenAndUserClipping);
|
||||||
|
fScreenAndUserClipping->IntersectWith(
|
||||||
|
&_ScreenClipping(windowContentClipping, force));
|
||||||
|
return *fScreenAndUserClipping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1633,6 +1648,8 @@ View::InvalidateScreenClipping()
|
|||||||
// if (!fScreenClippingValid)
|
// if (!fScreenClippingValid)
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
|
delete fScreenAndUserClipping;
|
||||||
|
fScreenAndUserClipping = NULL;
|
||||||
fScreenClippingValid = false;
|
fScreenClippingValid = false;
|
||||||
// invalidate the childrens screen clipping as well
|
// invalidate the childrens screen clipping as well
|
||||||
for (View* child = FirstChild(); child; child = child->NextSibling()) {
|
for (View* child = FirstChild(); child; child = child->NextSibling()) {
|
||||||
@@ -1641,11 +1658,43 @@ View::InvalidateScreenClipping()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRegion&
|
||||||
|
View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
|
||||||
|
{
|
||||||
|
if (!fScreenClippingValid || force) {
|
||||||
|
fScreenClipping = fLocalClipping;
|
||||||
|
ConvertToScreen(&fScreenClipping);
|
||||||
|
|
||||||
|
// see if parts of our bounds are hidden underneath
|
||||||
|
// the parent, the local clipping does not account for this
|
||||||
|
IntRect clippedBounds = Bounds();
|
||||||
|
ConvertToVisibleInTopView(&clippedBounds);
|
||||||
|
if (clippedBounds.Width() < fScreenClipping.Frame().Width()
|
||||||
|
|| clippedBounds.Height() < fScreenClipping.Frame().Height()) {
|
||||||
|
BRegion* temp = fWindow->GetRegion();
|
||||||
|
if (temp) {
|
||||||
|
temp->Set((clipping_rect)clippedBounds);
|
||||||
|
fScreenClipping.IntersectWith(temp);
|
||||||
|
fWindow->RecycleRegion(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fScreenClipping.IntersectWith(windowContentClipping);
|
||||||
|
fScreenClippingValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fScreenClipping;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
View::_MoveScreenClipping(int32 x, int32 y, bool deep)
|
View::_MoveScreenClipping(int32 x, int32 y, bool deep)
|
||||||
{
|
{
|
||||||
if (fScreenClippingValid)
|
if (fScreenClippingValid) {
|
||||||
fScreenClipping.OffsetBy(x, y);
|
fScreenClipping.OffsetBy(x, y);
|
||||||
|
delete fScreenAndUserClipping;
|
||||||
|
fScreenAndUserClipping = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (deep) {
|
if (deep) {
|
||||||
// move the childrens screen clipping as well
|
// move the childrens screen clipping as well
|
||||||
|
|||||||
+13
-2
@@ -225,11 +225,17 @@ class View {
|
|||||||
|
|
||||||
// clipping
|
// clipping
|
||||||
void RebuildClipping(bool deep);
|
void RebuildClipping(bool deep);
|
||||||
BRegion& ScreenClipping(BRegion* windowContentClipping,
|
BRegion& ScreenAndUserClipping(
|
||||||
|
BRegion* windowContentClipping,
|
||||||
bool force = false) const;
|
bool force = false) const;
|
||||||
void InvalidateScreenClipping();
|
void InvalidateScreenClipping();
|
||||||
inline bool IsScreenClippingValid() const
|
inline bool IsScreenClippingValid() const
|
||||||
{ return fScreenClippingValid; }
|
{
|
||||||
|
return fScreenClippingValid
|
||||||
|
&& (fUserClipping == NULL
|
||||||
|
|| (fUserClipping != NULL
|
||||||
|
&& fScreenAndUserClipping != NULL));
|
||||||
|
}
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
void PrintToStream() const;
|
void PrintToStream() const;
|
||||||
@@ -239,6 +245,8 @@ class View {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
BRegion& _ScreenClipping(BRegion* windowContentClipping,
|
||||||
|
bool force = false) const;
|
||||||
void _MoveScreenClipping(int32 x, int32 y,
|
void _MoveScreenClipping(int32 x, int32 y,
|
||||||
bool deep);
|
bool deep);
|
||||||
Overlay* _Overlay() const;
|
Overlay* _Overlay() const;
|
||||||
@@ -285,6 +293,9 @@ class View {
|
|||||||
|
|
||||||
mutable BRegion fScreenClipping;
|
mutable BRegion fScreenClipping;
|
||||||
mutable bool fScreenClippingValid;
|
mutable bool fScreenClippingValid;
|
||||||
|
|
||||||
|
BRegion* fUserClipping;
|
||||||
|
mutable BRegion* fScreenAndUserClipping;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VIEW_H
|
#endif // VIEW_H
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ Window::GetEffectiveDrawingRegion(View* view, BRegion& region)
|
|||||||
if (!fContentRegionValid)
|
if (!fContentRegionValid)
|
||||||
_UpdateContentRegion();
|
_UpdateContentRegion();
|
||||||
|
|
||||||
region.IntersectWith(&view->ScreenClipping(&fContentRegion));
|
region.IntersectWith(&view->ScreenAndUserClipping(&fContentRegion));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -706,7 +706,8 @@ Window::InvalidateView(View* view, BRegion& viewRegion)
|
|||||||
view->ConvertToScreen(&viewRegion);
|
view->ConvertToScreen(&viewRegion);
|
||||||
viewRegion.IntersectWith(&VisibleContentRegion());
|
viewRegion.IntersectWith(&VisibleContentRegion());
|
||||||
if (viewRegion.CountRects() > 0) {
|
if (viewRegion.CountRects() > 0) {
|
||||||
viewRegion.IntersectWith(&view->ScreenClipping(&fContentRegion));
|
viewRegion.IntersectWith(
|
||||||
|
&view->ScreenAndUserClipping(&fContentRegion));
|
||||||
|
|
||||||
//fDrawingEngine->FillRegion(viewRegion, rgb_color{ 0, 255, 0, 255 });
|
//fDrawingEngine->FillRegion(viewRegion, rgb_color{ 0, 255, 0, 255 });
|
||||||
//snooze(10000);
|
//snooze(10000);
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ WorkspacesView::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
|||||||
BRegion* windowContentClipping, bool deep)
|
BRegion* windowContentClipping, bool deep)
|
||||||
{
|
{
|
||||||
// we can only draw within our own area
|
// we can only draw within our own area
|
||||||
BRegion redraw(ScreenClipping(windowContentClipping));
|
BRegion redraw(ScreenAndUserClipping(windowContentClipping));
|
||||||
// add the current clipping
|
// add the current clipping
|
||||||
redraw.IntersectWith(effectiveClipping);
|
redraw.IntersectWith(effectiveClipping);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user