tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsFocusManager.h (44952B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef nsFocusManager_h___
      8 #define nsFocusManager_h___
      9 
     10 #include "mozilla/Attributes.h"
     11 #include "mozilla/RefPtr.h"
     12 #include "mozilla/StaticPtr.h"
     13 #include "mozilla/dom/Document.h"
     14 #include "nsCycleCollectionParticipant.h"
     15 #include "nsIContent.h"
     16 #include "nsIFocusManager.h"
     17 #include "nsIObserver.h"
     18 #include "nsWeakReference.h"
     19 
     20 #define FOCUSMANAGER_CONTRACTID "@mozilla.org/focus-manager;1"
     21 
     22 class nsIContent;
     23 class nsPIDOMWindowOuter;
     24 
     25 namespace mozilla {
     26 class PresShell;
     27 namespace dom {
     28 class Element;
     29 class HTMLAreaElement;
     30 struct FocusOptions;
     31 class BrowserParent;
     32 class ContentChild;
     33 class ContentParent;
     34 }  // namespace dom
     35 }  // namespace mozilla
     36 
     37 struct nsDelayedBlurOrFocusEvent;
     38 
     39 /**
     40 * The focus manager keeps track of where the focus is, that is, the node
     41 * which receives key events.
     42 */
     43 
     44 class nsFocusManager final : public nsIFocusManager,
     45                             public nsIObserver,
     46                             public nsSupportsWeakReference {
     47  using InputContextAction = mozilla::widget::InputContextAction;
     48  using Document = mozilla::dom::Document;
     49  friend class mozilla::dom::ContentChild;
     50  friend class mozilla::dom::ContentParent;
     51 
     52 public:
     53  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFocusManager, nsIFocusManager)
     54  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     55  NS_DECL_NSIOBSERVER
     56  NS_DECL_NSIFOCUSMANAGER
     57 
     58  // called to initialize and stop the focus manager at startup and shutdown
     59  static nsresult Init();
     60  static void Shutdown();
     61 
     62  // Simple helper to call SetFocusedWindow on the instance.
     63  //
     64  // This raises the window and switches to the tab as needed.
     65  MOZ_CAN_RUN_SCRIPT static void FocusWindow(
     66      nsPIDOMWindowOuter* aWindow, mozilla::dom::CallerType aCallerType);
     67 
     68  MOZ_CAN_RUN_SCRIPT_BOUNDARY static void PrefChanged(const char* aPref,
     69                                                      void* aSelf);
     70  MOZ_CAN_RUN_SCRIPT void PrefChanged(const char* aPref);
     71 
     72  /**
     73   * Retrieve the single focus manager.
     74   */
     75  static nsFocusManager* GetFocusManager() { return sInstance; }
     76 
     77  /**
     78   * A faster version of nsIFocusManager::GetFocusedElement, returning a
     79   * raw Element pointer (instead of having AddRef-ed Element
     80   * pointer filled in to an out-parameter).
     81   */
     82  mozilla::dom::Element* GetFocusedElement() { return mFocusedElement; }
     83  static mozilla::dom::Element* GetFocusedElementStatic() {
     84    return sInstance ? sInstance->GetFocusedElement() : nullptr;
     85  }
     86 
     87  /**
     88   * Returns true if aContent currently has focus.
     89   */
     90  bool IsFocused(nsIContent* aContent);
     91 
     92  /**
     93   * Returns true if test mode is enabled.
     94   */
     95  bool IsTestMode();
     96 
     97  /**
     98   * Return a focused window. Version of nsIFocusManager::GetFocusedWindow.
     99   */
    100  nsPIDOMWindowOuter* GetFocusedWindow() const { return mFocusedWindow; }
    101  static nsPIDOMWindowOuter* GetFocusedWindowStatic() {
    102    return sInstance ? sInstance->GetFocusedWindow() : nullptr;
    103  }
    104 
    105  /**
    106   * In the chrome process, retrieves the BrowsingContext corresponding
    107   * to GetFocusedWindow(). In a content process, retrieves the
    108   * focused BrowsingContext, which may not belong to this process.
    109   */
    110  mozilla::dom::BrowsingContext* GetFocusedBrowsingContext() const {
    111    if (XRE_IsParentProcess()) {
    112      if (mFocusedWindow) {
    113        return mFocusedWindow->GetBrowsingContext();
    114      }
    115      return nullptr;
    116    }
    117    return mFocusedBrowsingContextInContent;
    118  }
    119 
    120  /**
    121   * Returns whether the given browsing context is in the active window.
    122   */
    123  bool IsInActiveWindow(mozilla::dom::BrowsingContext*) const;
    124 
    125  /**
    126   * Return an active window. Version of nsIFocusManager::GetActiveWindow.
    127   */
    128  nsPIDOMWindowOuter* GetActiveWindow() const { return mActiveWindow; }
    129 
    130  /**
    131   * In the chrome process, retrieves the BrowsingContext corresponding
    132   * to GetActiveWindow(). In a content process, retrieves the
    133   * BrowsingContext of the top-level Web content in the active tab if
    134   * in the same process as the caller or nullptr otherwise.
    135   */
    136  mozilla::dom::BrowsingContext* GetActiveBrowsingContext() const {
    137    if (XRE_IsParentProcess()) {
    138      if (mActiveWindow) {
    139        return mActiveWindow->GetBrowsingContext();
    140      }
    141      return nullptr;
    142    }
    143    return mActiveBrowsingContextInContent;
    144  }
    145 
    146  void ContentInserted(nsIContent* aChild, const ContentInsertInfo& aInfo);
    147 
    148  void ContentAppended(nsIContent* aFirstNewContent,
    149                       const ContentAppendInfo& aInfo);
    150 
    151  /**
    152   * Called when content has been removed.
    153   */
    154  MOZ_CAN_RUN_SCRIPT nsresult ContentRemoved(Document* aDocument,
    155                                             nsIContent* aContent,
    156                                             const ContentRemoveInfo& aInfo);
    157 
    158  void NeedsFlushBeforeEventHandling(mozilla::dom::Element* aElement) {
    159    if (mFocusedElement == aElement) {
    160      mEventHandlingNeedsFlush = true;
    161    }
    162  }
    163 
    164  bool CanSkipFocus(nsIContent* aContent);
    165 
    166  MOZ_CAN_RUN_SCRIPT void FlushBeforeEventHandlingIfNeeded(
    167      nsIContent* aContent) {
    168    if (mEventHandlingNeedsFlush) {
    169      nsCOMPtr<Document> doc = aContent->GetComposedDoc();
    170      if (doc) {
    171        mEventHandlingNeedsFlush = false;
    172        doc->FlushPendingNotifications(mozilla::FlushType::Layout);
    173      }
    174    }
    175  }
    176 
    177  /**
    178   * Update the caret with current mode (whether in caret browsing mode or not).
    179   */
    180  MOZ_CAN_RUN_SCRIPT void UpdateCaretForCaretBrowsingMode();
    181 
    182  /** @see nsIFocusManager.getLastFocusMethod() */
    183  uint32_t GetLastFocusMethod(nsPIDOMWindowOuter*) const;
    184 
    185  /**
    186   * Returns the content node that would be focused if aWindow was in an
    187   * active window. This will traverse down the frame hierarchy, starting at
    188   * the given window aWindow. Sets aFocusedWindow to the window with the
    189   * document containing aFocusedContent. If no element is focused,
    190   * aFocusedWindow may be still be set -- this means that the document is
    191   * focused but no element within it is focused.
    192   *
    193   * aWindow, aFocusIsOutOfProcess, aFocusedWindow must all be non-null.
    194   */
    195  enum SearchRange {
    196    // Return focused content in aWindow.  So, aFocusedWindow is always aWindow.
    197    eOnlyCurrentWindow,
    198    // Return focused content in aWindow or one of all sub windows.
    199    eIncludeAllDescendants,
    200    // Return focused content in aWindow or one of visible sub windows.
    201    eIncludeVisibleDescendants,
    202  };
    203  static mozilla::dom::Element* GetFocusedDescendant(
    204      nsPIDOMWindowOuter* aWindow, SearchRange aSearchRange,
    205      nsPIDOMWindowOuter** aFocusedWindow);
    206 
    207  /**
    208   * Helper function for MoveFocus which determines the next element
    209   * to move the focus to and returns it in aNextContent.
    210   *
    211   * aWindow is the window to adjust the focus within, and aStart is
    212   * the element to start navigation from. For tab key navigation,
    213   * this should be the currently focused element.
    214   *
    215   * aType is the type passed to MoveFocus. If aNoParentTraversal is set,
    216   * navigation is not done to parent documents and iteration returns to the
    217   * beginning (or end) of the starting document.
    218   *
    219   * aNavigateByKey to move focus by keyboard as a side effect of computing the
    220   * next target.
    221   */
    222  MOZ_CAN_RUN_SCRIPT nsresult DetermineElementToMoveFocus(
    223      nsPIDOMWindowOuter* aWindow, nsIContent* aStart, int32_t aType,
    224      bool aNoParentTraversal, bool aNavigateByKey, nsIContent** aNextContent);
    225 
    226  /**
    227   * Setter for focusedWindow with CallerType
    228   */
    229  MOZ_CAN_RUN_SCRIPT nsresult SetFocusedWindowWithCallerType(
    230      mozIDOMWindowProxy* aWindowToFocus, mozilla::dom::CallerType aCallerType);
    231 
    232  /** Given a focused frame loader owner, fix up the focus to be consistent */
    233  MOZ_CAN_RUN_SCRIPT void FixUpFocusAfterFrameLoaderChange(
    234      mozilla::dom::Element&);
    235  /**
    236   * Keep track of whether the focused window is about to go away, and if so fix
    237   * up the focus state so that we can know if we're still focused by the time
    238   * the frame loader swap ends.
    239   */
    240  void FixUpFocusBeforeFrameLoaderChange(mozilla::dom::Element&,
    241                                         mozilla::dom::BrowsingContext* aBc);
    242 
    243  /**
    244   * Raises the top-level window aWindow at the widget level.
    245   */
    246  MOZ_CAN_RUN_SCRIPT void RaiseWindow(nsPIDOMWindowOuter* aWindow,
    247                                      mozilla::dom::CallerType aCallerType,
    248                                      uint64_t aActionId);
    249 
    250  /**
    251   * Called when a window has been raised.
    252   */
    253  MOZ_CAN_RUN_SCRIPT void WindowRaised(mozIDOMWindowProxy* aWindow,
    254                                       uint64_t aActionId);
    255 
    256  /**
    257   * Called when a window has been lowered.
    258   */
    259  MOZ_CAN_RUN_SCRIPT void WindowLowered(mozIDOMWindowProxy* aWindow,
    260                                        uint64_t aActionId);
    261 
    262  /**
    263   * Called when a new document in a window is shown.
    264   *
    265   * If aNeedsFocus is true, then focus events are expected to be fired on the
    266   * window if this window is in the focused window chain.
    267   */
    268  MOZ_CAN_RUN_SCRIPT void WindowShown(mozIDOMWindowProxy* aWindow,
    269                                      bool aNeedsFocus);
    270 
    271  /**
    272   * Called when a document in a window has been hidden or otherwise can no
    273   * longer accept focus.
    274   */
    275  MOZ_CAN_RUN_SCRIPT void WindowHidden(mozIDOMWindowProxy* aWindow,
    276                                       uint64_t aActionId,
    277                                       bool aIsEnteringBFCache);
    278 
    279  /**
    280   * Fire any events that have been delayed due to synchronized actions.
    281   */
    282  MOZ_CAN_RUN_SCRIPT void FireDelayedEvents(Document* aDocument);
    283 
    284  void WasNuked(nsPIDOMWindowOuter* aWindow);
    285 
    286  static uint32_t ProgrammaticFocusFlags(
    287      const mozilla::dom::FocusOptions& aOptions);
    288 
    289  /**
    290   * Returns an InputContextAction cause for aFlags.
    291   */
    292  static InputContextAction::Cause GetFocusMoveActionCause(uint32_t aFlags);
    293 
    294  /**
    295   * Notify of re-focus to same element.
    296   *
    297   * aElement is focused element.
    298   */
    299  MOZ_CAN_RUN_SCRIPT void NotifyOfReFocus(mozilla::dom::Element& aElement);
    300 
    301  static void MarkUncollectableForCCGeneration(uint32_t aGeneration);
    302 
    303  struct BlurredElementInfo {
    304    const mozilla::OwningNonNull<mozilla::dom::Element> mElement;
    305 
    306    explicit BlurredElementInfo(mozilla::dom::Element&);
    307    ~BlurredElementInfo();
    308  };
    309 
    310 protected:
    311  nsFocusManager();
    312  ~nsFocusManager();
    313 
    314  /**
    315   * Ensure that the widget associated with the currently focused window is
    316   * focused at the widget level.
    317   */
    318  void EnsureCurrentWidgetFocused(mozilla::dom::CallerType aCallerType);
    319 
    320  /**
    321   * Focus the last focused element in aWindow, after aWindow was raised (or if
    322   * aWindow was already raised).
    323   */
    324  MOZ_CAN_RUN_SCRIPT void MoveFocusToWindowAfterRaise(nsPIDOMWindowOuter*,
    325                                                      uint64_t aActionId);
    326 
    327  /**
    328   * Activate or deactivate the window and send the activate/deactivate events.
    329   */
    330  void ActivateOrDeactivate(nsPIDOMWindowOuter* aWindow, bool aActive);
    331 
    332  /**
    333   * Blur whatever is currently focused and focus aNewContent. aFlags is a
    334   * bitmask of the flags defined in nsIFocusManager. If aFocusChanged is
    335   * true, then the focus has actually shifted and the caret position will be
    336   * updated to the new focus, aNewContent will be scrolled into view (unless
    337   * a flag disables this) and the focus method for the window will be updated.
    338   * If aAdjustWidget is false, don't change the widget focus state.
    339   *
    340   * All actual focus changes must use this method to do so. (as opposed
    341   * to those that update the focus in an inactive window for instance).
    342   *
    343   * Returns Nothing() if we end up not trying to focus the element,
    344   * otherwise returns the generated action id.
    345   */
    346  MOZ_CAN_RUN_SCRIPT mozilla::Maybe<uint64_t> SetFocusInner(
    347      mozilla::dom::Element* aNewContent, int32_t aFlags, bool aFocusChanged,
    348      bool aAdjustWidget);
    349 
    350  /**
    351   * Returns true if aPossibleAncestor is the same as aWindow or an
    352   * ancestor of aWindow.
    353   */
    354  bool IsSameOrAncestor(nsPIDOMWindowOuter* aPossibleAncestor,
    355                        nsPIDOMWindowOuter* aWindow) const;
    356  bool IsSameOrAncestor(nsPIDOMWindowOuter* aPossibleAncestor,
    357                        mozilla::dom::BrowsingContext* aContext) const;
    358  bool IsSameOrAncestor(mozilla::dom::BrowsingContext* aPossibleAncestor,
    359                        nsPIDOMWindowOuter* aWindow) const;
    360 
    361 public:
    362  bool IsSameOrAncestor(mozilla::dom::BrowsingContext* aPossibleAncestor,
    363                        mozilla::dom::BrowsingContext* aContext) const;
    364 
    365 protected:
    366  /**
    367   * Returns the window that is the lowest common ancestor of both aWindow
    368   * and aContext, or null if they share no common ancestor.
    369   */
    370  mozilla::dom::BrowsingContext* GetCommonAncestor(
    371      nsPIDOMWindowOuter* aWindow, mozilla::dom::BrowsingContext* aContext);
    372 
    373  /**
    374   * When aBrowsingContext is focused or blurred, adjust the ancestors of
    375   * aBrowsingContext so that they also have their corresponding frames focused
    376   * or blurred. Thus, one can start at the active top-level window and navigate
    377   * down the currently focused elements for each frame in the tree to get to
    378   * aBrowsingContext.
    379   */
    380  MOZ_CAN_RUN_SCRIPT bool AdjustInProcessWindowFocus(
    381      mozilla::dom::BrowsingContext* aBrowsingContext, bool aCheckPermission,
    382      bool aIsVisible, uint64_t aActionId, bool aShouldClearAncestorFocus,
    383      mozilla::dom::BrowsingContext* aAncestorBrowsingContextToFocus);
    384 
    385  MOZ_CAN_RUN_SCRIPT void AdjustWindowFocus(
    386      mozilla::dom::BrowsingContext* aBrowsingContext, bool aCheckPermission,
    387      bool aIsVisible, uint64_t aActionId, bool aShouldClearAncestorFocus,
    388      mozilla::dom::BrowsingContext* aAncestorBrowsingContextToFocus);
    389 
    390  /**
    391   * Returns true if aWindow is visible.
    392   */
    393  bool IsWindowVisible(nsPIDOMWindowOuter* aWindow);
    394 
    395  /**
    396   * Returns true if aContent is a root element and not focusable.
    397   * I.e., even if aContent is editable root element, this returns true when
    398   * the document is in designMode.
    399   *
    400   * @param aContent must not be null and must be in a document.
    401   */
    402  bool IsNonFocusableRoot(nsIContent* aContent);
    403 
    404  /**
    405   * First flushes the pending notifications to ensure the PresShell and frames
    406   * are updated.
    407   * Checks and returns aElement if it may be focused, another element node if
    408   * the focus should be retargeted at another node, or null if the node
    409   * cannot be focused. aFlags are the flags passed to SetFocus and similar
    410   * methods.
    411   *
    412   * An element is focusable if it is in a document, the document isn't in
    413   * print preview mode and the element has an nsIFrame where the
    414   * IsFocusable method returns true. For <area> elements, there is no
    415   * frame, so only the IsFocusable method on the content node must be
    416   * true.
    417   */
    418  MOZ_CAN_RUN_SCRIPT mozilla::dom::Element* FlushAndCheckIfFocusable(
    419      mozilla::dom::Element* aElement, uint32_t aFlags);
    420 
    421  /**
    422   * Blurs the currently focused element. Returns false if another element was
    423   * focused as a result. This would mean that the caller should not proceed
    424   * with a pending call to Focus. Normally, true would be returned.
    425   *
    426   * The currently focused element within aBrowsingContextToClear will be
    427   * cleared. aBrowsingContextToClear may be null, which means that no window is
    428   * cleared. This will be the case, for example, when lowering a window, as we
    429   * want to fire a blur, but not actually change what element would be focused,
    430   * so that the same element will be focused again when the window is raised.
    431   *
    432   * aAncestorBrowsingContextToFocus should be set to the common ancestor of the
    433   * window that is being blurred and the window that is going to focused, when
    434   * switching focus to a sibling window.
    435   *
    436   * aIsLeavingDocument should be set to true if the document/window is being
    437   * blurred as well. Document/window blur events will be fired. It should be
    438   * false if an element is the same document is about to be focused.
    439   *
    440   * If aAdjustWidget is false, don't change the widget focus state.
    441   */
    442  MOZ_CAN_RUN_SCRIPT bool Blur(
    443      mozilla::dom::BrowsingContext* aBrowsingContextToClear,
    444      mozilla::dom::BrowsingContext* aAncestorBrowsingContextToFocus,
    445      bool aIsLeavingDocument, bool aAdjustWidget, bool aRemainActive,
    446      uint64_t aActionId, mozilla::dom::Element* aElementToFocus = nullptr);
    447  MOZ_CAN_RUN_SCRIPT void BlurFromOtherProcess(
    448      mozilla::dom::BrowsingContext* aFocusedBrowsingContext,
    449      mozilla::dom::BrowsingContext* aBrowsingContextToClear,
    450      mozilla::dom::BrowsingContext* aAncestorBrowsingContextToFocus,
    451      bool aIsLeavingDocument, bool aAdjustWidget, uint64_t aActionId);
    452  MOZ_CAN_RUN_SCRIPT bool BlurImpl(
    453      mozilla::dom::BrowsingContext* aBrowsingContextToClear,
    454      mozilla::dom::BrowsingContext* aAncestorBrowsingContextToFocus,
    455      bool aIsLeavingDocument, bool aAdjustWidget, bool aRemainActive,
    456      mozilla::dom::Element* aElementToFocus, uint64_t aActionId);
    457 
    458  /**
    459   * Focus an element in the active window and child frame.
    460   *
    461   * aWindow is the window containing the element aContent to focus.
    462   *
    463   * aFlags is the flags passed to the various focus methods in
    464   * nsIFocusManager.
    465   *
    466   * aIsNewDocument should be true if a new document is being focused.
    467   * Document/window focus events will be fired.
    468   *
    469   * aFocusChanged should be true if a new content node is being focused, so
    470   * the focused content will be scrolled into view and the caret position
    471   * will be updated. If false is passed, then a window is simply being
    472   * refocused, for instance, due to a window being raised, or a tab is being
    473   * switched to.
    474   *
    475   * If aFocusChanged is true, then the focus has moved to a new location.
    476   * Otherwise, the focus is just being updated because the window was
    477   * raised.
    478   *
    479   * aWindowRaised should be true if the window is being raised. In this case,
    480   * command updaters will not be called.
    481   *
    482   * If aAdjustWidget is false, don't change the widget focus state.
    483   */
    484  MOZ_CAN_RUN_SCRIPT void Focus(
    485      nsPIDOMWindowOuter* aWindow, mozilla::dom::Element* aContent,
    486      uint32_t aFlags, bool aIsNewDocument, bool aFocusChanged,
    487      bool aWindowRaised, bool aAdjustWidget, uint64_t aActionId,
    488      const mozilla::Maybe<BlurredElementInfo>& = mozilla::Nothing());
    489 
    490  /**
    491   * Send a focus or blur event at aTarget. It may be added to the delayed
    492   * event queue if the document is suppressing events.
    493   *
    494   * aEventMessage should be either eFocus or eBlur.
    495   *
    496   * aWindowRaised should only be true if called from WindowRaised.
    497   */
    498  MOZ_CAN_RUN_SCRIPT void SendFocusOrBlurEvent(
    499      mozilla::EventMessage aEventMessage, mozilla::PresShell* aPresShell,
    500      Document* aDocument, mozilla::dom::EventTarget* aTarget,
    501      bool aWindowRaised, bool aIsRefocus = false,
    502      mozilla::dom::EventTarget* aRelatedTarget = nullptr);
    503  /**
    504   * Fire a focus or blur event at aTarget.
    505   *
    506   * aEventMessage should be either eFocus or eBlur.
    507   * For blur events, aFocusMethod should normally be non-zero.
    508   *
    509   * aWindowRaised should only be true if called from WindowRaised.
    510   */
    511  MOZ_CAN_RUN_SCRIPT void FireFocusOrBlurEvent(
    512      mozilla::EventMessage aEventMessage, mozilla::PresShell* aPresShell,
    513      mozilla::dom::EventTarget* aTarget, bool aWindowRaised,
    514      bool aIsRefocus = false,
    515      mozilla::dom::EventTarget* aRelatedTarget = nullptr);
    516 
    517  /**
    518   *  Fire a focusin or focusout event
    519   *
    520   *  aEventMessage should be either eFocusIn or eFocusOut.
    521   *
    522   *  aTarget is the content the event will fire on (the object that gained
    523   *  focus for focusin, the object blurred for focusout).
    524   *
    525   *  aCurrentFocusedWindow is the window focused before the focus/blur event
    526   *  was fired.
    527   *
    528   *  aCurrentFocusedContent is the content focused before the focus/blur event
    529   *  was fired.
    530   *
    531   *  aRelatedTarget is the content related to the event (the object
    532   *  losing focus for focusin, the object getting focus for focusout).
    533   */
    534  MOZ_CAN_RUN_SCRIPT void FireFocusInOrOutEvent(
    535      mozilla::EventMessage aEventMessage, mozilla::PresShell* aPresShell,
    536      mozilla::dom::EventTarget* aTarget,
    537      nsPIDOMWindowOuter* aCurrentFocusedWindow,
    538      nsIContent* aCurrentFocusedContent,
    539      mozilla::dom::EventTarget* aRelatedTarget = nullptr);
    540 
    541  /**
    542   * Scrolls aContent into view unless the FLAG_NOSCROLL flag is set.
    543   */
    544  MOZ_CAN_RUN_SCRIPT
    545  void ScrollIntoView(mozilla::PresShell* aPresShell, nsIContent* aContent,
    546                      uint32_t aFlags);
    547 
    548  /**
    549   * Updates the caret positon and visibility to match the focus.
    550   *
    551   * aMoveCaretToFocus should be true to move the caret to aContent.
    552   *
    553   * aUpdateVisibility should be true to update whether the caret is
    554   * visible or not.
    555   */
    556  MOZ_CAN_RUN_SCRIPT void UpdateCaret(bool aMoveCaretToFocus,
    557                                      bool aUpdateVisibility,
    558                                      nsIContent* aContent);
    559 
    560  /**
    561   * Helper method to move the caret to the focused element aContent.
    562   */
    563  MOZ_CAN_RUN_SCRIPT void MoveCaretToFocus(mozilla::PresShell* aPresShell,
    564                                           nsIContent* aContent);
    565 
    566  /**
    567   * Makes the caret visible or not, depending on aVisible.
    568   */
    569  nsresult SetCaretVisible(mozilla::PresShell* aPresShell, bool aVisible,
    570                           nsIContent* aContent);
    571 
    572  // the remaining functions are used for tab key and document-navigation
    573 
    574  /**
    575   * Retrieves the start and end points of the current selection for
    576   * aDocument and stores them in aStartContent and aEndContent.
    577   */
    578  void GetSelectionLocation(Document* aDocument, mozilla::PresShell* aPresShell,
    579                            nsIContent** aStartContent,
    580                            nsIContent** aEndContent);
    581 
    582  /**
    583   * Retrieve the next tabbable element in scope owned by aOwner, using
    584   * focusability and tabindex to determine the tab order.
    585   *
    586   * aOwner is the owner of scope to search in.
    587   *
    588   * aStartContent is the starting point for this call of this method.
    589   *
    590   * aOriginalStartContent is the initial starting point for sequential
    591   * navigation.
    592   *
    593   * aForward should be true for forward navigation or false for backward
    594   * navigation.
    595   *
    596   * aCurrentTabIndex is the current tabindex.
    597   *
    598   * aIgnoreTabIndex to ignore the current tabindex and find the element
    599   * irrespective or the tab index.
    600   *
    601   * aForDocumentNavigation informs whether we're navigating only through
    602   * documents.
    603   *
    604   * aSkipOwner to skip owner while searching. The flag is set when caller is
    605   * |GetNextTabbableContent| in order to let caller handle owner.
    606   *
    607   * aReachedToEndForDocumentNavigation is true when this is a document
    608   * navigation and the focus algorithm has reached to the end of the top-level
    609   * document.
    610   *
    611   * NOTE:
    612   *   Consider the method searches downwards in flattened subtree
    613   *   rooted at aOwner.
    614   */
    615  MOZ_CAN_RUN_SCRIPT nsIContent* GetNextTabbableContentInScope(
    616      nsIContent* aOwner, nsIContent* aStartContent,
    617      nsIContent* aOriginalStartContent, bool aForward,
    618      int32_t aCurrentTabIndex, bool aIgnoreTabIndex,
    619      bool aForDocumentNavigation, bool aNavigateByKey, bool aSkipOwner,
    620      bool aReachedToEndForDocumentNavigation);
    621 
    622  /**
    623   * Retrieve the next tabbable element in scope including aStartContent
    624   * and the scope's ancestor scopes, using focusability and tabindex to
    625   * determine the tab order.
    626   *
    627   * aStartOwner is the scope owner of the aStartContent.
    628   *
    629   * aStartContent an in/out paremeter. It as input is the starting point
    630   * for this call of this method; as output it is the shadow host in
    631   * light DOM if the next tabbable element is not found in shadow DOM,
    632   * in order to continue searching in light DOM.
    633   *
    634   * aOriginalStartContent is the initial starting point for sequential
    635   * navigation.
    636   *
    637   * aForward should be true for forward navigation or false for backward
    638   * navigation.
    639   *
    640   * aCurrentTabIndex returns tab index of shadow host in light DOM if the
    641   * next tabbable element is not found in shadow DOM, in order to continue
    642   * searching in light DOM.
    643   *
    644   * aIgnoreTabIndex to ignore the current tabindex and find the element
    645   * irrespective or the tab index.
    646   *
    647   * aForDocumentNavigation informs whether we're navigating only through
    648   * documents.
    649   *
    650   * aNavigateByKey to move focus by keyboard as a side effect of computing the
    651   * next target.
    652   *
    653   * aReachedToEndForDocumentNavigation is true when this is a document
    654   * navigation and the focus algorithm has reached to the end of the top-level
    655   * document.
    656   *
    657   * NOTE:
    658   *   Consider the method searches upwards in all shadow host- or slot-rooted
    659   *   flattened subtrees that contains aStartContent as non-root, except
    660   *   the flattened subtree rooted at shadow host in light DOM.
    661   */
    662  MOZ_CAN_RUN_SCRIPT nsIContent* GetNextTabbableContentInAncestorScopes(
    663      nsIContent* aStartOwner, nsCOMPtr<nsIContent>& aStartContent /* inout */,
    664      nsIContent* aOriginalStartContent, bool aForward,
    665      int32_t* aCurrentTabIndex, bool* aIgnoreTabIndex,
    666      bool aForDocumentNavigation, bool aNavigateByKey,
    667      bool aReachedToEndForDocumentNavigation);
    668 
    669  /**
    670   * Retrieve the next tabbable element within a document, using focusability
    671   * and tabindex to determine the tab order. The element is returned in
    672   * aResultContent.
    673   *
    674   * aRootContent is the root node -- nodes above this will not be examined.
    675   * Typically this will be the root node of a document, but could also be
    676   * a popup node.
    677   *
    678   * aOriginalStartContent is the content which was originally the starting
    679   * node, in the case of recursive or looping calls.
    680   *
    681   * aStartContent is the starting point for this call of this method.
    682   * If aStartContent doesn't have visual representation, the next content
    683   * object, which does have a primary frame, will be used as a start.
    684   * If that content object is focusable, the method may return it.
    685   *
    686   * aForward should be true for forward navigation or false for backward
    687   * navigation.
    688   *
    689   * aCurrentTabIndex is the current tabindex.
    690   *
    691   * aIgnoreTabIndex to ignore the current tabindex and find the element
    692   * irrespective or the tab index. This will be true when a selection is
    693   * active, since we just want to focus the next element in tree order
    694   * from where the selection is. Similarly, if the starting element isn't
    695   * focusable, since it doesn't really have a defined tab index.
    696   *
    697   * aSkipPopover should be true to avoid an invoker triggering to step into
    698   * the popover that was already been visited again.
    699   *
    700   * aNavigateByKey to move focus by keyboard as a side effect of computing the
    701   * next target.
    702   *
    703   * aReachedToEndForDocumentNavigation is true when this is a document
    704   * navigation and the focus algorithm has reached to the end of the top-level
    705   * document.
    706   */
    707  MOZ_CAN_RUN_SCRIPT nsresult GetNextTabbableContent(
    708      mozilla::PresShell* aPresShell, nsIContent* aRootContent,
    709      nsIContent* aOriginalStartContent, nsIContent* aStartContent,
    710      bool aForward, int32_t aCurrentTabIndex, bool aIgnoreTabIndex,
    711      bool aForDocumentNavigation, bool aNavigateByKey, bool aSkipPopover,
    712      bool aReachedToEndForDocumentNavigation, nsIContent** aResultContent);
    713 
    714  /**
    715   * Get the next tabbable image map area and returns it.
    716   *
    717   * aForward should be true for forward navigation or false for backward
    718   * navigation.
    719   *
    720   * aCurrentTabIndex is the current tabindex.
    721   *
    722   * aImageContent is the image.
    723   *
    724   * aStartContent is the current image map area.
    725   */
    726  nsIContent* GetNextTabbableMapArea(bool aForward, int32_t aCurrentTabIndex,
    727                                     mozilla::dom::Element* aImageContent,
    728                                     nsIContent* aStartContent);
    729 
    730  /**
    731   * Return the next valid tabindex value after aCurrentTabIndex, if aForward
    732   * is true, or the previous tabindex value if aForward is false. aParent is
    733   * the node from which to start looking for tab indicies.
    734   */
    735  int32_t GetNextTabIndex(nsIContent* aParent, int32_t aCurrentTabIndex,
    736                          bool aForward);
    737 
    738  /**
    739   * Focus the first focusable content within the document with a root node of
    740   * aRootContent. For content documents, this will be aRootContent itself, but
    741   * for chrome documents, this will locate the next focusable content.
    742   *
    743   * aReachedToEndForDocumentNavigation is true when the focus algorithm has
    744   * reached to the end of the top-level document.
    745   */
    746  MOZ_CAN_RUN_SCRIPT nsresult
    747  FocusFirst(mozilla::dom::Element* aRootContent, nsIContent** aNextContent,
    748             bool aReachedToEndForDocumentNavigation);
    749 
    750  /**
    751   * Retrieves and returns the root node from aDocument to be focused. Will
    752   * return null if the root node cannot be focused. There are several reasons
    753   * for this:
    754   *
    755   * - if aForDocumentNavigation is false and aWindow is a chrome shell.
    756   * - if aCheckVisibility is true and the aWindow is not visible.
    757   * - if aDocument is a frameset document.
    758   */
    759  mozilla::dom::Element* GetRootForFocus(nsPIDOMWindowOuter* aWindow,
    760                                         Document* aDocument,
    761                                         bool aForDocumentNavigation,
    762                                         bool aCheckVisibility);
    763 
    764  /**
    765   * Retrieves and returns the root node as with GetRootForFocus but only if
    766   * aContent is a frame with a valid child document.
    767   */
    768  mozilla::dom::Element* GetRootForChildDocument(nsIContent* aContent);
    769 
    770  /**
    771   * Retreives a focusable element within the current selection of aWindow.
    772   * Currently, this only detects links.
    773   *
    774   * This is used when MoveFocus is called with a type of MOVEFOCUS_CARET,
    775   * which is used, for example, to focus links as the caret is moved over
    776   * them.
    777   */
    778  void GetFocusInSelection(nsPIDOMWindowOuter* aWindow,
    779                           nsIContent* aStartSelection,
    780                           nsIContent* aEndSelection,
    781                           nsIContent** aFocusedContent);
    782 
    783 private:
    784  /**
    785   * Given an element, which must be the focused element, activate the remote
    786   * frame it embeds, if any.
    787   */
    788  void ActivateRemoteFrameIfNeeded(mozilla::dom::Element&, uint64_t aActionId);
    789 
    790  // Notify that the focus state of aElement has changed.  Note that we need to
    791  // pass in whether the window should show a focus ring before the
    792  // SetFocusedNode call on it happened when losing focus and after the
    793  // SetFocusedNode call when gaining focus, which is why that information needs
    794  // to be an explicit argument instead of just passing in the window and asking
    795  // it whether it should show focus rings: in the losing focus case that
    796  // information could be wrong.
    797  //
    798  // aShouldShowFocusRing is only relevant if aGettingFocus is true.
    799  static void NotifyFocusStateChange(mozilla::dom::Element* aElement,
    800                                     mozilla::dom::Element* aElementToFocus,
    801                                     int32_t aFlags, bool aGettingFocus,
    802                                     bool aShouldShowFocusRing);
    803 
    804  void SetFocusedWindowInternal(nsPIDOMWindowOuter* aWindow, uint64_t aActionId,
    805                                bool aSyncBrowsingContext = true);
    806 
    807  MOZ_CAN_RUN_SCRIPT bool TryDocumentNavigation(nsIContent* aCurrentContent,
    808                                                bool* aCheckSubDocument,
    809                                                nsIContent** aResultContent);
    810 
    811  MOZ_CAN_RUN_SCRIPT bool TryToMoveFocusToSubDocument(
    812      nsIContent* aCurrentContent, nsIContent* aOriginalStartContent,
    813      bool aForward, bool aForDocumentNavigation, bool aNavigateByKey,
    814      bool aReachedToEndForDocumentNavigation, nsIContent** aResultContent);
    815 
    816  // Sets the focused BrowsingContext and, if appropriate, syncs it to
    817  // other processes.
    818  void SetFocusedBrowsingContext(mozilla::dom::BrowsingContext* aContext,
    819                                 uint64_t aActionId);
    820 
    821  // Content-only
    822  // Called when receiving an IPC message about another process setting
    823  // the focused BrowsingContext.
    824  void SetFocusedBrowsingContextFromOtherProcess(
    825      mozilla::dom::BrowsingContext* aContext, uint64_t aActionId);
    826 
    827  // Chrome-only
    828  // When returning true, sets the chrome process notion of what
    829  // BrowsingContext is focused in content. When returning false,
    830  // ignores the attempt to set as out-of-sequence.
    831  bool SetFocusedBrowsingContextInChrome(
    832      mozilla::dom::BrowsingContext* aContext, uint64_t aActionId);
    833 
    834  void InsertNewFocusActionId(uint64_t aActionId);
    835 
    836  bool ProcessPendingActiveBrowsingContextActionId(uint64_t aActionId,
    837                                                   bool aSettingToNonNull);
    838 
    839  bool ProcessPendingFocusedBrowsingContextActionId(uint64_t aActionId);
    840 
    841 public:
    842  // Chrome-only
    843  // Gets the chrome process notion of what BrowsingContext is focused
    844  // in content.
    845  mozilla::dom::BrowsingContext* GetFocusedBrowsingContextInChrome();
    846 
    847  // Chrome-only
    848  // Notifies the focus manager that BrowsingContext::Detach was called
    849  // on a BrowsingContext so that pointers to it can be forgotten.
    850  void BrowsingContextDetached(mozilla::dom::BrowsingContext* aContext);
    851 
    852 private:
    853  // Content-only
    854  // Sets the BrowsingContext corresponding to top-level Web content
    855  // in the frontmost tab if focus is in Web content.
    856  void SetActiveBrowsingContextInContent(
    857      mozilla::dom::BrowsingContext* aContext, uint64_t aActionId,
    858      bool aIsEnteringBFCache);
    859 
    860  // Content-only
    861  // Receives notification of another process setting the top-level Web
    862  // content as being in the frontmost tab with focus in Web content.
    863  void SetActiveBrowsingContextFromOtherProcess(
    864      mozilla::dom::BrowsingContext* aContext, uint64_t aActionId);
    865 
    866  // Content-only
    867  // Receives notification that another process determined that focus
    868  // moved to chrome so a particular BrowsingContext is no longer the
    869  // "active" one.
    870  void UnsetActiveBrowsingContextFromOtherProcess(
    871      mozilla::dom::BrowsingContext* aContext, uint64_t aActionId);
    872 
    873  // Content-only
    874  // Receives a notification from parent that this content process's
    875  // attempt to set the active browsing context was late and the
    876  // prevailing browsing context is instead the second argument of
    877  // this method call. This should be ignored if the first argument
    878  // doesn't match the latest action id associated with setting the
    879  // active browsing context in this process, because in that case,
    880  // this revision is late.
    881  void ReviseActiveBrowsingContext(uint64_t aOldActionId,
    882                                   mozilla::dom::BrowsingContext* aContext,
    883                                   uint64_t aNewActionId);
    884 
    885  // Receives a notification from parent that this content process's
    886  // attempt to set the focused browsing context was late and the
    887  // prevailing browsing context is instead the second argument of
    888  // this method call. This should be ignored if the first argument
    889  // doesn't match the latest action id associated with setting the
    890  // active browsing context in this process, because in that case,
    891  // this revision is late.
    892  void ReviseFocusedBrowsingContext(uint64_t aOldActionId,
    893                                    mozilla::dom::BrowsingContext* aContext,
    894                                    uint64_t aNewActionId);
    895 
    896  // Chrome-only
    897  // Sets the chrome process notion of what content believes to be
    898  // the top-level BrowsingContext in the frontmost tab when focus
    899  // is in Web content.
    900  // Returns true if set and false if ignored.
    901  bool SetActiveBrowsingContextInChrome(mozilla::dom::BrowsingContext* aContext,
    902                                        uint64_t aActionId);
    903 
    904  void FocusedElementMayHaveMoved(nsIContent* aContent, nsINode* aOldParent);
    905 
    906 public:
    907  // Chrome-only
    908  // Gets the chrome process notion of what content believes to be
    909  // the top-level BrowsingContext in the frontmost tab when focus
    910  // is in Web content.
    911  mozilla::dom::BrowsingContext* GetActiveBrowsingContextInChrome();
    912 
    913  uint64_t GetActionIdForActiveBrowsingContextInChrome() const;
    914 
    915  uint64_t GetActionIdForFocusedBrowsingContextInChrome() const;
    916 
    917  static uint64_t GenerateFocusActionId();
    918 
    919  // This function works very similar to
    920  // https://html.spec.whatwg.org/#get-the-focusable-area
    921  static mozilla::dom::Element* GetTheFocusableArea(
    922      mozilla::dom::Element* aTarget, uint32_t aFlags);
    923 
    924  // Returns true if it's an area element with one or more shapes that are
    925  // focusable areas.
    926  static bool IsAreaElementFocusable(mozilla::dom::HTMLAreaElement& aArea);
    927 
    928 private:
    929  // In the chrome process, the currently active and front-most top-most
    930  // window. Not supposed to be used in a meaningful way in content
    931  // processes. For legacy reasons, this exists as a separate field
    932  // instead of being derived from mFocusedWindow when needed, because
    933  // the defined relation that mActiveWindow is supposed to be the same
    934  // as or ancestor of mFocusedWindow is temporarily broken when a
    935  // window is being raised or lowered.
    936  nsCOMPtr<nsPIDOMWindowOuter> mActiveWindow;
    937 
    938  // In a content process, the BrowsingContext corresponding to top-level
    939  // Web content in the active tab or nullptr if focus is not in a
    940  // BrowsingContextGroup that this process participates in. Synced
    941  // across processes in a BrowsingContextGroup. This field exists
    942  // separately from mFocusedBrowsingContextInContent instead of being being
    943  // derived from it, because for legacy reasons the relation
    944  // mFocusedBrowsingContextInContent->Top() == mActiveBrowsingContextInContent
    945  // is temporarily broken when a window is being raised or lowered.
    946  // Not supposed to be used in a meaningful way in the chrome process.
    947  RefPtr<mozilla::dom::BrowsingContext> mActiveBrowsingContextInContent;
    948 
    949  // If this content process set mActiveBrowsingContextInContent, this
    950  // field holds the corresponding actionId so that
    951  // mActiveBrowsingContextInContent can be revised of the parent rejects
    952  // the update. This field is used for accepting revisions only if nothing
    953  // else has updated mActiveBrowsingContextInContent before the revision
    954  // arrives.
    955  uint64_t mActionIdForActiveBrowsingContextInContent;
    956 
    957  uint64_t mActionIdForActiveBrowsingContextInChrome;
    958 
    959  // If this content process set mFocusedBrowsingContextInContent, this
    960  // field holds the corresponding actionId so that
    961  // mFocusedBrowsingContextInContent can be revised of the parent rejects
    962  // the update. This field is used for accepting revisions only if nothing
    963  // else has updated mFocusedBrowsingContextInContent before the revision
    964  // arrives.
    965  uint64_t mActionIdForFocusedBrowsingContextInContent;
    966 
    967  uint64_t mActionIdForFocusedBrowsingContextInChrome;
    968 
    969  // Whether or not mActiveBrowsingContextInContent was set from another process
    970  // or from this process.
    971  bool mActiveBrowsingContextInContentSetFromOtherProcess;
    972 
    973  // This is the chrome process notion of content's
    974  // mActiveBrowsingContextInContent. Avoiding field reuse for different
    975  // semantics in different process types to make it easier to catch bugs.
    976  RefPtr<mozilla::dom::BrowsingContext> mActiveBrowsingContextInChrome;
    977 
    978  // the child or top-level window that is currently focused. In the chrome
    979  // process, when a window isn't being raised or lowered, this window will
    980  // either be the same window as mActiveWindow or a descendant of it.
    981  // Except during shutdown use SetFocusedWindowInternal to set mFocusedWindow!
    982  nsCOMPtr<nsPIDOMWindowOuter> mFocusedWindow;
    983 
    984  // The focused BrowsingContext if this is a chrome process and focus is
    985  // in chrome or if this is a content process and focus is in Web content
    986  // in this BrowsingContextGroup. nullptr otherwise.
    987  // Except during shutdown, must be set via SetFocusedWindowInternal which
    988  // calls SetFocusedBrowsingContext or if the value is coming in via IPC
    989  // via SetFocusedBrowsingContextFromOtherProcess.
    990  RefPtr<mozilla::dom::BrowsingContext> mFocusedBrowsingContextInContent;
    991 
    992  // This is the chrome process notion of content's
    993  // mFocusedBrowsingContextInContent. Avoiding field reuse for different
    994  // semantics in different process types to make it easier to catch bugs.
    995  RefPtr<mozilla::dom::BrowsingContext> mFocusedBrowsingContextInChrome;
    996 
    997  // the currently focused content if in-process or the XUL browser in which
    998  // Web content focus resides. Always inside mFocusedWindow. When a window
    999  // isn't being raised or lowered, this is a cached copy of the
   1000  // mFocusedWindow's current content. This may be null if no content is
   1001  // focused.
   1002  RefPtr<mozilla::dom::Element> mFocusedElement;
   1003 
   1004  // keep track of a window while it is being lowered
   1005  nsCOMPtr<nsPIDOMWindowOuter> mWindowBeingLowered;
   1006 
   1007  // synchronized actions cannot be interrupted with events, so queue these up
   1008  // and fire them later.
   1009  nsTArray<nsDelayedBlurOrFocusEvent> mDelayedBlurFocusEvents;
   1010 
   1011  // Array of focus action ids for which we haven't seen an active browsing
   1012  // context set yet. As set is allowed to overwrite an unset. Therefore,
   1013  // an unset removes earlier ids but not the matching id. A set removes
   1014  // earlier ids and the matching id.
   1015  //
   1016  // Conceptually, active browsing context shouldn't have to exist as a
   1017  // field, because it should be possible to always derive it from the
   1018  // focused browsing context. Unfortunately, for legacy reasons, this
   1019  // is not the case while a window is being raised or lowered.
   1020  //
   1021  // Conceptually, it should be possible for the parent to manage the
   1022  // active browsing context. Unfortunately, for legacy reasons, the
   1023  // code for setting the active browsing context needs to reside in
   1024  // the content process to retain the existing and test-passing code
   1025  // flow.
   1026  //
   1027  // This, obviously, raises the issue of content processes racing to
   1028  // set the active browsing context. In particular, there is a pattern
   1029  // that the parent initiates actions that cause multiple content
   1030  // processes to mutate the active browsing context at almost the
   1031  // same time. When two native browser windows change order, the
   1032  // lowering isn't distinguished from the case of lowering the
   1033  // entire app. For this reason, the owner of the previous active
   1034  // browsing context tries to unset it and at almost the same time
   1035  // the another content process sets a new active browsing context.
   1036  // If the IPC messages for these unset and set actions were to
   1037  // arrive in the wrong order, this could get in the wrong state.
   1038  //
   1039  // To address this issue, the parent manages an authortative order
   1040  // of attempts to (un)set the active browsing context using the
   1041  // array mPendingActiveBrowsingContextActions.
   1042  //
   1043  // A process reserves a slot in the order by calling
   1044  // GenerateFocusActionId(). Per one call to GenerateFocusActionId(),
   1045  // there may be at most one action to set the active browsing context
   1046  // to a new value. There may be logically prior attempts to unset it
   1047  // (i.e. set it to nullptr). That is, if there are both attempts to
   1048  // unset and set the active browsing context with the same action id,
   1049  // the attempt to set to a non-null value wins.
   1050  //
   1051  // The completion of an action from reserting the slot in the order
   1052  // and actually performing the setting of the active browsing context
   1053  // may span multiple processes and IPC messages.
   1054  //
   1055  // The at-most-once property is not asserted, because the process
   1056  // claiming the position in the order and the process setting the
   1057  // active browsing context with that actionId may be different, and
   1058  // the act of using an actionId to set the active browsing context
   1059  // is used to delete stale items from the array to avoid excessive
   1060  // growth of the array.
   1061  nsTArray<uint64_t> mPendingActiveBrowsingContextActions;
   1062 
   1063  // Like mPendingActiveBrowsingContextActions but for the focused
   1064  // browsing context.
   1065  nsTArray<uint64_t> mPendingFocusedBrowsingContextActions;
   1066 
   1067  // If set to true, layout of the document of the event target should be
   1068  // flushed before handling focus depending events.
   1069  bool mEventHandlingNeedsFlush;
   1070 
   1071  static bool sTestMode;
   1072 
   1073  // Process-specific counter for maintaining the prosess-specific
   1074  // uniqueness of actionIds.
   1075  static uint64_t sFocusActionCounter;
   1076 
   1077  // the single focus manager
   1078  static mozilla::StaticRefPtr<nsFocusManager> sInstance;
   1079 };
   1080 
   1081 nsresult NS_NewFocusManager(nsIFocusManager** aResult);
   1082 
   1083 #endif