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