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