LCOV - code coverage report
Current view: top level - layout/xul - nsMenuPopupFrame.h (source / functions) Hit Total Coverage
Test: output.info Lines: 11 72 15.3 %
Date: 2017-07-14 16:53:18 Functions: 7 41 17.1 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
       6             : //
       7             : // nsMenuPopupFrame
       8             : //
       9             : 
      10             : #ifndef nsMenuPopupFrame_h__
      11             : #define nsMenuPopupFrame_h__
      12             : 
      13             : #include "mozilla/Attributes.h"
      14             : #include "mozilla/gfx/Types.h"
      15             : #include "nsIAtom.h"
      16             : #include "nsGkAtoms.h"
      17             : #include "nsCOMPtr.h"
      18             : #include "nsMenuFrame.h"
      19             : 
      20             : #include "nsBoxFrame.h"
      21             : #include "nsMenuParent.h"
      22             : 
      23             : #include "nsITimer.h"
      24             : 
      25             : #include "Units.h"
      26             : 
      27             : class nsIWidget;
      28             : 
      29             : // XUL popups can be in several different states. When opening a popup, the
      30             : // state changes as follows:
      31             : //   ePopupClosed - initial state
      32             : //   ePopupShowing - during the period when the popupshowing event fires
      33             : //   ePopupOpening - between the popupshowing event and being visible. Creation
      34             : //                   of the child frames, layout and reflow occurs in this
      35             : //                   state. The popup is stored in the popup manager's list of
      36             : //                   open popups during this state.
      37             : //   ePopupVisible - layout is done and the popup's view and widget are made
      38             : //                   visible. The popup is visible on screen but may be
      39             : //                   transitioning. The popupshown event has not yet fired.
      40             : //   ePopupShown - the popup has been shown and is fully ready. This state is
      41             : //                 assigned just before the popupshown event fires.
      42             : // When closing a popup:
      43             : //   ePopupHidden - during the period when the popuphiding event fires and
      44             : //                  the popup is removed.
      45             : //   ePopupClosed - the popup's widget is made invisible.
      46             : enum nsPopupState {
      47             :   // state when a popup is not open
      48             :   ePopupClosed,
      49             :   // state from when a popup is requested to be shown to after the
      50             :   // popupshowing event has been fired.
      51             :   ePopupShowing,
      52             :   // state while a popup is waiting to be laid out and positioned
      53             :   ePopupPositioning,
      54             :   // state while a popup is open but the widget is not yet visible
      55             :   ePopupOpening,
      56             :   // state while a popup is visible and waiting for the popupshown event
      57             :   ePopupVisible,
      58             :   // state while a popup is open and visible on screen
      59             :   ePopupShown,
      60             :   // state from when a popup is requested to be hidden to when it is closed.
      61             :   ePopupHiding,
      62             :   // state which indicates that the popup was hidden without firing the
      63             :   // popuphiding or popuphidden events. It is used when executing a menu
      64             :   // command because the menu needs to be hidden before the command event
      65             :   // fires, yet the popuphiding and popuphidden events are fired after. This
      66             :   // state can also occur when the popup is removed because the document is
      67             :   // unloaded.
      68             :   ePopupInvisible
      69             : };
      70             : 
      71             : enum ConsumeOutsideClicksResult {
      72             :   ConsumeOutsideClicks_ParentOnly = 0, // Only consume clicks on the parent anchor
      73             :   ConsumeOutsideClicks_True = 1, // Always consume clicks
      74             :   ConsumeOutsideClicks_Never = 2 // Never consume clicks
      75             : };
      76             : 
      77             : // How a popup may be flipped. Flipping to the outside edge is like how
      78             : // a submenu would work. The entire popup is flipped to the opposite side
      79             : // of the anchor.
      80             : enum FlipStyle {
      81             :   FlipStyle_None = 0,
      82             :   FlipStyle_Outside = 1,
      83             :   FlipStyle_Inside = 2
      84             : };
      85             : 
      86             : // Values for the flip attribute
      87             : enum FlipType {
      88             :   FlipType_Default = 0,
      89             :   FlipType_None = 1,    // don't try to flip or translate to stay onscreen
      90             :   FlipType_Both = 2,    // flip in both directions
      91             :   FlipType_Slide = 3    // allow the arrow to "slide" instead of resizing
      92             : };
      93             : 
      94             : enum MenuPopupAnchorType {
      95             :   MenuPopupAnchorType_Node = 0, // anchored to a node
      96             :   MenuPopupAnchorType_Point = 1, // unanchored and positioned at a screen point
      97             :   MenuPopupAnchorType_Rect = 2, // anchored at a screen rectangle
      98             : };
      99             : 
     100             : // values are selected so that the direction can be flipped just by
     101             : // changing the sign
     102             : #define POPUPALIGNMENT_NONE 0
     103             : #define POPUPALIGNMENT_TOPLEFT 1
     104             : #define POPUPALIGNMENT_TOPRIGHT -1
     105             : #define POPUPALIGNMENT_BOTTOMLEFT 2
     106             : #define POPUPALIGNMENT_BOTTOMRIGHT -2
     107             : 
     108             : #define POPUPALIGNMENT_LEFTCENTER 16
     109             : #define POPUPALIGNMENT_RIGHTCENTER -16
     110             : #define POPUPALIGNMENT_TOPCENTER 17
     111             : #define POPUPALIGNMENT_BOTTOMCENTER 18
     112             : 
     113             : // The constants here are selected so that horizontally and vertically flipping
     114             : // can be easily handled using the two flip macros below.
     115             : #define POPUPPOSITION_UNKNOWN -1
     116             : #define POPUPPOSITION_BEFORESTART 0
     117             : #define POPUPPOSITION_BEFOREEND 1
     118             : #define POPUPPOSITION_AFTERSTART 2
     119             : #define POPUPPOSITION_AFTEREND 3
     120             : #define POPUPPOSITION_STARTBEFORE 4
     121             : #define POPUPPOSITION_ENDBEFORE 5
     122             : #define POPUPPOSITION_STARTAFTER 6
     123             : #define POPUPPOSITION_ENDAFTER 7
     124             : #define POPUPPOSITION_OVERLAP 8
     125             : #define POPUPPOSITION_AFTERPOINTER 9
     126             : #define POPUPPOSITION_SELECTION 10
     127             : 
     128             : #define POPUPPOSITION_HFLIP(v) (v ^ 1)
     129             : #define POPUPPOSITION_VFLIP(v) (v ^ 2)
     130             : 
     131             : nsIFrame* NS_NewMenuPopupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     132             : 
     133             : class nsView;
     134             : class nsMenuPopupFrame;
     135             : 
     136             : // this class is used for dispatching popupshown events asynchronously.
     137             : class nsXULPopupShownEvent : public mozilla::Runnable,
     138             :                              public nsIDOMEventListener
     139             : {
     140             : public:
     141           0 :   nsXULPopupShownEvent(nsIContent* aPopup, nsPresContext* aPresContext)
     142           0 :     : mozilla::Runnable("nsXULPopupShownEvent")
     143             :     , mPopup(aPopup)
     144           0 :     , mPresContext(aPresContext)
     145             :   {
     146           0 :   }
     147             : 
     148             :   NS_DECL_ISUPPORTS_INHERITED
     149             :   NS_DECL_NSIRUNNABLE
     150             :   NS_DECL_NSIDOMEVENTLISTENER
     151             : 
     152             :   void CancelListener();
     153             : 
     154             : protected:
     155           0 :   virtual ~nsXULPopupShownEvent() { }
     156             : 
     157             : private:
     158             :   nsCOMPtr<nsIContent> mPopup;
     159             :   RefPtr<nsPresContext> mPresContext;
     160             : };
     161             : 
     162           7 : class nsMenuPopupFrame final : public nsBoxFrame, public nsMenuParent,
     163             :                                public nsIReflowCallback
     164             : {
     165             : public:
     166             :   NS_DECL_QUERYFRAME
     167         154 :   NS_DECL_FRAMEARENA_HELPERS(nsMenuPopupFrame)
     168             : 
     169             :   explicit nsMenuPopupFrame(nsStyleContext* aContext);
     170             : 
     171             :   // nsMenuParent interface
     172             :   virtual nsMenuFrame* GetCurrentMenuItem() override;
     173             :   NS_IMETHOD SetCurrentMenuItem(nsMenuFrame* aMenuItem) override;
     174             :   virtual void CurrentMenuIsBeingDestroyed() override;
     175             :   NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem,
     176             :                             bool aSelectFirstItem,
     177             :                             bool aFromKey) override;
     178             : 
     179             :   // as popups are opened asynchronously, the popup pending state is used to
     180             :   // prevent multiple requests from attempting to open the same popup twice
     181           3 :   nsPopupState PopupState() { return mPopupState; }
     182           0 :   void SetPopupState(nsPopupState aPopupState) { mPopupState = aPopupState; }
     183             : 
     184           0 :   NS_IMETHOD SetActive(bool aActiveFlag) override { return NS_OK; } // We don't care.
     185           0 :   virtual bool IsActive() override { return false; }
     186           0 :   virtual bool IsMenuBar() override { return false; }
     187             : 
     188             :   /*
     189             :    * When this popup is open, should clicks outside of it be consumed?
     190             :    * Return true if the popup should rollup on an outside click,
     191             :    * but consume that click so it can't be used for anything else.
     192             :    * Return false to allow clicks outside the popup to activate content
     193             :    * even when the popup is open.
     194             :    * ---------------------------------------------------------------------
     195             :    *
     196             :    * Should clicks outside of a popup be eaten?
     197             :    *
     198             :    *       Menus     Autocomplete     Comboboxes
     199             :    * Mac     Eat           No              Eat
     200             :    * Win     No            No              Eat
     201             :    * Unix    Eat           No              Eat
     202             :    *
     203             :    */
     204             :   ConsumeOutsideClicksResult ConsumeOutsideClicks();
     205             : 
     206           0 :   virtual bool IsContextMenu() override { return mIsContextMenu; }
     207             : 
     208           0 :   virtual bool MenuClosed() override { return true; }
     209             : 
     210             :   virtual void LockMenuUntilClosed(bool aLock) override;
     211           0 :   virtual bool IsMenuLocked() override { return mIsMenuLocked; }
     212             : 
     213             :   nsIWidget* GetWidget();
     214             : 
     215             :   // The dismissal listener gets created and attached to the window.
     216             :   void AttachedDismissalListener();
     217             : 
     218             :   // Overridden methods
     219             :   virtual void Init(nsIContent*       aContent,
     220             :                     nsContainerFrame* aParent,
     221             :                     nsIFrame*         aPrevInFlow) override;
     222             : 
     223             :   virtual nsresult AttributeChanged(int32_t aNameSpaceID,
     224             :                                     nsIAtom* aAttribute,
     225             :                                     int32_t aModType) override;
     226             : 
     227             :   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
     228             : 
     229             :   bool HasRemoteContent() const;
     230             : 
     231             :   // returns true if the popup is a panel with the noautohide attribute set to
     232             :   // true. These panels do not roll up automatically.
     233             :   bool IsNoAutoHide() const;
     234             : 
     235           0 :   nsPopupLevel PopupLevel() const
     236             :   {
     237           0 :     return PopupLevel(IsNoAutoHide());
     238             :   }
     239             : 
     240             :   // Ensure that a widget has already been created for this view, and create
     241             :   // one if it hasn't. If aRecreate is true, destroys any existing widget and
     242             :   // creates a new one, regardless of whether one has already been created.
     243             :   void EnsureWidget(bool aRecreate = false);
     244             : 
     245             :   nsresult CreateWidgetForView(nsView* aView);
     246             :   uint8_t GetShadowStyle();
     247             : 
     248             :   virtual void SetInitialChildList(ChildListID  aListID,
     249             :                                    nsFrameList& aChildList) override;
     250             : 
     251             :   virtual bool IsLeafDynamic() const override;
     252             : 
     253             :   virtual void UpdateWidgetProperties() override;
     254             : 
     255             :   // layout, position and display the popup as needed
     256             :   void LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
     257             :                    nsIFrame* aAnchor, bool aSizedToPopup);
     258             : 
     259             :   nsView* GetRootViewForPopup(nsIFrame* aStartFrame);
     260             : 
     261             :   // Set the position of the popup either relative to the anchor aAnchorFrame
     262             :   // (or the frame for mAnchorContent if aAnchorFrame is null), anchored at a
     263             :   // rectangle, or at a specific point if a screen position is set. The popup
     264             :   // will be adjusted so that it is on screen. If aIsMove is true, then the
     265             :   // popup is being moved, and should not be flipped. If aNotify is true, then
     266             :   // a popuppositioned event is sent.
     267             :   nsresult SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove,
     268             :                             bool aSizedToPopup, bool aNotify);
     269             : 
     270           0 :   bool HasGeneratedChildren() { return mGeneratedChildren; }
     271           0 :   void SetGeneratedChildren() { mGeneratedChildren = true; }
     272             : 
     273             :   // called when the Enter key is pressed while the popup is open. This will
     274             :   // just pass the call down to the current menu, if any. If a current menu
     275             :   // should be opened as a result, this method should return the frame for
     276             :   // that menu, or null if no menu should be opened. Also, calling Enter will
     277             :   // reset the current incremental search string, calculated in
     278             :   // FindMenuWithShortcut.
     279             :   nsMenuFrame* Enter(mozilla::WidgetGUIEvent* aEvent);
     280             : 
     281           0 :   nsPopupType PopupType() const { return mPopupType; }
     282           0 :   bool IsMenu() override { return mPopupType == ePopupTypeMenu; }
     283           0 :   bool IsOpen() override { return mPopupState == ePopupOpening ||
     284           0 :                                       mPopupState == ePopupVisible ||
     285           0 :                                       mPopupState == ePopupShown; }
     286           0 :   bool IsVisible() { return mPopupState == ePopupVisible ||
     287           0 :                             mPopupState == ePopupShown; }
     288             : 
     289             :   // Return true if the popup is for a menulist.
     290             :   bool IsMenuList();
     291             : 
     292           0 :   bool IsMouseTransparent() { return mMouseTransparent; }
     293             : 
     294             :   static nsIContent* GetTriggerContent(nsMenuPopupFrame* aMenuPopupFrame);
     295           0 :   void ClearTriggerContent() { mTriggerContent = nullptr; }
     296             : 
     297             :   // returns true if the popup is in a content shell, or false for a popup in
     298             :   // a chrome shell
     299           0 :   bool IsInContentShell() { return mInContentShell; }
     300             : 
     301             :   // the Initialize methods are used to set the anchor position for
     302             :   // each way of opening a popup.
     303             :   void InitializePopup(nsIContent* aAnchorContent,
     304             :                        nsIContent* aTriggerContent,
     305             :                        const nsAString& aPosition,
     306             :                        int32_t aXPos, int32_t aYPos,
     307             :                        MenuPopupAnchorType aAnchorType,
     308             :                        bool aAttributesOverride);
     309             : 
     310             :   void InitializePopupAtRect(nsIContent* aTriggerContent,
     311             :                              const nsAString& aPosition,
     312             :                              const nsIntRect& aRect,
     313             :                              bool aAttributesOverride);
     314             : 
     315             :   /**
     316             :    * @param aIsContextMenu if true, then the popup is
     317             :    * positioned at a slight offset from aXPos/aYPos to ensure the
     318             :    * (presumed) mouse position is not over the menu.
     319             :    */
     320             :   void InitializePopupAtScreen(nsIContent* aTriggerContent,
     321             :                                int32_t aXPos, int32_t aYPos,
     322             :                                bool aIsContextMenu);
     323             : 
     324             :   void InitializePopupWithAnchorAlign(nsIContent* aAnchorContent,
     325             :                                       nsAString& aAnchor,
     326             :                                       nsAString& aAlign,
     327             :                                       int32_t aXPos, int32_t aYPos);
     328             : 
     329             :   // indicate that the popup should be opened
     330             :   void ShowPopup(bool aIsContextMenu);
     331             :   // indicate that the popup should be hidden. The new state should either be
     332             :   // ePopupClosed or ePopupInvisible.
     333             :   void HidePopup(bool aDeselectMenu, nsPopupState aNewState);
     334             : 
     335             :   // locate and return the menu frame that should be activated for the
     336             :   // supplied key event. If doAction is set to true by this method,
     337             :   // then the menu's action should be carried out, as if the user had pressed
     338             :   // the Enter key. If doAction is false, the menu should just be highlighted.
     339             :   // This method also handles incremental searching in menus so the user can
     340             :   // type the first few letters of an item/s name to select it.
     341             :   nsMenuFrame* FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction);
     342             : 
     343           0 :   void ClearIncrementalString() { mIncrementalString.Truncate(); }
     344           0 :   static bool IsWithinIncrementalTime(DOMTimeStamp time) {
     345           0 :     return !sTimeoutOfIncrementalSearch || time - sLastKeyTime <= sTimeoutOfIncrementalSearch;
     346             :   }
     347             : 
     348             : #ifdef DEBUG_FRAME_DUMP
     349           0 :   virtual nsresult GetFrameName(nsAString& aResult) const override
     350             :   {
     351           0 :       return MakeFrameName(NS_LITERAL_STRING("MenuPopup"), aResult);
     352             :   }
     353             : #endif
     354             : 
     355             :   void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame);
     356             : 
     357             :   void ChangeByPage(bool aIsUp);
     358             : 
     359             :   // Move the popup to the screen coordinate |aPos| in CSS pixels.
     360             :   // If aUpdateAttrs is true, and the popup already has left or top attributes,
     361             :   // then those attributes are updated to the new location.
     362             :   // The frame may be destroyed by this method.
     363             :   void MoveTo(const mozilla::CSSIntPoint& aPos, bool aUpdateAttrs);
     364             : 
     365             :   void MoveToAnchor(nsIContent* aAnchorContent,
     366             :                     const nsAString& aPosition,
     367             :                     int32_t aXPos, int32_t aYPos,
     368             :                     bool aAttributesOverride);
     369             : 
     370             :   bool GetAutoPosition();
     371             :   void SetAutoPosition(bool aShouldAutoPosition);
     372             :   void SetConsumeRollupEvent(uint32_t aConsumeMode);
     373             : 
     374             :   nsIScrollableFrame* GetScrollFrame(nsIFrame* aStart);
     375             : 
     376           0 :   void SetOverrideConstraintRect(mozilla::LayoutDeviceIntRect aRect) {
     377           0 :     mOverrideConstraintRect = ToAppUnits(aRect, PresContext()->AppUnitsPerCSSPixel());
     378           0 :   }
     379             : 
     380             :   // For a popup that should appear anchored at the given rect, determine
     381             :   // the screen area that it is constrained by. This will be the available
     382             :   // area of the screen the popup should be displayed on. Content popups,
     383             :   // however, will also be constrained by the content area, given by
     384             :   // aRootScreenRect. All coordinates are in app units.
     385             :   // For non-toplevel popups (which will always be panels), we will also
     386             :   // constrain them to the available screen rect, ie they will not fall
     387             :   // underneath the taskbar, dock or other fixed OS elements.
     388             :   // This operates in device pixels.
     389             :   mozilla::LayoutDeviceIntRect
     390             :   GetConstraintRect(const mozilla::LayoutDeviceIntRect& aAnchorRect,
     391             :                     const mozilla::LayoutDeviceIntRect& aRootScreenRect,
     392             :                     nsPopupLevel aPopupLevel);
     393             : 
     394             :   // Determines whether the given edges of the popup may be moved, where
     395             :   // aHorizontalSide and aVerticalSide are one of the enum Side constants.
     396             :   // aChange is the distance to move on those sides. If will be reset to 0
     397             :   // if the side cannot be adjusted at all in that direction. For example, a
     398             :   // popup cannot be moved if it is anchored on a particular side.
     399             :   //
     400             :   // Later, when bug 357725 is implemented, we can make this adjust aChange by
     401             :   // the amount that the side can be resized, so that minimums and maximums
     402             :   // can be taken into account.
     403             :   void CanAdjustEdges(mozilla::Side aHorizontalSide,
     404             :                       mozilla::Side aVerticalSide,
     405             :                       mozilla::LayoutDeviceIntPoint& aChange);
     406             : 
     407             :   // Return true if the popup is positioned relative to an anchor.
     408           0 :   bool IsAnchored() const { return mAnchorType != MenuPopupAnchorType_Point; }
     409             : 
     410             :   // Return the anchor if there is one.
     411           0 :   nsIContent* GetAnchor() const { return mAnchorContent; }
     412             : 
     413             :   // Return the screen coordinates in CSS pixels of the popup,
     414             :   // or (-1, -1, 0, 0) if anchored.
     415           0 :   nsIntRect GetScreenAnchorRect() const { return mScreenRect; }
     416             : 
     417           0 :   mozilla::LayoutDeviceIntPoint GetLastClientOffset() const
     418             :   {
     419           0 :     return mLastClientOffset;
     420             :   }
     421             : 
     422             :   // Return the alignment of the popup
     423             :   int8_t GetAlignmentPosition() const;
     424             : 
     425             :   // Return the offset applied to the alignment of the popup
     426           0 :   nscoord GetAlignmentOffset() const { return mAlignmentOffset; }
     427             : 
     428             :   // Clear the mPopupShownDispatcher, remove the listener and return true if
     429             :   // mPopupShownDispatcher was non-null.
     430           7 :   bool ClearPopupShownDispatcher()
     431             :   {
     432           7 :     if (mPopupShownDispatcher) {
     433           0 :       mPopupShownDispatcher->CancelListener();
     434           0 :       mPopupShownDispatcher = nullptr;
     435           0 :       return true;
     436             :     }
     437             : 
     438           7 :     return false;
     439             :   }
     440             : 
     441           0 :   void ShowWithPositionedEvent() {
     442           0 :     mPopupState = ePopupPositioning;
     443           0 :     mShouldAutoPosition = true;
     444           0 :   }
     445             : 
     446             :   // Checks for the anchor to change and either moves or hides the popup
     447             :   // accordingly. The original position of the anchor should be supplied as
     448             :   // the argument. If the popup needs to be hidden, HidePopup will be called by
     449             :   // CheckForAnchorChange. If the popup needs to be moved, aRect will be updated
     450             :   // with the new rectangle.
     451             :   void CheckForAnchorChange(nsRect& aRect);
     452             : 
     453             :   // nsIReflowCallback
     454             :   virtual bool ReflowFinished() override;
     455             :   virtual void ReflowCallbackCanceled() override;
     456             : 
     457             : protected:
     458             : 
     459             :   // returns the popup's level.
     460             :   nsPopupLevel PopupLevel(bool aIsNoAutoHide) const;
     461             : 
     462             :   // redefine to tell the box system not to move the views.
     463             :   virtual uint32_t GetXULLayoutFlags() override;
     464             : 
     465             :   void InitPositionFromAnchorAlign(const nsAString& aAnchor,
     466             :                                    const nsAString& aAlign);
     467             : 
     468             :   // return the position where the popup should be, when it should be
     469             :   // anchored at anchorRect. aHFlip and aVFlip will be set if the popup may be
     470             :   // flipped in that direction if there is not enough space available.
     471             :   nsPoint AdjustPositionForAnchorAlign(nsRect& anchorRect,
     472             :                                        FlipStyle& aHFlip, FlipStyle& aVFlip);
     473             : 
     474             :   // For popups that are going to align to their selected item, get the frame of
     475             :   // the selected item.
     476             :   nsIFrame* GetSelectedItemForAlignment();
     477             : 
     478             :   // check if the popup will fit into the available space and resize it. This
     479             :   // method handles only one axis at a time so is called twice, once for
     480             :   // horizontal and once for vertical. All arguments are specified for this
     481             :   // one axis. All coordinates are in app units relative to the screen.
     482             :   //   aScreenPoint - the point where the popup should appear
     483             :   //   aSize - the size of the popup
     484             :   //   aScreenBegin - the left or top edge of the screen
     485             :   //   aScreenEnd - the right or bottom edge of the screen
     486             :   //   aAnchorBegin - the left or top edge of the anchor rectangle
     487             :   //   aAnchorEnd - the right or bottom edge of the anchor rectangle
     488             :   //   aMarginBegin - the left or top margin of the popup
     489             :   //   aMarginEnd - the right or bottom margin of the popup
     490             :   //   aOffsetForContextMenu - the additional offset to add for context menus
     491             :   //   aFlip - how to flip or resize the popup when there isn't space
     492             :   //   aFlipSide - pointer to where current flip mode is stored
     493             :   nscoord FlipOrResize(nscoord& aScreenPoint, nscoord aSize,
     494             :                        nscoord aScreenBegin, nscoord aScreenEnd,
     495             :                        nscoord aAnchorBegin, nscoord aAnchorEnd,
     496             :                        nscoord aMarginBegin, nscoord aMarginEnd,
     497             :                        nscoord aOffsetForContextMenu, FlipStyle aFlip,
     498             :                        bool aIsOnEnd, bool* aFlipSide);
     499             : 
     500             :   // check if the popup can fit into the available space by "sliding" (i.e.,
     501             :   // by having the anchor arrow slide along one axis and only resizing if that
     502             :   // can't provide the requested size). Only one axis can be slid - the other
     503             :   // axis is "flipped" as normal. This method can handle either axis, but is
     504             :   // only called for the sliding axis. All coordinates are in app units
     505             :   // relative to the screen.
     506             :   //   aScreenPoint - the point where the popup should appear
     507             :   //   aSize - the size of the popup
     508             :   //   aScreenBegin - the left or top edge of the screen
     509             :   //   aScreenEnd - the right or bottom edge of the screen
     510             :   //   aOffset - the amount by which the arrow must be slid such that it is
     511             :   //             still aligned with the anchor.
     512             :   // Result is the new size of the popup, which will typically be the same
     513             :   // as aSize, unless aSize is greater than the screen width/height.
     514             :   nscoord SlideOrResize(nscoord& aScreenPoint, nscoord aSize,
     515             :                         nscoord aScreenBegin, nscoord aScreenEnd,
     516             :                         nscoord *aOffset);
     517             : 
     518             :   // Given an anchor frame, compute the anchor rectangle relative to the screen,
     519             :   // using the popup frame's app units, and taking into account transforms.
     520             :   nsRect ComputeAnchorRect(nsPresContext* aRootPresContext, nsIFrame* aAnchorFrame);
     521             : 
     522             :   // Move the popup to the position specified in its |left| and |top| attributes.
     523             :   void MoveToAttributePosition();
     524             : 
     525             :   /**
     526             :    * Return whether the popup direction should be RTL.
     527             :    * If the popup has an anchor, its direction is the anchor direction.
     528             :    * Otherwise, its the general direction of the UI.
     529             :    *
     530             :    * Return whether the popup direction should be RTL.
     531             :    */
     532           0 :   bool IsDirectionRTL() const {
     533           0 :     return mAnchorContent && mAnchorContent->GetPrimaryFrame()
     534           0 :       ? mAnchorContent->GetPrimaryFrame()->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL
     535           0 :       : StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
     536             :   }
     537             : 
     538             :   // Create a popup view for this frame. The view is added a child of the root
     539             :   // view, and is initially hidden.
     540             :   void CreatePopupView();
     541             : 
     542          64 :   nsView* GetViewInternal() const override { return mView; }
     543          44 :   void SetViewInternal(nsView* aView) override { mView = aView; }
     544             : 
     545             :   // Returns true if the popup should try to remain at the same relative
     546             :   // location as the anchor while it is open. If the anchor becomes hidden
     547             :   // either directly or indirectly because a parent popup or other element
     548             :   // is no longer visible, or a parent deck page is changed, the popup hides
     549             :   // as well. The second variation also sets the anchor rectangle, relative to
     550             :   // the popup frame.
     551             :   bool ShouldFollowAnchor();
     552             : public:
     553             :   bool ShouldFollowAnchor(nsRect& aRect);
     554             : 
     555             : protected:
     556             :   nsString     mIncrementalString;  // for incremental typing navigation
     557             : 
     558             :   // the content that the popup is anchored to, if any, which may be in a
     559             :   // different document than the popup.
     560             :   nsCOMPtr<nsIContent> mAnchorContent;
     561             : 
     562             :   // the content that triggered the popup, typically the node where the mouse
     563             :   // was clicked. It will be cleared when the popup is hidden.
     564             :   nsCOMPtr<nsIContent> mTriggerContent;
     565             : 
     566             :   nsMenuFrame* mCurrentMenu; // The current menu that is active.
     567             :   nsView* mView;
     568             : 
     569             :   RefPtr<nsXULPopupShownEvent> mPopupShownDispatcher;
     570             : 
     571             :   // The popup's screen rectangle in app units.
     572             :   nsIntRect mUsedScreenRect;
     573             : 
     574             :   // A popup's preferred size may be different than its actual size stored in
     575             :   // mRect in the case where the popup was resized because it was too large
     576             :   // for the screen. The preferred size mPrefSize holds the full size the popup
     577             :   // would be before resizing. Computations are performed using this size.
     578             :   nsSize mPrefSize;
     579             : 
     580             :   // The position of the popup, in CSS pixels.
     581             :   // The screen coordinates, if set to values other than -1,
     582             :   // override mXPos and mYPos.
     583             :   int32_t mXPos;
     584             :   int32_t mYPos;
     585             :   nsIntRect mScreenRect;
     586             : 
     587             :   // If the panel prefers to "slide" rather than resize, then the arrow gets
     588             :   // positioned at this offset (along either the x or y axis, depending on
     589             :   // mPosition)
     590             :   nscoord mAlignmentOffset;
     591             : 
     592             :   // The value of the client offset of our widget the last time we positioned
     593             :   // ourselves. We store this so that we can detect when it changes but the
     594             :   // position of our widget didn't change.
     595             :   mozilla::LayoutDeviceIntPoint mLastClientOffset;
     596             : 
     597             :   nsPopupType mPopupType; // type of popup
     598             :   nsPopupState mPopupState; // open state of the popup
     599             : 
     600             :   // popup alignment relative to the anchor node
     601             :   int8_t mPopupAlignment;
     602             :   int8_t mPopupAnchor;
     603             :   int8_t mPosition;
     604             : 
     605             :   // One of PopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME
     606             :   uint8_t mConsumeRollupEvent;
     607             :   FlipType mFlip; // Whether to flip
     608             : 
     609             :   struct ReflowCallbackData {
     610          44 :     ReflowCallbackData() :
     611             :       mPosted(false),
     612             :       mAnchor(nullptr),
     613          44 :       mSizedToPopup(false)
     614          44 :     {}
     615           0 :     void MarkPosted(nsIFrame* aAnchor, bool aSizedToPopup) {
     616           0 :       mPosted = true;
     617           0 :       mAnchor = aAnchor;
     618           0 :       mSizedToPopup = aSizedToPopup;
     619           0 :     }
     620           0 :     void Clear() {
     621           0 :       mPosted = false;
     622           0 :       mAnchor = nullptr;
     623           0 :       mSizedToPopup = false;
     624           0 :     }
     625             :     bool mPosted;
     626             :     nsIFrame* mAnchor;
     627             :     bool mSizedToPopup;
     628             :   };
     629             :   ReflowCallbackData mReflowCallbackData;
     630             : 
     631             :   bool mIsOpenChanged; // true if the open state changed since the last layout
     632             :   bool mIsContextMenu; // true for context menus
     633             :   // true if we need to offset the popup to ensure it's not under the mouse
     634             :   bool mAdjustOffsetForContextMenu;
     635             :   bool mGeneratedChildren; // true if the contents have been created
     636             : 
     637             :   bool mMenuCanOverlapOSBar;    // can we appear over the taskbar/menubar?
     638             :   bool mShouldAutoPosition; // Should SetPopupPosition be allowed to auto position popup?
     639             :   bool mInContentShell; // True if the popup is in a content shell
     640             :   bool mIsMenuLocked; // Should events inside this menu be ignored?
     641             :   bool mMouseTransparent; // True if this is a popup is transparent to mouse events
     642             : 
     643             :   // True if this popup has been offset due to moving off / near the edge of the screen.
     644             :   // (This is useful for ensuring that a move, which can't offset the popup, doesn't undo
     645             :   // a previously set offset.)
     646             :   bool mIsOffset;
     647             : 
     648             :   // the flip modes that were used when the popup was opened
     649             :   bool mHFlip;
     650             :   bool mVFlip;
     651             : 
     652             :   // How the popup is anchored.
     653             :   MenuPopupAnchorType mAnchorType;
     654             : 
     655             :   nsRect mOverrideConstraintRect;
     656             : 
     657             :   static int8_t sDefaultLevelIsTop;
     658             : 
     659             :   static DOMTimeStamp sLastKeyTime;
     660             : 
     661             :   // If 0, never timed out.  Otherwise, the value is in milliseconds.
     662             :   static uint32_t sTimeoutOfIncrementalSearch;
     663             : }; // class nsMenuPopupFrame
     664             : 
     665             : #endif

Generated by: LCOV version 1.13