diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index 40248795a8..96028f0f5d 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -1154,7 +1154,6 @@ FrameMoved(origin); //bigtime_t now = system_time(); //bigtime_t drawTime = 0; STRACE(("info:BWindow handling _UPDATE_.\n")); - BRect updateRect; fLink->StartMessage(AS_BEGIN_UPDATE); fInTransaction = true; @@ -1189,36 +1188,55 @@ FrameMoved(origin); FrameResized(width, height); } - // read culmulated update rect (is in screen coords) - fLink->Read(&updateRect); - // read tokens for views that need to be drawn // NOTE: we need to read the tokens completely - // first, or other calls would likely mess up the - // data in the link. - BList tokens(20); - int32 token; - status_t error = fLink->Read(&token); - while (error >= B_OK && token != B_NULL_TOKEN) { - tokens.AddItem((void*)token); - error = fLink->Read(&token); + // first, we cannot draw views in between reading + // the tokens, since other communication would likely + // mess up the data in the link. + struct ViewUpdateInfo { + int32 token; + BRect updateRect; + }; + BList infos(20); + while (true) { + // read next token and create/add ViewUpdateInfo + int32 token; + status_t error = fLink->Read(&token); + if (error < B_OK || token == B_NULL_TOKEN) + break; + ViewUpdateInfo* info = new (nothrow) ViewUpdateInfo; + if (info == NULL || !infos.AddItem(info)) { + delete info; + break; + } + info->token = token; + // read culmulated update rect (is in screen coords) + error = fLink->Read(&(info->updateRect)); + if (error < B_OK) + break; } // draw - int32 count = tokens.CountItems(); + int32 count = infos.CountItems(); for (int32 i = 0; i < count; i++) { //bigtime_t drawStart = system_time(); - if (BView* view = _FindView((int32)tokens.ItemAtFast(i))) - view->_Draw(updateRect); + ViewUpdateInfo* info + = (ViewUpdateInfo*)infos.ItemAtFast(i); + if (BView* view = _FindView(info->token)) + view->_Draw(info->updateRect); else - printf("_UPDATE_ - didn't find view by token: %ld\n", (int32)tokens.ItemAtFast(i)); + printf("_UPDATE_ - didn't find view by token: %ld\n", + info->token); //drawTime += system_time() - drawStart; } // NOTE: The tokens are actually hirachically sorted, // so traversing the list in revers and calling - // child->DrawAfterChildren actually works correctly + // child->_DrawAfterChildren() actually works like intended. for (int32 i = count - 1; i >= 0; i--) { - if (BView* view = _FindView((int32)tokens.ItemAtFast(i))) - view->_DrawAfterChildren(updateRect); + ViewUpdateInfo* info + = (ViewUpdateInfo*)infos.ItemAtFast(i); + if (BView* view = _FindView(info->token)) + view->_DrawAfterChildren(info->updateRect); + delete info; } //printf(" %ld views drawn, total Draw() time: %lld\n", count, drawTime); diff --git a/src/servers/app/View.cpp b/src/servers/app/View.cpp index 8ff350c6dc..4a2a0837cc 100644 --- a/src/servers/app/View.cpp +++ b/src/servers/app/View.cpp @@ -1475,23 +1475,6 @@ View::MarkBackgroundDirty() } -void -View::AddTokensForViewsInRegion(BMessage* message, BRegion& region, - BRegion* windowContentClipping) -{ - if (!fVisible) - return; - - if (region.Intersects(_ScreenClipping(windowContentClipping).Frame())) - message->AddInt32("_token", fToken); - - for (View* child = FirstChild(); child; child = child->NextSibling()) { - child->AddTokensForViewsInRegion(message, region, - windowContentClipping); - } -} - - void View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region, BRegion* windowContentClipping) @@ -1499,17 +1482,28 @@ View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region, if (!fVisible) return; - IntRect screenBounds(Bounds()); - ConvertToScreen(&screenBounds); - if (!region.Intersects((clipping_rect)screenBounds)) - return; + { + // NOTE: use scope in order to reduce stack space requirements - if (region.Intersects(_ScreenClipping(windowContentClipping).Frame())) - link.Attach(fToken); + // This check will prevent descending the view hierarchy + // any further than necessary + IntRect screenBounds(Bounds()); + ConvertToScreen(&screenBounds); + if (!region.Intersects((clipping_rect)screenBounds)) + return; - for (View* child = FirstChild(); child; child = child->NextSibling()) { - child->AddTokensForViewsInRegion(link, region, windowContentClipping); + // Unfortunately, we intersecting another region, but otherwise + // we couldn't provide the exact update rect to the client + BRegion localDirty = _ScreenClipping(windowContentClipping); + localDirty.IntersectWith(®ion); + if (localDirty.CountRects() > 0) { + link.Attach(fToken); + link.Attach(localDirty.Frame()); + } } + + for (View* child = FirstChild(); child; child = child->NextSibling()) + child->AddTokensForViewsInRegion(link, region, windowContentClipping); } diff --git a/src/servers/app/View.h b/src/servers/app/View.h index f2157b6bb9..303f70c3e0 100644 --- a/src/servers/app/View.h +++ b/src/servers/app/View.h @@ -215,10 +215,6 @@ class View { bool IsDesktopBackground() const { return fIsDesktopBackground; } - void AddTokensForViewsInRegion(BMessage* message, - BRegion& region, - BRegion* windowContentClipping); - void AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region, BRegion* windowContentClipping); diff --git a/src/servers/app/Window.cpp b/src/servers/app/Window.cpp index 2ee518314b..9e9982491c 100644 --- a/src/servers/app/Window.cpp +++ b/src/servers/app/Window.cpp @@ -1915,8 +1915,6 @@ Window::BeginUpdate(BPrivate::PortLink& link) link.Attach(fFrame.LeftTop()); link.Attach(fFrame.Width()); link.Attach(fFrame.Height()); - // append he update rect in screen coords - link.Attach(dirty->Frame()); // find and attach all views that intersect with // the dirty region fTopView->AddTokensForViewsInRegion(link, *dirty, &fContentRegion);