Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions
nsViewManager.cpp File Reference
#include "plarena.h"
#include "nsViewManager.h"
#include "nsUnitConversion.h"
#include "nsIRenderingContext.h"
#include "nsIDeviceContext.h"
#include "nsGfxCIID.h"
#include "nsIScrollableView.h"
#include "nsView.h"
#include "nsISupportsArray.h"
#include "nsICompositeListener.h"
#include "nsCOMPtr.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include "nsGUIEvent.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsRegion.h"
#include "nsInt64.h"
#include "nsScrollPortView.h"
#include "nsHashtable.h"
#include "nsCOMArray.h"

Go to the source code of this file.

Classes

class  BlendingBuffers
struct  DisplayListElement2
struct  DisplayZTreeNode
struct  nsViewManagerEvent
struct  nsInvalidateEvent
struct  nsSynthMouseMoveEvent

Defines

#define PL_ARENA_CONST_ALIGN_MASK   (sizeof(void*)-1)
#define ARENA_ALLOCATE(var, pool, type)
#define VIEW_RENDERED   0x00000001
 XXX TODO XXX.
#define PUSH_CLIP   0x00000002
#define POP_CLIP   0x00000004
#define VIEW_TRANSPARENT   0x00000008
#define VIEW_TRANSLUCENT   0x00000010
#define VIEW_CLIPPED   0x00000020
#define VIEW_ISSCROLLED   0x00000040
#define PUSH_FILTER   0x00000080
#define POP_FILTER   0x00000100
#define NSCOORD_NONE   PR_INT32_MIN
#define SUPPORT_TRANSLUCENT_VIEWS
#define MAX_OPAQUE_REGION_COMPLEXITY   10

Functions

static NS_DEFINE_IID (kBlenderCID, NS_BLENDER_CID)
static NS_DEFINE_IID (kRegionCID, NS_REGION_CID)
static NS_DEFINE_IID (kRenderingContextCID, NS_RENDERING_CONTEXT_CID)
static NS_DEFINE_CID (kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID)
static void *PR_CALLBACK HandlePLEvent (PLEvent *aEvent)
static void PR_CALLBACK DestroyPLEvent (PLEvent *aEvent)
static PRInt32 CompareZIndex (PRInt32 aZIndex1, PRBool aTopMost1, PRBool aIsAuto1, PRInt32 aZIndex2, PRBool aTopMost2, PRBool aIsAuto2)
static PRBool IsViewVisible (nsView *aView)
static PRBool DoDoubleBuffering (void)
static void ConvertNativeRegionToAppRegion (nsIRegion *aIn, nsRegion *aOut, nsIDeviceContext *context)
static void ApplyZOrderStableSort (nsVoidArray &aBuffer, nsVoidArray &aMergeTmp, PRInt32 aStart, PRInt32 aEnd)
static nsInt64 BuildExtendedZIndex (nsView *aView)
static void SortByZOrder (DisplayZTreeNode *aNode, nsVoidArray &aBuffer, nsVoidArray &aMergeTmp, PRBool aForceSort, PLArenaPool &aPool)
static void PushStateAndClip (nsIRenderingContext **aRCs, PRInt32 aCount, nsRect &aRect)
static void PopState (nsIRenderingContext **aRCs, PRInt32 aCount)
static nsresult NewOffscreenContext (nsIDeviceContext *deviceContext, nsIDrawingSurface *surface, const nsRect &aRect, nsIRenderingContext **aResult)
static void AccumulateIntersectionsIntoDirtyRegion (nsView *aTargetView, nsView *aSourceView, const nsPoint &aOffset)
static PRBool ComputePlaceholderContainment (nsView *aView)
static PRBool IsViewportScrollApparatus (nsView *aView, nsIView *aRootScroll)
 Returns PR_TRUE if this view is (or is part of) a viewport scrollbar/scrollcorner.
static PRBool IsAncestorOf (const nsIView *aAncestor, const nsIView *aView)
static nsresult EnsureZTreeNodeCreated (nsView *aView, DisplayZTreeNode *&aNode, PLArenaPool &aPool)
static nsViewFindFloatingViewContaining (nsView *aView, nsPoint aPt)
 Find the first floating view with a widget in a postorder traversal of the view tree that contains the point.

