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