From cd2b129d0777a3198229fa66f0f4c344f7027120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Thu, 29 Dec 2005 14:15:59 +0000 Subject: [PATCH] * removed superflous LockSingleWindow() from WindowLayer::MoveBy() and ResizeBy() * WindowLayer::SetSizeLimits() needs to be called with the AllWindows lock held * I was observing weird behaviour with "unclickable" windows that I might have fixed by explicitly excluding invisible windows from Desktop::WindowAt(), there might be something wrong with the "current" window list though, Axel would know * finally found the problem with "delayed background clearing" * enabled delayed background clearing and removed unnecessary code. It should be more efficient, since it clears larger areas at once, and it solves the problem of views unable to draw into regions that are pending for another update - among other things, updates in resizing windows are more fluent, especially for B_FULL_UPDATE_ON_RESIZE views. "Cut off" scroll bars should no longer appear when the view being scrolled takes too long to redraw. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15714 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Desktop.cpp | 4 +- src/servers/app/ServerWindow.cpp | 9 +++-- src/servers/app/WindowLayer.cpp | 39 +++++++++--------- src/servers/app/WindowLayer.h | 13 ------ src/servers/app/drawing/DrawingEngine.cpp | 44 ++++++++++----------- src/servers/app/drawing/Painter/Painter.cpp | 32 +++++++++++++++ src/servers/app/drawing/Painter/Painter.h | 3 ++ 7 files changed, 83 insertions(+), 61 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index bcc8f02e5d..eedf4e84ac 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -1583,14 +1583,14 @@ Desktop::SetWindowTitle(WindowLayer *window, const char* title) /*! Returns the window under the mouse cursor. - You need to have the window write lock acquired when calling this method. + You need to have acquired the All Windows lock when calling this method. */ WindowLayer* Desktop::WindowAt(BPoint where) { for (WindowLayer* window = _CurrentWindows().LastWindow(); window; window = window->PreviousWindow(fCurrentWorkspace)) { - if (window->VisibleRegion().Contains(where)) + if (window->IsVisible() && window->VisibleRegion().Contains(where)) return window; } diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 3d7536087d..8459fcdb82 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -854,10 +854,11 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) link.Read(&minHeight); link.Read(&maxHeight); */ - // TODO: setting size limits can change the window size, and therefore, - // it should be done by the Desktop class as well. - fWindowLayer->SetSizeLimits(minWidth, maxWidth, - minHeight, maxHeight); + if (fDesktop->LockAllWindows()) { + fWindowLayer->SetSizeLimits(minWidth, maxWidth, + minHeight, maxHeight); + fDesktop->UnlockAllWindows(); + } // and now, sync the client to the limits that we were able to enforce fWindowLayer->GetSizeLimits(&minWidth, &maxWidth, diff --git a/src/servers/app/WindowLayer.cpp b/src/servers/app/WindowLayer.cpp index 01356f8fde..ff0a8e21f3 100644 --- a/src/servers/app/WindowLayer.cpp +++ b/src/servers/app/WindowLayer.cpp @@ -53,6 +53,16 @@ using std::nothrow; +// if the background clearing is delayed until +// the client draws the view, we have less flickering +// when contents have to be redrawn because of resizing +// a window or because the client invalidates parts. +// when redrawing something that has been exposed from underneath +// other windows, the other window will be seen longer at +// its previous position though if the exposed parts are not +// cleared right away. maybe there ought to be a flag in +// the update session, which tells us the cause of the update +#define DELAYED_BACKGROUND_CLEARING 1 WindowLayer::WindowLayer(const BRect& frame, const char *name, window_look look, window_feel feel, @@ -291,7 +301,7 @@ WindowLayer::MoveBy(int32 x, int32 y) { // this function is only called from the desktop thread - if ((x == 0 && y == 0) || !ReadLockWindows()) + if (x == 0 && y == 0) return; fWindow->HandleDirectConnection(B_DIRECT_STOP); @@ -330,8 +340,6 @@ WindowLayer::MoveBy(int32 x, int32 y) msg.AddInt64("when", system_time()); msg.AddPoint("where", fFrame.LeftTop()); fWindow->SendMessageToClient(&msg); - - ReadUnlockWindows(); } @@ -357,7 +365,7 @@ WindowLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion) x = wantWidth - fFrame.IntegerWidth(); y = wantHeight - fFrame.IntegerHeight(); - if ((x == 0 && y == 0) || !ReadLockWindows()) + if (x == 0 && y == 0) return; fWindow->HandleDirectConnection(B_DIRECT_STOP); @@ -400,8 +408,6 @@ WindowLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion) msg.AddInt32("width", frame.IntegerWidth()); msg.AddInt32("height", frame.IntegerHeight()); fWindow->SendMessageToClient(&msg); - - ReadUnlockWindows(); } @@ -1561,8 +1567,9 @@ WindowLayer::_TriggerContentRedraw(BRegion& dirtyContentRegion) _TransferToUpdateSession(&dirtyContentRegion); #if DELAYED_BACKGROUND_CLEARING - if (!fTopLayer->IsBackgroundDirty()) - fTopLayer->MarkBackgroundDirty(); +// NOTE: currently not used, might come in handy later though +// if (!fTopLayer->IsBackgroundDirty()) +// fTopLayer->MarkBackgroundDirty(); #else if (!fContentRegionValid) _UpdateContentRegion(); @@ -1691,18 +1698,14 @@ WindowLayer::BeginUpdate() // command from the client during an update // (ViewLayer::IsBackgroundDirty() can be used // for this) - if (fDrawingEngine->Lock()) { - if (!fContentRegionValid) - _UpdateContentRegion(); - - BRegion dirty(fCurrentUpdateSession.DirtyRegion()); - dirty.IntersectWith(&VisibleContentRegion()); + if (!fContentRegionValid) + _UpdateContentRegion(); - fTopLayer->Draw(fDrawingEngine, &dirty, - &fContentRegion, true); + BRegion dirty(fCurrentUpdateSession.DirtyRegion()); + dirty.IntersectWith(&VisibleContentRegion()); - fDrawingEngine->Unlock(); - } + fTopLayer->Draw(fDrawingEngine, &dirty, + &fContentRegion, true); #endif } else { fprintf(stderr, "WindowLayer::BeginUpdate() - no update requested!\n"); diff --git a/src/servers/app/WindowLayer.h b/src/servers/app/WindowLayer.h index 1cf96cf0c2..0e12781efc 100644 --- a/src/servers/app/WindowLayer.h +++ b/src/servers/app/WindowLayer.h @@ -31,19 +31,6 @@ class WindowLayer; // TODO: move this into a proper place #define AS_REDRAW 'rdrw' - -// if the background clearing is delayed until -// the client draws the view, we have less flickering -// when contents have to be redrawn because of resizing -// a window or because the client invalidates parts. -// when redrawing something that has been exposed from underneath -// other windows, the other window will be seen longer at -// its previous position though if the exposed parts are not -// cleared right away. maybe there ought to be a flag in -// the update session, which tells us the cause of the update -#define DELAYED_BACKGROUND_CLEARING 0 - - class WindowLayer { public: WindowLayer(const BRect& frame, diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index 51243822a6..ad7fc090e6 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -758,34 +758,30 @@ DrawingEngine::FillRegion(BRegion& r, const RGBColor& color) // NOTE: Write locking because we might use HW acceleration. // This needs to be investigated, I'm doing this because of // gut feeling. + // NOTE: region expected to be already clipped correctly!! if (WriteLock()) { - BRect clipped = fPainter->ClipRect(r.Frame()); - if (clipped.IsValid()) { - fGraphicsCard->HideSoftwareCursor(clipped); + fGraphicsCard->HideSoftwareCursor(r.Frame()); - bool doInSoftware = true; - // try hardware optimized version first - if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { -// NOTE: region expected to be already clipped correctly -// r.IntersectWith(fPainter->ClippingRegion()); - fGraphicsCard->FillRegion(r, color); - doInSoftware = false; - } - - if (doInSoftware) { - - int32 count = r.CountRects(); - for (int32 i = 0; i < count; i++) { - fPainter->FillRect(r.RectAt(i), color.GetColor32()); - } - BRect touched = r.Frame(); - - fGraphicsCard->Invalidate(touched); - } - - fGraphicsCard->ShowSoftwareCursor(); + bool doInSoftware = true; + // try hardware optimized version first + if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { + fGraphicsCard->FillRegion(r, color); + doInSoftware = false; } + if (doInSoftware) { + + int32 count = r.CountRects(); + for (int32 i = 0; i < count; i++) { + fPainter->FillRectNoClipping(r.RectAt(i), color.GetColor32()); + } + BRect touched = r.Frame(); + + fGraphicsCard->Invalidate(touched); + } + + fGraphicsCard->ShowSoftwareCursor(); + WriteUnlock(); } } diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index ac0d7ca155..5c1c3b4130 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -738,6 +738,38 @@ Painter::FillRect(const BRect& r, const rgb_color& c) const } } +// FillRectNoClipping +void +Painter::FillRectNoClipping(const BRect& r, const rgb_color& c) const +{ + if (fBuffer) { + int32 left = (int32)r.left; + int32 y = (int32)r.top; + int32 right = (int32)r.right; + int32 bottom = (int32)r.bottom; + + uint8* dst = fBuffer->row(y); + uint32 bpr = fBuffer->stride(); + + // get a 32 bit pixel ready with the color + pixel32 color; + color.data8[0] = c.blue; + color.data8[1] = c.green; + color.data8[2] = c.red; + color.data8[3] = c.alpha; + + dst += left * 4; + + for (; y <= bottom; y++) { + uint32* handle = (uint32*)dst; + for (int32 x = left; x <= right; x++) { + *handle++ = color.data32; + } + dst += bpr; + } + } +} + // StrokeRoundRect BRect Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 5039a8ef07..771322aa21 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -136,6 +136,9 @@ class Painter { // fills a solid rect with color c, no blending void FillRect( const BRect& r, const rgb_color& c) const; + // fills a solid rect with color c, no blending, no clipping + void FillRectNoClipping(const BRect& r, + const rgb_color& c) const; // round rects BRect StrokeRoundRect(const BRect& r,