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