overall more correct, most importantly corrected a bug in content scrolling that caused view redraws to ignore the window content clipping

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15627 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2005-12-20 22:35:36 +00:00
parent 3c0e5f8e8b
commit bee1ec1ee0
2 changed files with 78 additions and 42 deletions

View File

@ -49,17 +49,6 @@
# define STRACE_CLICK(x) ; # define STRACE_CLICK(x) ;
#endif #endif
// 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
// IMPORTANT: nested LockSingleWindow()s are not supported (by MultiLocker) // IMPORTANT: nested LockSingleWindow()s are not supported (by MultiLocker)
using std::nothrow; using std::nothrow;
@ -435,6 +424,7 @@ WindowLayer::ScrollViewBy(ViewLayer* view, int32 dx, int32 dy)
//fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 255, 255)); //fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 255, 255));
//snooze(2000); //snooze(2000);
dirty.IntersectWith(&VisibleContentRegion());
_TriggerContentRedraw(dirty); _TriggerContentRedraw(dirty);
fDesktop->UnlockSingleWindow(); fDesktop->UnlockSingleWindow();
@ -707,12 +697,12 @@ WindowLayer::InvalidateView(ViewLayer* layer, BRegion& layerRegion)
_UpdateContentRegion(); _UpdateContentRegion();
layer->ConvertToScreen(&layerRegion); layer->ConvertToScreen(&layerRegion);
layerRegion.IntersectWith(&fVisibleRegion); layerRegion.IntersectWith(&VisibleContentRegion());
if (layerRegion.CountRects() > 0) { if (layerRegion.CountRects() > 0) {
layerRegion.IntersectWith(&layer->ScreenClipping(&fContentRegion)); layerRegion.IntersectWith(&layer->ScreenClipping(&fContentRegion));
//fDrawingEngine->FillRegion(layerRegion, RGBColor(255, 255, 0, 255)); //fDrawingEngine->FillRegion(layerRegion, RGBColor(0, 255, 0, 255));
//snooze(2000); //snooze(10000);
_TriggerContentRedraw(layerRegion); _TriggerContentRedraw(layerRegion);
} }
@ -935,24 +925,35 @@ WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken)
fDrawingEngine->Unlock(); fDrawingEngine->Unlock();
} }
if (fIsDragging && !(Flags() & B_NOT_MOVABLE)) { BPoint delta = where - fLastMousePosition;
BPoint delta = where - fLastMousePosition; // moving
fDesktop->MoveWindowBy(this, delta.x, delta.y); if (fIsDragging) {
if (!(Flags() & B_NOT_MOVABLE))
fDesktop->MoveWindowBy(this, delta.x, delta.y);
else
delta = BPoint(0, 0);
} }
if (fIsResizing && !(Flags() & B_NOT_RESIZABLE)) { // resizing
BPoint delta = where - fLastMousePosition; if (fIsResizing) {
if (Flags() & B_NOT_V_RESIZABLE) if (!(Flags() & B_NOT_RESIZABLE)) {
delta.y = 0; if (Flags() & B_NOT_V_RESIZABLE)
if (Flags() & B_NOT_H_RESIZABLE) delta.y = 0;
delta.x = 0; if (Flags() & B_NOT_H_RESIZABLE)
delta.x = 0;
fDesktop->ResizeWindowBy(this, delta.x, delta.y);
fDesktop->ResizeWindowBy(this, delta.x, delta.y);
} else
delta = BPoint(0, 0);
} }
// sliding tab
if (fIsSlidingTab) { if (fIsSlidingTab) {
// TODO: implement // TODO: implement
} }
fLastMousePosition = where; // NOTE: fLastMousePosition is currently only
// used for window moving/resizing/sliding the tab
// ther
fLastMousePosition += delta;
// change focus in FFM mode // change focus in FFM mode
DesktopSettings desktopSettings(fDesktop); DesktopSettings desktopSettings(fDesktop);
@ -1546,23 +1547,24 @@ void
WindowLayer::_TriggerContentRedraw(BRegion& dirtyContentRegion) WindowLayer::_TriggerContentRedraw(BRegion& dirtyContentRegion)
{ {
if (dirtyContentRegion.CountRects() > 0) { if (dirtyContentRegion.CountRects() > 0) {
// send UPDATE message to the client // put this into the pending dirty region
// to eventually trigger a client redraw
_TransferToUpdateSession(&dirtyContentRegion); _TransferToUpdateSession(&dirtyContentRegion);
#if DELAYED_BACKGROUND_CLEARING
if (!fTopLayer->IsBackgroundDirty())
fTopLayer->MarkBackgroundDirty();
#else
if (!fContentRegionValid) if (!fContentRegionValid)
_UpdateContentRegion(); _UpdateContentRegion();
if (fDrawingEngine->Lock()) { if (fDrawingEngine->Lock()) {
fDrawingEngine->ConstrainClippingRegion(&dirtyContentRegion); fDrawingEngine->ConstrainClippingRegion(&dirtyContentRegion);
#if DELAYED_BACKGROUND_CLEARING
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
&fContentRegion, false);
#else
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion, fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
&fContentRegion, true); &fContentRegion, true);
#endif
fDrawingEngine->Unlock(); fDrawingEngine->Unlock();
} }
#endif
} }
} }
@ -1606,6 +1608,9 @@ WindowLayer::_TransferToUpdateSession(BRegion* contentDirtyRegion)
if (contentDirtyRegion->CountRects() <= 0) if (contentDirtyRegion->CountRects() <= 0)
return; return;
//fDrawingEngine->FillRegion(*contentDirtyRegion, RGBColor(255, 255, 0, 255));
//snooze(10000);
// add to pending // add to pending
fPendingUpdateSession.SetUsed(true); fPendingUpdateSession.SetUsed(true);
fPendingUpdateSession.Include(contentDirtyRegion); fPendingUpdateSession.Include(contentDirtyRegion);
@ -1616,24 +1621,19 @@ WindowLayer::_TransferToUpdateSession(BRegion* contentDirtyRegion)
// this could be done smarter (clip layers from pending // this could be done smarter (clip layers from pending
// that have not yet been redrawn in the current update // that have not yet been redrawn in the current update
// session) // session)
#if !DELAYED_BACKGROUND_CLEARING
if (fCurrentUpdateSession.IsUsed()) { if (fCurrentUpdateSession.IsUsed()) {
fCurrentUpdateSession.Exclude(contentDirtyRegion); fCurrentUpdateSession.Exclude(contentDirtyRegion);
fEffectiveDrawingRegionValid = false; fEffectiveDrawingRegionValid = false;
} }
#endif
if (!fUpdateRequested) { if (!fUpdateRequested) {
// send this to client // send this to client
_SendUpdateMessage(); _SendUpdateMessage();
// as long as we have not received // the pending region is now the current,
// the "begin update" command, the // though the update does not start until
// pending session does not become the // we received BEGIN_UPDATE from the client
// current
// TODO: problem: since we sent the update regions frame,
// we should not add to the pending session after we
// sent the update message!!!
} else {
if (!fCurrentUpdateSession.IsUsed())
fprintf(stderr, "WindowLayer(%s)::_TransferToUpdateSession() - pending region changed before BeginUpdate()!\n", Title());
} }
} }
@ -1675,6 +1675,28 @@ WindowLayer::BeginUpdate()
// session enforced // session enforced
fInUpdate = true; fInUpdate = true;
fEffectiveDrawingRegionValid = false; fEffectiveDrawingRegionValid = false;
#if DELAYED_BACKGROUND_CLEARING
// TODO: each view could be drawn individually
// right before carrying out the first drawing
// 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());
fTopLayer->Draw(fDrawingEngine, &dirty,
&fContentRegion, true);
fDrawingEngine->Unlock();
}
#endif
} else {
fprintf(stderr, "WindowLayer::BeginUpdate() - no update requested!\n");
} }
fDesktop->UnlockSingleWindow(); fDesktop->UnlockSingleWindow();

View File

@ -32,6 +32,18 @@ class WindowLayer;
#define AS_REDRAW 'rdrw' #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 { class WindowLayer {
public: public:
WindowLayer(const BRect& frame, WindowLayer(const BRect& frame,
@ -105,6 +117,8 @@ class WindowLayer {
void BeginUpdate(); void BeginUpdate();
void EndUpdate(); void EndUpdate();
bool InUpdate() const
{ return fInUpdate; }
bool NeedsUpdate() const bool NeedsUpdate() const
{ return fUpdateRequested; } { return fUpdateRequested; }