Layer.cpp revision e603410b82dea0c0cf4a474dfa055b4bc87de5e6
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// RequestDraw
1320void
1321Layer::RequestDraw(const BRegion &reg, Layer *startFrom)
1322{
1323	STRACE(("Layer(%s)::RequestDraw()\n", Name()));
1324
1325	// do not redraw any child until you must
1326	int redraw = false;
1327	if (!startFrom)
1328		redraw = true;
1329
1330#ifndef NEW_CLIPPING
1331	if (HasClient() && IsTopLayer()) {
1332		// calculate the minimum region/rectangle to be updated with
1333		// a single message to the client.
1334		BRegion	updateReg(fFullVisible);
1335
1336		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1337			&& fFrameAction	== B_LAYER_ACTION_RESIZE)
1338		{
1339			// do nothing
1340		} else {
1341			updateReg.IntersectWith(&reg);
1342		}
1343		if (updateReg.CountRects() > 0) {
1344			fOwner->fCumulativeRegion.Include(&updateReg);
1345			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1346				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1347fOwner->cnt++;
1348if (fOwner->cnt != 1)
1349	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1350				fOwner->fCumulativeRegion.MakeEmpty();
1351				fOwner->fRequestSent = true;
1352				SendUpdateMsg(fOwner->fInUpdateRegion);
1353			}
1354		}
1355	}
1356
1357	if (fVisible.CountRects() > 0) {
1358		BRegion	updateReg(fVisible);
1359		// calculate the update region
1360		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fFrameAction == B_LAYER_ACTION_RESIZE) {
1361			// do nothing
1362		} else {
1363			updateReg.IntersectWith(&reg);
1364		}
1365
1366		if (updateReg.CountRects() > 0) {
1367			fDriver->ConstrainClippingRegion(&updateReg);
1368			Draw(updateReg.Frame());
1369			fDriver->ConstrainClippingRegion(NULL);
1370		}
1371	}
1372
1373	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1374		if (lay == startFrom)
1375			redraw = true;
1376
1377		if (redraw && !(lay->IsHidden())) {
1378			// no need to go deeper if not even the FullVisible region intersects
1379			// Update one.
1380			BRegion common(lay->fFullVisible);
1381			common.IntersectWith(&reg);
1382
1383			if (common.CountRects() > 0)
1384				lay->RequestDraw(reg, NULL);
1385		}
1386	}
1387#else
1388	if (HasClient() && IsTopLayer()) {
1389		// calculate the minimum region/rectangle to be updated with
1390		// a single message to the client.
1391		BRegion	updateReg(fFullVisible2);
1392
1393		updateReg.IntersectWith(&reg);
1394
1395		if (updateReg.CountRects() > 0) {
1396			fOwner->fCumulativeRegion.Include(&updateReg);
1397			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1398				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1399fOwner->cnt++;
1400if (fOwner->cnt != 1)
1401	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1402				fOwner->fCumulativeRegion.MakeEmpty();
1403				fOwner->fRequestSent = true;
1404printf("Send\n");
1405				SendUpdateMsg(fOwner->fInUpdateRegion);
1406			}
1407		}
1408	}
1409
1410	if (fVisible2.CountRects() > 0) {
1411		BRegion	updateReg(fVisible2);
1412			updateReg.IntersectWith(&reg);
1413
1414		if (updateReg.CountRects() > 0) {
1415			fDriver->ConstrainClippingRegion(&updateReg);
1416			Draw(updateReg.Frame());
1417			fDriver->ConstrainClippingRegion(NULL);
1418		}
1419	}
1420
1421	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1422		if (lay == startFrom)
1423			redraw = true;
1424
1425		if (redraw && !(lay->IsHidden())) {
1426			// no need to go deeper if not even the FullVisible region intersects
1427			// Update one.
1428			BRegion common(lay->fFullVisible2);
1429			common.IntersectWith(&reg);
1430
1431			if (common.CountRects() > 0)
1432				lay->RequestDraw(reg, NULL);
1433		}
1434	}
1435#endif
1436}
1437
1438#ifndef NEW_CLIPPING
1439
1440// move_layer
1441void
1442Layer::move_layer(float x, float y)
1443{
1444/*	if (fClassID == AS_WINBORDER_CLASS) {
1445		WinBorder	*wb = (WinBorder*)this;
1446		wb->fCumulativeRegion.OffsetBy(x, y);
1447		wb->fInUpdateRegion.OffsetBy(x, y);
1448		wb->fSavedForUpdateRegion.OffsetBy(x, y);
1449	}*/
1450
1451	fFrameAction = B_LAYER_ACTION_MOVE;
1452
1453	BPoint pt(x, y);
1454	BRect rect(fFull.Frame().OffsetByCopy(pt));
1455
1456if (!fParent) {
1457printf("no parent in Layer::move_layer() (%s)\n", Name());
1458fFrameAction = B_LAYER_ACTION_NONE;
1459return;
1460}
1461
1462	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_MOVE, pt);
1463
1464	fDriver->CopyRegionList(&fRootLayer->fCopyRegList,
1465							&fRootLayer->fCopyList,
1466							fRootLayer->fCopyRegList.CountItems(),
1467							&fFullVisible);
1468
1469	fParent->Redraw(fRootLayer->fRedrawReg, this);
1470
1471	SendViewCoordUpdateMsg();
1472
1473	EmptyGlobals();
1474
1475	fFrameAction = B_LAYER_ACTION_NONE;
1476}
1477
1478// resize_layer
1479void
1480Layer::resize_layer(float x, float y)
1481{
1482	fFrameAction = B_LAYER_ACTION_RESIZE;
1483
1484	BPoint pt(x,y);
1485
1486	BRect rect(fFull.Frame());
1487	rect.right += x;
1488	rect.bottom += y;
1489
1490if (!fParent) {
1491printf("no parent in Layer::resize_layer() (%s)\n", Name());
1492fFrameAction = B_LAYER_ACTION_NONE;
1493return;
1494}
1495
1496	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_RESIZE, pt);
1497
1498	fDriver->CopyRegionList(&fRootLayer->fCopyRegList, &fRootLayer->fCopyList, fRootLayer->fCopyRegList.CountItems(), &fFullVisible);
1499
1500
1501	fParent->Redraw(fRootLayer->fRedrawReg, this);
1502
1503	SendViewCoordUpdateMsg();
1504
1505	EmptyGlobals();
1506
1507	fFrameAction = B_LAYER_ACTION_NONE;
1508}
1509
1510// FullInvalidate
1511void
1512Layer::FullInvalidate(const BRect &rect)
1513{
1514	FullInvalidate(BRegion(rect));
1515}
1516
1517// FullInvalidate
1518void
1519Layer::FullInvalidate(const BRegion& region)
1520{
1521	STRACE(("Layer(%s)::FullInvalidate():\n", Name()));
1522
1523#ifdef DEBUG_LAYER
1524	region.PrintToStream();
1525	printf("\n");
1526#endif
1527
1528	BPoint pt(0,0);
1529	StartRebuildRegions(region, NULL,/* B_LAYER_INVALIDATE, pt); */B_LAYER_NONE, pt);
1530
1531	Redraw(fRootLayer->fRedrawReg);
1532
1533	EmptyGlobals();
1534}
1535
1536// Invalidate
1537void
1538Layer::Invalidate(const BRegion& region)
1539{
1540	STRACE(("Layer(%s)::Invalidate():\n", Name()));
1541#ifdef DEBUG_LAYER
1542	region.PrintToStream();
1543	printf("\n");
1544#endif
1545
1546	fRootLayer->fRedrawReg	= region;
1547
1548	Redraw(fRootLayer->fRedrawReg);
1549
1550	EmptyGlobals();
1551}
1552
1553#endif // 5 methods
1554
1555
1556/*!
1557	\brief Returns the layer's ServerWindow
1558
1559	If the layer's ServerWindow has not been assigned, it attempts to find
1560	the owning ServerWindow in the tree.
1561*/
1562ServerWindow*
1563Layer::SearchForServerWindow()
1564{
1565	if (!fServerWin)
1566		fServerWin=fParent->SearchForServerWindow();
1567
1568	return fServerWin;
1569}
1570
1571//! Sends an _UPDATE_ message to the client BWindow
1572void
1573Layer::SendUpdateMsg(BRegion& reg)
1574{
1575	BMessage msg;
1576	msg.what = _UPDATE_;
1577	msg.AddRect("_rect", ConvertFromTop(reg.Frame()) );
1578	msg.AddRect("debug_rect", reg.Frame() );
1579//	msg.AddInt32("_token",fViewToken);
1580
1581	fOwner->Window()->SendMessageToClient(&msg);
1582}
1583
1584// AddToViewsWithInvalidCoords
1585void
1586Layer::AddToViewsWithInvalidCoords() const
1587{
1588	if (fServerWin) {
1589		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
1590		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
1591		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
1592		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
1593	}
1594}
1595
1596// SendViewCoordUpdateMsg
1597void
1598Layer::SendViewCoordUpdateMsg() const
1599{
1600	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
1601		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
1602		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
1603	}
1604}
1605
1606// SetViewColor
1607void
1608Layer::SetViewColor(const RGBColor& color)
1609{
1610	fViewColor = color;
1611}
1612
1613// SetBackgroundBitmap
1614void
1615Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
1616{
1617	// TODO: What about reference counting?
1618	// "Release" old fBackgroundBitmap and "Aquire" new one?
1619	fBackgroundBitmap = bitmap;
1620}
1621
1622// SetOverlayBitmap
1623void
1624Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
1625{
1626	// TODO: What about reference counting?
1627	// "Release" old fOverlayBitmap and "Aquire" new one?
1628	fOverlayBitmap = bitmap;
1629}
1630
1631#ifdef NEW_CLIPPING
1632void
1633Layer::ConvertToScreen2(BRect* rect) const
1634{
1635	if (GetRootLayer())
1636		if (fParent) {
1637			BPoint origin = BoundsOrigin();
1638			rect->OffsetBy(-origin.x, -origin.y);
1639			rect->OffsetBy(fFrame.left, fFrame.top);
1640
1641			fParent->ConvertToScreen2(rect);
1642		}
1643}
1644
1645void
1646Layer::ConvertToScreen2(BRegion* reg) const
1647{
1648	if (GetRootLayer())
1649		if (fParent) {
1650			BPoint origin = BoundsOrigin();
1651			reg->OffsetBy(-origin.x, -origin.y);
1652			reg->OffsetBy(fFrame.left, fFrame.top);
1653
1654			fParent->ConvertToScreen2(reg);
1655		}
1656}
1657
1658void
1659Layer::do_Hide()
1660{
1661	fHidden = true;
1662
1663	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1664		// save fullVisible so we know what to invalidate
1665		BRegion invalid(fFullVisible2);
1666
1667		clear_visible_regions();
1668
1669		if (invalid.Frame().IsValid())
1670			fParent->do_Invalidate(invalid, this);
1671	}
1672}
1673
1674void
1675Layer::do_Show()
1676{
1677	fHidden = false;
1678
1679	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1680		BRegion invalid;
1681
1682		get_user_regions(invalid);
1683
1684		if (invalid.CountRects() > 0)
1685			fParent->do_Invalidate(invalid, this);
1686	}
1687}
1688
1689void
1690Layer::do_Invalidate(const BRegion &invalid, const Layer *startFrom)
1691{
1692	BRegion		localVisible(fFullVisible2);
1693	localVisible.IntersectWith(&invalid);
1694	rebuild_visible_regions(invalid, localVisible,
1695		startFrom? startFrom: BottomChild());
1696
1697	// add localVisible to our RootLayer's redraw region.
1698	GetRootLayer()->fRedrawReg.Include(&localVisible);
1699// TODO: ---
1700	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1701//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1702}
1703
1704void
1705Layer::do_Redraw(const BRegion &invalid, const Layer *startFrom)
1706{
1707	BRegion		localVisible(fFullVisible2);
1708	localVisible.IntersectWith(&invalid);
1709
1710	// add localVisible to our RootLayer's redraw region.
1711	GetRootLayer()->fRedrawReg.Include(&localVisible);
1712// TODO: ---
1713	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1714//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1715}
1716
1717inline void
1718Layer::resize_layer_frame_by(float x, float y)
1719{
1720	uint16		rm = fResizeMode & 0x0000FFFF;
1721	BRect		newFrame = fFrame;
1722
1723	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
1724		newFrame.left += 0.0f;
1725	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
1726		newFrame.left += x;
1727	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
1728		newFrame.left += x/2;
1729
1730	if ((rm & 0x000FU) == _VIEW_LEFT_)
1731		newFrame.right += 0.0f;
1732	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
1733		newFrame.right += x;
1734	else if ((rm & 0x000FU) == _VIEW_CENTER_)
1735		newFrame.right += x/2;
1736
1737	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
1738		newFrame.top += 0.0f;
1739	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
1740		newFrame.top += y;
1741	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
1742		newFrame.top += y/2;
1743
1744	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
1745		newFrame.bottom += 0.0f;
1746	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
1747		newFrame.bottom += y;
1748	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
1749		newFrame.bottom += y/2;
1750
1751	if (newFrame != fFrame) {
1752		float		dx, dy;
1753
1754		dx	= newFrame.Width() - fFrame.Width();
1755		dy	= newFrame.Height() - fFrame.Height();
1756
1757		fFrame	= newFrame;
1758
1759		if (dx != 0.0f || dy != 0.0f) {
1760			// call hook function
1761			ResizedByHook(dx, dy, true); // automatic
1762
1763			for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
1764				lay->resize_layer_frame_by(dx, dy);
1765		}
1766		else
1767			MovedByHook(dx, dy);
1768	}
1769}
1770
1771inline void
1772Layer::rezize_layer_redraw_more(BRegion &reg, float dx, float dy)
1773{
1774	if (dx == 0 && dy == 0)
1775		return;
1776
1777	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
1778		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1779
1780		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1781			// NOTE: this is not exactly corect, but it works :-)
1782			// Normaly we shoud've used the lay's old, required region - the one returned
1783			// from get_user_region() with the old frame, and the current one. lay->Bounds()
1784			// works for the moment so we leave it like this.
1785
1786			// calculate the old bounds.
1787			BRect	oldBounds(lay->Bounds());
1788			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
1789				oldBounds.right -=dx;
1790			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
1791				oldBounds.bottom -=dy;
1792
1793			// compute the region that became visible because we got bigger OR smaller.
1794			BRegion	regZ(lay->Bounds());
1795			regZ.Include(oldBounds);
1796			regZ.Exclude(oldBounds&lay->Bounds());
1797
1798			lay->ConvertToScreen2(&regZ);
1799
1800			// intersect that with this'(not lay's) fullVisible region
1801			regZ.IntersectWith(&fFullVisible2);
1802			reg.Include(&regZ);
1803
1804			lay->rezize_layer_redraw_more(reg,
1805				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1806				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1807
1808			// above, OR this:
1809			// reg.Include(&lay->fFullVisible2);
1810		}
1811		else
1812		if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
1813			((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) ||
1814			((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
1815			((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
1816		{
1817			reg.Include(&lay->fFullVisible2);
1818		}
1819	}
1820}
1821
1822inline void
1823Layer::resize_layer_full_update_on_resize(BRegion &reg, float dx, float dy)
1824{
1825	if (dx == 0 && dy == 0)
1826		return;
1827
1828	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
1829		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1830
1831		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1832			if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0)
1833				reg.Include(&lay->fVisible2);
1834
1835			lay->resize_layer_full_update_on_resize(reg,
1836				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1837				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1838		}
1839	}
1840}
1841
1842void
1843Layer::do_ResizeBy(float dx, float dy)
1844{
1845	fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
1846
1847	// resize children using their resize_mask.
1848	for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
1849			lay->resize_layer_frame_by(dx, dy);
1850
1851	// call hook function
1852	if (dx != 0.0f || dy != 0.0f)
1853		ResizedByHook(dx, dy, false); // manual
1854
1855	if (!IsHidden() && GetRootLayer()) {
1856		BRegion oldFullVisible(fFullVisible2);
1857		// this is required to invalidate the old border
1858		BRegion oldVisible(fVisible2);
1859
1860		// in case they moved, bottom, right and center aligned layers must be redrawn
1861		BRegion redrawMore;
1862		rezize_layer_redraw_more(redrawMore, dx, dy);
1863
1864		// we'll invalidate the old area and the new, maxmial one.
1865		BRegion invalid;
1866		get_user_regions(invalid);
1867		invalid.Include(&fFullVisible2);
1868
1869		clear_visible_regions();
1870
1871		fParent->do_RebuildVisibleRegions(invalid, this);
1872
1873		// done rebuilding regions, now redraw regions that became visible
1874
1875		// what's invalid, are the differences between to old and the new fullVisible region
1876		// 1) in case we grow.
1877		BRegion		redrawReg(fFullVisible2);
1878		redrawReg.Exclude(&oldFullVisible);
1879		// 2) in case we shrink
1880		BRegion		redrawReg2(oldFullVisible);
1881		redrawReg2.Exclude(&fFullVisible2);
1882		// 3) combine.
1883		redrawReg.Include(&redrawReg2);
1884
1885		// for center, right and bottom alligned layers, redraw their old positions
1886		redrawReg.Include(&redrawMore);
1887
1888		// layers that had their frame modified must be entirely redrawn.
1889		rezize_layer_redraw_more(redrawReg, dx, dy);
1890
1891		// add redrawReg to our RootLayer's redraw region.
1892		GetRootLayer()->fRedrawReg.Include(&redrawReg);
1893		// include layer's visible region in case we want a full update on resize
1894		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) {
1895			resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg, dx, dy);
1896
1897			GetRootLayer()->fRedrawReg.Include(&fVisible2);
1898			GetRootLayer()->fRedrawReg.Include(&oldVisible);
1899		}
1900		// clear canvas and set invalid regions for affected WinBorders
1901// TODO: ---
1902	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1903//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1904	}
1905}
1906
1907void Layer::do_MoveBy(float dx, float dy)
1908{
1909	if (dx == 0.0f && dy == 0.0f)
1910		return;
1911
1912//	fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
1913	fFrame.OffsetBy(dx, dy);
1914
1915	// call hook function
1916	MovedByHook(dx, dy);
1917
1918	if (!IsHidden() && GetRootLayer()) {
1919		BRegion oldFullVisible(fFullVisible2);
1920
1921		// we'll invalidate the old position and the new, maxmial one.
1922		BRegion invalid;
1923		get_user_regions(invalid);
1924		invalid.Include(&fFullVisible2);
1925
1926		clear_visible_regions();
1927
1928		fParent->do_RebuildVisibleRegions(invalid, this);
1929
1930		// done rebuilding regions, now copy common parts and redraw regions that became visible
1931
1932		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
1933		BRegion		redrawReg(fFullVisible2);
1934		redrawReg.Include(&oldFullVisible);
1935
1936		// offset to layer's new location so that we can calculate the common region.
1937		oldFullVisible.OffsetBy(dx, dy);
1938
1939		// finally we have the region that needs to be redrawn.
1940		redrawReg.Exclude(&oldFullVisible);
1941
1942		// by intersecting the old fullVisible offseted to layer's new location, with the current
1943		// fullVisible, we'll have the common region which can be copied using HW acceleration.
1944		oldFullVisible.IntersectWith(&fFullVisible2);
1945
1946		// offset back and instruct the HW to do the actual copying.
1947		oldFullVisible.OffsetBy(-dx, -dy);
1948// TODO: uncomment!!!
1949//		GetRootLayer()->CopyRegion(&oldFullVisible, dx, dy);
1950
1951		// add redrawReg to our RootLayer's redraw region.
1952		GetRootLayer()->fRedrawReg.Include(&redrawReg);
1953// TODO: ---
1954	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1955//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1956	}
1957}
1958
1959void
1960Layer::do_ScrollBy(float dx, float dy)
1961{
1962	fLayerData->OffsetOrigin(BPoint(dx, dy));
1963//	fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy);
1964
1965	if (!IsHidden() && GetRootLayer()) {
1966		// set the region to be invalidated.
1967		BRegion		invalid(fFullVisible2);
1968
1969		clear_visible_regions();
1970
1971		rebuild_visible_regions(invalid, invalid, BottomChild());
1972
1973		// for the moment we say that the whole surface needs to be redraw.
1974		BRegion		redrawReg(fFullVisible2);
1975
1976		// offset old region so that we can start comparing.
1977		invalid.OffsetBy(dx, dy);
1978
1979		// compute the common region. we'll use HW acc to copy this to the new location.
1980		invalid.IntersectWith(&fFullVisible2);
1981// TODO: uncomment!!!
1982//		GetRootLayer()->CopyRegion(&invalid, -dx, -dy);
1983
1984		// common region goes back to its original location. then, by excluding
1985		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
1986		invalid.OffsetBy(-dx, -dy);
1987		redrawReg.Exclude(&invalid);
1988
1989		GetRootLayer()->fRedrawReg.Include(&redrawReg);
1990// TODO: ---
1991	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1992//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1993	}
1994
1995	if (dx != 0.0f || dy != 0.0f)
1996		ScrolledByHook(dx, dy);
1997}
1998void
1999Layer::get_user_regions(BRegion &reg)
2000{
2001	// 1) set to frame in screen coords
2002	BRect			screenFrame(Bounds());
2003	ConvertToScreen2(&screenFrame);
2004	reg.Set(screenFrame);
2005
2006	// 2) intersect with screen region
2007	BRegion			screenReg(GetRootLayer()->Bounds());
2008	reg.IntersectWith(&screenReg);
2009
2010// TODO: you MUST at some point uncomment this block!
2011/*
2012	// 3) impose user constrained regions
2013	LayerData		*stackData = fLayerData;
2014	while (stackData)
2015	{
2016		// transform in screen coords
2017		BRegion		screenReg(stackData->ClippingRegion());
2018		ConvertToScreen2(&screenReg);
2019		reg.IntersectWith(&screenReg);
2020		stackData	= stackData->prevState;
2021	}
2022*/
2023}
2024
2025void
2026Layer::do_RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom)
2027{
2028	BRegion		localVisible(fFullVisible2);
2029	localVisible.IntersectWith(&invalid);
2030	rebuild_visible_regions(invalid, localVisible, startFrom);
2031}
2032
2033void
2034Layer::rebuild_visible_regions(const BRegion &invalid,
2035								const BRegion &parentLocalVisible,
2036								const Layer *startFrom)
2037{
2038	// no point in continuing if this layer is hidden. starting from here, all
2039	// descendants have (and will have) invalid visible regions.
2040	if (fHidden)
2041		return;
2042
2043	// no need to go deeper if the parent doesn't have a visible region anymore
2044	// and our fullVisible region is also empty.
2045	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0))
2046		return;
2047
2048	bool fullRebuild = false;
2049
2050	// intersect maximum wanted region with the invalid region
2051	BRegion common;
2052	get_user_regions(common);
2053	common.IntersectWith(&invalid);
2054
2055	// if the resulted region is not valid, this layer is not in the catchment area
2056	// of the region being invalidated
2057	if (!common.CountRects() > 0)
2058		return;
2059
2060	// now intersect with parent's visible part of the region that was/is invalidated
2061	common.IntersectWith(&parentLocalVisible);
2062
2063	// exclude the invalid region
2064	fFullVisible2.Exclude(&invalid);
2065	fVisible2.Exclude(&invalid);
2066
2067	// put in what's really visible
2068	fFullVisible2.Include(&common);
2069
2070	// this is to allow a layer to hide some parts of itself so children
2071	// won't take them.
2072	BRegion unalteredVisible(common);
2073	bool altered = alter_visible_for_children(common);
2074
2075	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
2076		if (lay == startFrom)
2077			fullRebuild = true;
2078
2079		if (fullRebuild)
2080			lay->rebuild_visible_regions(invalid, common, lay->BottomChild());
2081
2082		// to let children know much they can take from parent's visible region
2083		common.Exclude(&lay->fFullVisible2);
2084		// we've hidden some parts of our visible region from our children,
2085		// and we must be in sysnc with this region too...
2086		if (altered)
2087			unalteredVisible.Exclude(&lay->fFullVisible2);
2088	}
2089
2090	// the visible region of this layer is what left after all its children took
2091	// what they could.
2092	if (altered)
2093		fVisible2.Include(&unalteredVisible);
2094	else
2095		fVisible2.Include(&common);
2096}
2097
2098bool
2099Layer::alter_visible_for_children(BRegion &reg)
2100{
2101	// Empty Hook function
2102	return false;
2103}
2104
2105void
2106Layer::clear_visible_regions()
2107{
2108	// OPT: maybe we should uncomment these lines for performance
2109	//if (fFullVisible2.CountRects() <= 0)
2110	//	return;
2111
2112	fVisible2.MakeEmpty();
2113	fFullVisible2.MakeEmpty();
2114	for (Layer *child = BottomChild(); child; child = UpperSibling())
2115		child->clear_visible_regions();
2116}
2117
2118#endif
2119
2120