Layer.cpp revision 971ed3de1e9903f6c997fb61a1b42e8bb55ea879
1/*
2 * Copyright (c) 2001-2005, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 *		DarkWyrm <bpmagic@columbus.rr.com>
7 *		Adi Oanca <adioanca@gmail.com>
8 *		Stephan A��mus <superstippi@gmx.de>
9 *
10 * Description:
11 *		Class used for tracking drawing context and screen clipping.
12 *		One Layer per client BWindow (WindowBorder) and each BView therein.
13 */
14
15#include <string.h>
16#include <stdio.h>
17#include <stdlib.h>
18
19#include <AppDefs.h>
20#include <Message.h>
21#include <Region.h>
22#include <View.h>
23
24#include "DebugInfoManager.h"
25#include "DrawingEngine.h"
26#include "DrawState.h"
27#include "PortLink.h"
28#include "RootLayer.h"
29#include "ServerProtocol.h"
30#include "ServerWindow.h"
31#include "WinBorder.h"
32#include "Layer.h"
33#include "ServerBitmap.h"
34
35//#define DEBUG_LAYER
36#ifdef DEBUG_LAYER
37#	define STRACE(x) printf x
38#else
39#	define STRACE(x) ;
40#endif
41
42//#define DEBUG_LAYER_REBUILD
43#ifdef DEBUG_LAYER_REBUILD
44#	define RBTRACE(x) printf x
45#else
46#	define RBTRACE(x) ;
47#endif
48
49
50Layer::Layer(BRect frame, const char* name, int32 token,
51	uint32 resize, uint32 flags, DrawingEngine* driver)
52	:
53	fFrame(frame), // in parent coordinates
54//	fBoundsLeftTop(0.0, 0.0),
55
56	// Layer does not start out as a part of the tree
57	fOwner(NULL),
58
59	fParent(NULL),
60	fPreviousSibling(NULL),
61	fNextSibling(NULL),
62	fFirstChild(NULL),
63	fLastChild(NULL),
64
65	fCurrent(NULL),
66
67	// all regions (fVisible, fFullVisible, fFull) start empty
68	fVisible2(),
69	fFullVisible2(),
70	fDirtyForRebuild(),
71	fClipReg(&fVisible2),
72
73	fServerWin(NULL),
74	fName(name),
75	fViewToken(token),
76
77	fFlags(flags),
78	fResizeMode(resize),
79	fEventMask(0UL),
80	fEventOptions(0UL),
81	fHidden(false),
82	fIsTopLayer(false),
83
84	fAdFlags(0),
85
86	fDriver(driver),
87	fDrawState(new DrawState),
88
89	fRootLayer(NULL),
90
91	fViewColor(255, 255, 255, 255),
92	fBackgroundBitmap(NULL),
93	fOverlayBitmap(NULL)
94{
95	if (!frame.IsValid()) {
96char helper[1024];
97sprintf(helper, "Layer::Layer(BRect(%.1f, %.1f, %.1f, %.1f), name: %s, token: %ld) - frame is invalid\n",
98		frame.left, frame.top, frame.right, frame.bottom, name, token);
99CRITICAL(helper);
100		fFrame.Set(0, 0, 1, 1);
101	}
102
103	if (!fDriver)
104		CRITICAL("You MUST have a valid driver to init a Layer object\n");
105
106	// NOTE: This flag is forwarded to a DrawState setting, even
107	// though it is actually not part of a "state". However,
108	// it is an important detail of a graphics context, and we
109	// have no other means to pass this setting on to the DrawingEngine
110	// other than through the DrawState. If we ever add a flag
111	// B_ANTI_ALIASING to the view flags, it would have to be passed
112	// in the same way. Though when breaking binary compatibility,
113	// we might want to make this an actual part of a "state" (with
114	// a different API to set these).
115	// Note that the flag is also tested (updated) in Push/PopState and
116	// SetFlags().
117	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
118
119	STRACE(("Layer(%s) successfuly created\n", Name()));
120}
121
122
123Layer::~Layer()
124{
125	delete fDrawState;
126
127	// TODO: uncomment!
128	//PruneTree();
129}
130
131/*!
132	\brief Adds a child layer to the current one
133	\param layer a new child layer
134	\param serverWin the serverwindow to which the layer will belong
135
136	Unlike the BView version, if the layer already belongs to another, then
137	it spits an error to stdout and returns.
138*/
139void
140Layer::AddChild(Layer* layer, ServerWindow* serverWin)
141{
142	STRACE(("Layer(%s)::AddChild(%s) START\n", Name(), layer->Name()));
143
144	if (layer->fParent != NULL) {
145		printf("ERROR: AddChild(): Layer already has a parent\n");
146		return;
147	}
148
149	// 1) attach layer to the tree structure
150	layer->fParent = this;
151
152	// if we have children already, bump the current last child back one and
153	// make the new child the last layer
154	if (fLastChild) {
155		layer->fPreviousSibling = fLastChild;
156		fLastChild->fNextSibling = layer;
157	} else {
158		fFirstChild = layer;
159	}
160	fLastChild = layer;
161
162	// if we have no RootLayer yet, then there is no need to set any parameters --
163	// they will be set when the RootLayer for this tree will be added
164	// to the main tree structure.
165	if (!fRootLayer) {
166		STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name()));
167		return;
168	}
169
170	// 2) Iterate over the newly-added layer and all its children, setting the
171	//	root layer and server window and also rebuilding the full-size region
172	//	for every descendant of the newly-added layer
173
174	//c = short for: current
175	Layer* c = layer;
176	Layer* stop = layer;
177	while (true) {
178		// action block
179
180		// 2.1) set the RootLayer for this object.
181		c->SetRootLayer(c->fParent->fRootLayer);
182
183		// 2.2) this Layer must know if it has a ServerWindow object attached.
184		c->fServerWin=serverWin;
185
186		// tree parsing algorithm
187		if (c->fFirstChild) {
188			// go deep
189			c = c->fFirstChild;
190		} else {
191			// go right or up
192
193			if (c == stop) // our trip is over
194				break;
195
196			if (c->fNextSibling) {
197				// go right
198				c = c->fNextSibling;
199			} else {
200				// go up
201				while (!c->fParent->fNextSibling && c->fParent != stop)
202					c = c->fParent;
203
204				if (c->fParent == stop) // that's enough!
205					break;
206
207				c = c->fParent->fNextSibling;
208			}
209		}
210	}
211
212	STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name()));
213}
214
215/*!
216	\brief Removes a child layer from the current one
217	\param layer the layer to remove
218
219	If the layer does not belong to the the current layer, then this function
220	spits out an error to stdout and returns
221*/
222void
223Layer::RemoveChild(Layer *layer)
224{
225	STRACE(("Layer(%s)::RemoveChild(%s) START\n", Name(), layer->Name()));
226
227	if (!layer->fParent) {
228		printf("ERROR: RemoveChild(): Layer doesn't have a parent\n");
229		return;
230	}
231
232	if (layer->fParent != this) {
233		printf("ERROR: RemoveChild(): Layer is not a child of this layer\n");
234		return;
235	}
236
237	// 1) remove this layer from the main tree.
238
239	// Take care of fParent
240	layer->fParent = NULL;
241
242	if (fFirstChild == layer)
243		fFirstChild = layer->fNextSibling;
244
245	if (fLastChild == layer)
246		fLastChild = layer->fPreviousSibling;
247
248	// Take care of siblings
249	if (layer->fPreviousSibling != NULL)
250		layer->fPreviousSibling->fNextSibling	= layer->fNextSibling;
251
252	if (layer->fNextSibling != NULL)
253		layer->fNextSibling->fPreviousSibling = layer->fPreviousSibling;
254
255	layer->fPreviousSibling = NULL;
256	layer->fNextSibling = NULL;
257	layer->clear_visible_regions();
258
259	// 2) Iterate over all of the removed-layer's descendants and unset the
260	//	root layer, server window, and all redraw-related regions
261
262	Layer* c = layer; //c = short for: current
263	Layer* stop = layer;
264
265	while (true) {
266		// action block
267		{
268			// 2.1) set the RootLayer for this object.
269			c->SetRootLayer(NULL);
270			// 2.2) this Layer must know if it has a ServerWindow object attached.
271			c->fServerWin = NULL;
272		}
273
274		// tree parsing algorithm
275		if (c->fFirstChild) {
276			// go deep
277			c = c->fFirstChild;
278		} else {
279			// go right or up
280			if (c == stop) // out trip is over
281				break;
282
283			if (c->fNextSibling) {
284				// go right
285				c = c->fNextSibling;
286			} else {
287				// go up
288				while(!c->fParent->fNextSibling && c->fParent != stop)
289					c = c->fParent;
290
291				if (c->fParent == stop) // that enough!
292					break;
293
294				c = c->fParent->fNextSibling;
295			}
296		}
297	}
298	STRACE(("Layer(%s)::RemoveChild(%s) END\n", Name(), layer->Name()));
299}
300
301//! Removes the calling layer from the tree
302void
303Layer::RemoveSelf()
304{
305	// A Layer removes itself from the tree (duh)
306	if (fParent == NULL) {
307		printf("ERROR: RemoveSelf(): Layer doesn't have a parent\n");
308		return;
309	}
310	fParent->RemoveChild(this);
311}
312
313/*!
314	\return true if the child is owned by this Layer, false if not
315*/
316bool
317Layer::HasChild(Layer* layer)
318{
319	for (Layer* child = FirstChild(); child; child = NextChild()) {
320		if (child == layer)
321			return true;
322	}
323	return false;
324}
325
326//! Returns the number of children
327uint32
328Layer::CountChildren() const
329{
330	uint32 count = 0;
331	Layer* child = FirstChild();
332	while (child != NULL) {
333		child = NextChild();
334		count++;
335	}
336	return count;
337}
338
339/*!
340	\brief Finds a child of the caller based on its token ID
341	\param token ID of the layer to find
342	\return Pointer to the layer or NULL if not found
343*/
344Layer*
345Layer::FindLayer(const int32 token)
346{
347	// (recursive) search for a layer based on its view token
348
349	// iterate only over direct child layers first
350	for (Layer* child = FirstChild(); child; child = NextChild()) {
351		if (child->fViewToken == token)
352			return child;
353	}
354
355	// try a recursive search
356	for (Layer* child = FirstChild(); child; child = NextChild()) {
357		if (Layer* layer = child->FindLayer(token))
358			return layer;
359	}
360
361	return NULL;
362}
363
364/*!
365	\brief Returns the layer at the given point
366	\param pt The point to look the layer at
367	\return The layer containing the point or NULL if no layer found
368*/
369Layer*
370Layer::LayerAt(const BPoint &pt, bool recursive)
371{
372	//printf("%p:%s:LayerAt(x = %g, y = %g)\n", this, Name(), pt.x, pt.y);
373	if (!recursive)	{
374		if (VisibleRegion().Contains(pt))
375			return this;
376
377		for (Layer* child = LastChild(); child; child = PreviousChild())
378			if (child->FullVisible().Contains(pt))
379				return child;
380
381		return NULL;
382	}
383
384	if (fVisible2.Contains(pt))
385		return this;
386
387	if (fFullVisible2.Contains(pt)) {
388		for (Layer* child = LastChild(); child; child = PreviousChild()) {
389			if (Layer* layer = child->LayerAt(pt))
390				return layer;
391		}
392	}
393
394	return NULL;
395}
396
397// FirstChild
398Layer*
399Layer::FirstChild() const
400{
401	fCurrent = fFirstChild;
402	return fCurrent;
403}
404
405// NextChild
406Layer*
407Layer::NextChild() const
408{
409	fCurrent = fCurrent->fNextSibling;
410	return fCurrent;
411}
412
413// PreviousChild
414Layer*
415Layer::PreviousChild() const
416{
417	fCurrent = fCurrent->fPreviousSibling;
418	return fCurrent;
419}
420
421// LastChild
422Layer*
423Layer::LastChild() const
424{
425	fCurrent = fLastChild;
426	return fCurrent;
427}
428
429// SetName
430void
431Layer::SetName(const char* name)
432{
433	fName.SetTo(name);
434}
435
436// SetFlags
437void
438Layer::SetFlags(uint32 flags)
439{
440	fFlags = flags;
441	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
442}
443
444// Draw
445void
446Layer::Draw(const BRect &rect)
447{
448#ifdef DEBUG_LAYER
449	printf("Layer(%s)::Draw: ", Name());
450	rect.PrintToStream();
451#endif
452
453	if (!ViewColor().IsTransparentMagic())
454		fDriver->FillRect(rect, ViewColor());
455}
456
457/*!
458	\brief Shows the layer
459	\param invalidate Invalidate the region when showing the layer. defaults to true
460*/
461void
462Layer::Show(bool invalidate)
463{
464	STRACE(("Layer(%s)::Show()\n", Name()));
465	if(!IsHidden()) {
466		// an ancestor may be hidden. OK, we're not visible,
467		// but we're changing our visibility state
468		fHidden	= false;
469		return;
470	}
471
472	fHidden	= false;
473
474	SendViewCoordUpdateMsg();
475
476	if (invalidate) {
477		// compute the region this layer wants for itself
478		BRegion	invalid;
479		GetWantedRegion(invalid);
480		if (invalid.CountRects() > 0) {
481			fParent->MarkForRebuild(invalid);
482			GetRootLayer()->MarkForRedraw(invalid);
483
484			fParent->TriggerRebuild();
485			GetRootLayer()->TriggerRedraw();
486		}
487	}
488}
489
490/*!
491	\brief Shows the layer
492	\param invalidate Invalidate the region when hiding the layer. defaults to true
493*/
494void
495Layer::Hide(bool invalidate)
496{
497	STRACE(("Layer(%s)::Hide()\n", Name()));
498	if (IsHidden()) {
499		// an ancestor may be hidden. OK, we're not visible,
500		// but we're changing our visibility state
501		fHidden	= true;
502		return;
503	}
504
505	fHidden	= true;
506	if (invalidate && fFullVisible2.CountRects() > 0) {
507		BRegion invalid(fFullVisible2);
508
509		fParent->MarkForRebuild(invalid);
510		GetRootLayer()->MarkForRedraw(invalid);
511
512		fParent->TriggerRebuild();
513		GetRootLayer()->TriggerRedraw();
514	}
515}
516
517//! Returns true if the layer is hidden
518bool
519Layer::IsHidden(void) const
520{
521	if (fHidden)
522		return true;
523
524	if (fParent)
525			return fParent->IsHidden();
526
527	return fHidden;
528}
529
530
531void
532Layer::PushState()
533{
534	fDrawState = fDrawState->PushState();
535	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
536
537	// TODO: rebuild clipping and redraw
538}
539
540
541void
542Layer::PopState()
543{
544	if (fDrawState->PreviousState() == NULL) {
545		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), but there is NO state on stack!\n", Name());
546		return;
547	}
548
549	fDrawState = fDrawState->PopState();
550	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
551
552	// TODO: rebuild clipping and redraw
553}
554
555
556//! Matches the BView call of the same name
557BRect
558Layer::Bounds(void) const
559{
560	BRect r(fFrame);
561//	r.OffsetTo(fBoundsLeftTop);
562	r.OffsetTo(BoundsOrigin());
563	return r;
564}
565
566//! Matches the BView call of the same name
567BRect
568Layer::Frame(void) const
569{
570	return fFrame;
571}
572
573//! Moves the layer by specified values, complete with redraw
574void
575Layer::MoveBy(float x, float y)
576{
577	STRACE(("Layer(%s)::MoveBy() START\n", Name()));
578	if (!fParent) {
579		CRITICAL("ERROR: in Layer::MoveBy()! - No parent!\n");
580		return;
581	}
582
583	GetRootLayer()->Lock();
584	do_MoveBy(x, y);
585	GetRootLayer()->Unlock();
586
587	STRACE(("Layer(%s)::MoveBy() END\n", Name()));
588}
589
590//! Resize the layer by the specified amount, complete with redraw
591void
592Layer::ResizeBy(float x, float y)
593{
594	STRACE(("Layer(%s)::ResizeBy() START\n", Name()));
595
596	if (!fParent) {
597		printf("ERROR: in Layer::ResizeBy()! - No parent!\n");
598		return;
599	}
600
601	GetRootLayer()->Lock();
602	do_ResizeBy(x, y);
603	GetRootLayer()->Unlock();
604
605	STRACE(("Layer(%s)::ResizeBy() END\n", Name()));
606}
607
608//! scrolls the layer by the specified amount, complete with redraw
609void
610Layer::ScrollBy(float x, float y)
611{
612	STRACE(("Layer(%s)::ScrollBy() START\n", Name()));
613
614	GetRootLayer()->Lock();
615	do_ScrollBy(x, y);
616	GetRootLayer()->Unlock();
617
618	STRACE(("Layer(%s)::ScrollBy() END\n", Name()));
619}
620
621void
622Layer::MouseDown(const BMessage *msg)
623{
624	if (Window() && !IsTopLayer()) {
625		Window()->SendMessageToClient(msg, fViewToken, false);
626	}
627}
628
629void
630Layer::MouseUp(const BMessage *msg)
631{
632	if (Window() && !IsTopLayer()) {
633		Window()->SendMessageToClient(msg, fViewToken, false);
634	}
635}
636
637void
638Layer::MouseMoved(const BMessage *msg)
639{
640	if (Window() && !IsTopLayer()) {
641		Window()->SendMessageToClient(msg, fViewToken, false);
642	}
643}
644
645void
646Layer::MouseWheelChanged(const BMessage *msg)
647{
648	if (Window() && !IsTopLayer()) {
649		Window()->SendMessageToClient(msg, fViewToken, false);
650	}
651}
652
653void
654Layer::KeyDown(const BMessage *msg)
655{
656	if (Window() && !IsTopLayer()) {
657		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
658	}
659}
660
661void
662Layer::KeyUp(const BMessage *msg)
663{
664	if (Window() && !IsTopLayer()) {
665		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
666	}
667}
668
669void
670Layer::UnmappedKeyDown(const BMessage *msg)
671{
672	if (Window() && !IsTopLayer()) {
673		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
674	}
675}
676
677void
678Layer::UnmappedKeyUp(const BMessage *msg)
679{
680	if (Window() && !IsTopLayer()) {
681		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
682	}
683}
684
685void
686Layer::ModifiersChanged(const BMessage *msg)
687{
688	if (Window() && !IsTopLayer()) {
689		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
690	}
691}
692
693void
694Layer::WorkspaceActivated(int32 index, bool active)
695{
696	// Empty
697}
698
699void
700Layer::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces)
701{
702	// Empty
703}
704
705void
706Layer::Activated(bool active)
707{
708	// Empty
709}
710
711
712BPoint
713Layer::BoundsOrigin() const
714{
715	BPoint origin(fDrawState->Origin());
716	float scale = Scale();
717
718	// TODO: Figure this out, BoundsOrigin()
719	// is used for BView::Bounds(), but I think
720	// that the scale has nothing to do with it
721	// "local coordinate system origin" does have
722	// something to do with scale.
723
724	origin.x *= scale;
725	origin.y *= scale;
726
727	return origin;
728}
729
730
731float
732Layer::Scale() const
733{
734	return CurrentState()->Scale();
735}
736
737
738//! Converts the passed point to parent coordinates
739BPoint
740Layer::ConvertToParent(BPoint pt)
741{
742	ConvertToParent2(&pt);
743	return pt;
744}
745
746//! Converts the passed rectangle to parent coordinates
747BRect
748Layer::ConvertToParent(BRect rect)
749{
750	ConvertToParent2(&rect);
751	return rect;
752}
753
754//! Converts the passed region to parent coordinates
755BRegion
756Layer::ConvertToParent(BRegion* reg)
757{
758	BRegion newReg(*reg);
759	ConvertToParent2(&newReg);
760	return newReg;
761}
762
763//! Converts the passed point from parent coordinates
764BPoint
765Layer::ConvertFromParent(BPoint pt)
766{
767	ConvertFromParent2(&pt);
768	return pt;
769}
770
771//! Converts the passed rectangle from parent coordinates
772BRect
773Layer::ConvertFromParent(BRect rect)
774{
775	ConvertFromParent2(&rect);
776	return rect;
777}
778
779//! Converts the passed region from parent coordinates
780BRegion
781Layer::ConvertFromParent(BRegion *reg)
782{
783	BRegion newReg(*reg);
784	ConvertFromParent2(&newReg);
785	return newReg;
786}
787
788// ConvertToTop
789BPoint
790Layer::ConvertToTop(BPoint pt)
791{
792	ConvertToScreen2(&pt);
793	return pt;
794}
795
796//! Converts the passed rectangle to screen coordinates
797BRect
798Layer::ConvertToTop(BRect rect)
799{
800	ConvertToScreen2(&rect);
801	return rect;
802}
803
804//! Converts the passed region to screen coordinates
805BRegion
806Layer::ConvertToTop(BRegion *reg)
807{
808	BRegion newReg(*reg);
809	ConvertToScreen2(&newReg);
810	return newReg;
811}
812
813// ConvertFromTop
814BPoint
815Layer::ConvertFromTop(BPoint pt)
816{
817	ConvertFromScreen2(&pt);
818	return pt;
819}
820
821//! Converts the passed rectangle from screen coordinates
822BRect
823Layer::ConvertFromTop(BRect rect)
824{
825	ConvertFromScreen2(&rect);
826	return rect;
827}
828
829//! Converts the passed region from screen coordinates
830BRegion
831Layer::ConvertFromTop(BRegion *reg)
832{
833	BRegion newReg(*reg);
834	ConvertFromScreen2(&newReg);
835	return newReg;
836}
837
838//! Recursively deletes all children of the calling layer
839void
840Layer::PruneTree(void)
841{
842
843	Layer* lay;
844	Layer* nextlay;
845
846	lay = fFirstChild;
847	fFirstChild = NULL;
848
849	while (lay != NULL) {
850		if (lay->fFirstChild != NULL)
851			lay->PruneTree();
852
853		nextlay = lay->fNextSibling;
854		lay->fNextSibling = NULL;
855
856		delete lay;
857		lay = nextlay;
858	}
859	// Man, this thing is short. Elegant, ain't it? :P
860}
861
862//! Prints information about the layer's current state
863void
864Layer::PrintToStream()
865{
866	printf("\n *** Layer %s:\n", Name());
867	printf("\t Parent: %s", fParent ? fParent->Name() : "<no parent>");
868
869	printf("\t us: %s\t ls: %s\n",
870		fPreviousSibling ? fPreviousSibling->Name() : "<none>",
871		fNextSibling ? fNextSibling->Name() : "<none>");
872
873	printf("\t topChild: %s\t bottomChild: %s\n",
874		fFirstChild ? fFirstChild->Name() : "<none>",
875		fLastChild ? fLastChild->Name() : "<none>");
876
877	printf("Frame: (%f, %f, %f, %f)\n", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
878	printf("LocalOrigin: (%f, %f)\n", BoundsOrigin().x, BoundsOrigin().y);
879	printf("Token: %ld\n", fViewToken);
880	printf("Hidden - direct: %s ", fHidden?"true":"false");
881	printf("Hidden - indirect: %s\n", IsHidden()?"true":"false");
882	printf("ResizingMode: %lx ", fResizeMode);
883	printf("Flags: %lx\n", fFlags);
884
885	if (fDrawState)
886		fDrawState->PrintToStream();
887	else
888		printf(" NO DrawState valid pointer\n");
889}
890
891//! Prints pointer info kept by the current layer
892void
893Layer::PrintNode()
894{
895	printf("-----------\nLayer %s\n", Name());
896	if (fParent)
897		printf("Parent: %s (%p)\n", fParent->Name(), fParent);
898	else
899		printf("Parent: NULL\n");
900
901	if (fPreviousSibling)
902		printf("Upper sibling: %s (%p)\n", fPreviousSibling->Name(), fPreviousSibling);
903	else
904		printf("Upper sibling: NULL\n");
905
906	if (fNextSibling)
907		printf("Lower sibling: %s (%p)\n", fNextSibling->Name(), fNextSibling);
908	else
909		printf("Lower sibling: NULL\n");
910
911	if (fFirstChild)
912		printf("Top child: %s (%p)\n", fFirstChild->Name(), fFirstChild);
913	else
914		printf("Top child: NULL\n");
915
916	if (fLastChild)
917		printf("Bottom child: %s (%p)\n", fLastChild->Name(), fLastChild);
918	else
919		printf("Bottom child: NULL\n");
920}
921
922//! Prints the tree hierarchy from the current layer down
923void
924Layer::PrintTree()
925{
926	printf("\n Tree structure:\n");
927	printf("\t%s\t%s\n", Name(), IsHidden()? "Hidden": "NOT hidden");
928	for(Layer *lay = LastChild(); lay != NULL; lay = PreviousChild())
929		printf("\t%s\t%s\n", lay->Name(), lay->IsHidden()? "Hidden": "NOT hidden");
930}
931
932/*!
933	\brief Returns the layer's ServerWindow
934
935	If the layer's ServerWindow has not been assigned, it attempts to find
936	the owning ServerWindow in the tree.
937*/
938ServerWindow*
939Layer::SearchForServerWindow()
940{
941	if (!fServerWin)
942		fServerWin=fParent->SearchForServerWindow();
943
944	return fServerWin;
945}
946
947//! Sends an _UPDATE_ message to the client BWindow
948status_t
949Layer::SendUpdateMsg(BRegion& reg)
950{
951	BMessage msg;
952	msg.what = _UPDATE_;
953	BRect	rect(reg.Frame());
954	ConvertFromScreen2(&rect);
955	msg.AddRect("_rect", rect );
956	msg.AddRect("debug_rect", reg.Frame());
957
958	return Owner()->Window()->SendMessageToClient(&msg);
959}
960
961// AddToViewsWithInvalidCoords
962void
963Layer::AddToViewsWithInvalidCoords() const
964{
965	if (fServerWin) {
966		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
967		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
968		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
969		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
970	}
971}
972
973// SendViewCoordUpdateMsg
974void
975Layer::SendViewCoordUpdateMsg() const
976{
977	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
978		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
979		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
980	}
981}
982
983// SetViewColor
984void
985Layer::SetViewColor(const RGBColor& color)
986{
987	fViewColor = color;
988}
989
990// SetBackgroundBitmap
991void
992Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
993{
994	// TODO: What about reference counting?
995	// "Release" old fBackgroundBitmap and "Aquire" new one?
996	fBackgroundBitmap = bitmap;
997}
998
999// SetOverlayBitmap
1000void
1001Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
1002{
1003	// TODO: What about reference counting?
1004	// "Release" old fOverlayBitmap and "Aquire" new one?
1005	fOverlayBitmap = bitmap;
1006}
1007
1008void
1009Layer::CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
1010
1011	GetRootLayer()->Lock();
1012	do_CopyBits(src, dst, xOffset, yOffset);
1013	GetRootLayer()->Unlock();
1014}
1015
1016void
1017Layer::do_CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
1018	// NOTE: The correct behaviour is this:
1019	// * The region that is copied is the
1020	//   src rectangle, no matter if it fits
1021	//   into the dst rectangle. It is copied
1022	//   by the offset dst.LeftTop() - src.LeftTop()
1023	// * The dst rectangle is used for invalidation:
1024	//   Any area in the dst rectangle that could
1025	//   not be copied from src (because either the
1026	//   src rectangle was not big enough, or because there
1027	//   were parts cut off by the current layer clipping),
1028	//   are triggering BView::Draw() to be called
1029	//   and for these parts only.
1030
1031	// TODO: having moved this into Layer broke
1032	// offscreen windows (bitmaps)
1033	// -> move back into ServerWindow...
1034	if (!GetRootLayer())
1035		return;
1036
1037	// the region that is going to be copied
1038	BRegion copyRegion(src);
1039	// apply the current clipping of the layer
1040
1041	copyRegion.IntersectWith(&fVisible2);
1042
1043	// offset the region to the destination
1044	// and apply the current clipping there as well
1045	copyRegion.OffsetBy(xOffset, yOffset);
1046	copyRegion.IntersectWith(&fVisible2);
1047
1048	// the region at the destination that needs invalidation
1049	BRegion redrawReg(dst);
1050	// exclude the region drawn by the copy operation
1051// TODO: quick fix for our scrolling problem. FIX THIS!
1052//	redrawReg.Exclude(&copyRegion);
1053	// apply the current clipping as well
1054	redrawReg.IntersectWith(&fVisible2);
1055
1056	// move the region back for the actual operation
1057	copyRegion.OffsetBy(-xOffset, -yOffset);
1058
1059	GetDrawingEngine()->CopyRegion(&copyRegion, xOffset, yOffset);
1060
1061	// trigger the redraw
1062	GetRootLayer()->MarkForRedraw(redrawReg);
1063	GetRootLayer()->TriggerRedraw();
1064}
1065
1066void
1067Layer::MovedByHook(float dx, float dy)
1068{
1069	if (Window() && !IsTopLayer())
1070		AddToViewsWithInvalidCoords();
1071}
1072
1073void
1074Layer::ResizedByHook(float dx, float dy, bool automatic)
1075{
1076	if (Window() && !IsTopLayer())
1077		AddToViewsWithInvalidCoords();
1078}
1079
1080void
1081Layer::ScrolledByHook(float dx, float dy)
1082{
1083	// empty.
1084}
1085
1086//! converts a point from local to parent's coordinate system
1087void
1088Layer::ConvertToParent2(BPoint* pt) const
1089{
1090	if (fParent) {
1091		BPoint origin = BoundsOrigin();
1092		pt->x -= origin.x;
1093		pt->y -= origin.y;
1094		pt->x += fFrame.left;
1095		pt->y += fFrame.top;
1096	}
1097}
1098
1099//! converts a rect from local to parent's coordinate system
1100void
1101Layer::ConvertToParent2(BRect* rect) const
1102{
1103	if (fParent) {
1104		BPoint origin = BoundsOrigin();
1105		rect->OffsetBy(-origin.x, -origin.y);
1106		rect->OffsetBy(fFrame.left, fFrame.top);
1107	}
1108}
1109
1110//! converts a region from local to parent's coordinate system
1111void
1112Layer::ConvertToParent2(BRegion* reg) const
1113{
1114	if (fParent) {
1115		BPoint origin = BoundsOrigin();
1116		reg->OffsetBy(-origin.x, -origin.y);
1117		reg->OffsetBy(fFrame.left, fFrame.top);
1118	}
1119}
1120
1121//! converts a point from parent's to local coordinate system
1122void
1123Layer::ConvertFromParent2(BPoint* pt) const
1124{
1125	if (fParent) {
1126		BPoint origin = BoundsOrigin();
1127		pt->x += origin.x;
1128		pt->y += origin.y;
1129		pt->x -= fFrame.left;
1130		pt->y -= fFrame.top;
1131	}
1132}
1133
1134//! converts a rect from parent's to local coordinate system
1135void
1136Layer::ConvertFromParent2(BRect* rect) const
1137{
1138	if (fParent) {
1139		BPoint origin = BoundsOrigin();
1140		rect->OffsetBy(origin.x, origin.y);
1141		rect->OffsetBy(-fFrame.left, -fFrame.top);
1142	}
1143}
1144
1145//! converts a region from parent's to local coordinate system
1146void
1147Layer::ConvertFromParent2(BRegion* reg) const
1148{
1149	if (fParent) {
1150		BPoint origin = BoundsOrigin();
1151		reg->OffsetBy(origin.x, origin.y);
1152		reg->OffsetBy(-fFrame.left, -fFrame.top);
1153	}
1154}
1155
1156//! converts a point from local to screen coordinate system
1157void
1158Layer::ConvertToScreen2(BPoint* pt) const
1159{
1160	if (fParent) {
1161		ConvertToParent2(pt);
1162		fParent->ConvertToScreen2(pt);
1163	}
1164}
1165
1166//! converts a rect from local to screen coordinate system
1167void
1168Layer::ConvertToScreen2(BRect* rect) const
1169{
1170	if (fParent) {
1171		ConvertToParent2(rect);
1172		fParent->ConvertToScreen2(rect);
1173	}
1174}
1175
1176//! converts a region from local to screen coordinate system
1177void
1178Layer::ConvertToScreen2(BRegion* reg) const
1179{
1180	if (fParent) {
1181		ConvertToParent2(reg);
1182		fParent->ConvertToScreen2(reg);
1183	}
1184}
1185
1186//! converts a point from screen to local coordinate system
1187void
1188Layer::ConvertFromScreen2(BPoint* pt) const
1189{
1190	if (fParent) {
1191		ConvertFromParent2(pt);
1192		fParent->ConvertFromScreen2(pt);
1193	}
1194}
1195
1196//! converts a rect from screen to local coordinate system
1197void
1198Layer::ConvertFromScreen2(BRect* rect) const
1199{
1200	if (fParent) {
1201		ConvertFromParent2(rect);
1202		fParent->ConvertFromScreen2(rect);
1203	}
1204}
1205
1206//! converts a region from screen to local coordinate system
1207void
1208Layer::ConvertFromScreen2(BRegion* reg) const
1209{
1210	if (fParent) {
1211		ConvertFromParent2(reg);
1212		fParent->ConvertFromScreen2(reg);
1213	}
1214}
1215
1216
1217void
1218Layer::do_Hide()
1219{
1220	fHidden = true;
1221
1222	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1223		// save fullVisible so we know what to invalidate
1224		BRegion invalid(fFullVisible2);
1225
1226		clear_visible_regions();
1227
1228		if (invalid.CountRects() > 0) {
1229			fParent->MarkForRebuild(invalid);
1230			GetRootLayer()->MarkForRedraw(invalid);
1231
1232			fParent->TriggerRebuild();
1233			GetRootLayer()->TriggerRedraw();
1234		}
1235	}
1236}
1237
1238void
1239Layer::do_Show()
1240{
1241	fHidden = false;
1242
1243	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1244		BRegion invalid;
1245
1246		GetWantedRegion(invalid);
1247
1248		if (invalid.CountRects() > 0) {
1249			fParent->MarkForRebuild(invalid);
1250			GetRootLayer()->MarkForRedraw(invalid);
1251
1252			fParent->TriggerRebuild();
1253			GetRootLayer()->TriggerRedraw();
1254		}
1255	}
1256}
1257
1258inline void
1259Layer::resize_layer_frame_by(float x, float y)
1260{
1261	uint16		rm = fResizeMode & 0x0000FFFF;
1262	BRect		newFrame = fFrame;
1263
1264	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
1265		newFrame.left += 0.0f;
1266	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
1267		newFrame.left += x;
1268	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
1269		newFrame.left += x/2;
1270
1271	if ((rm & 0x000FU) == _VIEW_LEFT_)
1272		newFrame.right += 0.0f;
1273	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
1274		newFrame.right += x;
1275	else if ((rm & 0x000FU) == _VIEW_CENTER_)
1276		newFrame.right += x/2;
1277
1278	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
1279		newFrame.top += 0.0f;
1280	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
1281		newFrame.top += y;
1282	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
1283		newFrame.top += y/2;
1284
1285	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
1286		newFrame.bottom += 0.0f;
1287	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
1288		newFrame.bottom += y;
1289	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
1290		newFrame.bottom += y/2;
1291/*
1292	if (newFrame != fFrame) {
1293		float offsetX, offsetY;
1294		float dx, dy;
1295
1296		dx = newFrame.Width() - fFrame.Width();
1297		dy = newFrame.Height() - fFrame.Height();
1298		offsetX = newFrame.left - fFrame.left;
1299		offsetY = newFrame.top - fFrame.top;
1300
1301		fFrame = newFrame;
1302
1303		if (offsetX != 0.0f || offsetY != 0.0f) {
1304			MovedByHook(offsetX, offsetY);
1305		}
1306
1307		if (dx != 0.0f || dy != 0.0f) {
1308			// call hook function
1309			ResizedByHook(dx, dy, true); // automatic
1310
1311			for (Layer *lay = LastChild(); lay; lay = PreviousChild())
1312				lay->resize_layer_frame_by(dx, dy);
1313		}
1314	}
1315*/
1316// TODO: the above code is CORRECT!!!
1317// It's commented because BView::FrameResized()/Moved() be called twice a given view. FIX THIS!
1318	if (newFrame != fFrame) {
1319		float		dx, dy;
1320
1321		dx	= newFrame.Width() - fFrame.Width();
1322		dy	= newFrame.Height() - fFrame.Height();
1323
1324		fFrame	= newFrame;
1325
1326		if (dx != 0.0f || dy != 0.0f) {
1327			// call hook function
1328			ResizedByHook(dx, dy, true); // automatic
1329
1330			for (Layer *lay = LastChild(); lay; lay = PreviousChild())
1331				lay->resize_layer_frame_by(dx, dy);
1332		}
1333		else
1334			MovedByHook(dx, dy);
1335	}
1336}
1337
1338inline void
1339Layer::rezize_layer_redraw_more(BRegion &reg, float dx, float dy)
1340{
1341	if (dx == 0 && dy == 0)
1342		return;
1343
1344	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
1345		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1346
1347		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1348			// NOTE: this is not exactly corect, but it works :-)
1349			// Normaly we shoud've used the lay's old, required region - the one returned
1350			// from get_user_region() with the old frame, and the current one. lay->Bounds()
1351			// works for the moment so we leave it like this.
1352
1353			// calculate the old bounds.
1354			BRect	oldBounds(lay->Bounds());
1355			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
1356				oldBounds.right -=dx;
1357			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
1358				oldBounds.bottom -=dy;
1359
1360			// compute the region that became visible because we got bigger OR smaller.
1361			BRegion	regZ(lay->Bounds());
1362			regZ.Include(oldBounds);
1363			regZ.Exclude(oldBounds&lay->Bounds());
1364
1365			lay->ConvertToScreen2(&regZ);
1366
1367			// intersect that with this'(not lay's) fullVisible region
1368			regZ.IntersectWith(&fFullVisible2);
1369			reg.Include(&regZ);
1370
1371			lay->rezize_layer_redraw_more(reg,
1372				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1373				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1374
1375			// above, OR this:
1376			// reg.Include(&lay->fFullVisible2);
1377		}
1378		else
1379		if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
1380			((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) ||
1381			((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
1382			((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
1383		{
1384			reg.Include(&lay->fFullVisible2);
1385		}
1386	}
1387}
1388
1389inline void
1390Layer::resize_layer_full_update_on_resize(BRegion &reg, float dx, float dy)
1391{
1392	if (dx == 0 && dy == 0)
1393		return;
1394
1395	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
1396		uint16		rm = lay->fResizeMode & 0x0000FFFF;
1397
1398		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1399			if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0)
1400				reg.Include(&lay->fVisible2);
1401
1402			lay->resize_layer_full_update_on_resize(reg,
1403				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1404				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1405		}
1406	}
1407}
1408
1409void
1410Layer::do_ResizeBy(float dx, float dy)
1411{
1412	fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
1413
1414	// resize children using their resize_mask.
1415	for (Layer *lay = LastChild(); lay; lay = PreviousChild())
1416			lay->resize_layer_frame_by(dx, dy);
1417
1418	// call hook function
1419	if (dx != 0.0f || dy != 0.0f)
1420		ResizedByHook(dx, dy, false); // manual
1421
1422	if (!IsHidden() && GetRootLayer()) {
1423		BRegion oldFullVisible(fFullVisible2);
1424		// this is required to invalidate the old border
1425		BRegion oldVisible(fVisible2);
1426
1427		// in case they moved, bottom, right and center aligned layers must be redrawn
1428		BRegion redrawMore;
1429		rezize_layer_redraw_more(redrawMore, dx, dy);
1430
1431		// we'll invalidate the old area and the new, maxmial one.
1432		BRegion invalid;
1433		GetWantedRegion(invalid);
1434		invalid.Include(&fFullVisible2);
1435
1436		fParent->MarkForRebuild(invalid);
1437		fParent->TriggerRebuild();
1438
1439		// done rebuilding regions, now redraw regions that became visible
1440
1441		// what's invalid, are the differences between to old and the new fullVisible region
1442		// 1) in case we grow.
1443		BRegion		redrawReg(fFullVisible2);
1444		redrawReg.Exclude(&oldFullVisible);
1445		// 2) in case we shrink
1446		BRegion		redrawReg2(oldFullVisible);
1447		redrawReg2.Exclude(&fFullVisible2);
1448		// 3) combine.
1449		redrawReg.Include(&redrawReg2);
1450
1451		// for center, right and bottom alligned layers, redraw their old positions
1452		redrawReg.Include(&redrawMore);
1453
1454		// layers that had their frame modified must be entirely redrawn.
1455		rezize_layer_redraw_more(redrawReg, dx, dy);
1456
1457		// include layer's visible region in case we want a full update on resize
1458		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) {
1459			resize_layer_full_update_on_resize(redrawReg, dx, dy);
1460
1461			redrawReg.Include(&fVisible2);
1462			redrawReg.Include(&oldVisible);
1463		}
1464
1465		GetRootLayer()->MarkForRedraw(redrawReg);
1466		GetRootLayer()->TriggerRedraw();
1467	}
1468
1469	SendViewCoordUpdateMsg();
1470}
1471
1472void Layer::do_MoveBy(float dx, float dy)
1473{
1474	if (dx == 0.0f && dy == 0.0f)
1475		return;
1476
1477	fFrame.OffsetBy(dx, dy);
1478
1479	// call hook function
1480	MovedByHook(dx, dy);
1481
1482	if (!IsHidden() && GetRootLayer()) {
1483		BRegion oldFullVisible(fFullVisible2);
1484
1485		// we'll invalidate the old position and the new, maxmial one.
1486		BRegion invalid;
1487		GetWantedRegion(invalid);
1488		invalid.Include(&fFullVisible2);
1489
1490		fParent->MarkForRebuild(invalid);
1491		fParent->TriggerRebuild();
1492
1493		// done rebuilding regions, now copy common parts and redraw regions that became visible
1494
1495		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
1496		BRegion		redrawReg(fFullVisible2);
1497		redrawReg.Include(&oldFullVisible);
1498
1499		// offset to layer's new location so that we can calculate the common region.
1500		oldFullVisible.OffsetBy(dx, dy);
1501
1502		// finally we have the region that needs to be redrawn.
1503		redrawReg.Exclude(&oldFullVisible);
1504
1505		// by intersecting the old fullVisible offseted to layer's new location, with the current
1506		// fullVisible, we'll have the common region which can be copied using HW acceleration.
1507		oldFullVisible.IntersectWith(&fFullVisible2);
1508
1509		// offset back and instruct the HW to do the actual copying.
1510		oldFullVisible.OffsetBy(-dx, -dy);
1511		GetDrawingEngine()->CopyRegion(&oldFullVisible, dx, dy);
1512
1513		GetRootLayer()->MarkForRedraw(redrawReg);
1514		GetRootLayer()->TriggerRedraw();
1515	}
1516
1517	SendViewCoordUpdateMsg();
1518}
1519
1520void
1521Layer::do_ScrollBy(float dx, float dy)
1522{
1523	fDrawState->OffsetOrigin(BPoint(dx, dy));
1524
1525	if (!IsHidden() && GetRootLayer()) {
1526		// set the region to be invalidated.
1527		BRegion		invalid(fFullVisible2);
1528
1529		MarkForRebuild(invalid);
1530
1531		TriggerRebuild();
1532
1533		// for the moment we say that the whole surface needs to be redraw.
1534		BRegion		redrawReg(fFullVisible2);
1535
1536		// offset old region so that we can start comparing.
1537		invalid.OffsetBy(dx, dy);
1538
1539		// compute the common region. we'll use HW acc to copy this to the new location.
1540		invalid.IntersectWith(&fFullVisible2);
1541		GetDrawingEngine()->CopyRegion(&invalid, -dx, -dy);
1542
1543		// common region goes back to its original location. then, by excluding
1544		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
1545		invalid.OffsetBy(-dx, -dy);
1546// TODO: a quick fix for the scrolling problem!!! FIX THIS!
1547//		redrawReg.Exclude(&invalid);
1548
1549		GetRootLayer()->MarkForRedraw(redrawReg);
1550		GetRootLayer()->TriggerRedraw();
1551	}
1552
1553	if (dx != 0.0f || dy != 0.0f)
1554		ScrolledByHook(dx, dy);
1555}
1556
1557void
1558Layer::GetWantedRegion(BRegion &reg)
1559{
1560	// 1) set to frame in screen coords
1561	BRect screenFrame(Bounds());
1562	ConvertToScreen2(&screenFrame);
1563	reg.Set(screenFrame);
1564
1565	// 2) intersect with screen region
1566	BRegion screenReg(GetRootLayer()->Bounds());
1567	reg.IntersectWith(&screenReg);
1568
1569
1570	// 3) impose user constrained regions
1571	DrawState *stackData = fDrawState;
1572	while (stackData) {
1573		if (stackData->ClippingRegion()) {
1574			// transform in screen coords
1575// NOTE: Already is in screen coords, but I leave this here in
1576// case we change it
1577//			BRegion screenReg(*stackData->ClippingRegion());
1578//			ConvertToScreen2(&screenReg);
1579//			reg.IntersectWith(&screenReg);
1580			reg.IntersectWith(stackData->ClippingRegion());
1581		}
1582		stackData = stackData->PreviousState();
1583	}
1584}
1585
1586void
1587Layer::rebuild_visible_regions(const BRegion &invalid,
1588								const BRegion &parentLocalVisible,
1589								const Layer *startFrom)
1590{
1591/*
1592	// no point in continuing if this layer is hidden.
1593	if (fHidden)
1594		return;
1595
1596	// no need to go deeper if the parent doesn't have a visible region anymore
1597	// and our fullVisible region is also empty.
1598	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0))
1599		return;
1600
1601	bool fullRebuild = false;
1602
1603	// intersect maximum wanted region with the invalid region
1604	BRegion common;
1605	GetWantedRegion(common);
1606	common.IntersectWith(&invalid);
1607
1608	// if the resulted region is not valid, this layer is not in the catchment area
1609	// of the region being invalidated
1610	if (!common.CountRects() > 0)
1611		return;
1612
1613	// now intersect with parent's visible part of the region that was/is invalidated
1614	common.IntersectWith(&parentLocalVisible);
1615
1616	// exclude the invalid region
1617	fFullVisible2.Exclude(&invalid);
1618	fVisible2.Exclude(&invalid);
1619
1620	// put in what's really visible
1621	fFullVisible2.Include(&common);
1622
1623	// allow this layer to hide some parts from its children
1624	_ReserveRegions(common);
1625
1626	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
1627		if (lay == startFrom)
1628			fullRebuild = true;
1629
1630		if (fullRebuild)
1631			lay->rebuild_visible_regions(invalid, common, lay->LastChild());
1632
1633		// to let children know much they can take from parent's visible region
1634		common.Exclude(&lay->fFullVisible2);
1635	}
1636
1637	// include what's left after all children took what they could.
1638	fVisible2.Include(&common);
1639*/
1640
1641// NOTE: I modified this method for the moment because of some issues that I have
1642//		 with the new public methods that I recently introduced.
1643//		 This code works very well, the single problem that it has it's that it
1644//		 rebuilds all the visible regions of its descendants.
1645// TODO: only rebuild what's needed. See above code.
1646// NOTE2: this does not affect the redrawing code.
1647
1648	// no point in continuing if this layer is hidden.
1649	if (fHidden)
1650		return;
1651
1652	// no need to go deeper if the parent doesn't have a visible region anymore
1653	if (!parentLocalVisible.Frame().IsValid())
1654		return;
1655
1656	BRegion common;
1657	GetWantedRegion(common);
1658
1659	// see how much you can take
1660	common.IntersectWith(&parentLocalVisible);
1661	fFullVisible2 = common;
1662	fVisible2.MakeEmpty();
1663
1664	// allow this layer to hide some parts from its children
1665	_ReserveRegions(common);
1666
1667	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
1668		lay->rebuild_visible_regions(invalid, common, lay->LastChild());
1669
1670		// to let children know much they can take from parent's visible region
1671		common.Exclude(&lay->fFullVisible2);
1672	}
1673
1674	// include what's left after all children took what they could.
1675	fVisible2.Include(&common);
1676}
1677
1678void
1679Layer::_ReserveRegions(BRegion &reg)
1680{
1681	// Empty for Layer objects
1682}
1683
1684void
1685Layer::clear_visible_regions()
1686{
1687	// OPT: maybe we should uncomment these lines for performance
1688	//if (fFullVisible2.CountRects() <= 0)
1689	//	return;
1690
1691	fVisible2.MakeEmpty();
1692	fFullVisible2.MakeEmpty();
1693	for (Layer *child = LastChild(); child; child = PreviousChild())
1694		child->clear_visible_regions();
1695}
1696
1697// mark a region dirty so that the next region rebuild for us
1698// and our children will take this into account
1699void
1700Layer::MarkForRebuild(const BRegion &dirty)
1701{
1702	fDirtyForRebuild.Include(&dirty);
1703}
1704
1705// this will trigger visible region recalculation for us and
1706// our descendants.
1707void
1708Layer::TriggerRebuild()
1709{
1710	BRegion totalInvalidReg;
1711
1712	_GetAllRebuildDirty(&totalInvalidReg);
1713
1714	if (totalInvalidReg.CountRects() > 0) {
1715		BRegion localFullVisible(fFullVisible2);
1716
1717//		localFullVisible.IntersectWith(&totalInvalidReg);
1718
1719		clear_visible_regions();
1720
1721		rebuild_visible_regions(totalInvalidReg, localFullVisible, LastChild());
1722	}
1723}
1724
1725// find out the region for which we must rebuild the visible regions
1726void
1727Layer::_GetAllRebuildDirty(BRegion *totalReg)
1728{
1729	totalReg->Include(&fDirtyForRebuild);
1730
1731	for (Layer *child = LastChild(); child; child = PreviousChild())
1732		child->_GetAllRebuildDirty(totalReg);
1733
1734	fDirtyForRebuild.MakeEmpty();
1735}
1736
1737void
1738Layer::_AllRedraw(const BRegion &invalid)
1739{
1740	// couldn't find a simpler way to send _UPDATE_ message to client.
1741	WinBorder *wb = dynamic_cast<WinBorder*>(this);
1742	if (wb)
1743		wb->RequestClientRedraw(invalid);
1744
1745	if (fVisible2.CountRects() > 0) {
1746		BRegion	updateReg(fVisible2);
1747		updateReg.IntersectWith(&invalid);
1748
1749		if (updateReg.CountRects() > 0) {
1750			fDriver->ConstrainClippingRegion(&updateReg);
1751			Draw(updateReg.Frame());
1752			fDriver->ConstrainClippingRegion(NULL);
1753		}
1754	}
1755
1756	for (Layer *lay = LastChild(); lay != NULL; lay = PreviousChild()) {
1757		if (!(lay->IsHidden())) {
1758			BRegion common(lay->fFullVisible2);
1759			common.IntersectWith(&invalid);
1760
1761			if (common.CountRects() > 0)
1762				lay->_AllRedraw(invalid);
1763		}
1764	}
1765}
1766
1767