Define Documentation

#define ARENA_ALLOCATE (   var,
  pool,
  type 
)
Value:
{void *_tmp_; PL_ARENA_ALLOCATE(_tmp_, pool, sizeof(type)); \
    var = NS_REINTERPRET_CAST(type*, _tmp_); }

Definition at line 72 of file nsViewManager.cpp.

Definition at line 119 of file nsViewManager.cpp.

Definition at line 109 of file nsViewManager.cpp.

Definition at line 42 of file nsViewManager.cpp.

#define POP_CLIP   0x00000004

Definition at line 100 of file nsViewManager.cpp.

#define POP_FILTER   0x00000100

Definition at line 107 of file nsViewManager.cpp.

#define PUSH_CLIP   0x00000002

Definition at line 99 of file nsViewManager.cpp.

#define PUSH_FILTER   0x00000080

Definition at line 106 of file nsViewManager.cpp.

Definition at line 111 of file nsViewManager.cpp.

#define VIEW_CLIPPED   0x00000020

Definition at line 103 of file nsViewManager.cpp.

#define VIEW_ISSCROLLED   0x00000040

Definition at line 105 of file nsViewManager.cpp.

#define VIEW_RENDERED   0x00000001

XXX TODO XXX.

DeCOMify newly private methods Optimize view storage A note about platform assumptions:

We assume all native widgets are opaque.

We assume that a widget is z-ordered on top of its parent.

We do NOT assume anything about the relative z-ordering of sibling widgets. Even though we ask for a specific z-order, we don't assume that widget z-ordering actually works.

Definition at line 98 of file nsViewManager.cpp.

#define VIEW_TRANSLUCENT   0x00000010

Definition at line 102 of file nsViewManager.cpp.

#define VIEW_TRANSPARENT   0x00000008

Definition at line 101 of file nsViewManager.cpp.


Function Documentation

static void AccumulateIntersectionsIntoDirtyRegion ( nsView aTargetView,
nsView aSourceView,
const nsPoint aOffset 
) [static]

Definition at line 1652 of file nsViewManager.cpp.

{
  if (aSourceView->HasNonEmptyDirtyRegion()) {
    // In most cases, aSourceView is an ancestor of aTargetView, since most
    // commonly we have dirty rects on the root view.
    nsPoint offset = aTargetView->GetOffsetTo(aSourceView);
    nsRegion intersection;
    intersection.And(*aSourceView->GetDirtyRegion(),
                     aTargetView->GetClippedRect() + offset);
    if (!intersection.IsEmpty()) {
      nsRegion* targetRegion = aTargetView->GetDirtyRegion();
      if (targetRegion) {
        intersection.MoveBy(-offset + aOffset);
        targetRegion->Or(*targetRegion, intersection);
        // Random simplification number...
        targetRegion->SimplifyOutward(20);
      }
    }
  }

  if (aSourceView == aTargetView) {
    // No need to do this with kids of aTargetView
    return;
  }
  
  for (nsView* kid = aSourceView->GetFirstChild();
       kid;
       kid = kid->GetNextSibling()) {
    AccumulateIntersectionsIntoDirtyRegion(aTargetView, kid, aOffset);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ApplyZOrderStableSort ( nsVoidArray aBuffer,
nsVoidArray aMergeTmp,
PRInt32  aStart,
PRInt32  aEnd 
) [static]

Definition at line 1011 of file nsViewManager.cpp.

                                                                                                              {
  if (aEnd - aStart <= 6) {
    // do a fast bubble sort for the small sizes
    for (PRInt32 i = aEnd - 1; i > aStart; i--) {
      PRBool sorted = PR_TRUE;
      for (PRInt32 j = aStart; j < i; j++) {
        DisplayListElement2* e1 = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(j));
        DisplayListElement2* e2 = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(j + 1));
        if (e1->mZIndex > e2->mZIndex) {
          sorted = PR_FALSE;
          // We could use aBuffer.MoveElement(), but it wouldn't be much of
          // a win if any for swapping two elements.
          aBuffer.ReplaceElementAt(e2, j);
          aBuffer.ReplaceElementAt(e1, j + 1);
        }
      }
      if (sorted) {
        return;
      }
    }
  } else {
    // merge sort for the rest
    PRInt32 mid = (aEnd + aStart)/2;

    ApplyZOrderStableSort(aBuffer, aMergeTmp, aStart, mid);
    ApplyZOrderStableSort(aBuffer, aMergeTmp, mid, aEnd);

    DisplayListElement2* e1 = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(mid - 1));
    DisplayListElement2* e2 = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(mid));

    // fast common case: the list is already completely sorted
    if (e1->mZIndex <= e2->mZIndex) {
      return;
    }
    // we have some merging to do.

    PRInt32 i1 = aStart;
    PRInt32 i2 = mid;

    e1 = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(i1));
    e2 = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(i2));
    while (i1 < mid || i2 < aEnd) {
      if (i1 < mid && (i2 == aEnd || e1->mZIndex <= e2->mZIndex)) {
        aMergeTmp.AppendElement(e1);
        i1++;
        if (i1 < mid) {
          e1 = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(i1));
        }
      } else {
        aMergeTmp.AppendElement(e2);
        i2++;
        if (i2 < aEnd) {
          e2 = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(i2));
        }
      }
    }

    for (PRInt32 i = aStart; i < aEnd; i++) {
      aBuffer.ReplaceElementAt(aMergeTmp.ElementAt(i - aStart), i);
    }

    aMergeTmp.Clear();
  }
}

