diff --git a/src/servers/app/drawing/DisplayDriverPainter.cpp b/src/servers/app/drawing/DisplayDriverPainter.cpp index 74d9295592..49da8e7bba 100644 --- a/src/servers/app/drawing/DisplayDriverPainter.cpp +++ b/src/servers/app/drawing/DisplayDriverPainter.cpp @@ -84,6 +84,25 @@ DisplayDriverPainter::Shutdown() DisplayDriver::Shutdown(); } +// ConstrainClippingRegion +void DisplayDriverPainter::ConstrainClippingRegion(BRegion *region) +{ + if (Lock()) { + if (!region) { +// BRegion empty; +// fPainter->ConstrainClipping(empty); + if (RenderingBuffer* buffer = fGraphicsCard->DrawingBuffer()) { + BRegion all; + all.Include(BRect(0, 0, buffer->Width() - 1, buffer->Height() - 1)); + fPainter->ConstrainClipping(all); + } + } else { + fPainter->ConstrainClipping(*region); + } + Unlock(); + } +} + // CopyRegion() does a topological sort of the rects in the // region. The algorithm was suggested by Ingo Weinhold. // It compares each rect with each rect and builds a tree @@ -199,6 +218,8 @@ DisplayDriverPainter::CopyRegion(/*const*/ BRegion* region, int32 xOffset, int32 yOffset) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(fPainter->ClipRect(region->Frame())); + int32 count = region->CountRects(); // TODO: make this step unnecessary @@ -276,6 +297,7 @@ DisplayDriverPainter::CopyRegion(/*const*/ BRegion* region, inDegreeZeroNodes.push(n->pointers[k]); } } + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -314,9 +336,12 @@ void DisplayDriverPainter::InvertRect(const BRect &r) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(fPainter->ClipRect(r)); BRect touched = fPainter->InvertRect(r); + fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -333,12 +358,14 @@ DisplayDriverPainter::DrawBitmap(BRegion *region, ServerBitmap *bitmap, return; if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->ConstrainClipping(*region); fPainter->SetDrawData(d); fPainter->DrawBitmap(bitmap, source, dest); fGraphicsCard->Invalidate(dest); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -350,6 +377,7 @@ DisplayDriverPainter::FillArc(const BRect &r, const float &angle, const float &span, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); @@ -361,6 +389,7 @@ DisplayDriverPainter::FillArc(const BRect &r, const float &angle, BRect touched = fPainter->FillArc(center, xRadius, yRadius, angle, span); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -371,12 +400,14 @@ void DisplayDriverPainter::FillBezier(BPoint *pts, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->FillBezier(pts); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -387,6 +418,7 @@ void DisplayDriverPainter::FillEllipse(const BRect &r, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); @@ -398,6 +430,7 @@ DisplayDriverPainter::FillEllipse(const BRect &r, const DrawData *d) BRect touched = fPainter->FillEllipse(center, xRadius, yRadius); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -409,11 +442,13 @@ DisplayDriverPainter::FillPolygon(BPoint *ptlist, int32 numpts, const BRect &bounds, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->FillPolygon(ptlist, numpts); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -424,14 +459,18 @@ void DisplayDriverPainter::FillRect(const BRect &r, const RGBColor &color) { if (Lock()) { + BRect vr(min_c(r.left, r.right), + min_c(r.top, r.bottom), + max_c(r.left, r.right), + max_c(r.top, r.bottom)); + vr = fPainter->ClipRect(vr); - fPainter->FillRect(r, color.GetColor32()); - BRect touched(min_c(r.left, r.right), - min_c(r.top, r.bottom), - max_c(r.left, r.right), - max_c(r.top, r.bottom)); + fGraphicsCard->HideSoftwareCursor(vr); - fGraphicsCard->Invalidate(fPainter->ClipRect(touched)); + fPainter->FillRect(vr, color.GetColor32()); + + fGraphicsCard->Invalidate(vr); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -442,11 +481,19 @@ void DisplayDriverPainter::FillRect(const BRect &r, const DrawData *d) { if (Lock()) { + BRect vr(min_c(r.left, r.right), + min_c(r.top, r.bottom), + max_c(r.left, r.right), + max_c(r.top, r.bottom)); + vr = fPainter->ClipRect(vr); + + fGraphicsCard->HideSoftwareCursor(vr); fPainter->SetDrawData(d); - BRect touched = fPainter->FillRect(r); + BRect touched = fPainter->FillRect(vr); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -458,6 +505,8 @@ DisplayDriverPainter::FillRegion(BRegion& r, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(fPainter->ClipRect(r.Frame())); + fPainter->SetDrawData(d); BRect touched = fPainter->FillRect(r.RectAt(0)); @@ -468,6 +517,7 @@ DisplayDriverPainter::FillRegion(BRegion& r, const DrawData *d) } fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -480,11 +530,13 @@ DisplayDriverPainter::FillRoundRect(const BRect &r, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->FillRoundRect(r, xrad, yrad); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -511,11 +563,13 @@ DisplayDriverPainter::FillTriangle(BPoint *pts, const BRect &bounds, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->FillTriangle(pts[0], pts[1], pts[2]); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -527,6 +581,7 @@ DisplayDriverPainter::StrokeArc(const BRect &r, const float &angle, const float &span, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); @@ -538,6 +593,7 @@ DisplayDriverPainter::StrokeArc(const BRect &r, const float &angle, BRect touched = fPainter->StrokeArc(center, xRadius, yRadius, angle, span); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -548,11 +604,13 @@ void DisplayDriverPainter::StrokeBezier(BPoint *pts, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->StrokeBezier(pts); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -563,6 +621,7 @@ void DisplayDriverPainter::StrokeEllipse(const BRect &r, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); @@ -574,6 +633,7 @@ DisplayDriverPainter::StrokeEllipse(const BRect &r, const DrawData *d) BRect touched = fPainter->StrokeEllipse(center, xRadius, yRadius); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -587,18 +647,22 @@ void DisplayDriverPainter::StrokeLine(const BPoint &start, const BPoint &end, const RGBColor &color) { if (Lock()) { + BRect touched(min_c(start.x, end.x), + min_c(start.y, end.y), + max_c(start.x, end.x), + max_c(start.y, end.y)); + touched = fPainter->ClipRect(touched); + fGraphicsCard->HideSoftwareCursor(touched); + if (!fPainter->StraightLine(start, end, color.GetColor32())) { - DrawData context; + static DrawData context; context.SetHighColor(color); - context.SetDrawingMode(B_OP_COPY); + context.SetDrawingMode(B_OP_OVER); StrokeLine(start, end, &context); } else { - BRect touched(min_c(start.x, end.x), - min_c(start.y, end.y), - max_c(start.x, end.x), - max_c(start.y, end.y)); - fGraphicsCard->Invalidate(fPainter->ClipRect(touched)); + fGraphicsCard->Invalidate(touched); } + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } } @@ -608,8 +672,51 @@ void DisplayDriverPainter::StrokeLine(const BPoint &start, const BPoint &end, DrawData* context) { if (Lock()) { - BRect touched = fPainter->StrokeLine(start, end, context); + BRect touched(min_c(start.x, end.x), + min_c(start.y, end.y), + max_c(start.x, end.x), + max_c(start.y, end.y)); + touched = fPainter->ClipRect(touched); + fGraphicsCard->HideSoftwareCursor(touched); + + touched = fPainter->StrokeLine(start, end, context); + fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); + + Unlock(); + } +} + +// StrokeLineArray +void +DisplayDriverPainter::StrokeLineArray(const int32 &numlines, + const LineArrayData *linedata, + const DrawData *d) +{ + if(!d || !linedata || numlines <= 0) + return; + + if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); + + DrawData context; + context.SetDrawingMode(B_OP_COPY); + const LineArrayData *data; + + data = (const LineArrayData *)&(linedata[0]); + context.SetHighColor(data->color); + BRect touched = fPainter->StrokeLine(data->pt1, data->pt2, &context); + + for (int32 i = 1; i < numlines; i++) { + data = (const LineArrayData *)&(linedata[i]); + context.SetHighColor(data->color); + touched = touched | fPainter->StrokeLine(data->pt1, data->pt2, &context); + } + + fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); + Unlock(); } } @@ -637,11 +744,13 @@ DisplayDriverPainter::StrokePolygon(BPoint *ptlist, int32 numpts, bool closed) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->StrokePolygon(ptlist, numpts, closed); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -654,6 +763,8 @@ void DisplayDriverPainter::StrokeRect(const BRect &r, const RGBColor &color) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); + // support invalid rects BRect vr(min_c(r.left, r.right), min_c(r.top, r.bottom), @@ -662,14 +773,16 @@ DisplayDriverPainter::StrokeRect(const BRect &r, const RGBColor &color) fPainter->StrokeRect(vr, color.GetColor32()); - fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(vr.left, vr.top, +/* fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(vr.left, vr.top, vr.right, vr.top))); fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(vr.left, vr.top + 1, vr.left, vr.bottom - 1))); fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(vr.right, vr.top + 1, vr.right, vr.bottom - 1))); fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(vr.left, vr.bottom, - vr.right, vr.bottom))); + vr.right, vr.bottom)));*/ + fGraphicsCard->Invalidate(fPainter->ClipRect(vr)); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -680,11 +793,13 @@ void DisplayDriverPainter::StrokeRect(const BRect &r, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->StrokeRect(r); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -695,6 +810,7 @@ void DisplayDriverPainter::StrokeRegion(BRegion& r, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); @@ -706,6 +822,7 @@ DisplayDriverPainter::StrokeRegion(BRegion& r, const DrawData *d) } fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -717,11 +834,13 @@ DisplayDriverPainter::StrokeRoundRect(const BRect &r, const float &xrad, const float &yrad, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->StrokeRoundRect(r, xrad, yrad); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -747,11 +866,13 @@ DisplayDriverPainter::StrokeTriangle(BPoint *pts, const BRect &bounds, const DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->StrokeTriangle(pts[0], pts[1], pts[2]); fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -763,7 +884,7 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length, const BPoint &pt, const RGBColor &color, escapement_delta *delta) { - DrawData d; + static DrawData d; d.SetHighColor(color); if (delta) @@ -778,11 +899,14 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length, const BPoint &pt, DrawData *d) { if (Lock()) { + fGraphicsCard->HideSoftwareCursor(); fPainter->SetDrawData(d); BRect touched = fPainter->DrawString(string, length, pt); + fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); Unlock(); } @@ -1010,35 +1134,6 @@ DisplayDriverPainter::DumpToBitmap() return NULL; } -// StrokeLineArray -void -DisplayDriverPainter::StrokeLineArray(const int32 &numlines, - const LineArrayData *linedata, - const DrawData *d) -{ - if(!d || !linedata || numlines <= 0) - return; - - if (Lock()) { - DrawData context; - context.SetDrawingMode(B_OP_COPY); - const LineArrayData *data; - - data = (const LineArrayData *)&(linedata[0]); - context.SetHighColor(data->color); - BRect touched = fPainter->StrokeLine(data->pt1, data->pt2, &context); - - for (int32 i = 1; i < numlines; i++) { - data = (const LineArrayData *)&(linedata[i]); - context.SetHighColor(data->color); - touched = touched | fPainter->StrokeLine(data->pt1, data->pt2, &context); - } - - fGraphicsCard->Invalidate(touched); - Unlock(); - } -} - // SetDPMSMode status_t DisplayDriverPainter::SetDPMSMode(const uint32 &state) @@ -1150,46 +1245,6 @@ DisplayDriverPainter::WaitForRetrace(bigtime_t timeout) return ret; } -// CopyBitmap -void -DisplayDriverPainter::CopyBitmap(ServerBitmap *bitmap, - const BRect &source, const BRect &dest, - const DrawData *d) -{ -} - -// CopyToBitmap -void DisplayDriverPainter::CopyToBitmap(ServerBitmap *target, - const BRect &source) -{ -} - -// Invalidate -void DisplayDriverPainter::Invalidate(const BRect &r) -{ - // nothing to be done here -} - -// ConstrainClippingRegion -void DisplayDriverPainter::ConstrainClippingRegion(BRegion *region) -{ - if (Lock()) { - if (!region) { -// BRegion empty; -// fPainter->ConstrainClipping(empty); - if (RenderingBuffer* buffer = fGraphicsCard->DrawingBuffer()) { - BRegion all; - all.Include(BRect(0, 0, buffer->Width() - 1, - buffer->Height() - 1)); - fPainter->ConstrainClipping(all); - } - } else { - fPainter->ConstrainClipping(*region); - } - Unlock(); - } -} - // _CopyRect BRect DisplayDriverPainter::_CopyRect(BRect src, int32 xOffset, int32 yOffset) const diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index 48cf933ddc..09183c6a58 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -16,6 +16,8 @@ // constructor HWInterface::HWInterface(bool doubleBuffered) : BLocker("hw interface lock"), + fCursorAreaBackup(NULL), + fSoftwareCursorHidden(false), fCursor(NULL), fCursorVisible(true), fCursorLocation(0, 0), @@ -28,6 +30,7 @@ HWInterface::HWInterface(bool doubleBuffered) // destructor HWInterface::~HWInterface() { + delete fCursorAreaBackup; delete fCursor; delete fUpdateExecutor; } @@ -40,9 +43,17 @@ HWInterface::SetCursor(ServerCursor* cursor) if (fCursor != cursor) { BRect oldFrame = _CursorFrame(); delete fCursor; + delete fCursorAreaBackup; fCursor = cursor; Invalidate(oldFrame); - Invalidate(_CursorFrame()); + BRect r = _CursorFrame(); + if (fCursor && !IsDoubleBuffered()) { + fCursorAreaBackup = new buffer_clip(r.IntegerWidth() + 1, + r.IntegerHeight() + 1); + _DrawCursor(r); + } else + fCursorAreaBackup = NULL; + Invalidate(r); } Unlock(); } @@ -82,6 +93,10 @@ HWInterface::MoveCursorTo(const float& x, const float& y) if (p != fCursorLocation) { BRect oldFrame = _CursorFrame(); fCursorLocation = p; + if (fCursorAreaBackup) { + _RestoreCursorArea(oldFrame); + _DrawCursor(_CursorFrame()); + } Invalidate(oldFrame); Invalidate(_CursorFrame()); } @@ -136,7 +151,7 @@ HWInterface::Invalidate(const BRect& frame) } return B_BAD_VALUE;*/ } else { - _DrawCursor(frame); +// _DrawCursor(frame); } return B_OK; } @@ -181,6 +196,46 @@ HWInterface::CopyBackToFront(const BRect& frame) return B_BAD_VALUE; } +// HideSoftwareCursor +void +HWInterface::HideSoftwareCursor(const BRect& area) +{ + if (fCursorAreaBackup && !fSoftwareCursorHidden) { + BRect backupArea(fCursorAreaBackup->left, + fCursorAreaBackup->top, + fCursorAreaBackup->right, + fCursorAreaBackup->bottom); + if (area.Intersects(backupArea)) { + _RestoreCursorArea(backupArea); + fSoftwareCursorHidden = true; + } + } +} + +// HideSoftwareCursor +void +HWInterface::HideSoftwareCursor() +{ + if (fCursorAreaBackup && !fSoftwareCursorHidden) { + _RestoreCursorArea(BRect(fCursorAreaBackup->left, + fCursorAreaBackup->top, + fCursorAreaBackup->right, + fCursorAreaBackup->bottom)); + fSoftwareCursorHidden = true; + } +} + +// ShowSoftwareCursor +void +HWInterface::ShowSoftwareCursor() +{ + if (fCursorAreaBackup && fSoftwareCursorHidden) { + _DrawCursor(_CursorFrame()); + fSoftwareCursorHidden = false; + } +} + + // _DrawCursor // * default implementation, can be used as fallback or for // software cursor @@ -232,26 +287,65 @@ HWInterface::_DrawCursor(BRect area) const uint8* dst = buffer; - // blending - for (int32 y = top; y <= bottom; y++) { - uint8* s = src; - uint8* c = crs; - uint8* d = dst; - for (int32 x = left; x <= right; x++) { - // assume backbuffer alpha = 255 - // TODO: it appears alpha in cursor is upside down - uint8 a = 255 - c[3]; - d[0] = (((s[0] - c[0]) * a) + (c[0] << 8)) >> 8; - d[1] = (((s[1] - c[1]) * a) + (c[1] << 8)) >> 8; - d[2] = (((s[2] - c[2]) * a) + (c[2] << 8)) >> 8; - d[3] = 255; - s += 4; - c += 4; - d += 4; + if (fCursorAreaBackup) { + // remember which area the backup contains + fCursorAreaBackup->left = left; + fCursorAreaBackup->top = top; + fCursorAreaBackup->right = right; + fCursorAreaBackup->bottom = bottom; + uint8* bup = fCursorAreaBackup->buffer; + uint32 bupBPR = fCursorAreaBackup->bpr; + // blending and backup of drawing buffer + for (int32 y = top; y <= bottom; y++) { + uint8* s = src; + uint8* c = crs; + uint8* d = dst; + uint8* b = bup; + for (int32 x = left; x <= right; x++) { + // assumes backbuffer alpha = 255 + // TODO: it appears alpha in cursor is upside down + uint8 a = 255 - c[3]; + b[0] = s[0]; + b[1] = s[1]; + b[2] = s[2]; + // TODO: unnecessary? + b[3] = 255; + d[0] = (((s[0] - c[0]) * a) + (c[0] << 8)) >> 8; + d[1] = (((s[1] - c[1]) * a) + (c[1] << 8)) >> 8; + d[2] = (((s[2] - c[2]) * a) + (c[2] << 8)) >> 8; + d[3] = 255; + s += 4; + c += 4; + d += 4; + b += 4; + } + crs += crsBPR; + src += srcBPR; + dst += width * 4; + bup += bupBPR; + } + } else { + // blending + for (int32 y = top; y <= bottom; y++) { + uint8* s = src; + uint8* c = crs; + uint8* d = dst; + for (int32 x = left; x <= right; x++) { + // assumes backbuffer alpha = 255 + // TODO: it appears alpha in cursor is upside down + uint8 a = 255 - c[3]; + d[0] = (((s[0] - c[0]) * a) + (c[0] << 8)) >> 8; + d[1] = (((s[1] - c[1]) * a) + (c[1] << 8)) >> 8; + d[2] = (((s[2] - c[2]) * a) + (c[2] << 8)) >> 8; + d[3] = 255; + s += 4; + c += 4; + d += 4; + } + crs += crsBPR; + src += srcBPR; + dst += width * 4; } - crs += crsBPR; - src += srcBPR; - dst += width * 4; } // copy result to front buffer @@ -515,5 +609,31 @@ HWInterface::_CursorFrame() const return frame; } +// _RestoreCursorArea +void +HWInterface::_RestoreCursorArea(const BRect& area) const +{ + if (fCursorAreaBackup) { + + // clip backup area against "area" + int32 left = max_c((int32)area.left, fCursorAreaBackup->left); + int32 top = max_c((int32)area.top, fCursorAreaBackup->top); + int32 right = min_c((int32)area.right, fCursorAreaBackup->right); + int32 bottom = min_c((int32)area.bottom, fCursorAreaBackup->bottom); + + if (left <= right && top <= bottom) { + + uint8* src = fCursorAreaBackup->buffer; + if (fCursorAreaBackup->left < left) + src += left - fCursorAreaBackup->left; + if (fCursorAreaBackup->top < top) + src += (top - fCursorAreaBackup->top) * fCursorAreaBackup->bpr; + + _CopyToFront(src, fCursorAreaBackup->bpr, + left, top, right, bottom); + } + } +} + diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index bcfb177af9..972825a97b 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -21,7 +21,7 @@ class UpdateQueue; class HWInterface : public BLocker { public: - HWInterface(bool doubleBuffered = true); + HWInterface(bool doubleBuffered = false); virtual ~HWInterface(); virtual status_t Initialize() = 0; @@ -67,6 +67,17 @@ class HWInterface : public BLocker { // while as CopyBackToFront() actually performs the operation status_t CopyBackToFront(const BRect& frame); + // TODO: Just a quick and primitive way to get single buffered mode working. + // Later, the implementation should be smarter, right now, it will + // draw the cursor for almost every drawing operation. + // It seems to me, BeOS hides the cursor (in laymans words) before + // BView::Draw() is called, then, after all drawing commands that triggered + // have been caried out, it shows the cursor again. This approach would + // have the adventage of the code not cluttering/slowing down DisplayDriverPainter. + void HideSoftwareCursor(const BRect& area); + void HideSoftwareCursor(); + void ShowSoftwareCursor(); + protected: // implement this in derived classes virtual void _DrawCursor(BRect area) const; @@ -77,6 +88,39 @@ class HWInterface : public BLocker { int32 right, int32 bottom) const; BRect _CursorFrame() const; + void _RestoreCursorArea(const BRect& frame) const; + + // If we draw the cursor somewhere in the drawing buffer, + // we need to backup its contents before drawing, so that + // we can restore that area when the cursor needs to be + // drawn somewhere else. + struct buffer_clip { + buffer_clip(int32 width, int32 height) + { + bpr = width * 4; + if (bpr > 0 && height > 0) + buffer = new uint8[bpr * height]; + else + buffer = NULL; + left = 0; + top = 0; + right = -1; + bottom = -1; + } + ~buffer_clip() + { + delete[] buffer; + } + uint8* buffer; + int32 left; + int32 top; + int32 right; + int32 bottom; + int32 bpr; + }; + + buffer_clip* fCursorAreaBackup; + bool fSoftwareCursorHidden; ServerCursor* fCursor; bool fCursorVisible;