Layer.cpp revision be2eea8cf96eb45da805d3a826b58d0ed734b34b
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#ifndef NEW_CLIPPING
1121	pt -= BoundsOrigin();
1122	pt += fFrame.LeftTop();
1123	return pt;
1124#else
1125	ConvertToParent2(&pt);
1126	return pt;
1127#endif
1128}
1129
1130//! Converts the passed rectangle to parent coordinates
1131BRect
1132Layer::ConvertToParent(BRect rect)
1133{
1134#ifndef NEW_CLIPPING
1135//	rect.OffsetBy(fFrame.LeftTop());
1136//	return rect;
1137	rect.OffsetBy(-BoundsOrigin().x, -BoundsOrigin().y);
1138	rect.OffsetBy(fFrame.LeftTop());
1139	return rect;
1140#else
1141	ConvertToParent2(&rect);
1142	return rect;
1143#endif
1144}
1145
1146//! Converts the passed region to parent coordinates
1147BRegion
1148Layer::ConvertToParent(BRegion* reg)
1149{
1150#ifndef NEW_CLIPPING
1151	// TODO: wouldn't it be more efficient to use the copy
1152	// constructor for BRegion and then call OffsetBy()?
1153	BRegion newreg;
1154	for (int32 i = 0; i < reg->CountRects(); i++)
1155		newreg.Include(ConvertToParent(reg->RectAt(i)));
1156	return newreg;
1157#else
1158	BRegion newReg(*reg);
1159	ConvertToParent2(&newReg);
1160	return newReg;
1161#endif
1162}
1163
1164//! Converts the passed point from parent coordinates
1165BPoint
1166Layer::ConvertFromParent(BPoint pt)
1167{
1168#ifndef NEW_CLIPPING
1169//	return pt - fFrame.LeftTop();
1170	pt -= fFrame.LeftTop();
1171	pt += BoundsOrigin();
1172	return pt;
1173#else
1174	ConvertFromParent2(&pt);
1175	return pt;
1176#endif
1177}
1178
1179//! Converts the passed rectangle from parent coordinates
1180BRect
1181Layer::ConvertFromParent(BRect rect)
1182{
1183#ifndef NEW_CLIPPING
1184//	rect.OffsetBy(-fFrame.left, -fFrame.top);
1185//	return rect;
1186	rect.OffsetBy(-fFrame.left, -fFrame.top);
1187	rect.OffsetBy(BoundsOrigin());
1188	return rect;
1189#else
1190	ConvertFromParent2(&rect);
1191	return rect;
1192#endif
1193}
1194
1195//! Converts the passed region from parent coordinates
1196BRegion
1197Layer::ConvertFromParent(BRegion *reg)
1198{
1199#ifndef NEW_CLIPPING
1200	BRegion newreg;
1201	for(int32 i=0; i<reg->CountRects();i++)
1202		newreg.Include(ConvertFromParent(reg->RectAt(i)));
1203	return newreg;
1204#else
1205	BRegion newReg(*reg);
1206	ConvertFromParent2(&newReg);
1207	return newReg;
1208#endif
1209}
1210
1211// ConvertToTop
1212BPoint
1213Layer::ConvertToTop(BPoint pt)
1214{
1215#ifndef NEW_CLIPPING
1216	if (fParent) {
1217//		return (fParent->ConvertToTop(pt + fFrame.LeftTop()));
1218		pt = ConvertToParent(pt);
1219		return fParent->ConvertToTop(pt);
1220	} else
1221		return pt;
1222#else
1223	ConvertToScreen2(&pt);
1224	return pt;
1225#endif
1226}
1227
1228//! Converts the passed rectangle to screen coordinates
1229BRect
1230Layer::ConvertToTop(BRect rect)
1231{
1232#ifndef NEW_CLIPPING
1233	if (fParent) {
1234//		return fParent->ConvertToTop(rect.OffsetByCopy(fFrame.LeftTop()));
1235		rect = ConvertToParent(rect);
1236		return fParent->ConvertToTop(rect);
1237	} else
1238		return rect;
1239#else
1240	ConvertToScreen2(&rect);
1241	return rect;
1242#endif
1243}
1244
1245//! Converts the passed region to screen coordinates
1246BRegion
1247Layer::ConvertToTop(BRegion *reg)
1248{
1249#ifndef NEW_CLIPPING
1250	BRegion newreg;
1251	for (int32 i = 0; i < reg->CountRects();i++)
1252		newreg.Include(ConvertToTop(reg->RectAt(i)));
1253	return newreg;
1254#else
1255	BRegion newReg(*reg);
1256	ConvertToScreen2(&newReg);
1257	return newReg;
1258#endif
1259}
1260
1261// ConvertFromTop
1262BPoint
1263Layer::ConvertFromTop(BPoint pt)
1264{
1265#ifndef NEW_CLIPPING
1266	if (fParent) {
1267//		return fParent->ConvertFromTop(pt-fFrame.LeftTop());
1268		pt = ConvertFromParent(pt);
1269		return fParent->ConvertFromTop(pt);
1270	} else
1271		return pt;
1272#else
1273	ConvertFromScreen2(&pt);
1274	return pt;
1275#endif
1276}
1277
1278//! Converts the passed rectangle from screen coordinates
1279BRect
1280Layer::ConvertFromTop(BRect rect)
1281{
1282#ifndef NEW_CLIPPING
1283	if (fParent) {
1284//		return fParent->ConvertFromTop(rect.OffsetByCopy(-fFrame.LeftTop().x,
1285//														 -fFrame.LeftTop().y));
1286		rect = ConvertFromParent(rect);
1287		return fParent->ConvertFromTop(rect);
1288	} else
1289		return rect;
1290#else
1291	ConvertFromScreen2(&rect);
1292	return rect;
1293#endif
1294}
1295
1296//! Converts the passed region from screen coordinates
1297BRegion
1298Layer::ConvertFromTop(BRegion *reg)
1299{
1300#ifndef NEW_CLIPPING
1301	BRegion newreg;
1302
1303	for (int32 i = 0; i < reg->CountRects(); i++)
1304		newreg.Include(ConvertFromTop(reg->RectAt(i)));
1305
1306	return newreg;
1307#else
1308	BRegion newReg(*reg);
1309	ConvertFromScreen2(&newReg);
1310	return newReg;
1311#endif
1312}
1313
1314//! Recursively deletes all children of the calling layer
1315void
1316Layer::PruneTree(void)
1317{
1318
1319	Layer* lay;
1320	Layer* nextlay;
1321
1322	lay = fTopChild;
1323	fTopChild = NULL;
1324
1325	while (lay != NULL) {
1326		if (lay->fTopChild != NULL)
1327			lay->PruneTree();
1328
1329		nextlay = lay->fLowerSibling;
1330		lay->fLowerSibling = NULL;
1331
1332		delete lay;
1333		lay = nextlay;
1334	}
1335	// Man, this thing is short. Elegant, ain't it? :P
1336}
1337
1338//! Prints information about the layer's current state
1339void
1340Layer::PrintToStream()
1341{
1342	printf("\n *** Layer %s:\n", Name());
1343	printf("\t Parent: %s", fParent ? fParent->Name() : "<no parent>");
1344
1345	printf("\t us: %s\t ls: %s\n",
1346		fUpperSibling ? fUpperSibling->Name() : "<none>",
1347		fLowerSibling ? fLowerSibling->Name() : "<none>");
1348
1349	printf("\t topChild: %s\t bottomChild: %s\n",
1350		fTopChild ? fTopChild->Name() : "<none>",
1351		fBottomChild ? fBottomChild->Name() : "<none>");
1352
1353	printf("Frame: (%f, %f, %f, %f)\n", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
1354	printf("LocalOrigin: (%f, %f)\n", BoundsOrigin().x, BoundsOrigin().y);
1355	printf("Token: %ld\n", fViewToken);
1356	printf("Hidden - direct: %s ", fHidden?"true":"false");
1357	printf("Hidden - indirect: %s\n", IsHidden()?"true":"false");
1358	printf("ResizingMode: %lx ", fResizeMode);
1359	printf("Flags: %lx\n", fFlags);
1360
1361	if (fLayerData)
1362		fLayerData->PrintToStream();
1363	else
1364		printf(" NO LayerData valid pointer\n");
1365}
1366
1367//! Prints pointer info kept by the current layer
1368void
1369Layer::PrintNode()
1370{
1371	printf("-----------\nLayer %s\n", Name());
1372	if (fParent)
1373		printf("Parent: %s (%p)\n", fParent->Name(), fParent);
1374	else
1375		printf("Parent: NULL\n");
1376
1377	if (fUpperSibling)
1378		printf("Upper sibling: %s (%p)\n", fUpperSibling->Name(), fUpperSibling);
1379	else
1380		printf("Upper sibling: NULL\n");
1381
1382	if (fLowerSibling)
1383		printf("Lower sibling: %s (%p)\n", fLowerSibling->Name(), fLowerSibling);
1384	else
1385		printf("Lower sibling: NULL\n");
1386
1387	if (fTopChild)
1388		printf("Top child: %s (%p)\n", fTopChild->Name(), fTopChild);
1389	else
1390		printf("Top child: NULL\n");
1391
1392	if (fBottomChild)
1393		printf("Bottom child: %s (%p)\n", fBottomChild->Name(), fBottomChild);
1394	else
1395		printf("Bottom child: NULL\n");
1396#ifndef NEW_CLIPPING
1397	printf("Visible Areas: "); fVisible.PrintToStream();
1398#endif
1399}
1400
1401//! Prints the tree hierarchy from the current layer down
1402void
1403Layer::PrintTree()
1404{
1405	printf("\n Tree structure:\n");
1406	printf("\t%s\t%s\n", Name(), IsHidden()? "Hidden": "NOT hidden");
1407	for(Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling())
1408		printf("\t%s\t%s\n", lay->Name(), lay->IsHidden()? "Hidden": "NOT hidden");
1409}
1410
1411// RequestDraw
1412void
1413Layer::RequestDraw(const BRegion &reg, Layer *startFrom)
1414{
1415	STRACE(("Layer(%s)::RequestDraw()\n", Name()));
1416
1417	// do not redraw any child until you must
1418	int redraw = false;
1419	if (!startFrom)
1420		redraw = true;
1421
1422#ifndef NEW_CLIPPING
1423	if (HasClient() && IsTopLayer()) {
1424		// calculate the minimum region/rectangle to be updated with
1425		// a single message to the client.
1426		BRegion	updateReg(fFullVisible);
1427
1428		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1429			&& fFrameAction	== B_LAYER_ACTION_RESIZE)
1430		{
1431			// do nothing
1432		} else {
1433			updateReg.IntersectWith(&reg);
1434		}
1435		if (updateReg.CountRects() > 0) {
1436			fOwner->fCumulativeRegion.Include(&updateReg);
1437			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1438				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1439fOwner->cnt++;
1440if (fOwner->cnt != 1)
1441	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1442				fOwner->fCumulativeRegion.MakeEmpty();
1443				fOwner->fRequestSent = true;
1444				SendUpdateMsg(fOwner->fInUpdateRegion);
1445			}
1446		}
1447	}
1448
1449	if (fVisible.CountRects() > 0) {
1450		BRegion	updateReg(fVisible);
1451		// calculate the update region
1452		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fFrameAction == B_LAYER_ACTION_RESIZE) {
1453			// do nothing
1454		} else {
1455			updateReg.IntersectWith(&reg);
1456		}
1457
1458		if (updateReg.CountRects() > 0) {
1459			fDriver->ConstrainClippingRegion(&updateReg);
1460			Draw(updateReg.Frame());
1461			fDriver->ConstrainClippingRegion(NULL);
1462		}
1463	}
1464
1465	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1466		if (lay == startFrom)
1467			redraw = true;
1468
1469		if (redraw && !(lay->IsHidden())) {
1470			// no need to go deeper if not even the FullVisible region intersects
1471			// Update one.
1472			BRegion common(lay->fFullVisible);
1473			common.IntersectWith(&reg);
1474
1475			if (common.CountRects() > 0)
1476				lay->RequestDraw(reg, NULL);
1477		}
1478	}
1479#else
1480	if (HasClient() && IsTopLayer()) {
1481		// calculate the minimum region/rectangle to be updated with
1482		// a single message to the client.
1483		BRegion	updateReg(fFullVisible2);
1484
1485		updateReg.IntersectWith(&reg);
1486
1487		if (updateReg.CountRects() > 0) {
1488			fOwner->fCumulativeRegion.Include(&updateReg);
1489			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1490				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1491fOwner->cnt++;
1492if (fOwner->cnt != 1)
1493	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1494				fOwner->fCumulativeRegion.MakeEmpty();
1495				fOwner->fRequestSent = true;
1496				SendUpdateMsg(fOwner->fInUpdateRegion);
1497			}
1498		}
1499	}
1500
1501	if (fVisible2.CountRects() > 0) {
1502		BRegion	updateReg(fVisible2);
1503			updateReg.IntersectWith(&reg);
1504
1505		if (updateReg.CountRects() > 0) {
1506			fDriver->ConstrainClippingRegion(&updateReg);
1507			Draw(updateReg.Frame());
1508			fDriver->ConstrainClippingRegion(NULL);
1509		}
1510	}
1511
1512	for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) {
1513		if (lay == startFrom)
1514			redraw = true;
1515
1516		if (redraw && !(lay->IsHidden())) {
1517			// no need to go deeper if not even the FullVisible region intersects
1518			// Update one.
1519			BRegion common(lay->fFullVisible2);
1520			common.IntersectWith(&reg);
1521
1522			if (common.CountRects() > 0)
1523				lay->RequestDraw(reg, NULL);
1524		}
1525	}
1526#endif
1527}
1528
1529#ifndef NEW_CLIPPING
1530
1531// move_layer
1532void
1533Layer::move_layer(float x, float y)
1534{
1535/*	if (fClassID == AS_WINBORDER_CLASS) {
1536		WinBorder	*wb = (WinBorder*)this;
1537		wb->fCumulativeRegion.OffsetBy(x, y);
1538		wb->fInUpdateRegion.OffsetBy(x, y);
1539		wb->fSavedForUpdateRegion.OffsetBy(x, y);
1540	}*/
1541
1542	fFrameAction = B_LAYER_ACTION_MOVE;
1543
1544	BPoint pt(x, y);
1545	BRect rect(fFull.Frame().OffsetByCopy(pt));
1546
1547if (!fParent) {
1548printf("no parent in Layer::move_layer() (%s)\n", Name());
1549fFrameAction = B_LAYER_ACTION_NONE;
1550return;
1551}
1552
1553	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_MOVE, pt);
1554
1555	fDriver->CopyRegionList(&fRootLayer->fCopyRegList,
1556							&fRootLayer->fCopyList,
1557							fRootLayer->fCopyRegList.CountItems(),
1558							&fFullVisible);
1559
1560	fParent->Redraw(fRootLayer->fRedrawReg, this);
1561
1562	// redraw workspaces layer
1563	if (dynamic_cast<WinBorder*>(this) != NULL && fRootLayer->WorkspacesLayer() != NULL) {
1564		fRootLayer->GoRedraw(fRootLayer->WorkspacesLayer(), fRootLayer->WorkspacesLayer()->fVisible);
1565	}
1566
1567	SendViewCoordUpdateMsg();
1568
1569	EmptyGlobals();
1570
1571	fFrameAction = B_LAYER_ACTION_NONE;
1572}
1573
1574// resize_layer
1575void
1576Layer::resize_layer(float x, float y)
1577{
1578	fFrameAction = B_LAYER_ACTION_RESIZE;
1579
1580	BPoint pt(x,y);
1581
1582	BRect rect(fFull.Frame());
1583	rect.right += x;
1584	rect.bottom += y;
1585
1586if (!fParent) {
1587printf("no parent in Layer::resize_layer() (%s)\n", Name());
1588fFrameAction = B_LAYER_ACTION_NONE;
1589return;
1590}
1591
1592	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_RESIZE, pt);
1593
1594	fDriver->CopyRegionList(&fRootLayer->fCopyRegList, &fRootLayer->fCopyList, fRootLayer->fCopyRegList.CountItems(), &fFullVisible);
1595
1596	fParent->Redraw(fRootLayer->fRedrawReg, this);
1597
1598	// redraw workspaces layer
1599	if (dynamic_cast<WinBorder*>(this) != NULL && fRootLayer->WorkspacesLayer() != NULL) {
1600		fRootLayer->GoRedraw(fRootLayer->WorkspacesLayer(), fRootLayer->WorkspacesLayer()->fVisible);
1601	}
1602
1603	SendViewCoordUpdateMsg();
1604
1605	EmptyGlobals();
1606
1607	fFrameAction = B_LAYER_ACTION_NONE;
1608}
1609
1610// FullInvalidate
1611void
1612Layer::FullInvalidate(const BRect &rect)
1613{
1614	FullInvalidate(BRegion(rect));
1615}
1616
1617// FullInvalidate
1618void
1619Layer::FullInvalidate(const BRegion& region)
1620{
1621	STRACE(("Layer(%s)::FullInvalidate():\n", Name()));
1622
1623#ifdef DEBUG_LAYER
1624	region.PrintToStream();
1625	printf("\n");
1626#endif
1627
1628	BPoint pt(0,0);
1629	StartRebuildRegions(region, NULL,/* B_LAYER_INVALIDATE, pt); */B_LAYER_NONE, pt);
1630
1631	Redraw(fRootLayer->fRedrawReg);
1632
1633	EmptyGlobals();
1634}
1635
1636// Invalidate
1637void
1638Layer::Invalidate(const BRegion& region)
1639{
1640	STRACE(("Layer(%s)::Invalidate():\n", Name()));
1641#ifdef DEBUG_LAYER
1642	region.PrintToStream();
1643	printf("\n");
1644#endif
1645
1646	fRootLayer->fRedrawReg	= region;
1647
1648	Redraw(fRootLayer->fRedrawReg);
1649
1650	EmptyGlobals();
1651}
1652
1653#endif // 5 methods
1654
1655
1656/*!
1657	\brief Returns the layer's ServerWindow
1658
1659	If the layer's ServerWindow has not been assigned, it attempts to find
1660	the owning ServerWindow in the tree.
1661*/
1662ServerWindow*
1663Layer::SearchForServerWindow()
1664{
1665	if (!fServerWin)
1666		fServerWin=fParent->SearchForServerWindow();
1667
1668	return fServerWin;
1669}
1670
1671//! Sends an _UPDATE_ message to the client BWindow
1672void
1673Layer::SendUpdateMsg(BRegion& reg)
1674{
1675	BMessage msg;
1676	msg.what = _UPDATE_;
1677#ifndef NEW_CLIPPING
1678	msg.AddRect("_rect", ConvertFromTop(reg.Frame()));
1679#else
1680	BRect	rect(reg.Frame());
1681	ConvertFromScreen2(&rect);
1682	msg.AddRect("_rect", rect );
1683#endif
1684	msg.AddRect("debug_rect", reg.Frame());
1685//	msg.AddInt32("_token",fViewToken);
1686
1687	fOwner->Window()->SendMessageToClient(&msg);
1688}
1689
1690// AddToViewsWithInvalidCoords
1691void
1692Layer::AddToViewsWithInvalidCoords() const
1693{
1694	if (fServerWin) {
1695		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
1696		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
1697		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
1698		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
1699	}
1700}
1701
1702// SendViewCoordUpdateMsg
1703void
1704Layer::SendViewCoordUpdateMsg() const
1705{
1706	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
1707		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
1708		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
1709	}
1710}
1711
1712// SetViewColor
1713void
1714Layer::SetViewColor(const RGBColor& color)
1715{
1716	fViewColor = color;
1717}
1718
1719// SetBackgroundBitmap
1720void
1721Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
1722{
1723	// TODO: What about reference counting?
1724	// "Release" old fBackgroundBitmap and "Aquire" new one?
1725	fBackgroundBitmap = bitmap;
1726}
1727
1728// SetOverlayBitmap
1729void
1730Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
1731{
1732	// TODO: What about reference counting?
1733	// "Release" old fOverlayBitmap and "Aquire" new one?
1734	fOverlayBitmap = bitmap;
1735}
1736
1737void
1738Layer::CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
1739
1740	BPrivate::PortLink msg(-1, -1);
1741	msg.StartMessage(AS_ROOTLAYER_LAYER_COPYBITS);
1742	msg.Attach<Layer*>(this);
1743	msg.Attach<BRect>(src);
1744	msg.Attach<BRect>(dst);
1745	msg.Attach<int32>(xOffset);
1746	msg.Attach<int32>(yOffset);
1747	GetRootLayer()->EnqueueMessage(msg);
1748}
1749
1750void
1751Layer::do_CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
1752	// NOTE: The correct behaviour is this:
1753	// * The region that is copied is the
1754	//   src rectangle, no matter if it fits
1755	//   into the dst rectangle. It is copied
1756	//   by the offset dst.LeftTop() - src.LeftTop()
1757	// * The dst rectangle is used for invalidation:
1758	//   Any area in the dst rectangle that could
1759	//   not be copied from src (because either the
1760	//   src rectangle was not big enough, or because there
1761	//   were parts cut off by the current layer clipping),
1762	//   are triggering BView::Draw() to be called
1763	//   and for these parts only.
1764
1765#ifndef NEW_CLIPPING
1766
1767	// the region that is going to be copied
1768	BRegion copyRegion(src);
1769	// apply the current clipping of the layer
1770
1771	copyRegion.IntersectWith(&fVisible);
1772
1773	// offset the region to the destination
1774	// and apply the current clipping there as well
1775	copyRegion.OffsetBy(xOffset, yOffset);
1776	copyRegion.IntersectWith(&fVisible);
1777
1778	// the region at the destination that needs invalidation
1779	GetRootLayer()->fRedrawReg.Set(dst);
1780	// exclude the region drawn by the copy operation
1781	GetRootLayer()->fRedrawReg.Exclude(&copyRegion);
1782	// apply the current clipping as well
1783	GetRootLayer()->fRedrawReg.IntersectWith(&fVisible);
1784
1785	// move the region back for the actual operation
1786	copyRegion.OffsetBy(-xOffset, -yOffset);
1787
1788	GetDisplayDriver()->CopyRegion(&copyRegion, xOffset, yOffset);
1789
1790	// trigger the redraw
1791	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
1792#else
1793	// the region that is going to be copied
1794	BRegion copyRegion(src);
1795	// apply the current clipping of the layer
1796
1797	copyRegion.IntersectWith(&fVisible2);
1798
1799	// offset the region to the destination
1800	// and apply the current clipping there as well
1801	copyRegion.OffsetBy(xOffset, yOffset);
1802	copyRegion.IntersectWith(&fVisible2);
1803
1804	// the region at the destination that needs invalidation
1805	GetRootLayer()->fRedrawReg.Set(dst);
1806	// exclude the region drawn by the copy operation
1807	GetRootLayer()->fRedrawReg.Exclude(&copyRegion);
1808	// apply the current clipping as well
1809	GetRootLayer()->fRedrawReg.IntersectWith(&fVisible2);
1810
1811	// move the region back for the actual operation
1812	copyRegion.OffsetBy(-xOffset, -yOffset);
1813
1814	GetDisplayDriver()->CopyRegion(&copyRegion, xOffset, yOffset);
1815
1816	// trigger the redraw
1817	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
1818#endif
1819
1820}
1821
1822#ifdef NEW_CLIPPING
1823
1824void
1825Layer::MovedByHook(float dx, float dy)
1826{
1827	if (Window() && Flags() & B_FRAME_EVENTS && !IsTopLayer()) {
1828		BMessage msg(B_VIEW_MOVED);
1829		msg.AddInt64("when", system_time());
1830		msg.AddPoint("where", Frame().LeftTop());
1831		Window()->SendMessageToClient(&msg, fViewToken, false);
1832	}
1833}
1834
1835void
1836Layer::ResizedByHook(float dx, float dy, bool automatic)
1837{
1838	if (Window() && Flags() & B_FRAME_EVENTS && !IsTopLayer()) {
1839		BMessage msg(B_VIEW_RESIZED);
1840		msg.AddInt64("when", system_time());
1841		msg.AddFloat("width", Frame().Width());
1842		msg.AddFloat("height", Frame().Height());
1843		msg.AddPoint("where", Frame().LeftTop());
1844		Window()->SendMessageToClient(&msg, fViewToken, false);
1845	}
1846}
1847
1848void
1849Layer::ScrolledByHook(float dx, float dy)
1850{
1851	// empty.
1852}
1853
1854
1855void
1856Layer::GetWantedRegion(BRegion& reg) const
1857{
1858	// this is the same as get_user_region.
1859	// because get_user_region modifies nothing.
1860	const_cast<Layer*>(this)->Layer::get_user_regions(reg);
1861}
1862
1863//! converts a point from local to parent's coordinate system
1864void
1865Layer::ConvertToParent2(BPoint* pt) const
1866{
1867	if (fParent) {
1868		BPoint origin = BoundsOrigin();
1869		pt->x -= origin.x;
1870		pt->y -= origin.y;
1871		pt->x += fFrame.left;
1872		pt->y += fFrame.top;
1873	}
1874}
1875
1876//! converts a rect from local to parent's coordinate system
1877void
1878Layer::ConvertToParent2(BRect* rect) const
1879{
1880	if (fParent) {
1881		BPoint origin = BoundsOrigin();
1882		rect->OffsetBy(-origin.x, -origin.y);
1883		rect->OffsetBy(fFrame.left, fFrame.top);
1884	}
1885}
1886
1887//! converts a region from local to parent's coordinate system
1888void
1889Layer::ConvertToParent2(BRegion* reg) const
1890{
1891	if (fParent) {
1892		BPoint origin = BoundsOrigin();
1893		reg->OffsetBy(-origin.x, -origin.y);
1894		reg->OffsetBy(fFrame.left, fFrame.top);
1895	}
1896}
1897
1898//! converts a point from parent's to local coordinate system
1899void
1900Layer::ConvertFromParent2(BPoint* pt) const
1901{
1902	if (fParent) {
1903		BPoint origin = BoundsOrigin();
1904		pt->x += origin.x;
1905		pt->y += origin.y;
1906		pt->x -= fFrame.left;
1907		pt->y -= fFrame.top;
1908	}
1909}
1910
1911//! converts a rect from parent's to local coordinate system
1912void
1913Layer::ConvertFromParent2(BRect* rect) const
1914{
1915	if (fParent) {
1916		BPoint origin = BoundsOrigin();
1917		rect->OffsetBy(origin.x, origin.y);
1918		rect->OffsetBy(-fFrame.left, -fFrame.top);
1919	}
1920}
1921
1922//! converts a region from parent's to local coordinate system
1923void
1924Layer::ConvertFromParent2(BRegion* reg) const
1925{
1926	if (fParent) {
1927		BPoint origin = BoundsOrigin();
1928		reg->OffsetBy(origin.x, origin.y);
1929		reg->OffsetBy(-fFrame.left, -fFrame.top);
1930	}
1931}
1932
1933//! converts a point from local to screen coordinate system
1934void
1935Layer::ConvertToScreen2(BPoint* pt) const
1936{
1937	if (GetRootLayer())
1938		if (fParent) {
1939			BPoint origin = BoundsOrigin();
1940			pt->x -= origin.x;
1941			pt->y -= origin.y;
1942			pt->x += fFrame.left;
1943			pt->y += fFrame.top;
1944
1945			fParent->ConvertToScreen2(pt);
1946		}
1947}
1948
1949//! converts a rect from local to screen coordinate system
1950void
1951Layer::ConvertToScreen2(BRect* rect) const
1952{
1953	if (GetRootLayer())
1954		if (fParent) {
1955			BPoint origin = BoundsOrigin();
1956			rect->OffsetBy(-origin.x, -origin.y);
1957			rect->OffsetBy(fFrame.left, fFrame.top);
1958
1959			fParent->ConvertToScreen2(rect);
1960		}
1961}
1962
1963//! converts a region from local to screen coordinate system
1964void
1965Layer::ConvertToScreen2(BRegion* reg) const
1966{
1967	if (GetRootLayer())
1968		if (fParent) {
1969			BPoint origin = BoundsOrigin();
1970			reg->OffsetBy(-origin.x, -origin.y);
1971			reg->OffsetBy(fFrame.left, fFrame.top);
1972
1973			fParent->ConvertToScreen2(reg);
1974		}
1975}
1976
1977//! converts a point from screen to local coordinate system
1978void
1979Layer::ConvertFromScreen2(BPoint* pt) const
1980{
1981	if (GetRootLayer())
1982		if (fParent) {
1983			BPoint origin = BoundsOrigin();
1984			pt->x += origin.x;
1985			pt->y += origin.y;
1986			pt->x -= fFrame.left;
1987			pt->y -= fFrame.top;
1988
1989			fParent->ConvertToScreen2(pt);
1990		}
1991}
1992
1993//! converts a rect from screen to local coordinate system
1994void
1995Layer::ConvertFromScreen2(BRect* rect) const
1996{
1997	if (GetRootLayer())
1998		if (fParent) {
1999			BPoint origin = BoundsOrigin();
2000			rect->OffsetBy(origin.x, origin.y);
2001			rect->OffsetBy(-fFrame.left, -fFrame.top);
2002
2003			fParent->ConvertFromScreen2(rect);
2004		}
2005}
2006
2007//! converts a region from screen to local coordinate system
2008void
2009Layer::ConvertFromScreen2(BRegion* reg) const
2010{
2011	if (GetRootLayer())
2012		if (fParent) {
2013			BPoint origin = BoundsOrigin();
2014			reg->OffsetBy(origin.x, origin.y);
2015			reg->OffsetBy(-fFrame.left, -fFrame.top);
2016
2017			fParent->ConvertFromScreen2(reg);
2018		}
2019}
2020
2021
2022void
2023Layer::do_Hide()
2024{
2025	fHidden = true;
2026
2027	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
2028		// save fullVisible so we know what to invalidate
2029		BRegion invalid(fFullVisible2);
2030
2031		clear_visible_regions();
2032
2033		if (invalid.Frame().IsValid())
2034			fParent->do_Invalidate(invalid, this);
2035	}
2036}
2037
2038void
2039Layer::do_Show()
2040{
2041	fHidden = false;
2042
2043	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
2044		BRegion invalid;
2045
2046		get_user_regions(invalid);
2047
2048		if (invalid.CountRects() > 0)
2049			fParent->do_Invalidate(invalid, this);
2050	}
2051}
2052
2053void
2054Layer::do_Invalidate(const BRegion &invalid, const Layer *startFrom)
2055{
2056	BRegion		localVisible(fFullVisible2);
2057	localVisible.IntersectWith(&invalid);
2058	rebuild_visible_regions(invalid, localVisible,
2059		startFrom? startFrom: BottomChild());
2060
2061	// add localVisible to our RootLayer's redraw region.
2062//	GetRootLayer()->fRedrawReg.Include(&localVisible);
2063	GetRootLayer()->fRedrawReg = localVisible;
2064	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2065//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2066}
2067
2068void
2069Layer::do_Redraw(const BRegion &invalid, const Layer *startFrom)
2070{
2071	BRegion		localVisible(fFullVisible2);
2072	localVisible.IntersectWith(&invalid);
2073
2074	// add localVisible to our RootLayer's redraw region.
2075//	GetRootLayer()->fRedrawReg.Include(&localVisible);
2076	GetRootLayer()->fRedrawReg = localVisible;
2077	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2078//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2079}
2080
2081inline void
2082Layer::resize_layer_frame_by(float x, float y)
2083{
2084	uint16		rm = fResizeMode & 0x0000FFFF;
2085	BRect		newFrame = fFrame;
2086
2087	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
2088		newFrame.left += 0.0f;
2089	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
2090		newFrame.left += x;
2091	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
2092		newFrame.left += x/2;
2093
2094	if ((rm & 0x000FU) == _VIEW_LEFT_)
2095		newFrame.right += 0.0f;
2096	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
2097		newFrame.right += x;
2098	else if ((rm & 0x000FU) == _VIEW_CENTER_)
2099		newFrame.right += x/2;
2100
2101	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
2102		newFrame.top += 0.0f;
2103	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
2104		newFrame.top += y;
2105	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
2106		newFrame.top += y/2;
2107
2108	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
2109		newFrame.bottom += 0.0f;
2110	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
2111		newFrame.bottom += y;
2112	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
2113		newFrame.bottom += y/2;
2114
2115	if (newFrame != fFrame) {
2116		float		dx, dy;
2117
2118		dx	= newFrame.Width() - fFrame.Width();
2119		dy	= newFrame.Height() - fFrame.Height();
2120
2121		fFrame	= newFrame;
2122
2123		if (dx != 0.0f || dy != 0.0f) {
2124			// call hook function
2125			ResizedByHook(dx, dy, true); // automatic
2126
2127			for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
2128				lay->resize_layer_frame_by(dx, dy);
2129		}
2130		else
2131			MovedByHook(dx, dy);
2132	}
2133}
2134
2135inline void
2136Layer::rezize_layer_redraw_more(BRegion &reg, float dx, float dy)
2137{
2138	if (dx == 0 && dy == 0)
2139		return;
2140
2141	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
2142		uint16		rm = lay->fResizeMode & 0x0000FFFF;
2143
2144		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
2145			// NOTE: this is not exactly corect, but it works :-)
2146			// Normaly we shoud've used the lay's old, required region - the one returned
2147			// from get_user_region() with the old frame, and the current one. lay->Bounds()
2148			// works for the moment so we leave it like this.
2149
2150			// calculate the old bounds.
2151			BRect	oldBounds(lay->Bounds());
2152			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
2153				oldBounds.right -=dx;
2154			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
2155				oldBounds.bottom -=dy;
2156
2157			// compute the region that became visible because we got bigger OR smaller.
2158			BRegion	regZ(lay->Bounds());
2159			regZ.Include(oldBounds);
2160			regZ.Exclude(oldBounds&lay->Bounds());
2161
2162			lay->ConvertToScreen2(&regZ);
2163
2164			// intersect that with this'(not lay's) fullVisible region
2165			regZ.IntersectWith(&fFullVisible2);
2166			reg.Include(&regZ);
2167
2168			lay->rezize_layer_redraw_more(reg,
2169				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
2170				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
2171
2172			// above, OR this:
2173			// reg.Include(&lay->fFullVisible2);
2174		}
2175		else
2176		if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
2177			((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) ||
2178			((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
2179			((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
2180		{
2181			reg.Include(&lay->fFullVisible2);
2182		}
2183	}
2184}
2185
2186inline void
2187Layer::resize_layer_full_update_on_resize(BRegion &reg, float dx, float dy)
2188{
2189	if (dx == 0 && dy == 0)
2190		return;
2191
2192	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
2193		uint16		rm = lay->fResizeMode & 0x0000FFFF;
2194
2195		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
2196			if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0)
2197				reg.Include(&lay->fVisible2);
2198
2199			lay->resize_layer_full_update_on_resize(reg,
2200				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
2201				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
2202		}
2203	}
2204}
2205
2206void
2207Layer::do_ResizeBy(float dx, float dy)
2208{
2209	fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
2210
2211	// resize children using their resize_mask.
2212	for (Layer *lay = BottomChild(); lay; lay = UpperSibling())
2213			lay->resize_layer_frame_by(dx, dy);
2214
2215	// call hook function
2216	if (dx != 0.0f || dy != 0.0f)
2217		ResizedByHook(dx, dy, false); // manual
2218
2219	if (!IsHidden() && GetRootLayer()) {
2220		BRegion oldFullVisible(fFullVisible2);
2221		// this is required to invalidate the old border
2222		BRegion oldVisible(fVisible2);
2223
2224		// in case they moved, bottom, right and center aligned layers must be redrawn
2225		BRegion redrawMore;
2226		rezize_layer_redraw_more(redrawMore, dx, dy);
2227
2228		// we'll invalidate the old area and the new, maxmial one.
2229		BRegion invalid;
2230		get_user_regions(invalid);
2231		invalid.Include(&fFullVisible2);
2232
2233		clear_visible_regions();
2234
2235		fParent->do_RebuildVisibleRegions(invalid, this);
2236
2237		// done rebuilding regions, now redraw regions that became visible
2238
2239		// what's invalid, are the differences between to old and the new fullVisible region
2240		// 1) in case we grow.
2241		BRegion		redrawReg(fFullVisible2);
2242		redrawReg.Exclude(&oldFullVisible);
2243		// 2) in case we shrink
2244		BRegion		redrawReg2(oldFullVisible);
2245		redrawReg2.Exclude(&fFullVisible2);
2246		// 3) combine.
2247		redrawReg.Include(&redrawReg2);
2248
2249		// for center, right and bottom alligned layers, redraw their old positions
2250		redrawReg.Include(&redrawMore);
2251
2252		// layers that had their frame modified must be entirely redrawn.
2253		rezize_layer_redraw_more(redrawReg, dx, dy);
2254
2255		// add redrawReg to our RootLayer's redraw region.
2256//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2257		GetRootLayer()->fRedrawReg = redrawReg;
2258		// include layer's visible region in case we want a full update on resize
2259		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) {
2260			resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg, dx, dy);
2261
2262			GetRootLayer()->fRedrawReg.Include(&fVisible2);
2263			GetRootLayer()->fRedrawReg.Include(&oldVisible);
2264		}
2265		// clear canvas and set invalid regions for affected WinBorders
2266		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2267//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2268	}
2269}
2270
2271void Layer::do_MoveBy(float dx, float dy)
2272{
2273	if (dx == 0.0f && dy == 0.0f)
2274		return;
2275
2276//	fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
2277	fFrame.OffsetBy(dx, dy);
2278
2279	// call hook function
2280	MovedByHook(dx, dy);
2281
2282	if (!IsHidden() && GetRootLayer()) {
2283		BRegion oldFullVisible(fFullVisible2);
2284
2285		// we'll invalidate the old position and the new, maxmial one.
2286		BRegion invalid;
2287		get_user_regions(invalid);
2288		invalid.Include(&fFullVisible2);
2289
2290		clear_visible_regions();
2291
2292		fParent->do_RebuildVisibleRegions(invalid, this);
2293
2294		// done rebuilding regions, now copy common parts and redraw regions that became visible
2295
2296		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
2297		BRegion		redrawReg(fFullVisible2);
2298		redrawReg.Include(&oldFullVisible);
2299
2300		// offset to layer's new location so that we can calculate the common region.
2301		oldFullVisible.OffsetBy(dx, dy);
2302
2303		// finally we have the region that needs to be redrawn.
2304		redrawReg.Exclude(&oldFullVisible);
2305
2306		// by intersecting the old fullVisible offseted to layer's new location, with the current
2307		// fullVisible, we'll have the common region which can be copied using HW acceleration.
2308		oldFullVisible.IntersectWith(&fFullVisible2);
2309
2310		// offset back and instruct the HW to do the actual copying.
2311		oldFullVisible.OffsetBy(-dx, -dy);
2312		GetDisplayDriver()->CopyRegion(&oldFullVisible, dx, dy);
2313
2314		// add redrawReg to our RootLayer's redraw region.
2315//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2316		GetRootLayer()->fRedrawReg = redrawReg;
2317		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2318//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2319	}
2320}
2321
2322void
2323Layer::do_ScrollBy(float dx, float dy)
2324{
2325	fLayerData->OffsetOrigin(BPoint(dx, dy));
2326//	fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy);
2327
2328	if (!IsHidden() && GetRootLayer()) {
2329		// set the region to be invalidated.
2330		BRegion		invalid(fFullVisible2);
2331
2332		clear_visible_regions();
2333
2334		rebuild_visible_regions(invalid, invalid, BottomChild());
2335
2336		// for the moment we say that the whole surface needs to be redraw.
2337		BRegion		redrawReg(fFullVisible2);
2338
2339		// offset old region so that we can start comparing.
2340		invalid.OffsetBy(dx, dy);
2341
2342		// compute the common region. we'll use HW acc to copy this to the new location.
2343		invalid.IntersectWith(&fFullVisible2);
2344		GetDisplayDriver()->CopyRegion(&invalid, -dx, -dy);
2345
2346		// common region goes back to its original location. then, by excluding
2347		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
2348		invalid.OffsetBy(-dx, -dy);
2349		redrawReg.Exclude(&invalid);
2350
2351//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2352		GetRootLayer()->fRedrawReg = redrawReg;
2353		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2354//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2355	}
2356
2357	if (dx != 0.0f || dy != 0.0f)
2358		ScrolledByHook(dx, dy);
2359}
2360
2361void
2362Layer::get_user_regions(BRegion &reg)
2363{
2364	// 1) set to frame in screen coords
2365	BRect screenFrame(Bounds());
2366	ConvertToScreen2(&screenFrame);
2367	reg.Set(screenFrame);
2368
2369	// 2) intersect with screen region
2370	BRegion screenReg(GetRootLayer()->Bounds());
2371	reg.IntersectWith(&screenReg);
2372
2373
2374	// 3) impose user constrained regions
2375	LayerData *stackData = fLayerData;
2376	while (stackData) {
2377		if (stackData->ClippingRegion()) {
2378			// transform in screen coords
2379			BRegion screenReg(*stackData->ClippingRegion());
2380			ConvertToScreen2(&screenReg);
2381			reg.IntersectWith(&screenReg);
2382		}
2383		stackData = stackData->prevState;
2384	}
2385}
2386
2387void
2388Layer::do_RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom)
2389{
2390	BRegion		localVisible(fFullVisible2);
2391	localVisible.IntersectWith(&invalid);
2392	rebuild_visible_regions(invalid, localVisible, startFrom);
2393}
2394
2395void
2396Layer::rebuild_visible_regions(const BRegion &invalid,
2397								const BRegion &parentLocalVisible,
2398								const Layer *startFrom)
2399{
2400	// no point in continuing if this layer is hidden. starting from here, all
2401	// descendants have (and will have) invalid visible regions.
2402	if (fHidden)
2403		return;
2404
2405	// no need to go deeper if the parent doesn't have a visible region anymore
2406	// and our fullVisible region is also empty.
2407	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0))
2408		return;
2409
2410	bool fullRebuild = false;
2411
2412	// intersect maximum wanted region with the invalid region
2413	BRegion common;
2414	get_user_regions(common);
2415	common.IntersectWith(&invalid);
2416
2417	// if the resulted region is not valid, this layer is not in the catchment area
2418	// of the region being invalidated
2419	if (!common.CountRects() > 0)
2420		return;
2421
2422	// now intersect with parent's visible part of the region that was/is invalidated
2423	common.IntersectWith(&parentLocalVisible);
2424
2425	// exclude the invalid region
2426	fFullVisible2.Exclude(&invalid);
2427	fVisible2.Exclude(&invalid);
2428
2429	// put in what's really visible
2430	fFullVisible2.Include(&common);
2431
2432	// this is to allow a layer to hide some parts of itself so children
2433	// won't take them.
2434	BRegion unalteredVisible(common);
2435	bool altered = alter_visible_for_children(common);
2436
2437	for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) {
2438		if (lay == startFrom)
2439			fullRebuild = true;
2440
2441		if (fullRebuild)
2442			lay->rebuild_visible_regions(invalid, common, lay->BottomChild());
2443
2444		// to let children know much they can take from parent's visible region
2445		common.Exclude(&lay->fFullVisible2);
2446		// we've hidden some parts of our visible region from our children,
2447		// and we must be in sysnc with this region too...
2448		if (altered)
2449			unalteredVisible.Exclude(&lay->fFullVisible2);
2450	}
2451
2452	// the visible region of this layer is what left after all its children took
2453	// what they could.
2454	if (altered)
2455		fVisible2.Include(&unalteredVisible);
2456	else
2457		fVisible2.Include(&common);
2458}
2459
2460bool
2461Layer::alter_visible_for_children(BRegion &reg)
2462{
2463	// Empty Hook function
2464	return false;
2465}
2466
2467void
2468Layer::clear_visible_regions()
2469{
2470	// OPT: maybe we should uncomment these lines for performance
2471	//if (fFullVisible2.CountRects() <= 0)
2472	//	return;
2473
2474	fVisible2.MakeEmpty();
2475	fFullVisible2.MakeEmpty();
2476	for (Layer *child = BottomChild(); child; child = UpperSibling())
2477		child->clear_visible_regions();
2478}
2479
2480#endif
2481
2482