layout/xul/nsListBoxBodyFrame.h
author Lukasz Anforowicz <lukasza@chromium.org>
Mon, 09 Apr 2018 14:33:07 +0000
changeset 466985 861650deaddc7dfc160136f40bf3f7c83c504e09
parent 463054 0016368787a44bdf5deb4c9b73f3c0b59d2bc27a
child 469548 5add57b9a0cc9a37590bbd970ad04ad1d2f3cf7e
permissions -rw-r--r--
Bug 1452097 [wpt PR 9952] - Make 2 tests immune to legitimate races between cross-origin subframes, a=testonly Automatic update from web-platform-testsMake 2 tests immune to legitimate races between cross-origin subframes Bug: 820589 Change-Id: I16c02746c61f42fafead5f96ae436b331fba4f85 Reviewed-on: https://chromium-review.googlesource.com/957587 Commit-Queue: Ɓukasz Anforowicz <lukasza@chromium.org> Reviewed-by: Alex Moshchuk <alexmos@chromium.org> Cr-Commit-Position: refs/heads/master@{#542360} wpt-commits: 1f638e87c2b4411c53121108efc7aa19df8bc543 wpt-pr: 9952 wpt-commits: 1f638e87c2b4411c53121108efc7aa19df8bc543 wpt-pr: 9952

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef nsListBoxBodyFrame_h
#define nsListBoxBodyFrame_h

#include "mozilla/Attributes.h"
#include "nsCOMPtr.h"
#include "nsBoxFrame.h"
#include "nsIScrollbarMediator.h"
#include "nsIReflowCallback.h"
#include "nsBoxLayoutState.h"
#include "nsThreadUtils.h"
#include "nsPIBoxObject.h"

class nsPresContext;
class nsListScrollSmoother;
nsIFrame* NS_NewListBoxBodyFrame(nsIPresShell* aPresShell,
                                 mozilla::ComputedStyle* aStyle);

class nsListBoxBodyFrame final : public nsBoxFrame,
                                 public nsIScrollbarMediator,
                                 public nsIReflowCallback
{
  nsListBoxBodyFrame(ComputedStyle* aStyle,
                     nsBoxLayout* aLayoutManager);
  virtual ~nsListBoxBodyFrame();

public:
  NS_DECL_QUERYFRAME
  NS_DECL_FRAMEARENA_HELPERS(nsListBoxBodyFrame)

  // non-virtual ListBoxObject
  int32_t GetNumberOfVisibleRows();
  int32_t GetIndexOfFirstVisibleRow();
  nsresult EnsureIndexIsVisible(int32_t aRowIndex);
  nsresult ScrollToIndex(int32_t aRowIndex);
  nsresult ScrollByLines(int32_t aNumLines);
  nsresult GetItemAtIndex(int32_t aIndex, nsIDOMElement **aResult);
  nsresult GetIndexOfItem(nsIDOMElement *aItem, int32_t *aResult);

  friend nsIFrame* NS_NewListBoxBodyFrame(nsIPresShell* aPresShell,
                                          ComputedStyle* aStyle);

  // nsIFrame
  virtual void Init(nsIContent*       aContent,
                    nsContainerFrame* aParent,
                    nsIFrame*         aPrevInFlow) override;
  virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;

  virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, int32_t aModType) override;

  // nsIScrollbarMediator
  virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection,
                            nsIScrollbarMediator::ScrollSnapMode snapMode
                              = nsIScrollbarMediator::DISABLE_SNAP) override;
  virtual void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection,
                             nsIScrollbarMediator::ScrollSnapMode snapMode
                               = nsIScrollbarMediator::DISABLE_SNAP) override;
  virtual void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection,
                            nsIScrollbarMediator::ScrollSnapMode snapMode
                              = nsIScrollbarMediator::DISABLE_SNAP) override;
  virtual void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) override;
  virtual void ThumbMoved(nsScrollbarFrame* aScrollbar,
                          int32_t aOldPos,
                          int32_t aNewPos) override;
  virtual void ScrollbarReleased(nsScrollbarFrame* aScrollbar) override {}
  virtual void VisibilityChanged(bool aVisible) override;
  virtual nsIFrame* GetScrollbarBox(bool aVertical) override;
  virtual void ScrollbarActivityStarted() const override {}
  virtual void ScrollbarActivityStopped() const override {}
  virtual bool IsScrollbarOnRight() const override {
    return (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR);
  }
  virtual bool ShouldSuppressScrollbarRepaints() const override {
    return false;
  }


  // nsIReflowCallback
  virtual bool ReflowFinished() override;
  virtual void ReflowCallbackCanceled() override;

  NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
  virtual void MarkIntrinsicISizesDirty() override;

  virtual nsSize GetXULMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) override;
  virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;

  // size calculation
  int32_t GetRowCount();
  int32_t GetRowHeightAppUnits() { return mRowHeight; }
  int32_t GetRowHeightPixels() const;
  int32_t GetFixedRowSize();
  void SetRowHeight(nscoord aRowHeight);
  nscoord GetYPosition();
  nscoord GetAvailableHeight();
  nscoord ComputeIntrinsicISize(nsBoxLayoutState& aBoxLayoutState);

  // scrolling
  nsresult InternalPositionChangedCallback();
  nsresult InternalPositionChanged(bool aUp, int32_t aDelta);
  // Process pending position changed events, then do the position change.
  // This can wipe out the frametree.
  nsresult DoInternalPositionChangedSync(bool aUp, int32_t aDelta);
  // Actually do the internal position change.  This can wipe out the frametree
  nsresult DoInternalPositionChanged(bool aUp, int32_t aDelta);
  nsListScrollSmoother* GetSmoother();
  void VerticalScroll(int32_t aDelta);
  // Update the scroll index given a position, in CSS pixels
  void UpdateIndex(int32_t aNewPos);

  // frames
  nsIFrame* GetFirstFrame();
  nsIFrame* GetLastFrame();

  // lazy row creation and destruction
  void CreateRows();
  void DestroyRows(int32_t& aRowsToLose);
  void ReverseDestroyRows(int32_t& aRowsToLose);
  nsIFrame* GetFirstItemBox(int32_t aOffset, bool* aCreated);
  nsIFrame* GetNextItemBox(nsIFrame* aBox, int32_t aOffset, bool* aCreated);
  bool ContinueReflow(nscoord height);
  NS_IMETHOD ListBoxAppendFrames(nsFrameList& aFrameList);
  NS_IMETHOD ListBoxInsertFrames(nsIFrame* aPrevFrame, nsFrameList& aFrameList);
  void OnContentInserted(nsIContent* aContent);
  void OnContentRemoved(nsPresContext* aPresContext,  nsIContent* aContainer,
                        nsIFrame* aChildFrame, nsIContent* aOldNextSibling);

  void GetListItemContentAt(int32_t aIndex, nsIContent** aContent);
  void GetListItemNextSibling(nsIContent* aListItem, nsIContent** aContent, int32_t& aSiblingIndex);

  void PostReflowCallback();

  bool SetBoxObject(nsPIBoxObject* aBoxObject)
  {
    NS_ENSURE_TRUE(!mBoxObject, false);
    mBoxObject = aBoxObject;
    return true;
  }

  virtual bool SupportsOrdinalsInChildren() override;

  virtual bool ComputesOwnOverflowArea() override { return true; }

