diff --git a/headers/private/interface/ViewAux.h b/headers/private/interface/ViewAux.h index 24d9e674c3..dfc84e6298 100644 --- a/headers/private/interface/ViewAux.h +++ b/headers/private/interface/ViewAux.h @@ -75,6 +75,7 @@ class ViewState { ::drawing_mode drawing_mode; BRegion clipping_region; + bool clipping_region_used; BPoint origin; // line modes diff --git a/headers/private/servers/app/DrawState.h b/headers/private/servers/app/DrawState.h index 7ebea18a35..ad81ba0936 100644 --- a/headers/private/servers/app/DrawState.h +++ b/headers/private/servers/app/DrawState.h @@ -70,7 +70,7 @@ class DrawState { void InverseTransform(BPoint* point) const; // additional clipping as requested by client - void SetClippingRegion(const BRegion& region); + void SetClippingRegion(const BRegion* region); const BRegion* ClippingRegion() const { return fClippingRegion; } /* inline int32 CountClippingRects() const diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index a33dc62113..f44be3d292 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -129,8 +129,11 @@ ViewState::ViewState() pen_location.Set(0, 0); pen_size = 1.0; - // This probably needs to be set to bounds by the owning BView - clipping_region.MakeEmpty(); + // NOTE: the clipping_region is empty + // on construction but it is not used yet, + // we avoid having to keep track of it via + // this flag + clipping_region_used = false; set_rgb_color(high_color, 0, 0, 0); set_rgb_color(low_color, 255, 255, 255); @@ -226,11 +229,15 @@ ViewState::UpdateServerState(BPrivate::PortLink &link) link.Attach(font_aliasing); // we send the 'local' clipping region... if we have one... - int32 count = clipping_region.CountRects(); - - link.Attach(count); - for (int32 i = 0; i < count; i++) - link.Attach(clipping_region.RectAt(i)); + if (clipping_region_used) { + int32 count = clipping_region.CountRects(); + link.Attach(count); + for (int32 i = 0; i < count; i++) + link.Attach(clipping_region.RectAt(i)); + } else { + // no clipping region + link.Attach(-1); + } // Although we might have a 'local' clipping region, when we call // BView::GetClippingRegion() we ask for the 'global' one and it @@ -299,8 +306,22 @@ ViewState::UpdateFrom(BPrivate::PortLink &link) link.Read(&scale); link.Read(&font_aliasing); - // no need to read the clipping region, as it's invalid - // next time we need it anyway + // read the user clipping + // (that's NOT the current View visible clipping but the additional + // user specified clipping!) + int32 clippingRectCount; + link.Read(&clippingRectCount); + if (clippingRectCount >= 0) { + clipping_region.MakeEmpty(); + for (int32 i = 0; i < clippingRectCount; i++) { + BRect rect; + link.Read(&rect); + clipping_region.Include(rect); + } + } else { + // no user clipping used + clipping_region_used = false; + } valid_flags = ~B_VIEW_CLIP_REGION_BIT; } @@ -2151,10 +2172,10 @@ BView::GetClippingRegion(BRegion* region) const if (!region) return; - // TODO: For now, the clipping bit is ignored, since the client has no - // idea when the clipping in the server changed. -Stephan + // NOTE: the client has no idea when the clipping in the server + // changed, so it is always read from the serber + region->MakeEmpty(); -// if (!fState->IsValid(B_VIEW_CLIP_REGION_BIT) && fOwner && do_owner_check()) { if (fOwner && do_owner_check()) { fOwner->fLink->StartMessage(AS_LAYER_GET_CLIP_REGION); @@ -2164,21 +2185,15 @@ BView::GetClippingRegion(BRegion* region) const int32 count; fOwner->fLink->Read(&count); - fState->clipping_region.MakeEmpty(); - for (int32 i = 0; i < count; i++) { BRect rect; fOwner->fLink->Read(&rect); - fState->clipping_region.Include(rect); + region->Include(rect); } fState->valid_flags |= B_VIEW_CLIP_REGION_BIT; } - } else { - fState->clipping_region.MakeEmpty(); } - - *region = fState->clipping_region; } @@ -2186,19 +2201,19 @@ void BView::ConstrainClippingRegion(BRegion* region) { if (do_owner_check()) { - int32 count = 0; - if (region) - count = region->CountRects(); fOwner->fLink->StartMessage(AS_LAYER_SET_CLIP_REGION); - // '0' means that in the app_server, there won't be any 'local' - // clipping region (it will be = NULL) - - // TODO: note this in the specs - fOwner->fLink->Attach(count); - for (int32 i = 0; i < count; i++) - fOwner->fLink->Attach(region->RectAt(i)); + if (region) { + int32 count = region->CountRects(); + fOwner->fLink->Attach(count); + for (int32 i = 0; i < count; i++) + fOwner->fLink->Attach(region->RectAtInt(i)); + } else { + fOwner->fLink->Attach(-1); + // '-1' means that in the app_server, there won't be any 'local' + // clipping region (it will be NULL) + } // we flush here because app_server waits for all the rects fOwner->fLink->Flush(); diff --git a/src/servers/app/DrawState.cpp b/src/servers/app/DrawState.cpp index b89eb32968..c82a0d0839 100644 --- a/src/servers/app/DrawState.cpp +++ b/src/servers/app/DrawState.cpp @@ -214,15 +214,18 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link) int32 clipRectCount; link.Read(&clipRectCount); - BRegion region; - if (clipRectCount > 0) { + if (clipRectCount >= 0) { + BRegion region; BRect rect; for (int32 i = 0; i < clipRectCount; i++) { link.Read(&rect); region.Include(rect); } + SetClippingRegion(®ion); + } else { + // No user clipping used + SetClippingRegion(NULL); } - SetClippingRegion(region); } @@ -258,12 +261,15 @@ DrawState::WriteToLink(BPrivate::LinkSender& link) const link.Attach(fScale); link.Attach(fFontAliasing); - int32 clippingRectCount = fClippingRegion ? fClippingRegion->CountRects() : 0; - link.Attach(clippingRectCount); if (fClippingRegion) { + int32 clippingRectCount = fClippingRegion->CountRects(); + link.Attach(clippingRectCount); for (int i = 0; i < clippingRectCount; i++) link.Attach(fClippingRegion->RectAt(i)); + } else { + // no client clipping + link.Attach(-1); } } @@ -374,11 +380,11 @@ DrawState::InverseTransform(BPoint* point) const } - void -DrawState::SetClippingRegion(const BRegion& region) +DrawState::SetClippingRegion(const BRegion* region) { // reset clipping to that of previous state + // (that's the starting point) if (PreviousState() != NULL && PreviousState()->ClippingRegion()) { if (fClippingRegion) *fClippingRegion = *(PreviousState()->ClippingRegion()); @@ -389,12 +395,15 @@ DrawState::SetClippingRegion(const BRegion& region) fClippingRegion = NULL; } - // add the clipping from the passed region - if (region.Frame().IsValid()) { + // intersect with the clipping from the passed region + // (even if it is empty) + // passing NULL unsets this states additional region, + // it will then be the region of the previous state + if (region) { if (fClippingRegion) - fClippingRegion->IntersectWith(®ion); + fClippingRegion->IntersectWith(region); else - fClippingRegion = new BRegion(region); + fClippingRegion = new BRegion(*region); } } diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index d910def883..4c77fc23ca 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1527,7 +1527,7 @@ ServerWindow::_DispatchViewMessage(int32 code, if (PictureToRegion(picture, region, inverse, where) < B_OK) break; - fCurrentLayer->CurrentState()->SetClippingRegion(region); + fCurrentLayer->SetUserClipping(®ion); // TODO: reenable AS_LAYER_CLIP_TO_PICTURE #if 0 @@ -1576,15 +1576,31 @@ ServerWindow::_DispatchViewMessage(int32 code, DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); int32 rectCount; - link.Read(&rectCount); - + status_t status = link.Read(&rectCount); + // a negative count means no + // region for the current draw state, + // but an *empty* region is actually valid! + // even if it means no drawing is allowed BRegion region; - for (int32 i = 0; i < rectCount; i++) { - BRect r; - link.Read(&r); - region.Include(r); + if (status == B_OK && rectCount >= 0) { + for (int32 i = 0; i < rectCount; i++) { + clipping_rect r; + status = link.Read(&r); + if (status < B_OK) + break; + region.Include(r); + } + } else + status = B_ERROR; + + if (status == B_OK) { + fCurrentLayer->SetUserClipping(®ion); + } else { + // passing NULL sets this states region + // to that of the previous state + fCurrentLayer->SetUserClipping(NULL); } - fCurrentLayer->SetUserClipping(region); + break; } @@ -1749,11 +1765,9 @@ ServerWindow::_DispatchViewMessage(int32 code, BMessage dragMessage; if (link.Read(buffer, bufferSize) == B_OK && dragMessage.Unflatten(buffer) == B_OK) { -// ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken); - fDesktop->EventDispatcher().SetDragMessage(dragMessage/*, bitmap*/); -if (ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken)) { - fDesktop->HWInterface()->SetDragBitmap(bitmap, offset); -} + ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken); + fDesktop->EventDispatcher().SetDragMessage(dragMessage, + bitmap, offset); } delete[] buffer; } @@ -1781,7 +1795,9 @@ if (ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken)) { BMessage dragMessage; if (link.Read(buffer, bufferSize) == B_OK && dragMessage.Unflatten(buffer) == B_OK) { - fDesktop->EventDispatcher().SetDragMessage(dragMessage/*, dragRect*/); + fDesktop->EventDispatcher().SetDragMessage(dragMessage, + NULL, // should be dragRect + offset); } delete[] buffer; } diff --git a/src/servers/app/ViewLayer.cpp b/src/servers/app/ViewLayer.cpp index bc84828c1b..a9731d976f 100644 --- a/src/servers/app/ViewLayer.cpp +++ b/src/servers/app/ViewLayer.cpp @@ -393,7 +393,7 @@ ViewLayer::Scale() const void -ViewLayer::SetUserClipping(const BRegion& region) +ViewLayer::SetUserClipping(const BRegion* region) { fDrawState->SetClippingRegion(region); diff --git a/src/servers/app/ViewLayer.h b/src/servers/app/ViewLayer.h index 082da94d22..0452737d1f 100644 --- a/src/servers/app/ViewLayer.h +++ b/src/servers/app/ViewLayer.h @@ -64,7 +64,7 @@ class ViewLayer { void SetScale(float scale); float Scale() const; - void SetUserClipping(const BRegion& region); + void SetUserClipping(const BRegion* region); // region is expected in layer coordinates // converts the given frame up the view hierarchy and