Layer.cpp revision 08d9a6e30d49aac2ac85f0d141408bb66f7712c5
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, 1, 1);
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", 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)\n", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
1263	printf("LocalOrigin: (%f, %f)\n", BoundsOrigin().x, BoundsOrigin().y);
1264	printf("Token: %ld\n", fViewToken);
1265	printf("Hidden - direct: %s ", fHidden?"true":"false");
1266	printf("Hidden - indirect: %s\n", IsHidden()?"true":"false");
1267	printf("ResizingMode: %lx ", fResizeMode);
1268	printf("Flags: %lx\n", fFlags);
1269
1270	if (fLayerData)
1271		fLayerData->PrintToStream();
1272	else
1273		printf(" NO LayerData valid pointer\n");
1274}
1275
1276//! Prints pointer info kept by the current layer
1277void
1278Layer::PrintNode()
1279{
1280	printf("-----------\nLayer %s\n", Name());
1281	if (fParent)
1282		printf("Parent: %s (%p)\n", fParent->Name(), fParent);
1283	else
1284		printf("Parent: NULL\n");
1285
1286	if (fUpperSibling)
1287		printf("Upper sibling: %s (%p)\n", fUpperSibling->Name(), fUpperSibling);
1288	else
1289		printf("Upper sibling: NULL\n");
1290
1291	if (fLowerSibling)
1292		printf("Lower sibling: %s (%p)\n", fLowerSibling->Name(), fLowerSibling);
1293	else
1294		printf("Lower sibling: NULL\n");
1295
1296	if (fTopChild)
1297		printf("Top child: %s (%p)\n", fTopChild->Name(), fTopChild);
1298	else
1299		printf("Top child: NULL\n");
1300
1301	if (fBottomChild)
1302		printf("Bottom child: %s (%p)\n", fBottomChild->Name(), fBottomChild);
1303	else
1304		printf("Bottom child: NULL\n");
1305#ifndef NEW_CLIPPING
1306	printf("Visible Areas: "); fVisible.PrintToStream();
1307#endif
1308}
1309
1310//! Prints the tree hierarchy from the current layer down
1311void
1312Layer::PrintTree()
1313{
1314	printf("\n Tree structure:\n");
1315	printf("\t%s\t%s\n", Name(), IsHidden()? "Hidden": "NOT hidden");
1316	for(Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling())
1317		printf("\t%s\t%s\n", lay->Name(), lay->IsHidden()? "Hidden": "NOT hidden");
1318}
1319
1320// RequestDraw
1321void
1322Layer::RequestDraw(const BRegion &reg, Layer *startFrom)
1323{
1324	STRACE(("Layer(%s)::RequestDraw()\n", Name()));
1325
1326	// do not redraw any child until you must
1327	int redraw = false;
1328	if (!startFrom)
1329		redraw = true;
1330
1331#ifndef NEW_CLIPPING
1332	if (HasClient() && IsTopLayer()) {
1333		// calculate the minimum region/rectangle to be updated with
1334		// a single message to the client.
1335		BRegion	updateReg(fFullVisible);
1336
1337		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1338			&& fFrameAction	== B_LAYER_ACTION_RESIZE)
1339		{
1340			// do nothing
1341		} else {
1342			updateReg.IntersectWith(&reg);
1343		}
1344		if (updateReg.CountRects() > 0) {
1345			fOwner->fCumulativeRegion.Include(&updateReg);
1346			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1347				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1348fOwner->cnt++;
1349if (fOwner->cnt != 1)
1350	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1351				fOwner->fCumulativeRegion.MakeEmpty();
1352				fOwner->fRequestSent = true;
1353				SendUpdateMsg(fOwner->fInUpdateRegion);
1354			}
1355		}
1356	}
1357
1358	if (fVisible.CountRects() > 0) {
1359		BRegion	updateReg(fVisible);
1360		// calculate the update region
1361		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fFrameAction == B_LAYER_ACTION_RESIZE) {
1362			// do nothing
1363		} else {
1364			updateReg.IntersectWith(&reg);
1365		}
1366
1367		if (updateReg.CountRects() > 0) {
1368			fDriver->ConstrainClippingRegion(&updateReg);
1369			Draw(updateReg.Frame());
1370			fDriver->ConstrainClippingRegion(NULL);
1371		}
1372	}
1373
1374	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1375		if (lay == startFrom)
1376			redraw = true;
1377
1378		if (redraw && !(lay->IsHidden())) {
1379			// no need to go deeper if not even the FullVisible region intersects
1380			// Update one.
1381			BRegion common(lay->fFullVisible);
1382			common.IntersectWith(&reg);
1383
1384			if (common.CountRects() > 0)
1385				lay->RequestDraw(reg, NULL);
1386		}
1387	}
1388#else
1389	if (HasClient() && IsTopLayer()) {
1390		// calculate the minimum region/rectangle to be updated with
1391		// a single message to the client.
1392		BRegion	updateReg(fFullVisible2);
1393
1394		updateReg.IntersectWith(&reg);
1395
1396		if (updateReg.CountRects() > 0) {
1397			fOwner->fCumulativeRegion.Include(&updateReg);
1398			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1399				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1400fOwner->cnt++;
1401if (fOwner->cnt != 1)
1402	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1403				fOwner->fCumulativeRegion.MakeEmpty();
1404				fOwner->fRequestSent = true;
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#ifndef NEW_CLIPPING
1578	msg.AddRect("_rect", ConvertFromTop(reg.Frame()));
1579#else
1580	BRect	rect(reg.Frame());
1581	ConvertFromScreen2(&rect);
1582	msg.AddRect("_rect", rect );
1583#endif
1584	msg.AddRect("debug_rect", reg.Frame());
1585//	msg.AddInt32("_token",fViewToken);
1586
1587	fOwner->Window()->SendMessageToClient(&msg);
1588}
1589
1590// AddToViewsWithInvalidCoords
1591void
1592Layer::AddToViewsWithInvalidCoords() const
1593{
1594	if (fServerWin) {
1595		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
1596		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
1597		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
1598		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
1599	}
1600}
1601
1602// SendViewCoordUpdateMsg
1603void
1604Layer::SendViewCoordUpdateMsg() const
1605{
1606	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
1607		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
1608		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
1609	}
1610}
1611
1612// SetViewColor
1613void
1614Layer::SetViewColor(const RGBColor& color)
1615{
1616	fViewColor = color;
1617}
1618
1619// SetBackgroundBitmap
1620void
1621Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
1622{
1623	// TODO: What about reference counting?
1624	// "Release" old fBackgroundBitmap and "Aquire" new one?
1625	fBackgroundBitmap = bitmap;
1626}
1627
1628// SetOverlayBitmap
1629void
1630Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
1631{
1632	// TODO: What about reference counting?
1633	// "Release" old fOverlayBitmap and "Aquire" new one?
1634	fOverlayBitmap = bitmap;
1635}
1636
1637#ifdef NEW_CLIPPING
1638
1639//! converts a point from local to parent's coordinate system
1640void
1641Layer::ConvertToParent2(BPoint* pt) const
1642{
1643	if (fParent) {
1644		BPoint origin = BoundsOrigin();
1645		pt->x -= origin.x;
1646		pt->y -= origin.y;
1647		pt->x += fFrame.left;
1648		pt->y += fFrame.top;
1649	}
1650}
1651
1652//! converts a rect from local to parent's coordinate system
1653void
1654Layer::ConvertToParent2(BRect* rect) const
1655{
1656	if (fParent) {
1657		BPoint origin = BoundsOrigin();
1658		rect->OffsetBy(-origin.x, -origin.y);
1659		rect->OffsetBy(fFrame.left, fFrame.top);
1660	}
1661}
1662
1663//! converts a region from local to parent's coordinate system
1664void
1665Layer::ConvertToParent2(BRegion* reg) const
1666{
1667	if (fParent) {
1668		BPoint origin = BoundsOrigin();
1669		reg->OffsetBy(-origin.x, -origin.y);
1670		reg->OffsetBy(fFrame.left, fFrame.top);
1671	}
1672}
1673
1674//! converts a point from parent's to local coordinate system
1675void
1676Layer::ConvertFromParent2(BPoint* pt) const
1677{
1678	if (fParent) {
1679		BPoint origin = BoundsOrigin();
1680		pt->x += origin.x;
1681		pt->y += origin.y;
1682		pt->x -= fFrame.left;
1683		pt->y -= fFrame.top;
1684	}
1685}
1686
1687//! converts a rect from parent's to local coordinate system
1688void
1689Layer::ConvertFromParent2(BRect* rect) const
1690{
1691	if (fParent) {
1692		BPoint origin = BoundsOrigin();
1693		rect->OffsetBy(origin.x, origin.y);
1694		rect->OffsetBy(-fFrame.left, -fFrame.top);
1695	}
1696}
1697
1698//! converts a region from parent's to local coordinate system
1699void
1700Layer::ConvertFromParent2(BRegion* reg) const
1701{
1702	if (fParent) {
1703		BPoint origin = BoundsOrigin();
1704		reg->OffsetBy(origin.x, origin.y);
1705		reg->OffsetBy(-fFrame.left, -fFrame.top);
1706	}
1707}
1708
1709//! converts a point from local to screen coordinate system
1710void
1711Layer::ConvertToScreen2(BPoint* pt) const
1712{
1713	if (GetRootLayer())
1714		if (fParent) {
1715			BPoint origin = BoundsOrigin();
1716			pt->x -= origin.x;
1717			pt->y -= origin.y;
1718			pt->x += fFrame.left;
1719			pt->y += fFrame.top;
1720
1721			fParent->ConvertToScreen2(pt);
1722		}
1723}
1724
1725//! converts a rect from local to screen coordinate system
1726void
1727Layer::ConvertToScreen2(BRect* rect) const
1728{
1729	if (GetRootLayer())
1730		if (fParent) {
1731			BPoint origin = BoundsOrigin();
1732			rect->OffsetBy(-origin.x, -origin.y);
1733			rect->OffsetBy(fFrame.left, fFrame.top);
1734
1735			fParent->ConvertToScreen2(rect);
1736		}
1737}
1738
1739//! converts a region from local to screen coordinate system
1740void
1741Layer::ConvertToScreen2(BRegion* reg) const
1742{
1743	if (GetRootLayer())
1744		if (fParent) {
1745			BPoint origin = BoundsOrigin();
1746			reg->OffsetBy(-origin.x, -origin.y);
1747			reg->OffsetBy(fFrame.left, fFrame.top);
1748
1749			fParent->ConvertToScreen2(reg);
1750		}
1751}
1752
1753//! converts a point from screen to local coordinate system
1754void
1755Layer::ConvertFromScreen2(BPoint* pt) const
1756{
1757	if (GetRootLayer())
1758		if (fParent) {
1759			BPoint origin = BoundsOrigin();
1760			pt->x += origin.x;
1761			pt->y += origin.y;
1762			pt->x -= fFrame.left;
1763			pt->y -= fFrame.top;
1764
1765			fParent->ConvertToScreen2(pt);
1766		}
1767}
1768
1769//! converts a rect from screen to local coordinate system
1770void
1771Layer::ConvertFromScreen2(BRect* rect) const
1772{
1773	if (GetRootLayer())
1774		if (fParent) {
1775			BPoint origin = BoundsOrigin();
1776			rect->OffsetBy(origin.x, origin.y);
1777			rect->OffsetBy(-fFrame.left, -fFrame.top);
1778
1779			fParent->ConvertFromScreen2(rect);
1780		}
1781}
1782
1783//! converts a region from screen to local coordinate system
1784void
1785Layer::ConvertFromScreen2(BRegion* reg) const
1786{
1787	if (GetRootLayer())
1788		if (fParent) {
1789			BPoint origin = BoundsOrigin();
1790			reg->OffsetBy(origin.x, origin.y);
1791			reg->OffsetBy(-fFrame.left, -fFrame.top);
1792
1793			fParent->ConvertFromScreen2(reg);
1794		}
1795}
1796
1797
1798void
1799Layer::do_Hide()
1800{
1801	fHidden = true;
1802
1803	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1804		// save fullVisible so we know what to invalidate
1805		BRegion invalid(fFullVisible2);
1806
1807		clear_visible_regions();
1808
1809		if (invalid.Frame().IsValid())
1810			fParent->do_Invalidate(invalid, this);
1811	}
1812}
1813
1814void
1815Layer::do_Show()
1816{
1817	fHidden = false;
1818
1819	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1820		BRegion invalid;
1821
1822		get_user_regions(invalid);
1823
1824		if (invalid.CountRects() > 0)
1825			fParent->do_Invalidate(invalid, this);
1826	}
1827}
1828
1829void
1830Layer::do_Invalidate(const BRegion &invalid, const Layer *startFrom)
1831{
1832	BRegion		localVisible(fFullVisible2);
1833	localVisible.IntersectWith(&invalid);
1834	rebuild_visible_regions(invalid, localVisible,
1835		startFrom? startFrom: BottomChild());
1836
1837	// add localVisible to our RootLayer's redraw region.
1838	GetRootLayer()->fRedrawReg.Include(&localVisible);
1839// TODO: ---
1840	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1841//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1842}
1843
1844void
1845Layer::do_Redraw(const BRegion &invalid, const Layer *startFrom)
1846{
1847	BRegion		localVisible(fFullVisible2);
1848	localVisible.IntersectWith(&invalid);
1849
1850	// add localVisible to our RootLayer's redraw region.
1851	GetRootLayer()->fRedrawReg.Include(&localVisible);
1852// TODO: ---
1853	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
1854//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
1855}
1856
1857inline void
1858Layer::resize_layer_frame_by(float x, float y)
1859{
1860	uint16		rm = fResizeMode & 0x0000FFFF;
1861	BRect		newFrame = fFrame;
1862
1863	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
1864		newFrame.left += 0.0f;
1865	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
1866		newFrame.left += x;
1867	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
1868		newFrame.left += x/2;
1869
1870	if ((rm & 0x000FU) == _VIEW_LEFT_)
1871		newFrame.right += 0.0f;
1872	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
1873		newFrame.right += x;
1874	else if ((rm & 0x000FU) == _VIEW_CENTER_)
1875		newFrame.right += x/2;
1876
1877	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
1878		newFrame.top += 0.0f;
1879	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
1880		newFrame.top += y;
1881	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
1882		newFrame.top += y/2;
1883
1884	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
1885		newFrame.bottom += 0.0f;
1886	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
1887		newFrame.bottom += y;
1888	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
1889		newFrame.bottom += y/2;
1890
1891	if (newFrame != fFrame) {
1892		float		dx, dy;
1893
1894		dx	= newFrame.Width() - fFrame.Width();
1895		dy	= newFrame.Height() - fFrame.Height();
1896
1897		fFrame	= newFrame;
1898
1899		if (dx != 0.0f || dy != 0.0f) {
1900			// call hook function
1901			ResizedByHook(dx, dy, true); // automatic
1902
1903			for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
1904				lay->resize_layer_frame_by(dx, dy);
1905		}
1906		else
1907			MovedByHook(dx, dy);
1908	}
1909}
1910
1911inline void
1912Layer::rezize_layer_redraw_more(BRegion &reg, float dx, float dy)
1913{
1914	if (dx == 0 && dy == 0)
1915		return;
1916
1917	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
1918		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1919
1920		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1921			// NOTE: this is not exactly corect, but it works :-)
1922			// Normaly we shoud've used the lay's old, required region - the one returned
1923			// from get_user_region() with the old frame, and the current one. lay->Bounds()
1924			// works for the moment so we leave it like this.
1925
1926			// calculate the old bounds.
1927			BRect	oldBounds(lay->Bounds());
1928			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
1929				oldBounds.right -=dx;
1930			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
1931				oldBounds.bottom -=dy;
1932
1933			// compute the region that became visible because we got bigger OR smaller.
1934			BRegion	regZ(lay->Bounds());
1935			regZ.Include(oldBounds);
1936			regZ.Exclude(oldBounds&lay->Bounds());
1937
1938			lay->ConvertToScreen2(&regZ);
1939
1940			// intersect that with this'(not lay's) fullVisible region
1941			regZ.IntersectWith(&fFullVisible2);
1942			reg.Include(&regZ);
1943
1944			lay->rezize_layer_redraw_more(reg,
1945				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1946				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1947
1948			// above, OR this:
1949			// reg.Include(&lay->fFullVisible2);
1950		}
1951		else
1952		if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
1953			((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) ||
1954			((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
1955			((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
1956		{
1957			reg.Include(&lay->fFullVisible2);
1958		}
1959	}
1960}
1961
1962inline void
1963Layer::resize_layer_full_update_on_resize(BRegion &reg, float dx, float dy)
1964{
1965	if (dx == 0 && dy == 0)
1966		return;
1967
1968	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
1969		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1970
1971		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1972			if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0)
1973				reg.Include(&lay->fVisible2);
1974
1975			lay->resize_layer_full_update_on_resize(reg,
1976				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1977				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1978		}
1979	}
1980}
1981
1982void
1983Layer::do_ResizeBy(float dx, float dy)
1984{
1985	fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
1986
1987	// resize children using their resize_mask.
1988	for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
1989			lay->resize_layer_frame_by(dx, dy);
1990
1991	// call hook function
1992	if (dx != 0.0f || dy != 0.0f)
1993		ResizedByHook(dx, dy, false); // manual
1994
1995	if (!IsHidden() && GetRootLayer()) {
1996		BRegion oldFullVisible(fFullVisible2);
1997		// this is required to invalidate the old border
1998		BRegion oldVisible(fVisible2);
1999
2000		// in case they moved, bottom, right and center aligned layers must be redrawn
2001		BRegion redrawMore;
2002		rezize_layer_redraw_more(redrawMore, dx, dy);
2003
2004		// we'll invalidate the old area and the new, maxmial one.
2005		BRegion invalid;
2006		get_user_regions(invalid);
2007		invalid.Include(&fFullVisible2);
2008
2009		clear_visible_regions();
2010
2011		fParent->do_RebuildVisibleRegions(invalid, this);
2012
2013		// done rebuilding regions, now redraw regions that became visible
2014
2015		// what's invalid, are the differences between to old and the new fullVisible region
2016		// 1) in case we grow.
2017		BRegion		redrawReg(fFullVisible2);
2018		redrawReg.Exclude(&oldFullVisible);
2019		// 2) in case we shrink
2020		BRegion		redrawReg2(oldFullVisible);
2021		redrawReg2.Exclude(&fFullVisible2);
2022		// 3) combine.
2023		redrawReg.Include(&redrawReg2);
2024
2025		// for center, right and bottom alligned layers, redraw their old positions
2026		redrawReg.Include(&redrawMore);
2027
2028		// layers that had their frame modified must be entirely redrawn.
2029		rezize_layer_redraw_more(redrawReg, dx, dy);
2030
2031		// add redrawReg to our RootLayer's redraw region.
2032		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2033		// include layer's visible region in case we want a full update on resize
2034		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) {
2035			resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg, dx, dy);
2036
2037			GetRootLayer()->fRedrawReg.Include(&fVisible2);
2038			GetRootLayer()->fRedrawReg.Include(&oldVisible);
2039		}
2040		// clear canvas and set invalid regions for affected WinBorders
2041// TODO: ---
2042	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
2043//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2044	}
2045}
2046
2047void Layer::do_MoveBy(float dx, float dy)
2048{
2049	if (dx == 0.0f && dy == 0.0f)
2050		return;
2051
2052//	fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
2053	fFrame.OffsetBy(dx, dy);
2054
2055	// call hook function
2056	MovedByHook(dx, dy);
2057
2058	if (!IsHidden() && GetRootLayer()) {
2059		BRegion oldFullVisible(fFullVisible2);
2060
2061		// we'll invalidate the old position and the new, maxmial one.
2062		BRegion invalid;
2063		get_user_regions(invalid);
2064		invalid.Include(&fFullVisible2);
2065
2066		clear_visible_regions();
2067
2068		fParent->do_RebuildVisibleRegions(invalid, this);
2069
2070		// done rebuilding regions, now copy common parts and redraw regions that became visible
2071
2072		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
2073		BRegion		redrawReg(fFullVisible2);
2074		redrawReg.Include(&oldFullVisible);
2075
2076		// offset to layer's new location so that we can calculate the common region.
2077		oldFullVisible.OffsetBy(dx, dy);
2078
2079		// finally we have the region that needs to be redrawn.
2080		redrawReg.Exclude(&oldFullVisible);
2081
2082		// by intersecting the old fullVisible offseted to layer's new location, with the current
2083		// fullVisible, we'll have the common region which can be copied using HW acceleration.
2084		oldFullVisible.IntersectWith(&fFullVisible2);
2085
2086		// offset back and instruct the HW to do the actual copying.
2087		oldFullVisible.OffsetBy(-dx, -dy);
2088// TODO: uncomment!!!
2089//		GetRootLayer()->CopyRegion(&oldFullVisible, dx, dy);
2090
2091		// add redrawReg to our RootLayer's redraw region.
2092		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2093// TODO: ---
2094	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
2095//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2096	}
2097}
2098
2099void
2100Layer::do_ScrollBy(float dx, float dy)
2101{
2102	fLayerData->OffsetOrigin(BPoint(dx, dy));
2103//	fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy);
2104
2105	if (!IsHidden() && GetRootLayer()) {
2106		// set the region to be invalidated.
2107		BRegion		invalid(fFullVisible2);
2108
2109		clear_visible_regions();
2110
2111		rebuild_visible_regions(invalid, invalid, BottomChild());
2112
2113		// for the moment we say that the whole surface needs to be redraw.
2114		BRegion		redrawReg(fFullVisible2);
2115
2116		// offset old region so that we can start comparing.
2117		invalid.OffsetBy(dx, dy);
2118
2119		// compute the common region. we'll use HW acc to copy this to the new location.
2120		invalid.IntersectWith(&fFullVisible2);
2121// TODO: uncomment!!!
2122//		GetRootLayer()->CopyRegion(&invalid, -dx, -dy);
2123
2124		// common region goes back to its original location. then, by excluding
2125		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
2126		invalid.OffsetBy(-dx, -dy);
2127		redrawReg.Exclude(&invalid);
2128
2129		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2130// TODO: ---
2131	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, BottomChild());
2132//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2133	}
2134
2135	if (dx != 0.0f || dy != 0.0f)
2136		ScrolledByHook(dx, dy);
2137}
2138
2139void
2140Layer::get_user_regions(BRegion &reg)
2141{
2142	// 1) set to frame in screen coords
2143	BRect screenFrame(Bounds());
2144	ConvertToScreen2(&screenFrame);
2145	reg.Set(screenFrame);
2146
2147	// 2) intersect with screen region
2148	BRegion screenReg(GetRootLayer()->Bounds());
2149	reg.IntersectWith(&screenReg);
2150
2151
2152	// 3) impose user constrained regions
2153	LayerData *stackData = fLayerData;
2154	while (stackData) {
2155		if (stackData->ClippingRegion()) {
2156			// transform in screen coords
2157			BRegion screenReg(*stackData->ClippingRegion());
2158			ConvertToScreen2(&screenReg);
2159			reg.IntersectWith(&screenReg);
2160		}
2161		stackData = stackData->prevState;
2162	}
2163}
2164
2165void
2166Layer::do_RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom)
2167{
2168	BRegion		localVisible(fFullVisible2);
2169	localVisible.IntersectWith(&invalid);
2170	rebuild_visible_regions(invalid, localVisible, startFrom);
2171}
2172
2173void
2174Layer::rebuild_visible_regions(const BRegion &invalid,
2175								const BRegion &parentLocalVisible,
2176								const Layer *startFrom)
2177{
2178	// no point in continuing if this layer is hidden. starting from here, all
2179	// descendants have (and will have) invalid visible regions.
2180	if (fHidden)
2181		return;
2182
2183	// no need to go deeper if the parent doesn't have a visible region anymore
2184	// and our fullVisible region is also empty.
2185	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0))
2186		return;
2187
2188	bool fullRebuild = false;
2189
2190	// intersect maximum wanted region with the invalid region
2191	BRegion common;
2192	get_user_regions(common);
2193	common.IntersectWith(&invalid);
2194
2195	// if the resulted region is not valid, this layer is not in the catchment area
2196	// of the region being invalidated
2197	if (!common.CountRects() > 0)
2198		return;
2199
2200	// now intersect with parent's visible part of the region that was/is invalidated
2201	common.IntersectWith(&parentLocalVisible);
2202
2203	// exclude the invalid region
2204	fFullVisible2.Exclude(&invalid);
2205	fVisible2.Exclude(&invalid);
2206
2207	// put in what's really visible
2208	fFullVisible2.Include(&common);
2209
2210	// this is to allow a layer to hide some parts of itself so children
2211	// won't take them.
2212	BRegion unalteredVisible(common);
2213	bool altered = alter_visible_for_children(common);
2214
2215	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
2216		if (lay == startFrom)
2217			fullRebuild = true;
2218
2219		if (fullRebuild)
2220			lay->rebuild_visible_regions(invalid, common, lay->BottomChild());
2221
2222		// to let children know much they can take from parent's visible region
2223		common.Exclude(&lay->fFullVisible2);
2224		// we've hidden some parts of our visible region from our children,
2225		// and we must be in sysnc with this region too...
2226		if (altered)
2227			unalteredVisible.Exclude(&lay->fFullVisible2);
2228	}
2229
2230	// the visible region of this layer is what left after all its children took
2231	// what they could.
2232	if (altered)
2233		fVisible2.Include(&unalteredVisible);
2234	else
2235		fVisible2.Include(&common);
2236}
2237
2238bool
2239Layer::alter_visible_for_children(BRegion &reg)
2240{
2241	// Empty Hook function
2242	return false;
2243}
2244
2245void
2246Layer::clear_visible_regions()
2247{
2248	// OPT: maybe we should uncomment these lines for performance
2249	//if (fFullVisible2.CountRects() <= 0)
2250	//	return;
2251
2252	fVisible2.MakeEmpty();
2253	fFullVisible2.MakeEmpty();
2254	for (Layer *child = BottomChild(); child; child = UpperSibling())
2255		child->clear_visible_regions();
2256}
2257
2258#endif
2259
2260