* 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;
BRegion clipping_region;
bool clipping_region_used;
BPoint origin;
// line modes

View File

@ -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

View File

@ -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<bool>(font_aliasing);
// we send the 'local' clipping region... if we have one...
int32 count = clipping_region.CountRects();
link.Attach<int32>(count);
for (int32 i = 0; i < count; i++)
link.Attach<BRect>(clipping_region.RectAt(i));
if (clipping_region_used) {
int32 count = clipping_region.CountRects();
link.Attach<int32>(count);
for (int32 i = 0; i < count; 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
// 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<bool>(&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<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;
}
@ -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<int32>(&count);
fState->clipping_region.MakeEmpty();
for (int32 i = 0; i < count; i++) {
BRect rect;
fOwner->fLink->Read<BRect>(&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<int32>(count);
for (int32 i = 0; i < count; i++)
fOwner->fLink->Attach<BRect>(region->RectAt(i));
if (region) {
int32 count = region->CountRects();
fOwner->fLink->Attach<int32>(count);
for (int32 i = 0; i < count; 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
fOwner->fLink->Flush();

View File

@ -214,15 +214,18 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link)
int32 clipRectCount;
link.Read<int32>(&clipRectCount);
BRegion region;
if (clipRectCount > 0) {
if (clipRectCount >= 0) {
BRegion region;
BRect rect;
for (int32 i = 0; i < clipRectCount; i++) {
link.Read<BRect>(&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<bool>(fFontAliasing);
int32 clippingRectCount = fClippingRegion ? fClippingRegion->CountRects() : 0;
link.Attach<int32>(clippingRectCount);
if (fClippingRegion) {
int32 clippingRectCount = fClippingRegion->CountRects();
link.Attach<int32>(clippingRectCount);
for (int i = 0; i < clippingRectCount; 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
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(&region);
fClippingRegion->IntersectWith(region);
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)
break;
fCurrentLayer->CurrentState()->SetClippingRegion(region);
fCurrentLayer->SetUserClipping(&region);
// 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<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;
for (int32 i = 0; i < rectCount; i++) {
BRect r;
link.Read<BRect>(&r);
region.Include(r);
if (status == B_OK && rectCount >= 0) {
for (int32 i = 0; i < rectCount; i++) {
clipping_rect r;
status = link.Read<clipping_rect>(&r);
if (status < B_OK)
break;
region.Include(r);
}
} 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);
}
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;
}

View File

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

View File

@ -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