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 #ifndef NEW_CLIPPING 1121 pt -= BoundsOrigin(); 1122 pt += fFrame.LeftTop(); 1123 return pt; 1124 #else 1125 ConvertToParent2(&pt); 1126 return pt; 1127 #endif 1128 } 1129 1130 //! Converts the passed rectangle to parent coordinates 1131 BRect 1132 Layer::ConvertToParent(BRect rect) 1133 { 1134 #ifndef NEW_CLIPPING 1135 // rect.OffsetBy(fFrame.LeftTop()); 1136 // return rect; 1137 rect.OffsetBy(-BoundsOrigin().x, -BoundsOrigin().y); 1138 rect.OffsetBy(fFrame.LeftTop()); 1139 return rect; 1140 #else 1141 ConvertToParent2(&rect); 1142 return rect; 1143 #endif 1144 } 1145 1146 //! Converts the passed region to parent coordinates 1147 BRegion 1148 Layer::ConvertToParent(BRegion* reg) 1149 { 1150 #ifndef NEW_CLIPPING 1151 // TODO: wouldn't it be more efficient to use the copy 1152 // constructor for BRegion and then call OffsetBy()? 1153 BRegion newreg; 1154 for (int32 i = 0; i < reg->CountRects(); i++) 1155 newreg.Include(ConvertToParent(reg->RectAt(i))); 1156 return newreg; 1157 #else 1158 BRegion newReg(*reg); 1159 ConvertToParent2(&newReg); 1160 return newReg; 1161 #endif 1162 } 1163 1164 //! Converts the passed point from parent coordinates 1165 BPoint 1166 Layer::ConvertFromParent(BPoint pt) 1167 { 1168 #ifndef NEW_CLIPPING 1169 // return pt - fFrame.LeftTop(); 1170 pt -= fFrame.LeftTop(); 1171 pt += BoundsOrigin(); 1172 return pt; 1173 #else 1174 ConvertFromParent2(&pt); 1175 return pt; 1176 #endif 1177 } 1178 1179 //! Converts the passed rectangle from parent coordinates 1180 BRect 1181 Layer::ConvertFromParent(BRect rect) 1182 { 1183 #ifndef NEW_CLIPPING 1184 // rect.OffsetBy(-fFrame.left, -fFrame.top); 1185 // return rect; 1186 rect.OffsetBy(-fFrame.left, -fFrame.top); 1187 rect.OffsetBy(BoundsOrigin()); 1188 return rect; 1189 #else 1190 ConvertFromParent2(&rect); 1191 return rect; 1192 #endif 1193 } 1194 1195 //! Converts the passed region from parent coordinates 1196 BRegion 1197 Layer::ConvertFromParent(BRegion *reg) 1198 { 1199 #ifndef NEW_CLIPPING 1200 BRegion newreg; 1201 for(int32 i=0; i<reg->CountRects();i++) 1202 newreg.Include(ConvertFromParent(reg->RectAt(i))); 1203 return newreg; 1204 #else 1205 BRegion newReg(*reg); 1206 ConvertFromParent2(&newReg); 1207 return newReg; 1208 #endif 1209 } 1210 1211 // ConvertToTop 1212 BPoint 1213 Layer::ConvertToTop(BPoint pt) 1214 { 1215 #ifndef NEW_CLIPPING 1216 if (fParent) { 1217 // return (fParent->ConvertToTop(pt + fFrame.LeftTop())); 1218 pt = ConvertToParent(pt); 1219 return fParent->ConvertToTop(pt); 1220 } else 1221 return pt; 1222 #else 1223 ConvertToScreen2(&pt); 1224 return pt; 1225 #endif 1226 } 1227 1228 //! Converts the passed rectangle to screen coordinates 1229 BRect 1230 Layer::ConvertToTop(BRect rect) 1231 { 1232 #ifndef NEW_CLIPPING 1233 if (fParent) { 1234 // return fParent->ConvertToTop(rect.OffsetByCopy(fFrame.LeftTop())); 1235 rect = ConvertToParent(rect); 1236 return fParent->ConvertToTop(rect); 1237 } else 1238 return rect; 1239 #else 1240 ConvertToScreen2(&rect); 1241 return rect; 1242 #endif 1243 } 1244 1245 //! Converts the passed region to screen coordinates 1246 BRegion 1247 Layer::ConvertToTop(BRegion *reg) 1248 { 1249 #ifndef NEW_CLIPPING 1250 BRegion newreg; 1251 for (int32 i = 0; i < reg->CountRects();i++) 1252 newreg.Include(ConvertToTop(reg->RectAt(i))); 1253 return newreg; 1254 #else 1255 BRegion newReg(*reg); 1256 ConvertToScreen2(&newReg); 1257 return newReg; 1258 #endif 1259 } 1260 1261 // ConvertFromTop 1262 BPoint 1263 Layer::ConvertFromTop(BPoint pt) 1264 { 1265 #ifndef NEW_CLIPPING 1266 if (fParent) { 1267 // return fParent->ConvertFromTop(pt-fFrame.LeftTop()); 1268 pt = ConvertFromParent(pt); 1269 return fParent->ConvertFromTop(pt); 1270 } else 1271 return pt; 1272 #else 1273 ConvertFromScreen2(&pt); 1274 return pt; 1275 #endif 1276 } 1277 1278 //! Converts the passed rectangle from screen coordinates 1279 BRect 1280 Layer::ConvertFromTop(BRect rect) 1281 { 1282 #ifndef NEW_CLIPPING 1283 if (fParent) { 1284 // return fParent->ConvertFromTop(rect.OffsetByCopy(-fFrame.LeftTop().x, 1285 // -fFrame.LeftTop().y)); 1286 rect = ConvertFromParent(rect); 1287 return fParent->ConvertFromTop(rect); 1288 } else 1289 return rect; 1290 #else 1291 ConvertFromScreen2(&rect); 1292 return rect; 1293 #endif 1294 } 1295 1296 //! Converts the passed region from screen coordinates 1297 BRegion 1298 Layer::ConvertFromTop(BRegion *reg) 1299 { 1300 #ifndef NEW_CLIPPING 1301 BRegion newreg; 1302 1303 for (int32 i = 0; i < reg->CountRects(); i++) 1304 newreg.Include(ConvertFromTop(reg->RectAt(i))); 1305 1306 return newreg; 1307 #else 1308 BRegion newReg(*reg); 1309 ConvertFromScreen2(&newReg); 1310 return newReg; 1311 #endif 1312 } 1313 1314 //! Recursively deletes all children of the calling layer 1315 void 1316 Layer::PruneTree(void) 1317 { 1318 1319 Layer* lay; 1320 Layer* nextlay; 1321 1322 lay = fTopChild; 1323 fTopChild = NULL; 1324 1325 while (lay != NULL) { 1326 if (lay->fTopChild != NULL) 1327 lay->PruneTree(); 1328 1329 nextlay = lay->fLowerSibling; 1330 lay->fLowerSibling = NULL; 1331 1332 delete lay; 1333 lay = nextlay; 1334 } 1335 // Man, this thing is short. Elegant, ain't it? :P 1336 } 1337 1338 //! Prints information about the layer's current state 1339 void 1340 Layer::PrintToStream() 1341 { 1342 printf("\n *** Layer %s:\n", Name()); 1343 printf("\t Parent: %s", fParent ? fParent->Name() : "<no parent>"); 1344 1345 printf("\t us: %s\t ls: %s\n", 1346 fUpperSibling ? fUpperSibling->Name() : "<none>", 1347 fLowerSibling ? fLowerSibling->Name() : "<none>"); 1348 1349 printf("\t topChild: %s\t bottomChild: %s\n", 1350 fTopChild ? fTopChild->Name() : "<none>", 1351 fBottomChild ? fBottomChild->Name() : "<none>"); 1352 1353 printf("Frame: (%f, %f, %f, %f)\n", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom); 1354 printf("LocalOrigin: (%f, %f)\n", BoundsOrigin().x, BoundsOrigin().y); 1355 printf("Token: %ld\n", fViewToken); 1356 printf("Hidden - direct: %s ", fHidden?"true":"false"); 1357 printf("Hidden - indirect: %s\n", IsHidden()?"true":"false"); 1358 printf("ResizingMode: %lx ", fResizeMode); 1359 printf("Flags: %lx\n", fFlags); 1360 1361 if (fLayerData) 1362 fLayerData->PrintToStream(); 1363 else 1364 printf(" NO LayerData valid pointer\n"); 1365 } 1366 1367 //! Prints pointer info kept by the current layer 1368 void 1369 Layer::PrintNode() 1370 { 1371 printf("-----------\nLayer %s\n", Name()); 1372 if (fParent) 1373 printf("Parent: %s (%p)\n", fParent->Name(), fParent); 1374 else 1375 printf("Parent: NULL\n"); 1376 1377 if (fUpperSibling) 1378 printf("Upper sibling: %s (%p)\n", fUpperSibling->Name(), fUpperSibling); 1379 else 1380 printf("Upper sibling: NULL\n"); 1381 1382 if (fLowerSibling) 1383 printf("Lower sibling: %s (%p)\n", fLowerSibling->Name(), fLowerSibling); 1384 else 1385 printf("Lower sibling: NULL\n"); 1386 1387 if (fTopChild) 1388 printf("Top child: %s (%p)\n", fTopChild->Name(), fTopChild); 1389 else 1390 printf("Top child: NULL\n"); 1391 1392 if (fBottomChild) 1393 printf("Bottom child: %s (%p)\n", fBottomChild->Name(), fBottomChild); 1394 else 1395 printf("Bottom child: NULL\n"); 1396 #ifndef NEW_CLIPPING 1397 printf("Visible Areas: "); fVisible.PrintToStream(); 1398 #endif 1399 } 1400 1401 //! Prints the tree hierarchy from the current layer down 1402 void 1403 Layer::PrintTree() 1404 { 1405 printf("\n Tree structure:\n"); 1406 printf("\t%s\t%s\n", Name(), IsHidden()? "Hidden": "NOT hidden"); 1407 for(Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) 1408 printf("\t%s\t%s\n", lay->Name(), lay->IsHidden()? "Hidden": "NOT hidden"); 1409 } 1410 1411 // RequestDraw 1412 void 1413 Layer::RequestDraw(const BRegion ®, Layer *startFrom) 1414 { 1415 STRACE(("Layer(%s)::RequestDraw()\n", Name())); 1416 1417 // do not redraw any child until you must 1418 int redraw = false; 1419 if (!startFrom) 1420 redraw = true; 1421 1422 #ifndef NEW_CLIPPING 1423 if (HasClient() && IsTopLayer()) { 1424 // calculate the minimum region/rectangle to be updated with 1425 // a single message to the client. 1426 BRegion updateReg(fFullVisible); 1427 1428 if (fFlags & B_FULL_UPDATE_ON_RESIZE 1429 && fFrameAction == B_LAYER_ACTION_RESIZE) 1430 { 1431 // do nothing 1432 } else { 1433 updateReg.IntersectWith(®); 1434 } 1435 if (updateReg.CountRects() > 0) { 1436 fOwner->fCumulativeRegion.Include(&updateReg); 1437 if (!fOwner->InUpdate() && !fOwner->fRequestSent) { 1438 fOwner->fInUpdateRegion = fOwner->fCumulativeRegion; 1439 fOwner->cnt++; 1440 if (fOwner->cnt != 1) 1441 CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!"); 1442 fOwner->fCumulativeRegion.MakeEmpty(); 1443 fOwner->fRequestSent = true; 1444 SendUpdateMsg(fOwner->fInUpdateRegion); 1445 } 1446 } 1447 } 1448 1449 if (fVisible.CountRects() > 0) { 1450 BRegion updateReg(fVisible); 1451 // calculate the update region 1452 if (fFlags & B_FULL_UPDATE_ON_RESIZE && fFrameAction == B_LAYER_ACTION_RESIZE) { 1453 // do nothing 1454 } else { 1455 updateReg.IntersectWith(®); 1456 } 1457 1458 if (updateReg.CountRects() > 0) { 1459 fDriver->ConstrainClippingRegion(&updateReg); 1460 Draw(updateReg.Frame()); 1461 fDriver->ConstrainClippingRegion(NULL); 1462 } 1463 } 1464 1465 for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) { 1466 if (lay == startFrom) 1467 redraw = true; 1468 1469 if (redraw && !(lay->IsHidden())) { 1470 // no need to go deeper if not even the FullVisible region intersects 1471 // Update one. 1472 BRegion common(lay->fFullVisible); 1473 common.IntersectWith(®); 1474 1475 if (common.CountRects() > 0) 1476 lay->RequestDraw(reg, NULL); 1477 } 1478 } 1479 #else 1480 if (HasClient() && IsTopLayer()) { 1481 // calculate the minimum region/rectangle to be updated with 1482 // a single message to the client. 1483 BRegion updateReg(fFullVisible2); 1484 1485 updateReg.IntersectWith(®); 1486 1487 if (updateReg.CountRects() > 0) { 1488 fOwner->fCumulativeRegion.Include(&updateReg); 1489 if (!fOwner->InUpdate() && !fOwner->fRequestSent) { 1490 fOwner->fInUpdateRegion = fOwner->fCumulativeRegion; 1491 fOwner->cnt++; 1492 if (fOwner->cnt != 1) 1493 CRITICAL("Layer::RequestDraw(): fOwner->cnt != 1 -> Not Allowed!"); 1494 fOwner->fCumulativeRegion.MakeEmpty(); 1495 fOwner->fRequestSent = true; 1496 SendUpdateMsg(fOwner->fInUpdateRegion); 1497 } 1498 } 1499 } 1500 1501 if (fVisible2.CountRects() > 0) { 1502 BRegion updateReg(fVisible2); 1503 updateReg.IntersectWith(®); 1504 1505 if (updateReg.CountRects() > 0) { 1506 fDriver->ConstrainClippingRegion(&updateReg); 1507 Draw(updateReg.Frame()); 1508 fDriver->ConstrainClippingRegion(NULL); 1509 } 1510 } 1511 1512 for (Layer *lay = BottomChild(); lay != NULL; lay = UpperSibling()) { 1513 if (lay == startFrom) 1514 redraw = true; 1515 1516 if (redraw && !(lay->IsHidden())) { 1517 // no need to go deeper if not even the FullVisible region intersects 1518 // Update one. 1519 BRegion common(lay->fFullVisible2); 1520 common.IntersectWith(®); 1521 1522 if (common.CountRects() > 0) 1523 lay->RequestDraw(reg, NULL); 1524 } 1525 } 1526 #endif 1527 } 1528 1529 #ifndef NEW_CLIPPING 1530 1531 // move_layer 1532 void 1533 Layer::move_layer(float x, float y) 1534 { 1535 /* if (fClassID == AS_WINBORDER_CLASS) { 1536 WinBorder *wb = (WinBorder*)this; 1537 wb->fCumulativeRegion.OffsetBy(x, y); 1538 wb->fInUpdateRegion.OffsetBy(x, y); 1539 wb->fSavedForUpdateRegion.OffsetBy(x, y); 1540 }*/ 1541 1542 fFrameAction = B_LAYER_ACTION_MOVE; 1543 1544 BPoint pt(x, y); 1545 BRect rect(fFull.Frame().OffsetByCopy(pt)); 1546 1547 if (!fParent) { 1548 printf("no parent in Layer::move_layer() (%s)\n", Name()); 1549 fFrameAction = B_LAYER_ACTION_NONE; 1550 return; 1551 } 1552 1553 fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_MOVE, pt); 1554 1555 fDriver->CopyRegionList(&fRootLayer->fCopyRegList, 1556 &fRootLayer->fCopyList, 1557 fRootLayer->fCopyRegList.CountItems(), 1558 &fFullVisible); 1559 1560 fParent->Redraw(fRootLayer->fRedrawReg, this); 1561 1562 // redraw workspaces layer 1563 if (dynamic_cast<WinBorder*>(this) != NULL && fRootLayer->WorkspacesLayer() != NULL) { 1564 fRootLayer->GoRedraw(fRootLayer->WorkspacesLayer(), fRootLayer->WorkspacesLayer()->fVisible); 1565 } 1566 1567 SendViewCoordUpdateMsg(); 1568 1569 EmptyGlobals(); 1570 1571 fFrameAction = B_LAYER_ACTION_NONE; 1572 } 1573 1574 // resize_layer 1575 void 1576 Layer::resize_layer(float x, float y) 1577 { 1578 fFrameAction = B_LAYER_ACTION_RESIZE; 1579 1580 BPoint pt(x,y); 1581 1582 BRect rect(fFull.Frame()); 1583 rect.right += x; 1584 rect.bottom += y; 1585 1586 if (!fParent) { 1587 printf("no parent in Layer::resize_layer() (%s)\n", Name()); 1588 fFrameAction = B_LAYER_ACTION_NONE; 1589 return; 1590 } 1591 1592 fParent->StartRebuildRegions(BRegion(rect), this, B_LAYER_RESIZE, pt); 1593 1594 fDriver->CopyRegionList(&fRootLayer->fCopyRegList, &fRootLayer->fCopyList, fRootLayer->fCopyRegList.CountItems(), &fFullVisible); 1595 1596 fParent->Redraw(fRootLayer->fRedrawReg, this); 1597 1598 // redraw workspaces layer 1599 if (dynamic_cast<WinBorder*>(this) != NULL && fRootLayer->WorkspacesLayer() != NULL) { 1600 fRootLayer->GoRedraw(fRootLayer->WorkspacesLayer(), fRootLayer->WorkspacesLayer()->fVisible); 1601 } 1602 1603 SendViewCoordUpdateMsg(); 1604 1605 EmptyGlobals(); 1606 1607 fFrameAction = B_LAYER_ACTION_NONE; 1608 } 1609 1610 // FullInvalidate 1611 void 1612 Layer::FullInvalidate(const BRect &rect) 1613 { 1614 FullInvalidate(BRegion(rect)); 1615 } 1616 1617 // FullInvalidate 1618 void 1619 Layer::FullInvalidate(const BRegion& region) 1620 { 1621 STRACE(("Layer(%s)::FullInvalidate():\n", Name())); 1622 1623 #ifdef DEBUG_LAYER 1624 region.PrintToStream(); 1625 printf("\n"); 1626 #endif 1627 1628 BPoint pt(0,0); 1629 StartRebuildRegions(region, NULL,/* B_LAYER_INVALIDATE, pt); */B_LAYER_NONE, pt); 1630 1631 Redraw(fRootLayer->fRedrawReg); 1632 1633 EmptyGlobals(); 1634 } 1635 1636 // Invalidate 1637 void 1638 Layer::Invalidate(const BRegion& region) 1639 { 1640 STRACE(("Layer(%s)::Invalidate():\n", Name())); 1641 #ifdef DEBUG_LAYER 1642 region.PrintToStream(); 1643 printf("\n"); 1644 #endif 1645 1646 fRootLayer->fRedrawReg = region; 1647 1648 Redraw(fRootLayer->fRedrawReg); 1649 1650 EmptyGlobals(); 1651 } 1652 1653 #endif // 5 methods 1654 1655 1656 /*! 1657 \brief Returns the layer's ServerWindow 1658 1659 If the layer's ServerWindow has not been assigned, it attempts to find 1660 the owning ServerWindow in the tree. 1661 */ 1662 ServerWindow* 1663 Layer::SearchForServerWindow() 1664 { 1665 if (!fServerWin) 1666 fServerWin=fParent->SearchForServerWindow(); 1667 1668 return fServerWin; 1669 } 1670 1671 //! Sends an _UPDATE_ message to the client BWindow 1672 void 1673 Layer::SendUpdateMsg(BRegion& reg) 1674 { 1675 BMessage msg; 1676 msg.what = _UPDATE_; 1677 #ifndef NEW_CLIPPING 1678 msg.AddRect("_rect", ConvertFromTop(reg.Frame())); 1679 #else 1680 BRect rect(reg.Frame()); 1681 ConvertFromScreen2(&rect); 1682 msg.AddRect("_rect", rect ); 1683 #endif 1684 msg.AddRect("debug_rect", reg.Frame()); 1685 // msg.AddInt32("_token",fViewToken); 1686 1687 fOwner->Window()->SendMessageToClient(&msg); 1688 } 1689 1690 // AddToViewsWithInvalidCoords 1691 void 1692 Layer::AddToViewsWithInvalidCoords() const 1693 { 1694 if (fServerWin) { 1695 fServerWin->ClientViewsWithInvalidCoords().AddInt32("_token", fViewToken); 1696 fServerWin->ClientViewsWithInvalidCoords().AddPoint("where", fFrame.LeftTop()); 1697 fServerWin->ClientViewsWithInvalidCoords().AddFloat("width", fFrame.Width()); 1698 fServerWin->ClientViewsWithInvalidCoords().AddFloat("height", fFrame.Height()); 1699 } 1700 } 1701 1702 // SendViewCoordUpdateMsg 1703 void 1704 Layer::SendViewCoordUpdateMsg() const 1705 { 1706 if (fServerWin && !fServerWin->ClientViewsWithInvalidCoords().IsEmpty()) { 1707 fServerWin->SendMessageToClient(&fServerWin->ClientViewsWithInvalidCoords()); 1708 fServerWin->ClientViewsWithInvalidCoords().MakeEmpty(); 1709 } 1710 } 1711 1712 // SetViewColor 1713 void 1714 Layer::SetViewColor(const RGBColor& color) 1715 { 1716 fViewColor = color; 1717 } 1718 1719 // SetBackgroundBitmap 1720 void 1721 Layer::SetBackgroundBitmap(const ServerBitmap* bitmap) 1722 { 1723 // TODO: What about reference counting? 1724 // "Release" old fBackgroundBitmap and "Aquire" new one? 1725 fBackgroundBitmap = bitmap; 1726 } 1727 1728 // SetOverlayBitmap 1729 void 1730 Layer::SetOverlayBitmap(const ServerBitmap* bitmap) 1731 { 1732 // TODO: What about reference counting? 1733 // "Release" old fOverlayBitmap and "Aquire" new one? 1734 fOverlayBitmap = bitmap; 1735 } 1736 1737 void 1738 Layer::CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) { 1739 1740 BPrivate::PortLink msg(-1, -1); 1741 msg.StartMessage(AS_ROOTLAYER_LAYER_COPYBITS); 1742 msg.Attach<Layer*>(this); 1743 msg.Attach<BRect>(src); 1744 msg.Attach<BRect>(dst); 1745 msg.Attach<int32>(xOffset); 1746 msg.Attach<int32>(yOffset); 1747 GetRootLayer()->EnqueueMessage(msg); 1748 } 1749 1750 void 1751 Layer::do_CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset) { 1752 // NOTE: The correct behaviour is this: 1753 // * The region that is copied is the 1754 // src rectangle, no matter if it fits 1755 // into the dst rectangle. It is copied 1756 // by the offset dst.LeftTop() - src.LeftTop() 1757 // * The dst rectangle is used for invalidation: 1758 // Any area in the dst rectangle that could 1759 // not be copied from src (because either the 1760 // src rectangle was not big enough, or because there 1761 // were parts cut off by the current layer clipping), 1762 // are triggering BView::Draw() to be called 1763 // and for these parts only. 1764 1765 #ifndef NEW_CLIPPING 1766 1767 // the region that is going to be copied 1768 BRegion copyRegion(src); 1769 // apply the current clipping of the layer 1770 1771 copyRegion.IntersectWith(&fVisible); 1772 1773 // offset the region to the destination 1774 // and apply the current clipping there as well 1775 copyRegion.OffsetBy(xOffset, yOffset); 1776 copyRegion.IntersectWith(&fVisible); 1777 1778 // the region at the destination that needs invalidation 1779 GetRootLayer()->fRedrawReg.Set(dst); 1780 // exclude the region drawn by the copy operation 1781 GetRootLayer()->fRedrawReg.Exclude(©Region); 1782 // apply the current clipping as well 1783 GetRootLayer()->fRedrawReg.IntersectWith(&fVisible); 1784 1785 // move the region back for the actual operation 1786 copyRegion.OffsetBy(-xOffset, -yOffset); 1787 1788 GetDisplayDriver()->CopyRegion(©Region, xOffset, yOffset); 1789 1790 // trigger the redraw 1791 GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL); 1792 #else 1793 // the region that is going to be copied 1794 BRegion copyRegion(src); 1795 // apply the current clipping of the layer 1796 1797 copyRegion.IntersectWith(&fVisible2); 1798 1799 // offset the region to the destination 1800 // and apply the current clipping there as well 1801 copyRegion.OffsetBy(xOffset, yOffset); 1802 copyRegion.IntersectWith(&fVisible2); 1803 1804 // the region at the destination that needs invalidation 1805 GetRootLayer()->fRedrawReg.Set(dst); 1806 // exclude the region drawn by the copy operation 1807 GetRootLayer()->fRedrawReg.Exclude(©Region); 1808 // apply the current clipping as well 1809 GetRootLayer()->fRedrawReg.IntersectWith(&fVisible2); 1810 1811 // move the region back for the actual operation 1812 copyRegion.OffsetBy(-xOffset, -yOffset); 1813 1814 GetDisplayDriver()->CopyRegion(©Region, xOffset, yOffset); 1815 1816 // trigger the redraw 1817 GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL); 1818 #endif 1819 1820 } 1821 1822 #ifdef NEW_CLIPPING 1823 1824 void 1825 Layer::MovedByHook(float dx, float dy) 1826 { 1827 if (Window() && Flags() & B_FRAME_EVENTS && !IsTopLayer()) { 1828 BMessage msg(B_VIEW_MOVED); 1829 msg.AddInt64("when", system_time()); 1830 msg.AddPoint("where", Frame().LeftTop()); 1831 Window()->SendMessageToClient(&msg, fViewToken, false); 1832 } 1833 } 1834 1835 void 1836 Layer::ResizedByHook(float dx, float dy, bool automatic) 1837 { 1838 if (Window() && Flags() & B_FRAME_EVENTS && !IsTopLayer()) { 1839 BMessage msg(B_VIEW_RESIZED); 1840 msg.AddInt64("when", system_time()); 1841 msg.AddFloat("width", Frame().Width()); 1842 msg.AddFloat("height", Frame().Height()); 1843 msg.AddPoint("where", Frame().LeftTop()); 1844 Window()->SendMessageToClient(&msg, fViewToken, false); 1845 } 1846 } 1847 1848 void 1849 Layer::ScrolledByHook(float dx, float dy) 1850 { 1851 // empty. 1852 } 1853 1854 1855 void 1856 Layer::GetWantedRegion(BRegion& reg) const 1857 { 1858 // this is the same as get_user_region. 1859 // because get_user_region modifies nothing. 1860 const_cast<Layer*>(this)->Layer::get_user_regions(reg); 1861 } 1862 1863 //! converts a point from local to parent's coordinate system 1864 void 1865 Layer::ConvertToParent2(BPoint* pt) const 1866 { 1867 if (fParent) { 1868 BPoint origin = BoundsOrigin(); 1869 pt->x -= origin.x; 1870 pt->y -= origin.y; 1871 pt->x += fFrame.left; 1872 pt->y += fFrame.top; 1873 } 1874 } 1875 1876 //! converts a rect from local to parent's coordinate system 1877 void 1878 Layer::ConvertToParent2(BRect* rect) const 1879 { 1880 if (fParent) { 1881 BPoint origin = BoundsOrigin(); 1882 rect->OffsetBy(-origin.x, -origin.y); 1883 rect->OffsetBy(fFrame.left, fFrame.top); 1884 } 1885 } 1886 1887 //! converts a region from local to parent's coordinate system 1888 void 1889 Layer::ConvertToParent2(BRegion* reg) const 1890 { 1891 if (fParent) { 1892 BPoint origin = BoundsOrigin(); 1893 reg->OffsetBy(-origin.x, -origin.y); 1894 reg->OffsetBy(fFrame.left, fFrame.top); 1895 } 1896 } 1897 1898 //! converts a point from parent's to local coordinate system 1899 void 1900 Layer::ConvertFromParent2(BPoint* pt) const 1901 { 1902 if (fParent) { 1903 BPoint origin = BoundsOrigin(); 1904 pt->x += origin.x; 1905 pt->y += origin.y; 1906 pt->x -= fFrame.left; 1907 pt->y -= fFrame.top; 1908 } 1909 } 1910 1911 //! converts a rect from parent's to local coordinate system 1912 void 1913 Layer::ConvertFromParent2(BRect* rect) const 1914 { 1915 if (fParent) { 1916 BPoint origin = BoundsOrigin(); 1917 rect->OffsetBy(origin.x, origin.y); 1918 rect->OffsetBy(-fFrame.left, -fFrame.top); 1919 } 1920 } 1921 1922 //! converts a region from parent's to local coordinate system 1923 void 1924 Layer::ConvertFromParent2(BRegion* reg) const 1925 { 1926 if (fParent) { 1927 BPoint origin = BoundsOrigin(); 1928 reg->OffsetBy(origin.x, origin.y); 1929 reg->OffsetBy(-fFrame.left, -fFrame.top); 1930 } 1931 } 1932 1933 //! converts a point from local to screen coordinate system 1934 void 1935 Layer::ConvertToScreen2(BPoint* pt) const 1936 { 1937 if (GetRootLayer()) 1938 if (fParent) { 1939 BPoint origin = BoundsOrigin(); 1940 pt->x -= origin.x; 1941 pt->y -= origin.y; 1942 pt->x += fFrame.left; 1943 pt->y += fFrame.top; 1944 1945 fParent->ConvertToScreen2(pt); 1946 } 1947 } 1948 1949 //! converts a rect from local to screen coordinate system 1950 void 1951 Layer::ConvertToScreen2(BRect* rect) const 1952 { 1953 if (GetRootLayer()) 1954 if (fParent) { 1955 BPoint origin = BoundsOrigin(); 1956 rect->OffsetBy(-origin.x, -origin.y); 1957 rect->OffsetBy(fFrame.left, fFrame.top); 1958 1959 fParent->ConvertToScreen2(rect); 1960 } 1961 } 1962 1963 //! converts a region from local to screen coordinate system 1964 void 1965 Layer::ConvertToScreen2(BRegion* reg) const 1966 { 1967 if (GetRootLayer()) 1968 if (fParent) { 1969 BPoint origin = BoundsOrigin(); 1970 reg->OffsetBy(-origin.x, -origin.y); 1971 reg->OffsetBy(fFrame.left, fFrame.top); 1972 1973 fParent->ConvertToScreen2(reg); 1974 } 1975 } 1976 1977 //! converts a point from screen to local coordinate system 1978 void 1979 Layer::ConvertFromScreen2(BPoint* pt) const 1980 { 1981 if (GetRootLayer()) 1982 if (fParent) { 1983 BPoint origin = BoundsOrigin(); 1984 pt->x += origin.x; 1985 pt->y += origin.y; 1986 pt->x -= fFrame.left; 1987 pt->y -= fFrame.top; 1988 1989 fParent->ConvertToScreen2(pt); 1990 } 1991 } 1992 1993 //! converts a rect from screen to local coordinate system 1994 void 1995 Layer::ConvertFromScreen2(BRect* rect) const 1996 { 1997 if (GetRootLayer()) 1998 if (fParent) { 1999 BPoint origin = BoundsOrigin(); 2000 rect->OffsetBy(origin.x, origin.y); 2001 rect->OffsetBy(-fFrame.left, -fFrame.top); 2002 2003 fParent->ConvertFromScreen2(rect); 2004 } 2005 } 2006 2007 //! converts a region from screen to local coordinate system 2008 void 2009 Layer::ConvertFromScreen2(BRegion* reg) const 2010 { 2011 if (GetRootLayer()) 2012 if (fParent) { 2013 BPoint origin = BoundsOrigin(); 2014 reg->OffsetBy(origin.x, origin.y); 2015 reg->OffsetBy(-fFrame.left, -fFrame.top); 2016 2017 fParent->ConvertFromScreen2(reg); 2018 } 2019 } 2020 2021 2022 void 2023 Layer::do_Hide() 2024 { 2025 fHidden = true; 2026 2027 if (fParent && !fParent->IsHidden() && GetRootLayer()) { 2028 // save fullVisible so we know what to invalidate 2029 BRegion invalid(fFullVisible2); 2030 2031 clear_visible_regions(); 2032 2033 if (invalid.Frame().IsValid()) 2034 fParent->do_Invalidate(invalid, this); 2035 } 2036 } 2037 2038 void 2039 Layer::do_Show() 2040 { 2041 fHidden = false; 2042 2043 if (fParent && !fParent->IsHidden() && GetRootLayer()) { 2044 BRegion invalid; 2045 2046 get_user_regions(invalid); 2047 2048 if (invalid.CountRects() > 0) 2049 fParent->do_Invalidate(invalid, this); 2050 } 2051 } 2052 2053 void 2054 Layer::do_Invalidate(const BRegion &invalid, const Layer *startFrom) 2055 { 2056 BRegion localVisible(fFullVisible2); 2057 localVisible.IntersectWith(&invalid); 2058 rebuild_visible_regions(invalid, localVisible, 2059 startFrom? startFrom: BottomChild()); 2060 2061 // add localVisible to our RootLayer's redraw region. 2062 // GetRootLayer()->fRedrawReg.Include(&localVisible); 2063 GetRootLayer()->fRedrawReg = localVisible; 2064 GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL); 2065 // GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)? 2066 } 2067 2068 void 2069 Layer::do_Redraw(const BRegion &invalid, const Layer *startFrom) 2070 { 2071 BRegion localVisible(fFullVisible2); 2072 localVisible.IntersectWith(&invalid); 2073 2074 // add localVisible to our RootLayer's redraw region. 2075 // GetRootLayer()->fRedrawReg.Include(&localVisible); 2076 GetRootLayer()->fRedrawReg = localVisible; 2077 GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL); 2078 // GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)? 2079 } 2080 2081 inline void 2082 Layer::resize_layer_frame_by(float x, float y) 2083 { 2084 uint16 rm = fResizeMode & 0x0000FFFF; 2085 BRect newFrame = fFrame; 2086 2087 if ((rm & 0x0F00U) == _VIEW_LEFT_ << 8) 2088 newFrame.left += 0.0f; 2089 else if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8) 2090 newFrame.left += x; 2091 else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8) 2092 newFrame.left += x/2; 2093 2094 if ((rm & 0x000FU) == _VIEW_LEFT_) 2095 newFrame.right += 0.0f; 2096 else if ((rm & 0x000FU) == _VIEW_RIGHT_) 2097 newFrame.right += x; 2098 else if ((rm & 0x000FU) == _VIEW_CENTER_) 2099 newFrame.right += x/2; 2100 2101 if ((rm & 0xF000U) == _VIEW_TOP_ << 12) 2102 newFrame.top += 0.0f; 2103 else if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12) 2104 newFrame.top += y; 2105 else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12) 2106 newFrame.top += y/2; 2107 2108 if ((rm & 0x00F0U) == _VIEW_TOP_ << 4) 2109 newFrame.bottom += 0.0f; 2110 else if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4) 2111 newFrame.bottom += y; 2112 else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4) 2113 newFrame.bottom += y/2; 2114 2115 if (newFrame != fFrame) { 2116 float dx, dy; 2117 2118 dx = newFrame.Width() - fFrame.Width(); 2119 dy = newFrame.Height() - fFrame.Height(); 2120 2121 fFrame = newFrame; 2122 2123 if (dx != 0.0f || dy != 0.0f) { 2124 // call hook function 2125 ResizedByHook(dx, dy, true); // automatic 2126 2127 for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) 2128 lay->resize_layer_frame_by(dx, dy); 2129 } 2130 else 2131 MovedByHook(dx, dy); 2132 } 2133 } 2134 2135 inline void 2136 Layer::rezize_layer_redraw_more(BRegion ®, float dx, float dy) 2137 { 2138 if (dx == 0 && dy == 0) 2139 return; 2140 2141 for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) { 2142 uint16 rm = lay->fResizeMode & 0x0000FFFF; 2143 2144 if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) { 2145 // NOTE: this is not exactly corect, but it works :-) 2146 // Normaly we shoud've used the lay's old, required region - the one returned 2147 // from get_user_region() with the old frame, and the current one. lay->Bounds() 2148 // works for the moment so we leave it like this. 2149 2150 // calculate the old bounds. 2151 BRect oldBounds(lay->Bounds()); 2152 if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT) 2153 oldBounds.right -=dx; 2154 if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) 2155 oldBounds.bottom -=dy; 2156 2157 // compute the region that became visible because we got bigger OR smaller. 2158 BRegion regZ(lay->Bounds()); 2159 regZ.Include(oldBounds); 2160 regZ.Exclude(oldBounds&lay->Bounds()); 2161 2162 lay->ConvertToScreen2(®Z); 2163 2164 // intersect that with this'(not lay's) fullVisible region 2165 regZ.IntersectWith(&fFullVisible2); 2166 reg.Include(®Z); 2167 2168 lay->rezize_layer_redraw_more(reg, 2169 (rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0, 2170 (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0); 2171 2172 // above, OR this: 2173 // reg.Include(&lay->fFullVisible2); 2174 } 2175 else 2176 if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) || 2177 ((rm & 0x0F0F) == (uint16)B_FOLLOW_H_CENTER && dx != 0) || 2178 ((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)|| 2179 ((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0)) 2180 { 2181 reg.Include(&lay->fFullVisible2); 2182 } 2183 } 2184 } 2185 2186 inline void 2187 Layer::resize_layer_full_update_on_resize(BRegion ®, float dx, float dy) 2188 { 2189 if (dx == 0 && dy == 0) 2190 return; 2191 2192 for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) { 2193 uint16 rm = lay->fResizeMode & 0x0000FFFF; 2194 2195 if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) { 2196 if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0) 2197 reg.Include(&lay->fVisible2); 2198 2199 lay->resize_layer_full_update_on_resize(reg, 2200 (rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0, 2201 (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0); 2202 } 2203 } 2204 } 2205 2206 void 2207 Layer::do_ResizeBy(float dx, float dy) 2208 { 2209 fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy); 2210 2211 // resize children using their resize_mask. 2212 for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) 2213 lay->resize_layer_frame_by(dx, dy); 2214 2215 // call hook function 2216 if (dx != 0.0f || dy != 0.0f) 2217 ResizedByHook(dx, dy, false); // manual 2218 2219 if (!IsHidden() && GetRootLayer()) { 2220 BRegion oldFullVisible(fFullVisible2); 2221 // this is required to invalidate the old border 2222 BRegion oldVisible(fVisible2); 2223 2224 // in case they moved, bottom, right and center aligned layers must be redrawn 2225 BRegion redrawMore; 2226 rezize_layer_redraw_more(redrawMore, dx, dy); 2227 2228 // we'll invalidate the old area and the new, maxmial one. 2229 BRegion invalid; 2230 get_user_regions(invalid); 2231 invalid.Include(&fFullVisible2); 2232 2233 clear_visible_regions(); 2234 2235 fParent->do_RebuildVisibleRegions(invalid, this); 2236 2237 // done rebuilding regions, now redraw regions that became visible 2238 2239 // what's invalid, are the differences between to old and the new fullVisible region 2240 // 1) in case we grow. 2241 BRegion redrawReg(fFullVisible2); 2242 redrawReg.Exclude(&oldFullVisible); 2243 // 2) in case we shrink 2244 BRegion redrawReg2(oldFullVisible); 2245 redrawReg2.Exclude(&fFullVisible2); 2246 // 3) combine. 2247 redrawReg.Include(&redrawReg2); 2248 2249 // for center, right and bottom alligned layers, redraw their old positions 2250 redrawReg.Include(&redrawMore); 2251 2252 // layers that had their frame modified must be entirely redrawn. 2253 rezize_layer_redraw_more(redrawReg, dx, dy); 2254 2255 // add redrawReg to our RootLayer's redraw region. 2256 // GetRootLayer()->fRedrawReg.Include(&redrawReg); 2257 GetRootLayer()->fRedrawReg = redrawReg; 2258 // include layer's visible region in case we want a full update on resize 2259 if (fFlags & B_FULL_UPDATE_ON_RESIZE && fVisible2.Frame().IsValid()) { 2260 resize_layer_full_update_on_resize(GetRootLayer()->fRedrawReg, dx, dy); 2261 2262 GetRootLayer()->fRedrawReg.Include(&fVisible2); 2263 GetRootLayer()->fRedrawReg.Include(&oldVisible); 2264 } 2265 // clear canvas and set invalid regions for affected WinBorders 2266 GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL); 2267 // GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)? 2268 } 2269 } 2270 2271 void Layer::do_MoveBy(float dx, float dy) 2272 { 2273 if (dx == 0.0f && dy == 0.0f) 2274 return; 2275 2276 // fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy); 2277 fFrame.OffsetBy(dx, dy); 2278 2279 // call hook function 2280 MovedByHook(dx, dy); 2281 2282 if (!IsHidden() && GetRootLayer()) { 2283 BRegion oldFullVisible(fFullVisible2); 2284 2285 // we'll invalidate the old position and the new, maxmial one. 2286 BRegion invalid; 2287 get_user_regions(invalid); 2288 invalid.Include(&fFullVisible2); 2289 2290 clear_visible_regions(); 2291 2292 fParent->do_RebuildVisibleRegions(invalid, this); 2293 2294 // done rebuilding regions, now copy common parts and redraw regions that became visible 2295 2296 // include the actual and the old fullVisible regions. later, we'll exclude the common parts. 2297 BRegion redrawReg(fFullVisible2); 2298 redrawReg.Include(&oldFullVisible); 2299 2300 // offset to layer's new location so that we can calculate the common region. 2301 oldFullVisible.OffsetBy(dx, dy); 2302 2303 // finally we have the region that needs to be redrawn. 2304 redrawReg.Exclude(&oldFullVisible); 2305 2306 // by intersecting the old fullVisible offseted to layer's new location, with the current 2307 // fullVisible, we'll have the common region which can be copied using HW acceleration. 2308 oldFullVisible.IntersectWith(&fFullVisible2); 2309 2310 // offset back and instruct the HW to do the actual copying. 2311 oldFullVisible.OffsetBy(-dx, -dy); 2312 GetDisplayDriver()->CopyRegion(&oldFullVisible, dx, dy); 2313 2314 // add redrawReg to our RootLayer's redraw region. 2315 // GetRootLayer()->fRedrawReg.Include(&redrawReg); 2316 GetRootLayer()->fRedrawReg = redrawReg; 2317 GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL); 2318 // GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)? 2319 } 2320 } 2321 2322 void 2323 Layer::do_ScrollBy(float dx, float dy) 2324 { 2325 fLayerData->OffsetOrigin(BPoint(dx, dy)); 2326 // fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy); 2327 2328 if (!IsHidden() && GetRootLayer()) { 2329 // set the region to be invalidated. 2330 BRegion invalid(fFullVisible2); 2331 2332 clear_visible_regions(); 2333 2334 rebuild_visible_regions(invalid, invalid, BottomChild()); 2335 2336 // for the moment we say that the whole surface needs to be redraw. 2337 BRegion redrawReg(fFullVisible2); 2338 2339 // offset old region so that we can start comparing. 2340 invalid.OffsetBy(dx, dy); 2341 2342 // compute the common region. we'll use HW acc to copy this to the new location. 2343 invalid.IntersectWith(&fFullVisible2); 2344 GetDisplayDriver()->CopyRegion(&invalid, -dx, -dy); 2345 2346 // common region goes back to its original location. then, by excluding 2347 // it from curent fullVisible we'll obtain the region that needs to be redrawn. 2348 invalid.OffsetBy(-dx, -dy); 2349 redrawReg.Exclude(&invalid); 2350 2351 // GetRootLayer()->fRedrawReg.Include(&redrawReg); 2352 GetRootLayer()->fRedrawReg = redrawReg; 2353 GetRootLayer()->RequestDraw(GetRootLayer()->fRedrawReg, NULL); 2354 // GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)? 2355 } 2356 2357 if (dx != 0.0f || dy != 0.0f) 2358 ScrolledByHook(dx, dy); 2359 } 2360 2361 void 2362 Layer::get_user_regions(BRegion ®) 2363 { 2364 // 1) set to frame in screen coords 2365 BRect screenFrame(Bounds()); 2366 ConvertToScreen2(&screenFrame); 2367 reg.Set(screenFrame); 2368 2369 // 2) intersect with screen region 2370 BRegion screenReg(GetRootLayer()->Bounds()); 2371 reg.IntersectWith(&screenReg); 2372 2373 2374 // 3) impose user constrained regions 2375 LayerData *stackData = fLayerData; 2376 while (stackData) { 2377 if (stackData->ClippingRegion()) { 2378 // transform in screen coords 2379 BRegion screenReg(*stackData->ClippingRegion()); 2380 ConvertToScreen2(&screenReg); 2381 reg.IntersectWith(&screenReg); 2382 } 2383 stackData = stackData->prevState; 2384 } 2385 } 2386 2387 void 2388 Layer::do_RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom) 2389 { 2390 BRegion localVisible(fFullVisible2); 2391 localVisible.IntersectWith(&invalid); 2392 rebuild_visible_regions(invalid, localVisible, startFrom); 2393 } 2394 2395 void 2396 Layer::rebuild_visible_regions(const BRegion &invalid, 2397 const BRegion &parentLocalVisible, 2398 const Layer *startFrom) 2399 { 2400 // no point in continuing if this layer is hidden. starting from here, all 2401 // descendants have (and will have) invalid visible regions. 2402 if (fHidden) 2403 return; 2404 2405 // no need to go deeper if the parent doesn't have a visible region anymore 2406 // and our fullVisible region is also empty. 2407 if (!parentLocalVisible.Frame().IsValid() && !(fFullVisible2.CountRects() > 0)) 2408 return; 2409 2410 bool fullRebuild = false; 2411 2412 // intersect maximum wanted region with the invalid region 2413 BRegion common; 2414 get_user_regions(common); 2415 common.IntersectWith(&invalid); 2416 2417 // if the resulted region is not valid, this layer is not in the catchment area 2418 // of the region being invalidated 2419 if (!common.CountRects() > 0) 2420 return; 2421 2422 // now intersect with parent's visible part of the region that was/is invalidated 2423 common.IntersectWith(&parentLocalVisible); 2424 2425 // exclude the invalid region 2426 fFullVisible2.Exclude(&invalid); 2427 fVisible2.Exclude(&invalid); 2428 2429 // put in what's really visible 2430 fFullVisible2.Include(&common); 2431 2432 // this is to allow a layer to hide some parts of itself so children 2433 // won't take them. 2434 BRegion unalteredVisible(common); 2435 bool altered = alter_visible_for_children(common); 2436 2437 for (Layer *lay = BottomChild(); lay; lay = UpperSibling()) { 2438 if (lay == startFrom) 2439 fullRebuild = true; 2440 2441 if (fullRebuild) 2442 lay->rebuild_visible_regions(invalid, common, lay->BottomChild()); 2443 2444 // to let children know much they can take from parent's visible region 2445 common.Exclude(&lay->fFullVisible2); 2446 // we've hidden some parts of our visible region from our children, 2447 // and we must be in sysnc with this region too... 2448 if (altered) 2449 unalteredVisible.Exclude(&lay->fFullVisible2); 2450 } 2451 2452 // the visible region of this layer is what left after all its children took 2453 // what they could. 2454 if (altered) 2455 fVisible2.Include(&unalteredVisible); 2456 else 2457 fVisible2.Include(&common); 2458 } 2459 2460 bool 2461 Layer::alter_visible_for_children(BRegion ®) 2462 { 2463 // Empty Hook function 2464 return false; 2465 } 2466 2467 void 2468 Layer::clear_visible_regions() 2469 { 2470 // OPT: maybe we should uncomment these lines for performance 2471 //if (fFullVisible2.CountRects() <= 0) 2472 // return; 2473 2474 fVisible2.MakeEmpty(); 2475 fFullVisible2.MakeEmpty(); 2476 for (Layer *child = BottomChild(); child; child = UpperSibling()) 2477 child->clear_visible_regions(); 2478 } 2479 2480 #endif 2481 2482