* 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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -854,10 +854,11 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
link.Read<int32>(&minHeight);
|
||||
link.Read<int32>(&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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user