Layer.cpp revision a38e46a046cbb27fef680a1c9f93b000663d70c9
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		return;
921
922	fHidden	= false;
923
924// NOTE: I added this here and it solves the invalid region problem
925// for Windows that have been resized before they were shown. -Stephan
926#ifndef NEW_CLIPPING
927RebuildFullRegion();
928SendViewCoordUpdateMsg();
929
930	if (invalidate)
931		GetRootLayer()->GoInvalidate(this, fFull);
932#else
933
934#endif
935}
936
937/*!
938	\brief Shows the layer
939	\param invalidate Invalidate the region when hiding the layer. defaults to true
940*/
941void
942Layer::Hide(bool invalidate)
943{
944	STRACE(("Layer(%s)::Hide()\n", Name()));
945	if (IsHidden())
946		return;
947
948	fHidden	= true;
949#ifndef NEW_CLIPPING
950	if (invalidate)
951		GetRootLayer()->GoInvalidate(this, fFullVisible);
952#endif
953}
954
955//! Returns true if the layer is hidden
956bool
957Layer::IsHidden(void) const
958{
959	if (fHidden)
960		return true;
961
962	if (fParent)
963			return fParent->IsHidden();
964
965	return fHidden;
966}
967
968
969void
970Layer::PushState()
971{
972	LayerData *data = new LayerData(*fLayerData);
973	data->prevState = fLayerData;
974	fLayerData = data;
975}
976
977
978void
979Layer::PopState()
980{
981	if (fLayerData->prevState == NULL) {
982		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), but there is NO state on stack!\n", Name());
983		return;
984	}
985
986	LayerData *data = fLayerData;
987	fLayerData = fLayerData->prevState;
988	data->prevState = NULL;
989	delete data;
990}
991
992
993//! Matches the BView call of the same name
994BRect
995Layer::Bounds(void) const
996{
997	BRect r(fFrame);
998//	r.OffsetTo(fBoundsLeftTop);
999	r.OffsetTo(BoundsOrigin());
1000	return r;
1001}
1002
1003//! Matches the BView call of the same name
1004BRect
1005Layer::Frame(void) const
1006{
1007	return fFrame;
1008}
1009
1010//! Moves the layer by specified values, complete with redraw
1011void
1012Layer::MoveBy(float x, float y)
1013{
1014	STRACE(("Layer(%s)::MoveBy() START\n", Name()));
1015	if (!fParent) {
1016		CRITICAL("ERROR: in Layer::MoveBy()! - No parent!\n");
1017		return;
1018	}
1019
1020	BPrivate::PortLink msg(-1, -1);
1021	msg.StartMessage(AS_ROOTLAYER_LAYER_MOVE);
1022	msg.Attach<Layer*>(this);
1023	msg.Attach<float>(x);
1024	msg.Attach<float>(y);
1025	GetRootLayer()->EnqueueMessage(msg);
1026
1027	STRACE(("Layer(%s)::MoveBy() END\n", Name()));
1028}
1029
1030//! Resize the layer by the specified amount, complete with redraw
1031void
1032Layer::ResizeBy(float x, float y)
1033{
1034	STRACE(("Layer(%s)::ResizeBy() START\n", Name()));
1035
1036	if (!fParent) {
1037		printf("ERROR: in Layer::ResizeBy()! - No parent!\n");
1038		return;
1039	}
1040
1041	BPrivate::PortLink msg(-1, -1);
1042	msg.StartMessage(AS_ROOTLAYER_LAYER_RESIZE);
1043	msg.Attach<Layer*>(this);
1044	msg.Attach<float>(x);
1045	msg.Attach<float>(y);
1046	GetRootLayer()->EnqueueMessage(msg);
1047
1048	STRACE(("Layer(%s)::ResizeBy() END\n", Name()));
1049}
1050
1051// BoundsOrigin
1052BPoint
1053Layer::BoundsOrigin() const
1054{
1055	BPoint origin(0,0);
1056	float scale = Scale();
1057
1058	LayerData *ld = fLayerData;
1059	do {
1060		origin += ld->Origin();
1061	} while ((ld = ld->prevState));
1062
1063	origin.x *= scale;
1064	origin.y *= scale;
1065
1066	return origin;
1067}
1068
1069float
1070Layer::Scale() const
1071{
1072	float scale = 1.0f;
1073
1074	LayerData *ld = fLayerData;
1075	do {
1076		scale *= ld->Scale();
1077	} while ((ld = ld->prevState));
1078
1079	return scale;
1080}
1081
1082//! Converts the passed point to parent coordinates
1083BPoint
1084Layer::ConvertToParent(BPoint pt)
1085{
1086	pt -= BoundsOrigin();
1087	pt += fFrame.LeftTop();
1088	return pt;
1089}
1090
1091//! Converts the passed rectangle to parent coordinates
1092BRect
1093Layer::ConvertToParent(BRect rect)
1094{
1095//	rect.OffsetBy(fFrame.LeftTop());
1096//	return rect;
1097	rect.OffsetBy(-BoundsOrigin().x, -BoundsOrigin().y);
1098	rect.OffsetBy(fFrame.LeftTop());
1099	return rect;
1100}
1101
1102//! Converts the passed region to parent coordinates
1103BRegion
1104Layer::ConvertToParent(BRegion* reg)
1105{
1106	// TODO: wouldn't it be more efficient to use the copy
1107	// constructor for BRegion and then call OffsetBy()?
1108	BRegion newreg;
1109	for (int32 i = 0; i < reg->CountRects(); i++)
1110		newreg.Include(ConvertToParent(reg->RectAt(i)));
1111	return newreg;
1112}
1113
1114//! Converts the passed point from parent coordinates
1115BPoint
1116Layer::ConvertFromParent(BPoint pt)
1117{
1118//	return pt - fFrame.LeftTop();
1119	pt -= fFrame.LeftTop();
1120	pt += BoundsOrigin();
1121	return pt;
1122}
1123
1124//! Converts the passed rectangle from parent coordinates
1125BRect
1126Layer::ConvertFromParent(BRect rect)
1127{
1128//	rect.OffsetBy(-fFrame.left, -fFrame.top);
1129//	return rect;
1130	rect.OffsetBy(-fFrame.left, -fFrame.top);
1131	rect.OffsetBy(BoundsOrigin());
1132	return rect;
1133}
1134
1135//! Converts the passed region from parent coordinates
1136BRegion
1137Layer::ConvertFromParent(BRegion *reg)
1138{
1139	BRegion newreg;
1140	for(int32 i=0; i<reg->CountRects();i++)
1141		newreg.Include(ConvertFromParent(reg->RectAt(i)));
1142	return newreg;
1143}
1144
1145// ConvertToTop
1146BPoint
1147Layer::ConvertToTop(BPoint pt)
1148{
1149	if (fParent) {
1150//		return (fParent->ConvertToTop(pt + fFrame.LeftTop()));
1151		pt = ConvertToParent(pt);
1152		return fParent->ConvertToTop(pt);
1153	} else
1154		return pt;
1155}
1156
1157//! Converts the passed rectangle to screen coordinates
1158BRect
1159Layer::ConvertToTop(BRect rect)
1160{
1161	if (fParent) {
1162//		return fParent->ConvertToTop(rect.OffsetByCopy(fFrame.LeftTop()));
1163		rect = ConvertToParent(rect);
1164		return fParent->ConvertToTop(rect);
1165	} else
1166		return rect;
1167}
1168
1169//! Converts the passed region to screen coordinates
1170BRegion
1171Layer::ConvertToTop(BRegion *reg)
1172{
1173	BRegion newreg;
1174	for (int32 i = 0; i < reg->CountRects();i++)
1175		newreg.Include(ConvertToTop(reg->RectAt(i)));
1176	return newreg;
1177}
1178
1179// ConvertFromTop
1180BPoint
1181Layer::ConvertFromTop(BPoint pt)
1182{
1183	if (fParent) {
1184//		return fParent->ConvertFromTop(pt-fFrame.LeftTop());
1185		pt = ConvertFromParent(pt);
1186		return fParent->ConvertFromTop(pt);
1187	} else
1188		return pt;
1189}
1190
1191//! Converts the passed rectangle from screen coordinates
1192BRect
1193Layer::ConvertFromTop(BRect rect)
1194{
1195	if (fParent) {
1196//		return fParent->ConvertFromTop(rect.OffsetByCopy(-fFrame.LeftTop().x,
1197//														 -fFrame.LeftTop().y));
1198		rect = ConvertFromParent(rect);
1199		return fParent->ConvertFromTop(rect);
1200	} else
1201		return rect;
1202}
1203
1204//! Converts the passed region from screen coordinates
1205BRegion
1206Layer::ConvertFromTop(BRegion *reg)
1207{
1208	BRegion newreg;
1209
1210	for (int32 i = 0; i < reg->CountRects(); i++)
1211		newreg.Include(ConvertFromTop(reg->RectAt(i)));
1212
1213	return newreg;
1214}
1215
1216//! Recursively deletes all children of the calling layer
1217void
1218Layer::PruneTree(void)
1219{
1220	Layer* lay;
1221	Layer* nextlay;
1222
1223	lay = fTopChild;
1224	fTopChild = NULL;
1225
1226	while (lay != NULL) {
1227		if (lay->fTopChild != NULL)
1228			lay->PruneTree();
1229
1230		nextlay = lay->fLowerSibling;
1231		lay->fLowerSibling = NULL;
1232
1233		delete lay;
1234		lay = nextlay;
1235	}
1236	// Man, this thing is short. Elegant, ain't it? :P
1237}
1238
1239//! Prints information about the layer's current state
1240void
1241Layer::PrintToStream()
1242{
1243	printf("\n----------- Layer %s -----------\n", Name());
1244	printf("\t Parent: %s\n", fParent ? fParent->Name() : "<no parent>");
1245
1246	printf("\t us: %s\t ls: %s\n",
1247		fUpperSibling ? fUpperSibling->Name() : "<none>",
1248		fLowerSibling ? fLowerSibling->Name() : "<none>");
1249
1250	printf("\t topChild: %s\t bottomChild: %s\n",
1251		fTopChild ? fTopChild->Name() : "<none>",
1252		fBottomChild ? fBottomChild->Name() : "<none>");
1253
1254	printf("Frame: (%f, %f, %f, %f)", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
1255	printf("Token: %ld\n", fViewToken);
1256	printf("Hidden - direct: %s\n", fHidden?"true":"false");
1257	printf("Hidden - indirect: %s\n", IsHidden()?"true":"false");
1258	printf("ResizingMode: %lx\n", fResizeMode);
1259	printf("Flags: %lx\n", fFlags);
1260
1261	if (fLayerData)
1262		fLayerData->PrintToStream();
1263	else
1264		printf(" NO LayerData valid pointer\n");
1265}
1266
1267//! Prints pointer info kept by the current layer
1268void
1269Layer::PrintNode()
1270{
1271	printf("-----------\nLayer %s\n", Name());
1272	if (fParent)
1273		printf("Parent: %s (%p)\n", fParent->Name(), fParent);
1274	else
1275		printf("Parent: NULL\n");
1276
1277	if (fUpperSibling)
1278		printf("Upper sibling: %s (%p)\n", fUpperSibling->Name(), fUpperSibling);
1279	else
1280		printf("Upper sibling: NULL\n");
1281
1282	if (fLowerSibling)
1283		printf("Lower sibling: %s (%p)\n", fLowerSibling->Name(), fLowerSibling);
1284	else
1285		printf("Lower sibling: NULL\n");
1286
1287	if (fTopChild)
1288		printf("Top child: %s (%p)\n", fTopChild->Name(), fTopChild);
1289	else
1290		printf("Top child: NULL\n");
1291
1292	if (fBottomChild)
1293		printf("Bottom child: %s (%p)\n", fBottomChild->Name(), fBottomChild);
1294	else
1295		printf("Bottom child: NULL\n");
1296#ifndef NEW_CLIPPING
1297	printf("Visible Areas: "); fVisible.PrintToStream();
1298#endif
1299}
1300
1301//! Prints the tree hierarchy from the current layer down
1302void
1303Layer::PrintTree()
1304{
1305	printf("\n Tree structure:\n");
1306	printf("\t%s\t%s\n", Name(), IsHidden()? "Hidden": "NOT hidden");
1307	for(Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling())
1308		printf("\t%s\t%s\n", lay->Name(), lay->IsHidden()? "Hidden": "NOT hidden");
1309}
1310
1311// UpdateStart
1312void
1313Layer::UpdateStart()
1314{
1315	// During updates we only want to draw what's in the update region
1316	if (fClassID == AS_WINBORDER_CLASS) {
1317		// NOTE: don't worry, RooLayer is locked here.
1318		WinBorder	*wb = (WinBorder*)this;
1319
1320		wb->fInUpdate = true;
1321		wb->fRequestSent = false;
1322		wb->yUpdateReg = wb->fUpdateReg;
1323		wb->fUpdateReg.MakeEmpty();
1324wb->cnt--;
1325if (wb->cnt != 0)
1326	CRITICAL("Layer::UpdateStart(): wb->cnt != 0 -> Not Allowed!");
1327	}
1328}
1329
1330// UpdateEnd
1331void
1332Layer::UpdateEnd()
1333{
1334	// The usual case. Drawing is permitted in the whole visible area.
1335	if (fClassID == AS_WINBORDER_CLASS) {
1336		WinBorder	*wb = (WinBorder*)this;
1337
1338		wb->yUpdateReg.MakeEmpty();
1339
1340		wb->fInUpdate = false;
1341
1342		if (wb->zUpdateReg.CountRects() > 0) {
1343			BRegion		reg(wb->zUpdateReg);
1344			wb->RequestDraw(reg, NULL);
1345		}
1346	}
1347}
1348
1349
1350#ifndef NEW_CLIPPING
1351
1352
1353// move_layer
1354void
1355Layer::move_layer(float x, float y)
1356{
1357/*	if (fClassID == AS_WINBORDER_CLASS) {
1358		WinBorder	*wb = (WinBorder*)this;
1359		wb->zUpdateReg.OffsetBy(x, y);
1360		wb->yUpdateReg.OffsetBy(x, y);
1361		wb->fUpdateReg.OffsetBy(x, y);
1362	}*/
1363
1364	fFrameAction = B_LAYER_ACTION_MOVE;
1365
1366	BPoint pt(x, y);
1367	BRect rect(fFull.Frame().OffsetByCopy(pt));
1368
1369if (!fParent) {
1370printf("no parent in Layer::move_layer() (%s)\n", Name());
1371fFrameAction = B_LAYER_ACTION_NONE;
1372return;
1373}
1374
1375	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_MOVE, pt);
1376
1377	fDriver->CopyRegionList(&fRootLayer->fCopyRegList,
1378							&fRootLayer->fCopyList,
1379							fRootLayer->fCopyRegList.CountItems(),
1380							&fFullVisible);
1381
1382	fParent->Redraw(fRootLayer->fRedrawReg, this);
1383
1384	SendViewCoordUpdateMsg();
1385
1386	EmptyGlobals();
1387
1388	fFrameAction = B_LAYER_ACTION_NONE;
1389}
1390
1391// resize_layer
1392void
1393Layer::resize_layer(float x, float y)
1394{
1395	fFrameAction = B_LAYER_ACTION_RESIZE;
1396
1397	BPoint pt(x,y);
1398
1399	BRect rect(fFull.Frame());
1400	rect.right += x;
1401	rect.bottom += y;
1402
1403if (!fParent) {
1404printf("no parent in Layer::resize_layer() (%s)\n", Name());
1405fFrameAction = B_LAYER_ACTION_NONE;
1406return;
1407}
1408
1409	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_RESIZE, pt);
1410
1411	fDriver->CopyRegionList(&fRootLayer->fCopyRegList, &fRootLayer->fCopyList, fRootLayer->fCopyRegList.CountItems(), &fFullVisible);
1412
1413
1414	fParent->Redraw(fRootLayer->fRedrawReg, this);
1415
1416	SendViewCoordUpdateMsg();
1417
1418	EmptyGlobals();
1419
1420	fFrameAction = B_LAYER_ACTION_NONE;
1421}
1422
1423// FullInvalidate
1424void
1425Layer::FullInvalidate(const BRect &rect)
1426{
1427	FullInvalidate(BRegion(rect));
1428}
1429
1430// FullInvalidate
1431void
1432Layer::FullInvalidate(const BRegion& region)
1433{
1434	STRACE(("Layer(%s)::FullInvalidate():\n", Name()));
1435
1436#ifdef DEBUG_LAYER
1437	region.PrintToStream();
1438	printf("\n");
1439#endif
1440
1441	BPoint pt(0,0);
1442	StartRebuildRegions(region, NULL,/* B_LAYER_INVALIDATE, pt); */B_LAYER_NONE, pt);
1443
1444	Redraw(fRootLayer->fRedrawReg);
1445
1446	EmptyGlobals();
1447}
1448
1449// Invalidate
1450void
1451Layer::Invalidate(const BRegion& region)
1452{
1453	STRACE(("Layer(%s)::Invalidate():\n", Name()));
1454#ifdef DEBUG_LAYER
1455	region.PrintToStream();
1456	printf("\n");
1457#endif
1458
1459	fRootLayer->fRedrawReg	= region;
1460
1461	Redraw(fRootLayer->fRedrawReg);
1462
1463	EmptyGlobals();
1464}
1465
1466#endif // 5 methods
1467
1468// RequestDraw
1469void
1470Layer::RequestDraw(const BRegion &reg, Layer *startFrom)
1471{
1472	STRACE(("Layer(%s)::RequestDraw()\n", Name()));
1473printf("Layer(%s)::RequestDraw()\n", Name());
1474//if (fClassID == AS_ROOTLAYER_CLASS)
1475//	debugger("z");
1476	// do not redraw any child until you must
1477	int redraw = false;
1478	if (!startFrom)
1479		redraw = true;
1480
1481	if (HasClient() && IsTopLayer()) {
1482		// calculate the minimum region/rectangle to be updated with
1483		// a single message to the client.
1484#ifndef NEW_CLIPPING
1485		BRegion	updateReg(fFullVisible);
1486#else
1487		BRegion	updateReg(fFullVisible2);
1488#endif
1489
1490		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1491#ifndef NEW_CLIPPING
1492			&& fFrameAction	== B_LAYER_ACTION_RESIZE
1493#endif
1494		)
1495		{
1496			// do nothing
1497		} else {
1498			updateReg.IntersectWith(&reg);
1499		}
1500		if (updateReg.CountRects() > 0) {
1501			fOwner->zUpdateReg.Include(&updateReg);
1502			if (!fOwner->fInUpdate && !fOwner->fRequestSent) {
1503				fOwner->fUpdateReg = fOwner->zUpdateReg;
1504fOwner->cnt++;
1505if (fOwner->cnt != 1)
1506	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1507				fOwner->zUpdateReg.MakeEmpty();
1508				SendUpdateMsg(fOwner->fUpdateReg);
1509				fOwner->fRequestSent = true;
1510			}
1511		}
1512	}
1513
1514#ifndef NEW_CLIPPING
1515	if (fVisible.CountRects() > 0) {
1516		BRegion	updateReg(fVisible);
1517		// calculate the update region
1518		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fFrameAction == B_LAYER_ACTION_RESIZE) {
1519			// do nothing
1520		} else {
1521			updateReg.IntersectWith(&reg);
1522		}
1523
1524		if (updateReg.CountRects() > 0) {
1525			fDriver->ConstrainClippingRegion(&updateReg);
1526			Draw(updateReg.Frame());
1527			fDriver->ConstrainClippingRegion(NULL);
1528		}
1529	}
1530
1531	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1532		if (lay == startFrom)
1533			redraw = true;
1534
1535		if (redraw && !(lay->IsHidden())) {
1536			// no need to go deeper if not even the FullVisible region intersects
1537			// Update one.
1538			BRegion common(lay->fFullVisible);
1539			common.IntersectWith(&reg);
1540
1541			if (common.CountRects() > 0)
1542				lay->RequestDraw(reg, NULL);
1543		}
1544	}
1545#else
1546	if (fVisible2.CountRects() > 0) {
1547		BRegion	updateReg(fVisible2);
1548		// calculate the update region
1549		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1550// TODO: must be replaced!
1551//		 && fFrameAction == B_LAYER_ACTION_RESIZE
1552		) {
1553			// do nothing
1554		} else {
1555			updateReg.IntersectWith(&reg);
1556		}
1557
1558		if (updateReg.CountRects() > 0) {
1559			fDriver->ConstrainClippingRegion(&updateReg);
1560			Draw(updateReg.Frame());
1561			fDriver->ConstrainClippingRegion(NULL);
1562		}
1563	}
1564
1565	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1566		if (lay == startFrom)
1567			redraw = true;
1568
1569		if (redraw && !(lay->IsHidden())) {
1570			// no need to go deeper if not even the FullVisible region intersects
1571			// Update one.
1572			BRegion common(lay->fFullVisible2);
1573			common.IntersectWith(&reg);
1574
1575			if (common.CountRects() > 0)
1576				lay->RequestDraw(reg, NULL);
1577		}
1578	}
1579#endif
1580}
1581
1582/*!
1583	\brief Returns the layer's ServerWindow
1584
1585	If the layer's ServerWindow has not been assigned, it attempts to find
1586	the owning ServerWindow in the tree.
1587*/
1588ServerWindow*
1589Layer::SearchForServerWindow()
1590{
1591	if (!fServerWin)
1592		fServerWin=fParent->SearchForServerWindow();
1593
1594	return fServerWin;
1595}
1596
1597//! Sends an _UPDATE_ message to the client BWindow
1598void
1599Layer::SendUpdateMsg(BRegion& reg)
1600{
1601	BMessage msg;
1602	msg.what = _UPDATE_;
1603	msg.AddRect("_rect", ConvertFromTop(reg.Frame()) );
1604	msg.AddRect("debug_rect", reg.Frame() );
1605//	msg.AddInt32("_token",fViewToken);
1606
1607	fOwner->Window()->SendMessageToClient(&msg);
1608}
1609
1610// AddToViewsWithInvalidCoords
1611void
1612Layer::AddToViewsWithInvalidCoords() const
1613{
1614	if (fServerWin) {
1615		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
1616		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
1617		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
1618		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
1619	}
1620}
1621
1622// SendViewCoordUpdateMsg
1623void
1624Layer::SendViewCoordUpdateMsg() const
1625{
1626	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
1627		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
1628		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
1629	}
1630}
1631
1632// SetViewColor
1633void
1634Layer::SetViewColor(const RGBColor& color)
1635{
1636	fViewColor = color;
1637}
1638
1639// SetBackgroundBitmap
1640void
1641Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
1642{
1643	// TODO: What about reference counting?
1644	// "Release" old fBackgroundBitmap and "Aquire" new one?
1645	fBackgroundBitmap = bitmap;
1646}
1647
1648// SetOverlayBitmap
1649void
1650Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
1651{
1652	// TODO: What about reference counting?
1653	// "Release" old fOverlayBitmap and "Aquire" new one?
1654	fOverlayBitmap = bitmap;
1655}
1656
1657#ifdef NEW_CLIPPING
1658void
1659Layer::ConvertToScreen2(BRect* rect) const
1660{
1661	if (GetRootLayer())
1662		if (fParent) {
1663			BPoint origin = BoundsOrigin();
1664			rect->OffsetBy(-origin.x, -origin.y);
1665			rect->OffsetBy(fFrame.left, fFrame.top);
1666
1667			fParent->ConvertToScreen2(rect);
1668		}
1669}
1670
1671void
1672Layer::ConvertToScreen2(BRegion* reg) const
1673{
1674	if (GetRootLayer())
1675		if (fParent) {
1676			BPoint origin = BoundsOrigin();
1677			reg->OffsetBy(-origin.x, -origin.y);
1678			reg->OffsetBy(fFrame.left, fFrame.top);
1679
1680			fParent->ConvertToScreen2(reg);
1681		}
1682}
1683
1684void
1685Layer::do_Hide()
1686{
1687	fHidden = true;
1688
1689	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1690		// save fullVisible so we know what to invalidate
1691		BRegion invalid(fFullVisible2);
1692
1693		clear_visible_regions();
1694
1695		if (invalid.Frame().IsValid())
1696			fParent->do_Invalidate(invalid, this);
1697	}
1698}
1699
1700void
1701Layer::do_Show()
1702{
1703	fHidden = false;
1704
1705	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1706		BRegion invalid;
1707
1708		get_user_regions(invalid);
1709
1710		if (invalid.CountRects() > 0)
1711			fParent->do_Invalidate(invalid, this);
1712	}
1713}
1714
1715void
1716Layer::do_Invalidate(const BRegion &invalid, const Layer *startFrom)
1717{
1718	BRegion		localVisible(fFullVisible2);
1719	localVisible.IntersectWith(&invalid);
1720	rebuild_visible_regions(invalid, localVisible,
1721		startFrom? startFrom: BottomChild());
1722
1723	// add localVisible to our RootLayer's redraw region.
1724	GetRootLayer()->fRedrawReg.Include(&localVisible);
1725// TODO: ---
1726	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1727//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1728}
1729
1730void
1731Layer::do_Redraw(const BRegion &invalid, const Layer *startFrom)
1732{
1733	BRegion		localVisible(fFullVisible2);
1734	localVisible.IntersectWith(&invalid);
1735
1736	// add localVisible to our RootLayer's redraw region.
1737	GetRootLayer()->fRedrawReg.Include(&localVisible);
1738// TODO: ---
1739	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1740//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1741}
1742
1743inline void
1744Layer::resize_layer_frame_by(float x, float y)
1745{
1746	uint16		rm = fResizeMode & 0x0000FFFF;
1747	BRect		newFrame = fFrame;
1748
1749	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
1750		newFrame.left += 0.0f;
1751	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
1752		newFrame.left += x;
1753	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
1754		newFrame.left += x/2;
1755
1756	if ((rm & 0x000FU) == _VIEW_LEFT_)
1757		newFrame.right += 0.0f;
1758	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
1759		newFrame.right += x;
1760	else if ((rm & 0x000FU) == _VIEW_CENTER_)
1761		newFrame.right += x/2;
1762
1763	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
1764		newFrame.top += 0.0f;
1765	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
1766		newFrame.top += y;
1767	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
1768		newFrame.top += y/2;
1769
1770	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
1771		newFrame.bottom += 0.0f;
1772	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
1773		newFrame.bottom += y;
1774	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
1775		newFrame.bottom += y/2;
1776
1777	if (newFrame != fFrame) {
1778		float		dx, dy;
1779
1780		dx	= newFrame.Width() - fFrame.Width();
1781		dy	= newFrame.Height() - fFrame.Height();
1782
1783		fFrame	= newFrame;
1784
1785		if (dx != 0.0f || dy != 0.0f) {
1786			// call hook function
1787			ResizedByHook(dx, dy, true); // automatic
1788
1789			for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
1790				lay->resize_layer_frame_by(dx, dy);
1791		}
1792		else
1793			MovedByHook(dx, dy);
1794	}
1795}
1796
1797inline void
1798Layer::rezize_layer_redraw_more(BRegion &reg, float dx, float dy)
1799{
1800	if (dx == 0 && dy == 0)
1801		return;
1802
1803	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
1804		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1805
1806		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1807			// NOTE: this is not exactly corect, but it works :-)
1808			// Normaly we shoud've used the lay's old, required region - the one returned
1809			// from get_user_region() with the old frame, and the current one. lay->Bounds()
1810			// works for the moment so we leave it like this.
1811
1812			// calculate the old bounds.
1813			BRect	oldBounds(lay->Bounds());
1814			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
1815				oldBounds.right -=dx;
1816			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
1817				oldBounds.bottom -=dy;
1818
1819			// compute the region that became visible because we got bigger OR smaller.
1820			BRegion	regZ(lay->Bounds());
1821			regZ.Include(oldBounds);
1822			regZ.Exclude(oldBounds&lay->Bounds());
1823
1824			lay->ConvertToScreen2(&regZ);
1825
1826			// intersect that with this'(not lay's) fullVisible region
1827			regZ.IntersectWith(&fFullVisible2);
1828			reg.Include(&regZ);
1829
1830			lay->rezize_layer_redraw_more(reg,
1831				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1832				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1833
1834			// above, OR this:
1835			// reg.Include(&lay->fFullVisible2);
1836		}
1837		else
1838		if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
1839			((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) ||
1840			((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
1841			((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
1842		{
1843			reg.Include(&lay->fFullVisible2);
1844		}
1845	}
1846}
1847
1848inline void
1849Layer::resize_layer_full_update_on_resize(BRegion &reg, float dx, float dy)
1850{
1851	if (dx == 0 && dy == 0)
1852		return;
1853
1854	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
1855		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1856
1857		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1858			if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0)
1859				reg.Include(&lay->fVisible2);
1860
1861			lay->resize_layer_full_update_on_resize(reg,
1862				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1863				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1864		}
1865	}
1866}
1867
1868void
1869Layer::do_ResizeBy(float dx, float dy)
1870{
1871	fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
1872
1873	// resize children using their resize_mask.
1874	for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
1875			lay->resize_layer_frame_by(dx, dy);
1876
1877	// call hook function
1878	if (dx != 0.0f || dy != 0.0f)
1879		ResizedByHook(dx, dy, false); // manual
1880
1881	if (!IsHidden() && GetRootLayer()) {
1882		BRegion oldFullVisible(fFullVisible2);
1883		// this is required to invalidate the old border
1884		BRegion oldVisible(fVisible2);
1885
1886		// in case they moved, bottom, right and center aligned layers must be redrawn
1887		BRegion redrawMore;
1888		rezize_layer_redraw_more(redrawMore, dx, dy);
1889
1890		// we'll invalidate the old area and the new, maxmial one.
1891		BRegion invalid;
1892		get_user_regions(invalid);
1893		invalid.Include(&fFullVisible2);
1894
1895		clear_visible_regions();
1896
1897		fParent->do_RebuildVisibleRegions(invalid, this);
1898
1899		// done rebuilding regions, now redraw regions that became visible
1900
1901		// what's invalid, are the differences between to old and the new fullVisible region
1902		// 1) in case we grow.
1903		BRegion		redrawReg(fFullVisible2);
1904		redrawReg.Exclude(&oldFullVisible);
1905		// 2) in case we shrink
1906		BRegion		redrawReg2(oldFullVisible);
1907		redrawReg2.Exclude(&fFullVisible2);
1908		// 3) combine.
1909		redrawReg.Include(&redrawReg2);
1910
1911		// for center, right and bottom alligned layers, redraw their old positions
1912		redrawReg.Include(&redrawMore);
1913
1914		// layers that had their frame modified must be entirely redrawn.
1915		rezize_layer_redraw_more(redrawReg, dx, dy);
1916
1917		// add redrawReg to our RootLayer's redraw region.
1918		GetRootLayer()->fRedrawReg.Include(&redrawReg);
1919		// include layer's visible region in case we want a full update on resize
1920		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) {
1921			resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg, dx, dy);
1922
1923			GetRootLayer()->fRedrawReg.Include(&fVisible2);
1924			GetRootLayer()->fRedrawReg.Include(&oldVisible);
1925		}
1926		// clear canvas and set invalid regions for affected WinBorders
1927// TODO: ---
1928	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1929//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1930	}
1931}
1932
1933void Layer::do_MoveBy(float dx, float dy)
1934{
1935	if (dx == 0.0f && dy == 0.0f)
1936		return;
1937
1938//	fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
1939	fFrame.OffsetBy(dx, dy);
1940
1941	// call hook function
1942	MovedByHook(dx, dy);
1943
1944	if (!IsHidden() && GetRootLayer()) {
1945		BRegion oldFullVisible(fFullVisible2);
1946
1947		// we'll invalidate the old position and the new, maxmial one.
1948		BRegion invalid;
1949		get_user_regions(invalid);
1950		invalid.Include(&fFullVisible2);
1951
1952		clear_visible_regions();
1953
1954		fParent->do_RebuildVisibleRegions(invalid, this);
1955
1956		// done rebuilding regions, now copy common parts and redraw regions that became visible
1957
1958		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
1959		BRegion		redrawReg(fFullVisible2);
1960		redrawReg.Include(&oldFullVisible);
1961
1962		// offset to layer's new location so that we can calculate the common region.
1963		oldFullVisible.OffsetBy(dx, dy);
1964
1965		// finally we have the region that needs to be redrawn.
1966		redrawReg.Exclude(&oldFullVisible);
1967
1968		// by intersecting the old fullVisible offseted to layer's new location, with the current
1969		// fullVisible, we'll have the common region which can be copied using HW acceleration.
1970		oldFullVisible.IntersectWith(&fFullVisible2);
1971
1972		// offset back and instruct the HW to do the actual copying.
1973		oldFullVisible.OffsetBy(-dx, -dy);
1974// TODO: uncomment!!!
1975//		GetRootLayer()->CopyRegion(&oldFullVisible, dx, dy);
1976
1977		// add redrawReg to our RootLayer's redraw region.
1978		GetRootLayer()->fRedrawReg.Include(&redrawReg);
1979// TODO: ---
1980	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1981//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1982	}
1983}
1984
1985void
1986Layer::do_ScrollBy(float dx, float dy)
1987{
1988	fLayerData->OffsetOrigin(BPoint(dx, dy));
1989//	fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy);
1990
1991	if (!IsHidden() && GetRootLayer()) {
1992		// set the region to be invalidated.
1993		BRegion		invalid(fFullVisible2);
1994
1995		clear_visible_regions();
1996
1997		rebuild_visible_regions(invalid, invalid, BottomChild());
1998
1999		// for the moment we say that the whole surface needs to be redraw.
2000		BRegion		redrawReg(fFullVisible2);
2001
2002		// offset old region so that we can start comparing.
2003		invalid.OffsetBy(dx, dy);
2004
2005		// compute the common region. we'll use HW acc to copy this to the new location.
2006		invalid.IntersectWith(&fFullVisible2);
2007// TODO: uncomment!!!
2008//		GetRootLayer()->CopyRegion(&invalid, -dx, -dy);
2009
2010		// common region goes back to its original location. then, by excluding
2011		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
2012		invalid.OffsetBy(-dx, -dy);
2013		redrawReg.Exclude(&invalid);
2014
2015		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2016// TODO: ---
2017	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
2018//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2019	}
2020
2021	if (dx != 0.0f || dy != 0.0f)
2022		ScrolledByHook(dx, dy);
2023}
2024void
2025Layer::get_user_regions(BRegion &reg)
2026{
2027	// 1) set to frame in screen coords
2028	BRect			screenFrame(Bounds());
2029	ConvertToScreen2(&screenFrame);
2030	reg.Set(screenFrame);
2031
2032	// 2) intersect with screen region
2033	BRegion			screenReg(GetRootLayer()->Bounds());
2034	reg.IntersectWith(&screenReg);
2035
2036// TODO: you MUST at some point uncomment this block!
2037/*
2038	// 3) impose user constrained regions
2039	LayerData		*stackData = fLayerData;
2040	while (stackData)
2041	{
2042		// transform in screen coords
2043		BRegion		screenReg(stackData->ClippingRegion());
2044		ConvertToScreen2(&screenReg);
2045		reg.IntersectWith(&screenReg);
2046		stackData	= stackData->prevState;
2047	}
2048*/
2049}
2050
2051void
2052Layer::do_RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom)
2053{
2054	BRegion		localVisible(fFullVisible2);
2055	localVisible.IntersectWith(&invalid);
2056	rebuild_visible_regions(invalid, localVisible, startFrom);
2057}
2058
2059void
2060Layer::rebuild_visible_regions(const BRegion &invalid,
2061								const BRegion &parentLocalVisible,
2062								const Layer *startFrom)
2063{
2064	// no point in continuing if this layer is hidden. starting from here, all
2065	// descendants have (and will have) invalid visible regions.
2066	if (fHidden)
2067		return;
2068
2069	// no need to go deeper if the parent doesn't have a visible region anymore
2070	// and our fullVisible region is also empty.
2071	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0))
2072		return;
2073
2074	bool fullRebuild = false;
2075
2076	// intersect maximum wanted region with the invalid region
2077	BRegion common;
2078	get_user_regions(common);
2079	common.IntersectWith(&invalid);
2080
2081	// if the resulted region is not valid, this layer is not in the catchment area
2082	// of the region being invalidated
2083	if (!common.CountRects() > 0)
2084		return;
2085
2086	// now intersect with parent's visible part of the region that was/is invalidated
2087	common.IntersectWith(&parentLocalVisible);
2088
2089	// exclude the invalid region
2090	fFullVisible2.Exclude(&invalid);
2091	fVisible2.Exclude(&invalid);
2092
2093	// put in what's really visible
2094	fFullVisible2.Include(&common);
2095
2096	// this is to allow a layer to hide some parts of itself so children
2097	// won't take them.
2098	BRegion unalteredVisible(common);
2099	bool altered = alter_visible_for_children(common);
2100
2101	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
2102		if (lay == startFrom)
2103			fullRebuild = true;
2104
2105		if (fullRebuild)
2106			lay->rebuild_visible_regions(invalid, common, lay->BottomChild());
2107
2108		// to let children know much they can take from parent's visible region
2109		common.Exclude(&lay->fFullVisible2);
2110		// we've hidden some parts of our visible region from our children,
2111		// and we must be in sysnc with this region too...
2112		if (altered)
2113			unalteredVisible.Exclude(&lay->fFullVisible2);
2114	}
2115
2116	// the visible region of this layer is what left after all its children took
2117	// what they could.
2118	if (altered)
2119		fVisible2.Include(&unalteredVisible);
2120	else
2121		fVisible2.Include(&common);
2122}
2123
2124bool
2125Layer::alter_visible_for_children(BRegion &reg)
2126{
2127	// Empty Hook function
2128	return false;
2129}
2130
2131void
2132Layer::clear_visible_regions()
2133{
2134	// OPT: maybe we should uncomment these lines for performance
2135	//if (fFullVisible2.CountRects() <= 0)
2136	//	return;
2137
2138	fVisible2.MakeEmpty();
2139	fFullVisible2.MakeEmpty();
2140	for (Layer *child = BottomChild(); child; child = UpperSibling())
2141		child->clear_visible_regions();
2142}
2143
2144#endif
2145
2146