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