protected:
  class nsPositionChangedEvent;
  friend class nsPositionChangedEvent;

  class nsPositionChangedEvent : public mozilla::Runnable
  {
  public:
    nsPositionChangedEvent(nsListBoxBodyFrame* aFrame, bool aUp, int32_t aDelta)
      : mozilla::Runnable("nsListBoxBodyFrame::nsPositionChangedEvent")
      , mFrame(aFrame)
      , mUp(aUp)
      , mDelta(aDelta)
    {}

    NS_IMETHOD Run() override
    {
      if (!mFrame) {
        return NS_OK;
      }

      mFrame->mPendingPositionChangeEvents.RemoveElement(this);

      return mFrame->DoInternalPositionChanged(mUp, mDelta);
    }

    void Revoke() {
      mFrame = nullptr;
    }

    nsListBoxBodyFrame* mFrame;
    bool mUp;
    int32_t mDelta;
  };

  void ComputeTotalRowCount();
  int32_t ToRowIndex(nscoord aPos) const;
  void RemoveChildFrame(nsBoxLayoutState &aState, nsIFrame *aChild);

  nsTArray< RefPtr<nsPositionChangedEvent> > mPendingPositionChangeEvents;
  nsCOMPtr<nsPIBoxObject> mBoxObject;

  // frame markers
  WeakFrame mTopFrame;
  nsIFrame* mBottomFrame;
  nsIFrame* mLinkupFrame;

  nsListScrollSmoother* mScrollSmoother;

  int32_t mRowsToPrepend;

  // row height
  int32_t mRowCount;
  nscoord mRowHeight;
  nscoord mAvailableHeight;
  nscoord mStringWidth;

  // scrolling
  int32_t mCurrentIndex; // Row-based
  int32_t mOldIndex;
  int32_t mYPosition;
  int32_t mTimePerRow;

  // row height
  bool mRowHeightWasSet;
  // scrolling
  bool mScrolling;
  bool mAdjustScroll;

  bool mReflowCallbackPosted;
};

#endif // nsListBoxBodyFrame_h