diff --git a/src/servers/app/Layer.cpp b/src/servers/app/Layer.cpp index 3678c78557..8f27355e24 100644 --- a/src/servers/app/Layer.cpp +++ b/src/servers/app/Layer.cpp @@ -50,6 +50,7 @@ Layer::Layer(BRect frame, const char* name, int32 token, fVisible2(), fFullVisible2(), fDirtyForRebuild(), + fDrawingRegion(), fDriver(driver), fRootLayer(NULL), @@ -421,6 +422,16 @@ Layer::SetName(const char* name) fName.SetTo(name); } +// SetUserClipping +void +Layer::SetUserClipping(const BRegion& region) +{ + fDrawState->SetClippingRegion(region); + + // rebuild clipping + _RebuildDrawingRegion(); +} + // SetFlags void Layer::SetFlags(uint32 flags) @@ -521,8 +532,6 @@ Layer::PushState() { fDrawState = fDrawState->PushState(); fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE); - - // TODO: rebuild clipping and redraw } @@ -534,10 +543,15 @@ Layer::PopState() return; } + bool rebuildClipping = fDrawState->ClippingRegion() != NULL; + fDrawState = fDrawState->PopState(); fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE); - // TODO: rebuild clipping and redraw + // rebuild clipping + // (the clipping from the popped state is not effective anymore) + if (rebuildClipping) + _RebuildDrawingRegion(); } @@ -880,21 +894,21 @@ void Layer::PruneTree(void) { - Layer* lay; - Layer* nextlay; + Layer* child; + Layer* nextChild; - lay = fFirstChild; + child = fFirstChild; fFirstChild = NULL; - while (lay != NULL) { - if (lay->fFirstChild != NULL) - lay->PruneTree(); + while (child != NULL) { + if (child->fFirstChild != NULL) + child->PruneTree(); - nextlay = lay->fNextSibling; - lay->fNextSibling = NULL; + nextChild = child->fNextSibling; + child->fNextSibling = NULL; - delete lay; - lay = nextlay; + delete child; + child = nextChild; } // Man, this thing is short. Elegant, ain't it? :P } @@ -1249,8 +1263,8 @@ Layer::_ResizeLayerFrameBy(float x, float y) // call hook function ResizedByHook(dx, dy, true); // automatic - for (Layer *lay = LastChild(); lay; lay = PreviousChild()) - lay->resize_layer_frame_by(dx, dy); + for (Layer* child = LastChild(); child; child = PreviousChild()) + child->resize_layer_frame_by(dx, dy); } } */ @@ -1281,39 +1295,39 @@ Layer::_RezizeLayerRedrawMore(BRegion ®, float dx, float dy) if (dx == 0 && dy == 0) return; - for (Layer *lay = LastChild(); lay; lay = PreviousChild()) { - uint16 rm = lay->fResizeMode & 0x0000FFFF; + for (Layer* child = LastChild(); child; child = PreviousChild()) { + uint16 rm = child->fResizeMode & 0x0000FFFF; if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) { // NOTE: this is not exactly corect, but it works :-) - // Normaly we shoud've used the lay's old, required region - the one returned - // from get_user_region() with the old frame, and the current one. lay->Bounds() + // Normaly we shoud've used the child's old, required region - the one returned + // from get_user_region() with the old frame, and the current one. child->Bounds() // works for the moment so we leave it like this. // calculate the old bounds. - BRect oldBounds(lay->Bounds()); + BRect oldBounds(child->Bounds()); if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT) oldBounds.right -=dx; if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) oldBounds.bottom -=dy; // compute the region that became visible because we got bigger OR smaller. - BRegion regZ(lay->Bounds()); + BRegion regZ(child->Bounds()); regZ.Include(oldBounds); - regZ.Exclude(oldBounds&lay->Bounds()); + regZ.Exclude(oldBounds & child->Bounds()); - lay->ConvertToScreen(®Z); + child->ConvertToScreen(®Z); - // intersect that with this'(not lay's) fullVisible region + // intersect that with this'(not child's) fullVisible region regZ.IntersectWith(&fFullVisible2); reg.Include(®Z); - lay->_RezizeLayerRedrawMore(reg, + child->_RezizeLayerRedrawMore(reg, (rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0, (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0); // above, OR this: - // reg.Include(&lay->fFullVisible2); + // reg.Include(&child->fFullVisible2); } else if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) || @@ -1321,7 +1335,7 @@ Layer::_RezizeLayerRedrawMore(BRegion ®, float dx, float dy) ((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)|| ((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0)) { - reg.Include(&lay->fFullVisible2); + reg.Include(&child->fFullVisible2); } } } @@ -1332,14 +1346,14 @@ Layer::_ResizeLayerFullUpdateOnResize(BRegion ®, float dx, float dy) if (dx == 0 && dy == 0) return; - for (Layer *lay = LastChild(); lay; lay = PreviousChild()) { - uint16 rm = lay->fResizeMode & 0x0000FFFF; + for (Layer* child = LastChild(); child; child = PreviousChild()) { + uint16 rm = child->fResizeMode & 0x0000FFFF; if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) { - if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0) - reg.Include(&lay->fVisible2); + if (child->fFlags & B_FULL_UPDATE_ON_RESIZE && child->fVisible2.CountRects() > 0) + reg.Include(&child->fVisible2); - lay->_ResizeLayerFullUpdateOnResize(reg, + child->_ResizeLayerFullUpdateOnResize(reg, (rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0, (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0); } @@ -1409,15 +1423,15 @@ Layer::_RebuildVisibleRegions( const BRegion &invalid, // allow this layer to hide some parts from its children _ReserveRegions(common); - for (Layer *lay = LastChild(); lay; lay = PreviousChild()) { - if (lay == startFrom) + for (Layer *child = LastChild(); child; child = PreviousChild()) { + if (child == startFrom) fullRebuild = true; if (fullRebuild) - lay->_RebuildVisibleRegions(invalid, common, lay->LastChild()); + child->_RebuildVisibleRegions(invalid, common, child->LastChild()); // to let children know much they can take from parent's visible region - common.Exclude(&lay->fFullVisible2); + common.Exclude(&child->fFullVisible2); } // include what's left after all children took what they could. @@ -1450,15 +1464,30 @@ Layer::_RebuildVisibleRegions( const BRegion &invalid, // allow this layer to hide some parts from its children _ReserveRegions(common); - for (Layer *lay = LastChild(); lay; lay = PreviousChild()) { - lay->_RebuildVisibleRegions(invalid, common, lay->LastChild()); + for (Layer *child = LastChild(); child; child = PreviousChild()) { + child->_RebuildVisibleRegions(invalid, common, child->LastChild()); // to let children know much they can take from parent's visible region - common.Exclude(&lay->fFullVisible2); + common.Exclude(&child->fFullVisible2); } // include what's left after all children took what they could. fVisible2.Include(&common); + + _RebuildDrawingRegion(); +} + +// _RebuildDrawingRegion +void +Layer::_RebuildDrawingRegion() +{ + fDrawingRegion = fVisible2; + // apply user clipping which is in native coordinate system + if (const BRegion* userClipping = fDrawState->ClippingRegion()) { + BRegion screenUserClipping(*userClipping); + ConvertToScreen(&screenUserClipping); + fDrawingRegion.IntersectWith(&screenUserClipping); + } } void @@ -1539,13 +1568,13 @@ Layer::_AllRedraw(const BRegion &invalid) } } - for (Layer *lay = LastChild(); lay != NULL; lay = PreviousChild()) { - if (!(lay->IsHidden())) { - BRegion common(lay->fFullVisible2); + for (Layer *child = LastChild(); child != NULL; child = PreviousChild()) { + if (!(child->IsHidden())) { + BRegion common(child->fFullVisible2); common.IntersectWith(&invalid); if (common.CountRects() > 0) - lay->_AllRedraw(invalid); + child->_AllRedraw(invalid); } } } diff --git a/src/servers/app/Layer.h b/src/servers/app/Layer.h index 3a500334ed..3ef813b6c6 100644 --- a/src/servers/app/Layer.h +++ b/src/servers/app/Layer.h @@ -194,8 +194,12 @@ class Layer { void SetFlags(uint32 flags); // clipping stuff and redraw + void SetUserClipping(const BRegion& region); + // region is expected in layer coordinates + inline const BRegion& VisibleRegion() const { return fVisible2; } inline const BRegion& FullVisible() const { return fFullVisible2; } + inline const BRegion& DrawingRegion() const { return fDrawingRegion; } virtual void GetWantedRegion(BRegion& reg); @@ -224,6 +228,7 @@ class Layer { void _RebuildVisibleRegions( const BRegion &invalid, const BRegion &parentLocalVisible, const Layer *startFrom); + void _RebuildDrawingRegion(); void _ClearVisibleRegions(); void _ResizeLayerFrameBy(float x, float y); void _RezizeLayerRedrawMore(BRegion ®, float dx, float dy); @@ -245,6 +250,7 @@ class Layer { BRegion fVisible2; BRegion fFullVisible2; BRegion fDirtyForRebuild; + BRegion fDrawingRegion; DrawingEngine* fDriver; RootLayer* fRootLayer; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 47051b4fd0..b6c990e227 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1079,14 +1079,14 @@ if (myRootLayer) fLink.Attach(0L); fLink.Flush(); } else { - // TODO: Watch out for the coordinate system in AS_LAYER_GET_CLIP_REGION - int32 rectCount = fCurrentLayer->fVisible2.CountRects(); + BRegion drawingRegion = fCurrentLayer->DrawingRegion(); + int32 rectCount = drawingRegion.CountRects(); fLink.StartMessage(SERVER_TRUE); fLink.Attach(rectCount); for (int32 i = 0; i < rectCount; i++) { - BRect converted(fCurrentLayer->fVisible2.RectAt(i)); + BRect converted(drawingRegion.RectAt(i)); fCurrentLayer->ConvertFromScreen(&converted); fLink.Attach(converted); } @@ -1100,25 +1100,16 @@ if (myRootLayer) { DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: Layer: %s\n", Title(), fCurrentLayer->Name())); - // TODO: Watch out for the coordinate system in AS_LAYER_SET_CLIP_REGION - int32 noOfRects; - - link.Read(&noOfRects); + int32 rectCount; + link.Read(&rectCount); BRegion region; - for (int i = 0; i < noOfRects; i++) { + for (int32 i = 0; i < rectCount; i++) { BRect r; link.Read(&r); - fCurrentLayer->ConvertToScreen(&r); region.Include(r); } -// TODO: Turned off user clipping for now (will probably not harm anything but performance right now) -// We need to integrate user clipping more, in Layer::PopState, the clipping needs to be -// restored too. "AS_LAYER_SET_CLIP_REGION" is irritating, as I think it should be -// "AS_LAYER_CONSTRAIN_CLIP_REGION", since it means to "add" to the current clipping, not "set" it. -// fCurrentLayer->CurrentState()->SetClippingRegion(region); - - // TODO: rebuild clipping and redraw + fCurrentLayer->SetUserClipping(region); break; } @@ -1622,7 +1613,7 @@ ServerWindow::_DispatchGraphicsMessage(int32 code, BPrivate::LinkReceiver &link) // NOTE: fCurrentLayer and fCurrentLayer->fLayerData cannot be NULL, // _DispatchGraphicsMessage() is called from _DispatchMessage() which // checks both these conditions - BRegion rreg(fCurrentLayer->VisibleRegion()); + BRegion rreg(fCurrentLayer->DrawingRegion()); if (fWinBorder->InUpdate()) rreg.IntersectWith(&fWinBorder->RegionToBeUpdated());