tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsListControlFrame.h (9632B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 #ifndef nsListControlFrame_h___
      7 #define nsListControlFrame_h___
      8 
      9 #include "mozilla/Attributes.h"
     10 #include "mozilla/ScrollContainerFrame.h"
     11 #include "mozilla/StaticPtr.h"
     12 #include "nsISelectControlFrame.h"
     13 
     14 class nsComboboxControlFrame;
     15 class nsPresContext;
     16 
     17 namespace mozilla {
     18 class PresShell;
     19 class HTMLSelectEventListener;
     20 
     21 namespace dom {
     22 class Event;
     23 class HTMLOptionElement;
     24 class HTMLSelectElement;
     25 class HTMLOptionsCollection;
     26 }  // namespace dom
     27 }  // namespace mozilla
     28 
     29 /**
     30 * Frame-based listbox.
     31 */
     32 
     33 class nsListControlFrame final : public mozilla::ScrollContainerFrame,
     34                                 public nsISelectControlFrame {
     35 public:
     36  using HTMLOptionElement = mozilla::dom::HTMLOptionElement;
     37 
     38  friend nsListControlFrame* NS_NewListControlFrame(
     39      mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
     40 
     41  NS_DECL_QUERYFRAME
     42  NS_DECL_FRAMEARENA_HELPERS(nsListControlFrame)
     43 
     44  Maybe<nscoord> GetNaturalBaselineBOffset(
     45      mozilla::WritingMode aWM, BaselineSharingGroup aBaselineGroup,
     46      BaselineExportContext) const override;
     47 
     48  // nsIFrame
     49  nsresult HandleEvent(nsPresContext* aPresContext,
     50                       mozilla::WidgetGUIEvent* aEvent,
     51                       nsEventStatus* aEventStatus) final;
     52 
     53  void SetInitialChildList(ChildListID aListID, nsFrameList&& aChildList) final;
     54 
     55  nscoord IntrinsicISize(const mozilla::IntrinsicSizeInput& aInput,
     56                         mozilla::IntrinsicISizeType aType) final;
     57 
     58  void Reflow(nsPresContext* aCX, ReflowOutput& aDesiredSize,
     59              const ReflowInput& aReflowInput, nsReflowStatus& aStatus) final;
     60 
     61  void Init(nsIContent* aContent, nsContainerFrame* aParent,
     62            nsIFrame* aPrevInFlow) final;
     63 
     64  bool ReflowFinished() final;
     65  void Destroy(DestroyContext&) override;
     66 
     67  int32_t GetEndSelectionIndex() const { return mEndSelectionIndex; }
     68 
     69  mozilla::dom::HTMLOptionElement* GetCurrentOption() const;
     70 
     71 #ifdef DEBUG_FRAME_DUMP
     72  nsresult GetFrameName(nsAString& aResult) const final;
     73 #endif
     74 
     75  void ElementStateChanged(mozilla::dom::ElementState aStates) final;
     76  bool ShouldPropagateComputedBSizeToScrolledContent() const final;
     77 
     78  // for accessibility purposes
     79 #ifdef ACCESSIBILITY
     80  mozilla::a11y::AccType AccessibleType() final;
     81 #endif
     82 
     83  int32_t GetSelectedIndex();
     84 
     85  /**
     86   * Gets the text of the currently selected item.
     87   * If the there are zero items then an empty string is returned
     88   * If there is nothing selected, then the 0th item's text is returned.
     89   */
     90  void GetOptionText(uint32_t aIndex, nsAString& aStr);
     91 
     92  void CaptureMouseEvents(bool aGrabMouseEvents);
     93  nscoord GetBSizeOfARow();
     94  uint32_t GetNumberOfOptions();
     95 
     96  MOZ_CAN_RUN_SCRIPT_BOUNDARY void OnContentReset();
     97 
     98  // nsISelectControlFrame
     99  NS_IMETHOD AddOption(int32_t index) final;
    100  NS_IMETHOD RemoveOption(int32_t index) final;
    101  MOZ_CAN_RUN_SCRIPT_BOUNDARY
    102  NS_IMETHOD DoneAddingChildren(bool aIsDone) final;
    103 
    104  /**
    105   * Gets the content (an option) by index and then set it as
    106   * being selected or not selected.
    107   */
    108  MOZ_CAN_RUN_SCRIPT_BOUNDARY
    109  NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) final;
    110  MOZ_CAN_RUN_SCRIPT_BOUNDARY
    111  NS_IMETHOD_(void)
    112  OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) final;
    113 
    114  /**
    115   * Mouse event listeners.
    116   * @note These methods might destroy the frame, pres shell and other objects.
    117   */
    118  MOZ_CAN_RUN_SCRIPT
    119  nsresult HandleLeftButtonMouseDown(mozilla::dom::Event* aMouseEvent);
    120  MOZ_CAN_RUN_SCRIPT
    121  nsresult HandleLeftButtonMouseUp(mozilla::dom::Event* aMouseEvent);
    122  MOZ_CAN_RUN_SCRIPT
    123  nsresult DragMove(mozilla::dom::Event* aMouseEvent);
    124  MOZ_CAN_RUN_SCRIPT
    125 
    126  MOZ_CAN_RUN_SCRIPT
    127  bool PerformSelection(int32_t aClickedIndex, bool aIsShift, bool aIsControl);
    128  MOZ_CAN_RUN_SCRIPT
    129  void UpdateSelectionAfterKeyEvent(int32_t aNewIndex, uint32_t aCharCode,
    130                                    bool aIsShift, bool aIsControlOrMeta,
    131                                    bool aIsControlSelectMode);
    132 
    133  /**
    134   * Returns the options collection for mContent, if any.
    135   */
    136  mozilla::dom::HTMLOptionsCollection* GetOptions() const;
    137  /**
    138   * Returns the HTMLOptionElement for a given index in mContent's collection.
    139   */
    140  HTMLOptionElement* GetOption(uint32_t aIndex) const;
    141 
    142  // Helper
    143  bool IsFocused() const;
    144 
    145  /**
    146   * Function to paint the focus rect when our nsSelectsAreaFrame is painting.
    147   * @param aPt the offset of this frame, relative to the rendering reference
    148   * frame
    149   */
    150  void PaintFocus(mozilla::gfx::DrawTarget* aDrawTarget, nsPoint aPt);
    151 
    152  /**
    153   * If this frame IsFocused(), invalidates an area that includes anything
    154   * that PaintFocus will or could have painted --- basically the whole
    155   * GetOptionsContainer, plus some extra stuff if there are no options. This
    156   * must be called every time mEndSelectionIndex changes.
    157   */
    158  void InvalidateFocus();
    159 
    160  /**
    161   * Function to calculate the block size of a row, for use with the
    162   * "size" attribute.
    163   * Can't be const because GetNumberOfOptions() isn't const.
    164   */
    165  nscoord CalcBSizeOfARow();
    166 
    167  /**
    168   * Function to ask whether we're currently in what might be the
    169   * first pass of a two-pass reflow.
    170   */
    171  bool MightNeedSecondPass() const { return mMightNeedSecondPass; }
    172 
    173  /**
    174   * Return the number of displayed rows in the list.
    175   */
    176  uint32_t GetNumDisplayRows() const { return mNumDisplayRows; }
    177 
    178 #ifdef ACCESSIBILITY
    179  /**
    180   * Post a custom DOM event for the change, so that accessibility can
    181   * fire a native focus event for accessibility
    182   * (Some 3rd party products need to track our focus)
    183   */
    184  void FireMenuItemActiveEvent(
    185      nsIContent* aPreviousOption);  // Inform assistive tech what got focused
    186 #endif
    187 
    188 protected:
    189  /**
    190   * Updates the selected text in a combobox and then calls FireOnChange().
    191   * @note This method might destroy the frame, pres shell and other objects.
    192   * Returns false if calling it destroyed |this|.
    193   */
    194  MOZ_CAN_RUN_SCRIPT
    195  bool UpdateSelection();
    196 
    197  /**
    198   * Returns whether mContent supports multiple selection.
    199   */
    200  bool GetMultiple() const;
    201 
    202  mozilla::dom::HTMLSelectElement& Select() const;
    203 
    204  /**
    205   * @return true if the <option> at aIndex is selectable by the user.
    206   */
    207  bool IsOptionInteractivelySelectable(int32_t aIndex) const;
    208  /**
    209   * @return true if aOption in aSelect is selectable by the user.
    210   */
    211  static bool IsOptionInteractivelySelectable(
    212      mozilla::dom::HTMLSelectElement* aSelect,
    213      mozilla::dom::HTMLOptionElement* aOption);
    214 
    215  MOZ_CAN_RUN_SCRIPT void ScrollToFrame(HTMLOptionElement& aOptElement);
    216 
    217  MOZ_CAN_RUN_SCRIPT void ScrollToIndex(int32_t anIndex);
    218 
    219 public:
    220  /**
    221   * Resets the select back to it's original default values;
    222   * those values as determined by the original HTML
    223   */
    224  MOZ_CAN_RUN_SCRIPT void ResetList(bool aAllowScrolling);
    225 
    226 protected:
    227  explicit nsListControlFrame(ComputedStyle* aStyle,
    228                              nsPresContext* aPresContext);
    229  virtual ~nsListControlFrame();
    230 
    231  /**
    232   * Sets the mSelectedIndex and mOldSelectedIndex from figuring out what
    233   * item was selected using content
    234   * @param aPoint the event point, in listcontrolframe coordinates
    235   * @return NS_OK if it successfully found the selection
    236   */
    237  nsresult GetIndexFromDOMEvent(mozilla::dom::Event* aMouseEvent,
    238                                int32_t& aCurIndex);
    239 
    240  bool CheckIfAllFramesHere();
    241 
    242  // guess at a row block size based on our own style.
    243  nscoord CalcFallbackRowBSize(float aFontSizeInflation);
    244 
    245  // CalcIntrinsicBSize computes our intrinsic block size (taking the
    246  // "size" attribute into account).  This should only be called in
    247  // non-dropdown mode.
    248  nscoord CalcIntrinsicBSize(nscoord aBSizeOfARow, int32_t aNumberOfOptions);
    249 
    250  // Dropped down stuff
    251  void SetComboboxItem(int32_t aIndex);
    252 
    253  // Selection
    254  bool SetOptionsSelectedFromFrame(int32_t aStartIndex, int32_t aEndIndex,
    255                                   bool aValue, bool aClearAll);
    256  bool ToggleOptionSelectedFromFrame(int32_t aIndex);
    257 
    258  MOZ_CAN_RUN_SCRIPT
    259  bool SingleSelection(int32_t aClickedIndex, bool aDoToggle);
    260  bool ExtendedSelection(int32_t aStartIndex, int32_t aEndIndex,
    261                         bool aClearAll);
    262  MOZ_CAN_RUN_SCRIPT
    263  bool HandleListSelection(mozilla::dom::Event* aDOMEvent,
    264                           int32_t selectedIndex);
    265  void InitSelectionRange(int32_t aClickedIndex);
    266 
    267 public:
    268  static constexpr int32_t kNothingSelected = -1;
    269 
    270 protected:
    271  nscoord BSizeOfARow() const { return mBSizeOfARow; }
    272 
    273  /**
    274   * @return how many displayable options/optgroups this frame has.
    275   */
    276  uint32_t GetNumberOfRows();
    277 
    278  // Data Members
    279  int32_t mStartSelectionIndex = 0;
    280  int32_t mEndSelectionIndex = 0;
    281 
    282  uint32_t mNumDisplayRows = 0;
    283  nscoord mBSizeOfARow = -1;
    284  bool mChangesSinceDragStart : 1;
    285 
    286  bool mIsAllContentHere : 1;
    287  bool mIsAllFramesHere : 1;
    288  bool mHasBeenInitialized : 1;
    289  bool mNeedToReset : 1;
    290  bool mPostChildrenLoadedReset : 1;
    291 
    292  // True if we're in the middle of a reflow and might need a second
    293  // pass.  This only happens for auto heights.
    294  bool mMightNeedSecondPass : 1;
    295 
    296  // True if our reflow got interrupted.
    297  bool mReflowWasInterrupted : 1;
    298 
    299  RefPtr<mozilla::HTMLSelectEventListener> mEventListener;
    300 };
    301 
    302 #endif /* nsListControlFrame_h___ */