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