nsMenuPopupFrame.h 24 KB

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