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