* 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:
parent
680a35bbdb
commit
f0c3c996cd
@ -109,7 +109,9 @@ View::View(IntRect frame, IntPoint scrollingOffset, const char* name,
|
||||
|
||||
fLocalClipping((BRect)Bounds()),
|
||||
fScreenClipping(),
|
||||
fScreenClippingValid(false)
|
||||
fScreenClippingValid(false),
|
||||
fUserClipping(NULL),
|
||||
fScreenAndUserClipping(NULL)
|
||||
{
|
||||
if (fDrawState)
|
||||
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
|
||||
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
|
||||
// the other way arround but it doesn't matter)
|
||||
// the reason for this is that we are not supposed to visually
|
||||
// copy children in the source rect and neither to copy onto
|
||||
// children in the destination rect...
|
||||
copyRegion->Set((clipping_rect)visibleSrc);
|
||||
copyRegion->IntersectWith(&ScreenClipping(&windowContentClipping));
|
||||
// note that fScreenClipping is used directly from hereon
|
||||
copyRegion->IntersectWith(&ScreenAndUserClipping(&windowContentClipping));
|
||||
// note that fScreenAndUserClipping is used directly from hereon
|
||||
// because it is now up to date
|
||||
|
||||
copyRegion->OffsetBy(-xOffset, -yOffset);
|
||||
copyRegion->IntersectWith(&fScreenClipping);
|
||||
copyRegion->IntersectWith(fScreenAndUserClipping);
|
||||
|
||||
// do the actual blit
|
||||
fWindow->CopyContents(copyRegion, xOffset, yOffset);
|
||||
@ -1155,7 +1157,7 @@ View::CopyBits(IntRect src, IntRect dst, BRegion& windowContentClipping)
|
||||
// exclude the part that we could copy
|
||||
dirty->Exclude(copyRegion);
|
||||
|
||||
dirty->IntersectWith(&fScreenClipping);
|
||||
dirty->IntersectWith(fScreenAndUserClipping);
|
||||
fWindow->MarkContentDirty(*dirty);
|
||||
|
||||
fWindow->RecycleRegion(dirty);
|
||||
@ -1242,7 +1244,8 @@ View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
|
||||
if (fViewBitmap != NULL || fViewColor != B_TRANSPARENT_COLOR) {
|
||||
// we can only draw within our own area
|
||||
BRegion* redraw = fWindow->GetRegion(ScreenClipping(windowContentClipping));
|
||||
BRegion* redraw = fWindow->GetRegion(
|
||||
_ScreenClipping(windowContentClipping));
|
||||
if (!redraw)
|
||||
return;
|
||||
// add the current clipping
|
||||
@ -1478,7 +1481,7 @@ View::AddTokensForViewsInRegion(BMessage* message, BRegion& region,
|
||||
if (!fVisible)
|
||||
return;
|
||||
|
||||
if (region.Intersects(ScreenClipping(windowContentClipping).Frame()))
|
||||
if (region.Intersects(_ScreenClipping(windowContentClipping).Frame()))
|
||||
message->AddInt32("_token", fToken);
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
if (region.Intersects(ScreenClipping(windowContentClipping).Frame()))
|
||||
if (region.Intersects(_ScreenClipping(windowContentClipping).Frame()))
|
||||
link.Attach<int32>(fToken);
|
||||
|
||||
for (View* child = FirstChild(); child; child = child->NextSibling()) {
|
||||
@ -1525,6 +1528,19 @@ View::PrintToStream() const
|
||||
printf(" fScreenClipping:\n");
|
||||
fScreenClipping.PrintToStream();
|
||||
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(" user clipping: %d\n", fDrawState->HasClipping());
|
||||
BPoint origin = fDrawState->CombinedOrigin();
|
||||
@ -1572,45 +1588,44 @@ View::RebuildClipping(bool deep)
|
||||
// hand, views for which this feature is actually used will
|
||||
// probably not have any children, so it is not that expensive
|
||||
// after all
|
||||
BRegion* screenUserClipping = fWindow->GetRegion();
|
||||
if (!screenUserClipping)
|
||||
if (fUserClipping == NULL) {
|
||||
fUserClipping = new (nothrow) BRegion;
|
||||
if (fUserClipping == NULL)
|
||||
return;
|
||||
fDrawState->GetCombinedClippingRegion(screenUserClipping);
|
||||
fLocalClipping.IntersectWith(screenUserClipping);
|
||||
fWindow->RecycleRegion(screenUserClipping);
|
||||
}
|
||||
|
||||
fDrawState->GetCombinedClippingRegion(fUserClipping);
|
||||
} else {
|
||||
delete fUserClipping;
|
||||
fUserClipping = NULL;
|
||||
}
|
||||
|
||||
delete fScreenAndUserClipping;
|
||||
fScreenAndUserClipping = NULL;
|
||||
fScreenClippingValid = false;
|
||||
}
|
||||
|
||||
|
||||
BRegion&
|
||||
View::ScreenClipping(BRegion* windowContentClipping, bool force) const
|
||||
View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const
|
||||
{
|
||||
if (!fScreenClippingValid || force) {
|
||||
fScreenClipping = fLocalClipping;
|
||||
ConvertToScreen(&fScreenClipping);
|
||||
// no user clipping - return screen clipping directly
|
||||
if (fUserClipping == NULL)
|
||||
return _ScreenClipping(windowContentClipping, force);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
// combined screen and user clipping already valid
|
||||
if (fScreenAndUserClipping != NULL)
|
||||
return *fScreenAndUserClipping;
|
||||
|
||||
fScreenClipping.IntersectWith(windowContentClipping);
|
||||
fScreenClippingValid = true;
|
||||
}
|
||||
//printf("###View(%s)::ScreenClipping():\n", Name());
|
||||
//fScreenClipping.PrintToStream();
|
||||
// build a new combined user and screen clipping
|
||||
fScreenAndUserClipping = new (nothrow) BRegion(*fUserClipping);
|
||||
if (fScreenAndUserClipping == NULL)
|
||||
return fScreenClipping;
|
||||
|
||||
ConvertToScreen(fScreenAndUserClipping);
|
||||
fScreenAndUserClipping->IntersectWith(
|
||||
&_ScreenClipping(windowContentClipping, force));
|
||||
return *fScreenAndUserClipping;
|
||||
}
|
||||
|
||||
|
||||
@ -1633,6 +1648,8 @@ View::InvalidateScreenClipping()
|
||||
// if (!fScreenClippingValid)
|
||||
// return;
|
||||
|
||||
delete fScreenAndUserClipping;
|
||||
fScreenAndUserClipping = NULL;
|
||||
fScreenClippingValid = false;
|
||||
// invalidate the childrens screen clipping as well
|
||||
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
|
||||
View::_MoveScreenClipping(int32 x, int32 y, bool deep)
|
||||
{
|
||||
if (fScreenClippingValid)
|
||||
if (fScreenClippingValid) {
|
||||
fScreenClipping.OffsetBy(x, y);
|
||||
delete fScreenAndUserClipping;
|
||||
fScreenAndUserClipping = NULL;
|
||||
}
|
||||
|
||||
if (deep) {
|
||||
// move the childrens screen clipping as well
|
||||
|
@ -225,11 +225,17 @@ class View {
|
||||
|
||||
// clipping
|
||||
void RebuildClipping(bool deep);
|
||||
BRegion& ScreenClipping(BRegion* windowContentClipping,
|
||||
BRegion& ScreenAndUserClipping(
|
||||
BRegion* windowContentClipping,
|
||||
bool force = false) const;
|
||||
void InvalidateScreenClipping();
|
||||
inline bool IsScreenClippingValid() const
|
||||
{ return fScreenClippingValid; }
|
||||
{
|
||||
return fScreenClippingValid
|
||||
&& (fUserClipping == NULL
|
||||
|| (fUserClipping != NULL
|
||||
&& fScreenAndUserClipping != NULL));
|
||||
}
|
||||
|
||||
// debugging
|
||||
void PrintToStream() const;
|
||||
@ -239,6 +245,8 @@ class View {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
BRegion& _ScreenClipping(BRegion* windowContentClipping,
|
||||
bool force = false) const;
|
||||
void _MoveScreenClipping(int32 x, int32 y,
|
||||
bool deep);
|
||||
Overlay* _Overlay() const;
|
||||
@ -285,6 +293,9 @@ class View {
|
||||
|
||||
mutable BRegion fScreenClipping;
|
||||
mutable bool fScreenClippingValid;
|
||||
|
||||
BRegion* fUserClipping;
|
||||
mutable BRegion* fScreenAndUserClipping;
|
||||
};
|
||||
|
||||
#endif // VIEW_H
|
||||
|
@ -581,7 +581,7 @@ Window::GetEffectiveDrawingRegion(View* view, BRegion& region)
|
||||
if (!fContentRegionValid)
|
||||
_UpdateContentRegion();
|
||||
|
||||
region.IntersectWith(&view->ScreenClipping(&fContentRegion));
|
||||
region.IntersectWith(&view->ScreenAndUserClipping(&fContentRegion));
|
||||
}
|
||||
|
||||
|
||||
@ -706,7 +706,8 @@ Window::InvalidateView(View* view, BRegion& viewRegion)
|
||||
view->ConvertToScreen(&viewRegion);
|
||||
viewRegion.IntersectWith(&VisibleContentRegion());
|
||||
if (viewRegion.CountRects() > 0) {
|
||||
viewRegion.IntersectWith(&view->ScreenClipping(&fContentRegion));
|
||||
viewRegion.IntersectWith(
|
||||
&view->ScreenAndUserClipping(&fContentRegion));
|
||||
|
||||
//fDrawingEngine->FillRegion(viewRegion, rgb_color{ 0, 255, 0, 255 });
|
||||
//snooze(10000);
|
||||
|
@ -325,7 +325,7 @@ WorkspacesView::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
BRegion* windowContentClipping, bool deep)
|
||||
{
|
||||
// we can only draw within our own area
|
||||
BRegion redraw(ScreenClipping(windowContentClipping));
|
||||
BRegion redraw(ScreenAndUserClipping(windowContentClipping));
|
||||
// add the current clipping
|
||||
redraw.IntersectWith(effectiveClipping);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user