diff --git a/src/tests/servers/app/newerClipping/ClientLooper.cpp b/src/tests/servers/app/newerClipping/ClientLooper.cpp index 28b5492f4b..93bbd603a0 100644 --- a/src/tests/servers/app/newerClipping/ClientLooper.cpp +++ b/src/tests/servers/app/newerClipping/ClientLooper.cpp @@ -38,7 +38,7 @@ ClientLooper::MessageReceived(BMessage* message) for (int32 i = 0; i < fViewCount; i++) { // the client is slow - snooze(1000L); +// snooze(20000L); // send the command to redraw a view BMessage command(MSG_DRAWING_COMMAND); command.AddInt32("token", i); diff --git a/src/tests/servers/app/newerClipping/ViewLayer.cpp b/src/tests/servers/app/newerClipping/ViewLayer.cpp index b5568d43e6..4a748487c8 100644 --- a/src/tests/servers/app/newerClipping/ViewLayer.cpp +++ b/src/tests/servers/app/newerClipping/ViewLayer.cpp @@ -116,7 +116,19 @@ ViewLayer::AddChild(ViewLayer* layer) if (fWindow) { layer->AttachedToWindow(fWindow); - fWindow->MarkDirty(&layer->ScreenClipping()); + + // TODO: not correct... need something like + // ViewLayer::ClipToParent(BRect frame) + // { + // frame = frame & Bounds(); + // ConvertToParent(&frame); + // fParent->ClipToParent(&frame); + // } + BRect dirty(layer->Frame()); + dirty = dirty & Bounds(); + ConvertToTop(&dirty); + BRegion dirtyRegion(dirty); + fWindow->MarkContentDirty(&dirtyRegion); } } @@ -155,6 +167,7 @@ ViewLayer::RemoveChild(ViewLayer* layer) } if (fWindow) { layer->DetachedFromWindow(); + // TODO: handle exposed area } return true; @@ -290,16 +303,14 @@ ViewLayer::SetName(const char* string) fName.SetTo(string); } -#define HW_MOVE 0 - +#if 0 // MoveBy void -ViewLayer::MoveBy(int32 x, int32 y) +ViewLayer::MoveBy(int32 x, int32 y, BRegion* dirtyRegion) { if (x == 0 && y == 0) return; -#if HW_MOVE if (!fIsTopLayer && fWindow) { // blit to new location (children as well) BRect screenRect; @@ -355,21 +366,46 @@ if (fParent) { fFrame.OffsetBy(x, y); _MoveScreenClipping(x, y, true); } -#else // HW_MOVE fFrame.OffsetBy(x, y); - - _MoveScreenClipping(x, y, true); - - if (!fIsTopLayer && fWindow) { - BRect screenRect(Bounds()); - ConvertToTop(&screenRect); - screenRect = screenRect | screenRect.OffsetByCopy(-x, -y); - BRegion dirty(screenRect); - - fWindow->MarkDirty(&dirty); - } -#endif // !HW_MOVE } +#else // 0 + +// MoveBy +void +ViewLayer::MoveBy(int32 x, int32 y, BRegion* dirtyRegion) +{ + if (x == 0 && y == 0) + return; + + fFrame.OffsetBy(x, y); + InvalidateScreenClipping(true); + + if (!fIsTopLayer && dirtyRegion) { + if (fParent) { + // clip to parent + BRect oldScreenRect(Bounds()); + oldScreenRect.OffsetByCopy(-x, -y); + ConvertToParent(&oldScreenRect); + + BRect screenRect(Bounds()); + ConvertToParent(&screenRect); + + // TODO: see AddLayer + BRect dirty = oldScreenRect | screenRect; + dirty = dirty & fParent->Bounds(); + fParent->ConvertToTop(&dirty); + + dirtyRegion->Include(dirty); + } else { + BRect screenRect(Bounds()); + screenRect = screenRect | screenRect.OffsetByCopy(-x, -y); + ConvertToTop(&screenRect); + + dirtyRegion->Include(screenRect); + } + } +} +#endif // 0 // ResizeBy void @@ -391,7 +427,7 @@ ViewLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion) dirty.Exclude(oldBounds & Bounds()); } - _InvalidateScreenClipping(true); + InvalidateScreenClipping(true); if (dirty.CountRects() > 0) { // exclude children, they are expected to @@ -418,14 +454,14 @@ ViewLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion) // ScrollBy void -ViewLayer::ScrollBy(int32 x, int32 y) +ViewLayer::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion) { fScrollingOffset.x += x; fScrollingOffset.y += y; // TODO: CopyRegion... // TODO: ... - _InvalidateScreenClipping(true); + InvalidateScreenClipping(true); } // ParentResized @@ -463,7 +499,7 @@ ViewLayer::ParentResized(int32 x, int32 y, BRegion* dirtyRegion) // MoveBy will change fFrame, so cache it BRect oldFrame = fFrame; MoveBy(newFrame.left - oldFrame.left, - newFrame.top - oldFrame.top); + newFrame.top - oldFrame.top, dirtyRegion); ResizeBy(newFrame.Width() - oldFrame.Width(), newFrame.Height() - oldFrame.Height(), dirtyRegion); @@ -472,10 +508,11 @@ ViewLayer::ParentResized(int32 x, int32 y, BRegion* dirtyRegion) // Draw void -ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, bool deep) +ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, + BRegion* windowContentClipping,bool deep) { // we can only draw within our own area - BRegion redraw(ScreenClipping()); + BRegion redraw(ScreenClipping(windowContentClipping)); // add the current clipping redraw.IntersectWith(effectiveClipping); @@ -494,10 +531,11 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, bool d if (deep) { // before passing the clipping on to children, exclude our // own region from the available clipping - effectiveClipping->Exclude(&ScreenClipping()); + effectiveClipping->Exclude(&ScreenClipping(windowContentClipping)); for (ViewLayer* child = FirstChild(); child; child = NextChild()) { - child->Draw(drawingEngine, effectiveClipping, deep); + child->Draw(drawingEngine, effectiveClipping, + windowContentClipping, deep); } } } @@ -587,25 +625,26 @@ ViewLayer::RebuildClipping(bool deep) // ScreenClipping BRegion& -ViewLayer::ScreenClipping() const +ViewLayer::ScreenClipping(BRegion* windowContentClipping, bool force) const { - if (!fScreenClippingValid) { + if (!fScreenClippingValid || force) { fScreenClipping = fLocalClipping; ConvertToTop(&fScreenClipping); + fScreenClipping.IntersectWith(windowContentClipping); fScreenClippingValid = true; } return fScreenClipping; } -// _InvalidateScreenClipping +// InvalidateScreenClipping void -ViewLayer::_InvalidateScreenClipping(bool deep) +ViewLayer::InvalidateScreenClipping(bool deep) { fScreenClippingValid = false; if (deep) { // invalidate the childrens screen clipping as well for (ViewLayer* child = FirstChild(); child; child = NextChild()) { - child->_InvalidateScreenClipping(deep); + child->InvalidateScreenClipping(deep); } } } @@ -618,7 +657,7 @@ ViewLayer::_MoveScreenClipping(int32 x, int32 y, bool deep) fScreenClipping.OffsetBy(x, y); if (deep) { - // invalidate the childrens screen clipping as well + // move the childrens screen clipping as well for (ViewLayer* child = FirstChild(); child; child = NextChild()) { child->_MoveScreenClipping(x, y, deep); } diff --git a/src/tests/servers/app/newerClipping/ViewLayer.h b/src/tests/servers/app/newerClipping/ViewLayer.h index 737fb832aa..6515ac3fbd 100644 --- a/src/tests/servers/app/newerClipping/ViewLayer.h +++ b/src/tests/servers/app/newerClipping/ViewLayer.h @@ -62,21 +62,27 @@ class ViewLayer { inline const char* Name() const { return fName.String(); } - void MoveBy(int32 dx, int32 dy); - void ResizeBy(int32 dx, int32 dy, BRegion* dirtyRegion); - void ScrollBy(int32 dx, int32 dy); + void MoveBy( int32 dx, int32 dy, + BRegion* dirtyRegion); - void ParentResized(int32 dx, int32 dy, - BRegion* dirtyRegion); + void ResizeBy( int32 dx, int32 dy, + BRegion* dirtyRegion); + + void ScrollBy( int32 dx, int32 dy, + BRegion* dirtyRegion); + + void ParentResized( int32 dx, int32 dy, + BRegion* dirtyRegion); // for background clearing - void Draw(DrawingEngine* drawingEngine, - BRegion* effectiveClipping, - bool deep = false); + void Draw( DrawingEngine* drawingEngine, + BRegion* effectiveClipping, + BRegion* windowContentClipping, + bool deep = false); - // to simulate drawing done from client side - void ClientDraw(DrawingEngine* drawingEngine, - BRegion* effectiveClipping); + // to simulate drawing triggered from client side + void ClientDraw( DrawingEngine* drawingEngine, + BRegion* effectiveClipping); bool IsHidden() const; void Hide(); @@ -84,13 +90,15 @@ class ViewLayer { // clipping void RebuildClipping(bool deep); - BRegion& ScreenClipping() const; + BRegion& ScreenClipping(BRegion* windowContentClipping, + bool force = false) const; // debugging void PrintToStream() const; + void InvalidateScreenClipping(bool deep); + private: - void _InvalidateScreenClipping(bool deep); void _MoveScreenClipping(int32 x, int32 y, bool deep); diff --git a/src/tests/servers/app/newerClipping/WindowLayer.cpp b/src/tests/servers/app/newerClipping/WindowLayer.cpp index 569b1b9489..b276b6986b 100644 --- a/src/tests/servers/app/newerClipping/WindowLayer.cpp +++ b/src/tests/servers/app/newerClipping/WindowLayer.cpp @@ -18,12 +18,16 @@ WindowLayer::WindowLayer(BRect frame, const char* name, DrawingEngine* drawingEngine, Desktop* desktop) : BLooper(name), fFrame(frame), + fVisibleRegion(), + fVisibleContentRegion(), fBorderRegion(), fBorderRegionValid(false), fContentRegion(), fContentRegionValid(false), + fEffectiveDrawingRegion(), + fEffectiveDrawingRegionValid(false), fFocus(false), @@ -103,10 +107,18 @@ WindowLayer::MessageReceived(BMessage* message) void WindowLayer::SetClipping(BRegion* stillAvailableOnScreen) { + // this function is only called from the Desktop thread + // start from full region (as if the window was fully visible) GetFullRegion(&fVisibleRegion); // clip to region still available on screen fVisibleRegion.IntersectWith(stillAvailableOnScreen); + + GetContentRegion(&fVisibleContentRegion); + fVisibleContentRegion.IntersectWith(&fVisibleRegion); + + fEffectiveDrawingRegionValid = false; + fTopLayer->InvalidateScreenClipping(true); } // GetFullRegion @@ -123,45 +135,48 @@ WindowLayer::GetFullRegion(BRegion* region) const // GetBorderRegion void -WindowLayer::GetBorderRegion(BRegion* region) const +WindowLayer::GetBorderRegion(BRegion* region) { - if (fBorderRegionValid) { - *region = fBorderRegion; + if (!fBorderRegionValid) { + // TODO: speed up by avoiding "Exclude()" + // start from the frame, extend to include decorator border + fBorderRegion.Set(BRect(fFrame.left - 4, fFrame.top - 4, + fFrame.right + 4, fFrame.bottom + 4)); + + fBorderRegion.Exclude(fFrame); + + // add the title tab + fBorderRegion.Include(BRect(fFrame.left - 4, fFrame.top - 20, + (fFrame.left + fFrame.right) / 2, fFrame.top - 5)); + + // resize handle + // if (B_DOCUMENT_WINDOW_LOOK) + fBorderRegion.Include(BRect(fFrame.right - 10, fFrame.bottom - 10, + fFrame.right, fFrame.bottom)); + fBorderRegionValid = true; } - // TODO: speed up by avoiding "Exclude()" - // start from the frame, extend to include decorator border - region->Set(BRect(fFrame.left - 4, fFrame.top - 4, - fFrame.right + 4, fFrame.bottom + 4)); - - region->Exclude(fFrame); - - // add the title tab - region->Include(BRect(fFrame.left - 4, fFrame.top - 20, - (fFrame.left + fFrame.right) / 2, fFrame.top - 5)); - - // resize handle - // if (B_DOCUMENT_WINDOW_LOOK) - region->Include(BRect(fFrame.right - 10, fFrame.bottom - 10, - fFrame.right, fFrame.bottom)); + *region = fBorderRegion; } // GetContentRegion void -WindowLayer::GetContentRegion(BRegion* region) const +WindowLayer::GetContentRegion(BRegion* region) { - if (fContentRegionValid) { - *region = fContentRegion; + if (!fContentRegionValid) { + // TODO: speed up by avoiding "Exclude()" + // start from the frame, extend to include decorator border + fContentRegion.Set(fFrame); + + // resize handle + // if (B_DOCUMENT_WINDOW_LOOK) + fContentRegion.Exclude(BRect(fFrame.right - 10, fFrame.bottom - 10, + fFrame.right, fFrame.bottom)); + + fContentRegionValid = true; } - // TODO: speed up by avoiding "Exclude()" - // start from the frame, extend to include decorator border - region->Set(fFrame); - - // resize handle - // if (B_DOCUMENT_WINDOW_LOOK) - region->Exclude(BRect(fFrame.right - 10, fFrame.bottom - 10, - fFrame.right, fFrame.bottom)); + *region = fContentRegion; } // SetFocus @@ -189,6 +204,8 @@ WindowLayer::SetFocus(bool focus) void WindowLayer::MoveBy(int32 x, int32 y) { + // this function is only called from the desktop thread + if (x == 0 && y == 0) return; @@ -204,9 +221,11 @@ WindowLayer::MoveBy(int32 x, int32 y) if (fPendingUpdateSession) fPendingUpdateSession->MoveBy(x, y); - fTopLayer->MoveBy(x, y); + fEffectiveDrawingRegionValid = false; - // TODO: move a local dirty region! + fTopLayer->MoveBy(x, y, NULL); + + // the desktop will take care of dirty regions } // ResizeBy @@ -219,18 +238,21 @@ WindowLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion) fFrame.right += x; fFrame.bottom += y; + // put the previous border region into the dirty region as well + // to handle the part that was overlapping a layer + dirtyRegion->Include(&fBorderRegion); + fBorderRegionValid = false; fContentRegionValid = false; + fEffectiveDrawingRegionValid = false; // the border is dirty, put it into // dirtyRegion for a start - GetBorderRegion(dirtyRegion); - - // put the previous border region into the dirty region as well - // to handle the part that was overlapping a layer -// if B_DOCUMENT_WINDOW_LOOK - dirtyRegion->Include(&fBorderRegion); + BRegion newBorderRegion; + GetBorderRegion(&newBorderRegion); + dirtyRegion->Include(&newBorderRegion); + // TODO: should this be clipped to the content region? fTopLayer->ResizeBy(x, y, dirtyRegion); } @@ -259,6 +281,19 @@ WindowLayer::MarkDirty(BRegion* regionOnScreen) fDesktop->MarkDirty(regionOnScreen); } +// MarkDirty +void +WindowLayer::MarkContentDirty(BRegion* regionOnScreen) +{ + if (fDesktop && fDesktop->LockClipping()) { + + regionOnScreen->IntersectWith(&fVisibleContentRegion); + fDesktop->MarkDirty(regionOnScreen); + + fDesktop->UnlockClipping(); + } +} +/* // DirtyRegion BRegion WindowLayer::DirtyRegion() @@ -270,7 +305,7 @@ WindowLayer::DirtyRegion() } return dirty; } - +*/ # pragma mark - // _DrawContents @@ -285,30 +320,23 @@ WindowLayer::_DrawContents(ViewLayer* layer) if (!layer) layer = fTopLayer; - if (!fContentRegionValid) { - GetContentRegion(&fContentRegion); - fContentRegionValid = true; + if (fDesktop->ReadLockClipping()) { + + BRegion effectiveWindowClipping(fVisibleContentRegion); + effectiveWindowClipping.IntersectWith(fDesktop->DirtyRegion()); + + if (effectiveWindowClipping.Frame().IsValid()) { + // send UPDATE message to the client + _MarkContentDirty(&effectiveWindowClipping); + + layer->Draw(fDrawingEngine, &effectiveWindowClipping, + &fVisibleContentRegion, true); + + fDesktop->MarkClean(&fContentRegion); + } + + fDesktop->ReadUnlockClipping(); } - - BRegion effectiveWindowClipping(fContentRegion); - // TODO: simplify - // ideally, there would only be a local fDirtyRegion, - // that we need to intersect with. fDirtyRegion would - // already only include fVisibleRegion - effectiveWindowClipping.IntersectWith(&fVisibleRegion); - effectiveWindowClipping.IntersectWith(fDesktop->DirtyRegion()); - if (effectiveWindowClipping.Frame().IsValid()) { - // send UPDATE message to the client here - _MarkContentDirty(&effectiveWindowClipping); - - layer->Draw(fDrawingEngine, &effectiveWindowClipping, true); - - fDesktop->MarkClean(&fContentRegion); - } -//else { -//printf(" nothing to do\n"); -//} - } // _DrawClient @@ -319,22 +347,25 @@ WindowLayer::_DrawClient(int32 token) if (!layer) return; - BRegion effectiveClipping(layer->ScreenClipping()); - if (fInUpdate) { - // enforce the dirty region of the update session - effectiveClipping.IntersectWith(&fCurrentUpdateSession->DirtyRegion()); - } else { -printf("%s - _DrawClient(token: %ld) - not in update\n", Name(), token); - } + if (fDesktop->ReadLockClipping()) { - if (effectiveClipping.CountRects() > 0 && fDesktop->ReadLockClipping()) { - effectiveClipping.IntersectWith(&fVisibleRegion); - // TODO: This step seems too much - BRegion contentRegion; - GetContentRegion(&contentRegion); - effectiveClipping.IntersectWith(&contentRegion); + if (!fEffectiveDrawingRegionValid) { + fEffectiveDrawingRegion = fVisibleContentRegion; + if (fInUpdate) { + // enforce the dirty region of the update session + fEffectiveDrawingRegion.IntersectWith(&fCurrentUpdateSession->DirtyRegion()); + } else { + printf("%s - _DrawClient(token: %ld) - not in update\n", Name(), token); + } + fEffectiveDrawingRegionValid = true; + } - layer->ClientDraw(fDrawingEngine, &effectiveClipping); + BRegion effectiveClipping(fEffectiveDrawingRegion); + effectiveClipping.IntersectWith(&layer->ScreenClipping(&fVisibleContentRegion)); + + if (effectiveClipping.CountRects() > 0) { + layer->ClientDraw(fDrawingEngine, &effectiveClipping); + } fDesktop->ReadUnlockClipping(); } @@ -348,34 +379,31 @@ WindowLayer::_DrawBorder() #if SLOW_DRAWING snooze(10000); #endif - - if (!fBorderRegionValid) { - GetBorderRegion(&fBorderRegion); - fBorderRegionValid = true; - } - - // construct the region of the border that needs redrawing - BRegion dirtyBorderRegion(fBorderRegion); - // intersect with our visible region - dirtyBorderRegion.IntersectWith(&fVisibleRegion); - // intersect with the Desktop's dirty region - dirtyBorderRegion.IntersectWith(fDesktop->DirtyRegion()); - - if (dirtyBorderRegion.Frame().IsValid()) { - if (fDrawingEngine->Lock()) { - if (fFocus) - fDrawingEngine->SetHighColor(255, 203, 0, 255); - else - fDrawingEngine->SetHighColor(216, 216, 216, 0); - fDrawingEngine->FillRegion(&dirtyBorderRegion); - fDrawingEngine->MarkDirty(&dirtyBorderRegion); - fDrawingEngine->Unlock(); + if (fDesktop->ReadLockClipping()) { + + // construct the region of the border that needs redrawing + BRegion dirtyBorderRegion; + GetBorderRegion(&dirtyBorderRegion); + // intersect with our visible region + dirtyBorderRegion.IntersectWith(&fVisibleRegion); + // intersect with the Desktop's dirty region + dirtyBorderRegion.IntersectWith(fDesktop->DirtyRegion()); + + if (dirtyBorderRegion.Frame().IsValid()) { + if (fDrawingEngine->Lock()) { + if (fFocus) + fDrawingEngine->SetHighColor(255, 203, 0, 255); + else + fDrawingEngine->SetHighColor(216, 216, 216, 0); + fDrawingEngine->FillRegion(&dirtyBorderRegion); + fDrawingEngine->MarkDirty(&dirtyBorderRegion); + fDrawingEngine->Unlock(); + } + fDesktop->MarkClean(&dirtyBorderRegion); } - fDesktop->MarkClean(&dirtyBorderRegion); + + fDesktop->ReadUnlockClipping(); } -//else { -//printf(" nothing to do\n"); -//} } // _MarkContentDirty diff --git a/src/tests/servers/app/newerClipping/WindowLayer.h b/src/tests/servers/app/newerClipping/WindowLayer.h index 0356cfc793..eda09953b6 100644 --- a/src/tests/servers/app/newerClipping/WindowLayer.h +++ b/src/tests/servers/app/newerClipping/WindowLayer.h @@ -52,8 +52,8 @@ class WindowLayer : public BLooper { inline BRegion& VisibleRegion() { return fVisibleRegion; } void GetFullRegion(BRegion* region) const; - void GetBorderRegion(BRegion* region) const; - void GetContentRegion(BRegion* region) const; + void GetBorderRegion(BRegion* region); + void GetContentRegion(BRegion* region); void SetFocus(bool focus); @@ -63,11 +63,12 @@ class WindowLayer : public BLooper { void AddChild(ViewLayer* layer); void MarkDirty(BRegion* regionOnScreen); + void MarkContentDirty(BRegion* regionOnScreen); DrawingEngine* GetDrawingEngine() const { return fDrawingEngine; } - BRegion DirtyRegion(); +// BRegion DirtyRegion(); private: void _DrawContents(ViewLayer* layer = NULL); @@ -84,12 +85,15 @@ class WindowLayer : public BLooper { // Desktop thread, when using it, Desktop::LockClipping() // has to be called BRegion fVisibleRegion; + BRegion fVisibleContentRegion; // caching local regions BRegion fBorderRegion; bool fBorderRegionValid; BRegion fContentRegion; bool fContentRegionValid; + BRegion fEffectiveDrawingRegion; + bool fEffectiveDrawingRegionValid; bool fFocus;