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