Layer.cpp revision 8285d6b3c0e19b94803b48340ad12286a528b65d
1//------------------------------------------------------------------------------
2//	Copyright (c) 2001-2005, 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@cotty.iren.ro>
25//					Stephan A��mus <superstippi@gmx.de>
26//	Description:	Class used for rendering to the frame buffer. One layer per
27//					view on screen and also for window decorators
28//
29//------------------------------------------------------------------------------
30#include <string.h>
31#include <stdio.h>
32#include <stdlib.h>
33
34#include <AppDefs.h>
35#include <Message.h>
36#include <Region.h>
37#include <View.h>
38
39#include "DebugInfoManager.h"
40#include "DisplayDriver.h"
41#include "LayerData.h"
42#include "PortLink.h"
43#include "RootLayer.h"
44#include "ServerProtocol.h"
45#include "ServerWindow.h"
46#include "WinBorder.h"
47#include "Layer.h"
48#include "ServerBitmap.h"
49
50//#define DEBUG_LAYER
51#ifdef DEBUG_LAYER
52#	define STRACE(x) printf x
53#else
54#	define STRACE(x) ;
55#endif
56
57//#define DEBUG_LAYER_REBUILD
58#ifdef DEBUG_LAYER_REBUILD
59#	define RBTRACE(x) printf x
60#else
61#	define RBTRACE(x) ;
62#endif
63
64Layer::Layer(BRect frame, const char* name, int32 token,
65			 uint32 resize, uint32 flags, DisplayDriver* driver)
66	:
67	fFrame(frame), // in parent coordinates
68//	fBoundsLeftTop(0.0, 0.0),
69
70	// Layer does not start out as a part of the tree
71	fOwner(NULL),
72
73	fParent(NULL),
74	fPreviousSibling(NULL),
75	fNextSibling(NULL),
76	fFirstChild(NULL),
77	fLastChild(NULL),
78
79	fCurrent(NULL),
80
81	// all regions (fVisible, fFullVisible, fFull) start empty
82#ifndef NEW_CLIPPING
83	fVisible(),
84	fFullVisible(),
85	fFull(),
86	fFrameAction(B_LAYER_ACTION_NONE),
87	fClipReg(&fVisible),
88#else
89	fVisible2(),
90	fFullVisible2(),
91	fClipReg(&fVisible2),
92#endif
93
94	fServerWin(NULL),
95	fName(name),
96	fViewToken(token),
97
98	fFlags(flags),
99	fResizeMode(resize),
100	fEventMask(0UL),
101	fEventOptions(0UL),
102	fHidden(false),
103	fIsTopLayer(false),
104
105	fAdFlags(0),
106	fClassID(AS_LAYER_CLASS),
107
108	fDriver(driver),
109	fLayerData(new LayerData()),
110
111	fRootLayer(NULL),
112
113	fViewColor(255, 255, 255, 255),
114	fBackgroundBitmap(NULL),
115	fOverlayBitmap(NULL)
116{
117	if (!frame.IsValid()) {
118char helper[1024];
119sprintf(helper, "Layer::Layer(BRect(%.1f, %.1f, %.1f, %.1f), name: %s, token: %ld) - frame is invalid\n",
120		frame.left, frame.top, frame.right, frame.bottom, name, token);
121CRITICAL(helper);
122		fFrame.Set(0, 0, 1, 1);
123	}
124
125	if (!fDriver)
126		CRITICAL("You MUST have a valid driver to init a Layer object\n");
127
128	// NOTE: This flag is forwarded to a LayerData setting, even
129	// though it is actually not part of a "state". However,
130	// it is an important detail of a graphics context, and we
131	// have no other means to pass this setting on to the DisplayDriver
132	// other than through the LayerData. If we ever add a flag
133	// B_ANTI_ALIASING to the view flags, it would have to be passed
134	// in the same way. Though when breaking binary compatibility,
135	// we might want to make this an actual part of a "state" (with
136	// a different API to set these).
137	// Note that the flag is also tested (updated) in Push/PopState and
138	// SetFlags().
139	fLayerData->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
140
141	STRACE(("Layer(%s) successfuly created\n", Name()));
142}
143
144//! Destructor frees all allocated heap space
145Layer::~Layer()
146{
147	delete fLayerData;
148
149	// TODO: uncomment!
150	//PruneTree();
151}
152
153/*!
154	\brief Adds a child layer to the current one
155	\param layer a new child layer
156	\param serverWin the serverwindow to which the layer will belong
157
158	Unlike the BView version, if the layer already belongs to another, then
159	it spits an error to stdout and returns.
160*/
161void
162Layer::AddChild(Layer* layer, ServerWindow* serverWin)
163{
164	STRACE(("Layer(%s)::AddChild(%s) START\n", Name(), layer->Name()));
165
166	if (layer->fParent != NULL) {
167		printf("ERROR: AddChild(): Layer already has a parent\n");
168		return;
169	}
170
171	// 1) attach layer to the tree structure
172	layer->fParent = this;
173
174	// if we have children already, bump the current last child back one and
175	// make the new child the last layer
176	if (fLastChild) {
177		layer->fPreviousSibling = fLastChild;
178		fLastChild->fNextSibling = layer;
179	} else {
180		fFirstChild = layer;
181	}
182	fLastChild = layer;
183
184	// if we have no RootLayer yet, then there is no need to set any parameters --
185	// they will be set when the RootLayer for this tree will be added
186	// to the main tree structure.
187	if (!fRootLayer) {
188		STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name()));
189		return;
190	}
191
192	// 2) Iterate over the newly-added layer and all its children, setting the
193	//	root layer and server window and also rebuilding the full-size region
194	//	for every descendant of the newly-added layer
195
196	//c = short for: current
197	Layer* c = layer;
198	Layer* stop = layer;
199	while (true) {
200		// action block
201
202		// 2.1) set the RootLayer for this object.
203		c->SetRootLayer(c->fParent->fRootLayer);
204
205		// 2.2) this Layer must know if it has a ServerWindow object attached.
206		c->fServerWin=serverWin;
207
208		// 2.3) we are attached to the main tree so build our full region.
209#ifndef NEW_CLIPPING
210		c->RebuildFullRegion();
211#endif
212		// tree parsing algorithm
213		if (c->fFirstChild) {
214			// go deep
215			c = c->fFirstChild;
216		} else {
217			// go right or up
218
219			if (c == stop) // our trip is over
220				break;
221
222			if (c->fNextSibling) {
223				// go right
224				c = c->fNextSibling;
225			} else {
226				// go up
227				while (!c->fParent->fNextSibling && c->fParent != stop)
228					c = c->fParent;
229
230				if (c->fParent == stop) // that's enough!
231					break;
232
233				c = c->fParent->fNextSibling;
234			}
235		}
236	}
237
238	STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name()));
239}
240
241/*!
242	\brief Removes a child layer from the current one
243	\param layer the layer to remove
244
245	If the layer does not belong to the the current layer, then this function
246	spits out an error to stdout and returns
247*/
248void
249Layer::RemoveChild(Layer *layer)
250{
251	STRACE(("Layer(%s)::RemoveChild(%s) START\n", Name(), layer->Name()));
252
253	if (!layer->fParent) {
254		printf("ERROR: RemoveChild(): Layer doesn't have a parent\n");
255		return;
256	}
257
258	if (layer->fParent != this) {
259		printf("ERROR: RemoveChild(): Layer is not a child of this layer\n");
260		return;
261	}
262
263	// 1) remove this layer from the main tree.
264
265	// Take care of fParent
266	layer->fParent = NULL;
267
268	if (fFirstChild == layer)
269		fFirstChild = layer->fNextSibling;
270
271	if (fLastChild == layer)
272		fLastChild = layer->fPreviousSibling;
273
274	// Take care of siblings
275	if (layer->fPreviousSibling != NULL)
276		layer->fPreviousSibling->fNextSibling	= layer->fNextSibling;
277
278	if (layer->fNextSibling != NULL)
279		layer->fNextSibling->fPreviousSibling = layer->fPreviousSibling;
280
281	layer->fPreviousSibling = NULL;
282	layer->fNextSibling = NULL;
283
284#ifdef NEW_CLIPPING
285	layer->clear_visible_regions();
286#endif
287
288	// 2) Iterate over all of the removed-layer's descendants and unset the
289	//	root layer, server window, and all redraw-related regions
290
291	Layer* c = layer; //c = short for: current
292	Layer* stop = layer;
293
294	while (true) {
295		// action block
296		{
297			// 2.1) set the RootLayer for this object.
298			c->SetRootLayer(NULL);
299			// 2.2) this Layer must know if it has a ServerWindow object attached.
300			c->fServerWin = NULL;
301			// 2.3) we were removed from the main tree so clear our full region.
302#ifndef NEW_CLIPPING
303			c->fFull.MakeEmpty();
304			// 2.4) clear fullVisible region.
305			c->fFullVisible.MakeEmpty();
306			// 2.5) we don't have a visible region anymore.
307			c->fVisible.MakeEmpty();
308#endif
309		}
310
311		// tree parsing algorithm
312		if (c->fFirstChild) {
313			// go deep
314			c = c->fFirstChild;
315		} else {
316			// go right or up
317			if (c == stop) // out trip is over
318				break;
319
320			if (c->fNextSibling) {
321				// go right
322				c = c->fNextSibling;
323			} else {
324				// go up
325				while(!c->fParent->fNextSibling && c->fParent != stop)
326					c = c->fParent;
327
328				if (c->fParent == stop) // that enough!
329					break;
330
331				c = c->fParent->fNextSibling;
332			}
333		}
334	}
335	STRACE(("Layer(%s)::RemoveChild(%s) END\n", Name(), layer->Name()));
336}
337
338//! Removes the calling layer from the tree
339void
340Layer::RemoveSelf()
341{
342	// A Layer removes itself from the tree (duh)
343	if (fParent == NULL) {
344		printf("ERROR: RemoveSelf(): Layer doesn't have a parent\n");
345		return;
346	}
347	fParent->RemoveChild(this);
348}
349
350/*!
351	\return true if the child is owned by this Layer, false if not
352*/
353bool
354Layer::HasChild(Layer* layer)
355{
356	for (Layer* child = FirstChild(); child; child = NextChild()) {
357		if (child == layer)
358			return true;
359	}
360	return false;
361}
362
363//! Returns the number of children
364uint32
365Layer::CountChildren() const
366{
367	uint32 count = 0;
368	Layer* child = FirstChild();
369	while (child != NULL) {
370		child = NextChild();
371		count++;
372	}
373	return count;
374}
375
376/*!
377	\brief Finds a child of the caller based on its token ID
378	\param token ID of the layer to find
379	\return Pointer to the layer or NULL if not found
380*/
381Layer*
382Layer::FindLayer(const int32 token)
383{
384	// (recursive) search for a layer based on its view token
385
386	// iterate only over direct child layers first
387	for (Layer* child = FirstChild(); child; child = NextChild()) {
388		if (child->fViewToken == token)
389			return child;
390	}
391
392	// try a recursive search
393	for (Layer* child = FirstChild(); child; child = NextChild()) {
394		if (Layer* layer = child->FindLayer(token))
395			return layer;
396	}
397
398	return NULL;
399}
400
401/*!
402	\brief Returns the layer at the given point
403	\param pt The point to look the layer at
404	\return The layer containing the point or NULL if no layer found
405*/
406Layer*
407Layer::LayerAt(const BPoint &pt, bool recursive)
408{
409	//printf("%p:%s:LayerAt(x = %g, y = %g)\n", this, Name(), pt.x, pt.y);
410	if (!recursive)	{
411		if (VisibleRegion().Contains(pt))
412			return this;
413
414		for (Layer* child = LastChild(); child; child = PreviousChild())
415			if (child->FullVisible().Contains(pt))
416				return child;
417
418		return NULL;
419	}
420
421#ifndef NEW_CLIPPING
422	if (fVisible.Contains(pt))
423		return this;
424
425	if (fFullVisible.Contains(pt)) {
426		for (Layer* child = LastChild(); child; child = PreviousChild()) {
427			if (Layer* layer = child->LayerAt(pt))
428				return layer;
429		}
430	}
431#else
432	if (fVisible2.Contains(pt))
433		return this;
434
435	if (fFullVisible2.Contains(pt)) {
436		for (Layer* child = LastChild(); child; child = PreviousChild()) {
437			if (Layer* layer = child->LayerAt(pt))
438				return layer;
439		}
440	}
441#endif
442	return NULL;
443}
444
445// FirstChild
446Layer*
447Layer::FirstChild() const
448{
449	fCurrent = fFirstChild;
450	return fCurrent;
451}
452
453// NextChild
454Layer*
455Layer::NextChild() const
456{
457	fCurrent = fCurrent->fNextSibling;
458	return fCurrent;
459}
460
461// PreviousChild
462Layer*
463Layer::PreviousChild() const
464{
465	fCurrent = fCurrent->fPreviousSibling;
466	return fCurrent;
467}
468
469// LastChild
470Layer*
471Layer::LastChild() const
472{
473	fCurrent = fLastChild;
474	return fCurrent;
475}
476
477// SetName
478void
479Layer::SetName(const char* name)
480{
481	fName.SetTo(name);
482}
483
484// SetFlags
485void
486Layer::SetFlags(uint32 flags)
487{
488	fFlags = flags;
489	fLayerData->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
490}
491
492#ifndef NEW_CLIPPING
493
494//! Rebuilds the layer's "completely visible" region
495void
496Layer::RebuildFullRegion(void)
497{
498	STRACE(("Layer(%s)::RebuildFullRegion()\n", Name()));
499
500	if (fParent)
501		fFull.Set(fParent->ConvertToTop(fFrame ));
502	else
503		fFull.Set(fFrame);
504
505	// TODO: restrict to screen coordinates
506
507	// TODO: Convert to screen coordinates
508
509	LayerData *ld;
510	ld = fLayerData;
511	do {
512		// clip to user region
513		if (const BRegion* userClipping = ld->ClippingRegion())
514			fFull.IntersectWith(userClipping);
515
516	} while ((ld = ld->prevState));
517}
518
519// StartRebuildRegions
520void
521Layer::StartRebuildRegions( const BRegion& reg, Layer *target, uint32 action, BPoint& pt)
522{
523	STRACE(("Layer(%s)::StartRebuildRegions() START\n", Name()));
524	RBTRACE(("\n\nLayer(%s)::StartRebuildRegions() START\n", Name()));
525	if (!fParent)
526		fFullVisible = fFull;
527
528	BRegion oldVisible = fVisible;
529
530	fVisible = fFullVisible;
531
532	// Rebuild regions for children...
533	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
534		if (lay == target)
535			lay->RebuildRegions(reg, action, pt, BPoint(0.0f, 0.0f));
536		else
537			lay->RebuildRegions(reg, B_LAYER_NONE, pt, BPoint(0.0f, 0.0f));
538	}
539
540	#ifdef DEBUG_LAYER_REBUILD
541		printf("\nSRR: Layer(%s) ALMOST done regions:\n", Name());
542		printf("\tVisible Region:\n");
543		fVisible.PrintToStream();
544		printf("\tFull Visible Region:\n");
545		fFullVisible.PrintToStream();
546	#endif
547
548	BRegion redrawReg(fVisible);
549
550	// if this is the first time
551	if (oldVisible.CountRects() > 0)
552		redrawReg.Exclude(&oldVisible);
553
554	if (redrawReg.CountRects() > 0)
555		fRootLayer->fRedrawReg.Include(&redrawReg);
556
557	#ifdef DEBUG_LAYER_REBUILD
558		printf("\nLayer(%s)::StartRebuildRegions() DONE. Results:\n", Name());
559		printf("\tRedraw Region:\n");
560		fRootLayer->fRedrawReg.PrintToStream();
561		printf("\tCopy Region:\n");
562		for (int32 k=0; k<fRootLayer->fCopyRegList.CountItems(); k++) {
563			((BRegion*)(fRootLayer->fCopyRegList.ItemAt(k)))->PrintToStream();
564			((BPoint*)(fRootLayer->fCopyList.ItemAt(k)))->PrintToStream();
565		}
566		printf("\n");
567	#endif
568
569	STRACE(("Layer(%s)::StartRebuildRegions() END\n", Name()));
570	RBTRACE(("Layer(%s)::StartRebuildRegions() END\n", Name()));
571}
572
573// RebuildRegions
574void
575Layer::RebuildRegions( const BRegion& reg, uint32 action, BPoint pt, BPoint ptOffset)
576{
577	STRACE(("Layer(%s)::RebuildRegions() START\n", Name()));
578
579	// TODO:/NOTE: this method must be executed as quickly as possible.
580
581	// Currently SendView[Moved/Resized]Msg() simply constructs a message and calls
582	// ServerWindow::SendMessageToClient(). This involves the alternative use of
583	// kernel and this code in the CPU, so there are a lot of context switches.
584	// This is NOT good at all!
585
586	// One alternative would be the use of a BMessageQueue per ServerWindows OR only
587	// one for app_server which will be emptied as soon as this critical operation ended.
588	// Talk to DW, Gabe.
589
590	BRegion	oldRegion;
591	uint32 newAction = action;
592	BPoint newPt = pt;
593	BPoint newOffset = ptOffset; // used for resizing only
594
595	BPoint dummyNewLocation;
596
597	RRLabel1:
598	switch(action) {
599		case B_LAYER_NONE: {
600			RBTRACE(("1) Layer(%s): Action B_LAYER_NONE\n", Name()));
601			STRACE(("1) Layer(%s): Action B_LAYER_NONE\n", Name()));
602			oldRegion = fVisible;
603			break;
604		}
605		case B_LAYER_MOVE: {
606			RBTRACE(("1) Layer(%s): Action B_LAYER_MOVE\n", Name()));
607			STRACE(("1) Layer(%s): Action B_LAYER_MOVE\n", Name()));
608			oldRegion = fFullVisible;
609			fFrame.OffsetBy(pt.x, pt.y);
610			fFull.OffsetBy(pt.x, pt.y);
611
612			// TODO: investigate combining frame event messages for efficiency
613			//SendViewMovedMsg();
614			AddToViewsWithInvalidCoords();
615
616			newAction	= B_LAYER_SIMPLE_MOVE;
617			break;
618		}
619		case B_LAYER_SIMPLE_MOVE: {
620			RBTRACE(("1) Layer(%s): Action B_LAYER_SIMPLE_MOVE\n", Name()));
621			STRACE(("1) Layer(%s): Action B_LAYER_SIMPLE_MOVE\n", Name()));
622			fFull.OffsetBy(pt.x, pt.y);
623
624			break;
625		}
626		case B_LAYER_RESIZE: {
627			RBTRACE(("1) Layer(%s): Action B_LAYER_RESIZE\n", Name()));
628			STRACE(("1) Layer(%s): Action B_LAYER_RESIZE\n", Name()));
629			oldRegion	= fVisible;
630
631			fFrame.right	+= pt.x;
632			fFrame.bottom	+= pt.y;
633			RebuildFullRegion();
634
635			// TODO: investigate combining frame event messages for efficiency
636			//SendViewResizedMsg();
637			AddToViewsWithInvalidCoords();
638
639			newAction = B_LAYER_MASK_RESIZE;
640			break;
641		}
642		case B_LAYER_MASK_RESIZE: {
643			RBTRACE(("1) Layer(%s): Action B_LAYER_MASK_RESIZE\n", Name()));
644			STRACE(("1) Layer(%s): Action B_LAYER_MASK_RESIZE\n", Name()));
645			oldRegion = fVisible;
646
647			BPoint offset, rSize;
648			BPoint coords[2];
649
650			ResizeOthers(pt.x, pt.y, coords, NULL);
651			offset = coords[0];
652			rSize = coords[1];
653			newOffset = offset + ptOffset;
654
655			if (!(rSize.x == 0.0f && rSize.y == 0.0f)) {
656				fFrame.OffsetBy(offset);
657				fFrame.right += rSize.x;
658				fFrame.bottom += rSize.y;
659				RebuildFullRegion();
660
661				// TODO: investigate combining frame event messages for efficiency
662				//SendViewResizedMsg();
663				AddToViewsWithInvalidCoords();
664
665				newAction = B_LAYER_MASK_RESIZE;
666				newPt = rSize;
667				dummyNewLocation = newOffset;
668			} else {
669				if (!(offset.x == 0.0f && offset.y == 0.0f)) {
670					pt = newOffset;
671					action = B_LAYER_MOVE;
672					newPt = pt;
673					goto RRLabel1;
674				} else {
675					pt = ptOffset;
676					action = B_LAYER_MOVE;
677					newPt = pt;
678					goto RRLabel1;
679				}
680			}
681			break;
682		}
683	}
684
685	if (!IsHidden()) {
686		#ifdef DEBUG_LAYER_REBUILD
687			printf("Layer(%s) real action START\n", Name());
688			fFull.PrintToStream();
689		#endif
690		fFullVisible.MakeEmpty();
691		fVisible = fFull;
692
693		if (fParent && fVisible.CountRects() > 0) {
694			// not the usual case, but support fot this is needed.
695			if (fParent->fAdFlags & B_LAYER_CHILDREN_DEPENDANT) {
696				#ifdef DEBUG_LAYER_REBUILD
697					printf("   B_LAYER_CHILDREN_DEPENDANT Parent\n");
698				#endif
699
700				// because we're skipping one level, we need to do out
701				// parent business as well.
702
703				// our visible area is relative to our parent's parent.
704				if (fParent->fParent)
705					fVisible.IntersectWith(&(fParent->fParent->fVisible));
706
707				// exclude parent's visible area which could be composed by
708				// prior siblings' visible areas.
709				if (fVisible.CountRects() > 0)
710					fVisible.Exclude(&(fParent->fVisible));
711
712				// we have a final visible area. Include it to our parent's one,
713				// exclude from parent's parent.
714				if (fVisible.CountRects() > 0) {
715					fParent->fFullVisible.Include(&fVisible);
716
717					if (fParent->fParent)
718						fParent->fParent->fVisible.Exclude(&fVisible);
719				}
720			} else {
721				// for 95+% of cases
722
723				#ifdef DEBUG_LAYER_REBUILD
724					printf("   (!)B_LAYER_CHILDREN_DEPENDANT Parent\n");
725				#endif
726
727				// the visible area is the one common with parent's one.
728				fVisible.IntersectWith(&(fParent->fVisible));
729
730				// exclude from parent's visible area. we're the owners now.
731				if (fVisible.CountRects() > 0)
732					fParent->fVisible.Exclude(&fVisible);
733			}
734		}
735		fFullVisible = fVisible;
736	}
737
738	// Rebuild regions for children...
739	for(Layer *lay = LastChild(); lay != NULL; lay = PreviousChild())
740		lay->RebuildRegions(reg, newAction, newPt, newOffset);
741
742	#ifdef DEBUG_LAYER_REBUILD
743		printf("\nLayer(%s) ALMOST done regions:\n", Name());
744		printf("\tVisible Region:\n");
745		fVisible.PrintToStream();
746		printf("\tFull Visible Region:\n");
747		fFullVisible.PrintToStream();
748	#endif
749
750	if(!IsHidden()) {
751		switch(action) {
752			case B_LAYER_NONE: {
753				RBTRACE(("2) Layer(%s): Action B_LAYER_NONE\n", Name()));
754				BRegion r(fVisible);
755				if (oldRegion.CountRects() > 0)
756					r.Exclude(&oldRegion);
757
758				if(r.CountRects() > 0)
759					fRootLayer->fRedrawReg.Include(&r);
760				break;
761			}
762			case B_LAYER_MOVE: {
763				RBTRACE(("2) Layer(%s): Action B_LAYER_MOVE\n", Name()));
764				BRegion redrawReg;
765				BRegion	*copyReg = new BRegion();
766				BRegion	screenReg(fRootLayer->Bounds());
767
768				oldRegion.OffsetBy(pt.x, pt.y);
769				oldRegion.IntersectWith(&fFullVisible);
770
771				*copyReg = oldRegion;
772				copyReg->IntersectWith(&screenReg);
773				if (copyReg->CountRects() > 0 && !(pt.x == 0.0f && pt.y == 0.0f)) {
774					copyReg->OffsetBy(-pt.x, -pt.y);
775					BPoint		*point = new BPoint(pt);
776					fRootLayer->fCopyRegList.AddItem(copyReg);
777					fRootLayer->fCopyList.AddItem(point);
778				} else {
779					delete copyReg;
780				}
781
782				redrawReg	= fFullVisible;
783				redrawReg.Exclude(&oldRegion);
784				if (redrawReg.CountRects() > 0 && !(pt.x == 0.0f && pt.y == 0.0f)) {
785					fRootLayer->fRedrawReg.Include(&redrawReg);
786				}
787
788				break;
789			}
790			case B_LAYER_RESIZE: {
791				RBTRACE(("2) Layer(%s): Action B_LAYER_RESIZE\n", Name()));
792				BRegion redrawReg;
793
794				redrawReg = fVisible;
795				redrawReg.Exclude(&oldRegion);
796				if(redrawReg.CountRects() > 0)
797					fRootLayer->fRedrawReg.Include(&redrawReg);
798
799				break;
800			}
801			case B_LAYER_MASK_RESIZE: {
802				RBTRACE(("2) Layer(%s): Action B_LAYER_MASK_RESIZE\n", Name()));
803				BRegion redrawReg;
804				BRegion	*copyReg = new BRegion();
805
806				oldRegion.OffsetBy(dummyNewLocation.x, dummyNewLocation.y);
807
808				redrawReg	= fVisible;
809				redrawReg.Exclude(&oldRegion);
810				if (redrawReg.CountRects() > 0)
811					fRootLayer->fRedrawReg.Include(&redrawReg);
812
813				*copyReg = fVisible;
814				copyReg->IntersectWith(&oldRegion);
815				copyReg->OffsetBy(-dummyNewLocation.x, -dummyNewLocation.y);
816				if (copyReg->CountRects() > 0
817					&& !(dummyNewLocation.x == 0.0f && dummyNewLocation.y == 0.0f)) {
818					fRootLayer->fCopyRegList.AddItem(copyReg);
819					fRootLayer->fCopyList.AddItem(new BPoint(dummyNewLocation));
820				}
821
822				break;
823			}
824			default:
825				RBTRACE(("2) Layer(%s): Action default\n", Name()));
826				break;
827		}
828	}
829/*	if (IsHidden()) {
830		fFullVisible.MakeEmpty();
831		fVisible.MakeEmpty();
832	}
833*/
834
835	STRACE(("Layer(%s)::RebuildRegions() END\n", Name()));
836}
837
838// ResizeOthers
839uint32
840Layer::ResizeOthers(float x, float y, BPoint coords[], BPoint *ptOffset)
841{
842	STRACE(("Layer(%s)::ResizeOthers() START\n", Name()));
843	uint32 rmask = fResizeMode;
844
845	// offset
846	coords[0].x	= 0.0f;
847	coords[0].y	= 0.0f;
848
849	// resize by width/height
850	coords[1].x	= 0.0f;
851	coords[1].y	= 0.0f;
852
853	if ((rmask & 0x00000f00UL)>>8 == _VIEW_LEFT_ &&
854		(rmask & 0x0000000fUL)>>0 == _VIEW_RIGHT_) {
855		coords[1].x		= x;
856	} else if ((rmask & 0x00000f00UL)>>8 == _VIEW_LEFT_) {
857	} else if ((rmask & 0x0000000fUL)>>0 == _VIEW_RIGHT_) {
858		coords[0].x		= x;
859	} else if ((rmask & 0x00000f00UL)>>8 == _VIEW_CENTER_) {
860		coords[0].x		= x/2;
861	} else {
862		// illegal flag. Do nothing.
863	}
864
865
866	if ((rmask & 0x0000f000UL)>>12 == _VIEW_TOP_ &&
867		(rmask & 0x000000f0UL)>>4 == _VIEW_BOTTOM_) {
868		coords[1].y		= y;
869	} else if ((rmask & 0x0000f000UL)>>12 == _VIEW_TOP_) {
870	} else if ((rmask & 0x000000f0UL)>>4 == _VIEW_BOTTOM_) {
871		coords[0].y		= y;
872	} else if ((rmask & 0x0000f000UL)>>12 == _VIEW_CENTER_) {
873		coords[0].y		= y/2;
874	} else {
875		// illegal flag. Do nothing.
876	}
877
878	STRACE(("Layer(%s)::ResizeOthers() END\n", Name()));
879	return 0UL;
880}
881
882#endif
883
884// Redraw
885void
886Layer::Redraw(const BRegion& reg, Layer *startFrom)
887{
888	STRACE(("Layer(%s)::Redraw();\n", Name()));
889	if (IsHidden())
890		// this layer has nothing visible on screen, so bail out.
891		return;
892
893	BRegion *pReg = const_cast<BRegion*>(&reg);
894
895	if (pReg->CountRects() > 0)
896		RequestDraw(reg, startFrom);
897
898	STRACE(("Layer(%s)::Redraw() ENDED\n", Name()));
899}
900
901// Draw
902void
903Layer::Draw(const BRect &rect)
904{
905#ifdef DEBUG_LAYER
906	printf("Layer(%s)::Draw: ", Name());
907	rect.PrintToStream();
908#endif
909
910	if (!ViewColor().IsTransparentMagic())
911		fDriver->FillRect(rect, ViewColor());
912}
913
914#ifndef NEW_CLIPPING
915// EmptyGlobals
916void
917Layer::EmptyGlobals()
918{
919	fRootLayer->fRedrawReg.MakeEmpty();
920
921	int32 count = fRootLayer->fCopyRegList.CountItems();
922	for (int32 i = 0; i < count; i++)
923		delete (BRegion*)fRootLayer->fCopyRegList.ItemAt(i);
924	fRootLayer->fCopyRegList.MakeEmpty();
925
926	count = fRootLayer->fCopyList.CountItems();
927	for (int32 i = 0; i < count; i++)
928		delete (BPoint*)fRootLayer->fCopyList.ItemAt(i);
929	fRootLayer->fCopyList.MakeEmpty();
930}
931#endif
932
933/*!
934	\brief Shows the layer
935	\param invalidate Invalidate the region when showing the layer. defaults to true
936*/
937void
938Layer::Show(bool invalidate)
939{
940	STRACE(("Layer(%s)::Show()\n", Name()));
941	if(!IsHidden()) {
942		// an ancestor may be hidden. OK, we're not visible,
943		// but we're changing our visibility state
944		fHidden	= false;
945		return;
946	}
947
948	fHidden	= false;
949
950	SendViewCoordUpdateMsg();
951
952// NOTE: I added this here and it solves the invalid region problem
953// for Windows that have been resized before they were shown. -Stephan
954#ifndef NEW_CLIPPING
955RebuildFullRegion();
956
957	if (invalidate)
958		GetRootLayer()->GoInvalidate(this, fFull);
959#else
960	if (invalidate) {
961		// compute the region this layer wants for itself
962		BRegion	invalidRegion;
963		get_user_regions(invalidRegion);
964		if (invalidRegion.CountRects() > 0)
965			GetRootLayer()->GoInvalidate(this, invalidRegion);
966	}
967#endif
968}
969
970/*!
971	\brief Shows the layer
972	\param invalidate Invalidate the region when hiding the layer. defaults to true
973*/
974void
975Layer::Hide(bool invalidate)
976{
977	STRACE(("Layer(%s)::Hide()\n", Name()));
978	if (IsHidden()) {
979		// an ancestor may be hidden. OK, we're not visible,
980		// but we're changing our visibility state
981		fHidden	= true;
982		return;
983	}
984
985	fHidden	= true;
986#ifndef NEW_CLIPPING
987	if (invalidate)
988		GetRootLayer()->GoInvalidate(this, fFullVisible);
989#else
990	if (invalidate && fFullVisible2.CountRects() > 0) {
991		GetRootLayer()->GoInvalidate(this, fFullVisible2);
992	}
993#endif
994}
995
996//! Returns true if the layer is hidden
997bool
998Layer::IsHidden(void) const
999{
1000	if (fHidden)
1001		return true;
1002
1003	if (fParent)
1004			return fParent->IsHidden();
1005
1006	return fHidden;
1007}
1008
1009
1010void
1011Layer::PushState()
1012{
1013	LayerData *data = new LayerData(fLayerData);
1014	fLayerData = data;
1015
1016	fLayerData->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
1017}
1018
1019
1020void
1021Layer::PopState()
1022{
1023	if (fLayerData->prevState == NULL) {
1024		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), but there is NO state on stack!\n", Name());
1025		return;
1026	}
1027
1028	LayerData *data = fLayerData;
1029	fLayerData = fLayerData->prevState;
1030	data->prevState = NULL;
1031	delete data;
1032
1033	fLayerData->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
1034}
1035
1036
1037//! Matches the BView call of the same name
1038BRect
1039Layer::Bounds(void) const
1040{
1041	BRect r(fFrame);
1042//	r.OffsetTo(fBoundsLeftTop);
1043	r.OffsetTo(BoundsOrigin());
1044	return r;
1045}
1046
1047//! Matches the BView call of the same name
1048BRect
1049Layer::Frame(void) const
1050{
1051	return fFrame;
1052}
1053
1054//! Moves the layer by specified values, complete with redraw
1055void
1056Layer::MoveBy(float x, float y)
1057{
1058	STRACE(("Layer(%s)::MoveBy() START\n", Name()));
1059	if (!fParent) {
1060		CRITICAL("ERROR: in Layer::MoveBy()! - No parent!\n");
1061		return;
1062	}
1063
1064	BPrivate::PortLink msg(-1, -1);
1065	msg.StartMessage(AS_ROOTLAYER_LAYER_MOVE);
1066	msg.Attach<Layer*>(this);
1067	msg.Attach<float>(x);
1068	msg.Attach<float>(y);
1069	GetRootLayer()->EnqueueMessage(msg);
1070
1071	STRACE(("Layer(%s)::MoveBy() END\n", Name()));
1072}
1073
1074//! Resize the layer by the specified amount, complete with redraw
1075void
1076Layer::ResizeBy(float x, float y)
1077{
1078	STRACE(("Layer(%s)::ResizeBy() START\n", Name()));
1079
1080	if (!fParent) {
1081		printf("ERROR: in Layer::ResizeBy()! - No parent!\n");
1082		return;
1083	}
1084
1085	BPrivate::PortLink msg(-1, -1);
1086	msg.StartMessage(AS_ROOTLAYER_LAYER_RESIZE);
1087	msg.Attach<Layer*>(this);
1088	msg.Attach<float>(x);
1089	msg.Attach<float>(y);
1090	GetRootLayer()->EnqueueMessage(msg);
1091
1092	STRACE(("Layer(%s)::ResizeBy() END\n", Name()));
1093}
1094
1095//! scrolls the layer by the specified amount, complete with redraw
1096void
1097Layer::ScrollBy(float x, float y)
1098{
1099	STRACE(("Layer(%s)::ScrollBy() START\n", Name()));
1100
1101	BPrivate::PortLink msg(-1, -1);
1102	msg.StartMessage(AS_ROOTLAYER_LAYER_SCROLL);
1103	msg.Attach<Layer*>(this);
1104	msg.Attach<float>(x);
1105	msg.Attach<float>(y);
1106	GetRootLayer()->EnqueueMessage(msg);
1107
1108	STRACE(("Layer(%s)::ScrollBy() END\n", Name()));
1109}
1110#ifdef NEW_INPUT_HANDLING
1111void
1112Layer::MouseDown(const PointerEvent& evt)
1113{
1114	if (Window() && !IsTopLayer()) {
1115		BMessage msg;
1116		msg.what = B_MOUSE_DOWN;
1117		msg.AddInt64("when", evt.when);
1118		msg.AddPoint("where", evt.where);
1119		msg.AddInt32("modifiers", evt.modifiers);
1120		msg.AddInt32("buttons", evt.buttons);
1121		msg.AddInt32("clicks", evt.clicks);
1122
1123		Window()->SendMessageToClient(&msg, fViewToken, false);
1124	}
1125}
1126
1127void
1128Layer::MouseUp(const PointerEvent& evt)
1129{
1130	if (Window() && !IsTopLayer()) {
1131		BMessage upmsg(B_MOUSE_UP);
1132		upmsg.AddInt64("when",evt.when);
1133		upmsg.AddPoint("where",evt.where);
1134		upmsg.AddInt32("modifiers",evt.modifiers);
1135
1136		Window()->SendMessageToClient(&upmsg, fViewToken, false);
1137	}
1138}
1139
1140void
1141Layer::MouseMoved(const PointerEvent& evt, uint32 transit)
1142{
1143	if (Window() && !IsTopLayer()) {
1144		BMessage movemsg(B_MOUSE_MOVED);
1145		movemsg.AddInt64("when", evt.when);
1146		movemsg.AddPoint("where", evt.where);
1147		movemsg.AddInt32("buttons", evt.buttons);
1148		movemsg.AddInt32("transit", transit);
1149
1150		Window()->SendMessageToClient(&movemsg, fViewToken, false);
1151	}
1152}
1153void
1154Layer::WorkspaceActivated(int32 index, bool active)
1155{
1156	// Empty
1157}
1158#endif
1159// BoundsOrigin
1160BPoint
1161Layer::BoundsOrigin() const
1162{
1163	BPoint origin(0,0);
1164	float scale = Scale();
1165
1166	LayerData *ld = fLayerData;
1167	do {
1168		origin += ld->Origin();
1169	} while ((ld = ld->prevState));
1170
1171	origin.x *= scale;
1172	origin.y *= scale;
1173
1174	return origin;
1175}
1176
1177float
1178Layer::Scale() const
1179{
1180	float scale = 1.0f;
1181
1182	LayerData *ld = fLayerData;
1183	do {
1184		scale *= ld->Scale();
1185	} while ((ld = ld->prevState));
1186
1187	return scale;
1188}
1189
1190//! Converts the passed point to parent coordinates
1191BPoint
1192Layer::ConvertToParent(BPoint pt)
1193{
1194#ifndef NEW_CLIPPING
1195	pt -= BoundsOrigin();
1196	pt += fFrame.LeftTop();
1197	return pt;
1198#else
1199	ConvertToParent2(&pt);
1200	return pt;
1201#endif
1202}
1203
1204//! Converts the passed rectangle to parent coordinates
1205BRect
1206Layer::ConvertToParent(BRect rect)
1207{
1208#ifndef NEW_CLIPPING
1209//	rect.OffsetBy(fFrame.LeftTop());
1210//	return rect;
1211	rect.OffsetBy(-BoundsOrigin().x, -BoundsOrigin().y);
1212	rect.OffsetBy(fFrame.LeftTop());
1213	return rect;
1214#else
1215	ConvertToParent2(&rect);
1216	return rect;
1217#endif
1218}
1219
1220//! Converts the passed region to parent coordinates
1221BRegion
1222Layer::ConvertToParent(BRegion* reg)
1223{
1224#ifndef NEW_CLIPPING
1225	// TODO: wouldn't it be more efficient to use the copy
1226	// constructor for BRegion and then call OffsetBy()?
1227	BRegion newreg;
1228	for (int32 i = 0; i < reg->CountRects(); i++)
1229		newreg.Include(ConvertToParent(reg->RectAt(i)));
1230	return newreg;
1231#else
1232	BRegion newReg(*reg);
1233	ConvertToParent2(&newReg);
1234	return newReg;
1235#endif
1236}
1237
1238//! Converts the passed point from parent coordinates
1239BPoint
1240Layer::ConvertFromParent(BPoint pt)
1241{
1242#ifndef NEW_CLIPPING
1243//	return pt - fFrame.LeftTop();
1244	pt -= fFrame.LeftTop();
1245	pt += BoundsOrigin();
1246	return pt;
1247#else
1248	ConvertFromParent2(&pt);
1249	return pt;
1250#endif
1251}
1252
1253//! Converts the passed rectangle from parent coordinates
1254BRect
1255Layer::ConvertFromParent(BRect rect)
1256{
1257#ifndef NEW_CLIPPING
1258//	rect.OffsetBy(-fFrame.left, -fFrame.top);
1259//	return rect;
1260	rect.OffsetBy(-fFrame.left, -fFrame.top);
1261	rect.OffsetBy(BoundsOrigin());
1262	return rect;
1263#else
1264	ConvertFromParent2(&rect);
1265	return rect;
1266#endif
1267}
1268
1269//! Converts the passed region from parent coordinates
1270BRegion
1271Layer::ConvertFromParent(BRegion *reg)
1272{
1273#ifndef NEW_CLIPPING
1274	BRegion newreg;
1275	for(int32 i=0; i<reg->CountRects();i++)
1276		newreg.Include(ConvertFromParent(reg->RectAt(i)));
1277	return newreg;
1278#else
1279	BRegion newReg(*reg);
1280	ConvertFromParent2(&newReg);
1281	return newReg;
1282#endif
1283}
1284
1285// ConvertToTop
1286BPoint
1287Layer::ConvertToTop(BPoint pt)
1288{
1289#ifndef NEW_CLIPPING
1290	if (fParent) {
1291//		return (fParent->ConvertToTop(pt + fFrame.LeftTop()));
1292		pt = ConvertToParent(pt);
1293		return fParent->ConvertToTop(pt);
1294	} else
1295		return pt;
1296#else
1297	ConvertToScreen2(&pt);
1298	return pt;
1299#endif
1300}
1301
1302//! Converts the passed rectangle to screen coordinates
1303BRect
1304Layer::ConvertToTop(BRect rect)
1305{
1306#ifndef NEW_CLIPPING
1307	if (fParent) {
1308//		return fParent->ConvertToTop(rect.OffsetByCopy(fFrame.LeftTop()));
1309		rect = ConvertToParent(rect);
1310		return fParent->ConvertToTop(rect);
1311	} else
1312		return rect;
1313#else
1314	ConvertToScreen2(&rect);
1315	return rect;
1316#endif
1317}
1318
1319//! Converts the passed region to screen coordinates
1320BRegion
1321Layer::ConvertToTop(BRegion *reg)
1322{
1323#ifndef NEW_CLIPPING
1324	BRegion newreg;
1325	for (int32 i = 0; i < reg->CountRects();i++)
1326		newreg.Include(ConvertToTop(reg->RectAt(i)));
1327	return newreg;
1328#else
1329	BRegion newReg(*reg);
1330	ConvertToScreen2(&newReg);
1331	return newReg;
1332#endif
1333}
1334
1335// ConvertFromTop
1336BPoint
1337Layer::ConvertFromTop(BPoint pt)
1338{
1339#ifndef NEW_CLIPPING
1340	if (fParent) {
1341//		return fParent->ConvertFromTop(pt-fFrame.LeftTop());
1342		pt = ConvertFromParent(pt);
1343		return fParent->ConvertFromTop(pt);
1344	} else
1345		return pt;
1346#else
1347	ConvertFromScreen2(&pt);
1348	return pt;
1349#endif
1350}
1351
1352//! Converts the passed rectangle from screen coordinates
1353BRect
1354Layer::ConvertFromTop(BRect rect)
1355{
1356#ifndef NEW_CLIPPING
1357	if (fParent) {
1358//		return fParent->ConvertFromTop(rect.OffsetByCopy(-fFrame.LeftTop().x,
1359//														 -fFrame.LeftTop().y));
1360		rect = ConvertFromParent(rect);
1361		return fParent->ConvertFromTop(rect);
1362	} else
1363		return rect;
1364#else
1365	ConvertFromScreen2(&rect);
1366	return rect;
1367#endif
1368}
1369
1370//! Converts the passed region from screen coordinates
1371BRegion
1372Layer::ConvertFromTop(BRegion *reg)
1373{
1374#ifndef NEW_CLIPPING
1375	BRegion newreg;
1376
1377	for (int32 i = 0; i < reg->CountRects(); i++)
1378		newreg.Include(ConvertFromTop(reg->RectAt(i)));
1379
1380	return newreg;
1381#else
1382	BRegion newReg(*reg);
1383	ConvertFromScreen2(&newReg);
1384	return newReg;
1385#endif
1386}
1387
1388//! Recursively deletes all children of the calling layer
1389void
1390Layer::PruneTree(void)
1391{
1392
1393	Layer* lay;
1394	Layer* nextlay;
1395
1396	lay = fFirstChild;
1397	fFirstChild = NULL;
1398
1399	while (lay != NULL) {
1400		if (lay->fFirstChild != NULL)
1401			lay->PruneTree();
1402
1403		nextlay = lay->fNextSibling;
1404		lay->fNextSibling = NULL;
1405
1406		delete lay;
1407		lay = nextlay;
1408	}
1409	// Man, this thing is short. Elegant, ain't it? :P
1410}
1411
1412//! Prints information about the layer's current state
1413void
1414Layer::PrintToStream()
1415{
1416	printf("\n *** Layer %s:\n", Name());
1417	printf("\t Parent: %s", fParent ? fParent->Name() : "<no parent>");
1418
1419	printf("\t us: %s\t ls: %s\n",
1420		fPreviousSibling ? fPreviousSibling->Name() : "<none>",
1421		fNextSibling ? fNextSibling->Name() : "<none>");
1422
1423	printf("\t topChild: %s\t bottomChild: %s\n",
1424		fFirstChild ? fFirstChild->Name() : "<none>",
1425		fLastChild ? fLastChild->Name() : "<none>");
1426
1427	printf("Frame: (%f, %f, %f, %f)\n", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
1428	printf("LocalOrigin: (%f, %f)\n", BoundsOrigin().x, BoundsOrigin().y);
1429	printf("Token: %ld\n", fViewToken);
1430	printf("Hidden - direct: %s ", fHidden?"true":"false");
1431	printf("Hidden - indirect: %s\n", IsHidden()?"true":"false");
1432	printf("ResizingMode: %lx ", fResizeMode);
1433	printf("Flags: %lx\n", fFlags);
1434
1435	if (fLayerData)
1436		fLayerData->PrintToStream();
1437	else
1438		printf(" NO LayerData valid pointer\n");
1439}
1440
1441//! Prints pointer info kept by the current layer
1442void
1443Layer::PrintNode()
1444{
1445	printf("-----------\nLayer %s\n", Name());
1446	if (fParent)
1447		printf("Parent: %s (%p)\n", fParent->Name(), fParent);
1448	else
1449		printf("Parent: NULL\n");
1450
1451	if (fPreviousSibling)
1452		printf("Upper sibling: %s (%p)\n", fPreviousSibling->Name(), fPreviousSibling);
1453	else
1454		printf("Upper sibling: NULL\n");
1455
1456	if (fNextSibling)
1457		printf("Lower sibling: %s (%p)\n", fNextSibling->Name(), fNextSibling);
1458	else
1459		printf("Lower sibling: NULL\n");
1460
1461	if (fFirstChild)
1462		printf("Top child: %s (%p)\n", fFirstChild->Name(), fFirstChild);
1463	else
1464		printf("Top child: NULL\n");
1465
1466	if (fLastChild)
1467		printf("Bottom child: %s (%p)\n", fLastChild->Name(), fLastChild);
1468	else
1469		printf("Bottom child: NULL\n");
1470#ifndef NEW_CLIPPING
1471	printf("Visible Areas: "); fVisible.PrintToStream();
1472#endif
1473}
1474
1475//! Prints the tree hierarchy from the current layer down
1476void
1477Layer::PrintTree()
1478{
1479	printf("\n Tree structure:\n");
1480	printf("\t%s\t%s\n", Name(), IsHidden()? "Hidden": "NOT hidden");
1481	for(Layer *lay = LastChild(); lay != NULL; lay = PreviousChild())
1482		printf("\t%s\t%s\n", lay->Name(), lay->IsHidden()? "Hidden": "NOT hidden");
1483}
1484
1485// RequestDraw
1486void
1487Layer::RequestDraw(const BRegion &reg, Layer *startFrom)
1488{
1489	STRACE(("Layer(%s)::RequestDraw()\n", Name()));
1490
1491	// do not redraw any child until you must
1492	int redraw = false;
1493	if (!startFrom)
1494		redraw = true;
1495
1496#ifndef NEW_CLIPPING
1497	if (HasClient() && IsTopLayer()) {
1498		// calculate the minimum region/rectangle to be updated with
1499		// a single message to the client.
1500		BRegion	updateReg(fFullVisible);
1501
1502		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1503			&& fFrameAction	== B_LAYER_ACTION_RESIZE)
1504		{
1505			// do nothing
1506		} else {
1507			updateReg.IntersectWith(&reg);
1508		}
1509		if (updateReg.CountRects() > 0) {
1510			fOwner->fCumulativeRegion.Include(&updateReg);
1511			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1512				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1513fOwner->cnt++;
1514if (fOwner->cnt != 1)
1515	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1516				fOwner->fCumulativeRegion.MakeEmpty();
1517				fOwner->fRequestSent = true;
1518				SendUpdateMsg(fOwner->fInUpdateRegion);
1519			}
1520		}
1521	}
1522
1523	if (fVisible.CountRects() > 0) {
1524		BRegion	updateReg(fVisible);
1525		// calculate the update region
1526		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fFrameAction == B_LAYER_ACTION_RESIZE) {
1527			// do nothing
1528		} else {
1529			updateReg.IntersectWith(&reg);
1530		}
1531
1532		if (updateReg.CountRects() > 0) {
1533			fDriver->ConstrainClippingRegion(&updateReg);
1534			Draw(updateReg.Frame());
1535			fDriver->ConstrainClippingRegion(NULL);
1536		}
1537	}
1538
1539	for (Layer *lay = LastChild(); lay != NULL; lay = PreviousChild()) {
1540		if (lay == startFrom)
1541			redraw = true;
1542
1543		if (redraw && !(lay->IsHidden())) {
1544			// no need to go deeper if not even the FullVisible region intersects
1545			// Update one.
1546			BRegion common(lay->fFullVisible);
1547			common.IntersectWith(&reg);
1548
1549			if (common.CountRects() > 0)
1550				lay->RequestDraw(reg, NULL);
1551		}
1552	}
1553#else
1554	if (HasClient() && IsTopLayer()) {
1555		// calculate the minimum region/rectangle to be updated with
1556		// a single message to the client.
1557		BRegion	updateReg(fFullVisible2);
1558
1559		updateReg.IntersectWith(&reg);
1560
1561		if (updateReg.CountRects() > 0) {
1562			fOwner->fCumulativeRegion.Include(&updateReg);
1563			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1564				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1565fOwner->cnt++;
1566if (fOwner->cnt != 1)
1567	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1568				fOwner->fCumulativeRegion.MakeEmpty();
1569				fOwner->fRequestSent = true;
1570				SendUpdateMsg(fOwner->fInUpdateRegion);
1571			}
1572		}
1573	}
1574
1575	if (fVisible2.CountRects() > 0) {
1576		BRegion	updateReg(fVisible2);
1577			updateReg.IntersectWith(&reg);
1578
1579		if (updateReg.CountRects() > 0) {
1580			fDriver->ConstrainClippingRegion(&updateReg);
1581			Draw(updateReg.Frame());
1582			fDriver->ConstrainClippingRegion(NULL);
1583		}
1584	}
1585
1586	for (Layer *lay = LastChild(); lay != NULL; lay = PreviousChild()) {
1587		if (lay == startFrom)
1588			redraw = true;
1589
1590		if (redraw && !(lay->IsHidden())) {
1591			// no need to go deeper if not even the FullVisible region intersects
1592			// Update one.
1593			BRegion common(lay->fFullVisible2);
1594			common.IntersectWith(&reg);
1595
1596			if (common.CountRects() > 0)
1597				lay->RequestDraw(reg, NULL);
1598		}
1599	}
1600#endif
1601}
1602
1603#ifndef NEW_CLIPPING
1604
1605// move_layer
1606void
1607Layer::move_layer(float x, float y)
1608{
1609/*	if (fClassID == AS_WINBORDER_CLASS) {
1610		WinBorder	*wb = (WinBorder*)this;
1611		wb->fCumulativeRegion.OffsetBy(x, y);
1612		wb->fInUpdateRegion.OffsetBy(x, y);
1613		wb->fSavedForUpdateRegion.OffsetBy(x, y);
1614	}*/
1615
1616	fFrameAction = B_LAYER_ACTION_MOVE;
1617
1618	BPoint pt(x, y);
1619	BRect rect(fFull.Frame().OffsetByCopy(pt));
1620
1621if (!fParent) {
1622printf("no parent in Layer::move_layer() (%s)\n", Name());
1623fFrameAction = B_LAYER_ACTION_NONE;
1624return;
1625}
1626
1627	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_MOVE, pt);
1628
1629	fDriver->CopyRegionList(&fRootLayer->fCopyRegList,
1630							&fRootLayer->fCopyList,
1631							fRootLayer->fCopyRegList.CountItems(),
1632							&fFullVisible);
1633
1634	fParent->Redraw(fRootLayer->fRedrawReg, this);
1635
1636	// redraw workspaces layer
1637	if (dynamic_cast<WinBorder*>(this) != NULL && fRootLayer->WorkspacesLayer() != NULL) {
1638		fRootLayer->GoRedraw(fRootLayer->WorkspacesLayer(), fRootLayer->WorkspacesLayer()->fVisible);
1639	}
1640
1641	SendViewCoordUpdateMsg();
1642
1643	EmptyGlobals();
1644
1645	fFrameAction = B_LAYER_ACTION_NONE;
1646}
1647
1648// resize_layer
1649void
1650Layer::resize_layer(float x, float y)
1651{
1652	fFrameAction = B_LAYER_ACTION_RESIZE;
1653
1654	BPoint pt(x,y);
1655
1656	BRect rect(fFull.Frame());
1657	rect.right += x;
1658	rect.bottom += y;
1659
1660if (!fParent) {
1661printf("no parent in Layer::resize_layer() (%s)\n", Name());
1662fFrameAction = B_LAYER_ACTION_NONE;
1663return;
1664}
1665
1666	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_RESIZE, pt);
1667
1668	fDriver->CopyRegionList(&fRootLayer->fCopyRegList, &fRootLayer->fCopyList, fRootLayer->fCopyRegList.CountItems(), &fFullVisible);
1669
1670	fParent->Redraw(fRootLayer->fRedrawReg, this);
1671
1672	// redraw workspaces layer
1673	if (dynamic_cast<WinBorder*>(this) != NULL && fRootLayer->WorkspacesLayer() != NULL) {
1674		fRootLayer->GoRedraw(fRootLayer->WorkspacesLayer(), fRootLayer->WorkspacesLayer()->fVisible);
1675	}
1676
1677	SendViewCoordUpdateMsg();
1678
1679	EmptyGlobals();
1680
1681	fFrameAction = B_LAYER_ACTION_NONE;
1682}
1683
1684// FullInvalidate
1685void
1686Layer::FullInvalidate(const BRect &rect)
1687{
1688	FullInvalidate(BRegion(rect));
1689}
1690
1691// FullInvalidate
1692void
1693Layer::FullInvalidate(const BRegion& region)
1694{
1695	STRACE(("Layer(%s)::FullInvalidate():\n", Name()));
1696
1697#ifdef DEBUG_LAYER
1698	region.PrintToStream();
1699	printf("\n");
1700#endif
1701
1702	BPoint pt(0,0);
1703	StartRebuildRegions(region, NULL,/* B_LAYER_INVALIDATE, pt); */B_LAYER_NONE, pt);
1704
1705	Redraw(fRootLayer->fRedrawReg);
1706
1707	EmptyGlobals();
1708}
1709
1710// Invalidate
1711void
1712Layer::Invalidate(const BRegion& region)
1713{
1714	STRACE(("Layer(%s)::Invalidate():\n", Name()));
1715#ifdef DEBUG_LAYER
1716	region.PrintToStream();
1717	printf("\n");
1718#endif
1719
1720	fRootLayer->fRedrawReg	= region;
1721
1722	Redraw(fRootLayer->fRedrawReg);
1723
1724	EmptyGlobals();
1725}
1726
1727#endif // 5 methods
1728
1729
1730/*!
1731	\brief Returns the layer's ServerWindow
1732
1733	If the layer's ServerWindow has not been assigned, it attempts to find
1734	the owning ServerWindow in the tree.
1735*/
1736ServerWindow*
1737Layer::SearchForServerWindow()
1738{
1739	if (!fServerWin)
1740		fServerWin=fParent->SearchForServerWindow();
1741
1742	return fServerWin;
1743}
1744
1745//! Sends an _UPDATE_ message to the client BWindow
1746void
1747Layer::SendUpdateMsg(BRegion& reg)
1748{
1749	BMessage msg;
1750	msg.what = _UPDATE_;
1751#ifndef NEW_CLIPPING
1752	msg.AddRect("_rect", ConvertFromTop(reg.Frame()));
1753#else
1754	BRect	rect(reg.Frame());
1755	ConvertFromScreen2(&rect);
1756	msg.AddRect("_rect", rect );
1757#endif
1758	msg.AddRect("debug_rect", reg.Frame());
1759//	msg.AddInt32("_token",fViewToken);
1760
1761	fOwner->Window()->SendMessageToClient(&msg);
1762}
1763
1764// AddToViewsWithInvalidCoords
1765void
1766Layer::AddToViewsWithInvalidCoords() const
1767{
1768	if (fServerWin) {
1769		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
1770		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
1771		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
1772		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
1773	}
1774}
1775
1776// SendViewCoordUpdateMsg
1777void
1778Layer::SendViewCoordUpdateMsg() const
1779{
1780	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
1781		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
1782		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
1783	}
1784}
1785
1786// SetViewColor
1787void
1788Layer::SetViewColor(const RGBColor& color)
1789{
1790	fViewColor = color;
1791}
1792
1793// SetBackgroundBitmap
1794void
1795Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
1796{
1797	// TODO: What about reference counting?
1798	// "Release" old fBackgroundBitmap and "Aquire" new one?
1799	fBackgroundBitmap = bitmap;
1800}
1801
1802// SetOverlayBitmap
1803void
1804Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
1805{
1806	// TODO: What about reference counting?
1807	// "Release" old fOverlayBitmap and "Aquire" new one?
1808	fOverlayBitmap = bitmap;
1809}
1810
1811void
1812Layer::CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
1813
1814	BPrivate::PortLink msg(-1, -1);
1815	msg.StartMessage(AS_ROOTLAYER_LAYER_COPYBITS);
1816	msg.Attach<Layer*>(this);
1817	msg.Attach<BRect>(src);
1818	msg.Attach<BRect>(dst);
1819	msg.Attach<int32>(xOffset);
1820	msg.Attach<int32>(yOffset);
1821	GetRootLayer()->EnqueueMessage(msg);
1822}
1823
1824void
1825Layer::do_CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
1826	// NOTE: The correct behaviour is this:
1827	// * The region that is copied is the
1828	//   src rectangle, no matter if it fits
1829	//   into the dst rectangle. It is copied
1830	//   by the offset dst.LeftTop() - src.LeftTop()
1831	// * The dst rectangle is used for invalidation:
1832	//   Any area in the dst rectangle that could
1833	//   not be copied from src (because either the
1834	//   src rectangle was not big enough, or because there
1835	//   were parts cut off by the current layer clipping),
1836	//   are triggering BView::Draw() to be called
1837	//   and for these parts only.
1838
1839	// TODO: having moved this into Layer broke
1840	// offscreen windows (bitmaps)
1841	// -> move back into ServerWindow...
1842	if (!GetRootLayer())
1843		return;
1844
1845#ifndef NEW_CLIPPING
1846
1847	// the region that is going to be copied
1848	BRegion copyRegion(src);
1849	// apply the current clipping of the layer
1850
1851	copyRegion.IntersectWith(&fVisible);
1852
1853	// offset the region to the destination
1854	// and apply the current clipping there as well
1855	copyRegion.OffsetBy(xOffset, yOffset);
1856	copyRegion.IntersectWith(&fVisible);
1857
1858	// the region at the destination that needs invalidation
1859	GetRootLayer()->fRedrawReg.Set(dst);
1860	// exclude the region drawn by the copy operation
1861	GetRootLayer()->fRedrawReg.Exclude(&copyRegion);
1862	// apply the current clipping as well
1863	GetRootLayer()->fRedrawReg.IntersectWith(&fVisible);
1864
1865	// move the region back for the actual operation
1866	copyRegion.OffsetBy(-xOffset, -yOffset);
1867
1868	GetDisplayDriver()->CopyRegion(&copyRegion, xOffset, yOffset);
1869
1870	// trigger the redraw
1871	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
1872#else
1873	// the region that is going to be copied
1874	BRegion copyRegion(src);
1875	// apply the current clipping of the layer
1876
1877	copyRegion.IntersectWith(&fVisible2);
1878
1879	// offset the region to the destination
1880	// and apply the current clipping there as well
1881	copyRegion.OffsetBy(xOffset, yOffset);
1882	copyRegion.IntersectWith(&fVisible2);
1883
1884	// the region at the destination that needs invalidation
1885	GetRootLayer()->fRedrawReg.Set(dst);
1886	// exclude the region drawn by the copy operation
1887	GetRootLayer()->fRedrawReg.Exclude(&copyRegion);
1888	// apply the current clipping as well
1889	GetRootLayer()->fRedrawReg.IntersectWith(&fVisible2);
1890
1891	// move the region back for the actual operation
1892	copyRegion.OffsetBy(-xOffset, -yOffset);
1893
1894	GetDisplayDriver()->CopyRegion(&copyRegion, xOffset, yOffset);
1895
1896	// trigger the redraw
1897	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
1898#endif
1899
1900}
1901
1902#ifdef NEW_CLIPPING
1903
1904void
1905Layer::MovedByHook(float dx, float dy)
1906{
1907	if (Window() && Flags() & B_FRAME_EVENTS && !IsTopLayer()) {
1908		BMessage msg(B_VIEW_MOVED);
1909		msg.AddInt64("when", system_time());
1910		msg.AddPoint("where", Frame().LeftTop());
1911		Window()->SendMessageToClient(&msg, fViewToken, false);
1912	}
1913}
1914
1915void
1916Layer::ResizedByHook(float dx, float dy, bool automatic)
1917{
1918	if (Window() && Flags() & B_FRAME_EVENTS && !IsTopLayer()) {
1919		BMessage msg(B_VIEW_RESIZED);
1920		msg.AddInt64("when", system_time());
1921		msg.AddFloat("width", Frame().Width());
1922		msg.AddFloat("height", Frame().Height());
1923		msg.AddPoint("where", Frame().LeftTop());
1924		Window()->SendMessageToClient(&msg, fViewToken, false);
1925	}
1926}
1927
1928void
1929Layer::ScrolledByHook(float dx, float dy)
1930{
1931	// empty.
1932}
1933
1934
1935void
1936Layer::GetWantedRegion(BRegion& reg) const
1937{
1938	// this is the same as get_user_region.
1939	// because get_user_region modifies nothing.
1940	const_cast<Layer*>(this)->Layer::get_user_regions(reg);
1941}
1942
1943//! converts a point from local to parent's coordinate system
1944void
1945Layer::ConvertToParent2(BPoint* pt) const
1946{
1947	if (fParent) {
1948		BPoint origin = BoundsOrigin();
1949		pt->x -= origin.x;
1950		pt->y -= origin.y;
1951		pt->x += fFrame.left;
1952		pt->y += fFrame.top;
1953	}
1954}
1955
1956//! converts a rect from local to parent's coordinate system
1957void
1958Layer::ConvertToParent2(BRect* rect) const
1959{
1960	if (fParent) {
1961		BPoint origin = BoundsOrigin();
1962		rect->OffsetBy(-origin.x, -origin.y);
1963		rect->OffsetBy(fFrame.left, fFrame.top);
1964	}
1965}
1966
1967//! converts a region from local to parent's coordinate system
1968void
1969Layer::ConvertToParent2(BRegion* reg) const
1970{
1971	if (fParent) {
1972		BPoint origin = BoundsOrigin();
1973		reg->OffsetBy(-origin.x, -origin.y);
1974		reg->OffsetBy(fFrame.left, fFrame.top);
1975	}
1976}
1977
1978//! converts a point from parent's to local coordinate system
1979void
1980Layer::ConvertFromParent2(BPoint* pt) const
1981{
1982	if (fParent) {
1983		BPoint origin = BoundsOrigin();
1984		pt->x += origin.x;
1985		pt->y += origin.y;
1986		pt->x -= fFrame.left;
1987		pt->y -= fFrame.top;
1988	}
1989}
1990
1991//! converts a rect from parent's to local coordinate system
1992void
1993Layer::ConvertFromParent2(BRect* rect) const
1994{
1995	if (fParent) {
1996		BPoint origin = BoundsOrigin();
1997		rect->OffsetBy(origin.x, origin.y);
1998		rect->OffsetBy(-fFrame.left, -fFrame.top);
1999	}
2000}
2001
2002//! converts a region from parent's to local coordinate system
2003void
2004Layer::ConvertFromParent2(BRegion* reg) const
2005{
2006	if (fParent) {
2007		BPoint origin = BoundsOrigin();
2008		reg->OffsetBy(origin.x, origin.y);
2009		reg->OffsetBy(-fFrame.left, -fFrame.top);
2010	}
2011}
2012
2013//! converts a point from local to screen coordinate system
2014void
2015Layer::ConvertToScreen2(BPoint* pt) const
2016{
2017	if (GetRootLayer())
2018		if (fParent) {
2019			BPoint origin = BoundsOrigin();
2020			pt->x -= origin.x;
2021			pt->y -= origin.y;
2022			pt->x += fFrame.left;
2023			pt->y += fFrame.top;
2024
2025			fParent->ConvertToScreen2(pt);
2026		}
2027}
2028
2029//! converts a rect from local to screen coordinate system
2030void
2031Layer::ConvertToScreen2(BRect* rect) const
2032{
2033	if (GetRootLayer())
2034		if (fParent) {
2035			BPoint origin = BoundsOrigin();
2036			rect->OffsetBy(-origin.x, -origin.y);
2037			rect->OffsetBy(fFrame.left, fFrame.top);
2038
2039			fParent->ConvertToScreen2(rect);
2040		}
2041}
2042
2043//! converts a region from local to screen coordinate system
2044void
2045Layer::ConvertToScreen2(BRegion* reg) const
2046{
2047	if (GetRootLayer())
2048		if (fParent) {
2049			BPoint origin = BoundsOrigin();
2050			reg->OffsetBy(-origin.x, -origin.y);
2051			reg->OffsetBy(fFrame.left, fFrame.top);
2052
2053			fParent->ConvertToScreen2(reg);
2054		}
2055}
2056
2057//! converts a point from screen to local coordinate system
2058void
2059Layer::ConvertFromScreen2(BPoint* pt) const
2060{
2061	if (GetRootLayer())
2062		if (fParent) {
2063			BPoint origin = BoundsOrigin();
2064			pt->x += origin.x;
2065			pt->y += origin.y;
2066			pt->x -= fFrame.left;
2067			pt->y -= fFrame.top;
2068
2069			fParent->ConvertToScreen2(pt);
2070		}
2071}
2072
2073//! converts a rect from screen to local coordinate system
2074void
2075Layer::ConvertFromScreen2(BRect* rect) const
2076{
2077	if (GetRootLayer())
2078		if (fParent) {
2079			BPoint origin = BoundsOrigin();
2080			rect->OffsetBy(origin.x, origin.y);
2081			rect->OffsetBy(-fFrame.left, -fFrame.top);
2082
2083			fParent->ConvertFromScreen2(rect);
2084		}
2085}
2086
2087//! converts a region from screen to local coordinate system
2088void
2089Layer::ConvertFromScreen2(BRegion* reg) const
2090{
2091	if (GetRootLayer())
2092		if (fParent) {
2093			BPoint origin = BoundsOrigin();
2094			reg->OffsetBy(origin.x, origin.y);
2095			reg->OffsetBy(-fFrame.left, -fFrame.top);
2096
2097			fParent->ConvertFromScreen2(reg);
2098		}
2099}
2100
2101
2102void
2103Layer::do_Hide()
2104{
2105	fHidden = true;
2106
2107	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
2108		// save fullVisible so we know what to invalidate
2109		BRegion invalid(fFullVisible2);
2110
2111		clear_visible_regions();
2112
2113		if (invalid.Frame().IsValid())
2114			fParent->do_Invalidate(invalid, this);
2115	}
2116}
2117
2118void
2119Layer::do_Show()
2120{
2121	fHidden = false;
2122
2123	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
2124		BRegion invalid;
2125
2126		get_user_regions(invalid);
2127
2128		if (invalid.CountRects() > 0)
2129			fParent->do_Invalidate(invalid, this);
2130	}
2131}
2132
2133void
2134Layer::do_Invalidate(const BRegion &invalid, const Layer *startFrom)
2135{
2136	BRegion		localVisible(fFullVisible2);
2137	localVisible.IntersectWith(&invalid);
2138	rebuild_visible_regions(invalid, localVisible,
2139		startFrom? startFrom: LastChild());
2140
2141	// add localVisible to our RootLayer's redraw region.
2142//	GetRootLayer()->fRedrawReg.Include(&localVisible);
2143	GetRootLayer()->fRedrawReg = localVisible;
2144	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2145//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2146}
2147
2148void
2149Layer::do_Redraw(const BRegion &invalid, const Layer *startFrom)
2150{
2151	BRegion		localVisible(fFullVisible2);
2152	localVisible.IntersectWith(&invalid);
2153
2154	// add localVisible to our RootLayer's redraw region.
2155//	GetRootLayer()->fRedrawReg.Include(&localVisible);
2156	GetRootLayer()->fRedrawReg = localVisible;
2157	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2158//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2159}
2160
2161inline void
2162Layer::resize_layer_frame_by(float x, float y)
2163{
2164	uint16		rm = fResizeMode & 0x0000FFFF;
2165	BRect		newFrame = fFrame;
2166
2167	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
2168		newFrame.left += 0.0f;
2169	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
2170		newFrame.left += x;
2171	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
2172		newFrame.left += x/2;
2173
2174	if ((rm & 0x000FU) == _VIEW_LEFT_)
2175		newFrame.right += 0.0f;
2176	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
2177		newFrame.right += x;
2178	else if ((rm & 0x000FU) == _VIEW_CENTER_)
2179		newFrame.right += x/2;
2180
2181	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
2182		newFrame.top += 0.0f;
2183	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
2184		newFrame.top += y;
2185	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
2186		newFrame.top += y/2;
2187
2188	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
2189		newFrame.bottom += 0.0f;
2190	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
2191		newFrame.bottom += y;
2192	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
2193		newFrame.bottom += y/2;
2194
2195	if (newFrame != fFrame) {
2196		float		dx, dy;
2197
2198		dx	= newFrame.Width() - fFrame.Width();
2199		dy	= newFrame.Height() - fFrame.Height();
2200
2201		fFrame	= newFrame;
2202
2203		if (dx != 0.0f || dy != 0.0f) {
2204			// call hook function
2205			ResizedByHook(dx, dy, true); // automatic
2206
2207			for (Layer *lay = LastChild(); lay; lay = PreviousChild())
2208				lay->resize_layer_frame_by(dx, dy);
2209		}
2210		else
2211			MovedByHook(dx, dy);
2212	}
2213}
2214
2215inline void
2216Layer::rezize_layer_redraw_more(BRegion &reg, float dx, float dy)
2217{
2218	if (dx == 0 && dy == 0)
2219		return;
2220
2221	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
2222		uint16		rm = lay->fResizeMode & 0x0000FFFF;
2223
2224		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
2225			// NOTE: this is not exactly corect, but it works :-)
2226			// Normaly we shoud've used the lay's old, required region - the one returned
2227			// from get_user_region() with the old frame, and the current one. lay->Bounds()
2228			// works for the moment so we leave it like this.
2229
2230			// calculate the old bounds.
2231			BRect	oldBounds(lay->Bounds());
2232			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
2233				oldBounds.right -=dx;
2234			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
2235				oldBounds.bottom -=dy;
2236
2237			// compute the region that became visible because we got bigger OR smaller.
2238			BRegion	regZ(lay->Bounds());
2239			regZ.Include(oldBounds);
2240			regZ.Exclude(oldBounds&lay->Bounds());
2241
2242			lay->ConvertToScreen2(&regZ);
2243
2244			// intersect that with this'(not lay's) fullVisible region
2245			regZ.IntersectWith(&fFullVisible2);
2246			reg.Include(&regZ);
2247
2248			lay->rezize_layer_redraw_more(reg,
2249				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
2250				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
2251
2252			// above, OR this:
2253			// reg.Include(&lay->fFullVisible2);
2254		}
2255		else
2256		if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
2257			((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) ||
2258			((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
2259			((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
2260		{
2261			reg.Include(&lay->fFullVisible2);
2262		}
2263	}
2264}
2265
2266inline void
2267Layer::resize_layer_full_update_on_resize(BRegion &reg, float dx, float dy)
2268{
2269	if (dx == 0 && dy == 0)
2270		return;
2271
2272	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
2273		uint16		rm = lay->fResizeMode & 0x0000FFFF;
2274
2275		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
2276			if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0)
2277				reg.Include(&lay->fVisible2);
2278
2279			lay->resize_layer_full_update_on_resize(reg,
2280				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
2281				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
2282		}
2283	}
2284}
2285
2286void
2287Layer::do_ResizeBy(float dx, float dy)
2288{
2289	fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
2290
2291	// resize children using their resize_mask.
2292	for (Layer *lay = LastChild(); lay; lay = PreviousChild())
2293			lay->resize_layer_frame_by(dx, dy);
2294
2295	// call hook function
2296	if (dx != 0.0f || dy != 0.0f)
2297		ResizedByHook(dx, dy, false); // manual
2298
2299	if (!IsHidden() && GetRootLayer()) {
2300		BRegion oldFullVisible(fFullVisible2);
2301		// this is required to invalidate the old border
2302		BRegion oldVisible(fVisible2);
2303
2304		// in case they moved, bottom, right and center aligned layers must be redrawn
2305		BRegion redrawMore;
2306		rezize_layer_redraw_more(redrawMore, dx, dy);
2307
2308		// we'll invalidate the old area and the new, maxmial one.
2309		BRegion invalid;
2310		get_user_regions(invalid);
2311		invalid.Include(&fFullVisible2);
2312
2313		clear_visible_regions();
2314
2315		fParent->do_RebuildVisibleRegions(invalid, this);
2316
2317		// done rebuilding regions, now redraw regions that became visible
2318
2319		// what's invalid, are the differences between to old and the new fullVisible region
2320		// 1) in case we grow.
2321		BRegion		redrawReg(fFullVisible2);
2322		redrawReg.Exclude(&oldFullVisible);
2323		// 2) in case we shrink
2324		BRegion		redrawReg2(oldFullVisible);
2325		redrawReg2.Exclude(&fFullVisible2);
2326		// 3) combine.
2327		redrawReg.Include(&redrawReg2);
2328
2329		// for center, right and bottom alligned layers, redraw their old positions
2330		redrawReg.Include(&redrawMore);
2331
2332		// layers that had their frame modified must be entirely redrawn.
2333		rezize_layer_redraw_more(redrawReg, dx, dy);
2334
2335		// add redrawReg to our RootLayer's redraw region.
2336//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2337		GetRootLayer()->fRedrawReg = redrawReg;
2338		// include layer's visible region in case we want a full update on resize
2339		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) {
2340			resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg, dx, dy);
2341
2342			GetRootLayer()->fRedrawReg.Include(&fVisible2);
2343			GetRootLayer()->fRedrawReg.Include(&oldVisible);
2344		}
2345		// clear canvas and set invalid regions for affected WinBorders
2346		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2347//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2348	}
2349}
2350
2351void Layer::do_MoveBy(float dx, float dy)
2352{
2353	if (dx == 0.0f && dy == 0.0f)
2354		return;
2355
2356//	fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
2357	fFrame.OffsetBy(dx, dy);
2358
2359	// call hook function
2360	MovedByHook(dx, dy);
2361
2362	if (!IsHidden() && GetRootLayer()) {
2363		BRegion oldFullVisible(fFullVisible2);
2364
2365		// we'll invalidate the old position and the new, maxmial one.
2366		BRegion invalid;
2367		get_user_regions(invalid);
2368		invalid.Include(&fFullVisible2);
2369
2370		clear_visible_regions();
2371
2372		fParent->do_RebuildVisibleRegions(invalid, this);
2373
2374		// done rebuilding regions, now copy common parts and redraw regions that became visible
2375
2376		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
2377		BRegion		redrawReg(fFullVisible2);
2378		redrawReg.Include(&oldFullVisible);
2379
2380		// offset to layer's new location so that we can calculate the common region.
2381		oldFullVisible.OffsetBy(dx, dy);
2382
2383		// finally we have the region that needs to be redrawn.
2384		redrawReg.Exclude(&oldFullVisible);
2385
2386		// by intersecting the old fullVisible offseted to layer's new location, with the current
2387		// fullVisible, we'll have the common region which can be copied using HW acceleration.
2388		oldFullVisible.IntersectWith(&fFullVisible2);
2389
2390		// offset back and instruct the HW to do the actual copying.
2391		oldFullVisible.OffsetBy(-dx, -dy);
2392		GetDisplayDriver()->CopyRegion(&oldFullVisible, dx, dy);
2393
2394		// add redrawReg to our RootLayer's redraw region.
2395//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2396		GetRootLayer()->fRedrawReg = redrawReg;
2397		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2398//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2399	}
2400}
2401
2402void
2403Layer::do_ScrollBy(float dx, float dy)
2404{
2405	fLayerData->OffsetOrigin(BPoint(dx, dy));
2406//	fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy);
2407
2408	if (!IsHidden() && GetRootLayer()) {
2409		// set the region to be invalidated.
2410		BRegion		invalid(fFullVisible2);
2411
2412		clear_visible_regions();
2413
2414		rebuild_visible_regions(invalid, invalid, LastChild());
2415
2416		// for the moment we say that the whole surface needs to be redraw.
2417		BRegion		redrawReg(fFullVisible2);
2418
2419		// offset old region so that we can start comparing.
2420		invalid.OffsetBy(dx, dy);
2421
2422		// compute the common region. we'll use HW acc to copy this to the new location.
2423		invalid.IntersectWith(&fFullVisible2);
2424		GetDisplayDriver()->CopyRegion(&invalid, -dx, -dy);
2425
2426		// common region goes back to its original location. then, by excluding
2427		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
2428		invalid.OffsetBy(-dx, -dy);
2429		redrawReg.Exclude(&invalid);
2430
2431//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2432		GetRootLayer()->fRedrawReg = redrawReg;
2433		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2434//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2435	}
2436
2437	if (dx != 0.0f || dy != 0.0f)
2438		ScrolledByHook(dx, dy);
2439}
2440
2441void
2442Layer::get_user_regions(BRegion &reg)
2443{
2444	// 1) set to frame in screen coords
2445	BRect screenFrame(Bounds());
2446	ConvertToScreen2(&screenFrame);
2447	reg.Set(screenFrame);
2448
2449	// 2) intersect with screen region
2450	BRegion screenReg(GetRootLayer()->Bounds());
2451	reg.IntersectWith(&screenReg);
2452
2453
2454	// 3) impose user constrained regions
2455	LayerData *stackData = fLayerData;
2456	while (stackData) {
2457		if (stackData->ClippingRegion()) {
2458			// transform in screen coords
2459// NOTE: Already is in screen coords, but I leave this here in
2460// case we change it
2461//			BRegion screenReg(*stackData->ClippingRegion());
2462//			ConvertToScreen2(&screenReg);
2463//			reg.IntersectWith(&screenReg);
2464			reg.IntersectWith(stackData->ClippingRegion());
2465		}
2466		stackData = stackData->prevState;
2467	}
2468}
2469
2470void
2471Layer::do_RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom)
2472{
2473	BRegion		localVisible(fFullVisible2);
2474	localVisible.IntersectWith(&invalid);
2475	rebuild_visible_regions(invalid, localVisible, startFrom);
2476}
2477
2478void
2479Layer::rebuild_visible_regions(const BRegion &invalid,
2480								const BRegion &parentLocalVisible,
2481								const Layer *startFrom)
2482{
2483	// no point in continuing if this layer is hidden. starting from here, all
2484	// descendants have (and will have) invalid visible regions.
2485	if (fHidden)
2486		return;
2487
2488	// no need to go deeper if the parent doesn't have a visible region anymore
2489	// and our fullVisible region is also empty.
2490	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0))
2491		return;
2492
2493	bool fullRebuild = false;
2494
2495	// intersect maximum wanted region with the invalid region
2496	BRegion common;
2497	get_user_regions(common);
2498	common.IntersectWith(&invalid);
2499
2500	// if the resulted region is not valid, this layer is not in the catchment area
2501	// of the region being invalidated
2502	if (!common.CountRects() > 0)
2503		return;
2504
2505	// now intersect with parent's visible part of the region that was/is invalidated
2506	common.IntersectWith(&parentLocalVisible);
2507
2508	// exclude the invalid region
2509	fFullVisible2.Exclude(&invalid);
2510	fVisible2.Exclude(&invalid);
2511
2512	// put in what's really visible
2513	fFullVisible2.Include(&common);
2514
2515	// this is to allow a layer to hide some parts of itself so children
2516	// won't take them.
2517	BRegion unalteredVisible(common);
2518	bool altered = alter_visible_for_children(common);
2519
2520	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
2521		if (lay == startFrom)
2522			fullRebuild = true;
2523
2524		if (fullRebuild)
2525			lay->rebuild_visible_regions(invalid, common, lay->LastChild());
2526
2527		// to let children know much they can take from parent's visible region
2528		common.Exclude(&lay->fFullVisible2);
2529		// we've hidden some parts of our visible region from our children,
2530		// and we must be in sysnc with this region too...
2531		if (altered)
2532			unalteredVisible.Exclude(&lay->fFullVisible2);
2533	}
2534
2535	// the visible region of this layer is what left after all its children took
2536	// what they could.
2537	if (altered)
2538		fVisible2.Include(&unalteredVisible);
2539	else
2540		fVisible2.Include(&common);
2541}
2542
2543bool
2544Layer::alter_visible_for_children(BRegion &reg)
2545{
2546	// Empty Hook function
2547	return false;
2548}
2549
2550void
2551Layer::clear_visible_regions()
2552{
2553	// OPT: maybe we should uncomment these lines for performance
2554	//if (fFullVisible2.CountRects() <= 0)
2555	//	return;
2556
2557	fVisible2.MakeEmpty();
2558	fFullVisible2.MakeEmpty();
2559	for (Layer *child = LastChild(); child; child = PreviousChild())
2560		child->clear_visible_regions();
2561}
2562
2563#endif
2564
2565