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