michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // michael@0: // nsMenuPopupFrame michael@0: // michael@0: michael@0: #ifndef nsMenuPopupFrame_h__ michael@0: #define nsMenuPopupFrame_h__ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsIAtom.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsMenuFrame.h" michael@0: michael@0: #include "nsBoxFrame.h" michael@0: #include "nsMenuParent.h" michael@0: michael@0: #include "nsITimer.h" michael@0: michael@0: class nsIWidget; michael@0: michael@0: // XUL popups can be in several different states. When opening a popup, the michael@0: // state changes as follows: michael@0: // ePopupClosed - initial state michael@0: // ePopupShowing - during the period when the popupshowing event fires michael@0: // ePopupOpen - between the popupshowing event and being visible. Creation michael@0: // of the child frames, layout and reflow occurs in this state. michael@0: // ePopupOpenAndVisible - layout is done and the popup's view and widget are michael@0: // made visible. The popupshown event fires. michael@0: // When closing a popup: michael@0: // ePopupHidden - during the period when the popuphiding event fires and michael@0: // the popup is removed. michael@0: // ePopupClosed - the popup's widget is made invisible. michael@0: enum nsPopupState { michael@0: // state when a popup is not open michael@0: ePopupClosed, michael@0: // state from when a popup is requested to be shown to after the michael@0: // popupshowing event has been fired. michael@0: ePopupShowing, michael@0: // state while a popup is open but the widget is not yet visible michael@0: ePopupOpen, michael@0: // state while a popup is open and visible on screen michael@0: ePopupOpenAndVisible, michael@0: // state from when a popup is requested to be hidden to when it is closed. michael@0: ePopupHiding, michael@0: // state which indicates that the popup was hidden without firing the michael@0: // popuphiding or popuphidden events. It is used when executing a menu michael@0: // command because the menu needs to be hidden before the command event michael@0: // fires, yet the popuphiding and popuphidden events are fired after. This michael@0: // state can also occur when the popup is removed because the document is michael@0: // unloaded. michael@0: ePopupInvisible michael@0: }; michael@0: michael@0: // How a popup may be flipped. Flipping to the outside edge is like how michael@0: // a submenu would work. The entire popup is flipped to the opposite side michael@0: // of the anchor. michael@0: enum FlipStyle { michael@0: FlipStyle_None = 0, michael@0: FlipStyle_Outside = 1, michael@0: FlipStyle_Inside = 2 michael@0: }; michael@0: michael@0: // Values for the flip attribute michael@0: enum FlipType { michael@0: FlipType_Default = 0, michael@0: FlipType_None = 1, // don't try to flip or translate to stay onscreen michael@0: FlipType_Both = 2, // flip in both directions michael@0: FlipType_Slide = 3 // allow the arrow to "slide" instead of resizing michael@0: }; michael@0: michael@0: // values are selected so that the direction can be flipped just by michael@0: // changing the sign michael@0: #define POPUPALIGNMENT_NONE 0 michael@0: #define POPUPALIGNMENT_TOPLEFT 1 michael@0: #define POPUPALIGNMENT_TOPRIGHT -1 michael@0: #define POPUPALIGNMENT_BOTTOMLEFT 2 michael@0: #define POPUPALIGNMENT_BOTTOMRIGHT -2 michael@0: michael@0: #define POPUPALIGNMENT_LEFTCENTER 16 michael@0: #define POPUPALIGNMENT_RIGHTCENTER -16 michael@0: #define POPUPALIGNMENT_TOPCENTER 17 michael@0: #define POPUPALIGNMENT_BOTTOMCENTER 18 michael@0: michael@0: // The constants here are selected so that horizontally and vertically flipping michael@0: // can be easily handled using the two flip macros below. michael@0: #define POPUPPOSITION_UNKNOWN -1 michael@0: #define POPUPPOSITION_BEFORESTART 0 michael@0: #define POPUPPOSITION_BEFOREEND 1 michael@0: #define POPUPPOSITION_AFTERSTART 2 michael@0: #define POPUPPOSITION_AFTEREND 3 michael@0: #define POPUPPOSITION_STARTBEFORE 4 michael@0: #define POPUPPOSITION_ENDBEFORE 5 michael@0: #define POPUPPOSITION_STARTAFTER 6 michael@0: #define POPUPPOSITION_ENDAFTER 7 michael@0: #define POPUPPOSITION_OVERLAP 8 michael@0: #define POPUPPOSITION_AFTERPOINTER 9 michael@0: michael@0: #define POPUPPOSITION_HFLIP(v) (v ^ 1) michael@0: #define POPUPPOSITION_VFLIP(v) (v ^ 2) michael@0: michael@0: #define INC_TYP_INTERVAL 1000 // 1s. If the interval between two keypresses is shorter than this, michael@0: // treat as a continue typing michael@0: // XXX, kyle.yuan@sun.com, there are 4 definitions for the same purpose: michael@0: // nsMenuPopupFrame.h, nsListControlFrame.cpp, listbox.xml, tree.xml michael@0: // need to find a good place to put them together. michael@0: // if someone changes one, please also change the other. michael@0: michael@0: #define CONTEXT_MENU_OFFSET_PIXELS 2 michael@0: michael@0: nsIFrame* NS_NewMenuPopupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); michael@0: michael@0: class nsViewManager; michael@0: class nsView; michael@0: class nsMenuPopupFrame; michael@0: michael@0: class nsMenuPopupFrame : public nsBoxFrame, public nsMenuParent michael@0: { michael@0: public: michael@0: NS_DECL_QUERYFRAME_TARGET(nsMenuPopupFrame) michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: nsMenuPopupFrame(nsIPresShell* aShell, nsStyleContext* aContext); michael@0: michael@0: // nsMenuParent interface michael@0: virtual nsMenuFrame* GetCurrentMenuItem() MOZ_OVERRIDE; michael@0: NS_IMETHOD SetCurrentMenuItem(nsMenuFrame* aMenuItem) MOZ_OVERRIDE; michael@0: virtual void CurrentMenuIsBeingDestroyed() MOZ_OVERRIDE; michael@0: NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem, bool aSelectFirstItem) MOZ_OVERRIDE; michael@0: michael@0: // as popups are opened asynchronously, the popup pending state is used to michael@0: // prevent multiple requests from attempting to open the same popup twice michael@0: nsPopupState PopupState() { return mPopupState; } michael@0: void SetPopupState(nsPopupState aPopupState) { mPopupState = aPopupState; } michael@0: michael@0: NS_IMETHOD SetActive(bool aActiveFlag) MOZ_OVERRIDE { return NS_OK; } // We don't care. michael@0: virtual bool IsActive() MOZ_OVERRIDE { return false; } michael@0: virtual bool IsMenuBar() MOZ_OVERRIDE { return false; } michael@0: michael@0: /* michael@0: * When this popup is open, should clicks outside of it be consumed? michael@0: * Return true if the popup should rollup on an outside click, michael@0: * but consume that click so it can't be used for anything else. michael@0: * Return false to allow clicks outside the popup to activate content michael@0: * even when the popup is open. michael@0: * --------------------------------------------------------------------- michael@0: * michael@0: * Should clicks outside of a popup be eaten? michael@0: * michael@0: * Menus Autocomplete Comboboxes michael@0: * Mac Eat No Eat michael@0: * Win No No Eat michael@0: * Unix Eat No Eat michael@0: * michael@0: */ michael@0: bool ConsumeOutsideClicks(); michael@0: michael@0: virtual bool IsContextMenu() MOZ_OVERRIDE { return mIsContextMenu; } michael@0: michael@0: virtual bool MenuClosed() MOZ_OVERRIDE { return true; } michael@0: michael@0: virtual void LockMenuUntilClosed(bool aLock) MOZ_OVERRIDE; michael@0: virtual bool IsMenuLocked() MOZ_OVERRIDE { return mIsMenuLocked; } michael@0: michael@0: nsIWidget* GetWidget(); michael@0: michael@0: // The dismissal listener gets created and attached to the window. michael@0: void AttachedDismissalListener(); michael@0: michael@0: // Overridden methods michael@0: virtual void Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult AttributeChanged(int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute, michael@0: int32_t aModType) MOZ_OVERRIDE; michael@0: michael@0: virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; michael@0: michael@0: // returns true if the popup is a panel with the noautohide attribute set to michael@0: // true. These panels do not roll up automatically. michael@0: bool IsNoAutoHide() const; michael@0: michael@0: nsPopupLevel PopupLevel() const michael@0: { michael@0: return PopupLevel(IsNoAutoHide()); michael@0: } michael@0: michael@0: void EnsureWidget(); michael@0: michael@0: nsresult CreateWidgetForView(nsView* aView); michael@0: uint8_t GetShadowStyle(); michael@0: michael@0: virtual nsresult SetInitialChildList(ChildListID aListID, michael@0: nsFrameList& aChildList) MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsLeaf() const MOZ_OVERRIDE; michael@0: michael@0: // layout, position and display the popup as needed michael@0: void LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu, michael@0: nsIFrame* aAnchor, bool aSizedToPopup); michael@0: michael@0: nsView* GetRootViewForPopup(nsIFrame* aStartFrame); michael@0: michael@0: // set the position of the popup either relative to the anchor aAnchorFrame michael@0: // (or the frame for mAnchorContent if aAnchorFrame is null) or at a specific michael@0: // point if a screen position (mScreenXPos and mScreenYPos) are set. The popup michael@0: // will be adjusted so that it is on screen. If aIsMove is true, then the popup michael@0: // is being moved, and should not be flipped. michael@0: nsresult SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aSizedToPopup); michael@0: michael@0: bool HasGeneratedChildren() { return mGeneratedChildren; } michael@0: void SetGeneratedChildren() { mGeneratedChildren = true; } michael@0: michael@0: // called when the Enter key is pressed while the popup is open. This will michael@0: // just pass the call down to the current menu, if any. If a current menu michael@0: // should be opened as a result, this method should return the frame for michael@0: // that menu, or null if no menu should be opened. Also, calling Enter will michael@0: // reset the current incremental search string, calculated in michael@0: // FindMenuWithShortcut. michael@0: nsMenuFrame* Enter(mozilla::WidgetGUIEvent* aEvent); michael@0: michael@0: nsPopupType PopupType() const { return mPopupType; } michael@0: bool IsMenu() MOZ_OVERRIDE { return mPopupType == ePopupTypeMenu; } michael@0: bool IsOpen() MOZ_OVERRIDE { return mPopupState == ePopupOpen || mPopupState == ePopupOpenAndVisible; } michael@0: michael@0: bool IsMouseTransparent() { return mMouseTransparent; } michael@0: michael@0: static nsIContent* GetTriggerContent(nsMenuPopupFrame* aMenuPopupFrame); michael@0: void ClearTriggerContent() { mTriggerContent = nullptr; } michael@0: michael@0: // returns true if the popup is in a content shell, or false for a popup in michael@0: // a chrome shell michael@0: bool IsInContentShell() { return mInContentShell; } michael@0: michael@0: // the Initialize methods are used to set the anchor position for michael@0: // each way of opening a popup. michael@0: void InitializePopup(nsIContent* aAnchorContent, michael@0: nsIContent* aTriggerContent, michael@0: const nsAString& aPosition, michael@0: int32_t aXPos, int32_t aYPos, michael@0: bool aAttributesOverride); michael@0: michael@0: /** michael@0: * @param aIsContextMenu if true, then the popup is michael@0: * positioned at a slight offset from aXPos/aYPos to ensure the michael@0: * (presumed) mouse position is not over the menu. michael@0: */ michael@0: void InitializePopupAtScreen(nsIContent* aTriggerContent, michael@0: int32_t aXPos, int32_t aYPos, michael@0: bool aIsContextMenu); michael@0: michael@0: void InitializePopupWithAnchorAlign(nsIContent* aAnchorContent, michael@0: nsAString& aAnchor, michael@0: nsAString& aAlign, michael@0: int32_t aXPos, int32_t aYPos); michael@0: michael@0: // indicate that the popup should be opened michael@0: void ShowPopup(bool aIsContextMenu, bool aSelectFirstItem); michael@0: // indicate that the popup should be hidden. The new state should either be michael@0: // ePopupClosed or ePopupInvisible. michael@0: void HidePopup(bool aDeselectMenu, nsPopupState aNewState); michael@0: michael@0: // locate and return the menu frame that should be activated for the michael@0: // supplied key event. If doAction is set to true by this method, michael@0: // then the menu's action should be carried out, as if the user had pressed michael@0: // the Enter key. If doAction is false, the menu should just be highlighted. michael@0: // This method also handles incremental searching in menus so the user can michael@0: // type the first few letters of an item/s name to select it. michael@0: nsMenuFrame* FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction); michael@0: michael@0: void ClearIncrementalString() { mIncrementalString.Truncate(); } michael@0: michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE { return nsGkAtoms::menuPopupFrame; } michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE michael@0: { michael@0: return MakeFrameName(NS_LITERAL_STRING("MenuPopup"), aResult); michael@0: } michael@0: #endif michael@0: michael@0: void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame); michael@0: michael@0: // Move the popup to the screen coordinate (aLeft, aTop) in CSS pixels. michael@0: // If aUpdateAttrs is true, and the popup already has left or top attributes, michael@0: // then those attributes are updated to the new location. michael@0: // The frame may be destroyed by this method. michael@0: void MoveTo(int32_t aLeft, int32_t aTop, bool aUpdateAttrs); michael@0: michael@0: void MoveToAnchor(nsIContent* aAnchorContent, michael@0: const nsAString& aPosition, michael@0: int32_t aXPos, int32_t aYPos, michael@0: bool aAttributesOverride); michael@0: michael@0: bool GetAutoPosition(); michael@0: void SetAutoPosition(bool aShouldAutoPosition); michael@0: void SetConsumeRollupEvent(uint32_t aConsumeMode); michael@0: michael@0: nsIScrollableFrame* GetScrollFrame(nsIFrame* aStart); michael@0: michael@0: // For a popup that should appear anchored at the given rect, determine michael@0: // the screen area that it is constrained by. This will be the available michael@0: // area of the screen the popup should be displayed on. Content popups, michael@0: // however, will also be constrained by the content area, given by michael@0: // aRootScreenRect. All coordinates are in app units. michael@0: // For non-toplevel popups (which will always be panels), we will also michael@0: // constrain them to the available screen rect, ie they will not fall michael@0: // underneath the taskbar, dock or other fixed OS elements. michael@0: nsRect GetConstraintRect(const nsRect& aAnchorRect, const nsRect& aRootScreenRect, michael@0: nsPopupLevel aPopupLevel); michael@0: michael@0: // Determines whether the given edges of the popup may be moved, where michael@0: // aHorizontalSide and aVerticalSide are one of the NS_SIDE_* constants, or michael@0: // 0 for no movement in that direction. aChange is the distance to move on michael@0: // those sides. If will be reset to 0 if the side cannot be adjusted at all michael@0: // in that direction. For example, a popup cannot be moved if it is anchored michael@0: // on a particular side. michael@0: // michael@0: // Later, when bug 357725 is implemented, we can make this adjust aChange by michael@0: // the amount that the side can be resized, so that minimums and maximums michael@0: // can be taken into account. michael@0: void CanAdjustEdges(int8_t aHorizontalSide, int8_t aVerticalSide, nsIntPoint& aChange); michael@0: michael@0: // Return true if the popup is positioned relative to an anchor. michael@0: bool IsAnchored() const { return mScreenXPos == -1 && mScreenYPos == -1; } michael@0: michael@0: // Return the anchor if there is one. michael@0: nsIContent* GetAnchor() const { return mAnchorContent; } michael@0: michael@0: // Return the screen coordinates of the popup, or (-1, -1) if anchored. michael@0: // This position is in CSS pixels. michael@0: nsIntPoint ScreenPosition() const { return nsIntPoint(mScreenXPos, mScreenYPos); } michael@0: michael@0: nsIntPoint GetLastClientOffset() const { return mLastClientOffset; } michael@0: michael@0: // Return the alignment of the popup michael@0: int8_t GetAlignmentPosition() const; michael@0: michael@0: // Return the offset applied to the alignment of the popup michael@0: nscoord GetAlignmentOffset() const { return mAlignmentOffset; } michael@0: protected: michael@0: michael@0: // returns the popup's level. michael@0: nsPopupLevel PopupLevel(bool aIsNoAutoHide) const; michael@0: michael@0: // redefine to tell the box system not to move the views. michael@0: virtual void GetLayoutFlags(uint32_t& aFlags) MOZ_OVERRIDE; michael@0: michael@0: void InitPositionFromAnchorAlign(const nsAString& aAnchor, michael@0: const nsAString& aAlign); michael@0: michael@0: // return the position where the popup should be, when it should be michael@0: // anchored at anchorRect. aHFlip and aVFlip will be set if the popup may be michael@0: // flipped in that direction if there is not enough space available. michael@0: nsPoint AdjustPositionForAnchorAlign(nsRect& anchorRect, michael@0: FlipStyle& aHFlip, FlipStyle& aVFlip); michael@0: michael@0: // check if the popup will fit into the available space and resize it. This michael@0: // method handles only one axis at a time so is called twice, once for michael@0: // horizontal and once for vertical. All arguments are specified for this michael@0: // one axis. All coordinates are in app units relative to the screen. michael@0: // aScreenPoint - the point where the popup should appear michael@0: // aSize - the size of the popup michael@0: // aScreenBegin - the left or top edge of the screen michael@0: // aScreenEnd - the right or bottom edge of the screen michael@0: // aAnchorBegin - the left or top edge of the anchor rectangle michael@0: // aAnchorEnd - the right or bottom edge of the anchor rectangle michael@0: // aMarginBegin - the left or top margin of the popup michael@0: // aMarginEnd - the right or bottom margin of the popup michael@0: // aOffsetForContextMenu - the additional offset to add for context menus michael@0: // aFlip - how to flip or resize the popup when there isn't space michael@0: // aFlipSide - pointer to where current flip mode is stored michael@0: nscoord FlipOrResize(nscoord& aScreenPoint, nscoord aSize, michael@0: nscoord aScreenBegin, nscoord aScreenEnd, michael@0: nscoord aAnchorBegin, nscoord aAnchorEnd, michael@0: nscoord aMarginBegin, nscoord aMarginEnd, michael@0: nscoord aOffsetForContextMenu, FlipStyle aFlip, michael@0: bool* aFlipSide); michael@0: michael@0: // check if the popup can fit into the available space by "sliding" (i.e., michael@0: // by having the anchor arrow slide along one axis and only resizing if that michael@0: // can't provide the requested size). Only one axis can be slid - the other michael@0: // axis is "flipped" as normal. This method can handle either axis, but is michael@0: // only called for the sliding axis. All coordinates are in app units michael@0: // relative to the screen. michael@0: // aScreenPoint - the point where the popup should appear michael@0: // aSize - the size of the popup michael@0: // aScreenBegin - the left or top edge of the screen michael@0: // aScreenEnd - the right or bottom edge of the screen michael@0: // aOffset - the amount by which the arrow must be slid such that it is michael@0: // still aligned with the anchor. michael@0: // Result is the new size of the popup, which will typically be the same michael@0: // as aSize, unless aSize is greater than the screen width/height. michael@0: nscoord SlideOrResize(nscoord& aScreenPoint, nscoord aSize, michael@0: nscoord aScreenBegin, nscoord aScreenEnd, michael@0: nscoord *aOffset); michael@0: michael@0: // Move the popup to the position specified in its |left| and |top| attributes. michael@0: void MoveToAttributePosition(); michael@0: michael@0: /** michael@0: * Return whether the popup direction should be RTL. michael@0: * If the popup has an anchor, its direction is the anchor direction. michael@0: * Otherwise, its the general direction of the UI. michael@0: * michael@0: * Return whether the popup direction should be RTL. michael@0: */ michael@0: bool IsDirectionRTL() const { michael@0: return mAnchorContent && mAnchorContent->GetPrimaryFrame() michael@0: ? mAnchorContent->GetPrimaryFrame()->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL michael@0: : StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; michael@0: } michael@0: michael@0: // Create a popup view for this frame. The view is added a child of the root michael@0: // view, and is initially hidden. michael@0: void CreatePopupView(); michael@0: michael@0: nsString mIncrementalString; // for incremental typing navigation michael@0: michael@0: // the content that the popup is anchored to, if any, which may be in a michael@0: // different document than the popup. michael@0: nsCOMPtr mAnchorContent; michael@0: michael@0: // the content that triggered the popup, typically the node where the mouse michael@0: // was clicked. It will be cleared when the popup is hidden. michael@0: nsCOMPtr mTriggerContent; michael@0: michael@0: nsMenuFrame* mCurrentMenu; // The current menu that is active. michael@0: michael@0: // A popup's preferred size may be different than its actual size stored in michael@0: // mRect in the case where the popup was resized because it was too large michael@0: // for the screen. The preferred size mPrefSize holds the full size the popup michael@0: // would be before resizing. Computations are performed using this size. michael@0: nsSize mPrefSize; michael@0: michael@0: // The position of the popup, in CSS pixels. michael@0: // The screen coordinates, if set to values other than -1, michael@0: // override mXPos and mYPos. michael@0: int32_t mXPos; michael@0: int32_t mYPos; michael@0: int32_t mScreenXPos; michael@0: int32_t mScreenYPos; michael@0: michael@0: // If the panel prefers to "slide" rather than resize, then the arrow gets michael@0: // positioned at this offset (along either the x or y axis, depending on michael@0: // mPosition) michael@0: nscoord mAlignmentOffset; michael@0: michael@0: // The value of the client offset of our widget the last time we positioned michael@0: // ourselves. We store this so that we can detect when it changes but the michael@0: // position of our widget didn't change. michael@0: nsIntPoint mLastClientOffset; michael@0: michael@0: nsPopupType mPopupType; // type of popup michael@0: nsPopupState mPopupState; // open state of the popup michael@0: michael@0: // popup alignment relative to the anchor node michael@0: int8_t mPopupAlignment; michael@0: int8_t mPopupAnchor; michael@0: int8_t mPosition; michael@0: michael@0: // One of nsIPopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME michael@0: int8_t mConsumeRollupEvent; michael@0: FlipType mFlip; // Whether to flip michael@0: michael@0: bool mIsOpenChanged; // true if the open state changed since the last layout michael@0: bool mIsContextMenu; // true for context menus michael@0: // true if we need to offset the popup to ensure it's not under the mouse michael@0: bool mAdjustOffsetForContextMenu; michael@0: bool mGeneratedChildren; // true if the contents have been created michael@0: michael@0: bool mMenuCanOverlapOSBar; // can we appear over the taskbar/menubar? michael@0: bool mShouldAutoPosition; // Should SetPopupPosition be allowed to auto position popup? michael@0: bool mInContentShell; // True if the popup is in a content shell michael@0: bool mIsMenuLocked; // Should events inside this menu be ignored? michael@0: bool mMouseTransparent; // True if this is a popup is transparent to mouse events michael@0: michael@0: // the flip modes that were used when the popup was opened michael@0: bool mHFlip; michael@0: bool mVFlip; michael@0: michael@0: static int8_t sDefaultLevelIsTop; michael@0: }; // class nsMenuPopupFrame michael@0: michael@0: #endif