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