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