xref: /haiku/src/servers/app/Layer.cpp (revision 5412911f7f8ca41340b0f5cb928ed9726322ab44)
1 /*
2  * Copyright (c) 2001-2005, Haiku, Inc.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Adi Oanca <adioanca@gmail.com>
8  *		Stephan Aßmus <superstippi@gmx.de>
9  */
10 
11 /**	Class used for tracking drawing context and screen clipping.
12  *	One Layer per client BWindow (WindowBorder) and each BView therein.
13  */
14 
15 #include <string.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 
19 #include <AppDefs.h>
20 #include <Message.h>
21 #include <Region.h>
22 #include <View.h>
23 
24 #include "DebugInfoManager.h"
25 #include "DrawingEngine.h"
26 #include "DrawState.h"
27 #include "PortLink.h"
28 #include "RootLayer.h"
29 #include "ServerProtocol.h"
30 #include "ServerWindow.h"
31 #include "WinBorder.h"
32 #include "Layer.h"
33 #include "ServerBitmap.h"
34 
35 //#define DEBUG_LAYER
36 #ifdef DEBUG_LAYER
37 #	define STRACE(x) printf x
38 #else
39 #	define STRACE(x) ;
40 #endif
41 
42 
43 Layer::Layer(BRect frame, const char* name, int32 token,
44 	uint32 resize, uint32 flags, DrawingEngine* driver)
45 	:
46 	fName(name),
47 	fFrame(frame),
48 
49 	fDriver(driver),
50 	fRootLayer(NULL),
51 	fServerWin(NULL),
52 	fOwner(NULL),
53 
54 	fDrawState(new DrawState),
55 
56 	fParent(NULL),
57 	fPreviousSibling(NULL),
58 	fNextSibling(NULL),
59 	fFirstChild(NULL),
60 	fLastChild(NULL),
61 
62 	fCurrent(NULL),
63 
64 	fViewToken(token),
65 	fFlags(flags),
66 	fAdFlags(0),
67 	fResizeMode(resize),
68 	fEventMask(0UL),
69 	fEventOptions(0UL),
70 
71 	fHidden(false),
72 	fIsTopLayer(false),
73 	fViewColor(255, 255, 255, 255),
74 
75 	fBackgroundBitmap(NULL),
76 	fOverlayBitmap(NULL)
77 {
78 	if (!frame.IsValid()) {
79 		char helper[1024];
80 		sprintf(helper, "Layer::Layer(BRect(%.1f, %.1f, %.1f, %.1f), name: %s, token: %ld) - frame is invalid\n",
81 			frame.left, frame.top, frame.right, frame.bottom, name, token);
82 		CRITICAL(helper);
83 		fFrame.Set(0, 0, 1, 1);
84 	}
85 
86 	if (!fDriver)
87 		CRITICAL("You MUST have a valid driver to init a Layer object\n");
88 
89 	// NOTE: This flag is forwarded to a DrawState setting, even
90 	// though it is actually not part of a "state". However,
91 	// it is an important detail of a graphics context, and we
92 	// have no other means to pass this setting on to the DrawingEngine
93 	// other than through the DrawState. If we ever add a flag
94 	// B_ANTI_ALIASING to the view flags, it would have to be passed
95 	// in the same way. Though when breaking binary compatibility,
96 	// we might want to make this an actual part of a "state" (with
97 	// a different API to set these).
98 	// Note that the flag is also tested (updated) in Push/PopState and
99 	// SetFlags().
100 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
101 
102 	STRACE(("Layer(%s) successfuly created\n", Name()));
103 }
104 
105 
106 Layer::~Layer()
107 {
108 	delete fDrawState;
109 
110 	Layer* child = fFirstChild;
111 
112 	while (child != NULL) {
113 		Layer* nextChild = child->fNextSibling;
114 
115 		delete child;
116 		child = nextChild;
117 	}
118 }
119 
120 
121 /*!
122 	\brief Adds a child layer to the current one
123 	\param layer a new child layer
124 	\param serverWin the serverwindow to which the layer will belong
125 
126 	Unlike the BView version, if the layer already belongs to another, then
127 	it spits an error to stdout and returns.
128 */
129 void
130 Layer::AddChild(Layer* layer, ServerWindow* serverWin)
131 {
132 	STRACE(("Layer(%s)::AddChild(%s) START\n", Name(), layer->Name()));
133 
134 	if (layer->fParent != NULL) {
135 		printf("ERROR: AddChild(): Layer already has a parent\n");
136 		return;
137 	}
138 
139 	// 1) attach layer to the tree structure
140 	layer->fParent = this;
141 
142 	// if we have children already, bump the current last child back one and
143 	// make the new child the last layer
144 	if (fLastChild) {
145 		layer->fPreviousSibling = fLastChild;
146 		fLastChild->fNextSibling = layer;
147 	} else {
148 		fFirstChild = layer;
149 	}
150 	fLastChild = layer;
151 
152 	// if we have no RootLayer yet, then there is no need to set any parameters --
153 	// they will be set when the RootLayer for this tree will be added
154 	// to the main tree structure.
155 	if (!fRootLayer) {
156 		STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name()));
157 		return;
158 	}
159 
160 	// 2) Iterate over the newly-added layer and all its children, setting the
161 	//	root layer and server window and also rebuilding the full-size region
162 	//	for every descendant of the newly-added layer
163 
164 	//c = short for: current
165 	Layer* c = layer;
166 	Layer* stop = layer;
167 	while (true) {
168 		// action block
169 
170 		// 2.1) set the RootLayer for this object.
171 		c->SetRootLayer(c->fParent->fRootLayer);
172 
173 		// 2.2) this Layer must know if it has a ServerWindow object attached.
174 		c->fServerWin=serverWin;
175 
176 		// tree parsing algorithm
177 		if (c->fFirstChild) {
178 			// go deep
179 			c = c->fFirstChild;
180 		} else {
181 			// go right or up
182 
183 			if (c == stop) // our trip is over
184 				break;
185 
186 			if (c->fNextSibling) {
187 				// go right
188 				c = c->fNextSibling;
189 			} else {
190 				// go up
191 				while (!c->fParent->fNextSibling && c->fParent != stop)
192 					c = c->fParent;
193 
194 				if (c->fParent == stop) // that's enough!
195 					break;
196 
197 				c = c->fParent->fNextSibling;
198 			}
199 		}
200 	}
201 
202 	STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name()));
203 }
204 
205 /*!
206 	\brief Removes a child layer from the current one
207 	\param layer the layer to remove
208 
209 	If the layer does not belong to the the current layer, then this function
210 	spits out an error to stdout and returns
211 */
212 void
213 Layer::RemoveChild(Layer *layer)
214 {
215 	STRACE(("Layer(%s)::RemoveChild(%s) START\n", Name(), layer->Name()));
216 
217 	if (!layer->fParent) {
218 		printf("ERROR: RemoveChild(): Layer doesn't have a parent\n");
219 		return;
220 	}
221 
222 	if (layer->fParent != this) {
223 		printf("ERROR: RemoveChild(): Layer is not a child of this layer\n");
224 		return;
225 	}
226 
227 	// 1) remove this layer from the main tree.
228 
229 	// Take care of fParent
230 	layer->fParent = NULL;
231 
232 	if (fFirstChild == layer)
233 		fFirstChild = layer->fNextSibling;
234 
235 	if (fLastChild == layer)
236 		fLastChild = layer->fPreviousSibling;
237 
238 	// Take care of siblings
239 	if (layer->fPreviousSibling != NULL)
240 		layer->fPreviousSibling->fNextSibling	= layer->fNextSibling;
241 
242 	if (layer->fNextSibling != NULL)
243 		layer->fNextSibling->fPreviousSibling = layer->fPreviousSibling;
244 
245 	layer->fPreviousSibling = NULL;
246 	layer->fNextSibling = NULL;
247 	layer->_ClearVisibleRegions();
248 
249 	// 2) Iterate over all of the removed-layer's descendants and unset the
250 	//	root layer, server window, and all redraw-related regions
251 
252 	Layer* c = layer; //c = short for: current
253 	Layer* stop = layer;
254 
255 	while (true) {
256 		// action block
257 		{
258 			// 2.1) set the RootLayer for this object.
259 			c->SetRootLayer(NULL);
260 			// 2.2) this Layer must know if it has a ServerWindow object attached.
261 			c->fServerWin = NULL;
262 		}
263 
264 		// tree parsing algorithm
265 		if (c->fFirstChild) {
266 			// go deep
267 			c = c->fFirstChild;
268 		} else {
269 			// go right or up
270 			if (c == stop) // out trip is over
271 				break;
272 
273 			if (c->fNextSibling) {
274 				// go right
275 				c = c->fNextSibling;
276 			} else {
277 				// go up
278 				while(!c->fParent->fNextSibling && c->fParent != stop)
279 					c = c->fParent;
280 
281 				if (c->fParent == stop) // that enough!
282 					break;
283 
284 				c = c->fParent->fNextSibling;
285 			}
286 		}
287 	}
288 	STRACE(("Layer(%s)::RemoveChild(%s) END\n", Name(), layer->Name()));
289 }
290 
291 //! Removes the calling layer from the tree
292 void
293 Layer::RemoveSelf()
294 {
295 	// A Layer removes itself from the tree (duh)
296 	if (fParent == NULL) {
297 		printf("ERROR: RemoveSelf(): Layer doesn't have a parent\n");
298 		return;
299 	}
300 	fParent->RemoveChild(this);
301 }
302 
303 /*!
304 	\return true if the child is owned by this Layer, false if not
305 */
306 bool
307 Layer::HasChild(Layer* layer)
308 {
309 	for (Layer* child = FirstChild(); child; child = NextChild()) {
310 		if (child == layer)
311 			return true;
312 	}
313 	return false;
314 }
315 
316 //! Returns the number of children
317 uint32
318 Layer::CountChildren() const
319 {
320 	uint32 count = 0;
321 	Layer* child = FirstChild();
322 	while (child != NULL) {
323 		child = NextChild();
324 		count++;
325 	}
326 	return count;
327 }
328 
329 /*!
330 	\brief Finds a child of the caller based on its token ID
331 	\param token ID of the layer to find
332 	\return Pointer to the layer or NULL if not found
333 */
334 Layer*
335 Layer::FindLayer(const int32 token)
336 {
337 	// (recursive) search for a layer based on its view token
338 
339 	// iterate only over direct child layers first
340 	for (Layer* child = FirstChild(); child; child = NextChild()) {
341 		if (child->fViewToken == token)
342 			return child;
343 	}
344 
345 	// try a recursive search
346 	for (Layer* child = FirstChild(); child; child = NextChild()) {
347 		if (Layer* layer = child->FindLayer(token))
348 			return layer;
349 	}
350 
351 	return NULL;
352 }
353 
354 /*!
355 	\brief Returns the layer at the given point
356 	\param pt The point to look the layer at
357 	\return The layer containing the point or NULL if no layer found
358 */
359 Layer*
360 Layer::LayerAt(const BPoint &pt, bool recursive)
361 {
362 	//printf("%p:%s:LayerAt(x = %g, y = %g)\n", this, Name(), pt.x, pt.y);
363 	if (!recursive)	{
364 		if (VisibleRegion().Contains(pt))
365 			return this;
366 
367 		for (Layer* child = LastChild(); child; child = PreviousChild())
368 			if (child->FullVisible().Contains(pt))
369 				return child;
370 
371 		return NULL;
372 	}
373 
374 	if (fVisible.Contains(pt))
375 		return this;
376 
377 	if (fFullVisible.Contains(pt)) {
378 		for (Layer* child = LastChild(); child; child = PreviousChild()) {
379 			if (Layer* layer = child->LayerAt(pt))
380 				return layer;
381 		}
382 	}
383 
384 	return NULL;
385 }
386 
387 // FirstChild
388 Layer*
389 Layer::FirstChild() const
390 {
391 	fCurrent = fFirstChild;
392 	return fCurrent;
393 }
394 
395 // NextChild
396 Layer*
397 Layer::NextChild() const
398 {
399 	fCurrent = fCurrent->fNextSibling;
400 	return fCurrent;
401 }
402 
403 // PreviousChild
404 Layer*
405 Layer::PreviousChild() const
406 {
407 	fCurrent = fCurrent->fPreviousSibling;
408 	return fCurrent;
409 }
410 
411 // LastChild
412 Layer*
413 Layer::LastChild() const
414 {
415 	fCurrent = fLastChild;
416 	return fCurrent;
417 }
418 
419 // SetName
420 void
421 Layer::SetName(const char* name)
422 {
423 	fName.SetTo(name);
424 }
425 
426 // SetUserClipping
427 void
428 Layer::SetUserClipping(const BRegion& region)
429 {
430 	fDrawState->SetClippingRegion(region);
431 
432 	// rebuild clipping
433 	_RebuildDrawingRegion();
434 }
435 
436 // SetFlags
437 void
438 Layer::SetFlags(uint32 flags)
439 {
440 	fFlags = flags;
441 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
442 }
443 
444 // Draw
445 void
446 Layer::Draw(const BRect &rect)
447 {
448 #ifdef DEBUG_LAYER
449 	printf("Layer(%s)::Draw: ", Name());
450 	rect.PrintToStream();
451 #endif
452 
453 	if (!ViewColor().IsTransparentMagic())
454 		fDriver->FillRect(rect, ViewColor());
455 }
456 
457 /*!
458 	\brief Shows the layer
459 	\param invalidate Invalidate the region when showing the layer. defaults to true
460 */
461 void
462 Layer::Show(bool invalidate)
463 {
464 	STRACE(("Layer(%s)::Show()\n", Name()));
465 	if(!IsHidden()) {
466 		// an ancestor may be hidden. OK, we're not visible,
467 		// but we're changing our visibility state
468 		fHidden	= false;
469 		return;
470 	}
471 
472 	fHidden	= false;
473 
474 	SendViewCoordUpdateMsg();
475 
476 	if (invalidate) {
477 		// compute the region this layer wants for itself
478 		BRegion	invalid;
479 		GetOnScreenRegion(invalid);
480 		if (invalid.CountRects() > 0) {
481 			fParent->MarkForRebuild(invalid);
482 			GetRootLayer()->MarkForRedraw(invalid);
483 
484 			fParent->TriggerRebuild();
485 			GetRootLayer()->TriggerRedraw();
486 		}
487 	}
488 }
489 
490 /*!
491 	\brief Shows the layer
492 	\param invalidate Invalidate the region when hiding the layer. defaults to true
493 */
494 void
495 Layer::Hide(bool invalidate)
496 {
497 	STRACE(("Layer(%s)::Hide()\n", Name()));
498 	if (IsHidden()) {
499 		// an ancestor may be hidden. OK, we're not visible,
500 		// but we're changing our visibility state
501 		fHidden	= true;
502 		return;
503 	}
504 
505 	fHidden	= true;
506 	if (invalidate && fFullVisible.CountRects() > 0) {
507 		BRegion invalid(fFullVisible);
508 
509 		fParent->MarkForRebuild(invalid);
510 		GetRootLayer()->MarkForRedraw(invalid);
511 
512 		fParent->TriggerRebuild();
513 		GetRootLayer()->TriggerRedraw();
514 	}
515 }
516 
517 //! Returns true if the layer is hidden
518 bool
519 Layer::IsHidden(void) const
520 {
521 	if (fHidden)
522 		return true;
523 
524 	if (fParent)
525 			return fParent->IsHidden();
526 
527 	return fHidden;
528 }
529 
530 
531 void
532 Layer::PushState()
533 {
534 	fDrawState = fDrawState->PushState();
535 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
536 }
537 
538 
539 void
540 Layer::PopState()
541 {
542 	if (fDrawState->PreviousState() == NULL) {
543 		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), but there is NO state on stack!\n", Name());
544 		return;
545 	}
546 
547 	bool rebuildClipping = fDrawState->ClippingRegion() != NULL;
548 
549 	fDrawState = fDrawState->PopState();
550 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
551 
552 	// rebuild clipping
553 	// (the clipping from the popped state is not effective anymore)
554 	if (rebuildClipping)
555 		_RebuildDrawingRegion();
556 }
557 
558 
559 //! Matches the BView call of the same name
560 BRect
561 Layer::Bounds() const
562 {
563 	BRect r(fFrame);
564 //	r.OffsetTo(fBoundsLeftTop);
565 	r.OffsetTo(BoundsOrigin());
566 	return r;
567 }
568 
569 
570 //! Matches the BView call of the same name
571 BRect
572 Layer::Frame() const
573 {
574 	return fFrame;
575 }
576 
577 
578 //! Moves the layer by specified values, complete with redraw
579 void
580 Layer::MoveBy(float x, float y)
581 {
582 	STRACE(("Layer(%s)::MoveBy()\n", Name()));
583 
584 	if (x == 0.0f && y == 0.0f)
585 		return;
586 
587 	// must lock, even if we change frame coordinates
588 	if (fParent && !IsHidden() && GetRootLayer() && GetRootLayer()->Lock()) {
589 		fFrame.OffsetBy(x, y);
590 
591 		BRegion oldFullVisible(fFullVisible);
592 
593 		// we'll invalidate the old position and the new, maxmial one.
594 		BRegion invalid;
595 		GetOnScreenRegion(invalid);
596 		invalid.Include(&fFullVisible);
597 
598 		fParent->MarkForRebuild(invalid);
599 		fParent->TriggerRebuild();
600 
601 		// done rebuilding regions, now copy common parts and redraw regions that became visible
602 
603 		// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
604 		BRegion	redrawReg(fFullVisible);
605 		redrawReg.Include(&oldFullVisible);
606 
607 		// offset to layer's new location so that we can calculate the common region.
608 		oldFullVisible.OffsetBy(x, y);
609 
610 		// finally we have the region that needs to be redrawn.
611 		redrawReg.Exclude(&oldFullVisible);
612 
613 		// by intersecting the old fullVisible offseted to layer's new location, with the current
614 		// fullVisible, we'll have the common region which can be copied using HW acceleration.
615 		oldFullVisible.IntersectWith(&fFullVisible);
616 
617 		// offset back and instruct the HW to do the actual copying.
618 		oldFullVisible.OffsetBy(-x, -y);
619 		GetDrawingEngine()->CopyRegion(&oldFullVisible, x, y);
620 
621 		GetRootLayer()->MarkForRedraw(redrawReg);
622 		GetRootLayer()->TriggerRedraw();
623 
624 		GetRootLayer()->Unlock();
625 	}
626 	else {
627 		// just offset to the new position
628 		fFrame.OffsetBy(x, y);
629 	}
630 
631 	MovedByHook(x, y);
632 
633 	SendViewCoordUpdateMsg();
634 }
635 
636 
637 //! Resize the layer by the specified amount, complete with redraw
638 void
639 Layer::ResizeBy(float x, float y)
640 {
641 	STRACE(("Layer(%s)::ResizeBy()\n", Name()));
642 
643 	if (x == 0.0f && y == 0.0f)
644 		return;
645 
646 	// must lock, even if we change frame coordinates
647 	if (fParent && !IsHidden() && GetRootLayer() && GetRootLayer()->Lock()) {
648 		fFrame.Set(fFrame.left, fFrame.top, fFrame.right+x, fFrame.bottom+y);
649 
650 // TODO: you should call this hook function AFTER all region rebuilding
651 //		 and redrawing stuff
652 		ResizedByHook(x, y, false);
653 
654 // TODO: ResizedByHook(x,y,true) is called from inside _ResizeLayerFrameBy
655 //		 Should call this AFTER region rebuilding and redrawing.
656 		// resize children using their resize_mask.
657 		for (Layer *child = LastChild(); child != NULL; child = PreviousChild())
658 			child->_ResizeLayerFrameBy(x, y);
659 
660 		BRegion oldFullVisible(fFullVisible);
661 		// this is required to invalidate the old border
662 		BRegion oldVisible(fVisible);
663 
664 		// in case they moved, bottom, right and center aligned layers must be redrawn
665 		BRegion redrawMore;
666 		_RezizeLayerRedrawMore(redrawMore, x, y);
667 
668 		// we'll invalidate the old area and the new, maxmial one.
669 		BRegion invalid;
670 		GetOnScreenRegion(invalid);
671 		invalid.Include(&fFullVisible);
672 
673 		fParent->MarkForRebuild(invalid);
674 		fParent->TriggerRebuild();
675 
676 		// done rebuilding regions, now redraw regions that became visible
677 
678 		// what's invalid, are the differences between to old and the new fullVisible region
679 		// 1) in case we grow.
680 		BRegion redrawReg(fFullVisible);
681 		redrawReg.Exclude(&oldFullVisible);
682 		// 2) in case we shrink
683 		BRegion redrawReg2(oldFullVisible);
684 		redrawReg2.Exclude(&fFullVisible);
685 		// 3) combine.
686 		redrawReg.Include(&redrawReg2);
687 
688 		// for center, right and bottom alligned layers, redraw their old positions
689 		redrawReg.Include(&redrawMore);
690 
691 		// layers that had their frame modified must be entirely redrawn.
692 		_RezizeLayerRedrawMore(redrawReg, x, y);
693 
694 		// include layer's visible region in case we want a full update on resize
695 		if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible.Frame().IsValid()) {
696 			_ResizeLayerFullUpdateOnResize(redrawReg, x, y);
697 
698 			redrawReg.Include(&fVisible);
699 			redrawReg.Include(&oldVisible);
700 		}
701 
702 		GetRootLayer()->MarkForRedraw(redrawReg);
703 		GetRootLayer()->TriggerRedraw();
704 
705 		GetRootLayer()->Unlock();
706 	}
707 	// just resize our frame and those of out descendants if their resize mask says so
708 	else {
709 		fFrame.Set(fFrame.left, fFrame.top, fFrame.right+x, fFrame.bottom+y);
710 
711 // TODO: you should call this hook function AFTER all region rebuilding
712 //		 and redrawing stuff
713 		ResizedByHook(x, y, false);
714 
715 // TODO: ResizedByHook(x,y,true) is called from inside _ResizeLayerFrameBy
716 //		 Should call this AFTER region rebuilding and redrawing.
717 		// resize children using their resize_mask.
718 		for (Layer *child = LastChild(); child != NULL; child = PreviousChild())
719 			child->_ResizeLayerFrameBy(x, y);
720 	}
721 
722 	SendViewCoordUpdateMsg();
723 }
724 
725 
726 //! scrolls the layer by the specified amount, complete with redraw
727 void
728 Layer::ScrollBy(float x, float y)
729 {
730 	STRACE(("Layer(%s)::ScrollBy()\n", Name()));
731 
732 	if (x == 0.0f && y == 0.0f)
733 		return;
734 
735 	// must lock, even if we change frame/origin coordinates
736 	if (fParent && !IsHidden() && GetRootLayer() && GetRootLayer()->Lock()) {
737 		fDrawState->OffsetOrigin(BPoint(x, y));
738 
739 		// set the region to be invalidated.
740 		BRegion invalid(fFullVisible);
741 
742 		MarkForRebuild(invalid);
743 
744 		TriggerRebuild();
745 
746 		// for the moment we say that the whole surface needs to be redraw.
747 		BRegion redrawReg(fFullVisible);
748 
749 		// offset old region so that we can start comparing.
750 		invalid.OffsetBy(x, y);
751 
752 		// compute the common region. we'll use HW acc to copy this to the new location.
753 		invalid.IntersectWith(&fFullVisible);
754 		GetDrawingEngine()->CopyRegion(&invalid, -x, -y);
755 
756 		// common region goes back to its original location. then, by excluding
757 		// it from curent fullVisible we'll obtain the region that needs to be redrawn.
758 		invalid.OffsetBy(-x, -y);
759 // TODO: a quick fix for the scrolling problem!!! FIX THIS!
760 //		redrawReg.Exclude(&invalid);
761 
762 		GetRootLayer()->MarkForRedraw(redrawReg);
763 		GetRootLayer()->TriggerRedraw();
764 
765 		GetRootLayer()->Unlock();
766 	}
767 	else {
768 		fDrawState->OffsetOrigin(BPoint(x, y));
769 	}
770 
771 	ScrolledByHook(x, y);
772 
773 // TODO: I think we should update the client-side that bounds rect has modified
774 //	SendViewCoordUpdateMsg();
775 }
776 
777 void
778 Layer::MouseDown(const BMessage *msg)
779 {
780 	if (Window() && !IsTopLayer()) {
781 		Window()->SendMessageToClient(msg, fViewToken, false);
782 	}
783 }
784 
785 void
786 Layer::MouseUp(const BMessage *msg)
787 {
788 	if (Window() && !IsTopLayer()) {
789 		Window()->SendMessageToClient(msg, fViewToken, false);
790 	}
791 }
792 
793 void
794 Layer::MouseMoved(const BMessage *msg)
795 {
796 	if (Window() && !IsTopLayer()) {
797 		Window()->SendMessageToClient(msg, fViewToken, false);
798 	}
799 }
800 
801 void
802 Layer::MouseWheelChanged(const BMessage *msg)
803 {
804 	if (Window() && !IsTopLayer()) {
805 		Window()->SendMessageToClient(msg, fViewToken, false);
806 	}
807 }
808 
809 void
810 Layer::KeyDown(const BMessage *msg)
811 {
812 	if (Window() && !IsTopLayer()) {
813 		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
814 	}
815 }
816 
817 void
818 Layer::KeyUp(const BMessage *msg)
819 {
820 	if (Window() && !IsTopLayer()) {
821 		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
822 	}
823 }
824 
825 void
826 Layer::UnmappedKeyDown(const BMessage *msg)
827 {
828 	if (Window() && !IsTopLayer()) {
829 		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
830 	}
831 }
832 
833 void
834 Layer::UnmappedKeyUp(const BMessage *msg)
835 {
836 	if (Window() && !IsTopLayer()) {
837 		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
838 	}
839 }
840 
841 void
842 Layer::ModifiersChanged(const BMessage *msg)
843 {
844 	if (Window() && !IsTopLayer()) {
845 		Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
846 	}
847 }
848 
849 void
850 Layer::WorkspaceActivated(int32 index, bool active)
851 {
852 	// Empty
853 }
854 
855 void
856 Layer::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces)
857 {
858 	// Empty
859 }
860 
861 void
862 Layer::Activated(bool active)
863 {
864 	// Empty
865 }
866 
867 
868 BPoint
869 Layer::BoundsOrigin() const
870 {
871 	BPoint origin(fDrawState->Origin());
872 	float scale = Scale();
873 
874 	// TODO: Figure this out, BoundsOrigin()
875 	// is used for BView::Bounds(), but I think
876 	// that the scale has nothing to do with it
877 	// "local coordinate system origin" does have
878 	// something to do with scale.
879 
880 	origin.x *= scale;
881 	origin.y *= scale;
882 
883 	return origin;
884 }
885 
886 
887 float
888 Layer::Scale() const
889 {
890 	return CurrentState()->Scale();
891 }
892 
893 
894 void
895 Layer::AddToViewsWithInvalidCoords() const
896 {
897 	if (fServerWin) {
898 		fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken);
899 		fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop());
900 		fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width());
901 		fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height());
902 	}
903 }
904 
905 
906 void
907 Layer::SendViewCoordUpdateMsg() const
908 {
909 	if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) {
910 		fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords());
911 		fServerWin->ClientViewsWithInvalidCoords().MakeEmpty();
912 	}
913 }
914 
915 
916 void
917 Layer::SetViewColor(const RGBColor& color)
918 {
919 	fViewColor = color;
920 }
921 
922 
923 void
924 Layer::SetBackgroundBitmap(const ServerBitmap* bitmap)
925 {
926 	// TODO: What about reference counting?
927 	// "Release" old fBackgroundBitmap and "Aquire" new one?
928 	fBackgroundBitmap = bitmap;
929 }
930 
931 // SetOverlayBitmap
932 void
933 Layer::SetOverlayBitmap(const ServerBitmap* bitmap)
934 {
935 	// TODO: What about reference counting?
936 	// "Release" old fOverlayBitmap and "Aquire" new one?
937 	fOverlayBitmap = bitmap;
938 }
939 
940 void
941 Layer::CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
942 
943 	GetRootLayer()->Lock();
944 	do_CopyBits(src, dst, xOffset, yOffset);
945 	GetRootLayer()->Unlock();
946 }
947 
948 void
949 Layer::do_CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) {
950 	// NOTE: The correct behaviour is this:
951 	// * The region that is copied is the
952 	//   src rectangle, no matter if it fits
953 	//   into the dst rectangle. It is copied
954 	//   by the offset dst.LeftTop() - src.LeftTop()
955 	// * The dst rectangle is used for invalidation:
956 	//   Any area in the dst rectangle that could
957 	//   not be copied from src (because either the
958 	//   src rectangle was not big enough, or because there
959 	//   were parts cut off by the current layer clipping),
960 	//   are triggering BView::Draw() to be called
961 	//   and for these parts only.
962 
963 	// TODO: having moved this into Layer broke
964 	// offscreen windows (bitmaps)
965 	// -> move back into ServerWindow...
966 	if (!GetRootLayer())
967 		return;
968 
969 	// the region that is going to be copied
970 	BRegion copyRegion(src);
971 	// apply the current clipping of the layer
972 
973 	copyRegion.IntersectWith(&fVisible);
974 
975 	// offset the region to the destination
976 	// and apply the current clipping there as well
977 	copyRegion.OffsetBy(xOffset, yOffset);
978 	copyRegion.IntersectWith(&fVisible);
979 
980 	// the region at the destination that needs invalidation
981 	BRegion redrawReg(dst);
982 	// exclude the region drawn by the copy operation
983 // TODO: quick fix for our scrolling problem. FIX THIS!
984 //	redrawReg.Exclude(&copyRegion);
985 	// apply the current clipping as well
986 	redrawReg.IntersectWith(&fVisible);
987 
988 	// move the region back for the actual operation
989 	copyRegion.OffsetBy(-xOffset, -yOffset);
990 
991 	GetDrawingEngine()->CopyRegion(&copyRegion, xOffset, yOffset);
992 
993 	// trigger the redraw
994 	GetRootLayer()->MarkForRedraw(redrawReg);
995 	GetRootLayer()->TriggerRedraw();
996 }
997 
998 void
999 Layer::MovedByHook(float dx, float dy)
1000 {
1001 	if (Window() && !IsTopLayer())
1002 		AddToViewsWithInvalidCoords();
1003 }
1004 
1005 void
1006 Layer::ResizedByHook(float dx, float dy, bool automatic)
1007 {
1008 	if (Window() && !IsTopLayer())
1009 		AddToViewsWithInvalidCoords();
1010 }
1011 
1012 void
1013 Layer::ScrolledByHook(float dx, float dy)
1014 {
1015 	// empty.
1016 }
1017 
1018 //! converts a point from local to parent's coordinate system
1019 void
1020 Layer::ConvertToParent(BPoint* pt) const
1021 {
1022 	if (fParent) {
1023 		BPoint origin = BoundsOrigin();
1024 		pt->x -= origin.x;
1025 		pt->y -= origin.y;
1026 		pt->x += fFrame.left;
1027 		pt->y += fFrame.top;
1028 	}
1029 }
1030 
1031 //! converts a rect from local to parent's coordinate system
1032 void
1033 Layer::ConvertToParent(BRect* rect) const
1034 {
1035 	if (fParent) {
1036 		BPoint origin = BoundsOrigin();
1037 		rect->OffsetBy(-origin.x, -origin.y);
1038 		rect->OffsetBy(fFrame.left, fFrame.top);
1039 	}
1040 }
1041 
1042 //! converts a region from local to parent's coordinate system
1043 void
1044 Layer::ConvertToParent(BRegion* reg) const
1045 {
1046 	if (fParent) {
1047 		BPoint origin = BoundsOrigin();
1048 		reg->OffsetBy(-origin.x, -origin.y);
1049 		reg->OffsetBy(fFrame.left, fFrame.top);
1050 	}
1051 }
1052 
1053 //! converts a point from parent's to local coordinate system
1054 void
1055 Layer::ConvertFromParent(BPoint* pt) const
1056 {
1057 	if (fParent) {
1058 		BPoint origin = BoundsOrigin();
1059 		pt->x += origin.x;
1060 		pt->y += origin.y;
1061 		pt->x -= fFrame.left;
1062 		pt->y -= fFrame.top;
1063 	}
1064 }
1065 
1066 //! converts a rect from parent's to local coordinate system
1067 void
1068 Layer::ConvertFromParent(BRect* rect) const
1069 {
1070 	if (fParent) {
1071 		BPoint origin = BoundsOrigin();
1072 		rect->OffsetBy(origin.x, origin.y);
1073 		rect->OffsetBy(-fFrame.left, -fFrame.top);
1074 	}
1075 }
1076 
1077 //! converts a region from parent's to local coordinate system
1078 void
1079 Layer::ConvertFromParent(BRegion* reg) const
1080 {
1081 	if (fParent) {
1082 		BPoint origin = BoundsOrigin();
1083 		reg->OffsetBy(origin.x, origin.y);
1084 		reg->OffsetBy(-fFrame.left, -fFrame.top);
1085 	}
1086 }
1087 
1088 //! converts a point from local to screen coordinate system
1089 void
1090 Layer::ConvertToScreen(BPoint* pt) const
1091 {
1092 	if (fParent) {
1093 		ConvertToParent(pt);
1094 		fParent->ConvertToScreen(pt);
1095 	}
1096 }
1097 
1098 //! converts a rect from local to screen coordinate system
1099 void
1100 Layer::ConvertToScreen(BRect* rect) const
1101 {
1102 	if (fParent) {
1103 		ConvertToParent(rect);
1104 		fParent->ConvertToScreen(rect);
1105 	}
1106 }
1107 
1108 //! converts a region from local to screen coordinate system
1109 void
1110 Layer::ConvertToScreen(BRegion* reg) const
1111 {
1112 	if (fParent) {
1113 		ConvertToParent(reg);
1114 		fParent->ConvertToScreen(reg);
1115 	}
1116 }
1117 
1118 //! converts a point from screen to local coordinate system
1119 void
1120 Layer::ConvertFromScreen(BPoint* pt) const
1121 {
1122 	if (fParent) {
1123 		ConvertFromParent(pt);
1124 		fParent->ConvertFromScreen(pt);
1125 	}
1126 }
1127 
1128 //! converts a rect from screen to local coordinate system
1129 void
1130 Layer::ConvertFromScreen(BRect* rect) const
1131 {
1132 	if (fParent) {
1133 		ConvertFromParent(rect);
1134 		fParent->ConvertFromScreen(rect);
1135 	}
1136 }
1137 
1138 //! converts a region from screen to local coordinate system
1139 void
1140 Layer::ConvertFromScreen(BRegion* reg) const
1141 {
1142 	if (fParent) {
1143 		ConvertFromParent(reg);
1144 		fParent->ConvertFromScreen(reg);
1145 	}
1146 }
1147 
1148 
1149 void
1150 Layer::do_Hide()
1151 {
1152 	fHidden = true;
1153 
1154 	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1155 		// save fullVisible so we know what to invalidate
1156 		BRegion invalid(fFullVisible);
1157 
1158 		_ClearVisibleRegions();
1159 
1160 		if (invalid.CountRects() > 0) {
1161 			fParent->MarkForRebuild(invalid);
1162 			GetRootLayer()->MarkForRedraw(invalid);
1163 
1164 			fParent->TriggerRebuild();
1165 			GetRootLayer()->TriggerRedraw();
1166 		}
1167 	}
1168 }
1169 
1170 
1171 void
1172 Layer::do_Show()
1173 {
1174 	fHidden = false;
1175 
1176 	if (fParent && !fParent->IsHidden() && GetRootLayer()) {
1177 		BRegion invalid;
1178 
1179 		GetOnScreenRegion(invalid);
1180 
1181 		if (invalid.CountRects() > 0) {
1182 			fParent->MarkForRebuild(invalid);
1183 			GetRootLayer()->MarkForRedraw(invalid);
1184 
1185 			fParent->TriggerRebuild();
1186 			GetRootLayer()->TriggerRedraw();
1187 		}
1188 	}
1189 }
1190 
1191 
1192 void
1193 Layer::_ResizeLayerFrameBy(float x, float y)
1194 {
1195 	uint16 rm = fResizeMode & 0x0000FFFF;
1196 	BRect newFrame = fFrame;
1197 
1198 	if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8)
1199 		newFrame.left += 0.0f;
1200 	else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
1201 		newFrame.left += x;
1202 	else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
1203 		newFrame.left += x/2;
1204 
1205 	if ((rm & 0x000FU) == _VIEW_LEFT_)
1206 		newFrame.right += 0.0f;
1207 	else if ((rm & 0x000FU) == _VIEW_RIGHT_)
1208 		newFrame.right += x;
1209 	else if ((rm & 0x000FU) == _VIEW_CENTER_)
1210 		newFrame.right += x/2;
1211 
1212 	if ((rm & 0xF000U) == _VIEW_TOP_ << 12)
1213 		newFrame.top += 0.0f;
1214 	else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
1215 		newFrame.top += y;
1216 	else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
1217 		newFrame.top += y/2;
1218 
1219 	if ((rm & 0x00F0U) == _VIEW_TOP_ << 4)
1220 		newFrame.bottom += 0.0f;
1221 	else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
1222 		newFrame.bottom += y;
1223 	else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
1224 		newFrame.bottom += y/2;
1225 /*
1226 	if (newFrame != fFrame) {
1227 		float offsetX, offsetY;
1228 		float dx, dy;
1229 
1230 		dx = newFrame.Width() - fFrame.Width();
1231 		dy = newFrame.Height() - fFrame.Height();
1232 		offsetX = newFrame.left - fFrame.left;
1233 		offsetY = newFrame.top - fFrame.top;
1234 
1235 		fFrame = newFrame;
1236 
1237 		if (offsetX != 0.0f || offsetY != 0.0f) {
1238 			MovedByHook(offsetX, offsetY);
1239 		}
1240 
1241 		if (dx != 0.0f || dy != 0.0f) {
1242 			// call hook function
1243 			ResizedByHook(dx, dy, true); // automatic
1244 
1245 			for (Layer* child = LastChild(); child; child = PreviousChild())
1246 				child->resize_layer_frame_by(dx, dy);
1247 		}
1248 	}
1249 */
1250 // TODO: the above code is CORRECT!!!
1251 // It's commented because BView::FrameResized()/Moved() be called twice a given view. FIX THIS!
1252 	if (newFrame != fFrame) {
1253 		float dx, dy;
1254 
1255 		dx = newFrame.Width() - fFrame.Width();
1256 		dy = newFrame.Height() - fFrame.Height();
1257 
1258 		fFrame = newFrame;
1259 
1260 		if (dx != 0.0f || dy != 0.0f) {
1261 			// call hook function
1262 			ResizedByHook(dx, dy, true); // automatic
1263 
1264 			for (Layer *child = LastChild(); child != NULL; child = PreviousChild())
1265 				child->_ResizeLayerFrameBy(dx, dy);
1266 		} else
1267 			MovedByHook(dx, dy);
1268 	}
1269 }
1270 
1271 
1272 void
1273 Layer::_RezizeLayerRedrawMore(BRegion &reg, float dx, float dy)
1274 {
1275 	if (dx == 0 && dy == 0)
1276 		return;
1277 
1278 	for (Layer* child = LastChild(); child; child = PreviousChild()) {
1279 		uint16 rm = child->fResizeMode & 0x0000FFFF;
1280 
1281 		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1282 			// NOTE: this is not exactly corect, but it works :-)
1283 			// Normaly we shoud've used the child's old, required region - the one returned
1284 			// from get_user_region() with the old frame, and the current one. child->Bounds()
1285 			// works for the moment so we leave it like this.
1286 
1287 			// calculate the old bounds.
1288 			BRect	oldBounds(child->Bounds());
1289 			if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
1290 				oldBounds.right -=dx;
1291 			if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
1292 				oldBounds.bottom -=dy;
1293 
1294 			// compute the region that became visible because we got bigger OR smaller.
1295 			BRegion	regZ(child->Bounds());
1296 			regZ.Include(oldBounds);
1297 			regZ.Exclude(oldBounds & child->Bounds());
1298 
1299 			child->ConvertToScreen(&regZ);
1300 
1301 			// intersect that with this'(not child's) fullVisible region
1302 			regZ.IntersectWith(&fFullVisible);
1303 			reg.Include(&regZ);
1304 
1305 			child->_RezizeLayerRedrawMore(reg,
1306 				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1307 				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1308 
1309 			// above, OR this:
1310 			// reg.Include(&child->fFullVisible);
1311 		} else if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0)
1312 			|| ((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0)
1313 			|| ((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)
1314 			|| ((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0)) {
1315 			reg.Include(&child->fFullVisible);
1316 		}
1317 	}
1318 }
1319 
1320 
1321 void
1322 Layer::_ResizeLayerFullUpdateOnResize(BRegion &reg, float dx, float dy)
1323 {
1324 	if (dx == 0 && dy == 0)
1325 		return;
1326 
1327 	for (Layer* child = LastChild(); child; child = PreviousChild()) {
1328 		uint16 rm = child->fResizeMode & 0x0000FFFF;
1329 
1330 		if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
1331 			if (child->fFlags & B_FULL_UPDATE_ON_RESIZE && child->fVisible.CountRects() > 0)
1332 				reg.Include(&child->fVisible);
1333 
1334 			child->_ResizeLayerFullUpdateOnResize(reg,
1335 				(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
1336 				(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
1337 		}
1338 	}
1339 }
1340 
1341 
1342 /*!
1343 	\brief Returns the region of the layer that is within the screen region
1344 */
1345 void
1346 Layer::GetOnScreenRegion(BRegion &region)
1347 {
1348 	// 1) set to frame in screen coords
1349 	BRect frame(Bounds());
1350 	ConvertToScreen(&frame);
1351 	region.Set(frame);
1352 
1353 	// 2) intersect with screen region
1354 	BRegion screenRegion(GetRootLayer()->Bounds());
1355 	region.IntersectWith(&screenRegion);
1356 
1357 /*
1358 	// 3) impose user constrained regions
1359 	DrawState *stackData = fDrawState;
1360 	while (stackData) {
1361 		if (stackData->ClippingRegion()) {
1362 			reg.IntersectWith(stackData->ClippingRegion());
1363 		}
1364 		stackData = stackData->PreviousState();
1365 	}*/
1366 }
1367 
1368 
1369 void
1370 Layer::_RebuildVisibleRegions(const BRegion &invalid,
1371 	const BRegion &parentLocalVisible, const Layer *startFrom)
1372 {
1373 /*
1374 	// no point in continuing if this layer is hidden.
1375 	if (fHidden)
1376 		return;
1377 
1378 	// no need to go deeper if the parent doesn't have a visible region anymore
1379 	// and our fullVisible region is also empty.
1380 	if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible.CountRects() > 0))
1381 		return;
1382 
1383 	bool fullRebuild = false;
1384 
1385 	// intersect maximum wanted region with the invalid region
1386 	BRegion common;
1387 	GetOnScreenRegion(common);
1388 	common.IntersectWith(&invalid);
1389 
1390 	// if the resulted region is not valid, this layer is not in the catchment area
1391 	// of the region being invalidated
1392 	if (!common.CountRects() > 0)
1393 		return;
1394 
1395 	// now intersect with parent's visible part of the region that was/is invalidated
1396 	common.IntersectWith(&parentLocalVisible);
1397 
1398 	// exclude the invalid region
1399 	fFullVisible.Exclude(&invalid);
1400 	fVisible.Exclude(&invalid);
1401 
1402 	// put in what's really visible
1403 	fFullVisible.Include(&common);
1404 
1405 	// allow this layer to hide some parts from its children
1406 	_ReserveRegions(common);
1407 
1408 	for (Layer *child = LastChild(); child; child = PreviousChild()) {
1409 		if (child == startFrom)
1410 			fullRebuild = true;
1411 
1412 		if (fullRebuild)
1413 			child->_RebuildVisibleRegions(invalid, common, child->LastChild());
1414 
1415 		// to let children know much they can take from parent's visible region
1416 		common.Exclude(&child->fFullVisible);
1417 	}
1418 
1419 	// include what's left after all children took what they could.
1420 	fVisible.Include(&common);
1421 */
1422 
1423 // NOTE: I modified this method for the moment because of some issues that I have
1424 //		 with the new public methods that I recently introduced.
1425 //		 This code works very well, the single problem that it has it's that it
1426 //		 rebuilds all the visible regions of its descendants.
1427 // TODO: only rebuild what's needed. See above code.
1428 // NOTE2: this does not affect the redrawing code.
1429 
1430 	// no point in continuing if this layer is hidden.
1431 	if (fHidden)
1432 		return;
1433 
1434 	// no need to go deeper if the parent doesn't have a visible region anymore
1435 	if (!parentLocalVisible.Frame().IsValid())
1436 		return;
1437 
1438 	BRegion common;
1439 	GetOnScreenRegion(common);
1440 
1441 	// see how much you can take
1442 	common.IntersectWith(&parentLocalVisible);
1443 	fFullVisible = common;
1444 	fVisible.MakeEmpty();
1445 
1446 	// allow this layer to hide some parts from its children
1447 	_ReserveRegions(common);
1448 
1449 	for (Layer *child = LastChild(); child; child = PreviousChild()) {
1450 		child->_RebuildVisibleRegions(invalid, common, child->LastChild());
1451 
1452 		// to let children know much they can take from parent's visible region
1453 		common.Exclude(&child->fFullVisible);
1454 	}
1455 
1456 	// include what's left after all children took what they could.
1457 	fVisible.Include(&common);
1458 
1459 	_RebuildDrawingRegion();
1460 }
1461 
1462 // _RebuildDrawingRegion
1463 void
1464 Layer::_RebuildDrawingRegion()
1465 {
1466 	fDrawingRegion = fVisible;
1467 	// apply user clipping which is in native coordinate system
1468 	if (const BRegion* userClipping = fDrawState->ClippingRegion()) {
1469 		BRegion screenUserClipping(*userClipping);
1470 		ConvertToScreen(&screenUserClipping);
1471 		fDrawingRegion.IntersectWith(&screenUserClipping);
1472 	}
1473 }
1474 
1475 void
1476 Layer::_ReserveRegions(BRegion &reg)
1477 {
1478 	// Empty for Layer objects
1479 }
1480 
1481 void
1482 Layer::_ClearVisibleRegions()
1483 {
1484 	fDrawingRegion.MakeEmpty();
1485 
1486 	fVisible.MakeEmpty();
1487 	fFullVisible.MakeEmpty();
1488 	for (Layer *child = LastChild(); child; child = PreviousChild())
1489 		child->_ClearVisibleRegions();
1490 }
1491 
1492 // mark a region dirty so that the next region rebuild for us
1493 // and our children will take this into account
1494 void
1495 Layer::MarkForRebuild(const BRegion &dirty)
1496 {
1497 	fDirtyForRebuild.Include(&dirty);
1498 }
1499 
1500 // this will trigger visible region recalculation for us and
1501 // our descendants.
1502 void
1503 Layer::TriggerRebuild()
1504 {
1505 	BRegion totalInvalidReg;
1506 
1507 	_GetAllRebuildDirty(&totalInvalidReg);
1508 
1509 	if (totalInvalidReg.CountRects() > 0) {
1510 		BRegion localFullVisible(fFullVisible);
1511 
1512 //		localFullVisible.IntersectWith(&totalInvalidReg);
1513 
1514 		_ClearVisibleRegions();
1515 
1516 		_RebuildVisibleRegions(totalInvalidReg, localFullVisible, LastChild());
1517 	}
1518 }
1519 
1520 // find out the region for which we must rebuild the visible regions
1521 void
1522 Layer::_GetAllRebuildDirty(BRegion *totalReg)
1523 {
1524 	totalReg->Include(&fDirtyForRebuild);
1525 
1526 	for (Layer *child = LastChild(); child; child = PreviousChild())
1527 		child->_GetAllRebuildDirty(totalReg);
1528 
1529 	fDirtyForRebuild.MakeEmpty();
1530 }
1531 
1532 void
1533 Layer::_AllRedraw(const BRegion &invalid)
1534 {
1535 	// couldn't find a simpler way to send _UPDATE_ message to client.
1536 	WinBorder *wb = dynamic_cast<WinBorder*>(this);
1537 	if (wb)
1538 		wb->RequestClientRedraw(invalid);
1539 
1540 	if (fVisible.CountRects() > 0) {
1541 		BRegion	updateReg(fVisible);
1542 		updateReg.IntersectWith(&invalid);
1543 
1544 		if (updateReg.CountRects() > 0) {
1545 			fDriver->ConstrainClippingRegion(&updateReg);
1546 			Draw(updateReg.Frame());
1547 			fDriver->ConstrainClippingRegion(NULL);
1548 		}
1549 	}
1550 
1551 	for (Layer *child = LastChild(); child != NULL; child = PreviousChild()) {
1552 		if (!(child->IsHidden())) {
1553 			BRegion common(child->fFullVisible);
1554 			common.IntersectWith(&invalid);
1555 
1556 			if (common.CountRects() > 0)
1557 				child->_AllRedraw(invalid);
1558 		}
1559 	}
1560 }
1561 
1562