layout/forms/nsListControlFrame.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifndef nsListControlFrame_h___
     6 #define nsListControlFrame_h___
     8 #ifdef DEBUG_evaughan
     9 //#define DEBUG_rods
    10 #endif
    12 #ifdef DEBUG_rods
    13 //#define DO_REFLOW_DEBUG
    14 //#define DO_REFLOW_COUNTER
    15 //#define DO_UNCONSTRAINED_CHECK
    16 //#define DO_PIXELS
    17 #endif
    19 #include "mozilla/Attributes.h"
    20 #include "nsGfxScrollFrame.h"
    21 #include "nsIFormControlFrame.h"
    22 #include "nsIListControlFrame.h"
    23 #include "nsISelectControlFrame.h"
    24 #include "nsAutoPtr.h"
    25 #include "nsSelectsAreaFrame.h"
    27 // X.h defines KeyPress
    28 #ifdef KeyPress
    29 #undef KeyPress
    30 #endif
    32 class nsIDOMHTMLSelectElement;
    33 class nsIDOMHTMLOptionsCollection;
    34 class nsIComboboxControlFrame;
    35 class nsPresContext;
    36 class nsListEventListener;
    38 namespace mozilla {
    39 namespace dom {
    40 class HTMLOptionElement;
    41 class HTMLOptionsCollection;
    42 } // namespace dom
    43 } // namespace mozilla
    45 /**
    46  * Frame-based listbox.
    47  */
    49 class nsListControlFrame : public nsHTMLScrollFrame,
    50                            public nsIFormControlFrame, 
    51                            public nsIListControlFrame,
    52                            public nsISelectControlFrame
    53 {
    54 public:
    55   friend nsIFrame* NS_NewListControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
    57   NS_DECL_QUERYFRAME
    58   NS_DECL_FRAMEARENA_HELPERS
    60     // nsIFrame
    61   virtual nsresult HandleEvent(nsPresContext* aPresContext,
    62                                mozilla::WidgetGUIEvent* aEvent,
    63                                nsEventStatus* aEventStatus) MOZ_OVERRIDE;
    65   virtual nsresult SetInitialChildList(ChildListID     aListID,
    66                                        nsFrameList&    aChildList) MOZ_OVERRIDE;
    68   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
    69   virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
    71   virtual nsresult Reflow(nsPresContext*           aCX,
    72                           nsHTMLReflowMetrics&     aDesiredSize,
    73                           const nsHTMLReflowState& aReflowState,
    74                           nsReflowStatus&          aStatus) MOZ_OVERRIDE;
    76   virtual void Init(nsIContent*      aContent,
    77                     nsIFrame*        aParent,
    78                     nsIFrame*        aPrevInFlow) MOZ_OVERRIDE;
    80   virtual nsresult DidReflow(nsPresContext*            aPresContext, 
    81                              const nsHTMLReflowState*  aReflowState, 
    82                              nsDidReflowStatus         aStatus) MOZ_OVERRIDE;
    83   virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
    85   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
    86                                 const nsRect&           aDirtyRect,
    87                                 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
    89   virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
    91   /**
    92    * Get the "type" of the frame
    93    *
    94    * @see nsGkAtoms::scrollFrame
    95    */
    96   virtual nsIAtom* GetType() const MOZ_OVERRIDE;
    98   virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
    99   {
   100     return nsHTMLScrollFrame::IsFrameOfType(aFlags &
   101       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   102   }
   104 #ifdef DEBUG_FRAME_DUMP
   105   virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
   106 #endif
   108     // nsIFormControlFrame
   109   virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE;
   110   virtual void SetFocus(bool aOn = true, bool aRepaint = false) MOZ_OVERRIDE;
   112   virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE;
   113   virtual bool ShouldPropagateComputedHeightToScrolledContent() const MOZ_OVERRIDE;
   115     // for accessibility purposes
   116 #ifdef ACCESSIBILITY
   117   virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
   118 #endif
   120     // nsIListControlFrame
   121   virtual void SetComboboxFrame(nsIFrame* aComboboxFrame) MOZ_OVERRIDE;
   122   virtual int32_t GetSelectedIndex() MOZ_OVERRIDE;
   123   virtual mozilla::dom::HTMLOptionElement* GetCurrentOption() MOZ_OVERRIDE;
   125   /**
   126    * Gets the text of the currently selected item.
   127    * If the there are zero items then an empty string is returned
   128    * If there is nothing selected, then the 0th item's text is returned.
   129    */
   130   virtual void GetOptionText(uint32_t aIndex, nsAString& aStr) MOZ_OVERRIDE;
   132   virtual void CaptureMouseEvents(bool aGrabMouseEvents) MOZ_OVERRIDE;
   133   virtual nscoord GetHeightOfARow() MOZ_OVERRIDE;
   134   virtual uint32_t GetNumberOfOptions() MOZ_OVERRIDE;
   135   virtual void AboutToDropDown() MOZ_OVERRIDE;
   137   /**
   138    * @note This method might destroy the frame, pres shell and other objects.
   139    */
   140   virtual void AboutToRollup() MOZ_OVERRIDE;
   142   /**
   143    * Dispatch a DOM onchange event synchroniously.
   144    * @note This method might destroy the frame, pres shell and other objects.
   145    */
   146   virtual void FireOnChange() MOZ_OVERRIDE;
   148   /**
   149    * Makes aIndex the selected option of a combobox list.
   150    * @note This method might destroy the frame, pres shell and other objects.
   151    */
   152   virtual void ComboboxFinish(int32_t aIndex) MOZ_OVERRIDE;
   153   virtual void OnContentReset() MOZ_OVERRIDE;
   155   // nsISelectControlFrame
   156   NS_IMETHOD AddOption(int32_t index) MOZ_OVERRIDE;
   157   NS_IMETHOD RemoveOption(int32_t index) MOZ_OVERRIDE;
   158   NS_IMETHOD DoneAddingChildren(bool aIsDone) MOZ_OVERRIDE;
   160   /**
   161    * Gets the content (an option) by index and then set it as
   162    * being selected or not selected.
   163    */
   164   NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) MOZ_OVERRIDE;
   165   NS_IMETHOD OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE;
   167   /**
   168    * Mouse event listeners.
   169    * @note These methods might destroy the frame, pres shell and other objects.
   170    */
   171   nsresult MouseDown(nsIDOMEvent* aMouseEvent);
   172   nsresult MouseUp(nsIDOMEvent* aMouseEvent);
   173   nsresult MouseMove(nsIDOMEvent* aMouseEvent);
   174   nsresult DragMove(nsIDOMEvent* aMouseEvent);
   175   nsresult KeyDown(nsIDOMEvent* aKeyEvent);
   176   nsresult KeyPress(nsIDOMEvent* aKeyEvent);
   178   /**
   179    * Returns the options collection for mContent, if any.
   180    */
   181   mozilla::dom::HTMLOptionsCollection* GetOptions() const;
   182   /**
   183    * Returns the HTMLOptionElement for a given index in mContent's collection.
   184    */
   185   mozilla::dom::HTMLOptionElement* GetOption(uint32_t aIndex) const;
   187   static void ComboboxFocusSet();
   189   // Helper
   190   bool IsFocused() { return this == mFocused; }
   192   /**
   193    * Function to paint the focus rect when our nsSelectsAreaFrame is painting.
   194    * @param aPt the offset of this frame, relative to the rendering reference
   195    * frame
   196    */
   197   void PaintFocus(nsRenderingContext& aRC, nsPoint aPt);
   198   /**
   199    * If this frame IsFocused(), invalidates an area that includes anything
   200    * that PaintFocus will or could have painted --- basically the whole
   201    * GetOptionsContainer, plus some extra stuff if there are no options. This
   202    * must be called every time mEndSelectionIndex changes.
   203    */
   204   void InvalidateFocus();
   206   /**
   207    * Function to calculate the height a row, for use with the "size" attribute.
   208    * Can't be const because GetNumberOfOptions() isn't const.
   209    */
   210   nscoord CalcHeightOfARow();
   212   /**
   213    * Function to ask whether we're currently in what might be the
   214    * first pass of a two-pass reflow.
   215    */
   216   bool MightNeedSecondPass() const {
   217     return mMightNeedSecondPass;
   218   }
   220   void SetSuppressScrollbarUpdate(bool aSuppress) {
   221     nsHTMLScrollFrame::SetSuppressScrollbarUpdate(aSuppress);
   222   }
   224   /**
   225    * Return whether the list is in dropdown mode.
   226    */
   227   bool IsInDropDownMode() const;
   229   /**
   230    * Return the number of displayed rows in the list.
   231    */
   232   uint32_t GetNumDisplayRows() const { return mNumDisplayRows; }
   234   /**
   235    * Return true if the drop-down list can display more rows.
   236    * (always false if not in drop-down mode)
   237    */
   238   bool GetDropdownCanGrow() const { return mDropdownCanGrow; }
   240   /**
   241    * Dropdowns need views
   242    */
   243   virtual bool NeedsView() MOZ_OVERRIDE { return IsInDropDownMode(); }
   245   /**
   246    * Frees statics owned by this class.
   247    */
   248   static void Shutdown();
   250 #ifdef ACCESSIBILITY
   251   /**
   252    * Post a custom DOM event for the change, so that accessibility can
   253    * fire a native focus event for accessibility 
   254    * (Some 3rd party products need to track our focus)
   255    */
   256   void FireMenuItemActiveEvent(); // Inform assistive tech what got focused
   257 #endif
   259 protected:
   260   /**
   261    * Updates the selected text in a combobox and then calls FireOnChange().
   262    * @note This method might destroy the frame, pres shell and other objects.
   263    * Returns false if calling it destroyed |this|.
   264    */
   265   bool       UpdateSelection();
   267   /**
   268    * Returns whether mContent supports multiple selection.
   269    */
   270   bool       GetMultiple() const {
   271     return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
   272   }
   275   /**
   276    * Toggles (show/hide) the combobox dropdown menu.
   277    * @note This method might destroy the frame, pres shell and other objects.
   278    */
   279   void       DropDownToggleKey(nsIDOMEvent* aKeyEvent);
   281   nsresult   IsOptionDisabled(int32_t anIndex, bool &aIsDisabled);
   282   /**
   283    * @note This method might destroy the frame, pres shell and other objects.
   284    */
   285   void ScrollToFrame(mozilla::dom::HTMLOptionElement& aOptElement);
   286   /**
   287    * @note This method might destroy the frame, pres shell and other objects.
   288    */
   289   void ScrollToIndex(int32_t anIndex);
   291   /**
   292    * When the user clicks on the comboboxframe to show the dropdown
   293    * listbox, they then have to move the mouse into the list. We don't
   294    * want to process those mouse events as selection events (i.e., to
   295    * scroll list items into view). So we ignore the events until
   296    * the mouse moves below our border-inner-edge, when
   297    * mItemSelectionStarted is set.
   298    *
   299    * @param aPoint relative to this frame
   300    */
   301   bool       IgnoreMouseEventForSelection(nsIDOMEvent* aEvent);
   303   /**
   304    * If the dropdown is showing and the mouse has moved below our
   305    * border-inner-edge, then set mItemSelectionStarted.
   306    */
   307   void       UpdateInListState(nsIDOMEvent* aEvent);
   308   void       AdjustIndexForDisabledOpt(int32_t aStartIndex, int32_t &anNewIndex,
   309                                        int32_t aNumOptions, int32_t aDoAdjustInc, int32_t aDoAdjustIncNext);
   311   /**
   312    * Resets the select back to it's original default values;
   313    * those values as determined by the original HTML
   314    */
   315   virtual void ResetList(bool aAllowScrolling);
   317   nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument, nsStyleContext* aContext);
   318   virtual ~nsListControlFrame();
   320   /**
   321    * Sets the mSelectedIndex and mOldSelectedIndex from figuring out what 
   322    * item was selected using content
   323    * @param aPoint the event point, in listcontrolframe coordinates
   324    * @return NS_OK if it successfully found the selection
   325    */
   326   nsresult GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent, int32_t& aCurIndex);
   328   bool     CheckIfAllFramesHere();
   329   bool     IsLeftButton(nsIDOMEvent* aMouseEvent);
   331   // guess at a row height based on our own style.
   332   nscoord  CalcFallbackRowHeight(float aFontSizeInflation);
   334   // CalcIntrinsicHeight computes our intrinsic height (taking the "size"
   335   // attribute into account).  This should only be called in non-dropdown mode.
   336   nscoord CalcIntrinsicHeight(nscoord aHeightOfARow, int32_t aNumberOfOptions);
   338   // Dropped down stuff
   339   void     SetComboboxItem(int32_t aIndex);
   341   /**
   342    * Method to reflow ourselves as a dropdown list.  This differs from
   343    * reflow as a listbox because the criteria for needing a second
   344    * pass are different.  This will be called from Reflow() as needed.
   345    */
   346   nsresult ReflowAsDropdown(nsPresContext*           aPresContext,
   347                             nsHTMLReflowMetrics&     aDesiredSize,
   348                             const nsHTMLReflowState& aReflowState,
   349                             nsReflowStatus&          aStatus);
   351   // Selection
   352   bool     SetOptionsSelectedFromFrame(int32_t aStartIndex,
   353                                        int32_t aEndIndex,
   354                                        bool aValue,
   355                                        bool aClearAll);
   356   bool     ToggleOptionSelectedFromFrame(int32_t aIndex);
   357   /**
   358    * @note This method might destroy the frame, pres shell and other objects.
   359    */
   360   bool     SingleSelection(int32_t aClickedIndex, bool aDoToggle);
   361   bool     ExtendedSelection(int32_t aStartIndex, int32_t aEndIndex,
   362                              bool aClearAll);
   363   /**
   364    * @note This method might destroy the frame, pres shell and other objects.
   365    */
   366   bool     PerformSelection(int32_t aClickedIndex, bool aIsShift,
   367                             bool aIsControl);
   368   /**
   369    * @note This method might destroy the frame, pres shell and other objects.
   370    */
   371   bool     HandleListSelection(nsIDOMEvent * aDOMEvent, int32_t selectedIndex);
   372   void     InitSelectionRange(int32_t aClickedIndex);
   373   void     PostHandleKeyEvent(int32_t aNewIndex, uint32_t aCharCode,
   374                               bool aIsShift, bool aIsControlOrMeta);
   376 public:
   377   nsSelectsAreaFrame* GetOptionsContainer() const {
   378     return static_cast<nsSelectsAreaFrame*>(GetScrolledFrame());
   379   }
   381 protected:
   382   nscoord HeightOfARow() {
   383     return GetOptionsContainer()->HeightOfARow();
   384   }
   386   /**
   387    * @return how many displayable options/optgroups this frame has.
   388    */
   389   uint32_t GetNumberOfRows();
   391   // Data Members
   392   int32_t      mStartSelectionIndex;
   393   int32_t      mEndSelectionIndex;
   395   nsIComboboxControlFrame *mComboboxFrame;
   396   uint32_t     mNumDisplayRows;
   397   bool mChangesSinceDragStart:1;
   398   bool mButtonDown:1;
   399   // Has the user selected a visible item since we showed the
   400   // dropdown?
   401   bool mItemSelectionStarted:1;
   403   bool mIsAllContentHere:1;
   404   bool mIsAllFramesHere:1;
   405   bool mHasBeenInitialized:1;
   406   bool mNeedToReset:1;
   407   bool mPostChildrenLoadedReset:1;
   409   //bool value for multiple discontiguous selection
   410   bool mControlSelectMode:1;
   412   // True if we're in the middle of a reflow and might need a second
   413   // pass.  This only happens for auto heights.
   414   bool mMightNeedSecondPass:1;
   416   /**
   417    * Set to aPresContext->HasPendingInterrupt() at the start of Reflow.
   418    * Set to false at the end of DidReflow.
   419    */
   420   bool mHasPendingInterruptAtStartOfReflow:1;
   422   // True if the drop-down can show more rows.  Always false if this list
   423   // is not in drop-down mode.
   424   bool mDropdownCanGrow:1;
   426   // The last computed height we reflowed at if we're a combobox dropdown.
   427   // XXXbz should we be using a subclass here?  Or just not worry
   428   // about the extra member on listboxes?
   429   nscoord mLastDropdownComputedHeight;
   431   // At the time of our last dropdown, the backstop color to draw in case we
   432   // are translucent.
   433   nscolor mLastDropdownBackstopColor;
   435   nsRefPtr<nsListEventListener> mEventListener;
   437   static nsListControlFrame * mFocused;
   438   static nsString * sIncrementalString;
   440 #ifdef DO_REFLOW_COUNTER
   441   int32_t mReflowId;
   442 #endif
   444 private:
   445   // for incremental typing navigation
   446   static nsAString& GetIncrementalString ();
   447   static DOMTimeStamp gLastKeyTime;
   449   class MOZ_STACK_CLASS AutoIncrementalSearchResetter
   450   {
   451   public:
   452     AutoIncrementalSearchResetter() :
   453       mCancelled(false)
   454     {
   455     }
   456     ~AutoIncrementalSearchResetter()
   457     {
   458       if (!mCancelled) {
   459         nsListControlFrame::GetIncrementalString().Truncate();
   460       }
   461     }
   462     void Cancel()
   463     {
   464       mCancelled = true;
   465     }
   466   private:
   467     bool mCancelled;
   468   };
   469 };
   471 #endif /* nsListControlFrame_h___ */

mercurial