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