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