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(©Region); 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(©Region, 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 ®, 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(®Z); 1300 1301 // intersect that with this'(not child's) fullVisible region 1302 regZ.IntersectWith(&fFullVisible); 1303 reg.Include(®Z); 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 ®, 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 ®ion) 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 ®) 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