Layer.cpp revision aca4f50d1eefef8bf137cc16f5b707d223494377
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 "DrawState.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
64
65Layer::Layer(BRect frame, const char* name, int32 token,
66	uint32 resize, uint32 flags, DisplayDriver* driver)
67	:
68	fFrame(frame), // in parent coordinates
69//	fBoundsLeftTop(0.0, 0.0),
70
71	// Layer does not start out as a part of the tree
72	fOwner(NULL),
73
74	fParent(NULL),
75	fPreviousSibling(NULL),
76	fNextSibling(NULL),
77	fFirstChild(NULL),
78	fLastChild(NULL),
79
80	fCurrent(NULL),
81
82	// all regions (fVisible, fFullVisible, fFull) start empty
83#ifndef NEW_CLIPPING
84	fVisible(),
85	fFullVisible(),
86	fFull(),
87	fFrameAction(B_LAYER_ACTION_NONE),
88	fClipReg(&fVisible),
89#else
90	fVisible2(),
91	fFullVisible2(),
92	fClipReg(&fVisible2),
93#endif
94
95	fServerWin(NULL),
96	fName(name),
97	fViewToken(token),
98
99	fFlags(flags),
100	fResizeMode(resize),
101	fEventMask(0UL),
102	fEventOptions(0UL),
103	fHidden(false),
104	fIsTopLayer(false),
105
106	fAdFlags(0),
107
108	fDriver(driver),
109	fDrawState(new DrawState),
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 DrawState 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 DrawState. 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	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
140
141	STRACE(("Layer(%s) successfuly created\n", Name()));
142}
143
144
145Layer::~Layer()
146{
147	delete fDrawState;
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	fDrawState->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	DrawState *ld;
510	ld = fDrawState;
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		_GetWantedRegion(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	fDrawState = fDrawState->PushState();
1014	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
1015}
1016
1017
1018void
1019Layer::PopState()
1020{
1021	if (fDrawState->PreviousState() == NULL) {
1022		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), but there is NO state on stack!\n", Name());
1023		return;
1024	}
1025
1026	fDrawState = fDrawState->PopState();
1027	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
1028}
1029
1030
1031//! Matches the BView call of the same name
1032BRect
1033Layer::Bounds(void) const
1034{
1035	BRect r(fFrame);
1036//	r.OffsetTo(fBoundsLeftTop);
1037	r.OffsetTo(BoundsOrigin());
1038	return r;
1039}
1040
1041//! Matches the BView call of the same name
1042BRect
1043Layer::Frame(void) const
1044{
1045	return fFrame;
1046}
1047
1048//! Moves the layer by specified values, complete with redraw
1049void
1050Layer::MoveBy(float x, float y)
1051{
1052	STRACE(("Layer(%s)::MoveBy() START\n", Name()));
1053	if (!fParent) {
1054		CRITICAL("ERROR: in Layer::MoveBy()! - No parent!\n");
1055		return;
1056	}
1057
1058	GetRootLayer()->Lock();
1059#ifndef NEW_CLIPPING
1060	move_layer(x, y);
1061#else
1062	do_MoveBy(x, y);
1063#endif
1064	GetRootLayer()->Unlock();
1065
1066	STRACE(("Layer(%s)::MoveBy() END\n", Name()));
1067}
1068
1069//! Resize the layer by the specified amount, complete with redraw
1070void
1071Layer::ResizeBy(float x, float y)
1072{
1073	STRACE(("Layer(%s)::ResizeBy() START\n", Name()));
1074
1075	if (!fParent) {
1076		printf("ERROR: in Layer::ResizeBy()! - No parent!\n");
1077		return;
1078	}
1079
1080	GetRootLayer()->Lock();
1081#ifndef NEW_CLIPPING
1082	resize_layer(x, y);
1083#else
1084	do_ResizeBy(x, y);
1085#endif
1086	GetRootLayer()->Unlock();
1087
1088	STRACE(("Layer(%s)::ResizeBy() END\n", Name()));
1089}
1090
1091//! scrolls the layer by the specified amount, complete with redraw
1092void
1093Layer::ScrollBy(float x, float y)
1094{
1095	STRACE(("Layer(%s)::ScrollBy() START\n", Name()));
1096
1097	GetRootLayer()->Lock();
1098#ifndef NEW_CLIPPING
1099	// nothing
1100#else
1101	do_ScrollBy(x, y);
1102#endif
1103	GetRootLayer()->Unlock();
1104
1105	STRACE(("Layer(%s)::ScrollBy() END\n", Name()));
1106}
1107
1108void
1109Layer::MouseDown(const BMessage *msg)
1110{
1111	if (Window() && !IsTopLayer()) {
1112		Window()->SendMessageToClient(msg, fViewToken, false);
1113	}
1114}
1115
1116void
1117Layer::MouseUp(const BMessage *msg)
1118{
1119	if (Window() && !IsTopLayer()) {
1120		Window()->SendMessageToClient(msg, fViewToken, false);
1121	}
1122}
1123
1124void
1125Layer::MouseMoved(const BMessage *msg)
1126{
1127	if (Window() && !IsTopLayer()) {
1128		Window()->SendMessageToClient(msg, fViewToken, false);
1129	}
1130}
1131
1132void
1133Layer::MouseWheelChanged(const BMessage *msg)
1134{
1135	if (Window() && !IsTopLayer()) {
1136		Window()->SendMessageToClient(msg, fViewToken, false);
1137	}
1138}
1139
1140void
1141Layer::KeyDown(const BMessage *msg)
1142{
1143	if (Window() && !IsTopLayer()) {
1144		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
1145	}
1146}
1147
1148void
1149Layer::KeyUp(const BMessage *msg)
1150{
1151	if (Window() && !IsTopLayer()) {
1152		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
1153	}
1154}
1155
1156void
1157Layer::UnmappedKeyDown(const BMessage *msg)
1158{
1159	if (Window() && !IsTopLayer()) {
1160		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
1161	}
1162}
1163
1164void
1165Layer::UnmappedKeyUp(const BMessage *msg)
1166{
1167	if (Window() && !IsTopLayer()) {
1168		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
1169	}
1170}
1171
1172void
1173Layer::ModifiersChanged(const BMessage *msg)
1174{
1175	if (Window() && !IsTopLayer()) {
1176		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
1177	}
1178}
1179
1180void
1181Layer::WorkspaceActivated(int32 index, bool active)
1182{
1183	// Empty
1184}
1185
1186void
1187Layer::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces)
1188{
1189	// Empty
1190}
1191
1192void
1193Layer::Activated(bool active)
1194{
1195	// Empty
1196}
1197
1198
1199BPoint
1200Layer::BoundsOrigin() const
1201{
1202	BPoint origin(0,0);
1203	float scale = Scale();
1204
1205	DrawState* layerData = fDrawState;
1206	do {
1207		origin += layerData->Origin();
1208	} while ((layerData = layerData->PreviousState()) != NULL);
1209
1210	origin.x *= scale;
1211	origin.y *= scale;
1212
1213	return origin;
1214}
1215
1216
1217float
1218Layer::Scale() const
1219{
1220	float scale = 1.0f;
1221
1222	DrawState* layerData = fDrawState;
1223	do {
1224		scale *= layerData->Scale();
1225	} while ((layerData = layerData->PreviousState()) != NULL);
1226
1227	return scale;
1228}
1229
1230
1231//! Converts the passed point to parent coordinates
1232BPoint
1233Layer::ConvertToParent(BPoint pt)
1234{
1235#ifndef NEW_CLIPPING
1236	pt -= BoundsOrigin();
1237	pt += fFrame.LeftTop();
1238	return pt;
1239#else
1240	ConvertToParent2(&pt);
1241	return pt;
1242#endif
1243}
1244
1245//! Converts the passed rectangle to parent coordinates
1246BRect
1247Layer::ConvertToParent(BRect rect)
1248{
1249#ifndef NEW_CLIPPING
1250//	rect.OffsetBy(fFrame.LeftTop());
1251//	return rect;
1252	rect.OffsetBy(-BoundsOrigin().x, -BoundsOrigin().y);
1253	rect.OffsetBy(fFrame.LeftTop());
1254	return rect;
1255#else
1256	ConvertToParent2(&rect);
1257	return rect;
1258#endif
1259}
1260
1261//! Converts the passed region to parent coordinates
1262BRegion
1263Layer::ConvertToParent(BRegion* reg)
1264{
1265#ifndef NEW_CLIPPING
1266	// TODO: wouldn't it be more efficient to use the copy
1267	// constructor for BRegion and then call OffsetBy()?
1268	BRegion newreg;
1269	for (int32 i = 0; i < reg->CountRects(); i++)
1270		newreg.Include(ConvertToParent(reg->RectAt(i)));
1271	return newreg;
1272#else
1273	BRegion newReg(*reg);
1274	ConvertToParent2(&newReg);
1275	return newReg;
1276#endif
1277}
1278
1279//! Converts the passed point from parent coordinates
1280BPoint
1281Layer::ConvertFromParent(BPoint pt)
1282{
1283#ifndef NEW_CLIPPING
1284//	return pt - fFrame.LeftTop();
1285	pt -= fFrame.LeftTop();
1286	pt += BoundsOrigin();
1287	return pt;
1288#else
1289	ConvertFromParent2(&pt);
1290	return pt;
1291#endif
1292}
1293
1294//! Converts the passed rectangle from parent coordinates
1295BRect
1296Layer::ConvertFromParent(BRect rect)
1297{
1298#ifndef NEW_CLIPPING
1299//	rect.OffsetBy(-fFrame.left, -fFrame.top);
1300//	return rect;
1301	rect.OffsetBy(-fFrame.left, -fFrame.top);
1302	rect.OffsetBy(BoundsOrigin());
1303	return rect;
1304#else
1305	ConvertFromParent2(&rect);
1306	return rect;
1307#endif
1308}
1309
1310//! Converts the passed region from parent coordinates
1311BRegion
1312Layer::ConvertFromParent(BRegion *reg)
1313{
1314#ifndef NEW_CLIPPING
1315	BRegion newreg;
1316	for(int32 i=0; i<reg->CountRects();i++)
1317		newreg.Include(ConvertFromParent(reg->RectAt(i)));
1318	return newreg;
1319#else
1320	BRegion newReg(*reg);
1321	ConvertFromParent2(&newReg);
1322	return newReg;
1323#endif
1324}
1325
1326// ConvertToTop
1327BPoint
1328Layer::ConvertToTop(BPoint pt)
1329{
1330#ifndef NEW_CLIPPING
1331	if (fParent) {
1332//		return (fParent->ConvertToTop(pt + fFrame.LeftTop()));
1333		pt = ConvertToParent(pt);
1334		return fParent->ConvertToTop(pt);
1335	} else
1336		return pt;
1337#else
1338	ConvertToScreen2(&pt);
1339	return pt;
1340#endif
1341}
1342
1343//! Converts the passed rectangle to screen coordinates
1344BRect
1345Layer::ConvertToTop(BRect rect)
1346{
1347#ifndef NEW_CLIPPING
1348	if (fParent) {
1349//		return fParent->ConvertToTop(rect.OffsetByCopy(fFrame.LeftTop()));
1350		rect = ConvertToParent(rect);
1351		return fParent->ConvertToTop(rect);
1352	} else
1353		return rect;
1354#else
1355	ConvertToScreen2(&rect);
1356	return rect;
1357#endif
1358}
1359
1360//! Converts the passed region to screen coordinates
1361BRegion
1362Layer::ConvertToTop(BRegion *reg)
1363{
1364#ifndef NEW_CLIPPING
1365	BRegion newreg;
1366	for (int32 i = 0; i < reg->CountRects();i++)
1367		newreg.Include(ConvertToTop(reg->RectAt(i)));
1368	return newreg;
1369#else
1370	BRegion newReg(*reg);
1371	ConvertToScreen2(&newReg);
1372	return newReg;
1373#endif
1374}
1375
1376// ConvertFromTop
1377BPoint
1378Layer::ConvertFromTop(BPoint pt)
1379{
1380#ifndef NEW_CLIPPING
1381	if (fParent) {
1382//		return fParent->ConvertFromTop(pt-fFrame.LeftTop());
1383		pt = ConvertFromParent(pt);
1384		return fParent->ConvertFromTop(pt);
1385	} else
1386		return pt;
1387#else
1388	ConvertFromScreen2(&pt);
1389	return pt;
1390#endif
1391}
1392
1393//! Converts the passed rectangle from screen coordinates
1394BRect
1395Layer::ConvertFromTop(BRect rect)
1396{
1397#ifndef NEW_CLIPPING
1398	if (fParent) {
1399//		return fParent->ConvertFromTop(rect.OffsetByCopy(-fFrame.LeftTop().x,
1400//														 -fFrame.LeftTop().y));
1401		rect = ConvertFromParent(rect);
1402		return fParent->ConvertFromTop(rect);
1403	} else
1404		return rect;
1405#else
1406	ConvertFromScreen2(&rect);
1407	return rect;
1408#endif
1409}
1410
1411//! Converts the passed region from screen coordinates
1412BRegion
1413Layer::ConvertFromTop(BRegion *reg)
1414{
1415#ifndef NEW_CLIPPING
1416	BRegion newreg;
1417
1418	for (int32 i = 0; i < reg->CountRects(); i++)
1419		newreg.Include(ConvertFromTop(reg->RectAt(i)));
1420
1421	return newreg;
1422#else
1423	BRegion newReg(*reg);
1424	ConvertFromScreen2(&newReg);
1425	return newReg;
1426#endif
1427}
1428
1429//! Recursively deletes all children of the calling layer
1430void
1431Layer::PruneTree(void)
1432{
1433
1434	Layer* lay;
1435	Layer* nextlay;
1436
1437	lay = fFirstChild;
1438	fFirstChild = NULL;
1439
1440	while (lay != NULL) {
1441		if (lay->fFirstChild != NULL)
1442			lay->PruneTree();
1443
1444		nextlay = lay->fNextSibling;
1445		lay->fNextSibling = NULL;
1446
1447		delete lay;
1448		lay = nextlay;
1449	}
1450	// Man, this thing is short. Elegant, ain't it? :P
1451}
1452
1453//! Prints information about the layer's current state
1454void
1455Layer::PrintToStream()
1456{
1457	printf("\n *** Layer %s:\n", Name());
1458	printf("\t Parent: %s", fParent ? fParent->Name() : "<no parent>");
1459
1460	printf("\t us: %s\t ls: %s\n",
1461		fPreviousSibling ? fPreviousSibling->Name() : "<none>",
1462		fNextSibling ? fNextSibling->Name() : "<none>");
1463
1464	printf("\t topChild: %s\t bottomChild: %s\n",
1465		fFirstChild ? fFirstChild->Name() : "<none>",
1466		fLastChild ? fLastChild->Name() : "<none>");
1467
1468	printf("Frame: (%f, %f, %f, %f)\n", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
1469	printf("LocalOrigin: (%f, %f)\n", BoundsOrigin().x, BoundsOrigin().y);
1470	printf("Token: %ld\n", fViewToken);
1471	printf("Hidden - direct: %s ", fHidden?"true":"false");
1472	printf("Hidden - indirect: %s\n", IsHidden()?"true":"false");
1473	printf("ResizingMode: %lx ", fResizeMode);
1474	printf("Flags: %lx\n", fFlags);
1475
1476	if (fDrawState)
1477		fDrawState->PrintToStream();
1478	else
1479		printf(" NO DrawState valid pointer\n");
1480}
1481
1482//! Prints pointer info kept by the current layer
1483void
1484Layer::PrintNode()
1485{
1486	printf("-----------\nLayer %s\n", Name());
1487	if (fParent)
1488		printf("Parent: %s (%p)\n", fParent->Name(), fParent);
1489	else
1490		printf("Parent: NULL\n");
1491
1492	if (fPreviousSibling)
1493		printf("Upper sibling: %s (%p)\n", fPreviousSibling->Name(), fPreviousSibling);
1494	else
1495		printf("Upper sibling: NULL\n");
1496
1497	if (fNextSibling)
1498		printf("Lower sibling: %s (%p)\n", fNextSibling->Name(), fNextSibling);
1499	else
1500		printf("Lower sibling: NULL\n");
1501
1502	if (fFirstChild)
1503		printf("Top child: %s (%p)\n", fFirstChild->Name(), fFirstChild);
1504	else
1505		printf("Top child: NULL\n");
1506
1507	if (fLastChild)
1508		printf("Bottom child: %s (%p)\n", fLastChild->Name(), fLastChild);
1509	else
1510		printf("Bottom child: NULL\n");
1511#ifndef NEW_CLIPPING
1512	printf("Visible Areas: "); fVisible.PrintToStream();
1513#endif
1514}
1515
1516//! Prints the tree hierarchy from the current layer down
1517void
1518Layer::PrintTree()
1519{
1520	printf("\n Tree structure:\n");
1521	printf("\t%s\t%s\n", Name(), IsHidden()? "Hidden": "NOT hidden");
1522	for(Layer *lay = LastChild(); lay != NULL; lay = PreviousChild())
1523		printf("\t%s\t%s\n", lay->Name(), lay->IsHidden()? "Hidden": "NOT hidden");
1524}
1525
1526// RequestDraw
1527void
1528Layer::RequestDraw(const BRegion &reg, Layer *startFrom)
1529{
1530	STRACE(("Layer(%s)::RequestDraw()\n", Name()));
1531
1532	// do not redraw any child until you must
1533	int redraw = false;
1534	if (!startFrom)
1535		redraw = true;
1536
1537#ifndef NEW_CLIPPING
1538	if (HasClient() && IsTopLayer()) {
1539		// calculate the minimum region/rectangle to be updated with
1540		// a single message to the client.
1541		BRegion	updateReg(fFullVisible);
1542
1543		if (fFlags & B_FULL_UPDATE_ON_RESIZE
1544			&& fFrameAction	== B_LAYER_ACTION_RESIZE)
1545		{
1546			// do nothing
1547		} else {
1548			updateReg.IntersectWith(&reg);
1549		}
1550		if (updateReg.CountRects() > 0) {
1551			fOwner->fCumulativeRegion.Include(&updateReg);
1552			if (!fOwner->InUpdate() && !fOwner->fRequestSent) {
1553				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1554fOwner->cnt++;
1555if (fOwner->cnt != 1)
1556	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1557				fOwner->fRequestSent = true; // this is here to avoid a possible de-synchronization
1558				if (SendUpdateMsg(fOwner->fInUpdateRegion) == B_OK) {
1559					fOwner->fCumulativeRegion.MakeEmpty();
1560				}
1561				else {
1562					fOwner->fRequestSent = false;
1563					fOwner->fInUpdateRegion.MakeEmpty();
1564				}
1565			}
1566		}
1567	}
1568
1569	if (fVisible.CountRects() > 0) {
1570		BRegion	updateReg(fVisible);
1571		// calculate the update region
1572		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fFrameAction == B_LAYER_ACTION_RESIZE) {
1573			// do nothing
1574		} else {
1575			updateReg.IntersectWith(&reg);
1576		}
1577
1578		if (updateReg.CountRects() > 0) {
1579			fDriver->ConstrainClippingRegion(&updateReg);
1580			Draw(updateReg.Frame());
1581			fDriver->ConstrainClippingRegion(NULL);
1582		}
1583	}
1584
1585	for (Layer *lay = LastChild(); lay != NULL; lay = PreviousChild()) {
1586		if (lay == startFrom)
1587			redraw = true;
1588
1589		if (redraw && !(lay->IsHidden())) {
1590			// no need to go deeper if not even the FullVisible region intersects
1591			// Update one.
1592			BRegion common(lay->fFullVisible);
1593			common.IntersectWith(&reg);
1594
1595			if (common.CountRects() > 0)
1596				lay->RequestDraw(reg, NULL);
1597		}
1598	}
1599#else
1600	if (HasClient() && IsTopLayer()) {
1601		// calculate the minimum region/rectangle to be updated with
1602		// a single message to the client.
1603		BRegion	updateReg(fFullVisible2);
1604
1605		updateReg.IntersectWith(&reg);
1606
1607		if (updateReg.CountRects() > 0) {
1608			fOwner->fCumulativeRegion.Include(&updateReg);
1609			if (fOwner->fUpdateRequestsEnabled && !fOwner->InUpdate() && !fOwner->fRequestSent) {
1610				fOwner->fInUpdateRegion = fOwner->fCumulativeRegion;
1611fOwner->cnt++;
1612if (fOwner->cnt != 1)
1613	CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!");
1614				fOwner->fRequestSent = true; // this is here to avoid a possible de-synchronization
1615				if (SendUpdateMsg(fOwner->fInUpdateRegion) == B_OK) {
1616					fOwner->fCumulativeRegion.MakeEmpty();
1617				}
1618				else {
1619					fOwner->fRequestSent = false;
1620					fOwner->fInUpdateRegion.MakeEmpty();
1621				}
1622			}
1623		}
1624	}
1625
1626	if (fVisible2.CountRects() > 0) {
1627		BRegion	updateReg(fVisible2);
1628			updateReg.IntersectWith(&reg);
1629
1630		if (updateReg.CountRects() > 0) {
1631			fDriver->ConstrainClippingRegion(&updateReg);
1632			Draw(updateReg.Frame());
1633			fDriver->ConstrainClippingRegion(NULL);
1634		}
1635	}
1636
1637	for (Layer *lay = LastChild(); lay != NULL; lay = PreviousChild()) {
1638		if (lay == startFrom)
1639			redraw = true;
1640
1641		if (redraw && !(lay->IsHidden())) {
1642			// no need to go deeper if not even the FullVisible region intersects
1643			// Update one.
1644			BRegion common(lay->fFullVisible2);
1645			common.IntersectWith(&reg);
1646
1647			if (common.CountRects() > 0)
1648				lay->RequestDraw(reg, NULL);
1649		}
1650	}
1651#endif
1652}
1653
1654#ifndef NEW_CLIPPING
1655
1656// move_layer
1657void
1658Layer::move_layer(float x, float y)
1659{
1660/*	if (fClassID == AS_WINBORDER_CLASS) {
1661		WinBorder	*wb = (WinBorder*)this;
1662		wb->fCumulativeRegion.OffsetBy(x, y);
1663		wb->fInUpdateRegion.OffsetBy(x, y);
1664		wb->fSavedForUpdateRegion.OffsetBy(x, y);
1665	}*/
1666
1667	fFrameAction = B_LAYER_ACTION_MOVE;
1668
1669	BPoint pt(x, y);
1670	BRect rect(fFull.Frame().OffsetByCopy(pt));
1671
1672if (!fParent) {
1673printf("no parent in Layer::move_layer() (%s)\n", Name());
1674fFrameAction = B_LAYER_ACTION_NONE;
1675return;
1676}
1677
1678	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_MOVE, pt);
1679
1680	fDriver->CopyRegionList(&fRootLayer->fCopyRegList,
1681							&fRootLayer->fCopyList,
1682							fRootLayer->fCopyRegList.CountItems(),
1683							&fFullVisible);
1684
1685	fParent->Redraw(fRootLayer->fRedrawReg, this);
1686
1687	// redraw workspaces layer
1688	if (dynamic_cast<WinBorder*>(this) != NULL && fRootLayer->WorkspacesLayer() != NULL) {
1689		fRootLayer->GoRedraw(fRootLayer->WorkspacesLayer(), fRootLayer->WorkspacesLayer()->fVisible);
1690	}
1691
1692	SendViewCoordUpdateMsg();
1693
1694	EmptyGlobals();
1695
1696	fFrameAction = B_LAYER_ACTION_NONE;
1697}
1698
1699// resize_layer
1700void
1701Layer::resize_layer(float x, float y)
1702{
1703	fFrameAction = B_LAYER_ACTION_RESIZE;
1704
1705	BPoint pt(x,y);
1706
1707	BRect rect(fFull.Frame());
1708	rect.right += x;
1709	rect.bottom += y;
1710
1711if (!fParent) {
1712printf("no parent in Layer::resize_layer() (%s)\n", Name());
1713fFrameAction = B_LAYER_ACTION_NONE;
1714return;
1715}
1716
1717	fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_RESIZE, pt);
1718
1719	fDriver->CopyRegionList(&fRootLayer->fCopyRegList, &fRootLayer->fCopyList, fRootLayer->fCopyRegList.CountItems(), &fFullVisible);
1720
1721	fParent->Redraw(fRootLayer->fRedrawReg, this);
1722
1723	// redraw workspaces layer
1724	if (dynamic_cast<WinBorder*>(this) != NULL && fRootLayer->WorkspacesLayer() != NULL) {
1725		fRootLayer->GoRedraw(fRootLayer->WorkspacesLayer(), fRootLayer->WorkspacesLayer()->fVisible);
1726	}
1727
1728	SendViewCoordUpdateMsg();
1729
1730	EmptyGlobals();
1731
1732	fFrameAction = B_LAYER_ACTION_NONE;
1733}
1734
1735// FullInvalidate
1736void
1737Layer::FullInvalidate(const BRect &rect)
1738{
1739	FullInvalidate(BRegion(rect));
1740}
1741
1742// FullInvalidate
1743void
1744Layer::FullInvalidate(const BRegion& region)
1745{
1746	STRACE(("Layer(%s)::FullInvalidate():\n", Name()));
1747
1748#ifdef DEBUG_LAYER
1749	region.PrintToStream();
1750	printf("\n");
1751#endif
1752
1753	BPoint pt(0,0);
1754	StartRebuildRegions(region, NULL,/* B_LAYER_INVALIDATE, pt); */B_LAYER_NONE, pt);
1755
1756	Redraw(fRootLayer->fRedrawReg);
1757
1758	EmptyGlobals();
1759}
1760
1761// Invalidate
1762void
1763Layer::Invalidate(const BRegion& region)
1764{
1765	STRACE(("Layer(%s)::Invalidate():\n", Name()));
1766#ifdef DEBUG_LAYER
1767	region.PrintToStream();
1768	printf("\n");
1769#endif
1770
1771	fRootLayer->fRedrawReg	= region;
1772
1773	Redraw(fRootLayer->fRedrawReg);
1774
1775	EmptyGlobals();
1776}
1777
1778#endif // 5 methods
1779
1780
1781/*!
1782	\brief Returns the layer's ServerWindow
1783
1784	If the layer's ServerWindow has not been assigned, it attempts to find
1785	the owning ServerWindow in the tree.
1786*/
1787ServerWindow*
1788Layer::SearchForServerWindow()
1789{
1790	if (!fServerWin)
1791		fServerWin=fParent->SearchForServerWindow();
1792
1793	return fServerWin;
1794}
1795
1796//! Sends an _UPDATE_ message to the client BWindow
1797status_t
1798Layer::SendUpdateMsg(BRegion& reg)
1799{
1800	BMessage msg;
1801	msg.what = _UPDATE_;
1802#ifndef NEW_CLIPPING
1803	msg.AddRect("_rect", ConvertFromTop(reg.Frame()));
1804#else
1805	BRect	rect(reg.Frame());
1806	ConvertFromScreen2(&rect);
1807	msg.AddRect("_rect", rect );
1808#endif
1809	msg.AddRect("debug_rect", reg.Frame());
1810//	msg.AddInt32("_token",fViewToken);
1811
1812	return Owner()->Window()->SendMessageToClient(&msg);
1813}
1814
1815// AddToViewsWithInvalidCoords
1816void
1817Layer::AddToViewsWithInvalidCoords() const
1818{
1819	if (fServerWin) {
1820		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
1821		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
1822		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
1823		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
1824	}
1825}
1826
1827// SendViewCoordUpdateMsg
1828void
1829Layer::SendViewCoordUpdateMsg() const
1830{
1831	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
1832		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
1833		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
1834	}
1835}
1836
1837// SetViewColor
1838void
1839Layer::SetViewColor(const RGBColor& color)
1840{
1841	fViewColor = color;
1842}
1843
1844// SetBackgroundBitmap
1845void
1846Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
1847{
1848	// TODO: What about reference counting?
1849	// "Release" old fBackgroundBitmap and "Aquire" new one?
1850	fBackgroundBitmap = bitmap;
1851}
1852
1853// SetOverlayBitmap
1854void
1855Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
1856{
1857	// TODO: What about reference counting?
1858	// "Release" old fOverlayBitmap and "Aquire" new one?
1859	fOverlayBitmap = bitmap;
1860}
1861
1862void
1863Layer::CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
1864
1865	GetRootLayer()->Lock();
1866	do_CopyBits(src, dst, xOffset, yOffset);
1867	GetRootLayer()->Unlock();
1868}
1869
1870void
1871Layer::do_CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
1872	// NOTE: The correct behaviour is this:
1873	// * The region that is copied is the
1874	//   src rectangle, no matter if it fits
1875	//   into the dst rectangle. It is copied
1876	//   by the offset dst.LeftTop() - src.LeftTop()
1877	// * The dst rectangle is used for invalidation:
1878	//   Any area in the dst rectangle that could
1879	//   not be copied from src (because either the
1880	//   src rectangle was not big enough, or because there
1881	//   were parts cut off by the current layer clipping),
1882	//   are triggering BView::Draw() to be called
1883	//   and for these parts only.
1884
1885	// TODO: having moved this into Layer broke
1886	// offscreen windows (bitmaps)
1887	// -> move back into ServerWindow...
1888	if (!GetRootLayer())
1889		return;
1890
1891#ifndef NEW_CLIPPING
1892
1893	// the region that is going to be copied
1894	BRegion copyRegion(src);
1895	// apply the current clipping of the layer
1896	copyRegion.IntersectWith(&fVisible);
1897	// don't scroll regions that are pending for
1898	// (or already in) an update
1899	// NOTE: this fixes the visible glitches that resulted from
1900	// scrolling, but it brings up a new problem, which looks
1901	// like the the client receives multiple update messages for
1902	// the same area
1903	// NOTE2: if you don't include both regions, it doesn't work
1904	copyRegion.Exclude(&fOwner->CulmulatedUpdateRegion());
1905	copyRegion.Exclude(&fOwner->RegionToBeUpdated());
1906
1907	// offset the region to the destination
1908	// and apply the current clipping there as well
1909	copyRegion.OffsetBy(xOffset, yOffset);
1910	copyRegion.IntersectWith(&fVisible);
1911
1912	// the region at the destination that needs invalidation
1913	GetRootLayer()->fRedrawReg.Set(dst);
1914	// exclude the region drawn by the copy operation
1915	GetRootLayer()->fRedrawReg.Exclude(&copyRegion);
1916	// apply the current clipping as well
1917	GetRootLayer()->fRedrawReg.IntersectWith(&fVisible);
1918
1919	// move the region back for the actual operation
1920	copyRegion.OffsetBy(-xOffset, -yOffset);
1921
1922	GetDisplayDriver()->CopyRegion(&copyRegion, xOffset, yOffset);
1923
1924	// trigger the redraw
1925	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
1926#else
1927	// the region that is going to be copied
1928	BRegion copyRegion(src);
1929	// apply the current clipping of the layer
1930
1931	copyRegion.IntersectWith(&fVisible2);
1932
1933	// offset the region to the destination
1934	// and apply the current clipping there as well
1935	copyRegion.OffsetBy(xOffset, yOffset);
1936	copyRegion.IntersectWith(&fVisible2);
1937
1938	// the region at the destination that needs invalidation
1939	GetRootLayer()->fRedrawReg.Set(dst);
1940	// exclude the region drawn by the copy operation
1941// TODO: quick fix for our scrolling problem. FIX THIS!
1942//	GetRootLayer()->fRedrawReg.Exclude(&copyRegion);
1943	// apply the current clipping as well
1944	GetRootLayer()->fRedrawReg.IntersectWith(&fVisible2);
1945
1946	// move the region back for the actual operation
1947	copyRegion.OffsetBy(-xOffset, -yOffset);
1948
1949	GetDisplayDriver()->CopyRegion(&copyRegion, xOffset, yOffset);
1950
1951	// trigger the redraw
1952	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
1953#endif
1954
1955}
1956
1957#ifdef NEW_CLIPPING
1958
1959void
1960Layer::MovedByHook(float dx, float dy)
1961{
1962	if (Window() && !IsTopLayer())
1963		AddToViewsWithInvalidCoords();
1964}
1965
1966void
1967Layer::ResizedByHook(float dx, float dy, bool automatic)
1968{
1969	if (Window() && !IsTopLayer())
1970		AddToViewsWithInvalidCoords();
1971}
1972
1973void
1974Layer::ScrolledByHook(float dx, float dy)
1975{
1976	// empty.
1977}
1978
1979
1980void
1981Layer::GetWantedRegion(BRegion& reg) const
1982{
1983	// this is the same as get_user_region.
1984	// because get_user_region modifies nothing.
1985	const_cast<Layer*>(this)->Layer::_GetWantedRegion(reg);
1986}
1987
1988//! converts a point from local to parent's coordinate system
1989void
1990Layer::ConvertToParent2(BPoint* pt) const
1991{
1992	if (fParent) {
1993		BPoint origin = BoundsOrigin();
1994		pt->x -= origin.x;
1995		pt->y -= origin.y;
1996		pt->x += fFrame.left;
1997		pt->y += fFrame.top;
1998	}
1999}
2000
2001//! converts a rect from local to parent's coordinate system
2002void
2003Layer::ConvertToParent2(BRect* rect) const
2004{
2005	if (fParent) {
2006		BPoint origin = BoundsOrigin();
2007		rect->OffsetBy(-origin.x, -origin.y);
2008		rect->OffsetBy(fFrame.left, fFrame.top);
2009	}
2010}
2011
2012//! converts a region from local to parent's coordinate system
2013void
2014Layer::ConvertToParent2(BRegion* reg) const
2015{
2016	if (fParent) {
2017		BPoint origin = BoundsOrigin();
2018		reg->OffsetBy(-origin.x, -origin.y);
2019		reg->OffsetBy(fFrame.left, fFrame.top);
2020	}
2021}
2022
2023//! converts a point from parent's to local coordinate system
2024void
2025Layer::ConvertFromParent2(BPoint* pt) const
2026{
2027	if (fParent) {
2028		BPoint origin = BoundsOrigin();
2029		pt->x += origin.x;
2030		pt->y += origin.y;
2031		pt->x -= fFrame.left;
2032		pt->y -= fFrame.top;
2033	}
2034}
2035
2036//! converts a rect from parent's to local coordinate system
2037void
2038Layer::ConvertFromParent2(BRect* rect) const
2039{
2040	if (fParent) {
2041		BPoint origin = BoundsOrigin();
2042		rect->OffsetBy(origin.x, origin.y);
2043		rect->OffsetBy(-fFrame.left, -fFrame.top);
2044	}
2045}
2046
2047//! converts a region from parent's to local coordinate system
2048void
2049Layer::ConvertFromParent2(BRegion* reg) const
2050{
2051	if (fParent) {
2052		BPoint origin = BoundsOrigin();
2053		reg->OffsetBy(origin.x, origin.y);
2054		reg->OffsetBy(-fFrame.left, -fFrame.top);
2055	}
2056}
2057
2058//! converts a point from local to screen coordinate system
2059void
2060Layer::ConvertToScreen2(BPoint* pt) const
2061{
2062	if (GetRootLayer())
2063		if (fParent) {
2064			BPoint origin = BoundsOrigin();
2065			pt->x -= origin.x;
2066			pt->y -= origin.y;
2067			pt->x += fFrame.left;
2068			pt->y += fFrame.top;
2069
2070			fParent->ConvertToScreen2(pt);
2071		}
2072}
2073
2074//! converts a rect from local to screen coordinate system
2075void
2076Layer::ConvertToScreen2(BRect* rect) const
2077{
2078	if (GetRootLayer())
2079		if (fParent) {
2080			BPoint origin = BoundsOrigin();
2081			rect->OffsetBy(-origin.x, -origin.y);
2082			rect->OffsetBy(fFrame.left, fFrame.top);
2083
2084			fParent->ConvertToScreen2(rect);
2085		}
2086}
2087
2088//! converts a region from local to screen coordinate system
2089void
2090Layer::ConvertToScreen2(BRegion* reg) const
2091{
2092	if (GetRootLayer())
2093		if (fParent) {
2094			BPoint origin = BoundsOrigin();
2095			reg->OffsetBy(-origin.x, -origin.y);
2096			reg->OffsetBy(fFrame.left, fFrame.top);
2097
2098			fParent->ConvertToScreen2(reg);
2099		}
2100}
2101
2102//! converts a point from screen to local coordinate system
2103void
2104Layer::ConvertFromScreen2(BPoint* pt) const
2105{
2106	if (GetRootLayer())
2107		if (fParent) {
2108			BPoint origin = BoundsOrigin();
2109			pt->x += origin.x;
2110			pt->y += origin.y;
2111			pt->x -= fFrame.left;
2112			pt->y -= fFrame.top;
2113
2114			fParent->ConvertToScreen2(pt);
2115		}
2116}
2117
2118//! converts a rect from screen to local coordinate system
2119void
2120Layer::ConvertFromScreen2(BRect* rect) const
2121{
2122	if (GetRootLayer())
2123		if (fParent) {
2124			BPoint origin = BoundsOrigin();
2125			rect->OffsetBy(origin.x, origin.y);
2126			rect->OffsetBy(-fFrame.left, -fFrame.top);
2127
2128			fParent->ConvertFromScreen2(rect);
2129		}
2130}
2131
2132//! converts a region from screen to local coordinate system
2133void
2134Layer::ConvertFromScreen2(BRegion* reg) const
2135{
2136	if (GetRootLayer())
2137		if (fParent) {
2138			BPoint origin = BoundsOrigin();
2139			reg->OffsetBy(origin.x, origin.y);
2140			reg->OffsetBy(-fFrame.left, -fFrame.top);
2141
2142			fParent->ConvertFromScreen2(reg);
2143		}
2144}
2145
2146
2147void
2148Layer::do_Hide()
2149{
2150	fHidden = true;
2151
2152	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
2153		// save fullVisible so we know what to invalidate
2154		BRegion invalid(fFullVisible2);
2155
2156		clear_visible_regions();
2157
2158		if (invalid.Frame().IsValid())
2159			fParent->do_Invalidate(invalid, this);
2160	}
2161}
2162
2163void
2164Layer::do_Show()
2165{
2166	fHidden = false;
2167
2168	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
2169		BRegion invalid;
2170
2171		_GetWantedRegion(invalid);
2172
2173		if (invalid.CountRects() > 0)
2174			fParent->do_Invalidate(invalid, this);
2175	}
2176}
2177
2178void
2179Layer::do_Invalidate(const BRegion &invalid, const Layer *startFrom)
2180{
2181	BRegion		localVisible(fFullVisible2);
2182	localVisible.IntersectWith(&invalid);
2183	rebuild_visible_regions(invalid, localVisible,
2184		startFrom? startFrom: LastChild());
2185
2186	// add localVisible to our RootLayer's redraw region.
2187//	GetRootLayer()->fRedrawReg.Include(&localVisible);
2188	GetRootLayer()->fRedrawReg = localVisible;
2189	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2190//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2191}
2192
2193void
2194Layer::do_Redraw(const BRegion &invalid, const Layer *startFrom)
2195{
2196	BRegion		localVisible(fFullVisible2);
2197	localVisible.IntersectWith(&invalid);
2198
2199	// add localVisible to our RootLayer's redraw region.
2200//	GetRootLayer()->fRedrawReg.Include(&localVisible);
2201	GetRootLayer()->fRedrawReg = localVisible;
2202	GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2203//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2204}
2205
2206inline void
2207Layer::resize_layer_frame_by(float x, float y)
2208{
2209	uint16		rm = fResizeMode & 0x0000FFFF;
2210	BRect		newFrame = fFrame;
2211
2212	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
2213		newFrame.left += 0.0f;
2214	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
2215		newFrame.left += x;
2216	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
2217		newFrame.left += x/2;
2218
2219	if ((rm & 0x000FU) == _VIEW_LEFT_)
2220		newFrame.right += 0.0f;
2221	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
2222		newFrame.right += x;
2223	else if ((rm & 0x000FU) == _VIEW_CENTER_)
2224		newFrame.right += x/2;
2225
2226	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
2227		newFrame.top += 0.0f;
2228	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
2229		newFrame.top += y;
2230	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
2231		newFrame.top += y/2;
2232
2233	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
2234		newFrame.bottom += 0.0f;
2235	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
2236		newFrame.bottom += y;
2237	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
2238		newFrame.bottom += y/2;
2239/*
2240	if (newFrame != fFrame) {
2241		float offsetX, offsetY;
2242		float dx, dy;
2243
2244		dx = newFrame.Width() - fFrame.Width();
2245		dy = newFrame.Height() - fFrame.Height();
2246		offsetX = newFrame.left - fFrame.left;
2247		offsetY = newFrame.top - fFrame.top;
2248
2249		fFrame = newFrame;
2250
2251		if (offsetX != 0.0f || offsetY != 0.0f) {
2252			MovedByHook(offsetX, offsetY);
2253		}
2254
2255		if (dx != 0.0f || dy != 0.0f) {
2256			// call hook function
2257			ResizedByHook(dx, dy, true); // automatic
2258
2259			for (Layer *lay = LastChild(); lay; lay = PreviousChild())
2260				lay->resize_layer_frame_by(dx, dy);
2261		}
2262	}
2263*/
2264// TODO: the above code is CORRECT!!!
2265// It's commented because BView::FrameResized()/Moved() be called twice a given view. FIX THIS!
2266	if (newFrame != fFrame) {
2267		float		dx, dy;
2268
2269		dx	= newFrame.Width() - fFrame.Width();
2270		dy	= newFrame.Height() - fFrame.Height();
2271
2272		fFrame	= newFrame;
2273
2274		if (dx != 0.0f || dy != 0.0f) {
2275			// call hook function
2276			ResizedByHook(dx, dy, true); // automatic
2277
2278			for (Layer *lay = LastChild(); lay; lay = PreviousChild())
2279				lay->resize_layer_frame_by(dx, dy);
2280		}
2281		else
2282			MovedByHook(dx, dy);
2283	}
2284}
2285
2286inline void
2287Layer::rezize_layer_redraw_more(BRegion &reg, float dx, float dy)
2288{
2289	if (dx == 0 && dy == 0)
2290		return;
2291
2292	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
2293		uint16		rm = lay->fResizeMode & 0x0000FFFF;
2294
2295		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
2296			// NOTE: this is not exactly corect, but it works :-)
2297			// Normaly we shoud've used the lay's old, required region - the one returned
2298			// from get_user_region() with the old frame, and the current one. lay->Bounds()
2299			// works for the moment so we leave it like this.
2300
2301			// calculate the old bounds.
2302			BRect	oldBounds(lay->Bounds());
2303			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
2304				oldBounds.right -=dx;
2305			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
2306				oldBounds.bottom -=dy;
2307
2308			// compute the region that became visible because we got bigger OR smaller.
2309			BRegion	regZ(lay->Bounds());
2310			regZ.Include(oldBounds);
2311			regZ.Exclude(oldBounds&lay->Bounds());
2312
2313			lay->ConvertToScreen2(&regZ);
2314
2315			// intersect that with this'(not lay's) fullVisible region
2316			regZ.IntersectWith(&fFullVisible2);
2317			reg.Include(&regZ);
2318
2319			lay->rezize_layer_redraw_more(reg,
2320				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
2321				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
2322
2323			// above, OR this:
2324			// reg.Include(&lay->fFullVisible2);
2325		}
2326		else
2327		if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
2328			((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) ||
2329			((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
2330			((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
2331		{
2332			reg.Include(&lay->fFullVisible2);
2333		}
2334	}
2335}
2336
2337inline void
2338Layer::resize_layer_full_update_on_resize(BRegion &reg, float dx, float dy)
2339{
2340	if (dx == 0 && dy == 0)
2341		return;
2342
2343	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
2344		uint16		rm = lay->fResizeMode & 0x0000FFFF;
2345
2346		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
2347			if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0)
2348				reg.Include(&lay->fVisible2);
2349
2350			lay->resize_layer_full_update_on_resize(reg,
2351				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
2352				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
2353		}
2354	}
2355}
2356
2357void
2358Layer::do_ResizeBy(float dx, float dy)
2359{
2360	fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
2361
2362	// resize children using their resize_mask.
2363	for (Layer *lay = LastChild(); lay; lay = PreviousChild())
2364			lay->resize_layer_frame_by(dx, dy);
2365
2366	// call hook function
2367	if (dx != 0.0f || dy != 0.0f)
2368		ResizedByHook(dx, dy, false); // manual
2369
2370	if (!IsHidden() && GetRootLayer()) {
2371		BRegion oldFullVisible(fFullVisible2);
2372		// this is required to invalidate the old border
2373		BRegion oldVisible(fVisible2);
2374
2375		// in case they moved, bottom, right and center aligned layers must be redrawn
2376		BRegion redrawMore;
2377		rezize_layer_redraw_more(redrawMore, dx, dy);
2378
2379		// we'll invalidate the old area and the new, maxmial one.
2380		BRegion invalid;
2381		_GetWantedRegion(invalid);
2382		invalid.Include(&fFullVisible2);
2383
2384		clear_visible_regions();
2385
2386		fParent->do_RebuildVisibleRegions(invalid, this);
2387
2388		// done rebuilding regions, now redraw regions that became visible
2389
2390		// what's invalid, are the differences between to old and the new fullVisible region
2391		// 1) in case we grow.
2392		BRegion		redrawReg(fFullVisible2);
2393		redrawReg.Exclude(&oldFullVisible);
2394		// 2) in case we shrink
2395		BRegion		redrawReg2(oldFullVisible);
2396		redrawReg2.Exclude(&fFullVisible2);
2397		// 3) combine.
2398		redrawReg.Include(&redrawReg2);
2399
2400		// for center, right and bottom alligned layers, redraw their old positions
2401		redrawReg.Include(&redrawMore);
2402
2403		// layers that had their frame modified must be entirely redrawn.
2404		rezize_layer_redraw_more(redrawReg, dx, dy);
2405
2406		// add redrawReg to our RootLayer's redraw region.
2407//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2408		GetRootLayer()->fRedrawReg = redrawReg;
2409		// include layer's visible region in case we want a full update on resize
2410		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) {
2411			resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg, dx, dy);
2412
2413			GetRootLayer()->fRedrawReg.Include(&fVisible2);
2414			GetRootLayer()->fRedrawReg.Include(&oldVisible);
2415		}
2416		// clear canvas and set invalid regions for affected WinBorders
2417		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2418//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2419	}
2420
2421	SendViewCoordUpdateMsg();
2422}
2423
2424void Layer::do_MoveBy(float dx, float dy)
2425{
2426	if (dx == 0.0f && dy == 0.0f)
2427		return;
2428
2429//	fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
2430	fFrame.OffsetBy(dx, dy);
2431
2432	// call hook function
2433	MovedByHook(dx, dy);
2434
2435	if (!IsHidden() && GetRootLayer()) {
2436		BRegion oldFullVisible(fFullVisible2);
2437
2438		// we'll invalidate the old position and the new, maxmial one.
2439		BRegion invalid;
2440		_GetWantedRegion(invalid);
2441		invalid.Include(&fFullVisible2);
2442
2443		clear_visible_regions();
2444
2445		fParent->do_RebuildVisibleRegions(invalid, this);
2446
2447		// done rebuilding regions, now copy common parts and redraw regions that became visible
2448
2449		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
2450		BRegion		redrawReg(fFullVisible2);
2451		redrawReg.Include(&oldFullVisible);
2452
2453		// offset to layer's new location so that we can calculate the common region.
2454		oldFullVisible.OffsetBy(dx, dy);
2455
2456		// finally we have the region that needs to be redrawn.
2457		redrawReg.Exclude(&oldFullVisible);
2458
2459		// by intersecting the old fullVisible offseted to layer's new location, with the current
2460		// fullVisible, we'll have the common region which can be copied using HW acceleration.
2461		oldFullVisible.IntersectWith(&fFullVisible2);
2462
2463		// offset back and instruct the HW to do the actual copying.
2464		oldFullVisible.OffsetBy(-dx, -dy);
2465		GetDisplayDriver()->CopyRegion(&oldFullVisible, dx, dy);
2466
2467		// add redrawReg to our RootLayer's redraw region.
2468//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2469		GetRootLayer()->fRedrawReg = redrawReg;
2470		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2471//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2472	}
2473
2474	SendViewCoordUpdateMsg();
2475}
2476
2477void
2478Layer::do_ScrollBy(float dx, float dy)
2479{
2480	fDrawState->OffsetOrigin(BPoint(dx, dy));
2481//	fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy);
2482
2483	if (!IsHidden() && GetRootLayer()) {
2484		// set the region to be invalidated.
2485		BRegion		invalid(fFullVisible2);
2486
2487		clear_visible_regions();
2488
2489		rebuild_visible_regions(invalid, invalid, LastChild());
2490
2491		// for the moment we say that the whole surface needs to be redraw.
2492		BRegion		redrawReg(fFullVisible2);
2493
2494		// offset old region so that we can start comparing.
2495		invalid.OffsetBy(dx, dy);
2496
2497		// compute the common region. we'll use HW acc to copy this to the new location.
2498		invalid.IntersectWith(&fFullVisible2);
2499		GetDisplayDriver()->CopyRegion(&invalid, -dx, -dy);
2500
2501		// common region goes back to its original location. then, by excluding
2502		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
2503		invalid.OffsetBy(-dx, -dy);
2504// TODO: a quick fix for the scrolling problem!!! FIX THIS!
2505//		redrawReg.Exclude(&invalid);
2506
2507//		GetRootLayer()->fRedrawReg.Include(&redrawReg);
2508		GetRootLayer()->fRedrawReg = redrawReg;
2509		GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL);
2510//	GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
2511	}
2512
2513	if (dx != 0.0f || dy != 0.0f)
2514		ScrolledByHook(dx, dy);
2515
2516	SendViewCoordUpdateMsg();
2517}
2518
2519void
2520Layer::_GetWantedRegion(BRegion &reg)
2521{
2522	// 1) set to frame in screen coords
2523	BRect screenFrame(Bounds());
2524	ConvertToScreen2(&screenFrame);
2525	reg.Set(screenFrame);
2526
2527	// 2) intersect with screen region
2528	BRegion screenReg(GetRootLayer()->Bounds());
2529	reg.IntersectWith(&screenReg);
2530
2531
2532	// 3) impose user constrained regions
2533	DrawState *stackData = fDrawState;
2534	while (stackData) {
2535		if (stackData->ClippingRegion()) {
2536			// transform in screen coords
2537// NOTE: Already is in screen coords, but I leave this here in
2538// case we change it
2539//			BRegion screenReg(*stackData->ClippingRegion());
2540//			ConvertToScreen2(&screenReg);
2541//			reg.IntersectWith(&screenReg);
2542			reg.IntersectWith(stackData->ClippingRegion());
2543		}
2544		stackData = stackData->PreviousState();
2545	}
2546}
2547
2548void
2549Layer::do_RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom)
2550{
2551	BRegion		localVisible(fFullVisible2);
2552	localVisible.IntersectWith(&invalid);
2553	rebuild_visible_regions(invalid, localVisible, startFrom);
2554}
2555
2556void
2557Layer::rebuild_visible_regions(const BRegion &invalid,
2558								const BRegion &parentLocalVisible,
2559								const Layer *startFrom)
2560{
2561	// no point in continuing if this layer is hidden.
2562	if (fHidden)
2563		return;
2564
2565	// no need to go deeper if the parent doesn't have a visible region anymore
2566	// and our fullVisible region is also empty.
2567	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0))
2568		return;
2569
2570	bool fullRebuild = false;
2571
2572	// intersect maximum wanted region with the invalid region
2573	BRegion common;
2574	_GetWantedRegion(common);
2575	common.IntersectWith(&invalid);
2576
2577	// if the resulted region is not valid, this layer is not in the catchment area
2578	// of the region being invalidated
2579	if (!common.CountRects() > 0)
2580		return;
2581
2582	// now intersect with parent's visible part of the region that was/is invalidated
2583	common.IntersectWith(&parentLocalVisible);
2584
2585	// exclude the invalid region
2586	fFullVisible2.Exclude(&invalid);
2587	fVisible2.Exclude(&invalid);
2588
2589	// put in what's really visible
2590	fFullVisible2.Include(&common);
2591
2592	// allow this layer to hide some parts from its children
2593	_ReserveRegions(common);
2594
2595	for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
2596		if (lay == startFrom)
2597			fullRebuild = true;
2598
2599		if (fullRebuild)
2600			lay->rebuild_visible_regions(invalid, common, lay->LastChild());
2601
2602		// to let children know much they can take from parent's visible region
2603		common.Exclude(&lay->fFullVisible2);
2604	}
2605
2606	// include what's left after all children took what they could.
2607	fVisible2.Include(&common);
2608}
2609
2610void
2611Layer::_ReserveRegions(BRegion &reg)
2612{
2613	// Empty for Layer objects
2614}
2615
2616void
2617Layer::clear_visible_regions()
2618{
2619	// OPT: maybe we should uncomment these lines for performance
2620	//if (fFullVisible2.CountRects() <= 0)
2621	//	return;
2622
2623	fVisible2.MakeEmpty();
2624	fFullVisible2.MakeEmpty();
2625	for (Layer *child = LastChild(); child; child = PreviousChild())
2626		child->clear_visible_regions();
2627}
2628
2629#endif
2630
2631