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