* when the client constrained the clipping on a view, the server used to

take an empty region as an indication to remove the clipping, but on R5,
  this is actually valid... this patch fixes the problem
* the ViewState::clipping_region is now consistently used to memorize
  the user defined clipping of the view state instead of being sometimes
  used to cache the current view clipping


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16656 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2006-03-08 18:57:44 +00:00
parent 4d664f91ca
commit 8e89843efc
7 changed files with 98 additions and 57 deletions

View File

@ -75,6 +75,7 @@ class ViewState {
::drawing_mode drawing_mode; ::drawing_mode drawing_mode;
BRegion clipping_region; BRegion clipping_region;
bool clipping_region_used;
BPoint origin; BPoint origin;
// line modes // line modes

View File

@ -70,7 +70,7 @@ class DrawState {
void InverseTransform(BPoint* point) const; void InverseTransform(BPoint* point) const;
// additional clipping as requested by client // additional clipping as requested by client
void SetClippingRegion(const BRegion& region); void SetClippingRegion(const BRegion* region);
const BRegion* ClippingRegion() const const BRegion* ClippingRegion() const
{ return fClippingRegion; } { return fClippingRegion; }
/* inline int32 CountClippingRects() const /* inline int32 CountClippingRects() const

View File

@ -129,8 +129,11 @@ ViewState::ViewState()
pen_location.Set(0, 0); pen_location.Set(0, 0);
pen_size = 1.0; pen_size = 1.0;
// This probably needs to be set to bounds by the owning BView // NOTE: the clipping_region is empty
clipping_region.MakeEmpty(); // 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(high_color, 0, 0, 0);
set_rgb_color(low_color, 255, 255, 255); set_rgb_color(low_color, 255, 255, 255);
@ -226,11 +229,15 @@ ViewState::UpdateServerState(BPrivate::PortLink &link)
link.Attach<bool>(font_aliasing); link.Attach<bool>(font_aliasing);
// we send the 'local' clipping region... if we have one... // we send the 'local' clipping region... if we have one...
if (clipping_region_used) {
int32 count = clipping_region.CountRects(); int32 count = clipping_region.CountRects();
link.Attach<int32>(count); link.Attach<int32>(count);
for (int32 i = 0; i < count; i++) for (int32 i = 0; i < count; i++)
link.Attach<BRect>(clipping_region.RectAt(i)); link.Attach<BRect>(clipping_region.RectAt(i));
} else {
// no clipping region
link.Attach<int32>(-1);
}
// Although we might have a 'local' clipping region, when we call // Although we might have a 'local' clipping region, when we call
// BView::GetClippingRegion() we ask for the 'global' one and it // BView::GetClippingRegion() we ask for the 'global' one and it
@ -299,8 +306,22 @@ ViewState::UpdateFrom(BPrivate::PortLink &link)
link.Read<float>(&scale); link.Read<float>(&scale);
link.Read<bool>(&font_aliasing); link.Read<bool>(&font_aliasing);
// no need to read the clipping region, as it's invalid // read the user clipping
// next time we need it anyway // (that's NOT the current View visible clipping but the additional
// user specified clipping!)
int32 clippingRectCount;
link.Read<int32>(&clippingRectCount);
if (clippingRectCount >= 0) {
clipping_region.MakeEmpty();
for (int32 i = 0; i < clippingRectCount; i++) {
BRect rect;
link.Read<BRect>(&rect);
clipping_region.Include(rect);
}
} else {
// no user clipping used
clipping_region_used = false;
}
valid_flags = ~B_VIEW_CLIP_REGION_BIT; valid_flags = ~B_VIEW_CLIP_REGION_BIT;
} }
@ -2151,10 +2172,10 @@ BView::GetClippingRegion(BRegion* region) const
if (!region) if (!region)
return; return;
// TODO: For now, the clipping bit is ignored, since the client has no // NOTE: the client has no idea when the clipping in the server
// idea when the clipping in the server changed. -Stephan // 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()) { if (fOwner && do_owner_check()) {
fOwner->fLink->StartMessage(AS_LAYER_GET_CLIP_REGION); fOwner->fLink->StartMessage(AS_LAYER_GET_CLIP_REGION);
@ -2164,21 +2185,15 @@ BView::GetClippingRegion(BRegion* region) const
int32 count; int32 count;
fOwner->fLink->Read<int32>(&count); fOwner->fLink->Read<int32>(&count);
fState->clipping_region.MakeEmpty();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
BRect rect; BRect rect;
fOwner->fLink->Read<BRect>(&rect); fOwner->fLink->Read<BRect>(&rect);
fState->clipping_region.Include(rect); region->Include(rect);
} }
fState->valid_flags |= B_VIEW_CLIP_REGION_BIT; 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) BView::ConstrainClippingRegion(BRegion* region)
{ {
if (do_owner_check()) { if (do_owner_check()) {
int32 count = 0;
if (region)
count = region->CountRects();
fOwner->fLink->StartMessage(AS_LAYER_SET_CLIP_REGION); fOwner->fLink->StartMessage(AS_LAYER_SET_CLIP_REGION);
// '0' means that in the app_server, there won't be any 'local' if (region) {
// clipping region (it will be = NULL) int32 count = region->CountRects();
// TODO: note this in the specs
fOwner->fLink->Attach<int32>(count); fOwner->fLink->Attach<int32>(count);
for (int32 i = 0; i < count; i++) for (int32 i = 0; i < count; i++)
fOwner->fLink->Attach<BRect>(region->RectAt(i)); fOwner->fLink->Attach<clipping_rect>(region->RectAtInt(i));
} else {
fOwner->fLink->Attach<int32>(-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 // we flush here because app_server waits for all the rects
fOwner->fLink->Flush(); fOwner->fLink->Flush();

View File

@ -214,15 +214,18 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link)
int32 clipRectCount; int32 clipRectCount;
link.Read<int32>(&clipRectCount); link.Read<int32>(&clipRectCount);
if (clipRectCount >= 0) {
BRegion region; BRegion region;
if (clipRectCount > 0) {
BRect rect; BRect rect;
for (int32 i = 0; i < clipRectCount; i++) { for (int32 i = 0; i < clipRectCount; i++) {
link.Read<BRect>(&rect); link.Read<BRect>(&rect);
region.Include(rect); region.Include(rect);
} }
SetClippingRegion(&region);
} else {
// No user clipping used
SetClippingRegion(NULL);
} }
SetClippingRegion(region);
} }
@ -258,12 +261,15 @@ DrawState::WriteToLink(BPrivate::LinkSender& link) const
link.Attach<float>(fScale); link.Attach<float>(fScale);
link.Attach<bool>(fFontAliasing); link.Attach<bool>(fFontAliasing);
int32 clippingRectCount = fClippingRegion ? fClippingRegion->CountRects() : 0;
link.Attach<int32>(clippingRectCount);
if (fClippingRegion) { if (fClippingRegion) {
int32 clippingRectCount = fClippingRegion->CountRects();
link.Attach<int32>(clippingRectCount);
for (int i = 0; i < clippingRectCount; i++) for (int i = 0; i < clippingRectCount; i++)
link.Attach<BRect>(fClippingRegion->RectAt(i)); link.Attach<BRect>(fClippingRegion->RectAt(i));
} else {
// no client clipping
link.Attach<int32>(-1);
} }
} }
@ -374,11 +380,11 @@ DrawState::InverseTransform(BPoint* point) const
} }
void void
DrawState::SetClippingRegion(const BRegion& region) DrawState::SetClippingRegion(const BRegion* region)
{ {
// reset clipping to that of previous state // reset clipping to that of previous state
// (that's the starting point)
if (PreviousState() != NULL && PreviousState()->ClippingRegion()) { if (PreviousState() != NULL && PreviousState()->ClippingRegion()) {
if (fClippingRegion) if (fClippingRegion)
*fClippingRegion = *(PreviousState()->ClippingRegion()); *fClippingRegion = *(PreviousState()->ClippingRegion());
@ -389,12 +395,15 @@ DrawState::SetClippingRegion(const BRegion& region)
fClippingRegion = NULL; fClippingRegion = NULL;
} }
// add the clipping from the passed region // intersect with the clipping from the passed region
if (region.Frame().IsValid()) { // (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) if (fClippingRegion)
fClippingRegion->IntersectWith(&region); fClippingRegion->IntersectWith(region);
else else
fClippingRegion = new BRegion(region); fClippingRegion = new BRegion(*region);
} }
} }

View File

@ -1527,7 +1527,7 @@ ServerWindow::_DispatchViewMessage(int32 code,
if (PictureToRegion(picture, region, inverse, where) < B_OK) if (PictureToRegion(picture, region, inverse, where) < B_OK)
break; break;
fCurrentLayer->CurrentState()->SetClippingRegion(region); fCurrentLayer->SetUserClipping(&region);
// TODO: reenable AS_LAYER_CLIP_TO_PICTURE // TODO: reenable AS_LAYER_CLIP_TO_PICTURE
#if 0 #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())); DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
int32 rectCount; int32 rectCount;
link.Read<int32>(&rectCount); status_t status = link.Read<int32>(&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; BRegion region;
if (status == B_OK && rectCount >= 0) {
for (int32 i = 0; i < rectCount; i++) { for (int32 i = 0; i < rectCount; i++) {
BRect r; clipping_rect r;
link.Read<BRect>(&r); status = link.Read<clipping_rect>(&r);
if (status < B_OK)
break;
region.Include(r); region.Include(r);
} }
fCurrentLayer->SetUserClipping(region); } else
status = B_ERROR;
if (status == B_OK) {
fCurrentLayer->SetUserClipping(&region);
} else {
// passing NULL sets this states region
// to that of the previous state
fCurrentLayer->SetUserClipping(NULL);
}
break; break;
} }
@ -1749,11 +1765,9 @@ ServerWindow::_DispatchViewMessage(int32 code,
BMessage dragMessage; BMessage dragMessage;
if (link.Read(buffer, bufferSize) == B_OK if (link.Read(buffer, bufferSize) == B_OK
&& dragMessage.Unflatten(buffer) == B_OK) { && dragMessage.Unflatten(buffer) == B_OK) {
// ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken); ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken);
fDesktop->EventDispatcher().SetDragMessage(dragMessage/*, bitmap*/); fDesktop->EventDispatcher().SetDragMessage(dragMessage,
if (ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken)) { bitmap, offset);
fDesktop->HWInterface()->SetDragBitmap(bitmap, offset);
}
} }
delete[] buffer; delete[] buffer;
} }
@ -1781,7 +1795,9 @@ if (ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken)) {
BMessage dragMessage; BMessage dragMessage;
if (link.Read(buffer, bufferSize) == B_OK if (link.Read(buffer, bufferSize) == B_OK
&& dragMessage.Unflatten(buffer) == B_OK) { && dragMessage.Unflatten(buffer) == B_OK) {
fDesktop->EventDispatcher().SetDragMessage(dragMessage/*, dragRect*/); fDesktop->EventDispatcher().SetDragMessage(dragMessage,
NULL, // should be dragRect
offset);
} }
delete[] buffer; delete[] buffer;
} }

View File

@ -393,7 +393,7 @@ ViewLayer::Scale() const
void void
ViewLayer::SetUserClipping(const BRegion& region) ViewLayer::SetUserClipping(const BRegion* region)
{ {
fDrawState->SetClippingRegion(region); fDrawState->SetClippingRegion(region);

View File

@ -64,7 +64,7 @@ class ViewLayer {
void SetScale(float scale); void SetScale(float scale);
float Scale() const; float Scale() const;
void SetUserClipping(const BRegion& region); void SetUserClipping(const BRegion* region);
// region is expected in layer coordinates // region is expected in layer coordinates
// converts the given frame up the view hierarchy and // converts the given frame up the view hierarchy and