LCOV - code coverage report
Current view: directory - objdir/dist/include - nsXULPopupManager.h (source / functions) Found Hit Coverage
Test: app.info Lines: 41 0 0.0 %
Date: 2012-06-02 Functions: 25 0 0.0 %

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

Generated by: LCOV version 1.7