Layer.cpp revision d53639ce2e27b02b8fd5f6b320495f6361314cce
1//------------------------------------------------------------------------------
2//	Copyright (c) 2001-2002, Haiku, Inc.
3//
4//	Permission is hereby granted, free of charge, to any person obtaining a
5//	copy of this software and associated documentation files (the "Software"),
6//	to deal in the Software without restriction, including without limitation
7//	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8//	and/or sell copies of the Software, and to permit persons to whom the
9//	Software is furnished to do so, subject to the following conditions:
10//
11//	The above copyright notice and this permission notice shall be included in
12//	all copies or substantial portions of the Software.
13//
14//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19//	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20//	DEALINGS IN THE SOFTWARE.
21//
22//	File Name:		Layer.cpp
23//	Author:			DarkWyrm <bpmagic@columbus.rr.com>
24//					Adi Oanca <adioanca@myrealbox.com>
25//	Description:	Class used for rendering to the frame buffer. One layer per
26//					view on screen and also for window decorators
27//
28//------------------------------------------------------------------------------
29#include <View.h>
30#include <Message.h>
31#include <AppDefs.h>
32#include <Region.h>
33#include <string.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include "Layer.h"
37#include "ServerWindow.h"
38#include "WinBorder.h"
39#include "RGBColor.h"
40#include "RootLayer.h"
41#include "DisplayDriver.h"
42#include "LayerData.h"
43#include "PortLink.h"
44#include "ServerProtocol.h"
45
46//#define DEBUG_LAYER
47#ifdef DEBUG_LAYER
48#	define STRACE(x) printf x
49#else
50#	define STRACE(x) ;
51#endif
52
53//#define DEBUG_LAYER_REBUILD
54#ifdef DEBUG_LAYER_REBUILD
55#	define RBTRACE(x) printf x
56#else
57#	define RBTRACE(x) ;
58#endif
59
60enum {
61	B_LAYER_ACTION_NONE = 0,
62	B_LAYER_ACTION_MOVE,
63	B_LAYER_ACTION_RESIZE
64};
65
66Layer::Layer(BRect frame, const char *name, int32 token, uint32 resize,
67				uint32 flags, DisplayDriver *driver)
68{
69	// frame is in fParent coordinates
70	if(frame.IsValid())
71		fFrame		= frame;
72	else
73		// TODO: Decorator class should have a method witch returns the minimum frame width.
74		fFrame.Set(0.0f, 0.0f, 5.0f, 5.0f);
75
76	fBoundsLeftTop.Set( 0.0f, 0.0f );
77
78	fName			= new BString(name ? name : B_EMPTY_STRING);
79	fLayerData		= new LayerData();
80
81	// driver init
82	if (!driver)
83		debugger("You MUST have a valid driver to init a Layer object\n");
84	fDriver			= driver;
85
86	// Layer does not start out as a part of the tree
87	fOwner			= NULL;
88	fParent			= NULL;
89	fUpperSibling	= NULL;
90	fLowerSibling	= NULL;
91	fTopChild		= NULL;
92	fBottomChild	= NULL;
93
94	fCurrent		= NULL;
95	fRootLayer		= NULL;
96
97	fFlags			= flags;
98	fAdFlags		= 0;
99	fClassID		= AS_LAYER_CLASS;
100	fFrameAction	= B_LAYER_ACTION_NONE;
101	fResizeMode		= resize;
102
103	fHidden			= false;
104	fEventMask		= 0UL;
105	fEventOptions	= 0UL;
106	fIsTopLayer		= false;
107
108	fViewToken		= token;
109	fServerWin		= NULL;
110	clipToPicture	= NULL;
111
112	// NOW all regions (fVisible, fFullVisible, fFull) are empty
113	fClipReg		= &fVisible;
114	STRACE(("Layer(%s) successfuly created\n", GetName()));
115}
116
117//! Destructor frees all allocated heap space
118Layer::~Layer(void)
119{
120	if(fLayerData)
121	{
122		delete fLayerData;
123		fLayerData = NULL;
124	}
125
126	if(fName)
127	{
128		delete fName;
129		fName = NULL;
130	}
131
132	// TODO: uncomment!
133	//PruneTree();
134
135//	fServerWin->RemoveChild(fDriver);
136//	delete fDriver;
137
138	if (clipToPicture)
139	{
140		delete clipToPicture;
141		clipToPicture = NULL;
142
143		// TODO: allocate and release a ServerPicture Object.
144	}
145}
146
147/*!
148	\brief Adds a child layer to the current one
149	\param layer a new child layer
150	\param serverWin the serverwindow to which the layer will belong
151
152	Unlike the BView version, if the layer already belongs to another, then
153	it spits an error to stdout and returns.
154*/
155void Layer::AddChild(Layer *layer, ServerWindow *serverWin)
156{
157	STRACE(("Layer(%s)::AddChild(%s) START\n", GetName(), layer->GetName()));
158
159	if( layer->fParent != NULL )
160	{
161		printf("ERROR: AddChild(): Layer already has a parent\n");
162		return;
163	}
164
165	// 1) attach layer to the tree structure
166	layer->fParent = this;
167
168	// if we have children already, bump the current front child back one and
169	// make the new child the frontmost layer
170	if( fBottomChild )
171	{
172		layer->fUpperSibling = fBottomChild;
173		fBottomChild->fLowerSibling	= layer;
174	}
175	else
176	{
177		fTopChild = layer;
178	}
179	fBottomChild = layer;
180
181	// if we have no RootLayer yet, then there is no need to set any parameters --
182	// they will be set when the RootLayer for this tree will be added
183	// to the main tree structure.
184	if (!fRootLayer)
185	{
186		STRACE(("Layer(%s)::AddChild(%s) END\n", GetName(), layer->GetName()));
187		return;
188	}
189
190	// 2) Iterate over the newly-added layer and all its children, setting the
191	//	root layer and server window and also rebuilding the full-size region
192	//	for every descendant of the newly-added layer
193
194	//c = short for: current
195	Layer *c = layer;
196	Layer *stop = layer;
197	while( true )
198	{
199		// action block
200
201		// 2.1) set the RootLayer for this object.
202		c->SetRootLayer(c->fParent->fRootLayer);
203
204		// 2.2) this Layer must know if it has a ServerWindow object attached.
205		c->fServerWin=serverWin;
206
207		// 2.3) we are attached to the main tree so build our full region.
208		c->RebuildFullRegion();
209
210		// tree parsing algorithm
211		if(	c->fTopChild )
212		{
213			// go deep
214			c = c->fTopChild;
215		}
216		else
217		{
218			// go right or up
219
220			if (c == stop) // out trip is over
221				break;
222
223			if( c->fLowerSibling )
224			{
225				// go right
226				c = c->fLowerSibling;
227			}
228			else
229			{
230				// go up
231				while( !c->fParent->fLowerSibling && c->fParent != stop )
232					c = c->fParent;
233
234				if( c->fParent == stop ) // that's enough!
235					break;
236
237				c = c->fParent->fLowerSibling;
238			}
239		}
240	}
241
242	STRACE(("Layer(%s)::AddChild(%s) END\n", GetName(), layer->GetName()));
243}
244
245/*!
246	\brief Removes a child layer from the current one
247	\param layer the layer to remove
248
249	If the layer does not belong to the the current layer, then this function
250	spits out an error to stdout and returns
251*/
252void Layer::RemoveChild(Layer *layer)
253{
254	STRACE(("Layer(%s)::RemoveChild(%s) START\n", GetName(), layer->GetName()));
255
256	if(!layer->fParent)
257	{
258		printf("ERROR: RemoveChild(): Layer doesn't have a fParent\n");
259		return;
260	}
261
262	if(layer->fParent != this)
263	{
264		printf("ERROR: RemoveChild(): Layer is not a child of this layer\n");
265		return;
266	}
267
268	// 1) remove this layer from the main tree.
269
270	// Take care of fParent
271	layer->fParent = NULL;
272
273	if( fTopChild == layer )
274		fTopChild = layer->fLowerSibling;
275
276	if( fBottomChild == layer )
277		fBottomChild = layer->fUpperSibling;
278
279	// Take care of siblings
280	if( layer->fUpperSibling != NULL )
281		layer->fUpperSibling->fLowerSibling	= layer->fLowerSibling;
282
283	if( layer->fLowerSibling != NULL )
284		layer->fLowerSibling->fUpperSibling = layer->fUpperSibling;
285
286	layer->fUpperSibling = NULL;
287	layer->fLowerSibling = NULL;
288
289	// 2) Iterate over all of the removed-layer's descendants and unset the
290	//	root layer, server window, and all redraw-related regions
291
292	Layer *c = layer; //c = short for: current
293	Layer *stop = layer;
294
295	while( true )
296	{
297		// action block
298		{
299			// 2.1) set the RootLayer for this object.
300			c->SetRootLayer(NULL);
301			// 2.2) this Layer must know if it has a ServerWindow object attached.
302			c->fServerWin=NULL;
303			// 2.3) we were removed from the main tree so clear our full region.
304			c->fFull.MakeEmpty();
305			// 2.4) clear fullVisible region.
306			c->fFullVisible.MakeEmpty();
307			// 2.5) we don't have a visible region anymore.
308			c->fVisible.MakeEmpty();
309		}
310
311		// tree parsing algorithm
312		if(	c->fTopChild )
313		{
314			// go deep
315			c = c->fTopChild;
316		}
317		else
318		{
319			// go right or up
320			if (c == stop) // out trip is over
321				break;
322
323			if( c->fLowerSibling )
324			{
325				// go right
326				c = c->fLowerSibling;
327			}
328			else
329			{
330				// go up
331				while( !c->fParent->fLowerSibling && c->fParent != stop )
332					c = c->fParent;
333
334				if( c->fParent == stop ) // that enough!
335					break;
336
337				c = c->fParent->fLowerSibling;
338			}
339		}
340	}
341	STRACE(("Layer(%s)::RemoveChild(%s) END\n", GetName(), layer->GetName()));
342}
343
344//! Removes the calling layer from the tree
345void Layer::RemoveSelf()
346{
347	// A Layer removes itself from the tree (duh)
348	if( fParent == NULL )
349	{
350		printf("ERROR: RemoveSelf(): Layer doesn't have a fParent\n");
351		return;
352	}
353	fParent->RemoveChild(this);
354}
355
356/*!
357	\brief Determins if the calling layer has the passed layer as a child
358	\return true if the child is owned by the caller, false if not
359*/
360bool Layer::HasChild(Layer* layer)
361{
362	for(Layer *lay = VirtualTopChild(); lay; lay = VirtualLowerSibling())
363	{
364		if(lay == layer)
365			return true;
366	}
367	return false;
368}
369
370/*!
371	\brief Returns the layer at the given point
372	\param pt The point to look the layer at
373	\return The layer containing the point or NULL if no layer found
374*/
375Layer* Layer::LayerAt(const BPoint &pt)
376{
377	if (fVisible.Contains(pt))
378		return this;
379
380	if (fFullVisible.Contains(pt))
381	{
382		Layer *lay = NULL;
383		for ( Layer* child = VirtualBottomChild(); child; child = VirtualUpperSibling() )
384		{
385			lay = child->LayerAt( pt );
386			if (lay)
387				return lay;
388		}
389	}
390
391	return NULL;
392}
393
394//! Matches the BView call of the same name
395BRect Layer::Bounds(void) const
396{
397	BRect r(fFrame);
398	r.OffsetTo( fBoundsLeftTop );
399	return r;
400}
401
402//! Matches the BView call of the same name
403BRect Layer::Frame(void) const
404{
405	return fFrame;
406}
407
408//! Recursively deletes all children of the calling layer
409void Layer::PruneTree(void)
410{
411	Layer *lay;
412	Layer *nextlay;
413
414	lay = fTopChild;
415	fTopChild = NULL;
416
417	while(lay != NULL)
418	{
419		if(lay->fTopChild != NULL)
420			lay->PruneTree();
421
422		nextlay = lay->fLowerSibling;
423		lay->fLowerSibling = NULL;
424
425		delete lay;
426		lay = nextlay;
427	}
428	// Man, this thing is short. Elegant, ain't it? :P
429}
430
431/*!
432	\brief Finds a child of the caller based on its token ID
433	\param token ID of the layer to find
434	\return Pointer to the layer or NULL if not found
435*/
436Layer *Layer::FindLayer(const int32 token)
437{
438	// recursive search for a layer based on its view token
439	Layer *lay;
440	Layer *trylay;
441
442	// Search child layers first
443	for(lay = VirtualTopChild(); lay; lay = VirtualLowerSibling())
444	{
445		if(lay->fViewToken == token)
446			return lay;
447	}
448
449	// Hmmm... not in this layer's children. Try lower descendants
450	for(lay = VirtualTopChild(); lay != NULL; lay = VirtualLowerSibling())
451	{
452		trylay = lay->FindLayer(token);
453		if(trylay)
454			return trylay;
455	}
456
457	// Well, we got this far in the function, so apparently there is no match to be found
458	return NULL;
459}
460
461/*!
462	\brief Returns the layer's ServerWindow
463
464	If the layer's ServerWindow has not been assigned, it attempts to find
465	the owning ServerWindow in the tree.
466*/
467ServerWindow* Layer::SearchForServerWindow()
468{
469	if(!fServerWin)
470		fServerWin=fParent->SearchForServerWindow();
471
472	return fServerWin;
473}
474
475void Layer::FullInvalidate(const BRect &rect)
476{
477	FullInvalidate( BRegion(rect) );
478}
479
480void Layer::FullInvalidate(const BRegion& region)
481{
482	STRACE(("Layer(%s)::FullInvalidate():\n", GetName()));
483
484	#ifdef DEBUG_LAYER
485	region.PrintToStream();
486	printf("\n");
487	#endif
488
489	BPoint pt(0,0);
490	StartRebuildRegions(region, NULL,/* B_LAYER_INVALIDATE, pt); */B_LAYER_NONE, pt);
491
492	Redraw(fRootLayer->fRedrawReg);
493
494	EmptyGlobals();
495}
496
497void Layer::Invalidate(const BRegion& region)
498{
499	STRACE(("Layer(%s)::Invalidate():\n", GetName()));
500	#ifdef DEBUG_LAYER
501	region.PrintToStream();
502	printf("\n");
503	#endif
504
505	fRootLayer->fRedrawReg	= region;
506
507	Redraw(fRootLayer->fRedrawReg);
508
509	EmptyGlobals();
510}
511
512void Layer::Redraw(const BRegion& reg, Layer *startFrom)
513{
514	STRACE(("Layer(%s)::Redraw();\n", GetName()));
515	if (IsHidden())
516		// this layer has nothing visible on screen, so bail out.
517		return;
518
519	BRegion *pReg = const_cast<BRegion*>(&reg);
520
521	if (pReg->CountRects() > 0)
522		RequestDraw(reg, startFrom);
523
524	STRACE(("Layer(%s)::Redraw() ENDED\n", GetName()));
525}
526
527void Layer::RequestDraw(const BRegion &reg, Layer *startFrom)
528{
529	STRACE(("Layer(%s)::RequestDraw()\n", GetName()));
530
531	// do not redraw any child until you must
532	int redraw = false;
533	if (!startFrom)
534		redraw = true;
535
536	if (HasClient() && IsTopLayer())
537	{
538		// calculate the minimum region/rectangle to be updated with
539		// a single message to the client.
540		BRegion	updateReg(fFullVisible);
541		if (fFlags & B_FULL_UPDATE_ON_RESIZE
542			&& fFrameAction	== B_LAYER_ACTION_RESIZE)
543		{
544			// do nothing
545		}
546		else
547		{
548			updateReg.IntersectWith(&reg);
549		}
550		if (updateReg.CountRects() > 0)
551		{
552			fOwner->zUpdateReg.Include(&updateReg);
553			if (!fOwner->fInUpdate && !fOwner->fRequestSent)
554			{
555				fOwner->fUpdateReg = fOwner->zUpdateReg;
556fOwner->cnt++;
557if (fOwner->cnt != 1)
558	debugger("Adi: Not Allowed!");
559				fOwner->zUpdateReg.MakeEmpty();
560				SendUpdateMsg(fOwner->fUpdateReg);
561				fOwner->fRequestSent = true;
562			}
563		}
564	}
565
566	if (fVisible.CountRects() > 0)
567	{
568		BRegion	updateReg(fVisible);
569		// calculate the update region
570		if (fFlags & B_FULL_UPDATE_ON_RESIZE
571			&& fFrameAction	== B_LAYER_ACTION_RESIZE)
572		{
573			// do nothing
574		}
575		else
576		{
577			updateReg.IntersectWith(&reg);
578		}
579
580		if (updateReg.CountRects() > 0)
581		{
582			fDriver->ConstrainClippingRegion(&updateReg);
583			Draw(updateReg.Frame());
584			fDriver->ConstrainClippingRegion(NULL);
585		}
586	}
587
588	for (Layer *lay = VirtualBottomChild(); lay != NULL; lay = VirtualUpperSibling())
589	{
590		if (lay == startFrom)
591			redraw = true;
592
593		if (redraw && !(lay->IsHidden()))
594		{
595			// no need to go deeper if not even the FullVisible region intersects
596			// Update one.
597
598			BRegion common(lay->fFullVisible);
599			common.IntersectWith(&reg);
600
601			if (common.CountRects() > 0)
602				lay->RequestDraw(reg, NULL);
603		}
604	}
605}
606
607void Layer::Draw(const BRect &r)
608{
609	// TODO/NOTE: this should be an empty method! the next lines are for testing only
610
611	#ifdef DEBUG_LAYER
612	printf("Layer(%s)::Draw: ", GetName());
613	r.PrintToStream();
614	#endif
615
616	fDriver->FillRect(r, fLayerData->ViewColor());
617//	RGBColor c(rand()%255,rand()%255,rand()%255);
618//	fDriver->FillRect(r, c);
619
620	// empty HOOK function.
621}
622
623void Layer::UpdateStart()
624{
625	// During updates we only want to draw what's in the update region
626	if (fClassID == AS_WINBORDER_CLASS)
627	{
628		// NOTE: don't worry, RooLayer is locked here.
629		WinBorder	*wb = (WinBorder*)this;
630
631		wb->fInUpdate = true;
632		wb->fRequestSent = false;
633		wb->yUpdateReg = wb->fUpdateReg;
634		wb->fUpdateReg.MakeEmpty();
635wb->cnt--;
636if (wb->cnt != 0)
637	debugger("Adi2: Not Allowed!");
638	}
639}
640
641void Layer::UpdateEnd()
642{
643	// The usual case. Drawing is permitted in the whole visible area.
644	if (fClassID == AS_WINBORDER_CLASS)
645	{
646		WinBorder	*wb = (WinBorder*)this;
647
648		wb->yUpdateReg.MakeEmpty();
649
650		wb->fInUpdate = false;
651
652		if (wb->zUpdateReg.CountRects() > 0)
653		{
654			BRegion		reg(wb->zUpdateReg);
655			wb->RequestDraw(reg, NULL);
656		}
657	}
658}
659
660/*!
661	\brief Shows the layer
662	\param invalidate Invalidate the region when showing the layer. defaults to true
663*/
664void Layer::Show(bool invalidate)
665{
666	STRACE(("Layer(%s)::Show()\n", GetName()));
667	if( !IsHidden() )
668		return;
669
670	fHidden	= false;
671
672	if(invalidate)
673		GetRootLayer()->GoInvalidate(this, fFull);
674}
675
676/*!
677	\brief Shows the layer
678	\param invalidate Invalidate the region when hiding the layer. defaults to true
679*/
680void Layer::Hide(bool invalidate)
681{
682	STRACE(("Layer(%s)::Hide()\n", GetName()));
683	if ( IsHidden() )
684		return;
685
686	fHidden	= true;
687
688	if(invalidate)
689		GetRootLayer()->GoInvalidate(this, fFullVisible);
690}
691
692//! Returns true if the layer is hidden
693bool Layer::IsHidden(void) const
694{
695	if (fHidden)
696		return true;
697	else
698	{
699		if (fParent)
700			return fParent->IsHidden();
701	}
702
703	return false;
704}
705
706//! Returns the number of children
707uint32 Layer::CountChildren(void) const
708{
709	uint32 i = 0;
710	Layer *lay = VirtualTopChild();
711	while(lay != NULL)
712	{
713		lay	= VirtualLowerSibling();
714		i++;
715	}
716	return i;
717}
718
719//! Rebuilds the layer's "completely visible" region
720void Layer::RebuildFullRegion(void)
721{
722	STRACE(("Layer(%s)::RebuildFullRegion()\n", GetName()));
723
724	if (fParent)
725		fFull.Set(fParent->ConvertToTop(fFrame ));
726	else
727		fFull.Set(fFrame);
728
729	// TODO: restrict to screen coordinates
730
731	// TODO: Convert to screen coordinates
732
733	LayerData *ld;
734	ld = fLayerData;
735	do
736	{
737		// clip to user region
738		if (const BRegion* userClipping = ld->ClippingRegion())
739			fFull.IntersectWith(userClipping);
740
741	} while( (ld = ld->prevState) );
742
743	// clip to user picture region
744	if(clipToPicture)
745	{
746		if(clipToPictureInverse)
747			fFull.Exclude( clipToPicture );
748		else
749			fFull.IntersectWith( clipToPicture );
750	}
751}
752
753void Layer::RebuildRegions( const BRegion& reg, uint32 action, BPoint pt, BPoint ptOffset)
754{
755	STRACE(("Layer(%s)::RebuildRegions() START\n", GetName()));
756
757	// TODO:/NOTE: this method must be executed as quickly as possible.
758
759	// Currently SendView[Moved/Resized]Msg() simply constructs a message and calls
760	// ServerWindow::SendMessageToClient(). This involves the alternative use of
761	// kernel and this code in the CPU, so there are a lot of context switches.
762	// This is NOT good at all!
763
764	// One alternative would be the use of a BMessageQueue per ServerWindows OR only
765	// one for app_server which will be emptied as soon as this critical operation ended.
766	// Talk to DW, Gabe.
767
768	BRegion	oldRegion;
769	uint32 newAction = action;
770	BPoint newPt = pt;
771	BPoint newOffset = ptOffset; // used for resizing only
772
773	BPoint dummyNewLocation;
774
775	RRLabel1:
776	switch(action)
777	{
778		case B_LAYER_NONE:
779		{
780			RBTRACE(("1) Layer(%s): Action B_LAYER_NONE\n", GetName()));
781			oldRegion = fVisible;
782			break;
783		}
784		case B_LAYER_MOVE:
785		{
786			RBTRACE(("1) Layer(%s): Action B_LAYER_MOVE\n", GetName()));
787			oldRegion = fFullVisible;
788			fFrame.OffsetBy(pt.x, pt.y);
789			fFull.OffsetBy(pt.x, pt.y);
790
791			// TODO: uncomment later when you'll implement a queue in ServerWindow::SendMessgeToClient()
792			//SendViewMovedMsg();
793
794			newAction	= B_LAYER_SIMPLE_MOVE;
795			break;
796		}
797		case B_LAYER_SIMPLE_MOVE:
798		{
799			RBTRACE(("1) Layer(%s): Action B_LAYER_SIMPLE_MOVE\n", GetName()));
800			fFull.OffsetBy(pt.x, pt.y);
801
802			break;
803		}
804		case B_LAYER_RESIZE:
805		{
806			RBTRACE(("1) Layer(%s): Action B_LAYER_RESIZE\n", GetName()));
807			oldRegion	= fVisible;
808
809			fFrame.right	+= pt.x;
810			fFrame.bottom	+= pt.y;
811			RebuildFullRegion();
812
813			// TODO: uncomment later when you'll implement a queue in ServerWindow::SendMessgeToClient()
814			//SendViewResizedMsg();
815
816			newAction = B_LAYER_MASK_RESIZE;
817			break;
818		}
819		case B_LAYER_MASK_RESIZE:
820		{
821			RBTRACE(("1) Layer(%s): Action B_LAYER_MASK_RESIZE\n", GetName()));
822			oldRegion = fVisible;
823
824			BPoint offset, rSize;
825			BPoint coords[2];
826
827			ResizeOthers(pt.x, pt.y, coords, NULL);
828			offset = coords[0];
829			rSize = coords[1];
830			newOffset = offset + ptOffset;
831
832			if(!(rSize.x == 0.0f && rSize.y == 0.0f))
833			{
834				fFrame.OffsetBy(offset);
835				fFrame.right += rSize.x;
836				fFrame.bottom += rSize.y;
837				RebuildFullRegion();
838
839				// TODO: uncomment later when you'll implement a queue in ServerWindow::SendMessgeToClient()
840				//SendViewResizedMsg();
841
842				newAction = B_LAYER_MASK_RESIZE;
843				newPt = rSize;
844				dummyNewLocation = newOffset;
845			}
846			else
847			{
848				if (!(offset.x == 0.0f && offset.y == 0.0f))
849				{
850					pt = newOffset;
851					action = B_LAYER_MOVE;
852					newPt = pt;
853					goto RRLabel1;
854				}
855				else
856				{
857					pt = ptOffset;
858					action = B_LAYER_MOVE;
859					newPt = pt;
860					goto RRLabel1;
861				}
862			}
863			break;
864		}
865	}
866
867	if (!IsHidden())
868	{
869		#ifdef DEBUG_LAYER_REBUILD
870			printf("Layer(%s) real action START\n", GetName());
871			fFull.PrintToStream();
872		#endif
873		fFullVisible.MakeEmpty();
874		fVisible = fFull;
875
876		if (fParent && fVisible.CountRects() > 0)
877		{
878			// not the usual case, but support fot this is needed.
879			if (fParent->fAdFlags & B_LAYER_CHILDREN_DEPENDANT)
880			{
881				#ifdef DEBUG_LAYER_REBUILD
882					printf("   B_LAYER_CHILDREN_DEPENDANT Parent\n");
883				#endif
884
885				// because we're skipping one level, we need to do out
886				// parent business as well.
887
888				// our visible area is relative to our parent's parent.
889				if (fParent->fParent)
890					fVisible.IntersectWith(&(fParent->fParent->fVisible));
891
892				// exclude parent's visible area which could be composed by
893				// prior siblings' visible areas.
894				if (fVisible.CountRects() > 0)
895					fVisible.Exclude(&(fParent->fVisible));
896
897				// we have a final visible area. Include it to our parent's one,
898				// exclude from parent's parent.
899				if (fVisible.CountRects() > 0)
900				{
901					fParent->fFullVisible.Include(&fVisible);
902
903					if (fParent->fParent)
904						fParent->fParent->fVisible.Exclude(&fVisible);
905				}
906			}
907			else
908			{
909				// for 95+% of cases
910
911				#ifdef DEBUG_LAYER_REBUILD
912					printf("   (!)B_LAYER_CHILDREN_DEPENDANT Parent\n");
913				#endif
914
915				// the visible area is the one common with parent's one.
916				fVisible.IntersectWith(&(fParent->fVisible));
917
918				// exclude from parent's visible area. we're the owners now.
919				if (fVisible.CountRects() > 0)
920					fParent->fVisible.Exclude(&fVisible);
921			}
922		}
923		fFullVisible = fVisible;
924	}
925
926	// Rebuild regions for children...
927	for(Layer *lay = VirtualBottomChild(); lay != NULL; lay = VirtualUpperSibling())
928		lay->RebuildRegions(reg, newAction, newPt, newOffset);
929
930	#ifdef DEBUG_LAYER_REBUILD
931		printf("\nLayer(%s) ALMOST done regions:\n", GetName());
932		printf("\tVisible Region:\n");
933		fVisible.PrintToStream();
934		printf("\tFull Visible Region:\n");
935		fFullVisible.PrintToStream();
936	#endif
937
938	if(!IsHidden())
939	{
940		switch(action)
941		{
942			case B_LAYER_NONE:
943			{
944				RBTRACE(("2) Layer(%s): Action B_LAYER_NONE\n", GetName()));
945				BRegion r(fVisible);
946				if (oldRegion.CountRects() > 0)
947					r.Exclude(&oldRegion);
948
949				if(r.CountRects() > 0)
950					fRootLayer->fRedrawReg.Include(&r);
951				break;
952			}
953			case B_LAYER_MOVE:
954			{
955				RBTRACE(("2) Layer(%s): Action B_LAYER_MOVE\n", GetName()));
956				BRegion redrawReg;
957				BRegion	*copyReg = new BRegion();
958				BRegion	screenReg(fRootLayer->Bounds());
959
960				oldRegion.OffsetBy(pt.x, pt.y);
961				oldRegion.IntersectWith(&fFullVisible);
962
963				*copyReg = oldRegion;
964				copyReg->IntersectWith(&screenReg);
965				if(copyReg->CountRects() > 0 && !(pt.x == 0.0f && pt.y == 0.0f) )
966				{
967					copyReg->OffsetBy(-pt.x, -pt.y);
968					BPoint		*point = new BPoint(pt);
969					fRootLayer->fCopyRegList.AddItem(copyReg);
970					fRootLayer->fCopyList.AddItem(point);
971				}
972				else
973				{
974					delete copyReg;
975				}
976
977				redrawReg	= fFullVisible;
978				redrawReg.Exclude(&oldRegion);
979				if(redrawReg.CountRects() > 0 && !(pt.x == 0.0f && pt.y == 0.0f) )
980				{
981					fRootLayer->fRedrawReg.Include(&redrawReg);
982				}
983
984				break;
985			}
986			case B_LAYER_RESIZE:
987			{
988				RBTRACE(("2) Layer(%s): Action B_LAYER_RESIZE\n", GetName()));
989				BRegion redrawReg;
990
991				redrawReg = fVisible;
992				redrawReg.Exclude(&oldRegion);
993				if(redrawReg.CountRects() > 0)
994					fRootLayer->fRedrawReg.Include(&redrawReg);
995
996				break;
997			}
998			case B_LAYER_MASK_RESIZE:
999			{
1000				RBTRACE(("2) Layer(%s): Action B_LAYER_MASK_RESIZE\n", GetName()));
1001				BRegion redrawReg;
1002				BRegion	*copyReg = new BRegion();
1003
1004				oldRegion.OffsetBy(dummyNewLocation.x, dummyNewLocation.y);
1005
1006				redrawReg	= fVisible;
1007				redrawReg.Exclude(&oldRegion);
1008				if(redrawReg.CountRects() > 0)
1009				{
1010					fRootLayer->fRedrawReg.Include(&redrawReg);
1011				}
1012
1013				*copyReg = fVisible;
1014				copyReg->IntersectWith(&oldRegion);
1015				copyReg->OffsetBy(-dummyNewLocation.x, -dummyNewLocation.y);
1016				if(copyReg->CountRects() > 0
1017					&& !(dummyNewLocation.x == 0.0f && dummyNewLocation.y == 0.0f))
1018				{
1019					fRootLayer->fCopyRegList.AddItem(copyReg);
1020					fRootLayer->fCopyList.AddItem(new BPoint(dummyNewLocation));
1021				}
1022
1023				break;
1024			}
1025			default:
1026			{
1027				RBTRACE(("2) Layer(%s): Action default\n", GetName()));
1028				break;
1029			}
1030		}
1031	}
1032/*	if (IsHidden())
1033	{
1034		fFullVisible.MakeEmpty();
1035		fVisible.MakeEmpty();
1036	}
1037*/
1038
1039	STRACE(("Layer(%s)::RebuildRegions() END\n", GetName()));
1040}
1041
1042void Layer::StartRebuildRegions( const BRegion& reg, Layer *target, uint32 action, BPoint& pt)
1043{
1044	STRACE(("Layer(%s)::StartRebuildRegions() START\n", GetName()));
1045	RBTRACE(("\n\nLayer(%s)::StartRebuildRegions() START\n", GetName()));
1046	if(!fParent)
1047		fFullVisible = fFull;
1048
1049	BRegion oldVisible = fVisible;
1050
1051	fVisible = fFullVisible;
1052
1053	// Rebuild regions for children...
1054	for(Layer *lay = VirtualBottomChild(); lay; lay = VirtualUpperSibling())
1055	{
1056		if (lay == target)
1057			lay->RebuildRegions(reg, action, pt, BPoint(0.0f, 0.0f));
1058		else
1059			lay->RebuildRegions(reg, B_LAYER_NONE, pt, BPoint(0.0f, 0.0f));
1060	}
1061
1062	#ifdef DEBUG_LAYER_REBUILD
1063		printf("\nSRR: Layer(%s) ALMOST done regions:\n", GetName());
1064		printf("\tVisible Region:\n");
1065		fVisible.PrintToStream();
1066		printf("\tFull Visible Region:\n");
1067		fFullVisible.PrintToStream();
1068	#endif
1069
1070	BRegion redrawReg(fVisible);
1071
1072	// if this is the first time
1073	if (oldVisible.CountRects() > 0)
1074		redrawReg.Exclude(&oldVisible);
1075
1076	if (redrawReg.CountRects() > 0)
1077		fRootLayer->fRedrawReg.Include(&redrawReg);
1078
1079	#ifdef DEBUG_LAYER_REBUILD
1080		printf("\nLayer(%s)::StartRebuildRegions() DONE. Results:\n", GetName());
1081		printf("\tRedraw Region:\n");
1082		fRootLayer->fRedrawReg.PrintToStream();
1083		printf("\tCopy Region:\n");
1084		for(int32 k=0; k<fRootLayer->fCopyRegList.CountItems(); k++)
1085		{
1086			((BRegion*)(fRootLayer->fCopyRegList.ItemAt(k)))->PrintToStream();
1087			((BPoint*)(fRootLayer->fCopyList.ItemAt(k)))->PrintToStream();
1088		}
1089		printf("\n");
1090	#endif
1091
1092	STRACE(("Layer(%s)::StartRebuildRegions() END\n", GetName()));
1093	RBTRACE(("Layer(%s)::StartRebuildRegions() END\n", GetName()));
1094}
1095
1096//! Moves the layer by specified values, complete with redraw
1097void Layer::MoveBy(float x, float y)
1098{
1099	STRACE(("Layer(%s)::MoveBy() START\n", GetName()));
1100	if(!fParent)
1101	{
1102		debugger("ERROR: in Layer::MoveBy()! - No parent!\n");
1103		return;
1104	}
1105
1106	BPortLink	msg(-1, -1);
1107	msg.StartMessage(AS_ROOTLAYER_LAYER_MOVE);
1108	msg.Attach<Layer*>(this);
1109	msg.Attach<float>(x);
1110	msg.Attach<float>(y);
1111	GetRootLayer()->EnqueueMessage(msg);
1112
1113	STRACE(("Layer(%s)::MoveBy() END\n", GetName()));
1114}
1115
1116void Layer::move_layer(float x, float y)
1117{
1118	fFrameAction	= B_LAYER_ACTION_MOVE;
1119
1120	BPoint pt(x,y);
1121	BRect rect(fFull.Frame().OffsetByCopy(pt));
1122	if (fClassID == AS_WINBORDER_CLASS)
1123	{
1124		WinBorder	*wb = (WinBorder*)this;
1125		wb->zUpdateReg.OffsetBy(x, y);
1126		wb->yUpdateReg.OffsetBy(x, y);
1127		wb->fUpdateReg.OffsetBy(x, y);
1128	}
1129
1130	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_MOVE, pt);
1131	fDriver->CopyRegionList(&fRootLayer->fCopyRegList,
1132							&fRootLayer->fCopyList,
1133							fRootLayer->fCopyRegList.CountItems(),
1134							&fFullVisible);
1135	fParent->Redraw(fRootLayer->fRedrawReg, this);
1136
1137	EmptyGlobals();
1138
1139	fFrameAction	= B_LAYER_ACTION_NONE;
1140}
1141
1142void Layer::EmptyGlobals()
1143{
1144	void *item;
1145
1146	fRootLayer->fRedrawReg.MakeEmpty();
1147
1148	while((item = fRootLayer->fCopyRegList.RemoveItem((int32)0)))
1149		delete (BRegion*)item;
1150
1151	while((item = fRootLayer->fCopyList.RemoveItem((int32)0)))
1152		delete (BPoint*)item;
1153}
1154
1155uint32 Layer::ResizeOthers(float x, float y, BPoint coords[], BPoint *ptOffset)
1156{
1157	STRACE(("Layer(%s)::ResizeOthers() START\n", GetName()));
1158	uint32 rmask = fResizeMode;
1159
1160	// offset
1161	coords[0].x	= 0.0f;
1162	coords[0].y	= 0.0f;
1163
1164	// resize by width/height
1165	coords[1].x	= 0.0f;
1166	coords[1].y	= 0.0f;
1167
1168	if ((rmask & 0x00000f00UL)>>8 == _VIEW_LEFT_
1169			&& (rmask & 0x0000000fUL)>>0 == _VIEW_RIGHT_)
1170	{
1171		coords[1].x		= x;
1172	}
1173	else
1174	if ((rmask & 0x00000f00UL)>>8 == _VIEW_LEFT_)
1175	{
1176	}
1177	else
1178	if ((rmask & 0x0000000fUL)>>0 == _VIEW_RIGHT_)
1179	{
1180		coords[0].x		= x;
1181	}
1182	else
1183	if ((rmask & 0x00000f00UL)>>8 == _VIEW_CENTER_)
1184	{
1185		coords[0].x		= x/2;
1186	}
1187	else
1188	{
1189		// illegal flag. Do nothing.
1190	}
1191
1192
1193	if ((rmask & 0x0000f000UL)>>12 == _VIEW_TOP_
1194			&& (rmask & 0x000000f0UL)>>4 == _VIEW_BOTTOM_)
1195	{
1196		coords[1].y		= y;
1197	}
1198	else
1199	if ((rmask & 0x0000f000UL)>>12 == _VIEW_TOP_)
1200	{
1201	}
1202	else
1203	if ((rmask & 0x000000f0UL)>>4 == _VIEW_BOTTOM_)
1204	{
1205		coords[0].y		= y;
1206	}
1207	else
1208	if ((rmask & 0x0000f000UL)>>12 == _VIEW_CENTER_)
1209	{
1210		coords[0].y		= y/2;
1211	}
1212	else
1213	{
1214		// illegal flag. Do nothing.
1215	}
1216
1217	STRACE(("Layer(%s)::ResizeOthers() END\n", GetName()));
1218	return 0UL;
1219}
1220
1221//! Resize the layer by the specified amount, complete with redraw
1222void Layer::ResizeBy(float x, float y)
1223{
1224	STRACE(("Layer(%s)::ResizeBy() START\n", GetName()));
1225
1226	if(!fParent)
1227	{
1228		printf("ERROR: in Layer::MoveBy()! - No parent!\n");
1229		return;
1230	}
1231
1232	BPortLink	msg(-1, -1);
1233	msg.StartMessage(AS_ROOTLAYER_LAYER_RESIZE);
1234	msg.Attach<Layer*>(this);
1235	msg.Attach<float>(x);
1236	msg.Attach<float>(y);
1237	GetRootLayer()->EnqueueMessage(msg);
1238
1239	STRACE(("Layer(%s)::ResizeBy() END\n", GetName()));
1240}
1241
1242void Layer::resize_layer(float x, float y)
1243{
1244	fFrameAction	= B_LAYER_ACTION_RESIZE;
1245
1246	BPoint pt(x,y);
1247	BRect rect(fFull.Frame());
1248	rect.right += x;
1249	rect.bottom += y;
1250
1251	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_RESIZE, pt);
1252
1253	fDriver->CopyRegionList(&fRootLayer->fCopyRegList, &fRootLayer->fCopyList, fRootLayer->fCopyRegList.CountItems(), &fFullVisible);
1254	fParent->Redraw(fRootLayer->fRedrawReg, this);
1255
1256	EmptyGlobals();
1257
1258	fFrameAction	= B_LAYER_ACTION_NONE;
1259}
1260
1261//! Prints information about the layer's current state
1262void Layer::PrintToStream(void)
1263{
1264	printf("\n----------- Layer %s -----------\n",fName->String());
1265	printf("\t Parent: %s\n", fParent? fParent->GetName():"NULL");
1266	printf("\t us: %s\t ls: %s\n",
1267				fUpperSibling? fUpperSibling->GetName():"NULL",
1268				fLowerSibling? fLowerSibling->GetName():"NULL");
1269	printf("\t topChild: %s\t bottomChild: %s\n",
1270				fTopChild? fTopChild->GetName():"NULL",
1271				fBottomChild? fBottomChild->GetName():"NULL");
1272
1273	printf("Frame: (%f, %f, %f, %f)", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
1274	printf("Token: %ld\n",fViewToken);
1275	printf("Hidden - direct: %s\n", fHidden?"true":"false");
1276	printf("Hidden - indirect: %s\n", IsHidden()?"true":"false");
1277	printf("ResizingMode: %lx\n", fResizeMode);
1278	printf("Flags: %lx\n", fFlags);
1279
1280	if (fLayerData)
1281		fLayerData->PrintToStream();
1282	else
1283		printf(" NO LayerData valid pointer\n");
1284}
1285
1286//! Prints pointer info kept by the current layer
1287void Layer::PrintNode(void)
1288{
1289	printf("-----------\nLayer %s\n",fName->String());
1290	if(fParent)
1291		printf("Parent: %s (%p)\n",fParent->GetName(), fParent);
1292	else
1293		printf("Parent: NULL\n");
1294	if(fUpperSibling)
1295		printf("Upper sibling: %s (%p)\n",fUpperSibling->GetName(), fUpperSibling);
1296	else
1297		printf("Upper sibling: NULL\n");
1298	if(fLowerSibling)
1299		printf("Lower sibling: %s (%p)\n",fLowerSibling->GetName(), fLowerSibling);
1300	else
1301		printf("Lower sibling: NULL\n");
1302	if(fTopChild)
1303		printf("Top child: %s (%p)\n",fTopChild->GetName(), fTopChild);
1304	else
1305		printf("Top child: NULL\n");
1306	if(fBottomChild)
1307		printf("Bottom child: %s (%p)\n",fBottomChild->GetName(), fBottomChild);
1308	else
1309		printf("Bottom child: NULL\n");
1310	printf("Visible Areas: "); fVisible.PrintToStream();
1311}
1312
1313//! Prints the tree hierarchy from the current layer down
1314void Layer::PrintTree()
1315{
1316	printf("\n Tree structure:\n");
1317	printf("\t%s\t%s\n", GetName(), IsHidden()? "Hidden": "NOT hidden");
1318	for(Layer *lay = VirtualBottomChild(); lay != NULL; lay = VirtualUpperSibling())
1319		printf("\t%s\t%s\n", lay->GetName(), lay->IsHidden()? "Hidden": "NOT hidden");
1320}
1321
1322//! Converts the passed rectangle to parent coordinates
1323BRect Layer::ConvertToParent(BRect rect)
1324{
1325	return (rect.OffsetByCopy(fFrame.LeftTop()));
1326}
1327
1328//! Converts the passed region to parent coordinates
1329BRegion Layer::ConvertToParent(BRegion *reg)
1330{
1331	BRegion newreg;
1332
1333	for(int32 i=0; i<reg->CountRects(); i++)
1334		newreg.Include( (reg->RectAt(i)).OffsetByCopy(fFrame.LeftTop()) );
1335
1336	return newreg;
1337}
1338
1339//! Converts the passed rectangle from parent coordinates
1340BPoint Layer::ConvertFromParent(BPoint pt)
1341{
1342	return (pt - fFrame.LeftTop());
1343}
1344
1345//! Converts the passed rectangle from parent coordinates
1346BRect Layer::ConvertFromParent(BRect rect)
1347{
1348	return (rect.OffsetByCopy(fFrame.left*-1,fFrame.top*-1));
1349}
1350
1351//! Converts the passed region from parent coordinates
1352BRegion Layer::ConvertFromParent(BRegion *reg)
1353{
1354	BRegion newreg;
1355
1356	for(int32 i=0; i<reg->CountRects();i++)
1357		newreg.Include((reg->RectAt(i)).OffsetByCopy(fFrame.left*-1,fFrame.top*-1));
1358
1359	return newreg;
1360}
1361
1362BPoint Layer::ConvertToTop(BPoint pt)
1363{
1364	if (fParent!=NULL)
1365	{
1366		return(fParent->ConvertToTop(pt+fFrame.LeftTop()));
1367	}
1368	else
1369		return(pt);
1370}
1371
1372//! Converts the passed region to screen coordinates
1373BRegion Layer::ConvertToTop(BRegion *reg)
1374{
1375	BRegion newreg;
1376	for(int32 i=0; i<reg->CountRects();i++)
1377		newreg.Include(ConvertToTop(reg->RectAt(i)));
1378	return newreg;
1379}
1380
1381//! Converts the passed rectangle to screen coordinates
1382BRect Layer::ConvertToTop(BRect rect)
1383{
1384	if (fParent)
1385		return(fParent->ConvertToTop(rect.OffsetByCopy(fFrame.LeftTop())) );
1386	else
1387		return(rect);
1388}
1389
1390BPoint Layer::ConvertFromTop(BPoint pt)
1391{
1392	if (fParent)
1393	{
1394		return(fParent->ConvertFromTop(pt-fFrame.LeftTop()));
1395	}
1396	else
1397		return(pt);
1398}
1399
1400//! Converts the passed region from screen coordinates
1401BRegion Layer::ConvertFromTop(BRegion *reg)
1402{
1403	BRegion newreg;
1404
1405	for(int32 i=0; i<reg->CountRects();i++)
1406		newreg.Include(ConvertFromTop(reg->RectAt(i)));
1407
1408	return newreg;
1409}
1410
1411//! Converts the passed rectangle from screen coordinates
1412BRect Layer::ConvertFromTop(BRect rect)
1413{
1414	if (fParent!=NULL)
1415		return(fParent->ConvertFromTop(rect.OffsetByCopy(fFrame.LeftTop().x*-1,
1416			fFrame.LeftTop().y*-1)) );
1417	else
1418		return(rect);
1419}
1420
1421//! Sends a B_VIEW_RESIZE message to the client BWindow
1422void Layer::SendViewResizedMsg()
1423{
1424	if( fServerWin && fFlags & B_FRAME_EVENTS )
1425	{
1426		BMessage msg;
1427		msg.what = B_VIEW_RESIZED;
1428		msg.AddInt64( "when", real_time_clock_usecs() );
1429		msg.AddInt32( "_token", fViewToken );
1430		msg.AddFloat( "width", fFrame.Width() );
1431		msg.AddFloat( "height", fFrame.Height() );
1432
1433		// no need for that... it's here because of backward compatibility
1434		msg.AddPoint( "where", fFrame.LeftTop() );
1435
1436		fServerWin->SendMessageToClient( &msg );
1437	}
1438}
1439
1440//! Sends a B_VIEW_MOVED message to the client BWindow
1441void Layer::SendViewMovedMsg()
1442{
1443	if( fServerWin && fFlags & B_FRAME_EVENTS )
1444	{
1445		BMessage msg;
1446		msg.what = B_VIEW_MOVED;
1447		msg.AddInt64( "when", real_time_clock_usecs() );
1448		msg.AddInt32( "_token", fViewToken );
1449		msg.AddPoint( "where", fFrame.LeftTop() );
1450
1451		fServerWin->SendMessageToClient( &msg );
1452	}
1453}
1454
1455//! Sends an _UPDATE_ message to the client BWindow
1456void Layer::SendUpdateMsg(BRegion &reg)
1457{
1458	BMessage msg;
1459	msg.what = _UPDATE_;
1460	msg.AddRect("_rect", ConvertFromTop(reg.Frame()) );
1461	msg.AddRect("debug_rect", reg.Frame() );
1462//	msg.AddInt32("_token",fViewToken);
1463
1464	fOwner->Window()->SendMessageToClient(&msg);
1465}
1466
1467Layer *Layer::VirtualTopChild() const
1468{
1469	fCurrent = fTopChild;
1470	return fCurrent;
1471}
1472
1473Layer *Layer::VirtualLowerSibling() const
1474{
1475	fCurrent = fCurrent->fLowerSibling;
1476	return fCurrent;
1477}
1478
1479Layer *Layer::VirtualUpperSibling() const
1480{
1481	fCurrent = fCurrent->fUpperSibling;
1482	return fCurrent;
1483}
1484
1485Layer* Layer::VirtualBottomChild() const
1486{
1487	fCurrent = fBottomChild;
1488	return fCurrent;
1489}
1490