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