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