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