Layer.cpp revision 3df649ecb33bb25aeb4ecb3cee6184eef4451081
1//------------------------------------------------------------------------------
2//	Copyright (c) 2001-2005, Haiku, Inc.
3//
4//	Permission is hereby granted, free of charge, to any person obtaining a
5//	copy of this software and associated documentation files (the "Software"),
6//	to deal in the Software without restriction, including without limitation
7//	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8//	and/or sell copies of the Software, and to permit persons to whom the
9//	Software is furnished to do so, subject to the following conditions:
10//
11//	The above copyright notice and this permission notice shall be included in
12//	all copies or substantial portions of the Software.
13//
14//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19//	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20//	DEALINGS IN THE SOFTWARE.
21//
22//	File Name:		Layer.cpp
23//	Author:			DarkWyrm <bpmagic@columbus.rr.com>
24//					Adi Oanca <adioanca@cotty.iren.ro>
25//					Stephan A��mus <superstippi@gmx.de>
26//	Description:	Class used for rendering to the frame buffer. One layer per
27//					view on screen and also for window decorators
28//
29//------------------------------------------------------------------------------
30#include <string.h>
31#include <stdio.h>
32#include <stdlib.h>
33
34#include <AppDefs.h>
35#include <Message.h>
36#include <Region.h>
37#include <View.h>
38
39#include "DebugInfoManager.h"
40#include "DisplayDriver.h"
41#include "LayerData.h"
42#include "PortLink.h"
43#include "RootLayer.h"
44#include "ServerProtocol.h"
45#include "ServerWindow.h"
46#include "WinBorder.h"
47#include "Layer.h"
48#include "ServerBitmap.h"
49
50//#define DEBUG_LAYER
51#ifdef DEBUG_LAYER
52#	define STRACE(x) printf x
53#else
54#	define STRACE(x) ;
55#endif
56
57//#define DEBUG_LAYER_REBUILD
58#ifdef DEBUG_LAYER_REBUILD
59#	define RBTRACE(x) printf x
60#else
61#	define RBTRACE(x) ;
62#endif
63
64enum {
65	B_LAYER_ACTION_NONE = 0,
66	B_LAYER_ACTION_MOVE,
67	B_LAYER_ACTION_RESIZE
68};
69
70Layer::Layer(BRect frame, const char* name, int32 token,
71			 uint32 resize, uint32 flags, DisplayDriver* driver)
72	:
73	fFrame(frame), // in parent coordinates
74//	fBoundsLeftTop(0.0, 0.0),
75
76	// Layer does not start out as a part of the tree
77	fOwner(NULL),
78	fParent(NULL),
79	fUpperSibling(NULL),
80	fLowerSibling(NULL),
81	fTopChild(NULL),
82	fBottomChild(NULL),
83	fCurrent(NULL),
84
85	// all regions (fVisible, fFullVisible, fFull) start empty
86#ifndef NEW_CLIPPING
87	fVisible(),
88	fFullVisible(),
89	fFull(),
90	fFrameAction(B_LAYER_ACTION_NONE),
91#else
92	fVisible2(),
93	fFullVisible2(),
94#endif
95
96#ifndef NEW_CLIPPING
97	fClipReg(&fVisible),
98#else
99	fClipReg(&fVisible2),
100#endif
101	fServerWin(NULL),
102	fName(new BString(name)),
103	fViewToken(token),
104
105	fFlags(flags),
106	fResizeMode(resize),
107	fEventMask(0UL),
108	fEventOptions(0UL),
109	fHidden(false),
110	fIsTopLayer(false),
111
112	fAdFlags(0),
113	fClassID(AS_LAYER_CLASS),
114
115	fDriver(driver),
116	fLayerData(new LayerData()),
117
118	fRootLayer(NULL),
119
120	fViewColor(255, 255, 255, 255),
121	fBackgroundBitmap(NULL),
122	fOverlayBitmap(NULL)
123{
124	if (!frame.IsValid()) {
125char helper[1024];
126sprintf(helper, "Layer::Layer(BRect(%.1f, %.1f, %.1f, %.1f), name: %s, token: %ld) - frame is invalid\n",
127		frame.left, frame.top, frame.right, frame.bottom, name, token);
128CRITICAL(helper);
129		fFrame.Set(0, 0, 10, 10);
130	}
131
132	if (!fDriver)
133		CRITICAL("You MUST have a valid driver to init a Layer object\n");
134
135	STRACE(("Layer(%s) successfuly created\n", GetName()));
136}
137
138//! Destructor frees all allocated heap space
139Layer::~Layer()
140{
141	delete fLayerData;
142	delete fName;
143
144	// TODO: uncomment!
145	//PruneTree();
146
147//	fServerWin->RemoveChild(fDriver);
148//	delete fDriver;
149}
150
151/*!
152	\brief Adds a child layer to the current one
153	\param layer a new child layer
154	\param serverWin the serverwindow to which the layer will belong
155
156	Unlike the BView version, if the layer already belongs to another, then
157	it spits an error to stdout and returns.
158*/
159void
160Layer::AddChild(Layer* layer, ServerWindow* serverWin)
161{
162	STRACE(("Layer(%s)::AddChild(%s) START\n", GetName(), layer->GetName()));
163
164	if (layer->fParent != NULL) {
165		printf("ERROR: AddChild(): Layer already has a parent\n");
166		return;
167	}
168
169	// 1) attach layer to the tree structure
170	layer->fParent = this;
171
172	// if we have children already, bump the current front child back one and
173	// make the new child the frontmost layer
174	if (fBottomChild) {
175		layer->fUpperSibling = fBottomChild;
176		fBottomChild->fLowerSibling	= layer;
177	} else {
178		fTopChild = layer;
179	}
180	fBottomChild = layer;
181
182	// if we have no RootLayer yet, then there is no need to set any parameters --
183	// they will be set when the RootLayer for this tree will be added
184	// to the main tree structure.
185	if (!fRootLayer) {
186		STRACE(("Layer(%s)::AddChild(%s) END\n", GetName(), layer->GetName()));
187		return;
188	}
189
190	// 2) Iterate over the newly-added layer and all its children, setting the
191	//	root layer and server window and also rebuilding the full-size region
192	//	for every descendant of the newly-added layer
193
194	//c = short for: current
195	Layer* c = layer;
196	Layer* stop = layer;
197	while (true) {
198		// action block
199
200		// 2.1) set the RootLayer for this object.
201		c->SetRootLayer(c->fParent->fRootLayer);
202
203		// 2.2) this Layer must know if it has a ServerWindow object attached.
204		c->fServerWin=serverWin;
205
206		// 2.3) we are attached to the main tree so build our full region.
207#ifndef NEW_CLIPPING
208		c->RebuildFullRegion();
209#endif
210		// tree parsing algorithm
211		if (c->fTopChild) {
212			// go deep
213			c = c->fTopChild;
214		} else {
215			// go right or up
216
217			if (c == stop) // out trip is over
218				break;
219
220			if (c->fLowerSibling) {
221				// go right
222				c = c->fLowerSibling;
223			} else {
224				// go up
225				while (!c->fParent->fLowerSibling && c->fParent != stop)
226					c = c->fParent;
227
228				if (c->fParent == stop) // that's enough!
229					break;
230
231				c = c->fParent->fLowerSibling;
232			}
233		}
234	}
235
236	STRACE(("Layer(%s)::AddChild(%s) END\n", GetName(), layer->GetName()));
237}
238
239/*!
240	\brief Removes a child layer from the current one
241	\param layer the layer to remove
242
243	If the layer does not belong to the the current layer, then this function
244	spits out an error to stdout and returns
245*/
246void
247Layer::RemoveChild(Layer *layer)
248{
249	STRACE(("Layer(%s)::RemoveChild(%s) START\n", GetName(), layer->GetName()));
250
251	if (!layer->fParent) {
252		printf("ERROR: RemoveChild(): Layer doesn't have a fParent\n");
253		return;
254	}
255
256	if (layer->fParent != this) {
257		printf("ERROR: RemoveChild(): Layer is not a child of this layer\n");
258		return;
259	}
260
261	// 1) remove this layer from the main tree.
262
263	// Take care of fParent
264	layer->fParent = NULL;
265
266	if (fTopChild == layer)
267		fTopChild = layer->fLowerSibling;
268
269	if (fBottomChild == layer)
270		fBottomChild = layer->fUpperSibling;
271
272	// Take care of siblings
273	if (layer->fUpperSibling != NULL)
274		layer->fUpperSibling->fLowerSibling	= layer->fLowerSibling;
275
276	if (layer->fLowerSibling != NULL)
277		layer->fLowerSibling->fUpperSibling = layer->fUpperSibling;
278
279	layer->fUpperSibling = NULL;
280	layer->fLowerSibling = NULL;
281
282#ifdef NEW_CLIPPING
283	layer->clear_visible_regions();
284#endif
285
286	// 2) Iterate over all of the removed-layer's descendants and unset the
287	//	root layer, server window, and all redraw-related regions
288
289	Layer* c = layer; //c = short for: current
290	Layer* stop = layer;
291
292	while (true) {
293		// action block
294		{
295			// 2.1) set the RootLayer for this object.
296			c->SetRootLayer(NULL);
297			// 2.2) this Layer must know if it has a ServerWindow object attached.
298			c->fServerWin = NULL;
299			// 2.3) we were removed from the main tree so clear our full region.
300#ifndef NEW_CLIPPING
301			c->fFull.MakeEmpty();
302			// 2.4) clear fullVisible region.
303			c->fFullVisible.MakeEmpty();
304			// 2.5) we don't have a visible region anymore.
305			c->fVisible.MakeEmpty();
306#endif
307		}
308
309		// tree parsing algorithm
310		if (c->fTopChild) {
311			// go deep
312			c = c->fTopChild;
313		} else {
314			// go right or up
315			if (c == stop) // out trip is over
316				break;
317
318			if (c->fLowerSibling) {
319				// go right
320				c = c->fLowerSibling;
321			} else {
322				// go up
323				while(!c->fParent->fLowerSibling && c->fParent != stop)
324					c = c->fParent;
325
326				if (c->fParent == stop) // that enough!
327					break;
328
329				c = c->fParent->fLowerSibling;
330			}
331		}
332	}
333	STRACE(("Layer(%s)::RemoveChild(%s) END\n", GetName(), layer->GetName()));
334}
335
336//! Removes the calling layer from the tree
337void
338Layer::RemoveSelf()
339{
340	// A Layer removes itself from the tree (duh)
341	if (fParent == NULL) {
342		printf("ERROR: RemoveSelf(): Layer doesn't have a fParent\n");
343		return;
344	}
345	fParent->RemoveChild(this);
346}
347
348/*!
349	\brief Determins if the calling layer has the passed layer as a child
350	\return true if the child is owned by the caller, false if not
351*/
352bool
353Layer::HasChild(Layer* layer)
354{
355	for (Layer *lay = TopChild(); lay; lay = LowerSibling()) {
356		if (lay == layer)
357			return true;
358	}
359	return false;
360}
361
362//! Returns the number of children
363uint32
364Layer::CountChildren(void) const
365{
366	uint32 count = 0;
367	Layer *lay = TopChild();
368	while (lay != NULL) {
369		lay	= LowerSibling();
370		count++;
371	}
372	return count;
373}
374
375/*!
376	\brief Finds a child of the caller based on its token ID
377	\param token ID of the layer to find
378	\return Pointer to the layer or NULL if not found
379*/
380Layer*
381Layer::FindLayer(const int32 token)
382{
383	// recursive search for a layer based on its view token
384	Layer* lay;
385	Layer* trylay;
386
387	// Search child layers first
388	for (lay = TopChild(); lay; lay = LowerSibling()) {
389		if (lay->fViewToken == token)
390			return lay;
391	}
392
393	// Hmmm... not in this layer's children. Try lower descendants
394	for (lay = TopChild(); lay != NULL; lay = LowerSibling()) {
395		trylay = lay->FindLayer(token);
396		if (trylay)
397			return trylay;
398	}
399
400	// Well, we got this far in the function,
401	// so apparently there is no match to be found
402	return NULL;
403}
404
405/*!
406	\brief Returns the layer at the given point
407	\param pt The point to look the layer at
408	\return The layer containing the point or NULL if no layer found
409*/
410Layer*
411Layer::LayerAt(const BPoint &pt)
412{
413#ifndef NEW_CLIPPING
414	if (fVisible.Contains(pt))
415		return this;
416
417	if (fFullVisible.Contains(pt)) {
418		Layer *lay = NULL;
419		for (Layer* child = BottomChild(); child; child = UpperSibling()) {
420			lay = child->LayerAt(pt);
421			if (lay)
422				return lay;
423		}
424	}
425#else
426	if (fVisible2.Contains(pt))
427		return this;
428
429	if (fFullVisible2.Contains(pt)) {
430		Layer *lay = NULL;
431		for (Layer* child = BottomChild(); child; child = UpperSibling()) {
432			lay = child->LayerAt(pt);
433			if (lay)
434				return lay;
435		}
436	}
437#endif
438	return NULL;
439}
440
441// TopChild
442Layer*
443Layer::TopChild() const
444{
445	fCurrent = fTopChild;
446	return fCurrent;
447}
448
449// LowerSibling
450Layer*
451Layer::LowerSibling() const
452{
453	fCurrent = fCurrent->fLowerSibling;
454	return fCurrent;
455}
456
457// UpperSibling
458Layer*
459Layer::UpperSibling() const
460{
461	fCurrent = fCurrent->fUpperSibling;
462	return fCurrent;
463}
464
465// BottomChild
466Layer*
467Layer::BottomChild() const
468{
469	fCurrent = fBottomChild;
470	return fCurrent;
471}
472
473#ifndef NEW_CLIPPING
474
475//! Rebuilds the layer's "completely visible" region
476void
477Layer::RebuildFullRegion(void)
478{
479	STRACE(("Layer(%s)::RebuildFullRegion()\n", GetName()));
480
481	if (fParent)
482		fFull.Set(fParent->ConvertToTop(fFrame ));
483	else
484		fFull.Set(fFrame);
485
486	// TODO: restrict to screen coordinates
487
488	// TODO: Convert to screen coordinates
489
490	LayerData *ld;
491	ld = fLayerData;
492	do {
493		// clip to user region
494		if (const BRegion* userClipping = ld->ClippingRegion())
495			fFull.IntersectWith(userClipping);
496
497	} while ((ld = ld->prevState));
498}
499
500// StartRebuildRegions
501void
502Layer::StartRebuildRegions( const BRegion& reg, Layer *target, uint32 action, BPoint& pt)
503{
504	STRACE(("Layer(%s)::StartRebuildRegions() START\n", GetName()));
505	RBTRACE(("\n\nLayer(%s)::StartRebuildRegions() START\n", GetName()));
506	if (!fParent)
507		fFullVisible = fFull;
508
509	BRegion oldVisible = fVisible;
510
511	fVisible = fFullVisible;
512
513	// Rebuild regions for children...
514	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
515		if (lay == target)
516			lay->RebuildRegions(reg, action, pt, BPoint(0.0f, 0.0f));
517		else
518			lay->RebuildRegions(reg, B_LAYER_NONE, pt, BPoint(0.0f, 0.0f));
519	}
520
521	#ifdef DEBUG_LAYER_REBUILD
522		printf("\nSRR: Layer(%s) ALMOST done regions:\n", GetName());
523		printf("\tVisible Region:\n");
524		fVisible.PrintToStream();
525		printf("\tFull Visible Region:\n");
526		fFullVisible.PrintToStream();
527	#endif
528
529	BRegion redrawReg(fVisible);
530
531	// if this is the first time
532	if (oldVisible.CountRects() > 0)
533		redrawReg.Exclude(&oldVisible);
534
535	if (redrawReg.CountRects() > 0)
536		fRootLayer->fRedrawReg.Include(&redrawReg);
537
538	#ifdef DEBUG_LAYER_REBUILD
539		printf("\nLayer(%s)::StartRebuildRegions() DONE. Results:\n", GetName());
540		printf("\tRedraw Region:\n");
541		fRootLayer->fRedrawReg.PrintToStream();
542		printf("\tCopy Region:\n");
543		for (int32 k=0; k<fRootLayer->fCopyRegList.CountItems(); k++) {
544			((BRegion*)(fRootLayer->fCopyRegList.ItemAt(k)))->PrintToStream();
545			((BPoint*)(fRootLayer->fCopyList.ItemAt(k)))->PrintToStream();
546		}
547		printf("\n");
548	#endif
549
550	STRACE(("Layer(%s)::StartRebuildRegions() END\n", GetName()));
551	RBTRACE(("Layer(%s)::StartRebuildRegions() END\n", GetName()));
552}
553
554// RebuildRegions
555void
556Layer::RebuildRegions( const BRegion& reg, uint32 action, BPoint pt, BPoint ptOffset)
557{
558	STRACE(("Layer(%s)::RebuildRegions() START\n", GetName()));
559
560	// TODO:/NOTE: this method must be executed as quickly as possible.
561
562	// Currently SendView[Moved/Resized]Msg() simply constructs a message and calls
563	// ServerWindow::SendMessageToClient(). This involves the alternative use of
564	// kernel and this code in the CPU, so there are a lot of context switches.
565	// This is NOT good at all!
566
567	// One alternative would be the use of a BMessageQueue per ServerWindows OR only
568	// one for app_server which will be emptied as soon as this critical operation ended.
569	// Talk to DW, Gabe.
570
571	BRegion	oldRegion;
572	uint32 newAction = action;
573	BPoint newPt = pt;
574	BPoint newOffset = ptOffset; // used for resizing only
575
576	BPoint dummyNewLocation;
577
578	RRLabel1:
579	switch(action) {
580		case B_LAYER_NONE: {
581			RBTRACE(("1) Layer(%s): Action B_LAYER_NONE\n", GetName()));
582			STRACE(("1) Layer(%s): Action B_LAYER_NONE\n", GetName()));
583			oldRegion = fVisible;
584			break;
585		}
586		case B_LAYER_MOVE: {
587			RBTRACE(("1) Layer(%s): Action B_LAYER_MOVE\n", GetName()));
588			STRACE(("1) Layer(%s): Action B_LAYER_MOVE\n", GetName()));
589			oldRegion = fFullVisible;
590			fFrame.OffsetBy(pt.x, pt.y);
591			fFull.OffsetBy(pt.x, pt.y);
592
593			// TODO: investigate combining frame event messages for efficiency
594			//SendViewMovedMsg();
595			AddToViewsWithInvalidCoords();
596
597			newAction	= B_LAYER_SIMPLE_MOVE;
598			break;
599		}
600		case B_LAYER_SIMPLE_MOVE: {
601			RBTRACE(("1) Layer(%s): Action B_LAYER_SIMPLE_MOVE\n", GetName()));
602			STRACE(("1) Layer(%s): Action B_LAYER_SIMPLE_MOVE\n", GetName()));
603			fFull.OffsetBy(pt.x, pt.y);
604
605			break;
606		}
607		case B_LAYER_RESIZE: {
608			RBTRACE(("1) Layer(%s): Action B_LAYER_RESIZE\n", GetName()));
609			STRACE(("1) Layer(%s): Action B_LAYER_RESIZE\n", GetName()));
610			oldRegion	= fVisible;
611
612			fFrame.right	+= pt.x;
613			fFrame.bottom	+= pt.y;
614			RebuildFullRegion();
615
616			// TODO: investigate combining frame event messages for efficiency
617			//SendViewResizedMsg();
618			AddToViewsWithInvalidCoords();
619
620			newAction = B_LAYER_MASK_RESIZE;
621			break;
622		}
623		case B_LAYER_MASK_RESIZE: {
624			RBTRACE(("1) Layer(%s): Action B_LAYER_MASK_RESIZE\n", GetName()));
625			STRACE(("1) Layer(%s): Action B_LAYER_MASK_RESIZE\n", GetName()));
626			oldRegion = fVisible;
627
628			BPoint offset, rSize;
629			BPoint coords[2];
630
631			ResizeOthers(pt.x, pt.y, coords, NULL);
632			offset = coords[0];
633			rSize = coords[1];
634			newOffset = offset + ptOffset;
635
636			if (!(rSize.x == 0.0f && rSize.y == 0.0f)) {
637				fFrame.OffsetBy(offset);
638				fFrame.right += rSize.x;
639				fFrame.bottom += rSize.y;
640				RebuildFullRegion();
641
642				// TODO: investigate combining frame event messages for efficiency
643				//SendViewResizedMsg();
644				AddToViewsWithInvalidCoords();
645
646				newAction = B_LAYER_MASK_RESIZE;
647				newPt = rSize;
648				dummyNewLocation = newOffset;
649			} else {
650				if (!(offset.x == 0.0f && offset.y == 0.0f)) {
651					pt = newOffset;
652					action = B_LAYER_MOVE;
653					newPt = pt;
654					goto RRLabel1;
655				} else {
656					pt = ptOffset;
657					action = B_LAYER_MOVE;
658					newPt = pt;
659					goto RRLabel1;
660				}
661			}
662			break;
663		}
664	}
665
666	if (!IsHidden()) {
667		#ifdef DEBUG_LAYER_REBUILD
668			printf("Layer(%s) real action START\n", GetName());
669			fFull.PrintToStream();
670		#endif
671		fFullVisible.MakeEmpty();
672		fVisible = fFull;
673
674		if (fParent && fVisible.CountRects() > 0) {
675			// not the usual case, but support fot this is needed.
676			if (fParent->fAdFlags & B_LAYER_CHILDREN_DEPENDANT) {
677				#ifdef DEBUG_LAYER_REBUILD
678					printf("   B_LAYER_CHILDREN_DEPENDANT Parent\n");
679				#endif
680
681				// because we're skipping one level, we need to do out
682				// parent business as well.
683
684				// our visible area is relative to our parent's parent.
685				if (fParent->fParent)
686					fVisible.IntersectWith(&(fParent->fParent->fVisible));
687
688				// exclude parent's visible area which could be composed by
689				// prior siblings' visible areas.
690				if (fVisible.CountRects() > 0)
691					fVisible.Exclude(&(fParent->fVisible));
692
693				// we have a final visible area. Include it to our parent's one,
694				// exclude from parent's parent.
695				if (fVisible.CountRects() > 0) {
696					fParent->fFullVisible.Include(&fVisible);
697
698					if (fParent->fParent)
699						fParent->fParent->fVisible.Exclude(&fVisible);
700				}
701			} else {
702				// for 95+% of cases
703
704				#ifdef DEBUG_LAYER_REBUILD
705					printf("   (!)B_LAYER_CHILDREN_DEPENDANT Parent\n");
706				#endif
707
708				// the visible area is the one common with parent's one.
709				fVisible.IntersectWith(&(fParent->fVisible));
710
711				// exclude from parent's visible area. we're the owners now.
712				if (fVisible.CountRects() > 0)
713					fParent->fVisible.Exclude(&fVisible);
714			}
715		}
716		fFullVisible = fVisible;
717	}
718
719	// Rebuild regions for children...
720	for(Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling())
721		lay->RebuildRegions(reg, newAction, newPt, newOffset);
722
723	#ifdef DEBUG_LAYER_REBUILD
724		printf("\nLayer(%s) ALMOST done regions:\n", GetName());
725		printf("\tVisible Region:\n");
726		fVisible.PrintToStream();
727		printf("\tFull Visible Region:\n");
728		fFullVisible.PrintToStream();
729	#endif
730
731	if(!IsHidden()) {
732		switch(action) {
733			case B_LAYER_NONE: {
734				RBTRACE(("2) Layer(%s): Action B_LAYER_NONE\n", GetName()));
735				BRegion r(fVisible);
736				if (oldRegion.CountRects() > 0)
737					r.Exclude(&oldRegion);
738
739				if(r.CountRects() > 0)
740					fRootLayer->fRedrawReg.Include(&r);
741				break;
742			}
743			case B_LAYER_MOVE: {
744				RBTRACE(("2) Layer(%s): Action B_LAYER_MOVE\n", GetName()));
745				BRegion redrawReg;
746				BRegion	*copyReg = new BRegion();
747				BRegion	screenReg(fRootLayer->Bounds());
748
749				oldRegion.OffsetBy(pt.x, pt.y);
750				oldRegion.IntersectWith(&fFullVisible);
751
752				*copyReg = oldRegion;
753				copyReg->IntersectWith(&screenReg);
754				if (copyReg->CountRects() > 0 && !(pt.x == 0.0f && pt.y == 0.0f)) {
755					copyReg->OffsetBy(-pt.x, -pt.y);
756					BPoint		*point = new BPoint(pt);
757					fRootLayer->fCopyRegList.AddItem(copyReg);
758					fRootLayer->fCopyList.AddItem(point);
759				} else {
760					delete copyReg;
761				}
762
763				redrawReg	= fFullVisible;
764				redrawReg.Exclude(&oldRegion);
765				if (redrawReg.CountRects() > 0 && !(pt.x == 0.0f && pt.y == 0.0f)) {
766					fRootLayer->fRedrawReg.Include(&redrawReg);
767				}
768
769				break;
770			}
771			case B_LAYER_RESIZE: {
772				RBTRACE(("2) Layer(%s): Action B_LAYER_RESIZE\n", GetName()));
773				BRegion redrawReg;
774
775				redrawReg = fVisible;
776				redrawReg.Exclude(&oldRegion);
777				if(redrawReg.CountRects() > 0)
778					fRootLayer->fRedrawReg.Include(&redrawReg);
779
780				break;
781			}
782			case B_LAYER_MASK_RESIZE: {
783				RBTRACE(("2) Layer(%s): Action B_LAYER_MASK_RESIZE\n", GetName()));
784				BRegion redrawReg;
785				BRegion	*copyReg = new BRegion();
786
787				oldRegion.OffsetBy(dummyNewLocation.x, dummyNewLocation.y);
788
789				redrawReg	= fVisible;
790				redrawReg.Exclude(&oldRegion);
791				if (redrawReg.CountRects() > 0)
792					fRootLayer->fRedrawReg.Include(&redrawReg);
793
794				*copyReg = fVisible;
795				copyReg->IntersectWith(&oldRegion);
796				copyReg->OffsetBy(-dummyNewLocation.x, -dummyNewLocation.y);
797				if (copyReg->CountRects() > 0
798					&& !(dummyNewLocation.x == 0.0f && dummyNewLocation.y == 0.0f)) {
799					fRootLayer->fCopyRegList.AddItem(copyReg);
800					fRootLayer->fCopyList.AddItem(new BPoint(dummyNewLocation));
801				}
802
803				break;
804			}
805			default:
806				RBTRACE(("2) Layer(%s): Action default\n", GetName()));
807				break;
808		}
809	}
810/*	if (IsHidden()) {
811		fFullVisible.MakeEmpty();
812		fVisible.MakeEmpty();
813	}
814*/
815
816	STRACE(("Layer(%s)::RebuildRegions() END\n", GetName()));
817}
818
819// ResizeOthers
820uint32
821Layer::ResizeOthers(float x, float y, BPoint coords[], BPoint *ptOffset)
822{
823	STRACE(("Layer(%s)::ResizeOthers() START\n", GetName()));
824	uint32 rmask = fResizeMode;
825
826	// offset
827	coords[0].x	= 0.0f;
828	coords[0].y	= 0.0f;
829
830	// resize by width/height
831	coords[1].x	= 0.0f;
832	coords[1].y	= 0.0f;
833
834	if ((rmask & 0x00000f00UL)>>8 == _VIEW_LEFT_ &&
835		(rmask & 0x0000000fUL)>>0 == _VIEW_RIGHT_) {
836		coords[1].x		= x;
837	} else if ((rmask & 0x00000f00UL)>>8 == _VIEW_LEFT_) {
838	} else if ((rmask & 0x0000000fUL)>>0 == _VIEW_RIGHT_) {
839		coords[0].x		= x;
840	} else if ((rmask & 0x00000f00UL)>>8 == _VIEW_CENTER_) {
841		coords[0].x		= x/2;
842	} else {
843		// illegal flag. Do nothing.
844	}
845
846
847	if ((rmask & 0x0000f000UL)>>12 == _VIEW_TOP_ &&
848		(rmask & 0x000000f0UL)>>4 == _VIEW_BOTTOM_) {
849		coords[1].y		= y;
850	} else if ((rmask & 0x0000f000UL)>>12 == _VIEW_TOP_) {
851	} else if ((rmask & 0x000000f0UL)>>4 == _VIEW_BOTTOM_) {
852		coords[0].y		= y;
853	} else if ((rmask & 0x0000f000UL)>>12 == _VIEW_CENTER_) {
854		coords[0].y		= y/2;
855	} else {
856		// illegal flag. Do nothing.
857	}
858
859	STRACE(("Layer(%s)::ResizeOthers() END\n", GetName()));
860	return 0UL;
861}
862
863#endif
864
865// Redraw
866void
867Layer::Redraw(const BRegion& reg, Layer *startFrom)
868{
869	STRACE(("Layer(%s)::Redraw();\n", GetName()));
870	if (IsHidden())
871		// this layer has nothing visible on screen, so bail out.
872		return;
873
874	BRegion *pReg = const_cast<BRegion*>(&reg);
875
876	if (pReg->CountRects() > 0)
877		RequestDraw(reg, startFrom);
878
879	STRACE(("Layer(%s)::Redraw() ENDED\n", GetName()));
880}
881
882// Draw
883void
884Layer::Draw(const BRect &rect)
885{
886#ifdef DEBUG_LAYER
887	printf("Layer(%s)::Draw: ", GetName());
888	rect.PrintToStream();
889#endif
890
891	if (!ViewColor().IsTransparentMagic())
892		fDriver->FillRect(rect, ViewColor());
893}
894
895// EmptyGlobals
896void
897Layer::EmptyGlobals()
898{
899	fRootLayer->fRedrawReg.MakeEmpty();
900
901	int32 count = fRootLayer->fCopyRegList.CountItems();
902	for (int32 i = 0; i < count; i++)
903		delete (BRegion*)fRootLayer->fCopyRegList.ItemAt(i);
904	fRootLayer->fCopyRegList.MakeEmpty();
905
906	count = fRootLayer->fCopyList.CountItems();
907	for (int32 i = 0; i < count; i++)
908		delete (BPoint*)fRootLayer->fCopyList.ItemAt(i);
909	fRootLayer->fCopyList.MakeEmpty();
910}
911
912/*!
913	\brief Shows the layer
914	\param invalidate Invalidate the region when showing the layer. defaults to true
915*/
916void
917Layer::Show(bool invalidate)
918{
919	STRACE(("Layer(%s)::Show()\n", GetName()));
920	if(!IsHidden())
921		return;
922
923	fHidden	= false;
924
925// NOTE: I added this here and it solves the invalid region problem
926// for Windows that have been resized before they were shown. -Stephan
927#ifndef NEW_CLIPPING
928RebuildFullRegion();
929SendViewCoordUpdateMsg();
930
931	if (invalidate)
932		GetRootLayer()->GoInvalidate(this, fFull);
933#else
934
935#endif
936}
937
938/*!
939	\brief Shows the layer
940	\param invalidate Invalidate the region when hiding the layer. defaults to true
941*/
942void
943Layer::Hide(bool invalidate)
944{
945	STRACE(("Layer(%s)::Hide()\n", GetName()));
946	if (IsHidden())
947		return;
948
949	fHidden	= true;
950#ifndef NEW_CLIPPING
951	if (invalidate)
952		GetRootLayer()->GoInvalidate(this, fFullVisible);
953#endif
954}
955
956//! Returns true if the layer is hidden
957bool
958Layer::IsHidden(void) const
959{
960	if (fHidden)
961		return true;
962
963	if (fParent)
964			return fParent->IsHidden();
965
966	return fHidden;
967}
968
969
970void
971Layer::PushState()
972{
973	LayerData *data = new LayerData(*fLayerData);
974	data->prevState = fLayerData;
975	fLayerData = data;
976}
977
978
979void
980Layer::PopState()
981{
982	if (fLayerData->prevState == NULL) {
983		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), but there is NO state on stack!\n", fName->String());
984		return;
985	}
986
987	LayerData *data = fLayerData;
988	fLayerData = fLayerData->prevState;
989	data->prevState = NULL;
990	delete data;
991}
992
993
994//! Matches the BView call of the same name
995BRect
996Layer::Bounds(void) const
997{
998	BRect r(fFrame);
999//	r.OffsetTo(fBoundsLeftTop);
1000	r.OffsetTo(BoundsOrigin());
1001	return r;
1002}
1003
1004//! Matches the BView call of the same name
1005BRect
1006Layer::Frame(void) const
1007{
1008	return fFrame;
1009}
1010
1011//! Moves the layer by specified values, complete with redraw
1012void
1013Layer::MoveBy(float x, float y)
1014{
1015	STRACE(("Layer(%s)::MoveBy() START\n", GetName()));
1016	if (!fParent) {
1017		CRITICAL("ERROR: in Layer::MoveBy()! - No parent!\n");
1018		return;
1019	}
1020
1021	BPrivate::PortLink msg(-1, -1);
1022	msg.StartMessage(AS_ROOTLAYER_LAYER_MOVE);
1023	msg.Attach<Layer*>(this);
1024	msg.Attach<float>(x);
1025	msg.Attach<float>(y);
1026	GetRootLayer()->EnqueueMessage(msg);
1027
1028	STRACE(("Layer(%s)::MoveBy() END\n", GetName()));
1029}
1030
1031//! Resize the layer by the specified amount, complete with redraw
1032void
1033Layer::ResizeBy(float x, float y)
1034{
1035	STRACE(("Layer(%s)::ResizeBy() START\n", GetName()));
1036
1037	if (!fParent) {
1038		printf("ERROR: in Layer::ResizeBy()! - No parent!\n");
1039		return;
1040	}
1041
1042	BPrivate::PortLink msg(-1, -1);
1043	msg.StartMessage(AS_ROOTLAYER_LAYER_RESIZE);
1044	msg.Attach<Layer*>(this);
1045	msg.Attach<float>(x);
1046	msg.Attach<float>(y);
1047	GetRootLayer()->EnqueueMessage(msg);
1048
1049	STRACE(("Layer(%s)::ResizeBy() END\n", GetName()));
1050}
1051
1052// BoundsOrigin
1053BPoint
1054Layer::BoundsOrigin() const
1055{
1056	BPoint origin(0,0);
1057	float scale = Scale();
1058
1059	LayerData *ld = fLayerData;
1060	do {
1061		origin += ld->Origin();
1062	} while ((ld = ld->prevState));
1063
1064	origin.x *= scale;
1065	origin.y *= scale;
1066
1067	return origin;
1068}
1069
1070float
1071Layer::Scale() const
1072{
1073	float scale = 1.0f;
1074
1075	LayerData *ld = fLayerData;
1076	do {
1077		scale *= ld->Scale();
1078	} while ((ld = ld->prevState));
1079
1080	return scale;
1081}
1082
1083//! Converts the passed point to parent coordinates
1084BPoint
1085Layer::ConvertToParent(BPoint pt)
1086{
1087	pt -= BoundsOrigin();
1088	pt += fFrame.LeftTop();
1089	return pt;
1090}
1091
1092//! Converts the passed rectangle to parent coordinates
1093BRect
1094Layer::ConvertToParent(BRect rect)
1095{
1096//	rect.OffsetBy(fFrame.LeftTop());
1097//	return rect;
1098	rect.OffsetBy(-BoundsOrigin().x, -BoundsOrigin().y);
1099	rect.OffsetBy(fFrame.LeftTop());
1100	return rect;
1101}
1102
1103//! Converts the passed region to parent coordinates
1104BRegion
1105Layer::ConvertToParent(BRegion* reg)
1106{
1107	// TODO: wouldn't it be more efficient to use the copy
1108	// constructor for BRegion and then call OffsetBy()?
1109	BRegion newreg;
1110	for (int32 i = 0; i < reg->CountRects(); i++)
1111		newreg.Include(ConvertToParent(reg->RectAt(i)));
1112	return newreg;
1113}
1114
1115//! Converts the passed point from parent coordinates
1116BPoint
1117Layer::ConvertFromParent(BPoint pt)
1118{
1119//	return pt - fFrame.LeftTop();
1120	pt -= fFrame.LeftTop();
1121	pt += BoundsOrigin();
1122	return pt;
1123}
1124
1125//! Converts the passed rectangle from parent coordinates
1126BRect
1127Layer::ConvertFromParent(BRect rect)
1128{
1129//	rect.OffsetBy(-fFrame.left, -fFrame.top);
1130//	return rect;
1131	rect.OffsetBy(-fFrame.left, -fFrame.top);
1132	rect.OffsetBy(BoundsOrigin());
1133	return rect;
1134}
1135
1136//! Converts the passed region from parent coordinates
1137BRegion
1138Layer::ConvertFromParent(BRegion *reg)
1139{
1140	BRegion newreg;
1141	for(int32 i=0; i<reg->CountRects();i++)
1142		newreg.Include(ConvertFromParent(reg->RectAt(i)));
1143	return newreg;
1144}
1145
1146// ConvertToTop
1147BPoint
1148Layer::ConvertToTop(BPoint pt)
1149{
1150	if (fParent) {
1151//		return (fParent->ConvertToTop(pt + fFrame.LeftTop()));
1152		pt = ConvertToParent(pt);
1153		return fParent->ConvertToTop(pt);
1154	} else
1155		return pt;
1156}
1157
1158//! Converts the passed rectangle to screen coordinates
1159BRect
1160Layer::ConvertToTop(BRect rect)
1161{
1162	if (fParent) {
1163//		return fParent->ConvertToTop(rect.OffsetByCopy(fFrame.LeftTop()));
1164		rect = ConvertToParent(rect);
1165		return fParent->ConvertToTop(rect);
1166	} else
1167		return rect;
1168}
1169
1170//! Converts the passed region to screen coordinates
1171BRegion
1172Layer::ConvertToTop(BRegion *reg)
1173{
1174	BRegion newreg;
1175	for (int32 i = 0; i < reg->CountRects();i++)
1176		newreg.Include(ConvertToTop(reg->RectAt(i)));
1177	return newreg;
1178}
1179
1180// ConvertFromTop
1181BPoint
1182Layer::ConvertFromTop(BPoint pt)
1183{
1184	if (fParent) {
1185//		return fParent->ConvertFromTop(pt-fFrame.LeftTop());
1186		pt = ConvertFromParent(pt);
1187		return fParent->ConvertFromTop(pt);
1188	} else
1189		return pt;
1190}
1191
1192//! Converts the passed rectangle from screen coordinates
1193BRect
1194Layer::ConvertFromTop(BRect rect)
1195{
1196	if (fParent) {
1197//		return fParent->ConvertFromTop(rect.OffsetByCopy(-fFrame.LeftTop().x,
1198//														 -fFrame.LeftTop().y));
1199		rect = ConvertFromParent(rect);
1200		return fParent->ConvertFromTop(rect);
1201	} else
1202		return rect;
1203}
1204
1205//! Converts the passed region from screen coordinates
1206BRegion
1207Layer::ConvertFromTop(BRegion *reg)
1208{
1209	BRegion newreg;
1210
1211	for (int32 i = 0; i < reg->CountRects(); i++)
1212		newreg.Include(ConvertFromTop(reg->RectAt(i)));
1213
1214	return newreg;
1215}
1216
1217//! Recursively deletes all children of the calling layer
1218void
1219Layer::PruneTree(void)
1220{
1221	Layer* lay;
1222	Layer* nextlay;
1223
1224	lay = fTopChild;
1225	fTopChild = NULL;
1226
1227	while (lay != NULL) {
1228		if (lay->fTopChild != NULL)
1229			lay->PruneTree();
1230
1231		nextlay = lay->fLowerSibling;
1232		lay->fLowerSibling = NULL;
1233
1234		delete lay;
1235		lay = nextlay;
1236	}
1237	// Man, this thing is short. Elegant, ain't it? :P
1238}
1239
1240//! Prints information about the layer's current state
1241void
1242Layer::PrintToStream()
1243{
1244	printf("\n----------- Layer %s -----------\n",fName->String());
1245	printf("\t Parent: %s\n", fParent? fParent->GetName():"NULL");
1246	printf("\t us: %s\t ls: %s\n",
1247				fUpperSibling? fUpperSibling->GetName():"NULL",
1248				fLowerSibling? fLowerSibling->GetName():"NULL");
1249	printf("\t topChild: %s\t bottomChild: %s\n",
1250				fTopChild? fTopChild->GetName():"NULL",
1251				fBottomChild? fBottomChild->GetName():"NULL");
1252
1253	printf("Frame: (%f, %f, %f, %f)", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
1254	printf("Token: %ld\n",fViewToken);
1255	printf("Hidden - direct: %s\n", fHidden?"true":"false");
1256	printf("Hidden - indirect: %s\n", IsHidden()?"true":"false");
1257	printf("ResizingMode: %lx\n", fResizeMode);
1258	printf("Flags: %lx\n", fFlags);
1259
1260	if (fLayerData)
1261		fLayerData->PrintToStream();
1262	else
1263		printf(" NO LayerData valid pointer\n");
1264}
1265
1266//! Prints pointer info kept by the current layer
1267void
1268Layer::PrintNode()
1269{
1270	printf("-----------\nLayer %s\n",fName->String());
1271	if(fParent)
1272		printf("Parent: %s (%p)\n",fParent->GetName(), fParent);
1273	else
1274		printf("Parent: NULL\n");
1275	if(fUpperSibling)
1276		printf("Upper sibling: %s (%p)\n",fUpperSibling->GetName(), fUpperSibling);
1277	else
1278		printf("Upper sibling: NULL\n");
1279	if(fLowerSibling)
1280		printf("Lower sibling: %s (%p)\n",fLowerSibling->GetName(), fLowerSibling);
1281	else
1282		printf("Lower sibling: NULL\n");
1283	if(fTopChild)
1284		printf("Top child: %s (%p)\n",fTopChild->GetName(), fTopChild);
1285	else
1286		printf("Top child: NULL\n");
1287	if(fBottomChild)
1288		printf("Bottom child: %s (%p)\n",fBottomChild->GetName(), fBottomChild);
1289	else
1290		printf("Bottom child: NULL\n");
1291#ifndef NEW_CLIPPING
1292	printf("Visible Areas: "); fVisible.PrintToStream();
1293#endif
1294}
1295
1296//! Prints the tree hierarchy from the current layer down
1297void
1298Layer::PrintTree()
1299{
1300	printf("\n Tree structure:\n");
1301	printf("\t%s\t%s\n", GetName(), IsHidden()? "Hidden": "NOT hidden");
1302	for(Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling())
1303		printf("\t%s\t%s\n", lay->GetName(), lay->IsHidden()? "Hidden": "NOT hidden");
1304}
1305
1306// UpdateStart
1307void
1308Layer::UpdateStart()
1309{
1310	// During updates we only want to draw what's in the update region
1311	if (fClassID == AS_WINBORDER_CLASS) {
1312		// NOTE: don't worry, RooLayer is locked here.
1313		WinBorder	*wb = (WinBorder*)this;
1314
1315		wb->fInUpdate = true;
1316		wb->fRequestSent = false;
1317		wb->yUpdateReg = wb->fUpdateReg;
1318		wb->fUpdateReg.MakeEmpty();
1319wb->cnt--;
1320if (wb->cnt != 0)
1321	CRITICAL("Layer::UpdateStart(): wb->cnt != 0 -> Not Allowed!");
1322	}
1323}
1324
1325// UpdateEnd
1326void
1327Layer::UpdateEnd()
1328{
1329	// The usual case. Drawing is permitted in the whole visible area.
1330	if (fClassID == AS_WINBORDER_CLASS) {
1331		WinBorder	*wb = (WinBorder*)this;
1332
1333		wb->yUpdateReg.MakeEmpty();
1334
1335		wb->fInUpdate = false;
1336
1337		if (wb->zUpdateReg.CountRects() > 0) {
1338			BRegion		reg(wb->zUpdateReg);
1339			wb->RequestDraw(reg, NULL);
1340		}
1341	}
1342}
1343
1344
1345#ifndef NEW_CLIPPING
1346
1347
1348// move_layer
1349void
1350Layer::move_layer(float x, float y)
1351{
1352/*	if (fClassID == AS_WINBORDER_CLASS) {
1353		WinBorder	*wb = (WinBorder*)this;
1354		wb->zUpdateReg.OffsetBy(x, y);
1355		wb->yUpdateReg.OffsetBy(x, y);
1356		wb->fUpdateReg.OffsetBy(x, y);
1357	}*/
1358
1359	fFrameAction = B_LAYER_ACTION_MOVE;
1360
1361	BPoint pt(x, y);
1362	BRect rect(fFull.Frame().OffsetByCopy(pt));
1363
1364if (!fParent) {
1365printf("no parent in Layer::move_layer() (%s)\n", GetName());
1366fFrameAction = B_LAYER_ACTION_NONE;
1367return;
1368}
1369
1370	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_MOVE, pt);
1371
1372	fDriver->CopyRegionList(&fRootLayer->fCopyRegList,
1373							&fRootLayer->fCopyList,
1374							fRootLayer->fCopyRegList.CountItems(),
1375							&fFullVisible);
1376
1377	fParent->Redraw(fRootLayer->fRedrawReg, this);
1378
1379	SendViewCoordUpdateMsg();
1380
1381	EmptyGlobals();
1382
1383	fFrameAction = B_LAYER_ACTION_NONE;
1384}
1385
1386// resize_layer
1387void
1388Layer::resize_layer(float x, float y)
1389{
1390	fFrameAction = B_LAYER_ACTION_RESIZE;
1391
1392	BPoint pt(x,y);
1393
1394	BRect rect(fFull.Frame());
1395	rect.right += x;
1396	rect.bottom += y;
1397
1398if (!fParent) {
1399printf("no parent in Layer::resize_layer() (%s)\n", GetName());
1400fFrameAction = B_LAYER_ACTION_NONE;
1401return;
1402}
1403
1404	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_RESIZE, pt);
1405
1406	fDriver->CopyRegionList(&fRootLayer->fCopyRegList, &fRootLayer->fCopyList, fRootLayer->fCopyRegList.CountItems(), &fFullVisible);
1407
1408
1409	fParent->Redraw(fRootLayer->fRedrawReg, this);
1410
1411	SendViewCoordUpdateMsg();
1412
1413	EmptyGlobals();
1414
1415	fFrameAction = B_LAYER_ACTION_NONE;
1416}
1417
1418// FullInvalidate
1419void
1420Layer::FullInvalidate(const BRect &rect)
1421{
1422	FullInvalidate(BRegion(rect));
1423}
1424
1425// FullInvalidate
1426void
1427Layer::FullInvalidate(const BRegion& region)
1428{
1429	STRACE(("Layer(%s)::FullInvalidate():\n", GetName()));
1430
1431#ifdef DEBUG_LAYER
1432	region.PrintToStream();
1433	printf("\n");
1434#endif
1435
1436	BPoint pt(0,0);
1437	StartRebuildRegions(region, NULL,/* B_LAYER_INVALIDATE, pt); */B_LAYER_NONE, pt);
1438
1439	Redraw(fRootLayer->fRedrawReg);
1440
1441	EmptyGlobals();
1442}
1443
1444// Invalidate
1445void
1446Layer::Invalidate(const BRegion& region)
1447{
1448	STRACE(("Layer(%s)::Invalidate():\n", GetName()));
1449#ifdef DEBUG_LAYER
1450	region.PrintToStream();
1451	printf("\n");
1452#endif
1453
1454	fRootLayer->fRedrawReg	= region;
1455
1456	Redraw(fRootLayer->fRedrawReg);
1457
1458	EmptyGlobals();
1459}
1460
1461#endif // 5 methods
1462
1463// RequestDraw
1464void
1465Layer::RequestDraw(const BRegion &reg, Layer *startFrom)
1466{
1467	STRACE(("Layer(%s)::RequestDraw()\n", GetName()));
1468printf("Layer(%s)::RequestDraw()\n", GetName());
1469//if (fClassID == AS_ROOTLAYER_CLASS)
1470//	debugger("z");
1471	// do not redraw any child until you must
1472	int redraw = false;
1473	if (!startFrom)
1474		redraw = true;
1475
1476	if (HasClient() && IsTopLayer()) {
1477		// calculate the minimum region/rectangle to be updated with
1478		// a single message to the client.
1479#ifndef NEW_CLIPPING
1480		BRegion	updateReg(fFullVisible);
1481#else
1482		BRegion	updateReg(fFullVisible2);
1483#endif
1484
1485		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1486#ifndef NEW_CLIPPING
1487			&& fFrameAction	== B_LAYER_ACTION_RESIZE
1488#endif
1489		)
1490		{
1491			// do nothing
1492		} else {
1493			updateReg.IntersectWith(&reg);
1494		}
1495		if (updateReg.CountRects() > 0) {
1496			fOwner->zUpdateReg.Include(&updateReg);
1497			if (!fOwner->fInUpdate && !fOwner->fRequestSent) {
1498				fOwner->fUpdateReg = fOwner->zUpdateReg;
1499fOwner->cnt++;
1500if (fOwner->cnt != 1)
1501	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1502				fOwner->zUpdateReg.MakeEmpty();
1503				SendUpdateMsg(fOwner->fUpdateReg);
1504				fOwner->fRequestSent = true;
1505			}
1506		}
1507	}
1508
1509#ifndef NEW_CLIPPING
1510	if (fVisible.CountRects() > 0) {
1511		BRegion	updateReg(fVisible);
1512		// calculate the update region
1513		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fFrameAction == B_LAYER_ACTION_RESIZE) {
1514			// do nothing
1515		} else {
1516			updateReg.IntersectWith(&reg);
1517		}
1518
1519		if (updateReg.CountRects() > 0) {
1520			fDriver->ConstrainClippingRegion(&updateReg);
1521			Draw(updateReg.Frame());
1522			fDriver->ConstrainClippingRegion(NULL);
1523		}
1524	}
1525
1526	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1527		if (lay == startFrom)
1528			redraw = true;
1529
1530		if (redraw && !(lay->IsHidden())) {
1531			// no need to go deeper if not even the FullVisible region intersects
1532			// Update one.
1533			BRegion common(lay->fFullVisible);
1534			common.IntersectWith(&reg);
1535
1536			if (common.CountRects() > 0)
1537				lay->RequestDraw(reg, NULL);
1538		}
1539	}
1540#else
1541	if (fVisible2.CountRects() > 0) {
1542		BRegion	updateReg(fVisible2);
1543		// calculate the update region
1544		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1545// TODO: must be replaced!
1546//		 && fFrameAction == B_LAYER_ACTION_RESIZE
1547		) {
1548			// do nothing
1549		} else {
1550			updateReg.IntersectWith(&reg);
1551		}
1552
1553		if (updateReg.CountRects() > 0) {
1554			fDriver->ConstrainClippingRegion(&updateReg);
1555			Draw(updateReg.Frame());
1556			fDriver->ConstrainClippingRegion(NULL);
1557		}
1558	}
1559
1560	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1561		if (lay == startFrom)
1562			redraw = true;
1563
1564		if (redraw && !(lay->IsHidden())) {
1565			// no need to go deeper if not even the FullVisible region intersects
1566			// Update one.
1567			BRegion common(lay->fFullVisible2);
1568			common.IntersectWith(&reg);
1569
1570			if (common.CountRects() > 0)
1571				lay->RequestDraw(reg, NULL);
1572		}
1573	}
1574#endif
1575}
1576
1577/*!
1578	\brief Returns the layer's ServerWindow
1579
1580	If the layer's ServerWindow has not been assigned, it attempts to find
1581	the owning ServerWindow in the tree.
1582*/
1583ServerWindow*
1584Layer::SearchForServerWindow()
1585{
1586	if (!fServerWin)
1587		fServerWin=fParent->SearchForServerWindow();
1588
1589	return fServerWin;
1590}
1591
1592//! Sends an _UPDATE_ message to the client BWindow
1593void
1594Layer::SendUpdateMsg(BRegion& reg)
1595{
1596	BMessage msg;
1597	msg.what = _UPDATE_;
1598	msg.AddRect("_rect", ConvertFromTop(reg.Frame()) );
1599	msg.AddRect("debug_rect", reg.Frame() );
1600//	msg.AddInt32("_token",fViewToken);
1601
1602	fOwner->Window()->SendMessageToClient(&msg);
1603}
1604
1605// AddToViewsWithInvalidCoords
1606void
1607Layer::AddToViewsWithInvalidCoords() const
1608{
1609	if (fServerWin) {
1610		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
1611		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
1612		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
1613		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
1614	}
1615}
1616
1617// SendViewCoordUpdateMsg
1618void
1619Layer::SendViewCoordUpdateMsg() const
1620{
1621	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
1622		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
1623		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
1624	}
1625}
1626
1627// SetViewColor
1628void
1629Layer::SetViewColor(const RGBColor& color)
1630{
1631	fViewColor = color;
1632}
1633
1634// SetBackgroundBitmap
1635void
1636Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
1637{
1638	// TODO: What about reference counting?
1639	// "Release" old fBackgroundBitmap and "Aquire" new one?
1640	fBackgroundBitmap = bitmap;
1641}
1642
1643// SetOverlayBitmap
1644void
1645Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
1646{
1647	// TODO: What about reference counting?
1648	// "Release" old fOverlayBitmap and "Aquire" new one?
1649	fOverlayBitmap = bitmap;
1650}
1651
1652#ifdef NEW_CLIPPING
1653void
1654Layer::ConvertToScreen2(BRect* rect) const
1655{
1656	if (GetRootLayer())
1657		if (fParent) {
1658			BPoint origin = BoundsOrigin();
1659			rect->OffsetBy(-origin.x, -origin.y);
1660			rect->OffsetBy(fFrame.left, fFrame.top);
1661
1662			fParent->ConvertToScreen2(rect);
1663		}
1664}
1665
1666void
1667Layer::ConvertToScreen2(BRegion* reg) const
1668{
1669	if (GetRootLayer())
1670		if (fParent) {
1671			BPoint origin = BoundsOrigin();
1672			reg->OffsetBy(-origin.x, -origin.y);
1673			reg->OffsetBy(fFrame.left, fFrame.top);
1674
1675			fParent->ConvertToScreen2(reg);
1676		}
1677}
1678
1679void
1680Layer::do_Hide()
1681{
1682	fHidden = true;
1683
1684	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1685		// save fullVisible so we know what to invalidate
1686		BRegion invalid(fFullVisible2);
1687
1688		clear_visible_regions();
1689
1690		if (invalid.Frame().IsValid())
1691			fParent->do_Invalidate(invalid, this);
1692	}
1693}
1694
1695void
1696Layer::do_Show()
1697{
1698	fHidden = false;
1699
1700	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1701		BRegion invalid;
1702
1703		get_user_regions(invalid);
1704
1705		if (invalid.CountRects() > 0)
1706			fParent->do_Invalidate(invalid, this);
1707	}
1708}
1709
1710void
1711Layer::do_Invalidate(const BRegion &invalid, const Layer *startFrom)
1712{
1713	BRegion		localVisible(fFullVisible2);
1714	localVisible.IntersectWith(&invalid);
1715	rebuild_visible_regions(invalid, localVisible,
1716		startFrom? startFrom: BottomChild());
1717
1718	// add localVisible to our RootLayer's redraw region.
1719	GetRootLayer()->fRedrawReg.Include(&localVisible);
1720// TODO: ---
1721	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1722//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1723}
1724
1725void
1726Layer::do_Redraw(const BRegion &invalid, const Layer *startFrom)
1727{
1728	BRegion		localVisible(fFullVisible2);
1729	localVisible.IntersectWith(&invalid);
1730
1731	// add localVisible to our RootLayer's redraw region.
1732	GetRootLayer()->fRedrawReg.Include(&localVisible);
1733// TODO: ---
1734	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1735//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1736}
1737
1738inline void
1739Layer::resize_layer_frame_by(float x, float y)
1740{
1741	uint16		rm = fResizeMode & 0x0000FFFF;
1742	BRect		newFrame = fFrame;
1743
1744	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
1745		newFrame.left += 0.0f;
1746	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
1747		newFrame.left += x;
1748	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
1749		newFrame.left += x/2;
1750
1751	if ((rm & 0x000FU) == _VIEW_LEFT_)
1752		newFrame.right += 0.0f;
1753	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
1754		newFrame.right += x;
1755	else if ((rm & 0x000FU) == _VIEW_CENTER_)
1756		newFrame.right += x/2;
1757
1758	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
1759		newFrame.top += 0.0f;
1760	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
1761		newFrame.top += y;
1762	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
1763		newFrame.top += y/2;
1764
1765	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
1766		newFrame.bottom += 0.0f;
1767	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
1768		newFrame.bottom += y;
1769	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
1770		newFrame.bottom += y/2;
1771
1772	if (newFrame != fFrame) {
1773		float		dx, dy;
1774
1775		dx	= newFrame.Width() - fFrame.Width();
1776		dy	= newFrame.Height() - fFrame.Height();
1777
1778		fFrame	= newFrame;
1779
1780		if (dx != 0.0f || dy != 0.0f) {
1781			// call hook function
1782			ResizedByHook(dx, dy, true); // automatic
1783
1784			for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
1785				lay->resize_layer_frame_by(dx, dy);
1786		}
1787		else
1788			MovedByHook(dx, dy);
1789	}
1790}
1791
1792inline void
1793Layer::rezize_layer_redraw_more(BRegion &reg, float dx, float dy)
1794{
1795	if (dx == 0 && dy == 0)
1796		return;
1797
1798	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
1799		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1800
1801		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1802			// NOTE: this is not exactly corect, but it works :-)
1803			// Normaly we shoud've used the lay's old, required region - the one returned
1804			// from get_user_region() with the old frame, and the current one. lay->Bounds()
1805			// works for the moment so we leave it like this.
1806
1807			// calculate the old bounds.
1808			BRect	oldBounds(lay->Bounds());
1809			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
1810				oldBounds.right -=dx;
1811			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
1812				oldBounds.bottom -=dy;
1813
1814			// compute the region that became visible because we got bigger OR smaller.
1815			BRegion	regZ(lay->Bounds());
1816			regZ.Include(oldBounds);
1817			regZ.Exclude(oldBounds&lay->Bounds());
1818
1819			lay->ConvertToScreen2(&regZ);
1820
1821			// intersect that with this'(not lay's) fullVisible region
1822			regZ.IntersectWith(&fFullVisible2);
1823			reg.Include(&regZ);
1824
1825			lay->rezize_layer_redraw_more(reg,
1826				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1827				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1828
1829			// above, OR this:
1830			// reg.Include(&lay->fFullVisible2);
1831		}
1832		else
1833		if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
1834			((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) ||
1835			((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
1836			((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
1837		{
1838			reg.Include(&lay->fFullVisible2);
1839		}
1840	}
1841}
1842
1843inline void
1844Layer::resize_layer_full_update_on_resize(BRegion &reg, float dx, float dy)
1845{
1846	if (dx == 0 && dy == 0)
1847		return;
1848
1849	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
1850		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1851
1852		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1853			if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0)
1854				reg.Include(&lay->fVisible2);
1855
1856			lay->resize_layer_full_update_on_resize(reg,
1857				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1858				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1859		}
1860	}
1861}
1862
1863void
1864Layer::do_ResizeBy(float dx, float dy)
1865{
1866	fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
1867
1868	// resize children using their resize_mask.
1869	for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
1870			lay->resize_layer_frame_by(dx, dy);
1871
1872	// call hook function
1873	if (dx != 0.0f || dy != 0.0f)
1874		ResizedByHook(dx, dy, false); // manual
1875
1876	if (!IsHidden() && GetRootLayer()) {
1877		BRegion oldFullVisible(fFullVisible2);
1878		// this is required to invalidate the old border
1879		BRegion oldVisible(fVisible2);
1880
1881		// in case they moved, bottom, right and center aligned layers must be redrawn
1882		BRegion redrawMore;
1883		rezize_layer_redraw_more(redrawMore, dx, dy);
1884
1885		// we'll invalidate the old area and the new, maxmial one.
1886		BRegion invalid;
1887		get_user_regions(invalid);
1888		invalid.Include(&fFullVisible2);
1889
1890		clear_visible_regions();
1891
1892		fParent->do_RebuildVisibleRegions(invalid, this);
1893
1894		// done rebuilding regions, now redraw regions that became visible
1895
1896		// what's invalid, are the differences between to old and the new fullVisible region
1897		// 1) in case we grow.
1898		BRegion		redrawReg(fFullVisible2);
1899		redrawReg.Exclude(&oldFullVisible);
1900		// 2) in case we shrink
1901		BRegion		redrawReg2(oldFullVisible);
1902		redrawReg2.Exclude(&fFullVisible2);
1903		// 3) combine.
1904		redrawReg.Include(&redrawReg2);
1905
1906		// for center, right and bottom alligned layers, redraw their old positions
1907		redrawReg.Include(&redrawMore);
1908
1909		// layers that had their frame modified must be entirely redrawn.
1910		rezize_layer_redraw_more(redrawReg, dx, dy);
1911
1912		// add redrawReg to our RootLayer's redraw region.
1913		GetRootLayer()->fRedrawReg.Include(&redrawReg);
1914		// include layer's visible region in case we want a full update on resize
1915		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) {
1916			resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg, dx, dy);
1917
1918			GetRootLayer()->fRedrawReg.Include(&fVisible2);
1919			GetRootLayer()->fRedrawReg.Include(&oldVisible);
1920		}
1921		// clear canvas and set invalid regions for affected WinBorders
1922// TODO: ---
1923	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1924//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1925	}
1926}
1927
1928void Layer::do_MoveBy(float dx, float dy)
1929{
1930	if (dx == 0.0f && dy == 0.0f)
1931		return;
1932
1933//	fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
1934	fFrame.OffsetBy(dx, dy);
1935
1936	// call hook function
1937	MovedByHook(dx, dy);
1938
1939	if (!IsHidden() && GetRootLayer()) {
1940		BRegion oldFullVisible(fFullVisible2);
1941
1942		// we'll invalidate the old position and the new, maxmial one.
1943		BRegion invalid;
1944		get_user_regions(invalid);
1945		invalid.Include(&fFullVisible2);
1946
1947		clear_visible_regions();
1948
1949		fParent->do_RebuildVisibleRegions(invalid, this);
1950
1951		// done rebuilding regions, now copy common parts and redraw regions that became visible
1952
1953		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
1954		BRegion		redrawReg(fFullVisible2);
1955		redrawReg.Include(&oldFullVisible);
1956
1957		// offset to layer's new location so that we can calculate the common region.
1958		oldFullVisible.OffsetBy(dx, dy);
1959
1960		// finally we have the region that needs to be redrawn.
1961		redrawReg.Exclude(&oldFullVisible);
1962
1963		// by intersecting the old fullVisible offseted to layer's new location, with the current
1964		// fullVisible, we'll have the common region which can be copied using HW acceleration.
1965		oldFullVisible.IntersectWith(&fFullVisible2);
1966
1967		// offset back and instruct the HW to do the actual copying.
1968		oldFullVisible.OffsetBy(-dx, -dy);
1969// TODO: uncomment!!!
1970//		GetRootLayer()->CopyRegion(&oldFullVisible, dx, dy);
1971
1972		// add redrawReg to our RootLayer's redraw region.
1973		GetRootLayer()->fRedrawReg.Include(&redrawReg);
1974// TODO: ---
1975	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1976//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1977	}
1978}
1979
1980void
1981Layer::do_ScrollBy(float dx, float dy)
1982{
1983	fLayerData->OffsetOrigin(BPoint(dx, dy));
1984//	fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy);
1985
1986	if (!IsHidden() && GetRootLayer()) {
1987		// set the region to be invalidated.
1988		BRegion		invalid(fFullVisible2);
1989
1990		clear_visible_regions();
1991
1992		rebuild_visible_regions(invalid, invalid, BottomChild());
1993
1994		// for the moment we say that the whole surface needs to be redraw.
1995		BRegion		redrawReg(fFullVisible2);
1996
1997		// offset old region so that we can start comparing.
1998		invalid.OffsetBy(dx, dy);
1999
2000		// compute the common region. we'll use HW acc to copy this to the new location.
2001		invalid.IntersectWith(&fFullVisible2);
2002// TODO: uncomment!!!
2003//		GetRootLayer()->CopyRegion(&invalid, -dx, -dy);
2004
2005		// common region goes back to its original location. then, by excluding
2006		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
2007		invalid.OffsetBy(-dx, -dy);
2008		redrawReg.Exclude(&invalid);
2009
2010		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2011// TODO: ---
2012	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
2013//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2014	}
2015
2016	if (dx != 0.0f || dy != 0.0f)
2017		ScrolledByHook(dx, dy);
2018}
2019void
2020Layer::get_user_regions(BRegion &reg)
2021{
2022	// 1) set to frame in screen coords
2023	BRect			screenFrame(Bounds());
2024	ConvertToScreen2(&screenFrame);
2025	reg.Set(screenFrame);
2026
2027	// 2) intersect with screen region
2028	BRegion			screenReg(GetRootLayer()->Bounds());
2029	reg.IntersectWith(&screenReg);
2030
2031// TODO: you MUST at some point uncomment this block!
2032/*
2033	// 3) impose user constrained regions
2034	LayerData		*stackData = fLayerData;
2035	while (stackData)
2036	{
2037		// transform in screen coords
2038		BRegion		screenReg(stackData->ClippingRegion());
2039		ConvertToScreen2(&screenReg);
2040		reg.IntersectWith(&screenReg);
2041		stackData	= stackData->prevState;
2042	}
2043*/
2044}
2045
2046void
2047Layer::do_RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom)
2048{
2049	BRegion		localVisible(fFullVisible2);
2050	localVisible.IntersectWith(&invalid);
2051	rebuild_visible_regions(invalid, localVisible, startFrom);
2052}
2053
2054void
2055Layer::rebuild_visible_regions(const BRegion &invalid,
2056								const BRegion &parentLocalVisible,
2057								const Layer *startFrom)
2058{
2059	// no point in continuing if this layer is hidden. starting from here, all
2060	// descendants have (and will have) invalid visible regions.
2061	if (fHidden)
2062		return;
2063
2064	// no need to go deeper if the parent doesn't have a visible region anymore
2065	// and our fullVisible region is also empty.
2066	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0))
2067		return;
2068
2069	bool fullRebuild = false;
2070
2071	// intersect maximum wanted region with the invalid region
2072	BRegion common;
2073	get_user_regions(common);
2074	common.IntersectWith(&invalid);
2075
2076	// if the resulted region is not valid, this layer is not in the catchment area
2077	// of the region being invalidated
2078	if (!common.CountRects() > 0)
2079		return;
2080
2081	// now intersect with parent's visible part of the region that was/is invalidated
2082	common.IntersectWith(&parentLocalVisible);
2083
2084	// exclude the invalid region
2085	fFullVisible2.Exclude(&invalid);
2086	fVisible2.Exclude(&invalid);
2087
2088	// put in what's really visible
2089	fFullVisible2.Include(&common);
2090
2091	// this is to allow a layer to hide some parts of itself so children
2092	// won't take them.
2093	BRegion unalteredVisible(common);
2094	bool altered = alter_visible_for_children(common);
2095
2096	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
2097		if (lay == startFrom)
2098			fullRebuild = true;
2099
2100		if (fullRebuild)
2101			lay->rebuild_visible_regions(invalid, common, lay->BottomChild());
2102
2103		// to let children know much they can take from parent's visible region
2104		common.Exclude(&lay->fFullVisible2);
2105		// we've hidden some parts of our visible region from our children,
2106		// and we must be in sysnc with this region too...
2107		if (altered)
2108			unalteredVisible.Exclude(&lay->fFullVisible2);
2109	}
2110
2111	// the visible region of this layer is what left after all its children took
2112	// what they could.
2113	if (altered)
2114		fVisible2.Include(&unalteredVisible);
2115	else
2116		fVisible2.Include(&common);
2117}
2118
2119bool
2120Layer::alter_visible_for_children(BRegion &reg)
2121{
2122	// Empty Hook function
2123	return false;
2124}
2125
2126void
2127Layer::clear_visible_regions()
2128{
2129	// OPT: maybe we should uncomment these lines for performance
2130	//if (fFullVisible2.CountRects() <= 0)
2131	//	return;
2132
2133	fVisible2.MakeEmpty();
2134	fFullVisible2.MakeEmpty();
2135	for (Layer *child = BottomChild(); child; child = UpperSibling())
2136		child->clear_visible_regions();
2137}
2138
2139#endif
2140
2141