figured out and solved several problems:
* views are now correctly clipped when they are (partly) hidden under their parent(s) * removed fIsTopView, the top view in a window simply has no parent * introduced WindowLayer::CopyContents() which blits part of the contents to another location, while moving that part in the dirty regions. Since this is currently used from the Desktop thread, messing with the update session dirty regions requires now to lock the clipping * that feature is now used for blitting a view to its new location in ViewLayer::MoveBy(), which works for right and/or bottom aligned views just fine * I left the global dirty region in Desktop for now, moving it into each WindowLayer gave quite a slowdown and caused all kinds of other problems. * a view is now cleared to the background color right before the first drawing command from the client is executed for that view, this reduces flickering a lot because the content is drawn much more shortly after the background is cleared. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15201 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
94dc3ed625
commit
748533bbf9
@ -159,13 +159,13 @@ Desktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
|
||||
|
||||
if (dx != 0 || dy != 0) {
|
||||
if (fClickedWindow) {
|
||||
bigtime_t now = system_time();
|
||||
//bigtime_t now = system_time();
|
||||
if (fResizing) {
|
||||
ResizeWindowBy(fClickedWindow, dx, dy);
|
||||
printf("resizing: %lld\n", system_time() - now);
|
||||
//printf("resizing: %lld\n", system_time() - now);
|
||||
} else {
|
||||
MoveWindowBy(fClickedWindow, dx, dy);
|
||||
printf("moving: %lld\n", system_time() - now);
|
||||
//printf("moving: %lld\n", system_time() - now);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,6 +358,9 @@ Desktop::BottomWindow() const
|
||||
void
|
||||
Desktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y)
|
||||
{
|
||||
if (!Lock())
|
||||
return;
|
||||
|
||||
if (LockClipping()) {
|
||||
// the dirty region starts with the visible area of the window being moved
|
||||
BRegion newDirtyRegion(window->VisibleRegion());
|
||||
@ -403,12 +406,17 @@ Desktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y)
|
||||
|
||||
UnlockClipping();
|
||||
}
|
||||
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// ResizeWindowBy
|
||||
void
|
||||
Desktop::ResizeWindowBy(WindowLayer* window, int32 x, int32 y)
|
||||
{
|
||||
if (!Lock())
|
||||
return;
|
||||
|
||||
if (LockClipping()) {
|
||||
BRegion newDirtyRegion;
|
||||
BRegion previouslyOccupiedRegion(window->VisibleRegion());
|
||||
@ -428,6 +436,8 @@ Desktop::ResizeWindowBy(WindowLayer* window, int32 x, int32 y)
|
||||
|
||||
UnlockClipping();
|
||||
}
|
||||
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// BringToFront
|
||||
|
@ -31,7 +31,6 @@ ViewLayer::ViewLayer(BRect frame, const char* name,
|
||||
|
||||
fWindow(NULL),
|
||||
fParent(NULL),
|
||||
fIsTopLayer(false),
|
||||
|
||||
fFirstChild(NULL),
|
||||
fPreviousSibling(NULL),
|
||||
@ -72,12 +71,23 @@ ViewLayer::Bounds() const
|
||||
return bounds;
|
||||
}
|
||||
|
||||
// ConvertToVisibleInTopView
|
||||
void
|
||||
ViewLayer::ConvertToVisibleInTopView(BRect* bounds) const
|
||||
{
|
||||
*bounds = *bounds & Bounds();
|
||||
// NOTE: this step is necessary even if we don't have a parent!
|
||||
ConvertToParent(bounds);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertToVisibleInTopView(bounds);
|
||||
}
|
||||
|
||||
// AttachedToWindow
|
||||
void
|
||||
ViewLayer::AttachedToWindow(WindowLayer* window, bool topLayer)
|
||||
ViewLayer::AttachedToWindow(WindowLayer* window)
|
||||
{
|
||||
fWindow = window;
|
||||
fIsTopLayer = topLayer;
|
||||
|
||||
for (ViewLayer* child = FirstChild(); child; child = NextChild())
|
||||
child->AttachedToWindow(window);
|
||||
@ -211,13 +221,13 @@ ViewLayer::LastChild() const
|
||||
ViewLayer*
|
||||
ViewLayer::TopLayer()
|
||||
{
|
||||
if (fIsTopLayer)
|
||||
return this;
|
||||
// returns the top level view of the hirarchy,
|
||||
// it doesn't have to be the top level of a window
|
||||
|
||||
if (fParent)
|
||||
return fParent->TopLayer();
|
||||
else
|
||||
return NULL;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// CountChildren
|
||||
@ -328,6 +338,36 @@ ViewLayer::ConvertToTop(BRegion* region) const
|
||||
fParent->ConvertToTop(region);
|
||||
}
|
||||
|
||||
// ConvertFromTop
|
||||
void
|
||||
ViewLayer::ConvertFromTop(BPoint* point) const
|
||||
{
|
||||
ConvertFromParent(point);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertFromTop(point);
|
||||
}
|
||||
|
||||
// ConvertFromTop
|
||||
void
|
||||
ViewLayer::ConvertFromTop(BRect* rect) const
|
||||
{
|
||||
ConvertFromParent(rect);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertFromTop(rect);
|
||||
}
|
||||
|
||||
// ConvertFromTop
|
||||
void
|
||||
ViewLayer::ConvertFromTop(BRegion* region) const
|
||||
{
|
||||
ConvertFromParent(region);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertFromTop(region);
|
||||
}
|
||||
|
||||
// SetName
|
||||
void
|
||||
ViewLayer::SetName(const char* string)
|
||||
@ -335,72 +375,7 @@ ViewLayer::SetName(const char* string)
|
||||
fName.SetTo(string);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// MoveBy
|
||||
void
|
||||
ViewLayer::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
|
||||
{
|
||||
if (x == 0 && y == 0)
|
||||
return;
|
||||
|
||||
if (!fIsTopLayer && fWindow) {
|
||||
// blit to new location (children as well)
|
||||
BRect screenRect;
|
||||
if (fParent) {
|
||||
screenRect = fFrame & fParent->Bounds();
|
||||
fParent->ConvertToTop(&screenRect);
|
||||
} else {
|
||||
screenRect = Bounds();
|
||||
ConvertToTop(&screenRect);
|
||||
}
|
||||
|
||||
BRegion effectiveClippingRegion;
|
||||
fWindow->GetContentRegion(&effectiveClippingRegion);
|
||||
effectiveClippingRegion.IntersectWith(&fWindow->VisibleRegion());
|
||||
|
||||
BRegion copyRegion(screenRect);
|
||||
copyRegion.IntersectWith(&effectiveClippingRegion);
|
||||
|
||||
copyRegion.OffsetBy(x, y);
|
||||
copyRegion.IntersectWith(&effectiveClippingRegion);
|
||||
|
||||
BRegion alreadyDirty(screenRect);
|
||||
{
|
||||
BRegion windowDirty(fWindow->DirtyRegion());
|
||||
alreadyDirty.IntersectWith(&windowDirty);
|
||||
}
|
||||
|
||||
fFrame.OffsetBy(x, y);
|
||||
_MoveScreenClipping(x, y, true);
|
||||
|
||||
if (fParent) {
|
||||
screenRect = fFrame & fParent->Bounds();
|
||||
fParent->ConvertToTop(&screenRect);
|
||||
} else {
|
||||
screenRect = Bounds();
|
||||
ConvertToTop(&screenRect);
|
||||
}
|
||||
BRegion dirtyRegion(screenRect);
|
||||
dirtyRegion.Exclude(©Region);
|
||||
|
||||
alreadyDirty.OffsetBy(x, y);
|
||||
dirtyRegion.Include(&alreadyDirty);
|
||||
|
||||
fWindow->MarkDirty(&dirtyRegion);
|
||||
|
||||
copyRegion.OffsetBy(-x, -y);
|
||||
|
||||
if (fWindow->GetDrawingEngine()->Lock()) {
|
||||
fWindow->GetDrawingEngine()->CopyRegion(©Region, x, y);
|
||||
fWindow->GetDrawingEngine()->Unlock();
|
||||
}
|
||||
} else {
|
||||
fFrame.OffsetBy(x, y);
|
||||
_MoveScreenClipping(x, y, true);
|
||||
}
|
||||
fFrame.OffsetBy(x, y);
|
||||
}
|
||||
#else // 0
|
||||
#pragma mark -
|
||||
|
||||
// MoveBy
|
||||
void
|
||||
@ -410,28 +385,64 @@ ViewLayer::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
|
||||
return;
|
||||
|
||||
fFrame.OffsetBy(x, y);
|
||||
InvalidateScreenClipping(true);
|
||||
|
||||
// to move on screen, we must not be hidden and we must have a parent
|
||||
if (!IsHidden() && fParent && !fIsTopLayer && dirtyRegion) {
|
||||
// clip to parent
|
||||
BRect oldScreenRect(Bounds());
|
||||
oldScreenRect.OffsetByCopy(-x, -y);
|
||||
ConvertToParent(&oldScreenRect);
|
||||
if (!IsHidden() && fParent && dirtyRegion) {
|
||||
#if 0
|
||||
// based on redraw on new location
|
||||
// the place were we are now visible
|
||||
BRect newVisibleBounds = Bounds();
|
||||
// we can use the frame of the old
|
||||
// local clipping to see which parts need invalidation
|
||||
BRect oldVisibleBounds(Bounds());
|
||||
oldVisibleBounds.OffsetBy(-x, -y);
|
||||
ConvertToTop(&oldVisibleBounds);
|
||||
|
||||
BRect screenRect(Bounds());
|
||||
ConvertToParent(&screenRect);
|
||||
ConvertToVisibleInTopView(&newVisibleBounds);
|
||||
|
||||
// TODO: see AddChild
|
||||
// TODO: shouldn't we use regions?
|
||||
BRect dirty = oldScreenRect | screenRect;
|
||||
dirty = dirty & fParent->Bounds();
|
||||
fParent->ConvertToTop(&dirty);
|
||||
|
||||
dirtyRegion->Include(dirty);
|
||||
dirtyRegion->Include(oldVisibleBounds);
|
||||
// newVisibleBounds already is in screen coords
|
||||
dirtyRegion->Include(newVisibleBounds);
|
||||
#else
|
||||
// blitting version, invalidates
|
||||
// old contents
|
||||
BRect oldVisibleBounds(Bounds());
|
||||
oldVisibleBounds.OffsetBy(-x, -y);
|
||||
ConvertToTop(&oldVisibleBounds);
|
||||
|
||||
BRect newVisibleBounds(Bounds());
|
||||
// NOTE: using ConvertToVisibleInTopView()
|
||||
// instead of ConvertToTop()! see below
|
||||
ConvertToVisibleInTopView(&newVisibleBounds);
|
||||
|
||||
newVisibleBounds.OffsetBy(-x, -y);
|
||||
|
||||
// clipping oldVisibleBounds to newVisibleBounds
|
||||
// makes sure we don't copy parts hidden under
|
||||
// parent views
|
||||
BRegion copyRegion(oldVisibleBounds & newVisibleBounds);
|
||||
fWindow->CopyContents(©Region, x, y);
|
||||
|
||||
BRegion dirty(oldVisibleBounds);
|
||||
newVisibleBounds.OffsetBy(x, y);
|
||||
dirty.Exclude(newVisibleBounds);
|
||||
dirtyRegion->Include(&dirty);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!fParent) {
|
||||
// the top view's screen clipping does not change,
|
||||
// because no parts are clipped away from parent
|
||||
// views
|
||||
_MoveScreenClipping(x, y, true);
|
||||
} else {
|
||||
// parts might have been revealed from underneath
|
||||
// the parent, or might now be hidden underneath
|
||||
// the parent, this is taken care of when building
|
||||
// the screen clipping
|
||||
InvalidateScreenClipping(true);
|
||||
}
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
// ResizeBy
|
||||
void
|
||||
@ -472,19 +483,17 @@ ViewLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
|
||||
ConvertToTop(&dirty);
|
||||
dirtyRegion->Include(&dirty);
|
||||
}
|
||||
|
||||
// layout the children
|
||||
for (ViewLayer* child = FirstChild(); child; child = NextChild())
|
||||
child->ParentResized(x, y, dirtyRegion);
|
||||
|
||||
// at this point, children are at their new locations,
|
||||
// so we can rebuild the clipping
|
||||
RebuildClipping(false);
|
||||
} else {
|
||||
// just layout the children
|
||||
for (ViewLayer* child = FirstChild(); child; child = NextChild())
|
||||
child->ParentResized(x, y, NULL);
|
||||
}
|
||||
|
||||
// layout the children
|
||||
for (ViewLayer* child = FirstChild(); child; child = NextChild())
|
||||
child->ParentResized(x, y, dirtyRegion);
|
||||
|
||||
// at this point, children are at their new locations,
|
||||
// so we can rebuild the clipping
|
||||
// TODO: when the implementation of Hide() and Show() is
|
||||
// complete, see if this should be avoided
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
// ParentResized
|
||||
@ -542,6 +551,8 @@ ViewLayer::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
|
||||
InvalidateScreenClipping(true);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// Draw
|
||||
void
|
||||
ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
@ -606,20 +617,17 @@ ViewLayer::ClientDraw(DrawingEngine* drawingEngine, BRegion* effectiveClipping)
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// IsHidden
|
||||
bool
|
||||
ViewLayer::IsHidden() const
|
||||
{
|
||||
// if we're explicitely hidden...
|
||||
// if we're explicitely hidden, then we're hidden...
|
||||
if (fHidden)
|
||||
return true;
|
||||
|
||||
// if we don't have a window, or our window is hidden,
|
||||
// then yes, we're hidden too
|
||||
if (fWindow == NULL || (fWindow && fWindow->IsHidden()))
|
||||
return true;
|
||||
|
||||
// if we're not hidden yet, we might still be hidden if our parent is
|
||||
// ...but if we're not hidden, we might still be hidden if our parent is
|
||||
if (fParent)
|
||||
return fParent->IsHidden();
|
||||
|
||||
@ -631,18 +639,30 @@ ViewLayer::IsHidden() const
|
||||
void
|
||||
ViewLayer::Hide()
|
||||
{
|
||||
fHidden = true;
|
||||
if (!fHidden) {
|
||||
fHidden = true;
|
||||
|
||||
// TODO: track regions
|
||||
if (fParent && !fParent->IsHidden()) {
|
||||
// TODO: track regions
|
||||
// RebuildClipping()
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show
|
||||
void
|
||||
ViewLayer::Show()
|
||||
{
|
||||
fHidden = false;
|
||||
if (fHidden) {
|
||||
fHidden = false;
|
||||
|
||||
// TODO: track regions
|
||||
if (fParent && !fParent->IsHidden()) {
|
||||
// TODO: track regions
|
||||
// RebuildClipping()
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PrintToStream
|
||||
@ -655,9 +675,6 @@ ViewLayer::PrintToStream() const
|
||||
void
|
||||
ViewLayer::RebuildClipping(bool deep)
|
||||
{
|
||||
// remember current local clipping in dirty region
|
||||
BRegion oldLocalClipping(fLocalClipping);
|
||||
|
||||
// the clipping spans over the bounds area
|
||||
fLocalClipping.Set(Bounds());
|
||||
|
||||
@ -678,13 +695,18 @@ ViewLayer::ScreenClipping(BRegion* windowContentClipping, bool force) const
|
||||
{
|
||||
if (!fScreenClippingValid || force) {
|
||||
fScreenClipping = fLocalClipping;
|
||||
if (fParent) {
|
||||
BRect parentWindow = fParent->Bounds();
|
||||
ConvertFromParent(&parentWindow);
|
||||
BRegion visibleInParent(parentWindow);
|
||||
fScreenClipping.IntersectWith(&visibleInParent);
|
||||
}
|
||||
ConvertToTop(&fScreenClipping);
|
||||
|
||||
// see if we parts of our bounds are hidden underneath
|
||||
// the parent, the local clipping does not account for this
|
||||
BRect clippedBounds = Bounds();
|
||||
ConvertToVisibleInTopView(&clippedBounds);
|
||||
if (clippedBounds.Width() < fScreenClipping.Frame().Width() ||
|
||||
clippedBounds.Height() < fScreenClipping.Frame().Height()) {
|
||||
BRegion temp(clippedBounds);
|
||||
fScreenClipping.IntersectWith(&temp);
|
||||
}
|
||||
|
||||
fScreenClipping.IntersectWith(windowContentClipping);
|
||||
fScreenClippingValid = true;
|
||||
}
|
||||
|
@ -23,12 +23,14 @@ class ViewLayer {
|
||||
inline BRect Frame() const
|
||||
{ return fFrame; }
|
||||
BRect Bounds() const;
|
||||
// converts the given frame up the view hirarchy and
|
||||
// clips to each views bounds
|
||||
void ConvertToVisibleInTopView(BRect* bounds) const;
|
||||
|
||||
inline rgb_color ViewColor() const
|
||||
{ return fViewColor; }
|
||||
|
||||
void AttachedToWindow(WindowLayer* window,
|
||||
bool topLayer = false);
|
||||
void AttachedToWindow(WindowLayer* window);
|
||||
void DetachedFromWindow();
|
||||
|
||||
// tree stuff
|
||||
@ -61,6 +63,10 @@ class ViewLayer {
|
||||
void ConvertToTop(BRect* rect) const;
|
||||
void ConvertToTop(BRegion* region) const;
|
||||
|
||||
void ConvertFromTop(BPoint* point) const;
|
||||
void ConvertFromTop(BRect* rect) const;
|
||||
void ConvertFromTop(BRegion* region) const;
|
||||
|
||||
// settings
|
||||
void SetName(const char* string);
|
||||
inline const char* Name() const
|
||||
@ -120,7 +126,6 @@ private:
|
||||
|
||||
WindowLayer* fWindow;
|
||||
ViewLayer* fParent;
|
||||
bool fIsTopLayer;
|
||||
|
||||
ViewLayer* fFirstChild;
|
||||
ViewLayer* fPreviousSibling;
|
||||
|
@ -56,7 +56,7 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
|
||||
// fFrame as if it had
|
||||
fTopLayer = new(nothrow) ViewLayer(fFrame, "top view", B_FOLLOW_ALL, 0,
|
||||
(rgb_color){ 255, 255, 255, 255 });
|
||||
fTopLayer->AttachedToWindow(this, true);
|
||||
fTopLayer->AttachedToWindow(this);
|
||||
|
||||
fClient->Run();
|
||||
}
|
||||
@ -82,7 +82,7 @@ WindowLayer::MessageReceived(BMessage* message)
|
||||
}
|
||||
}
|
||||
_DrawBorder();
|
||||
_DrawContents(fTopLayer);
|
||||
_TriggerContentRedraw();
|
||||
|
||||
fDesktop->ReadUnlockClipping();
|
||||
} else {
|
||||
@ -307,6 +307,7 @@ WindowLayer::Show()
|
||||
void
|
||||
WindowLayer::MarkDirty(BRegion* regionOnScreen)
|
||||
{
|
||||
// for triggering MSG_REDRAW
|
||||
if (fDesktop)
|
||||
fDesktop->MarkDirty(regionOnScreen);
|
||||
}
|
||||
@ -315,6 +316,7 @@ WindowLayer::MarkDirty(BRegion* regionOnScreen)
|
||||
void
|
||||
WindowLayer::MarkContentDirty(BRegion* regionOnScreen)
|
||||
{
|
||||
// for triggering MSG_REDRAW
|
||||
if (fDesktop && fDesktop->LockClipping()) {
|
||||
|
||||
regionOnScreen->IntersectWith(&fVisibleContentRegion);
|
||||
@ -323,29 +325,65 @@ WindowLayer::MarkContentDirty(BRegion* regionOnScreen)
|
||||
fDesktop->UnlockClipping();
|
||||
}
|
||||
}
|
||||
/*
|
||||
// DirtyRegion
|
||||
BRegion
|
||||
WindowLayer::DirtyRegion()
|
||||
{
|
||||
BRegion dirty;
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
dirty = *fDesktop->DirtyRegion();
|
||||
fDesktop->ReadUnlockClipping();
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
*/
|
||||
|
||||
# pragma mark -
|
||||
|
||||
// _DrawContents
|
||||
// CopyContents
|
||||
void
|
||||
WindowLayer::_DrawContents(ViewLayer* layer)
|
||||
WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset)
|
||||
{
|
||||
// this function takes care of invalidating parts that could not be copied
|
||||
|
||||
if (fDesktop->LockClipping()) {
|
||||
|
||||
BRegion newDirty(*region);
|
||||
|
||||
region->IntersectWith(&fVisibleContentRegion);
|
||||
region->OffsetBy(xOffset, yOffset);
|
||||
region->IntersectWith(&fVisibleContentRegion);
|
||||
|
||||
region->OffsetBy(-xOffset, -yOffset);
|
||||
|
||||
newDirty.Exclude(region);
|
||||
|
||||
_ShiftPartOfRegion(fDesktop->DirtyRegion(), region, xOffset, yOffset);
|
||||
if (fDrawingEngine->Lock()) {
|
||||
fDrawingEngine->CopyRegion(region, xOffset, yOffset);
|
||||
fDrawingEngine->Unlock();
|
||||
}
|
||||
|
||||
if (fCurrentUpdateSession)
|
||||
_ShiftPartOfRegion(&fCurrentUpdateSession->DirtyRegion(), region, xOffset, yOffset);
|
||||
if (fPendingUpdateSession)
|
||||
_ShiftPartOfRegion(&fPendingUpdateSession->DirtyRegion(), region, xOffset, yOffset);
|
||||
|
||||
newDirty.OffsetBy(xOffset, yOffset);
|
||||
newDirty.IntersectWith(&fVisibleContentRegion);
|
||||
fDesktop->MarkDirty(&newDirty);
|
||||
|
||||
fDesktop->UnlockClipping();
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark -
|
||||
|
||||
// _ShiftPartOfRegion
|
||||
void
|
||||
WindowLayer::_ShiftPartOfRegion(BRegion* region, BRegion* regionToShift,
|
||||
int32 xOffset, int32 yOffset)
|
||||
{
|
||||
BRegion common(*region);
|
||||
common.IntersectWith(regionToShift);
|
||||
region->Exclude(&common);
|
||||
common.OffsetBy(xOffset, yOffset);
|
||||
region->Include(&common);
|
||||
}
|
||||
|
||||
// _TriggerContentRedraw
|
||||
void
|
||||
WindowLayer::_TriggerContentRedraw()
|
||||
{
|
||||
//printf("%s - DrawContents()\n", Name());
|
||||
if (!layer)
|
||||
layer = fTopLayer;
|
||||
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
|
||||
BRegion dirtyContentRegion(fVisibleContentRegion);
|
||||
@ -367,8 +405,8 @@ if (fDrawingEngine->Lock()) {
|
||||
|
||||
fDesktop->MarkClean(&dirtyContentRegion);
|
||||
|
||||
layer->Draw(fDrawingEngine, &dirtyContentRegion,
|
||||
&fVisibleContentRegion, true);
|
||||
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
|
||||
&fVisibleContentRegion, false);
|
||||
}
|
||||
|
||||
fDesktop->ReadUnlockClipping();
|
||||
@ -398,8 +436,14 @@ WindowLayer::_DrawClient(int32 token)
|
||||
|
||||
BRegion effectiveClipping(fEffectiveDrawingRegion);
|
||||
effectiveClipping.IntersectWith(&layer->ScreenClipping(&fVisibleContentRegion));
|
||||
|
||||
|
||||
if (effectiveClipping.CountRects() > 0) {
|
||||
// clear the back ground
|
||||
// TODO: only if this is the first drawing command for
|
||||
// this layer of course!
|
||||
layer->Draw(fDrawingEngine, &effectiveClipping,
|
||||
&fVisibleContentRegion, false);
|
||||
|
||||
layer->ClientDraw(fDrawingEngine, &effectiveClipping);
|
||||
}
|
||||
|
||||
@ -456,6 +500,8 @@ WindowLayer::_DrawBorder()
|
||||
void
|
||||
WindowLayer::_MarkContentDirty(BRegion* contentDirtyRegion)
|
||||
{
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
|
||||
if (contentDirtyRegion->CountRects() <= 0)
|
||||
return;
|
||||
|
||||
@ -480,12 +526,17 @@ WindowLayer::_MarkContentDirty(BRegion* contentDirtyRegion)
|
||||
fClient->PostMessage(MSG_UPDATE);
|
||||
fUpdateRequested = true;
|
||||
}
|
||||
|
||||
fDesktop->ReadUnlockClipping();
|
||||
}
|
||||
}
|
||||
|
||||
// _BeginUpdate
|
||||
void
|
||||
WindowLayer::_BeginUpdate()
|
||||
{
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
|
||||
if (fUpdateRequested && !fCurrentUpdateSession) {
|
||||
fCurrentUpdateSession = fPendingUpdateSession;
|
||||
fPendingUpdateSession = NULL;
|
||||
@ -498,12 +549,17 @@ WindowLayer::_BeginUpdate()
|
||||
}
|
||||
fEffectiveDrawingRegionValid = false;
|
||||
}
|
||||
|
||||
fDesktop->ReadUnlockClipping();
|
||||
}
|
||||
}
|
||||
|
||||
// _EndUpdate
|
||||
void
|
||||
WindowLayer::_EndUpdate()
|
||||
{
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
|
||||
if (fInUpdate) {
|
||||
delete fCurrentUpdateSession;
|
||||
fCurrentUpdateSession = NULL;
|
||||
@ -518,6 +574,9 @@ WindowLayer::_EndUpdate()
|
||||
} else {
|
||||
fUpdateRequested = false;
|
||||
}
|
||||
|
||||
fDesktop->ReadUnlockClipping();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
@ -74,13 +74,19 @@ class WindowLayer : public BLooper {
|
||||
DrawingEngine* GetDrawingEngine() const
|
||||
{ return fDrawingEngine; }
|
||||
|
||||
// BRegion DirtyRegion();
|
||||
void CopyContents(BRegion* region,
|
||||
int32 xOffset, int32 yOffset);
|
||||
|
||||
private:
|
||||
void _DrawContents(ViewLayer* layer = NULL);
|
||||
void _ShiftPartOfRegion(BRegion* region, BRegion* regionToShift,
|
||||
int32 xOffset, int32 yOffset);
|
||||
|
||||
// different types of drawing
|
||||
void _TriggerContentRedraw();
|
||||
void _DrawClient(int32 token);
|
||||
void _DrawBorder();
|
||||
|
||||
// handling update sessions
|
||||
void _MarkContentDirty(BRegion* contentDirtyRegion);
|
||||
void _BeginUpdate();
|
||||
void _EndUpdate();
|
||||
@ -110,11 +116,26 @@ class WindowLayer : public BLooper {
|
||||
DrawingEngine* fDrawingEngine;
|
||||
Desktop* fDesktop;
|
||||
|
||||
// for mapping drawing requests from the client
|
||||
// to the local view pointers
|
||||
BList fTokenViewMap;
|
||||
|
||||
// the client looper, which will do asynchronous
|
||||
// drawing (the window will clear the content
|
||||
// and the client is supposed to draw onto
|
||||
// the cleared regions)
|
||||
ClientLooper* fClient;
|
||||
// The synchronization, which client drawing commands
|
||||
// belong to the redraw of which region is handled
|
||||
// through an UpdateSession. When the client has
|
||||
// been informed that it should redraw stuff, then
|
||||
// this is the current update session. All new
|
||||
// redraw requests from the root layer will go
|
||||
// into the pending update session.
|
||||
UpdateSession* fCurrentUpdateSession;
|
||||
UpdateSession* fPendingUpdateSession;
|
||||
// these two flags are supposed to ensure a sane
|
||||
// and consistent update session
|
||||
bool fUpdateRequested;
|
||||
bool fInUpdate;
|
||||
};
|
||||
|
@ -144,13 +144,15 @@ Window::AddWindow(BRect frame, const char* name)
|
||||
|
||||
f.OffsetBy(f.Width() + 6, 0);
|
||||
|
||||
layer = new ViewLayer(f, "View", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM,
|
||||
// layer = new ViewLayer(f, "View", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM,
|
||||
layer = new ViewLayer(f, "View", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM,
|
||||
B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
|
||||
layer1->AddChild(layer);
|
||||
|
||||
f.OffsetBy(f.Width() + 6, 0);
|
||||
|
||||
layer = new ViewLayer(f, "View", B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM,
|
||||
// layer = new ViewLayer(f, "View", B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM,
|
||||
layer = new ViewLayer(f, "View", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM,
|
||||
B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
|
||||
layer1->AddChild(layer);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user