14 Layer::Layer(BRect frame
, const char* name
, uint32 rm
, uint32 flags
, rgb_color c
)
17 fOrigin
.Set(0.0f
, 0.0f
);
46 Layer::ConvertToScreen2(BRect
* rect
) const
50 rect
->OffsetBy(-fOrigin
.x
, -fOrigin
.y
);
51 rect
->OffsetBy(fFrame
.left
, fFrame
.top
);
53 fParent
->ConvertToScreen2(rect
);
58 Layer::ConvertToScreen2(BRegion
* reg
) const
62 reg
->OffsetBy(-fOrigin
.x
, -fOrigin
.y
);
63 reg
->OffsetBy(fFrame
.left
, fFrame
.top
);
65 fParent
->ConvertToScreen2(reg
);
70 Layer::GetRootLayer() const // we already have
76 return fParent
->GetRootLayer();
82 Layer::BottomChild() const // we already have
89 Layer::TopChild() const// we already have
96 Layer::UpperSibling() const// we already have
98 fCurrent
= fCurrent
->fUpper
;
103 Layer::LowerSibling() const// we already have
105 fCurrent
= fCurrent
->fLower
;
110 Layer::AddLayer(Layer
* layer
)// we already have
112 if( layer
->fParent
!= NULL
) {
113 printf("ERROR: Layer already has a parent\n");
117 layer
->fParent
= this;
124 fBottom
->fLower
= layer
;
125 layer
->fUpper
= fBottom
;
130 Layer::RemLayer(Layer
* layer
)// we already have
132 if(!layer
->fParent
|| layer
->fParent
!= this) {
133 printf("ERROR: Rem: Layer doesn't have a fParent or !=this\n");
137 layer
->fParent
= NULL
;
140 fTop
= layer
->fLower
;
142 if(fBottom
== layer
)
143 fBottom
= layer
->fUpper
;
145 if(layer
->fUpper
!= NULL
)
146 layer
->fUpper
->fLower
= layer
->fLower
;
148 if(layer
->fLower
!= NULL
)
149 layer
->fLower
->fUpper
= layer
->fUpper
;
151 layer
->fUpper
= NULL
;
152 layer
->fLower
= NULL
;
154 layer
->clear_visible_regions(); // TAKE
160 Layer::IsHidden() const
165 // TODO: remove the following 2 lines when for real.
170 return fParent
->IsHidden();
180 if (fParent
&& !fParent
->IsHidden() && GetRootLayer()) {
181 // save fullVisible so we know what to invalidate
182 BRegion
invalid(fFullVisible
);
184 clear_visible_regions();
186 if (invalid
.Frame().IsValid())
187 fParent
->Invalidate(invalid
, this);
196 if (fParent
&& !fParent
->IsHidden() && GetRootLayer()) {
199 get_user_regions(invalid
);
201 if (invalid
.CountRects() > 0)
202 fParent
->Invalidate(invalid
, this);
207 Layer::Invalidate(const BRegion
&invalid
, const Layer
*startFrom
)
209 BRegion
localVisible(fFullVisible
);
210 localVisible
.IntersectWith(&invalid
);
211 rebuild_visible_regions(invalid
, localVisible
,
212 startFrom
? startFrom
: BottomChild());
214 // add localVisible to our RootLayer's redraw region.
215 GetRootLayer()->fRedrawReg
.Include(&localVisible
);
216 GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
220 Layer::resize_layer_frame_by(float x
, float y
)
222 uint16 rm
= fResizeMode
& 0x0000FFFF;
223 BRect newFrame
= fFrame
;
225 if ((rm
& 0x0F00U
) == _VIEW_LEFT_
<< 8)
226 newFrame
.left
+= 0.0f
;
227 else if ((rm
& 0x0F00U
) == _VIEW_RIGHT_
<< 8)
229 else if ((rm
& 0x0F00U
) == _VIEW_CENTER_
<< 8)
230 newFrame
.left
+= x
/2;
232 if ((rm
& 0x000FU
) == _VIEW_LEFT_
)
233 newFrame
.right
+= 0.0f
;
234 else if ((rm
& 0x000FU
) == _VIEW_RIGHT_
)
236 else if ((rm
& 0x000FU
) == _VIEW_CENTER_
)
237 newFrame
.right
+= x
/2;
239 if ((rm
& 0xF000U
) == _VIEW_TOP_
<< 12)
240 newFrame
.top
+= 0.0f
;
241 else if ((rm
& 0xF000U
) == _VIEW_BOTTOM_
<< 12)
243 else if ((rm
& 0xF000U
) == _VIEW_CENTER_
<< 12)
246 if ((rm
& 0x00F0U
) == _VIEW_TOP_
<< 4)
247 newFrame
.bottom
+= 0.0f
;
248 else if ((rm
& 0x00F0U
) == _VIEW_BOTTOM_
<< 4)
249 newFrame
.bottom
+= y
;
250 else if ((rm
& 0x00F0U
) == _VIEW_CENTER_
<< 4)
251 newFrame
.bottom
+= y
/2;
253 if (newFrame
!= fFrame
) {
256 dx
= newFrame
.Width() - fFrame
.Width();
257 dy
= newFrame
.Height() - fFrame
.Height();
261 if (dx
!= 0.0f
|| dy
!= 0.0f
) {
262 // call hook function
263 ResizedByHook(dx
, dy
, true); // automatic
265 for (Layer
*lay
= BottomChild(); lay
; lay
= UpperSibling())
266 lay
->resize_layer_frame_by(dx
, dy
);
274 Layer::rezize_layer_redraw_more(BRegion
®
, float dx
, float dy
)
276 if (dx
== 0 && dy
== 0)
279 for (Layer
*lay
= BottomChild(); lay
; lay
= UpperSibling()) {
280 uint16 rm
= lay
->fResizeMode
& 0x0000FFFF;
282 if ((rm
& 0x0F0F) == (uint16
)B_FOLLOW_LEFT_RIGHT
|| (rm
& 0xF0F0) == (uint16
)B_FOLLOW_TOP_BOTTOM
) {
283 // NOTE: this is not exactly corect, but it works :-)
284 // Normaly we shoud've used the lay's old, required region - the one returned
285 // from get_user_region() with the old frame, and the current one. lay->Bounds()
286 // works for the moment so we leave it like this.
288 // calculate the old bounds.
289 BRect
oldBounds(lay
->Bounds());
290 if ((rm
& 0x0F0F) == (uint16
)B_FOLLOW_LEFT_RIGHT
)
291 oldBounds
.right
-=dx
;
292 if ((rm
& 0xF0F0) == (uint16
)B_FOLLOW_TOP_BOTTOM
)
293 oldBounds
.bottom
-=dy
;
295 // compute the region that became visible because we got bigger OR smaller.
296 BRegion
regZ(lay
->Bounds());
297 regZ
.Include(oldBounds
);
298 regZ
.Exclude(oldBounds
&lay
->Bounds());
300 lay
->ConvertToScreen2(®Z
);
302 // intersect that with this'(not lay's) fullVisible region
303 regZ
.IntersectWith(&fFullVisible
);
306 lay
->rezize_layer_redraw_more(reg
,
307 (rm
& 0x0F0F) == (uint16
)B_FOLLOW_LEFT_RIGHT
? dx
: 0,
308 (rm
& 0xF0F0) == (uint16
)B_FOLLOW_TOP_BOTTOM
? dy
: 0);
311 // reg.Include(&lay->fFullVisible);
314 if (((rm
& 0x0F0F) == (uint16
)B_FOLLOW_RIGHT
&& dx
!= 0) ||
315 ((rm
& 0x0F0F) == (uint16
)B_FOLLOW_H_CENTER
&& dx
!= 0) ||
316 ((rm
& 0xF0F0) == (uint16
)B_FOLLOW_BOTTOM
&& dy
!= 0)||
317 ((rm
& 0xF0F0) == (uint16
)B_FOLLOW_V_CENTER
&& dy
!= 0))
319 reg
.Include(&lay
->fFullVisible
);
325 Layer::resize_layer_full_update_on_resize(BRegion
®
, float dx
, float dy
)
327 if (dx
== 0 && dy
== 0)
330 for (Layer
*lay
= BottomChild(); lay
; lay
= UpperSibling()) {
331 uint16 rm
= lay
->fResizeMode
& 0x0000FFFF;
333 if ((rm
& 0x0F0F) == (uint16
)B_FOLLOW_LEFT_RIGHT
|| (rm
& 0xF0F0) == (uint16
)B_FOLLOW_TOP_BOTTOM
) {
334 if (lay
->fFlags
& B_FULL_UPDATE_ON_RESIZE
&& lay
->fVisible
.CountRects() > 0)
335 reg
.Include(&lay
->fVisible
);
337 lay
->resize_layer_full_update_on_resize(reg
,
338 (rm
& 0x0F0F) == (uint16
)B_FOLLOW_LEFT_RIGHT
? dx
: 0,
339 (rm
& 0xF0F0) == (uint16
)B_FOLLOW_TOP_BOTTOM
? dy
: 0);
345 Layer::ResizeBy(float dx
, float dy
)
347 fFrame
.Set(fFrame
.left
, fFrame
.top
, fFrame
.right
+dx
, fFrame
.bottom
+dy
);
349 // resize children using their resize_mask.
350 for (Layer
*lay
= BottomChild(); lay
; lay
= UpperSibling())
351 lay
->resize_layer_frame_by(dx
, dy
);
353 // call hook function
354 if (dx
!= 0.0f
|| dy
!= 0.0f
)
355 ResizedByHook(dx
, dy
, false); // manual
357 if (!IsHidden() && GetRootLayer()) {
358 BRegion
oldFullVisible(fFullVisible
);
359 // this is required to invalidate the old border
360 BRegion
oldVisible(fVisible
);
362 // in case they moved, bottom, right and center aligned layers must be redrawn
364 rezize_layer_redraw_more(redrawMore
, dx
, dy
);
366 // we'll invalidate the old area and the new, maxmial one.
368 get_user_regions(invalid
);
369 invalid
.Include(&fFullVisible
);
371 clear_visible_regions();
373 fParent
->RebuildVisibleRegions(invalid
, this);
375 // done rebuilding regions, now redraw regions that became visible
377 // what's invalid, are the differences between to old and the new fullVisible region
378 // 1) in case we grow.
379 BRegion
redrawReg(fFullVisible
);
380 redrawReg
.Exclude(&oldFullVisible
);
381 // 2) in case we shrink
382 BRegion
redrawReg2(oldFullVisible
);
383 redrawReg2
.Exclude(&fFullVisible
);
385 redrawReg
.Include(&redrawReg2
);
387 // for center, right and bottom alligned layers, redraw their old positions
388 redrawReg
.Include(&redrawMore
);
390 // layers that had their frame modified must be entirely redrawn.
391 rezize_layer_redraw_more(redrawReg
, dx
, dy
);
393 // add redrawReg to our RootLayer's redraw region.
394 GetRootLayer()->fRedrawReg
.Include(&redrawReg
);
395 // include layer's visible region in case we want a full update on resize
396 if (fFlags
& B_FULL_UPDATE_ON_RESIZE
&& fVisible
.Frame().IsValid()) {
397 resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg
, dx
, dy
);
399 GetRootLayer()->fRedrawReg
.Include(&fVisible
);
400 GetRootLayer()->fRedrawReg
.Include(&oldVisible
);
402 // clear canvas and set invalid regions for affected WinBorders
403 GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
407 void Layer::MoveBy(float dx
, float dy
)
409 if (dx
== 0.0f
&& dy
== 0.0f
)
412 // fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
413 fFrame
.OffsetBy(dx
, dy
);
415 // call hook function
418 if (!IsHidden() && GetRootLayer()) {
419 BRegion
oldFullVisible(fFullVisible
);
421 // we'll invalidate the old position and the new, maxmial one.
423 get_user_regions(invalid
);
424 invalid
.Include(&fFullVisible
);
426 clear_visible_regions();
428 fParent
->RebuildVisibleRegions(invalid
, this);
430 // done rebuilding regions, now copy common parts and redraw regions that became visible
432 // include the actual and the old fullVisible regions. later, we'll exclude the common parts.
433 BRegion
redrawReg(fFullVisible
);
434 redrawReg
.Include(&oldFullVisible
);
436 // offset to layer's new location so that we can calculate the common region.
437 oldFullVisible
.OffsetBy(dx
, dy
);
439 // finally we have the region that needs to be redrawn.
440 redrawReg
.Exclude(&oldFullVisible
);
442 // by intersecting the old fullVisible offseted to layer's new location, with the current
443 // fullVisible, we'll have the common region which can be copied using HW acceleration.
444 oldFullVisible
.IntersectWith(&fFullVisible
);
446 // offset back and instruct the HW to do the actual copying.
447 oldFullVisible
.OffsetBy(-dx
, -dy
);
448 GetRootLayer()->CopyRegion(&oldFullVisible
, dx
, dy
);
450 // add redrawReg to our RootLayer's redraw region.
451 GetRootLayer()->fRedrawReg
.Include(&redrawReg
);
452 GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
457 Layer::ScrollBy(float dx
, float dy
)
459 fOrigin
.Set(fOrigin
.x
+ dx
, fOrigin
.y
+ dy
);
461 if (!IsHidden() && GetRootLayer()) {
462 // set the region to be invalidated.
463 BRegion
invalid(fFullVisible
);
465 clear_visible_regions();
467 rebuild_visible_regions(invalid
, invalid
, BottomChild());
469 // for the moment we say that the whole surface needs to be redraw.
470 BRegion
redrawReg(fFullVisible
);
472 // offset old region so that we can start comparing.
473 invalid
.OffsetBy(dx
, dy
);
475 // compute the common region. we'll use HW acc to copy this to the new location.
476 invalid
.IntersectWith(&fFullVisible
);
477 GetRootLayer()->CopyRegion(&invalid
, -dx
, -dy
);
479 // common region goes back to its original location. then, by excluding
480 // it from curent fullVisible we'll obtain the region that needs to be redrawn.
481 invalid
.OffsetBy(-dx
, -dy
);
482 redrawReg
.Exclude(&invalid
);
484 GetRootLayer()->fRedrawReg
.Include(&redrawReg
);
485 GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
488 if (dx
!= 0.0f
|| dy
!= 0.0f
)
489 ScrolledByHook(dx
, dy
);
497 Layer::GetWantedRegion(BRegion
®
) // TAKE?
499 get_user_regions(reg
);
503 Layer::get_user_regions(BRegion
®
)
505 // 1) set to frame in screen coords
506 BRect
screenFrame(Bounds());
507 ConvertToScreen2(&screenFrame
);
508 reg
.Set(screenFrame
);
510 // 2) intersect with screen region
511 // TODO: remove locking when for real
513 BRegion
screenReg(GetRootLayer()->Bounds());
515 reg
.IntersectWith(&screenReg
);
517 // TODO: you MUST at some point uncomment this block!
519 // 3) impose user constrained regions
520 LayerData *stackData = fLayerData;
523 // transform in screen coords
524 BRegion screenReg(stackData->ClippingRegion());
525 ConvertToScreen2(&screenReg);
526 reg.IntersectWith(&screenReg);
527 stackData = stackData->prevState;
533 Layer::RebuildVisibleRegions(const BRegion
&invalid
, const Layer
*startFrom
)
535 BRegion
localVisible(fFullVisible
);
536 localVisible
.IntersectWith(&invalid
);
537 rebuild_visible_regions(invalid
, localVisible
, startFrom
);
541 Layer::rebuild_visible_regions(const BRegion
&invalid
,
542 const BRegion
&parentLocalVisible
,
543 const Layer
*startFrom
)
545 // no point in continuing if this layer is hidden. starting from here, all
546 // descendants have (and will have) invalid visible regions.
550 // no need to go deeper if the parent doesn't have a visible region anymore
551 // and our fullVisible region is also empty.
552 if (!parentLocalVisible
.Frame().IsValid() && !(fFullVisible
.CountRects() > 0))
555 bool fullRebuild
= false;
557 // intersect maximum wanted region with the invalid region
559 get_user_regions(common
);
560 common
.IntersectWith(&invalid
);
562 // if the resulted region is not valid, this layer is not in the catchment area
563 // of the region being invalidated
564 if (!common
.CountRects() > 0)
567 // now intersect with parent's visible part of the region that was/is invalidated
568 common
.IntersectWith(&parentLocalVisible
);
570 // exclude the invalid region
571 fFullVisible
.Exclude(&invalid
);
572 fVisible
.Exclude(&invalid
);
574 // put in what's really visible
575 fFullVisible
.Include(&common
);
577 // this is to allow a layer to hide some parts of itself so children
579 BRegion
unalteredVisible(common
);
580 bool altered
= alter_visible_for_children(common
);
582 for (Layer
*lay
= BottomChild(); lay
; lay
= UpperSibling()) {
583 if (lay
== startFrom
)
587 lay
->rebuild_visible_regions(invalid
, common
, lay
->BottomChild());
589 // to let children know much they can take from parent's visible region
590 common
.Exclude(&lay
->fFullVisible
);
591 // we've hidden some parts of our visible region from our children,
592 // and we must be in sysnc with this region too...
594 unalteredVisible
.Exclude(&lay
->fFullVisible
);
597 // the visible region of this layer is what left after all its children took
600 fVisible
.Include(&unalteredVisible
);
602 fVisible
.Include(&common
);
606 Layer::alter_visible_for_children(BRegion
®
)
608 // Empty Hook function
613 Layer::clear_visible_regions()
615 // OPT: maybe we should uncomment these lines for performance
616 //if (fFullVisible.CountRects() <= 0)
619 fVisible
.MakeEmpty();
620 fFullVisible
.MakeEmpty();
621 for (Layer
*child
= BottomChild(); child
; child
= UpperSibling())
622 child
->clear_visible_regions();
626 Layer::PrintToStream() const
628 printf("-> %s\n", fName
);
629 fVisible
.PrintToStream();
630 fFullVisible
.PrintToStream();
631 for (Layer
*child
= BottomChild(); child
; child
= UpperSibling())
632 child
->PrintToStream();