layout/xul/nsXULPopupManager.h

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
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 * The XUL Popup Manager keeps track of all open popups.
michael@0 8 */
michael@0 9
michael@0 10 #ifndef nsXULPopupManager_h__
michael@0 11 #define nsXULPopupManager_h__
michael@0 12
michael@0 13 #include "prlog.h"
michael@0 14 #include "nsIContent.h"
michael@0 15 #include "nsIRollupListener.h"
michael@0 16 #include "nsIDOMEventListener.h"
michael@0 17 #include "nsPoint.h"
michael@0 18 #include "nsCOMPtr.h"
michael@0 19 #include "nsTArray.h"
michael@0 20 #include "nsIObserver.h"
michael@0 21 #include "nsITimer.h"
michael@0 22 #include "nsIReflowCallback.h"
michael@0 23 #include "nsThreadUtils.h"
michael@0 24 #include "nsStyleConsts.h"
michael@0 25 #include "nsWidgetInitData.h"
michael@0 26 #include "mozilla/Attributes.h"
michael@0 27
michael@0 28 // X.h defines KeyPress
michael@0 29 #ifdef KeyPress
michael@0 30 #undef KeyPress
michael@0 31 #endif
michael@0 32
michael@0 33 /**
michael@0 34 * There are two types that are used:
michael@0 35 * - dismissable popups such as menus, which should close up when there is a
michael@0 36 * click outside the popup. In this situation, the entire chain of menus
michael@0 37 * above should also be closed.
michael@0 38 * - panels, which stay open until a request is made to close them. This
michael@0 39 * type is used by tooltips.
michael@0 40 *
michael@0 41 * When a new popup is opened, it is appended to the popup chain, stored in a
michael@0 42 * linked list in mPopups for dismissable menus and panels or mNoHidePanels
michael@0 43 * for tooltips and panels with noautohide="true".
michael@0 44 * Popups are stored in this list linked from newest to oldest. When a click
michael@0 45 * occurs outside one of the open dismissable popups, the chain is closed by
michael@0 46 * calling Rollup.
michael@0 47 */
michael@0 48
michael@0 49 class nsMenuFrame;
michael@0 50 class nsMenuPopupFrame;
michael@0 51 class nsMenuBarFrame;
michael@0 52 class nsMenuParent;
michael@0 53 class nsIDOMKeyEvent;
michael@0 54 class nsIDocShellTreeItem;
michael@0 55 class nsPIDOMWindow;
michael@0 56
michael@0 57 // when a menu command is executed, the closemenu attribute may be used
michael@0 58 // to define how the menu should be closed up
michael@0 59 enum CloseMenuMode {
michael@0 60 CloseMenuMode_Auto, // close up the chain of menus, default value
michael@0 61 CloseMenuMode_None, // don't close up any menus
michael@0 62 CloseMenuMode_Single // close up only the menu the command is inside
michael@0 63 };
michael@0 64
michael@0 65 /**
michael@0 66 * nsNavigationDirection: an enum expressing navigation through the menus in
michael@0 67 * terms which are independent of the directionality of the chrome. The
michael@0 68 * terminology, derived from XSL-FO and CSS3 (e.g.
michael@0 69 * http://www.w3.org/TR/css3-text/#TextLayout), is BASE (Before, After, Start,
michael@0 70 * End), with the addition of First and Last (mapped to Home and End
michael@0 71 * respectively).
michael@0 72 *
michael@0 73 * In languages such as English where the inline progression is left-to-right
michael@0 74 * and the block progression is top-to-bottom (lr-tb), these terms will map out
michael@0 75 * as in the following diagram
michael@0 76 *
michael@0 77 * --- inline progression --->
michael@0 78 *
michael@0 79 * First |
michael@0 80 * ... |
michael@0 81 * Before |
michael@0 82 * +--------+ block
michael@0 83 * Start | | End progression
michael@0 84 * +--------+ |
michael@0 85 * After |
michael@0 86 * ... |
michael@0 87 * Last V
michael@0 88 *
michael@0 89 */
michael@0 90
michael@0 91 enum nsNavigationDirection {
michael@0 92 eNavigationDirection_Last,
michael@0 93 eNavigationDirection_First,
michael@0 94 eNavigationDirection_Start,
michael@0 95 eNavigationDirection_Before,
michael@0 96 eNavigationDirection_End,
michael@0 97 eNavigationDirection_After
michael@0 98 };
michael@0 99
michael@0 100 #define NS_DIRECTION_IS_INLINE(dir) (dir == eNavigationDirection_Start || \
michael@0 101 dir == eNavigationDirection_End)
michael@0 102 #define NS_DIRECTION_IS_BLOCK(dir) (dir == eNavigationDirection_Before || \
michael@0 103 dir == eNavigationDirection_After)
michael@0 104 #define NS_DIRECTION_IS_BLOCK_TO_EDGE(dir) (dir == eNavigationDirection_First || \
michael@0 105 dir == eNavigationDirection_Last)
michael@0 106
michael@0 107 PR_STATIC_ASSERT(NS_STYLE_DIRECTION_LTR == 0 && NS_STYLE_DIRECTION_RTL == 1);
michael@0 108
michael@0 109 /**
michael@0 110 * DirectionFromKeyCodeTable: two arrays, the first for left-to-right and the
michael@0 111 * other for right-to-left, that map keycodes to values of
michael@0 112 * nsNavigationDirection.
michael@0 113 */
michael@0 114 extern const nsNavigationDirection DirectionFromKeyCodeTable[2][6];
michael@0 115
michael@0 116 #define NS_DIRECTION_FROM_KEY_CODE(frame, keycode) \
michael@0 117 (DirectionFromKeyCodeTable[frame->StyleVisibility()->mDirection] \
michael@0 118 [keycode - nsIDOMKeyEvent::DOM_VK_END])
michael@0 119
michael@0 120 // nsMenuChainItem holds info about an open popup. Items are stored in a
michael@0 121 // doubly linked list. Note that the linked list is stored beginning from
michael@0 122 // the lowest child in a chain of menus, as this is the active submenu.
michael@0 123 class nsMenuChainItem
michael@0 124 {
michael@0 125 private:
michael@0 126 nsMenuPopupFrame* mFrame; // the popup frame
michael@0 127 nsPopupType mPopupType; // the popup type of the frame
michael@0 128 bool mIsContext; // true for context menus
michael@0 129 bool mOnMenuBar; // true if the menu is on a menu bar
michael@0 130 bool mIgnoreKeys; // true if keyboard listeners should not be used
michael@0 131
michael@0 132 nsMenuChainItem* mParent;
michael@0 133 nsMenuChainItem* mChild;
michael@0 134
michael@0 135 public:
michael@0 136 nsMenuChainItem(nsMenuPopupFrame* aFrame, bool aIsContext, nsPopupType aPopupType)
michael@0 137 : mFrame(aFrame),
michael@0 138 mPopupType(aPopupType),
michael@0 139 mIsContext(aIsContext),
michael@0 140 mOnMenuBar(false),
michael@0 141 mIgnoreKeys(false),
michael@0 142 mParent(nullptr),
michael@0 143 mChild(nullptr)
michael@0 144 {
michael@0 145 NS_ASSERTION(aFrame, "null frame passed to nsMenuChainItem constructor");
michael@0 146 MOZ_COUNT_CTOR(nsMenuChainItem);
michael@0 147 }
michael@0 148
michael@0 149 ~nsMenuChainItem()
michael@0 150 {
michael@0 151 MOZ_COUNT_DTOR(nsMenuChainItem);
michael@0 152 }
michael@0 153
michael@0 154 nsIContent* Content();
michael@0 155 nsMenuPopupFrame* Frame() { return mFrame; }
michael@0 156 nsPopupType PopupType() { return mPopupType; }
michael@0 157 bool IsMenu() { return mPopupType == ePopupTypeMenu; }
michael@0 158 bool IsContextMenu() { return mIsContext; }
michael@0 159 bool IgnoreKeys() { return mIgnoreKeys; }
michael@0 160 bool IsOnMenuBar() { return mOnMenuBar; }
michael@0 161 void SetIgnoreKeys(bool aIgnoreKeys) { mIgnoreKeys = aIgnoreKeys; }
michael@0 162 void SetOnMenuBar(bool aOnMenuBar) { mOnMenuBar = aOnMenuBar; }
michael@0 163 nsMenuChainItem* GetParent() { return mParent; }
michael@0 164 nsMenuChainItem* GetChild() { return mChild; }
michael@0 165
michael@0 166 // set the parent of this item to aParent, also changing the parent
michael@0 167 // to have this as a child.
michael@0 168 void SetParent(nsMenuChainItem* aParent);
michael@0 169
michael@0 170 // removes an item from the chain. The root pointer must be supplied in case
michael@0 171 // the item is the first item in the chain in which case the pointer will be
michael@0 172 // set to the next item, or null if there isn't another item. After detaching,
michael@0 173 // this item will not have a parent or a child.
michael@0 174 void Detach(nsMenuChainItem** aRoot);
michael@0 175 };
michael@0 176
michael@0 177 // this class is used for dispatching popupshowing events asynchronously.
michael@0 178 class nsXULPopupShowingEvent : public nsRunnable
michael@0 179 {
michael@0 180 public:
michael@0 181 nsXULPopupShowingEvent(nsIContent *aPopup,
michael@0 182 bool aIsContextMenu,
michael@0 183 bool aSelectFirstItem)
michael@0 184 : mPopup(aPopup),
michael@0 185 mIsContextMenu(aIsContextMenu),
michael@0 186 mSelectFirstItem(aSelectFirstItem)
michael@0 187 {
michael@0 188 NS_ASSERTION(aPopup, "null popup supplied to nsXULPopupShowingEvent constructor");
michael@0 189 }
michael@0 190
michael@0 191 NS_IMETHOD Run() MOZ_OVERRIDE;
michael@0 192
michael@0 193 private:
michael@0 194 nsCOMPtr<nsIContent> mPopup;
michael@0 195 bool mIsContextMenu;
michael@0 196 bool mSelectFirstItem;
michael@0 197 };
michael@0 198
michael@0 199 // this class is used for dispatching popuphiding events asynchronously.
michael@0 200 class nsXULPopupHidingEvent : public nsRunnable
michael@0 201 {
michael@0 202 public:
michael@0 203 nsXULPopupHidingEvent(nsIContent *aPopup,
michael@0 204 nsIContent* aNextPopup,
michael@0 205 nsIContent* aLastPopup,
michael@0 206 nsPopupType aPopupType,
michael@0 207 bool aDeselectMenu,
michael@0 208 bool aIsRollup)
michael@0 209 : mPopup(aPopup),
michael@0 210 mNextPopup(aNextPopup),
michael@0 211 mLastPopup(aLastPopup),
michael@0 212 mPopupType(aPopupType),
michael@0 213 mDeselectMenu(aDeselectMenu),
michael@0 214 mIsRollup(aIsRollup)
michael@0 215 {
michael@0 216 NS_ASSERTION(aPopup, "null popup supplied to nsXULPopupHidingEvent constructor");
michael@0 217 // aNextPopup and aLastPopup may be null
michael@0 218 }
michael@0 219
michael@0 220 NS_IMETHOD Run() MOZ_OVERRIDE;
michael@0 221
michael@0 222 private:
michael@0 223 nsCOMPtr<nsIContent> mPopup;
michael@0 224 nsCOMPtr<nsIContent> mNextPopup;
michael@0 225 nsCOMPtr<nsIContent> mLastPopup;
michael@0 226 nsPopupType mPopupType;
michael@0 227 bool mDeselectMenu;
michael@0 228 bool mIsRollup;
michael@0 229 };
michael@0 230
michael@0 231 // this class is used for dispatching menu command events asynchronously.
michael@0 232 class nsXULMenuCommandEvent : public nsRunnable
michael@0 233 {
michael@0 234 public:
michael@0 235 nsXULMenuCommandEvent(nsIContent *aMenu,
michael@0 236 bool aIsTrusted,
michael@0 237 bool aShift,
michael@0 238 bool aControl,
michael@0 239 bool aAlt,
michael@0 240 bool aMeta,
michael@0 241 bool aUserInput,
michael@0 242 bool aFlipChecked)
michael@0 243 : mMenu(aMenu),
michael@0 244 mIsTrusted(aIsTrusted),
michael@0 245 mShift(aShift),
michael@0 246 mControl(aControl),
michael@0 247 mAlt(aAlt),
michael@0 248 mMeta(aMeta),
michael@0 249 mUserInput(aUserInput),
michael@0 250 mFlipChecked(aFlipChecked),
michael@0 251 mCloseMenuMode(CloseMenuMode_Auto)
michael@0 252 {
michael@0 253 NS_ASSERTION(aMenu, "null menu supplied to nsXULMenuCommandEvent constructor");
michael@0 254 }
michael@0 255
michael@0 256 NS_IMETHOD Run() MOZ_OVERRIDE;
michael@0 257
michael@0 258 void SetCloseMenuMode(CloseMenuMode aCloseMenuMode) { mCloseMenuMode = aCloseMenuMode; }
michael@0 259
michael@0 260 private:
michael@0 261 nsCOMPtr<nsIContent> mMenu;
michael@0 262 bool mIsTrusted;
michael@0 263 bool mShift;
michael@0 264 bool mControl;
michael@0 265 bool mAlt;
michael@0 266 bool mMeta;
michael@0 267 bool mUserInput;
michael@0 268 bool mFlipChecked;
michael@0 269 CloseMenuMode mCloseMenuMode;
michael@0 270 };
michael@0 271
michael@0 272 class nsXULPopupManager MOZ_FINAL : public nsIDOMEventListener,
michael@0 273 public nsIRollupListener,
michael@0 274 public nsITimerCallback,
michael@0 275 public nsIObserver
michael@0 276 {
michael@0 277
michael@0 278 public:
michael@0 279 friend class nsXULPopupShowingEvent;
michael@0 280 friend class nsXULPopupHidingEvent;
michael@0 281 friend class nsXULMenuCommandEvent;
michael@0 282 friend class TransitionEnder;
michael@0 283
michael@0 284 NS_DECL_ISUPPORTS
michael@0 285 NS_DECL_NSIOBSERVER
michael@0 286 NS_DECL_NSITIMERCALLBACK
michael@0 287 NS_DECL_NSIDOMEVENTLISTENER
michael@0 288
michael@0 289 // nsIRollupListener
michael@0 290 virtual bool Rollup(uint32_t aCount, const nsIntPoint* pos, nsIContent** aLastRolledUp) MOZ_OVERRIDE;
michael@0 291 virtual bool ShouldRollupOnMouseWheelEvent() MOZ_OVERRIDE;
michael@0 292 virtual bool ShouldConsumeOnMouseWheelEvent() MOZ_OVERRIDE;
michael@0 293 virtual bool ShouldRollupOnMouseActivate() MOZ_OVERRIDE;
michael@0 294 virtual uint32_t GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain) MOZ_OVERRIDE;
michael@0 295 virtual void NotifyGeometryChange() MOZ_OVERRIDE {}
michael@0 296 virtual nsIWidget* GetRollupWidget() MOZ_OVERRIDE;
michael@0 297
michael@0 298 static nsXULPopupManager* sInstance;
michael@0 299
michael@0 300 // initialize and shutdown methods called by nsLayoutStatics
michael@0 301 static nsresult Init();
michael@0 302 static void Shutdown();
michael@0 303
michael@0 304 // returns a weak reference to the popup manager instance, could return null
michael@0 305 // if a popup manager could not be allocated
michael@0 306 static nsXULPopupManager* GetInstance();
michael@0 307
michael@0 308 // This should be called when a window is moved or resized to adjust the
michael@0 309 // popups accordingly.
michael@0 310 void AdjustPopupsOnWindowChange(nsPIDOMWindow* aWindow);
michael@0 311 void AdjustPopupsOnWindowChange(nsIPresShell* aPresShell);
michael@0 312
michael@0 313 // given a menu frame, find the prevous or next menu frame. If aPopup is
michael@0 314 // true then navigate a menupopup, from one item on the menu to the previous
michael@0 315 // or next one. This is used for cursor navigation between items in a popup
michael@0 316 // menu. If aIsPopup is false, the navigation is on a menubar, so navigate
michael@0 317 // between menus on the menubar. This is used for left/right cursor navigation.
michael@0 318 //
michael@0 319 // Items that are not valid, such as non-menu or non-menuitem elements are
michael@0 320 // skipped, and the next or previous item after that is checked.
michael@0 321 //
michael@0 322 // If aStart is null, the first valid item is retrieved by GetNextMenuItem
michael@0 323 // and the last valid item is retrieved by GetPreviousMenuItem.
michael@0 324 //
michael@0 325 // Both methods will loop around the beginning or end if needed.
michael@0 326 //
michael@0 327 // aParent - the parent menubar or menupopup
michael@0 328 // aStart - the menu/menuitem to start navigation from. GetPreviousMenuItem
michael@0 329 // returns the item before it, while GetNextMenuItem returns the
michael@0 330 // item after it.
michael@0 331 // aIsPopup - true for menupopups, false for menubars
michael@0 332 static nsMenuFrame* GetPreviousMenuItem(nsIFrame* aParent,
michael@0 333 nsMenuFrame* aStart,
michael@0 334 bool aIsPopup);
michael@0 335 static nsMenuFrame* GetNextMenuItem(nsIFrame* aParent,
michael@0 336 nsMenuFrame* aStart,
michael@0 337 bool aIsPopup);
michael@0 338
michael@0 339 // returns true if the menu item aContent is a valid menuitem which may
michael@0 340 // be navigated to. aIsPopup should be true for items on a popup, or false
michael@0 341 // for items on a menubar.
michael@0 342 static bool IsValidMenuItem(nsPresContext* aPresContext,
michael@0 343 nsIContent* aContent,
michael@0 344 bool aOnPopup);
michael@0 345
michael@0 346 // inform the popup manager that a menu bar has been activated or deactivated,
michael@0 347 // either because one of its menus has opened or closed, or that the menubar
michael@0 348 // has been focused such that its menus may be navigated with the keyboard.
michael@0 349 // aActivate should be true when the menubar should be focused, and false
michael@0 350 // when the active menu bar should be defocused. In the latter case, if
michael@0 351 // aMenuBar isn't currently active, yet another menu bar is, that menu bar
michael@0 352 // will remain active.
michael@0 353 void SetActiveMenuBar(nsMenuBarFrame* aMenuBar, bool aActivate);
michael@0 354
michael@0 355 // retrieve the node and offset of the last mouse event used to open a
michael@0 356 // context menu. This information is determined from the rangeParent and
michael@0 357 // the rangeOffset of the event supplied to ShowPopup or ShowPopupAtScreen.
michael@0 358 // This is used by the implementation of nsIDOMXULDocument::GetPopupRangeParent
michael@0 359 // and nsIDOMXULDocument::GetPopupRangeOffset.
michael@0 360 void GetMouseLocation(nsIDOMNode** aNode, int32_t* aOffset);
michael@0 361
michael@0 362 /**
michael@0 363 * Open a <menu> given its content node. If aSelectFirstItem is
michael@0 364 * set to true, the first item on the menu will automatically be
michael@0 365 * selected. If aAsynchronous is true, the event will be dispatched
michael@0 366 * asynchronously. This should be true when called from frame code.
michael@0 367 */
michael@0 368 void ShowMenu(nsIContent *aMenu, bool aSelectFirstItem, bool aAsynchronous);
michael@0 369
michael@0 370 /**
michael@0 371 * Open a popup, either anchored or unanchored. If aSelectFirstItem is
michael@0 372 * true, then the first item in the menu is selected. The arguments are
michael@0 373 * similar to those for nsIPopupBoxObject::OpenPopup.
michael@0 374 *
michael@0 375 * aTriggerEvent should be the event that triggered the event. This is used
michael@0 376 * to determine the coordinates and trigger node for the popup. This may be
michael@0 377 * null if the popup was not triggered by an event.
michael@0 378 *
michael@0 379 * This fires the popupshowing event synchronously.
michael@0 380 */
michael@0 381 void ShowPopup(nsIContent* aPopup,
michael@0 382 nsIContent* aAnchorContent,
michael@0 383 const nsAString& aPosition,
michael@0 384 int32_t aXPos, int32_t aYPos,
michael@0 385 bool aIsContextMenu,
michael@0 386 bool aAttributesOverride,
michael@0 387 bool aSelectFirstItem,
michael@0 388 nsIDOMEvent* aTriggerEvent);
michael@0 389
michael@0 390 /**
michael@0 391 * Open a popup at a specific screen position specified by aXPos and aYPos,
michael@0 392 * measured in CSS pixels.
michael@0 393 *
michael@0 394 * This fires the popupshowing event synchronously.
michael@0 395 *
michael@0 396 * If aIsContextMenu is true, the popup is positioned at a slight
michael@0 397 * offset from aXPos/aYPos to ensure that it is not under the mouse
michael@0 398 * cursor.
michael@0 399 */
michael@0 400 void ShowPopupAtScreen(nsIContent* aPopup,
michael@0 401 int32_t aXPos, int32_t aYPos,
michael@0 402 bool aIsContextMenu,
michael@0 403 nsIDOMEvent* aTriggerEvent);
michael@0 404
michael@0 405 /**
michael@0 406 * Open a tooltip at a specific screen position specified by aXPos and aYPos,
michael@0 407 * measured in CSS pixels.
michael@0 408 *
michael@0 409 * This fires the popupshowing event synchronously.
michael@0 410 */
michael@0 411 void ShowTooltipAtScreen(nsIContent* aPopup,
michael@0 412 nsIContent* aTriggerContent,
michael@0 413 int32_t aXPos, int32_t aYPos);
michael@0 414
michael@0 415 /**
michael@0 416 * This method is provided only for compatibility with an older popup API.
michael@0 417 * New code should not call this function and should call ShowPopup instead.
michael@0 418 *
michael@0 419 * This fires the popupshowing event synchronously.
michael@0 420 */
michael@0 421 void ShowPopupWithAnchorAlign(nsIContent* aPopup,
michael@0 422 nsIContent* aAnchorContent,
michael@0 423 nsAString& aAnchor,
michael@0 424 nsAString& aAlign,
michael@0 425 int32_t aXPos, int32_t aYPos,
michael@0 426 bool aIsContextMenu);
michael@0 427
michael@0 428 /*
michael@0 429 * Hide a popup aPopup. If the popup is in a <menu>, then also inform the
michael@0 430 * menu that the popup is being hidden.
michael@0 431 *
michael@0 432 * aHideChain - true if the entire chain of menus should be closed. If false,
michael@0 433 * only this popup is closed.
michael@0 434 * aDeselectMenu - true if the parent <menu> of the popup should be deselected.
michael@0 435 * This will be false when the menu is closed by pressing the
michael@0 436 * Escape key.
michael@0 437 * aAsynchronous - true if the first popuphiding event should be sent
michael@0 438 * asynchrously. This should be true if HidePopup is called
michael@0 439 * from a frame.
michael@0 440 * aIsRollup - true if this popup is hiding due to a rollup or escape keypress.
michael@0 441 * aLastPopup - optional popup to close last when hiding a chain of menus.
michael@0 442 * If null, then all popups will be closed.
michael@0 443 */
michael@0 444 void HidePopup(nsIContent* aPopup,
michael@0 445 bool aHideChain,
michael@0 446 bool aDeselectMenu,
michael@0 447 bool aAsynchronous,
michael@0 448 bool aIsRollup,
michael@0 449 nsIContent* aLastPopup = nullptr);
michael@0 450
michael@0 451 /**
michael@0 452 * Hide the popup aFrame. This method is called by the view manager when the
michael@0 453 * close button is pressed.
michael@0 454 */
michael@0 455 void HidePopup(nsIFrame* aFrame);
michael@0 456
michael@0 457 /**
michael@0 458 * Hide a popup after a short delay. This is used when rolling over menu items.
michael@0 459 * This timer is stored in mCloseTimer. The timer may be cancelled and the popup
michael@0 460 * closed by calling KillMenuTimer.
michael@0 461 */
michael@0 462 void HidePopupAfterDelay(nsMenuPopupFrame* aPopup);
michael@0 463
michael@0 464 /**
michael@0 465 * Hide all of the popups from a given docshell. This should be called when the
michael@0 466 * document is hidden.
michael@0 467 */
michael@0 468 void HidePopupsInDocShell(nsIDocShellTreeItem* aDocShellToHide);
michael@0 469
michael@0 470 /**
michael@0 471 * Execute a menu command from the triggering event aEvent.
michael@0 472 *
michael@0 473 * aMenu - a menuitem to execute
michael@0 474 * aEvent - an nsXULMenuCommandEvent that contains all the info from the mouse
michael@0 475 * event which triggered the menu to be executed, may not be null
michael@0 476 */
michael@0 477 void ExecuteMenu(nsIContent* aMenu, nsXULMenuCommandEvent* aEvent);
michael@0 478
michael@0 479 /**
michael@0 480 * Return true if the popup for the supplied content node is open.
michael@0 481 */
michael@0 482 bool IsPopupOpen(nsIContent* aPopup);
michael@0 483
michael@0 484 /**
michael@0 485 * Return true if the popup for the supplied menu parent is open.
michael@0 486 */
michael@0 487 bool IsPopupOpenForMenuParent(nsMenuParent* aMenuParent);
michael@0 488
michael@0 489 /**
michael@0 490 * Return the frame for the topmost open popup of a given type, or null if
michael@0 491 * no popup of that type is open. If aType is ePopupTypeAny, a menu of any
michael@0 492 * type is returned, except for popups in the mNoHidePanels list.
michael@0 493 */
michael@0 494 nsIFrame* GetTopPopup(nsPopupType aType);
michael@0 495
michael@0 496 /**
michael@0 497 * Return an array of all the open and visible popup frames for
michael@0 498 * menus, in order from top to bottom.
michael@0 499 */
michael@0 500 void GetVisiblePopups(nsTArray<nsIFrame *>& aPopups);
michael@0 501
michael@0 502 /**
michael@0 503 * Get the node that last triggered a popup or tooltip in the document
michael@0 504 * aDocument. aDocument must be non-null and be a document contained within
michael@0 505 * the same window hierarchy as the popup to retrieve.
michael@0 506 */
michael@0 507 already_AddRefed<nsIDOMNode> GetLastTriggerPopupNode(nsIDocument* aDocument)
michael@0 508 {
michael@0 509 return GetLastTriggerNode(aDocument, false);
michael@0 510 }
michael@0 511
michael@0 512 already_AddRefed<nsIDOMNode> GetLastTriggerTooltipNode(nsIDocument* aDocument)
michael@0 513 {
michael@0 514 return GetLastTriggerNode(aDocument, true);
michael@0 515 }
michael@0 516
michael@0 517 /**
michael@0 518 * Return false if a popup may not be opened. This will return false if the
michael@0 519 * popup is already open, if the popup is in a content shell that is not
michael@0 520 * focused, or if it is a submenu of another menu that isn't open.
michael@0 521 */
michael@0 522 bool MayShowPopup(nsMenuPopupFrame* aFrame);
michael@0 523
michael@0 524 /**
michael@0 525 * Indicate that the popup associated with aView has been moved to the
michael@0 526 * specified screen coordiates.
michael@0 527 */
michael@0 528 void PopupMoved(nsIFrame* aFrame, nsIntPoint aPoint);
michael@0 529
michael@0 530 /**
michael@0 531 * Indicate that the popup associated with aView has been resized to the
michael@0 532 * specified screen width and height.
michael@0 533 */
michael@0 534 void PopupResized(nsIFrame* aFrame, nsIntSize ASize);
michael@0 535
michael@0 536 /**
michael@0 537 * Called when a popup frame is destroyed. In this case, just remove the
michael@0 538 * item and later popups from the list. No point going through HidePopup as
michael@0 539 * the frames have gone away.
michael@0 540 */
michael@0 541 void PopupDestroyed(nsMenuPopupFrame* aFrame);
michael@0 542
michael@0 543 /**
michael@0 544 * Returns true if there is a context menu open. If aPopup is specified,
michael@0 545 * then the context menu must be later in the chain than aPopup. If aPopup
michael@0 546 * is null, returns true if any context menu at all is open.
michael@0 547 */
michael@0 548 bool HasContextMenu(nsMenuPopupFrame* aPopup);
michael@0 549
michael@0 550 /**
michael@0 551 * Update the commands for the menus within the menu popup for a given
michael@0 552 * content node. aPopup should be a XUL menupopup element. This method
michael@0 553 * changes attributes on the children of aPopup, and deals only with the
michael@0 554 * content of the popup, not the frames.
michael@0 555 */
michael@0 556 void UpdateMenuItems(nsIContent* aPopup);
michael@0 557
michael@0 558 /**
michael@0 559 * Stop the timer which hides a popup after a delay, started by a previous
michael@0 560 * call to HidePopupAfterDelay. In addition, the popup awaiting to be hidden
michael@0 561 * is closed asynchronously.
michael@0 562 */
michael@0 563 void KillMenuTimer();
michael@0 564
michael@0 565 /**
michael@0 566 * Cancel the timer which closes menus after delay, but only if the menu to
michael@0 567 * close is aMenuParent. When a submenu is opened, the user might move the
michael@0 568 * mouse over a sibling menuitem which would normally close the menu. This
michael@0 569 * menu is closed via a timer. However, if the user moves the mouse over the
michael@0 570 * submenu before the timer fires, we should instead cancel the timer. This
michael@0 571 * ensures that the user can move the mouse diagonally over a menu.
michael@0 572 */
michael@0 573 void CancelMenuTimer(nsMenuParent* aMenuParent);
michael@0 574
michael@0 575 /**
michael@0 576 * Handles navigation for menu accelkeys. Returns true if the key has
michael@0 577 * been handled. If aFrame is specified, then the key is handled by that
michael@0 578 * popup, otherwise if aFrame is null, the key is handled by the active
michael@0 579 * popup or menubar.
michael@0 580 */
michael@0 581 bool HandleShortcutNavigation(nsIDOMKeyEvent* aKeyEvent,
michael@0 582 nsMenuPopupFrame* aFrame);
michael@0 583
michael@0 584 /**
michael@0 585 * Handles cursor navigation within a menu. Returns true if the key has
michael@0 586 * been handled.
michael@0 587 */
michael@0 588 bool HandleKeyboardNavigation(uint32_t aKeyCode);
michael@0 589
michael@0 590 /**
michael@0 591 * Handle keyboard navigation within a menu popup specified by aFrame.
michael@0 592 * Returns true if the key was handled and other default handling
michael@0 593 * should not occur.
michael@0 594 */
michael@0 595 bool HandleKeyboardNavigationInPopup(nsMenuPopupFrame* aFrame,
michael@0 596 nsNavigationDirection aDir)
michael@0 597 {
michael@0 598 return HandleKeyboardNavigationInPopup(nullptr, aFrame, aDir);
michael@0 599 }
michael@0 600
michael@0 601 /**
michael@0 602 * Handles the keyboard event with keyCode value. Returns true if the event
michael@0 603 * has been handled.
michael@0 604 */
michael@0 605 bool HandleKeyboardEventWithKeyCode(nsIDOMKeyEvent* aKeyEvent,
michael@0 606 nsMenuChainItem* aTopVisibleMenuItem);
michael@0 607
michael@0 608 nsresult KeyUp(nsIDOMKeyEvent* aKeyEvent);
michael@0 609 nsresult KeyDown(nsIDOMKeyEvent* aKeyEvent);
michael@0 610 nsresult KeyPress(nsIDOMKeyEvent* aKeyEvent);
michael@0 611
michael@0 612 protected:
michael@0 613 nsXULPopupManager();
michael@0 614 ~nsXULPopupManager();
michael@0 615
michael@0 616 // get the nsMenuPopupFrame, if any, for the given content node
michael@0 617 nsMenuPopupFrame* GetPopupFrameForContent(nsIContent* aContent, bool aShouldFlush);
michael@0 618
michael@0 619 // return the topmost menu, skipping over invisible popups
michael@0 620 nsMenuChainItem* GetTopVisibleMenu();
michael@0 621
michael@0 622 // Hide all of the visible popups from the given list. aDeselectMenu
michael@0 623 // indicates whether to deselect the menu of popups when hiding; this
michael@0 624 // flag is passed as the first argument to HidePopup. This function
michael@0 625 // can cause style changes and frame destruction.
michael@0 626 void HidePopupsInList(const nsTArray<nsMenuPopupFrame *> &aFrames,
michael@0 627 bool aDeselectMenu);
michael@0 628
michael@0 629 // set the event that was used to trigger the popup, or null to clear the
michael@0 630 // event details. aTriggerContent will be set to the target of the event.
michael@0 631 void InitTriggerEvent(nsIDOMEvent* aEvent, nsIContent* aPopup, nsIContent** aTriggerContent);
michael@0 632
michael@0 633 // callbacks for ShowPopup and HidePopup as events may be done asynchronously
michael@0 634 void ShowPopupCallback(nsIContent* aPopup,
michael@0 635 nsMenuPopupFrame* aPopupFrame,
michael@0 636 bool aIsContextMenu,
michael@0 637 bool aSelectFirstItem);
michael@0 638 void HidePopupCallback(nsIContent* aPopup,
michael@0 639 nsMenuPopupFrame* aPopupFrame,
michael@0 640 nsIContent* aNextPopup,
michael@0 641 nsIContent* aLastPopup,
michael@0 642 nsPopupType aPopupType,
michael@0 643 bool aDeselectMenu);
michael@0 644
michael@0 645 /**
michael@0 646 * Fire a popupshowing event on the popup and then open the popup.
michael@0 647 *
michael@0 648 * aPopup - the popup to open
michael@0 649 * aIsContextMenu - true for context menus
michael@0 650 * aSelectFirstItem - true to select the first item in the menu
michael@0 651 */
michael@0 652 void FirePopupShowingEvent(nsIContent* aPopup,
michael@0 653 bool aIsContextMenu,
michael@0 654 bool aSelectFirstItem);
michael@0 655
michael@0 656 /**
michael@0 657 * Fire a popuphiding event and then hide the popup. This will be called
michael@0 658 * recursively if aNextPopup and aLastPopup are set in order to hide a chain
michael@0 659 * of open menus. If these are not set, only one popup is closed. However,
michael@0 660 * if the popup type indicates a menu, yet the next popup is not a menu,
michael@0 661 * then this ends the closing of popups. This allows a menulist inside a
michael@0 662 * non-menu to close up the menu but not close up the panel it is contained
michael@0 663 * within.
michael@0 664 *
michael@0 665 * The caller must keep a strong reference to aPopup, aNextPopup and aLastPopup.
michael@0 666 *
michael@0 667 * aPopup - the popup to hide
michael@0 668 * aNextPopup - the next popup to hide
michael@0 669 * aLastPopup - the last popup in the chain to hide
michael@0 670 * aPresContext - nsPresContext for the popup's frame
michael@0 671 * aPopupType - the PopupType of the frame.
michael@0 672 * aDeselectMenu - true to unhighlight the menu when hiding it
michael@0 673 * aIsRollup - true if this popup is hiding due to a rollup or escape keypress
michael@0 674 */
michael@0 675 void FirePopupHidingEvent(nsIContent* aPopup,
michael@0 676 nsIContent* aNextPopup,
michael@0 677 nsIContent* aLastPopup,
michael@0 678 nsPresContext *aPresContext,
michael@0 679 nsPopupType aPopupType,
michael@0 680 bool aDeselectMenu,
michael@0 681 bool aIsRollup);
michael@0 682
michael@0 683 /**
michael@0 684 * Handle keyboard navigation within a menu popup specified by aItem.
michael@0 685 */
michael@0 686 bool HandleKeyboardNavigationInPopup(nsMenuChainItem* aItem,
michael@0 687 nsNavigationDirection aDir)
michael@0 688 {
michael@0 689 return HandleKeyboardNavigationInPopup(aItem, aItem->Frame(), aDir);
michael@0 690 }
michael@0 691
michael@0 692 private:
michael@0 693 /**
michael@0 694 * Handle keyboard navigation within a menu popup aFrame. If aItem is
michael@0 695 * supplied, then it is expected to have a frame equal to aFrame.
michael@0 696 * If aItem is non-null, then the navigation may be redirected to
michael@0 697 * an open submenu if one exists. Returns true if the key was
michael@0 698 * handled and other default handling should not occur.
michael@0 699 */
michael@0 700 bool HandleKeyboardNavigationInPopup(nsMenuChainItem* aItem,
michael@0 701 nsMenuPopupFrame* aFrame,
michael@0 702 nsNavigationDirection aDir);
michael@0 703
michael@0 704 protected:
michael@0 705
michael@0 706 already_AddRefed<nsIDOMNode> GetLastTriggerNode(nsIDocument* aDocument, bool aIsTooltip);
michael@0 707
michael@0 708 /**
michael@0 709 * Set mouse capturing for the current popup. This traps mouse clicks that
michael@0 710 * occur outside the popup so that it can be closed up. aOldPopup should be
michael@0 711 * set to the popup that was previously the current popup.
michael@0 712 */
michael@0 713 void SetCaptureState(nsIContent *aOldPopup);
michael@0 714
michael@0 715 /**
michael@0 716 * Key event listeners are attached to the document containing the current
michael@0 717 * menu for menu and shortcut navigation. Only one listener is needed at a
michael@0 718 * time, stored in mKeyListener, so switch it only if the document changes.
michael@0 719 * Having menus in different documents is very rare, so the listeners will
michael@0 720 * usually only be attached when the first menu opens and removed when all
michael@0 721 * menus have closed.
michael@0 722 *
michael@0 723 * This is also used when only a menubar is active without any open menus,
michael@0 724 * so that keyboard navigation between menus on the menubar may be done.
michael@0 725 */
michael@0 726 void UpdateKeyboardListeners();
michael@0 727
michael@0 728 /*
michael@0 729 * Returns true if the docshell for aDoc is aExpected or a child of aExpected.
michael@0 730 */
michael@0 731 bool IsChildOfDocShell(nsIDocument* aDoc, nsIDocShellTreeItem* aExpected);
michael@0 732
michael@0 733 // the document the key event listener is attached to
michael@0 734 nsCOMPtr<mozilla::dom::EventTarget> mKeyListener;
michael@0 735
michael@0 736 // widget that is currently listening to rollup events
michael@0 737 nsCOMPtr<nsIWidget> mWidget;
michael@0 738
michael@0 739 // range parent and offset set in SetTriggerEvent
michael@0 740 nsCOMPtr<nsIDOMNode> mRangeParent;
michael@0 741 int32_t mRangeOffset;
michael@0 742 // Device pixels relative to the showing popup's presshell's
michael@0 743 // root prescontext's root frame.
michael@0 744 nsIntPoint mCachedMousePoint;
michael@0 745
michael@0 746 // cached modifiers
michael@0 747 mozilla::Modifiers mCachedModifiers;
michael@0 748
michael@0 749 // set to the currently active menu bar, if any
michael@0 750 nsMenuBarFrame* mActiveMenuBar;
michael@0 751
michael@0 752 // linked list of normal menus and panels.
michael@0 753 nsMenuChainItem* mPopups;
michael@0 754
michael@0 755 // linked list of noautohide panels and tooltips.
michael@0 756 nsMenuChainItem* mNoHidePanels;
michael@0 757
michael@0 758 // timer used for HidePopupAfterDelay
michael@0 759 nsCOMPtr<nsITimer> mCloseTimer;
michael@0 760
michael@0 761 // a popup that is waiting on the timer
michael@0 762 nsMenuPopupFrame* mTimerMenu;
michael@0 763
michael@0 764 // the popup that is currently being opened, stored only during the
michael@0 765 // popupshowing event
michael@0 766 nsCOMPtr<nsIContent> mOpeningPopup;
michael@0 767 };
michael@0 768
michael@0 769 #endif

mercurial