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