app_server: clear background immediately on expose
Reduce stamping artifacts when application slowly responds to redraw requests. This fixes and reintroduces logic previously removed in hrev53711. Previous logic was incorrect as it didn't take the possibility of multiple invalidations of different kinds (expose, update request) into account. Now separate update and expose regions are maintained and only expose region is cleared immediately. Change-Id: I0fd98cb1b45ccec285154e8c0d8e3a1400d156d7 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6067 Reviewed-by: Jérôme Duval <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
+23
-13
@@ -1558,12 +1558,14 @@ Desktop::ResizeWindowBy(Window* window, float x, float y)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the dirty region for the inside of the window is
|
// The dirty region for the inside of the window is constructed by the window itself in
|
||||||
// constructed by the window itself in ResizeBy()
|
// ResizeBy()
|
||||||
BRegion newDirtyRegion;
|
BRegion newDirtyRegion;
|
||||||
// track the dirty region outside the window in case
|
// Track the dirty region outside the window in case it is shrunk in "previouslyOccupiedRegion"
|
||||||
// it is shrunk in "previouslyOccupiedRegion"
|
|
||||||
BRegion previouslyOccupiedRegion(window->VisibleRegion());
|
BRegion previouslyOccupiedRegion(window->VisibleRegion());
|
||||||
|
// Track the region that was drawn in previous update sessions, so we can compute the newly
|
||||||
|
// exposed areas by excluding this from the update region.
|
||||||
|
BRegion previousVisibleContentRegion(window->VisibleContentRegion());
|
||||||
|
|
||||||
// stop direct frame buffer access
|
// stop direct frame buffer access
|
||||||
bool direct = false;
|
bool direct = false;
|
||||||
@@ -1586,7 +1588,15 @@ Desktop::ResizeWindowBy(Window* window, float x, float y)
|
|||||||
// ...because we do this ourselves
|
// ...because we do this ourselves
|
||||||
newDirtyRegion.Include(&previouslyOccupiedRegion);
|
newDirtyRegion.Include(&previouslyOccupiedRegion);
|
||||||
|
|
||||||
MarkDirty(newDirtyRegion);
|
// calculate old expose region as window visible region difference
|
||||||
|
BRegion exposeRegion(previouslyOccupiedRegion);
|
||||||
|
exposeRegion.Exclude(&window->VisibleRegion());
|
||||||
|
// ...and new expose region as window content visible region difference
|
||||||
|
BRegion tmp(window->VisibleContentRegion());
|
||||||
|
tmp.Exclude(&previousVisibleContentRegion);
|
||||||
|
exposeRegion.Include(&tmp);
|
||||||
|
|
||||||
|
MarkDirty(newDirtyRegion, exposeRegion);
|
||||||
_SetBackground(background);
|
_SetBackground(background);
|
||||||
_WindowChanged(window);
|
_WindowChanged(window);
|
||||||
|
|
||||||
@@ -2166,14 +2176,14 @@ Desktop::FindTarget(BMessenger& messenger)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Desktop::MarkDirty(BRegion& region)
|
Desktop::MarkDirty(BRegion& dirtyRegion, BRegion& exposeRegion)
|
||||||
{
|
{
|
||||||
if (region.CountRects() == 0)
|
if (dirtyRegion.CountRects() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (LockAllWindows()) {
|
if (LockAllWindows()) {
|
||||||
// send redraw messages to all windows intersecting the dirty region
|
// send redraw messages to all windows intersecting the dirty region
|
||||||
_TriggerWindowRedrawing(region);
|
_TriggerWindowRedrawing(dirtyRegion, exposeRegion);
|
||||||
|
|
||||||
UnlockAllWindows();
|
UnlockAllWindows();
|
||||||
}
|
}
|
||||||
@@ -3455,14 +3465,14 @@ Desktop::_RebuildClippingForAllWindows(BRegion& stillAvailableOnScreen)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Desktop::_TriggerWindowRedrawing(BRegion& newDirtyRegion)
|
Desktop::_TriggerWindowRedrawing(BRegion& dirtyRegion, BRegion& exposeRegion)
|
||||||
{
|
{
|
||||||
// send redraw messages to all windows intersecting the dirty region
|
// send redraw messages to all windows intersecting the dirty region
|
||||||
for (Window* window = CurrentWindows().LastWindow(); window != NULL;
|
for (Window* window = CurrentWindows().LastWindow(); window != NULL;
|
||||||
window = window->PreviousWindow(fCurrentWorkspace)) {
|
window = window->PreviousWindow(fCurrentWorkspace)) {
|
||||||
if (!window->IsHidden()
|
if (!window->IsHidden()
|
||||||
&& newDirtyRegion.Intersects(window->VisibleRegion().Frame()))
|
&& dirtyRegion.Intersects(window->VisibleRegion().Frame()))
|
||||||
window->ProcessDirtyRegion(newDirtyRegion);
|
window->ProcessDirtyRegion(dirtyRegion, exposeRegion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3531,7 +3541,7 @@ Desktop::RebuildAndRedrawAfterWindowChange(Window* changedWindow,
|
|||||||
_SetBackground(stillAvailableOnScreen);
|
_SetBackground(stillAvailableOnScreen);
|
||||||
_WindowChanged(changedWindow);
|
_WindowChanged(changedWindow);
|
||||||
|
|
||||||
_TriggerWindowRedrawing(dirty);
|
_TriggerWindowRedrawing(dirty, dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3603,7 +3613,7 @@ Desktop::_ScreenChanged(Screen* screen)
|
|||||||
|
|
||||||
// figure out dirty region
|
// figure out dirty region
|
||||||
dirty.Exclude(&background);
|
dirty.Exclude(&background);
|
||||||
_TriggerWindowRedrawing(dirty);
|
_TriggerWindowRedrawing(dirty, dirty);
|
||||||
|
|
||||||
// send B_SCREEN_CHANGED to windows on that screen
|
// send B_SCREEN_CHANGED to windows on that screen
|
||||||
BMessage update(B_SCREEN_CHANGED);
|
BMessage update(B_SCREEN_CHANGED);
|
||||||
|
|||||||
@@ -240,7 +240,9 @@ public:
|
|||||||
team_id teamID);
|
team_id teamID);
|
||||||
EventTarget* FindTarget(BMessenger& messenger);
|
EventTarget* FindTarget(BMessenger& messenger);
|
||||||
|
|
||||||
void MarkDirty(BRegion& region);
|
void MarkDirty(BRegion& dirtyRegion, BRegion& exposeRegion);
|
||||||
|
void MarkDirty(BRegion& region)
|
||||||
|
{ return MarkDirty(region, region); }
|
||||||
void Redraw();
|
void Redraw();
|
||||||
void RedrawBackground();
|
void RedrawBackground();
|
||||||
|
|
||||||
@@ -312,7 +314,7 @@ private:
|
|||||||
void _RebuildClippingForAllWindows(
|
void _RebuildClippingForAllWindows(
|
||||||
BRegion& stillAvailableOnScreen);
|
BRegion& stillAvailableOnScreen);
|
||||||
void _TriggerWindowRedrawing(
|
void _TriggerWindowRedrawing(
|
||||||
BRegion& newDirtyRegion);
|
BRegion& dirtyRegion, BRegion& exposeRegion);
|
||||||
void _SetBackground(BRegion& background);
|
void _SetBackground(BRegion& background);
|
||||||
|
|
||||||
status_t _ActivateApp(team_id team);
|
status_t _ActivateApp(team_id team);
|
||||||
|
|||||||
@@ -1378,7 +1378,7 @@ fDesktop->LockSingleWindow();
|
|||||||
float offsetX = x - fCurrentView->Frame().left;
|
float offsetX = x - fCurrentView->Frame().left;
|
||||||
float offsetY = y - fCurrentView->Frame().top;
|
float offsetY = y - fCurrentView->Frame().top;
|
||||||
|
|
||||||
BRegion dirty;
|
BRegion dirty, expose;
|
||||||
fCurrentView->MoveBy(offsetX, offsetY, &dirty);
|
fCurrentView->MoveBy(offsetX, offsetY, &dirty);
|
||||||
|
|
||||||
// TODO: think about how to avoid this hack:
|
// TODO: think about how to avoid this hack:
|
||||||
@@ -1389,7 +1389,7 @@ fDesktop->LockSingleWindow();
|
|||||||
if (View* parent = fCurrentView->Parent())
|
if (View* parent = fCurrentView->Parent())
|
||||||
parent->RebuildClipping(false);
|
parent->RebuildClipping(false);
|
||||||
|
|
||||||
fWindow->MarkContentDirty(dirty);
|
fWindow->MarkContentDirty(dirty, expose);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_VIEW_RESIZE_TO:
|
case AS_VIEW_RESIZE_TO:
|
||||||
@@ -1406,14 +1406,14 @@ fDesktop->LockSingleWindow();
|
|||||||
float deltaWidth = newWidth - fCurrentView->Frame().Width();
|
float deltaWidth = newWidth - fCurrentView->Frame().Width();
|
||||||
float deltaHeight = newHeight - fCurrentView->Frame().Height();
|
float deltaHeight = newHeight - fCurrentView->Frame().Height();
|
||||||
|
|
||||||
BRegion dirty;
|
BRegion dirty, expose;
|
||||||
fCurrentView->ResizeBy(deltaWidth, deltaHeight, &dirty);
|
fCurrentView->ResizeBy(deltaWidth, deltaHeight, &dirty);
|
||||||
|
|
||||||
// TODO: see above
|
// TODO: see above
|
||||||
if (View* parent = fCurrentView->Parent())
|
if (View* parent = fCurrentView->Parent())
|
||||||
parent->RebuildClipping(false);
|
parent->RebuildClipping(false);
|
||||||
|
|
||||||
fWindow->MarkContentDirty(dirty);
|
fWindow->MarkContentDirty(dirty, expose);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_VIEW_GET_COORD:
|
case AS_VIEW_GET_COORD:
|
||||||
|
|||||||
@@ -905,7 +905,7 @@ View::CopyBits(IntRect src, IntRect dst, BRegion& windowContentClipping)
|
|||||||
dirty->Exclude(copyRegion);
|
dirty->Exclude(copyRegion);
|
||||||
|
|
||||||
dirty->IntersectWith(screenAndUserClipping);
|
dirty->IntersectWith(screenAndUserClipping);
|
||||||
fWindow->MarkContentDirty(*dirty);
|
fWindow->MarkContentDirty(*dirty, *dirty);
|
||||||
|
|
||||||
fWindow->RecycleRegion(dirty);
|
fWindow->RecycleRegion(dirty);
|
||||||
fWindow->RecycleRegion(copyRegion);
|
fWindow->RecycleRegion(copyRegion);
|
||||||
@@ -1045,8 +1045,8 @@ View::BlendAllLayers()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
View::Draw(DrawingEngine* drawingEngine, const BRegion* effectiveClipping,
|
||||||
BRegion* windowContentClipping, bool deep)
|
const BRegion* windowContentClipping, bool deep)
|
||||||
{
|
{
|
||||||
if (!fVisible) {
|
if (!fVisible) {
|
||||||
// child views cannot be visible either
|
// child views cannot be visible either
|
||||||
@@ -1245,9 +1245,9 @@ View::SetHidden(bool hidden)
|
|||||||
IntRect clippedBounds = Bounds();
|
IntRect clippedBounds = Bounds();
|
||||||
ConvertToVisibleInTopView(&clippedBounds);
|
ConvertToVisibleInTopView(&clippedBounds);
|
||||||
|
|
||||||
BRegion dirty;
|
BRegion dirty, expose;
|
||||||
dirty.Set((clipping_rect)clippedBounds);
|
dirty.Set((clipping_rect)clippedBounds);
|
||||||
fWindow->MarkContentDirty(dirty);
|
fWindow->MarkContentDirty(dirty, expose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1426,7 +1426,7 @@ View::RebuildClipping(bool deep)
|
|||||||
|
|
||||||
|
|
||||||
BRegion&
|
BRegion&
|
||||||
View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const
|
View::ScreenAndUserClipping(const BRegion* windowContentClipping, bool force) const
|
||||||
{
|
{
|
||||||
// no user clipping - return screen clipping directly
|
// no user clipping - return screen clipping directly
|
||||||
if (!fUserClipping.IsSet())
|
if (!fUserClipping.IsSet())
|
||||||
@@ -1477,7 +1477,7 @@ View::InvalidateScreenClipping()
|
|||||||
|
|
||||||
|
|
||||||
BRegion&
|
BRegion&
|
||||||
View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
|
View::_ScreenClipping(const BRegion* windowContentClipping, bool force) const
|
||||||
{
|
{
|
||||||
if (!fScreenClippingValid || force) {
|
if (!fScreenClippingValid || force) {
|
||||||
fScreenClipping = fLocalClipping;
|
fScreenClipping = fLocalClipping;
|
||||||
|
|||||||
@@ -170,8 +170,8 @@ public:
|
|||||||
|
|
||||||
// for background clearing
|
// for background clearing
|
||||||
virtual void Draw(DrawingEngine* drawingEngine,
|
virtual void Draw(DrawingEngine* drawingEngine,
|
||||||
BRegion* effectiveClipping,
|
const BRegion* effectiveClipping,
|
||||||
BRegion* windowContentClipping,
|
const BRegion* windowContentClipping,
|
||||||
bool deep = false);
|
bool deep = false);
|
||||||
|
|
||||||
virtual void MouseDown(BMessage* message, BPoint where);
|
virtual void MouseDown(BMessage* message, BPoint where);
|
||||||
@@ -204,7 +204,7 @@ public:
|
|||||||
// clipping
|
// clipping
|
||||||
void RebuildClipping(bool deep);
|
void RebuildClipping(bool deep);
|
||||||
BRegion& ScreenAndUserClipping(
|
BRegion& ScreenAndUserClipping(
|
||||||
BRegion* windowContentClipping,
|
const BRegion* windowContentClipping,
|
||||||
bool force = false) const;
|
bool force = false) const;
|
||||||
void InvalidateScreenClipping();
|
void InvalidateScreenClipping();
|
||||||
inline bool IsScreenClippingValid() const
|
inline bool IsScreenClippingValid() const
|
||||||
@@ -228,7 +228,7 @@ protected:
|
|||||||
virtual void _ScreenToLocalTransform(
|
virtual void _ScreenToLocalTransform(
|
||||||
SimpleTransform& transform) const;
|
SimpleTransform& transform) const;
|
||||||
|
|
||||||
BRegion& _ScreenClipping(BRegion* windowContentClipping,
|
BRegion& _ScreenClipping(const BRegion* windowContentClipping,
|
||||||
bool force = false) const;
|
bool force = false) const;
|
||||||
void _MoveScreenClipping(int32 x, int32 y,
|
void _MoveScreenClipping(int32 x, int32 y,
|
||||||
bool deep);
|
bool deep);
|
||||||
|
|||||||
+35
-41
@@ -81,7 +81,6 @@ Window::Window(const BRect& frame, const char *name,
|
|||||||
fVisibleRegion(),
|
fVisibleRegion(),
|
||||||
fVisibleContentRegion(),
|
fVisibleContentRegion(),
|
||||||
fDirtyRegion(),
|
fDirtyRegion(),
|
||||||
fDirtyCause(0),
|
|
||||||
|
|
||||||
fContentRegion(),
|
fContentRegion(),
|
||||||
fEffectiveDrawingRegion(),
|
fEffectiveDrawingRegion(),
|
||||||
@@ -289,6 +288,7 @@ Window::MoveBy(int32 x, int32 y, bool moveStack)
|
|||||||
// take along the dirty region which is not
|
// take along the dirty region which is not
|
||||||
// processed yet
|
// processed yet
|
||||||
fDirtyRegion.OffsetBy(x, y);
|
fDirtyRegion.OffsetBy(x, y);
|
||||||
|
fExposeRegion.OffsetBy(x, y);
|
||||||
|
|
||||||
if (fContentRegionValid)
|
if (fContentRegionValid)
|
||||||
fContentRegion.OffsetBy(x, y);
|
fContentRegion.OffsetBy(x, y);
|
||||||
@@ -737,7 +737,7 @@ Window::DrawingRegionChanged(View* view) const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Window::ProcessDirtyRegion(BRegion& region)
|
Window::ProcessDirtyRegion(const BRegion& dirtyRegion, const BRegion& exposeRegion)
|
||||||
{
|
{
|
||||||
// if this is executed in the desktop thread,
|
// if this is executed in the desktop thread,
|
||||||
// it means that the window thread currently
|
// it means that the window thread currently
|
||||||
@@ -760,8 +760,8 @@ Window::ProcessDirtyRegion(BRegion& region)
|
|||||||
ServerWindow()->RequestRedraw();
|
ServerWindow()->RequestRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
fDirtyRegion.Include(®ion);
|
fDirtyRegion.Include(&dirtyRegion);
|
||||||
fDirtyCause |= UPDATE_EXPOSE;
|
fExposeRegion.Include(&exposeRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -770,7 +770,7 @@ Window::RedrawDirtyRegion()
|
|||||||
{
|
{
|
||||||
if (TopLayerStackWindow() != this) {
|
if (TopLayerStackWindow() != this) {
|
||||||
fDirtyRegion.MakeEmpty();
|
fDirtyRegion.MakeEmpty();
|
||||||
fDirtyCause = 0;
|
fExposeRegion.MakeEmpty();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,13 +778,15 @@ Window::RedrawDirtyRegion()
|
|||||||
if (IsVisible()) {
|
if (IsVisible()) {
|
||||||
_DrawBorder();
|
_DrawBorder();
|
||||||
|
|
||||||
BRegion* dirtyContentRegion =
|
BRegion* dirtyContentRegion = fRegionPool.GetRegion(VisibleContentRegion());
|
||||||
fRegionPool.GetRegion(VisibleContentRegion());
|
BRegion* exposeContentRegion = fRegionPool.GetRegion(VisibleContentRegion());
|
||||||
dirtyContentRegion->IntersectWith(&fDirtyRegion);
|
dirtyContentRegion->IntersectWith(&fDirtyRegion);
|
||||||
|
exposeContentRegion->IntersectWith(&fExposeRegion);
|
||||||
|
|
||||||
_TriggerContentRedraw(*dirtyContentRegion);
|
_TriggerContentRedraw(*dirtyContentRegion, *exposeContentRegion);
|
||||||
|
|
||||||
fRegionPool.Recycle(dirtyContentRegion);
|
fRegionPool.Recycle(dirtyContentRegion);
|
||||||
|
fRegionPool.Recycle(exposeContentRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the dirty region, since
|
// reset the dirty region, since
|
||||||
@@ -795,7 +797,7 @@ Window::RedrawDirtyRegion()
|
|||||||
// get write access, since we're holding
|
// get write access, since we're holding
|
||||||
// the read lock for the whole time.
|
// the read lock for the whole time.
|
||||||
fDirtyRegion.MakeEmpty();
|
fDirtyRegion.MakeEmpty();
|
||||||
fDirtyCause = 0;
|
fExposeRegion.MakeEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -812,7 +814,7 @@ Window::MarkDirty(BRegion& regionOnScreen)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Window::MarkContentDirty(BRegion& regionOnScreen)
|
Window::MarkContentDirty(BRegion& dirtyRegion, BRegion& exposeRegion)
|
||||||
{
|
{
|
||||||
// for triggering AS_REDRAW
|
// for triggering AS_REDRAW
|
||||||
// since this won't affect other windows, read locking
|
// since this won't affect other windows, read locking
|
||||||
@@ -821,27 +823,26 @@ Window::MarkContentDirty(BRegion& regionOnScreen)
|
|||||||
if (fHidden || IsOffscreenWindow())
|
if (fHidden || IsOffscreenWindow())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
regionOnScreen.IntersectWith(&VisibleContentRegion());
|
dirtyRegion.IntersectWith(&VisibleContentRegion());
|
||||||
fDirtyCause |= UPDATE_REQUEST;
|
exposeRegion.IntersectWith(&VisibleContentRegion());
|
||||||
_TriggerContentRedraw(regionOnScreen);
|
_TriggerContentRedraw(dirtyRegion, exposeRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Window::MarkContentDirtyAsync(BRegion& regionOnScreen)
|
Window::MarkContentDirtyAsync(BRegion& dirtyRegion)
|
||||||
{
|
{
|
||||||
// NOTE: see comments in ProcessDirtyRegion()
|
// NOTE: see comments in ProcessDirtyRegion()
|
||||||
if (fHidden || IsOffscreenWindow())
|
if (fHidden || IsOffscreenWindow())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
regionOnScreen.IntersectWith(&VisibleContentRegion());
|
dirtyRegion.IntersectWith(&VisibleContentRegion());
|
||||||
|
|
||||||
if (fDirtyRegion.CountRects() == 0) {
|
if (fDirtyRegion.CountRects() == 0) {
|
||||||
ServerWindow()->RequestRedraw();
|
ServerWindow()->RequestRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
fDirtyRegion.Include(®ionOnScreen);
|
fDirtyRegion.Include(&dirtyRegion);
|
||||||
fDirtyCause |= UPDATE_REQUEST;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -860,7 +861,6 @@ Window::InvalidateView(View* view, BRegion& viewRegion)
|
|||||||
|
|
||||||
//fDrawingEngine->FillRegion(viewRegion, rgb_color{ 0, 255, 0, 255 });
|
//fDrawingEngine->FillRegion(viewRegion, rgb_color{ 0, 255, 0, 255 });
|
||||||
//snooze(10000);
|
//snooze(10000);
|
||||||
fDirtyCause |= UPDATE_REQUEST;
|
|
||||||
_TriggerContentRedraw(viewRegion);
|
_TriggerContentRedraw(viewRegion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1767,16 +1767,27 @@ Window::_ShiftPartOfRegion(BRegion* region, BRegion* regionToShift,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Window::_TriggerContentRedraw(BRegion& dirtyContentRegion)
|
Window::_TriggerContentRedraw(BRegion& dirty, const BRegion& expose)
|
||||||
{
|
{
|
||||||
if (!IsVisible() || dirtyContentRegion.CountRects() == 0
|
if (!IsVisible() || dirty.CountRects() == 0 || (fFlags & kWindowScreenFlag) != 0)
|
||||||
|| (fFlags & kWindowScreenFlag) != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// put this into the pending dirty region
|
// put this into the pending dirty region
|
||||||
// to eventually trigger a client redraw
|
// to eventually trigger a client redraw
|
||||||
|
_TransferToUpdateSession(&dirty);
|
||||||
|
|
||||||
_TransferToUpdateSession(&dirtyContentRegion);
|
if (expose.CountRects() > 0) {
|
||||||
|
// draw exposed region background right now to avoid stamping artifacts
|
||||||
|
if (fDrawingEngine->LockParallelAccess()) {
|
||||||
|
bool copyToFrontEnabled = fDrawingEngine->CopyToFrontEnabled();
|
||||||
|
fDrawingEngine->SetCopyToFrontEnabled(true);
|
||||||
|
fDrawingEngine->SuspendAutoSync();
|
||||||
|
fTopView->Draw(fDrawingEngine.Get(), &expose, &fContentRegion, true);
|
||||||
|
fDrawingEngine->Sync();
|
||||||
|
fDrawingEngine->SetCopyToFrontEnabled(copyToFrontEnabled);
|
||||||
|
fDrawingEngine->UnlockParallelAccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1841,8 +1852,6 @@ Window::_TransferToUpdateSession(BRegion* contentDirtyRegion)
|
|||||||
|
|
||||||
// add to pending
|
// add to pending
|
||||||
fPendingUpdateSession->SetUsed(true);
|
fPendingUpdateSession->SetUsed(true);
|
||||||
// if (!fPendingUpdateSession->IsExpose())
|
|
||||||
fPendingUpdateSession->AddCause(fDirtyCause);
|
|
||||||
fPendingUpdateSession->Include(contentDirtyRegion);
|
fPendingUpdateSession->Include(contentDirtyRegion);
|
||||||
|
|
||||||
if (!fUpdateRequested) {
|
if (!fUpdateRequested) {
|
||||||
@@ -2058,13 +2067,7 @@ Window::_ObeySizeLimits()
|
|||||||
Window::UpdateSession::UpdateSession()
|
Window::UpdateSession::UpdateSession()
|
||||||
:
|
:
|
||||||
fDirtyRegion(),
|
fDirtyRegion(),
|
||||||
fInUse(false),
|
fInUse(false)
|
||||||
fCause(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Window::UpdateSession::~UpdateSession()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2094,17 +2097,8 @@ void
|
|||||||
Window::UpdateSession::SetUsed(bool used)
|
Window::UpdateSession::SetUsed(bool used)
|
||||||
{
|
{
|
||||||
fInUse = used;
|
fInUse = used;
|
||||||
if (!fInUse) {
|
if (!fInUse)
|
||||||
fDirtyRegion.MakeEmpty();
|
fDirtyRegion.MakeEmpty();
|
||||||
fCause = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Window::UpdateSession::AddCause(uint8 cause)
|
|
||||||
{
|
|
||||||
fCause |= cause;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+21
-23
@@ -81,11 +81,6 @@ class WorkspacesView;
|
|||||||
// TODO: move this into a proper place
|
// TODO: move this into a proper place
|
||||||
#define AS_REDRAW 'rdrw'
|
#define AS_REDRAW 'rdrw'
|
||||||
|
|
||||||
enum {
|
|
||||||
UPDATE_REQUEST = 0x01,
|
|
||||||
UPDATE_EXPOSE = 0x02,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Window {
|
class Window {
|
||||||
public:
|
public:
|
||||||
@@ -149,15 +144,19 @@ public:
|
|||||||
bool DrawingRegionChanged(View* view) const;
|
bool DrawingRegionChanged(View* view) const;
|
||||||
|
|
||||||
// generic version, used by the Desktop
|
// generic version, used by the Desktop
|
||||||
void ProcessDirtyRegion(BRegion& regionOnScreen);
|
void ProcessDirtyRegion(const BRegion& dirtyRegion,
|
||||||
|
const BRegion& exposeRegion);
|
||||||
|
void ProcessDirtyRegion(const BRegion& exposeRegion)
|
||||||
|
{ ProcessDirtyRegion(exposeRegion, exposeRegion); }
|
||||||
void RedrawDirtyRegion();
|
void RedrawDirtyRegion();
|
||||||
|
|
||||||
// can be used from inside classes that don't
|
// can be used from inside classes that don't
|
||||||
// need to know about Desktop (first version uses Desktop)
|
// need to know about Desktop (first version uses Desktop)
|
||||||
void MarkDirty(BRegion& regionOnScreen);
|
void MarkDirty(BRegion& regionOnScreen);
|
||||||
// these versions do not use the Desktop
|
// these versions do not use the Desktop
|
||||||
void MarkContentDirty(BRegion& regionOnScreen);
|
void MarkContentDirty(BRegion& dirtyRegion,
|
||||||
void MarkContentDirtyAsync(BRegion& regionOnScreen);
|
BRegion& exposeRegion);
|
||||||
|
void MarkContentDirtyAsync(BRegion& dirtyRegion);
|
||||||
// shortcut for invalidating just one view
|
// shortcut for invalidating just one view
|
||||||
void InvalidateView(View* view, BRegion& viewRegion);
|
void InvalidateView(View* view, BRegion& viewRegion);
|
||||||
|
|
||||||
@@ -322,7 +321,8 @@ protected:
|
|||||||
int32 yOffset);
|
int32 yOffset);
|
||||||
|
|
||||||
// different types of drawing
|
// different types of drawing
|
||||||
void _TriggerContentRedraw(BRegion& dirty);
|
void _TriggerContentRedraw(BRegion& dirty,
|
||||||
|
const BRegion& expose = BRegion());
|
||||||
void _DrawBorder();
|
void _DrawBorder();
|
||||||
|
|
||||||
// handling update sessions
|
// handling update sessions
|
||||||
@@ -348,13 +348,19 @@ protected:
|
|||||||
|
|
||||||
BRegion fVisibleRegion;
|
BRegion fVisibleRegion;
|
||||||
BRegion fVisibleContentRegion;
|
BRegion fVisibleContentRegion;
|
||||||
// our part of the "global" dirty region
|
|
||||||
// it is calculated from the desktop thread,
|
// Our part of the "global" dirty region (what needs to be redrawn).
|
||||||
// but we can write to it when we read locked
|
// It is calculated from the desktop thread, but we can write to it when we read locked
|
||||||
// the clipping, since it is local and the desktop
|
// the clipping, since it is local and the desktop thread is blocked.
|
||||||
// thread is blocked
|
|
||||||
BRegion fDirtyRegion;
|
BRegion fDirtyRegion;
|
||||||
uint32 fDirtyCause;
|
|
||||||
|
// Subset of the dirty region that is newly exposed. While the dirty region is merely
|
||||||
|
// showing out of date data on screen, this subset of it is showing remains of other
|
||||||
|
// windows. To avoid glitches, it must be set to a reasonable state as fast as possible,
|
||||||
|
// without waiting for a roundtrip to the window's Draw() methods. So it will be filled
|
||||||
|
// using background color and view bitmap, which can all be done without leaving
|
||||||
|
// app_server.
|
||||||
|
BRegion fExposeRegion;
|
||||||
|
|
||||||
// caching local regions
|
// caching local regions
|
||||||
BRegion fContentRegion;
|
BRegion fContentRegion;
|
||||||
@@ -386,7 +392,6 @@ protected:
|
|||||||
class UpdateSession {
|
class UpdateSession {
|
||||||
public:
|
public:
|
||||||
UpdateSession();
|
UpdateSession();
|
||||||
virtual ~UpdateSession();
|
|
||||||
|
|
||||||
void Include(BRegion* additionalDirty);
|
void Include(BRegion* additionalDirty);
|
||||||
void Exclude(BRegion* dirtyInNextSession);
|
void Exclude(BRegion* dirtyInNextSession);
|
||||||
@@ -400,16 +405,9 @@ protected:
|
|||||||
inline bool IsUsed() const
|
inline bool IsUsed() const
|
||||||
{ return fInUse; }
|
{ return fInUse; }
|
||||||
|
|
||||||
void AddCause(uint8 cause);
|
|
||||||
inline bool IsExpose() const
|
|
||||||
{ return fCause & UPDATE_EXPOSE; }
|
|
||||||
inline bool IsRequest() const
|
|
||||||
{ return fCause & UPDATE_REQUEST; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BRegion fDirtyRegion;
|
BRegion fDirtyRegion;
|
||||||
bool fInUse;
|
bool fInUse;
|
||||||
uint8 fCause;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UpdateSession fUpdateSessions[2];
|
UpdateSession fUpdateSessions[2];
|
||||||
|
|||||||
@@ -358,14 +358,14 @@ WorkspacesView::_Invalidate() const
|
|||||||
BRect frame = Bounds();
|
BRect frame = Bounds();
|
||||||
LocalToScreenTransform().Apply(&frame);
|
LocalToScreenTransform().Apply(&frame);
|
||||||
|
|
||||||
BRegion region(frame);
|
BRegion region(frame), expose;
|
||||||
Window()->MarkContentDirty(region);
|
Window()->MarkContentDirty(region, expose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WorkspacesView::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
WorkspacesView::Draw(DrawingEngine* drawingEngine, const BRegion* effectiveClipping,
|
||||||
BRegion* windowContentClipping, bool deep)
|
const BRegion* windowContentClipping, bool deep)
|
||||||
{
|
{
|
||||||
// we can only draw within our own area
|
// we can only draw within our own area
|
||||||
BRegion redraw(ScreenAndUserClipping(windowContentClipping));
|
BRegion redraw(ScreenAndUserClipping(windowContentClipping));
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ public:
|
|||||||
virtual void DetachedFromWindow();
|
virtual void DetachedFromWindow();
|
||||||
|
|
||||||
virtual void Draw(DrawingEngine* drawingEngine,
|
virtual void Draw(DrawingEngine* drawingEngine,
|
||||||
BRegion* effectiveClipping,
|
const BRegion* effectiveClipping,
|
||||||
BRegion* windowContentClipping, bool deep = false);
|
const BRegion* windowContentClipping, bool deep = false);
|
||||||
|
|
||||||
virtual void MouseDown(BMessage* message, BPoint where);
|
virtual void MouseDown(BMessage* message, BPoint where);
|
||||||
virtual void MouseUp(BMessage* message, BPoint where);
|
virtual void MouseUp(BMessage* message, BPoint where);
|
||||||
|
|||||||
Reference in New Issue
Block a user