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,