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