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