Here is the caller graph for this function:

static nsInt64 BuildExtendedZIndex ( nsView aView) [static]

Definition at line 1076 of file nsViewManager.cpp.

                                                  {
  return (nsInt64(aView->GetZIndex()) << 1) | nsInt64(aView->IsTopMost() ? 1 : 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 CompareZIndex ( PRInt32  aZIndex1,
PRBool  aTopMost1,
PRBool  aIsAuto1,
PRInt32  aZIndex2,
PRBool  aTopMost2,
PRBool  aIsAuto2 
) [static]

Definition at line 397 of file nsViewManager.cpp.

{
  NS_ASSERTION(!aIsAuto1 || aZIndex1 == 0,"auto is set and the z-index is not 0");
  NS_ASSERTION(!aIsAuto2 || aZIndex2 == 0,"auto is set and the z-index is not 0");

  if (aZIndex1 != aZIndex2) {
    return aZIndex1 - aZIndex2;
  } else {
    return aTopMost1 - aTopMost2;
  }
}

Here is the caller graph for this function:

static PRBool ComputePlaceholderContainment ( nsView aView) [static]

Definition at line 2341 of file nsViewManager.cpp.

                                                           {
  PRBool containsPlaceholder = aView->IsZPlaceholderView();

  nsView* child;
  for (child = aView->GetFirstChild(); child != nsnull; child = child->GetNextSibling()) {
    if (ComputePlaceholderContainment(child)) {
      containsPlaceholder = PR_TRUE;
    }
  }

  if (containsPlaceholder) {
    aView->SetViewFlags(aView->GetViewFlags() | NS_VIEW_FLAG_CONTAINS_PLACEHOLDER);
  } else {
    aView->SetViewFlags(aView->GetViewFlags() & ~NS_VIEW_FLAG_CONTAINS_PLACEHOLDER);
  }

  return containsPlaceholder;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ConvertNativeRegionToAppRegion ( nsIRegion aIn,
nsRegion *  aOut,
nsIDeviceContext context 
) [static]

Definition at line 731 of file nsViewManager.cpp.

{
  nsRegionRectSet* rects = nsnull;
  aIn->GetRects(&rects);
  if (!rects)
    return;
  
  float  p2t;
  p2t = context->DevUnitsToAppUnits();

  PRUint32 i;
  for (i = 0; i < rects->mNumRects; i++) {
    const nsRegionRect& inR = rects->mRects[i];
    nsRect outR;
    outR.x = NSToIntRound(inR.x * p2t);
    outR.y = NSToIntRound(inR.y * p2t);
    outR.width = NSToIntRound(inR.width * p2t);
    outR.height = NSToIntRound(inR.height * p2t);
    aOut->Or(*aOut, outR);
  }

  aIn->FreeRects(rects);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void PR_CALLBACK DestroyPLEvent ( PLEvent aEvent) [static]

Definition at line 365 of file nsViewManager.cpp.

{
  NS_ASSERTION(nsnull != aEvent,"Event is null");
  nsViewManagerEvent *event = NS_STATIC_CAST(nsViewManagerEvent*, aEvent);
  delete event;
}
static PRBool DoDoubleBuffering ( void  ) [static]

Definition at line 705 of file nsViewManager.cpp.

{
  static PRBool gotDoublebufferPrefs = PR_FALSE;
  static PRBool doDoublebuffering    = PR_TRUE;  /* Double-buffering is ON by default */
  
  if (!gotDoublebufferPrefs) {
    nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
    if (prefBranch) {
      PRBool val;
      if (NS_SUCCEEDED(prefBranch->GetBoolPref("viewmanager.do_doublebuffering", &val))) {
        doDoublebuffering = val;
      }
    }

#ifdef DEBUG
    if (!doDoublebuffering) {
      printf("nsViewManager: Note: Double-buffering disabled via prefs.\n");
    }
#endif /* DEBUG */

    gotDoublebufferPrefs = PR_TRUE;
  }
  
  return doDoublebuffering;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static nsresult EnsureZTreeNodeCreated ( nsView aView,
DisplayZTreeNode *&  aNode,
PLArenaPool aPool 
) [static]

Definition at line 3667 of file nsViewManager.cpp.

{
  if (nsnull == aNode) {
    ARENA_ALLOCATE(aNode, &aPool, DisplayZTreeNode);

    if (nsnull == aNode) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
    aNode->mView = aView;
    aNode->mDisplayElement = nsnull;
    aNode->mZChild = nsnull;
    aNode->mZSibling = nsnull;
  }
  return NS_OK;
}

Here is the caller graph for this function:

static nsView* FindFloatingViewContaining ( nsView aView,
nsPoint  aPt 
) [static]

Find the first floating view with a widget in a postorder traversal of the view tree that contains the point.

Thus more deeply nested floating views are preferred over their ancestors, and floating views earlier in the view hierarchy (i.e., added later) are preferred over their siblings. This is adequate for finding the "topmost" floating view under a point, given that floating views don't supporting having a specific z-index.

We cannot exit early when aPt is outside the view bounds, because floating views aren't necessarily included in their parent's bounds, so this could traverse the entire view hierarchy --- use carefully.

Definition at line 4523 of file nsViewManager.cpp.

{
  for (nsView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
    nsView* r = FindFloatingViewContaining(v, aPt - v->GetOffsetTo(aView));
    if (r)
      return r;
  }

  if (aView->GetFloating() && aView->HasWidget() &&
      aView->GetDimensions().Contains(aPt) && IsViewVisible(aView))
    return aView;

  return nsnull;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* PR_CALLBACK HandlePLEvent ( PLEvent aEvent) [static]

Definition at line 356 of file nsViewManager.cpp.

{
  NS_ASSERTION(nsnull != aEvent,"Event is null");
  nsViewManagerEvent *event = NS_STATIC_CAST(nsViewManagerEvent*, aEvent);

  event->HandleEvent();
  return nsnull;
}
static PRBool IsAncestorOf ( const nsIView aAncestor,
const nsIView aView 
) [static]

Definition at line 2975 of file nsViewManager.cpp.

{
  while (nsnull != aView) {
    aView = aView->GetParent();
    if (aView == aAncestor) {
      return PR_TRUE;
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool IsViewportScrollApparatus ( nsView aView,
nsIView aRootScroll 
) [static]

Returns PR_TRUE if this view is (or is part of) a viewport scrollbar/scrollcorner.

Definition at line 2363 of file nsViewManager.cpp.

                                                                             {
  if (!aRootScroll)
    return PR_FALSE;

  // aView is NOT part of the scrolling apparatus if and only if it is a descendant
  // of aRootScroll, OR it is a fixed position view or descendant
  nsIView* aRootScrollframeView = aRootScroll->GetParent();
  while (aView) {
    if (aView == aRootScroll) {
      // We're part of the scrolled document.
      return PR_FALSE;
    }
    if (aView == aRootScrollframeView) {
      return PR_TRUE;
    }
    aView = aView->GetParent();
  }
  // We're the root view or perhaps the view for a position:fixed element
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool IsViewVisible ( nsView aView) [static]

Definition at line 410 of file nsViewManager.cpp.

{
  for (nsIView *view = aView; view; view = view->GetParent()) {
    // We don't check widget visibility here because in the future (with
    // the better approach to this that's in attachment 160801 on bug
    // 227361), callers of the equivalent to this function should be able
    // to rely on being notified when the result of this function changes.
    if (view->GetVisibility() == nsViewVisibility_kHide)
      return PR_FALSE;
  }
  // Find out if the root view is visible by asking the view observer
  // (this won't be needed anymore if we link view trees across chrome /
  // content boundaries in DocumentViewerImpl::MakeWindow).
  nsIViewObserver* vo = aView->GetViewManager()->GetViewObserver();
  return vo && vo->IsVisible();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static nsresult NewOffscreenContext ( nsIDeviceContext deviceContext,
nsIDrawingSurface surface,
const nsRect aRect,
nsIRenderingContext **  aResult 
) [static]

Definition at line 1473 of file nsViewManager.cpp.

{
  nsresult             rv;
  nsIRenderingContext *context = nsnull;

  rv = deviceContext->CreateRenderingContext(surface, context);
  if (NS_FAILED(rv))
    return rv;

  // always initialize clipping, linux won't draw images otherwise.
  nsRect clip(0, 0, aRect.width, aRect.height);
  context->SetClipRect(clip, nsClipCombine_kReplace);

  context->Translate(-aRect.x, -aRect.y);
  
  *aResult = context;
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static NS_DEFINE_IID ( kBlenderCID  ,
NS_BLENDER_CID   
) [static]
static NS_DEFINE_IID ( kRegionCID  ,
NS_REGION_CID   
) [static]
static NS_DEFINE_IID ( kRenderingContextCID  ,
NS_RENDERING_CONTEXT_CID   
) [static]
static void PopState ( nsIRenderingContext **  aRCs,
PRInt32  aCount 
) [static]

Definition at line 1217 of file nsViewManager.cpp.

                                                                 {
  for (int i = 0; i < aCount; i++) {
    if (aRCs[i])
      aRCs[i]->PopState();
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void PushStateAndClip ( nsIRenderingContext **  aRCs,
PRInt32  aCount,
nsRect aRect 
) [static]

Definition at line 1208 of file nsViewManager.cpp.

                                                                                        {
  for (int i = 0; i < aCount; i++) {
    if (aRCs[i]) {
      aRCs[i]->PushState();
      aRCs[i]->SetClipRect(aRect, nsClipCombine_kIntersect);
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void SortByZOrder ( DisplayZTreeNode aNode,
nsVoidArray aBuffer,
nsVoidArray aMergeTmp,
PRBool  aForceSort,
PLArenaPool aPool 
) [static]

Definition at line 1085 of file nsViewManager.cpp.

{
  PRBool autoZIndex = PR_TRUE;
  nsInt64 explicitZIndex = 0;

  if (nsnull != aNode->mView) {
    // Hixie says only non-translucent elements can have z-index:auto
    autoZIndex = aNode->mView->GetZIndexIsAuto() && aNode->mView->GetOpacity() == 1.0f;
    explicitZIndex = BuildExtendedZIndex(aNode->mView);
  }

  if (nsnull == aNode->mZChild) {
    if (nsnull != aNode->mDisplayElement) {
      aBuffer.AppendElement(aNode->mDisplayElement);
      aNode->mDisplayElement->mZIndex = explicitZIndex;
      aNode->mDisplayElement = nsnull;
    }
    return;
  }

  DisplayZTreeNode *child;
  PRInt32 childStartIndex = aBuffer.Count();
  for (child = aNode->mZChild; nsnull != child; child = child->mZSibling) {
    SortByZOrder(child, aBuffer, aMergeTmp, PR_FALSE, aPool);
  }
  PRInt32 childEndIndex = aBuffer.Count();
  PRInt32 sortStartIndex = childStartIndex;
  PRInt32 sortEndIndex = childEndIndex;
  PRBool hasClip = PR_FALSE;
  DisplayListElement2* ePush = nsnull;
  DisplayListElement2* ePop = nsnull;

  // When we sort the children by z-index, don't sort any PUSH_ or POP_ instructions
  // which are bracketing the children.
  while (sortEndIndex - sortStartIndex >= 2) {
    DisplayListElement2* childElem =
      NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortStartIndex));
    if (childElem->mView == aNode->mView) {
      if (childElem->mFlags & PUSH_CLIP) {
        hasClip = PR_TRUE;
        // remember where the push and pop instructions are so we can
        // duplicate them later, if necessary
        ePush = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortStartIndex));
        ePop = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortEndIndex - 1));
        sortStartIndex++;
        sortEndIndex--;
      } else if (childElem->mFlags & PUSH_FILTER) {
        NS_ASSERTION(!autoZIndex, "FILTER cannot apply to z-index:auto view");
        sortStartIndex++;
        sortEndIndex--;
      } else {
        break;
      }
    } else {
      break;
    }
  }

  if (hasClip) {
    ApplyZOrderStableSort(aBuffer, aMergeTmp, sortStartIndex, sortEndIndex);
    
    if (autoZIndex && sortEndIndex - sortStartIndex >= 1) {
      // If we're an auto-z-index, then we have to worry about the possibility that some of
      // our children may be moved by the z-sorter beyond the bounds of the PUSH...POP clip
      // instructions. So basically, we ensure that around every group of children of
      // equal z-index, there is a PUSH...POP element pair with the same z-index. The stable
      // z-sorter will not break up such a group.
      // Note that if we're not an auto-z-index set, then our children will never be broken
      // up so we don't need to do this.
      // We also don't have to worry if we have no real children.
      // We don't have to do the same thing for PUSH_FILTER/POP_FILTER because
      // a filter always corresponds to non-auto z-index; there is no way children
      // can be sorted beyond the PUSH/POP instructions.
      DisplayListElement2* eFirstChild = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortStartIndex));

      ePush->mZIndex = eFirstChild->mZIndex;

      DisplayListElement2* eLastChild = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortEndIndex - 1));

      ePop->mZIndex = eLastChild->mZIndex;

      DisplayListElement2* e = eFirstChild;
      for (PRInt32 i = sortStartIndex; i < sortEndIndex - 1; i++) {
        DisplayListElement2* eNext = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(i + 1));
        NS_ASSERTION(e->mZIndex <= eNext->mZIndex, "Display Z-list is not sorted!!");
        if (e->mZIndex != eNext->mZIndex) {
          // need to insert a POP for the last sequence and a PUSH for the next sequence
          DisplayListElement2 *newPop, *newPush;

          ARENA_ALLOCATE(newPop, &aPool, DisplayListElement2);
          ARENA_ALLOCATE(newPush, &aPool, DisplayListElement2);

          *newPop = *ePop;
          newPop->mZIndex = e->mZIndex;
          *newPush = *ePush;
          newPush->mZIndex = eNext->mZIndex;
          aBuffer.InsertElementAt(newPop, i + 1);
          aBuffer.InsertElementAt(newPush, i + 2);
          i += 2;
          childEndIndex += 2;
          sortEndIndex += 2;
        }
        e = eNext;
      }
    }
  } else if (aForceSort || !autoZIndex || aNode->mView->IsTopMost()) {
    // We must do a sort now if we're going to update all the topmost bits
    // below
    ApplyZOrderStableSort(aBuffer, aMergeTmp, sortStartIndex, sortEndIndex);
  }

  for (PRInt32 i = childStartIndex; i < childEndIndex; i++) {
    DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(i));
    if (!autoZIndex) {
      element->mZIndex = explicitZIndex;
    } else if (aNode->mView->IsTopMost()) {
      // promote children to topmost if this view is topmost
      element->mZIndex |= nsInt64(1);
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function: