Bug 1867925 - Mark some storage-access-api tests as intermittent after wpt-sync....
[gecko.git] / layout / xul / nsMenuPopupFrame.h
blob8c96f8d79e5be9f51ea89c16ef038e009c00a42c
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/. */
7 //
8 // nsMenuPopupFrame
9 //
11 #ifndef nsMenuPopupFrame_h__
12 #define nsMenuPopupFrame_h__
14 #include "mozilla/Attributes.h"
15 #include "mozilla/gfx/Types.h"
16 #include "mozilla/StaticPrefs_ui.h"
17 #include "mozilla/TimeStamp.h"
18 #include "nsAtom.h"
19 #include "nsGkAtoms.h"
20 #include "nsCOMPtr.h"
21 #include "nsIDOMEventListener.h"
22 #include "nsXULPopupManager.h"
24 #include "nsBlockFrame.h"
26 #include "Units.h"
28 class nsIWidget;
30 namespace mozilla {
31 class PresShell;
32 namespace dom {
33 class KeyboardEvent;
34 class XULButtonElement;
35 class XULPopupElement;
36 } // namespace dom
37 namespace widget {
38 enum class PopupLevel : uint8_t;
40 } // namespace mozilla
42 enum ConsumeOutsideClicksResult {
43 ConsumeOutsideClicks_ParentOnly =
44 0, // Only consume clicks on the parent anchor
45 ConsumeOutsideClicks_True = 1, // Always consume clicks
46 ConsumeOutsideClicks_Never = 2 // Never consume clicks
49 // How a popup may be flipped. Flipping to the outside edge is like how
50 // a submenu would work. The entire popup is flipped to the opposite side
51 // of the anchor.
52 enum FlipStyle {
53 FlipStyle_None = 0,
54 FlipStyle_Outside = 1,
55 FlipStyle_Inside = 2
58 // Values for the flip attribute
59 enum FlipType {
60 FlipType_Default = 0,
61 FlipType_None = 1, // don't try to flip or translate to stay onscreen
62 FlipType_Both = 2, // flip in both directions
63 FlipType_Slide = 3 // allow the arrow to "slide" instead of resizing
66 enum MenuPopupAnchorType {
67 MenuPopupAnchorType_Node = 0, // anchored to a node
68 MenuPopupAnchorType_Point = 1, // unanchored and positioned at a screen point
69 MenuPopupAnchorType_Rect = 2, // anchored at a screen rectangle
72 // values are selected so that the direction can be flipped just by
73 // changing the sign
74 #define POPUPALIGNMENT_NONE 0
75 #define POPUPALIGNMENT_TOPLEFT 1
76 #define POPUPALIGNMENT_TOPRIGHT -1
77 #define POPUPALIGNMENT_BOTTOMLEFT 2
78 #define POPUPALIGNMENT_BOTTOMRIGHT -2
80 #define POPUPALIGNMENT_LEFTCENTER 16
81 #define POPUPALIGNMENT_RIGHTCENTER -16
82 #define POPUPALIGNMENT_TOPCENTER 17
83 #define POPUPALIGNMENT_BOTTOMCENTER 18
85 // The constants here are selected so that horizontally and vertically flipping
86 // can be easily handled using the two flip macros below.
87 #define POPUPPOSITION_UNKNOWN -1
88 #define POPUPPOSITION_BEFORESTART 0
89 #define POPUPPOSITION_BEFOREEND 1
90 #define POPUPPOSITION_AFTERSTART 2
91 #define POPUPPOSITION_AFTEREND 3
92 #define POPUPPOSITION_STARTBEFORE 4
93 #define POPUPPOSITION_ENDBEFORE 5
94 #define POPUPPOSITION_STARTAFTER 6
95 #define POPUPPOSITION_ENDAFTER 7
96 #define POPUPPOSITION_OVERLAP 8
97 #define POPUPPOSITION_AFTERPOINTER 9
98 #define POPUPPOSITION_SELECTION 10
100 #define POPUPPOSITION_HFLIP(v) (v ^ 1)
101 #define POPUPPOSITION_VFLIP(v) (v ^ 2)
103 nsIFrame* NS_NewMenuPopupFrame(mozilla::PresShell* aPresShell,
104 mozilla::ComputedStyle* aStyle);
106 class nsView;
107 class nsMenuPopupFrame;
109 // this class is used for dispatching popupshown events asynchronously.
110 class nsXULPopupShownEvent final : public mozilla::Runnable,
111 public nsIDOMEventListener {
112 public:
113 nsXULPopupShownEvent(nsIContent* aPopup, nsPresContext* aPresContext)
114 : mozilla::Runnable("nsXULPopupShownEvent"),
115 mPopup(aPopup),
116 mPresContext(aPresContext) {}
118 NS_DECL_ISUPPORTS_INHERITED
119 NS_DECL_NSIRUNNABLE
120 NS_DECL_NSIDOMEVENTLISTENER
122 void CancelListener();
124 protected:
125 virtual ~nsXULPopupShownEvent() = default;
127 private:
128 const nsCOMPtr<nsIContent> mPopup;
129 const RefPtr<nsPresContext> mPresContext;
132 class nsMenuPopupFrame final : public nsBlockFrame {
133 using PopupLevel = mozilla::widget::PopupLevel;
134 using PopupType = mozilla::widget::PopupType;
136 public:
137 NS_DECL_QUERYFRAME
138 NS_DECL_FRAMEARENA_HELPERS(nsMenuPopupFrame)
140 explicit nsMenuPopupFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
141 ~nsMenuPopupFrame();
143 // as popups are opened asynchronously, the popup pending state is used to
144 // prevent multiple requests from attempting to open the same popup twice
145 nsPopupState PopupState() const { return mPopupState; }
146 void SetPopupState(nsPopupState);
149 * When this popup is open, should clicks outside of it be consumed?
150 * Return true if the popup should rollup on an outside click,
151 * but consume that click so it can't be used for anything else.
152 * Return false to allow clicks outside the popup to activate content
153 * even when the popup is open.
154 * ---------------------------------------------------------------------
156 * Should clicks outside of a popup be eaten?
158 * Menus Autocomplete Comboboxes
159 * Mac Eat No Eat
160 * Win No No Eat
161 * Unix Eat No Eat
164 ConsumeOutsideClicksResult ConsumeOutsideClicks();
166 mozilla::dom::XULPopupElement& PopupElement() const;
168 nscoord GetPrefISize(gfxContext*) final;
169 nscoord GetMinISize(gfxContext*) final;
170 void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
171 const ReflowInput& aReflowInput,
172 nsReflowStatus& aStatus) override;
174 nsIWidget* GetWidget() const;
176 enum class WidgetStyle : uint8_t {
177 ColorScheme,
178 InputRegion,
179 Opacity,
180 Shadow,
181 Transform,
183 using WidgetStyleFlags = mozilla::EnumSet<WidgetStyle>;
184 static constexpr WidgetStyleFlags AllWidgetStyleFlags() {
185 return {WidgetStyle::ColorScheme, WidgetStyle::InputRegion,
186 WidgetStyle::Opacity, WidgetStyle::Shadow, WidgetStyle::Transform};
188 void PropagateStyleToWidget(WidgetStyleFlags = AllWidgetStyleFlags()) const;
190 // Overridden methods
191 void Init(nsIContent* aContent, nsContainerFrame* aParent,
192 nsIFrame* aPrevInFlow) override;
194 nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
195 int32_t aModType) override;
197 // FIXME: This shouldn't run script (this can end up calling HidePopup).
198 MOZ_CAN_RUN_SCRIPT_BOUNDARY void Destroy(DestroyContext&) override;
200 bool HasRemoteContent() const;
202 // Whether we should create a widget on Init().
203 bool ShouldCreateWidgetUpfront() const;
205 // Whether we should expand the menu to take the size of the parent menulist.
206 bool ShouldExpandToInflowParentOrAnchor() const;
208 // Returns true if the popup is a panel with the noautohide attribute set to
209 // true. These panels do not roll up automatically.
210 bool IsNoAutoHide() const;
212 PopupLevel GetPopupLevel() const { return GetPopupLevel(IsNoAutoHide()); }
214 // Ensure that a widget has already been created for this view, and create
215 // one if it hasn't. If aRecreate is true, destroys any existing widget and
216 // creates a new one, regardless of whether one has already been created.
217 void PrepareWidget(bool aRecreate = false);
219 MOZ_CAN_RUN_SCRIPT void EnsureActiveMenuListItemIsVisible();
221 nsresult CreateWidgetForView(nsView* aView);
222 mozilla::StyleWindowShadow GetShadowStyle() const;
224 void DidSetComputedStyle(ComputedStyle* aOldStyle) override;
226 // layout, position and display the popup as needed
227 MOZ_CAN_RUN_SCRIPT_BOUNDARY
228 void LayoutPopup(nsPresContext*, ReflowOutput&, const ReflowInput&,
229 nsReflowStatus&);
231 // Set the position of the popup relative to the anchor content, anchored at a
232 // rectangle, or at a specific point if a screen position is set. The popup
233 // will be adjusted so that it is on screen. If aIsMove is true, then the
234 // popup is being moved, and should not be flipped.
235 void SetPopupPosition(bool aIsMove);
237 // Called when the Enter key is pressed while the popup is open. This will
238 // just pass the call down to the current menu, if any.
239 // Also, calling Enter will reset the current incremental search string,
240 // calculated in FindMenuWithShortcut.
241 MOZ_CAN_RUN_SCRIPT void HandleEnterKeyPress(mozilla::WidgetEvent&);
243 // Locate and return the menu frame that should be activated for the supplied
244 // key event. If aDoAction is set to true by this method, then the menu's
245 // action should be carried out, as if the user had pressed the Enter key. If
246 // aDoAction is false, the menu should just be highlighted.
247 // This method also handles incremental searching in menus so the user can
248 // type the first few letters of an item/s name to select it.
249 mozilla::dom::XULButtonElement* FindMenuWithShortcut(
250 mozilla::dom::KeyboardEvent& aKeyEvent, bool& aDoAction);
252 mozilla::dom::XULButtonElement* GetCurrentMenuItem() const;
253 nsIFrame* GetCurrentMenuItemFrame() const;
255 PopupType GetPopupType() const { return mPopupType; }
256 bool IsContextMenu() const { return mIsContextMenu; }
258 bool IsOpen() const {
259 return mPopupState == ePopupOpening || mPopupState == ePopupVisible ||
260 mPopupState == ePopupShown;
262 bool IsVisible() {
263 return mPopupState == ePopupVisible || mPopupState == ePopupShown;
265 bool IsVisibleOrShowing() {
266 return IsOpen() || mPopupState == ePopupPositioning ||
267 mPopupState == ePopupShowing;
269 bool IsNativeMenu() const { return mIsNativeMenu; }
270 bool IsMouseTransparent() const;
272 // Return true if the popup is for a menulist.
273 bool IsMenuList() const;
275 bool IsDragSource() const { return mIsDragSource; }
276 void SetIsDragSource(bool aIsDragSource) { mIsDragSource = aIsDragSource; }
278 static nsIContent* GetTriggerContent(nsMenuPopupFrame* aMenuPopupFrame);
279 void ClearTriggerContent() { mTriggerContent = nullptr; }
280 void ClearTriggerContentIncludingDocument();
282 // returns true if the popup is in a content shell, or false for a popup in
283 // a chrome shell
284 bool IsInContentShell() const { return mInContentShell; }
286 // the Initialize methods are used to set the anchor position for
287 // each way of opening a popup.
288 void InitializePopup(nsIContent* aAnchorContent, nsIContent* aTriggerContent,
289 const nsAString& aPosition, int32_t aXPos, int32_t aYPos,
290 MenuPopupAnchorType aAnchorType,
291 bool aAttributesOverride);
293 void InitializePopupAtRect(nsIContent* aTriggerContent,
294 const nsAString& aPosition, const nsIntRect& aRect,
295 bool aAttributesOverride);
298 * @param aIsContextMenu if true, then the popup is
299 * positioned at a slight offset from aXPos/aYPos to ensure the
300 * (presumed) mouse position is not over the menu.
302 void InitializePopupAtScreen(nsIContent* aTriggerContent, int32_t aXPos,
303 int32_t aYPos, bool aIsContextMenu);
305 // Called if this popup should be displayed as an OS-native context menu.
306 void InitializePopupAsNativeContextMenu(nsIContent* aTriggerContent,
307 int32_t aXPos, int32_t aYPos);
309 // indicate that the popup should be opened
310 void ShowPopup(bool aIsContextMenu);
311 // indicate that the popup should be hidden. The new state should either be
312 // ePopupClosed or ePopupInvisible.
313 MOZ_CAN_RUN_SCRIPT void HidePopup(bool aDeselectMenu, nsPopupState aNewState,
314 bool aFromFrameDestruction = false);
316 void ClearIncrementalString() { mIncrementalString.Truncate(); }
317 static bool IsWithinIncrementalTime(mozilla::TimeStamp time) {
318 return !sLastKeyTime.IsNull() &&
319 ((time - sLastKeyTime).ToMilliseconds() <=
320 mozilla::StaticPrefs::ui_menu_incremental_search_timeout());
323 #ifdef DEBUG_FRAME_DUMP
324 virtual nsresult GetFrameName(nsAString& aResult) const override {
325 return MakeFrameName(u"MenuPopup"_ns, aResult);
327 #endif
329 MOZ_CAN_RUN_SCRIPT void ChangeByPage(bool aIsUp);
331 // Move the popup to the screen coordinate |aPos| in CSS pixels.
332 // If aUpdateAttrs is true, and the popup already has left or top attributes,
333 // then those attributes are updated to the new location.
334 // The frame may be destroyed by this method.
335 void MoveTo(const mozilla::CSSPoint& aPos, bool aUpdateAttrs,
336 bool aByMoveToRect = false);
338 void MoveToAnchor(nsIContent* aAnchorContent, const nsAString& aPosition,
339 int32_t aXPos, int32_t aYPos, bool aAttributesOverride);
341 nsIScrollableFrame* GetScrollFrame() const;
343 void SetOverrideConstraintRect(const mozilla::CSSIntRect& aRect) {
344 mOverrideConstraintRect = mozilla::CSSIntRect::ToAppUnits(aRect);
347 bool IsConstrainedByLayout() const { return mConstrainedByLayout; }
349 struct Rects {
350 // For anchored popups, the anchor rectangle. For non-anchored popups, the
351 // size will be 0.
352 nsRect mAnchorRect;
353 // mAnchorRect before accounting for flipping / resizing / intersecting with
354 // the screen. This is needed for Wayland, which flips / resizes at the
355 // widget level.
356 nsRect mUntransformedAnchorRect;
357 // The final used rect we want to occupy.
358 nsRect mUsedRect;
359 // The alignment offset for sliding the panel, see
360 // nsMenuPopupFrame::mAlignmentOffset.
361 nscoord mAlignmentOffset = 0;
362 bool mHFlip = false;
363 bool mVFlip = false;
364 bool mConstrainedByLayout = false;
365 // The client offset of our widget.
366 mozilla::LayoutDeviceIntPoint mClientOffset;
367 nsPoint mViewPoint;
370 // For a popup that should appear anchored at the given rect, gets the anchor
371 // and constraint rects for that popup.
372 // This will be the available area of the screen the popup should be displayed
373 // on. Content popups, however, will also be constrained by the content area.
375 // For non-toplevel popups (which will always be panels), we will also
376 // constrain them to the available screen rect, ie they will not fall
377 // underneath the taskbar, dock or other fixed OS elements.
378 Rects GetRects(const nsSize& aPrefSize) const;
379 Maybe<nsRect> GetConstraintRect(const nsRect& aAnchorRect,
380 const nsRect& aRootScreenRect,
381 PopupLevel) const;
382 void PerformMove(const Rects&);
384 // Return true if the popup is positioned relative to an anchor.
385 bool IsAnchored() const { return mAnchorType != MenuPopupAnchorType_Point; }
387 // Return the anchor if there is one.
388 nsIContent* GetAnchor() const { return mAnchorContent; }
390 // Return the screen coordinates in CSS pixels of the popup,
391 // or (-1, -1, 0, 0) if anchored.
392 mozilla::CSSIntRect GetScreenAnchorRect() const {
393 return mozilla::CSSRect::FromAppUnitsRounded(mScreenRect);
396 mozilla::LayoutDeviceIntPoint GetLastClientOffset() const {
397 return mLastClientOffset;
400 // Return the alignment of the popup
401 int8_t GetAlignmentPosition() const;
403 // Return the offset applied to the alignment of the popup
404 nscoord GetAlignmentOffset() const { return mAlignmentOffset; }
406 // Clear the mPopupShownDispatcher, remove the listener and return true if
407 // mPopupShownDispatcher was non-null.
408 bool ClearPopupShownDispatcher() {
409 if (mPopupShownDispatcher) {
410 mPopupShownDispatcher->CancelListener();
411 mPopupShownDispatcher = nullptr;
412 return true;
415 return false;
418 void ShowWithPositionedEvent() { mPopupState = ePopupPositioning; }
420 // Checks for the anchor to change and either moves or hides the popup
421 // accordingly. The original position of the anchor should be supplied as
422 // the argument. If the popup needs to be hidden, HidePopup will be called by
423 // CheckForAnchorChange. If the popup needs to be moved, aRect will be updated
424 // with the new rectangle.
425 void CheckForAnchorChange(nsRect& aRect);
427 void WillDispatchPopupPositioned() { mPendingPositionedEvent = false; }
429 protected:
430 // returns the popup's level.
431 PopupLevel GetPopupLevel(bool aIsNoAutoHide) const;
432 void TweakMinPrefISize(nscoord&);
434 void InitPositionFromAnchorAlign(const nsAString& aAnchor,
435 const nsAString& aAlign);
437 // return the position where the popup should be, when it should be
438 // anchored at anchorRect. aHFlip and aVFlip will be set if the popup may be
439 // flipped in that direction if there is not enough space available.
440 nsPoint AdjustPositionForAnchorAlign(nsRect& aAnchorRect,
441 const nsSize& aPrefSize,
442 FlipStyle& aHFlip,
443 FlipStyle& aVFlip) const;
445 // For popups that are going to align to their selected item, get the frame of
446 // the selected item.
447 nsIFrame* GetSelectedItemForAlignment() const;
449 // check if the popup will fit into the available space and resize it. This
450 // method handles only one axis at a time so is called twice, once for
451 // horizontal and once for vertical. All arguments are specified for this
452 // one axis. All coordinates are in app units relative to the screen.
453 // aScreenPoint - the point where the popup should appear
454 // aSize - the size of the popup
455 // aScreenBegin - the left or top edge of the screen
456 // aScreenEnd - the right or bottom edge of the screen
457 // aAnchorBegin - the left or top edge of the anchor rectangle
458 // aAnchorEnd - the right or bottom edge of the anchor rectangle
459 // aMarginBegin - the left or top margin of the popup
460 // aMarginEnd - the right or bottom margin of the popup
461 // aFlip - how to flip or resize the popup when there isn't space
462 // aFlipSide - pointer to where current flip mode is stored
463 nscoord FlipOrResize(nscoord& aScreenPoint, nscoord aSize,
464 nscoord aScreenBegin, nscoord aScreenEnd,
465 nscoord aAnchorBegin, nscoord aAnchorEnd,
466 nscoord aMarginBegin, nscoord aMarginEnd,
467 FlipStyle aFlip, bool aIsOnEnd, bool* aFlipSide) const;
469 // check if the popup can fit into the available space by "sliding" (i.e.,
470 // by having the anchor arrow slide along one axis and only resizing if that
471 // can't provide the requested size). Only one axis can be slid - the other
472 // axis is "flipped" as normal. This method can handle either axis, but is
473 // only called for the sliding axis. All coordinates are in app units
474 // relative to the screen.
475 // aScreenPoint - the point where the popup should appear
476 // aSize - the size of the popup
477 // aScreenBegin - the left or top edge of the screen
478 // aScreenEnd - the right or bottom edge of the screen
479 // aOffset - the amount by which the arrow must be slid such that it is
480 // still aligned with the anchor.
481 // Result is the new size of the popup, which will typically be the same
482 // as aSize, unless aSize is greater than the screen width/height.
483 nscoord SlideOrResize(nscoord& aScreenPoint, nscoord aSize,
484 nscoord aScreenBegin, nscoord aScreenEnd,
485 nscoord* aOffset) const;
487 // Given an anchor frame, compute the anchor rectangle relative to the screen,
488 // using the popup frame's app units, and taking into account transforms.
489 nsRect ComputeAnchorRect(nsPresContext* aRootPresContext,
490 nsIFrame* aAnchorFrame) const;
492 // Move the popup to the position specified in its |left| and |top|
493 // attributes.
494 void MoveToAttributePosition();
496 // Create a popup view for this frame. The view is added a child of the root
497 // view, and is initially hidden.
498 void CreatePopupView();
500 nsView* GetViewInternal() const override { return mView; }
501 void SetViewInternal(nsView* aView) override { mView = aView; }
503 // Returns true if the popup should try to remain at the same relative
504 // location as the anchor while it is open. If the anchor becomes hidden
505 // either directly or indirectly because a parent popup or other element
506 // is no longer visible, or a parent deck page is changed, the popup hides
507 // as well. The second variation also sets the anchor rectangle, relative to
508 // the popup frame.
509 bool ShouldFollowAnchor() const;
511 nsIFrame* GetAnchorFrame() const;
513 public:
515 * Return whether the popup direction should be RTL.
516 * If the popup has an anchor, its direction is the anchor direction.
517 * Otherwise, its the general direction of the UI.
519 * Return whether the popup direction should be RTL.
521 bool IsDirectionRTL() const;
523 bool ShouldFollowAnchor(nsRect& aRect);
525 // Returns parent menu widget for submenus that are in the same
526 // frame hierarchy, it's needed for Linux/Wayland which demands
527 // strict popup windows hierarchy.
528 nsIWidget* GetParentMenuWidget();
530 // Returns the effective margin for this popup. This is the CSS margin plus
531 // the context-menu shift, if needed.
532 nsMargin GetMargin() const;
534 // These are used by Wayland backend.
535 const nsRect& GetUntransformedAnchorRect() const {
536 return mUntransformedAnchorRect;
538 int GetPopupAlignment() const { return mPopupAlignment; }
539 int GetPopupAnchor() const { return mPopupAnchor; }
540 FlipType GetFlipType() const { return mFlip; }
542 void WidgetPositionOrSizeDidChange();
544 protected:
545 nsString mIncrementalString; // for incremental typing navigation
547 // the content that the popup is anchored to, if any, which may be in a
548 // different document than the popup.
549 nsCOMPtr<nsIContent> mAnchorContent;
551 // the content that triggered the popup, typically the node where the mouse
552 // was clicked. It will be cleared when the popup is hidden.
553 nsCOMPtr<nsIContent> mTriggerContent;
555 nsView* mView = nullptr;
557 RefPtr<nsXULPopupShownEvent> mPopupShownDispatcher;
559 // The popup's screen rectangle in app units.
560 nsRect mUsedScreenRect;
562 // A popup's preferred size may be different than its actual size stored in
563 // mRect in the case where the popup was resized because it was too large
564 // for the screen. The preferred size mPrefSize holds the full size the popup
565 // would be before resizing. Computations are performed using this size.
566 nsSize mPrefSize{-1, -1};
568 // The position of the popup, in CSS pixels.
569 // The screen coordinates, if set to values other than -1,
570 // override mXPos and mYPos.
571 int32_t mXPos = 0;
572 int32_t mYPos = 0;
573 nsRect mScreenRect;
574 // Used for store rectangle which the popup is going to be anchored to, we
575 // need that for Wayland. It's important that this rect is unflipped, and
576 // without margins applied, as GTK is what takes care of determining how to
577 // flip etc. on Wayland.
578 nsRect mUntransformedAnchorRect;
580 // If the panel prefers to "slide" rather than resize, then the arrow gets
581 // positioned at this offset (along either the x or y axis, depending on
582 // mPosition)
583 nscoord mAlignmentOffset = 0;
585 // The value of the client offset of our widget the last time we positioned
586 // ourselves. We store this so that we can detect when it changes but the
587 // position of our widget didn't change.
588 mozilla::LayoutDeviceIntPoint mLastClientOffset;
590 PopupType mPopupType = PopupType::Panel; // type of popup
591 nsPopupState mPopupState = ePopupClosed; // open state of the popup
593 // popup alignment relative to the anchor node
594 int8_t mPopupAlignment = POPUPALIGNMENT_NONE;
595 int8_t mPopupAnchor = POPUPALIGNMENT_NONE;
596 int8_t mPosition = POPUPPOSITION_UNKNOWN;
598 FlipType mFlip = FlipType_Default; // Whether to flip
600 // Whether we were moved by the move-to-rect Wayland callback. In that case,
601 // we stop updating the anchor so that we can end up with a stable position.
602 bool mPositionedByMoveToRect = false;
603 // true if the open state changed since the last layout.
604 bool mIsOpenChanged = false;
605 // true for context menus and their submenus.
606 bool mIsContextMenu = false;
607 // true for the topmost context menu.
608 bool mIsTopLevelContextMenu = false;
609 // true if the popup is in a content shell.
610 bool mInContentShell = true;
612 // The flip modes that were used when the popup was opened
613 bool mHFlip = false;
614 bool mVFlip = false;
615 // Whether layout has constrained this popup in some way.
616 bool mConstrainedByLayout = false;
618 // Whether the most recent initialization of this menupopup happened via
619 // InitializePopupAsNativeContextMenu.
620 bool mIsNativeMenu = false;
622 // Whether we have a pending `popuppositioned` event.
623 bool mPendingPositionedEvent = false;
625 // Whether this popup is source of D&D operation. We can't close such
626 // popup on Wayland as it cancel whole D&D operation.
627 bool mIsDragSource = false;
629 // When POPUPPOSITION_SELECTION is used, this indicates the vertical offset
630 // that the original selected item was. This needs to be used in case the
631 // popup gets changed so that we can keep the popup at the same vertical
632 // offset.
633 // TODO(emilio): try to make this not mutable.
634 mutable nscoord mPositionedOffset = 0;
636 // How the popup is anchored.
637 MenuPopupAnchorType mAnchorType = MenuPopupAnchorType_Node;
639 nsRect mOverrideConstraintRect;
641 static int8_t sDefaultLevelIsTop;
643 static mozilla::TimeStamp sLastKeyTime;
645 }; // class nsMenuPopupFrame
647 #endif