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