LCOV - code coverage report
Current view: top level - widget - TextEvents.h (source / functions) Hit Total Coverage
Test: output.info Lines: 15 272 5.5 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef mozilla_TextEvents_h__
       7             : #define mozilla_TextEvents_h__
       8             : 
       9             : #include <stdint.h>
      10             : 
      11             : #include "mozilla/Assertions.h"
      12             : #include "mozilla/BasicEvents.h"
      13             : #include "mozilla/CheckedInt.h"
      14             : #include "mozilla/EventForwards.h" // for KeyNameIndex, temporarily
      15             : #include "mozilla/FontRange.h"
      16             : #include "mozilla/TextRange.h"
      17             : #include "mozilla/WritingModes.h"
      18             : #include "mozilla/dom/KeyboardEventBinding.h"
      19             : #include "nsCOMPtr.h"
      20             : #include "nsISelectionController.h"
      21             : #include "nsISelectionListener.h"
      22             : #include "nsITransferable.h"
      23             : #include "nsRect.h"
      24             : #include "nsString.h"
      25             : #include "nsTArray.h"
      26             : 
      27             : class nsStringHashKey;
      28             : template<class, class> class nsDataHashtable;
      29             : 
      30             : /******************************************************************************
      31             :  * virtual keycode values
      32             :  ******************************************************************************/
      33             : 
      34             : enum
      35             : {
      36             : #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) NS_##aDOMKeyName = aDOMKeyCode,
      37             : #include "mozilla/VirtualKeyCodeList.h"
      38             : #undef NS_DEFINE_VK
      39             :   NS_VK_UNKNOWN = 0xFF
      40             : };
      41             : 
      42             : namespace mozilla {
      43             : 
      44             : enum : uint32_t
      45             : {
      46             :   eKeyLocationStandard = dom::KeyboardEventBinding::DOM_KEY_LOCATION_STANDARD,
      47             :   eKeyLocationLeft     = dom::KeyboardEventBinding::DOM_KEY_LOCATION_LEFT,
      48             :   eKeyLocationRight    = dom::KeyboardEventBinding::DOM_KEY_LOCATION_RIGHT,
      49             :   eKeyLocationNumpad   = dom::KeyboardEventBinding::DOM_KEY_LOCATION_NUMPAD
      50             : };
      51             : 
      52             : const nsCString GetDOMKeyCodeName(uint32_t aKeyCode);
      53             : 
      54             : namespace dom {
      55             :   class PBrowserParent;
      56             :   class PBrowserChild;
      57             : } // namespace dom
      58             : namespace plugins {
      59             :   class PPluginInstanceChild;
      60             : } // namespace plugins
      61             : 
      62             : enum class AccessKeyType
      63             : {
      64             :   // Handle access key for chrome.
      65             :   eChrome,
      66             :   // Handle access key for content.
      67             :   eContent,
      68             :   // Don't handle access key.
      69             :   eNone
      70             : };
      71             : 
      72             : /******************************************************************************
      73             :  * mozilla::AlternativeCharCode
      74             :  *
      75             :  * This stores alternative charCode values of a key event with some modifiers.
      76             :  * The stored values proper for testing shortcut key or access key.
      77             :  ******************************************************************************/
      78             : 
      79             : struct AlternativeCharCode
      80             : {
      81           0 :   AlternativeCharCode() :
      82           0 :     mUnshiftedCharCode(0), mShiftedCharCode(0)
      83             :   {
      84             :   }
      85           0 :   AlternativeCharCode(uint32_t aUnshiftedCharCode, uint32_t aShiftedCharCode) :
      86           0 :     mUnshiftedCharCode(aUnshiftedCharCode), mShiftedCharCode(aShiftedCharCode)
      87             :   {
      88             :   }
      89             :   uint32_t mUnshiftedCharCode;
      90             :   uint32_t mShiftedCharCode;
      91             : };
      92             : 
      93             : /******************************************************************************
      94             :  * mozilla::ShortcutKeyCandidate
      95             :  *
      96             :  * This stores a candidate of shortcut key combination.
      97             :  ******************************************************************************/
      98             : 
      99             : struct ShortcutKeyCandidate
     100             : {
     101             :   ShortcutKeyCandidate()
     102           0 :     : mCharCode(0)
     103           0 :     , mIgnoreShift(0)
     104             :   {
     105             :   }
     106             :   ShortcutKeyCandidate(uint32_t aCharCode, bool aIgnoreShift)
     107           0 :     : mCharCode(aCharCode)
     108           0 :     , mIgnoreShift(aIgnoreShift)
     109             :   {
     110             :   }
     111             :   // The mCharCode value which must match keyboard shortcut definition.
     112             :   uint32_t mCharCode;
     113             :   // true if Shift state can be ignored.  Otherwise, Shift key state must
     114             :   // match keyboard shortcut definition.
     115             :   bool mIgnoreShift;
     116             : };
     117             : 
     118             : /******************************************************************************
     119             :  * mozilla::IgnoreModifierState
     120             :  *
     121             :  * This stores flags for modifiers that should be ignored when matching
     122             :  * XBL handlers.
     123             :  ******************************************************************************/
     124             : 
     125             : struct IgnoreModifierState
     126             : {
     127             :   // When mShift is true, Shift key state will be ignored.
     128             :   bool mShift;
     129             :   // When mOS is true, OS key state will be ignored.
     130             :   bool mOS;
     131             : 
     132             :   IgnoreModifierState()
     133           0 :     : mShift(false)
     134           0 :     , mOS(false)
     135             :   {
     136             :   }
     137             : };
     138             : 
     139             : /******************************************************************************
     140             :  * mozilla::WidgetKeyboardEvent
     141             :  ******************************************************************************/
     142             : 
     143           0 : class WidgetKeyboardEvent : public WidgetInputEvent
     144             : {
     145             : private:
     146             :   friend class dom::PBrowserParent;
     147             :   friend class dom::PBrowserChild;
     148             :   friend struct IPC::ParamTraits<WidgetKeyboardEvent>;
     149             : 
     150             : protected:
     151           0 :   WidgetKeyboardEvent()
     152           0 :     : mNativeKeyEvent(nullptr)
     153             :     , mKeyCode(0)
     154             :     , mCharCode(0)
     155             :     , mPseudoCharCode(0)
     156             :     , mLocation(eKeyLocationStandard)
     157             :     , mUniqueId(0)
     158             : #ifdef XP_MACOSX
     159             :     , mNativeModifierFlags(0)
     160             :     , mNativeKeyCode(0)
     161             : #endif // #ifdef XP_MACOSX
     162             :     , mKeyNameIndex(KEY_NAME_INDEX_Unidentified)
     163             :     , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
     164             :     , mIsRepeat(false)
     165             :     , mIsComposing(false)
     166             :     , mIsSynthesizedByTIP(false)
     167             :     , mMaybeSkippableInRemoteProcess(true)
     168             :     , mEditCommandsForSingleLineEditorInitialized(false)
     169             :     , mEditCommandsForMultiLineEditorInitialized(false)
     170           0 :     , mEditCommandsForRichTextEditorInitialized(false)
     171             :   {
     172           0 :   }
     173             : 
     174             : public:
     175           0 :   virtual WidgetKeyboardEvent* AsKeyboardEvent() override { return this; }
     176             : 
     177           0 :   WidgetKeyboardEvent(bool aIsTrusted, EventMessage aMessage,
     178             :                       nsIWidget* aWidget,
     179             :                       EventClassID aEventClassID = eKeyboardEventClass)
     180           0 :     : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
     181             :     , mNativeKeyEvent(nullptr)
     182             :     , mKeyCode(0)
     183             :     , mCharCode(0)
     184             :     , mPseudoCharCode(0)
     185             :     , mLocation(eKeyLocationStandard)
     186             :     , mUniqueId(0)
     187             : #ifdef XP_MACOSX
     188             :     , mNativeModifierFlags(0)
     189             :     , mNativeKeyCode(0)
     190             : #endif // #ifdef XP_MACOSX
     191             :     , mKeyNameIndex(KEY_NAME_INDEX_Unidentified)
     192             :     , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
     193             :     , mIsRepeat(false)
     194             :     , mIsComposing(false)
     195             :     , mIsSynthesizedByTIP(false)
     196             :     , mMaybeSkippableInRemoteProcess(true)
     197             :     , mEditCommandsForSingleLineEditorInitialized(false)
     198             :     , mEditCommandsForMultiLineEditorInitialized(false)
     199           0 :     , mEditCommandsForRichTextEditorInitialized(false)
     200             :   {
     201             :     // If this is a keyboard event on a plugin, it shouldn't fired on content.
     202           0 :     if (IsKeyEventOnPlugin()) {
     203           0 :       mFlags.mOnlySystemGroupDispatchInContent = true;
     204           0 :       StopCrossProcessForwarding();
     205             :     }
     206           0 :   }
     207             : 
     208             :   static bool IsKeyDownOrKeyDownOnPlugin(EventMessage aMessage)
     209             :   {
     210           0 :     return aMessage == eKeyDown || aMessage == eKeyDownOnPlugin;
     211             :   }
     212             :   bool IsKeyDownOrKeyDownOnPlugin() const
     213             :   {
     214           0 :     return IsKeyDownOrKeyDownOnPlugin(mMessage);
     215             :   }
     216             :   static bool IsKeyUpOrKeyUpOnPlugin(EventMessage aMessage)
     217             :   {
     218           0 :     return aMessage == eKeyUp || aMessage == eKeyUpOnPlugin;
     219             :   }
     220             :   bool IsKeyUpOrKeyUpOnPlugin() const
     221             :   {
     222           0 :     return IsKeyUpOrKeyUpOnPlugin(mMessage);
     223             :   }
     224             :   static bool IsKeyEventOnPlugin(EventMessage aMessage)
     225             :   {
     226           0 :     return aMessage == eKeyDownOnPlugin || aMessage == eKeyUpOnPlugin;
     227             :   }
     228             :   bool IsKeyEventOnPlugin() const
     229             :   {
     230           0 :     return IsKeyEventOnPlugin(mMessage);
     231             :   }
     232             : 
     233             :   // IsInputtingText() and IsInputtingLineBreak() are used to check if
     234             :   // it should cause eKeyPress events even on web content.
     235             :   // UI Events defines that "keypress" event should be fired "if and only if
     236             :   // that key normally produces a character value".
     237             :   // <https://www.w3.org/TR/uievents/#event-type-keypress>
     238             :   // Additionally, for backward compatiblity with all existing browsers,
     239             :   // there is a spec issue for Enter key press.
     240             :   // <https://github.com/w3c/uievents/issues/183>
     241           0 :   bool IsInputtingText() const
     242             :   {
     243             :     // NOTE: On some keyboard layout, some characters are inputted with Control
     244             :     //       key or Alt key, but at that time, widget clears the modifier flag
     245             :     //       from eKeyPress event because our TextEditor won't handle eKeyPress
     246             :     //       events as inputting text (bug 1346832).
     247             :     // NOTE: There are some complicated issues of our traditional behavior.
     248             :     //       -- On Windows, KeyboardLayout::WillDispatchKeyboardEvent() clears
     249             :     //       MODIFIER_ALT and MODIFIER_CONTROL of eKeyPress event if it
     250             :     //       should be treated as inputting a character because AltGr is
     251             :     //       represented with both Alt key and Ctrl key are pressed, and
     252             :     //       some keyboard layouts may produces a character with Ctrl key.
     253             :     //       -- On Linux, KeymapWrapper doesn't have this hack since perhaps,
     254             :     //       we don't have any bug reports that user cannot input proper
     255             :     //       character with Alt and/or Ctrl key.
     256             :     //       -- On macOS, IMEInputHandler::WillDispatchKeyboardEvent() clears
     257             :     //       MODIFIER_ALT and MDOFIEIR_CONTROL of eKeyPress event only when
     258             :     //       TextInputHandler::InsertText() has been called for the event.
     259             :     //       I.e., they are cleared only when an editor has focus (even if IME
     260             :     //       is disabled in password field or by |ime-mode: disabled;|) because
     261             :     //       TextInputHandler::InsertText() is called while
     262             :     //       TextInputHandler::HandleKeyDownEvent() calls interpretKeyEvents:
     263             :     //       to notify text input processor of Cocoa (including IME).  In other
     264             :     //       words, when we need to disable IME completey when no editor has
     265             :     //       focus, we cannot call interpretKeyEvents:.  So,
     266             :     //       TextInputHandler::InsertText() won't be called when no editor has
     267             :     //       focus so that neither MODIFIER_ALT nor MODIFIER_CONTROL is
     268             :     //       cleared.  So, fortunately, altKey and ctrlKey values of "keypress"
     269             :     //       events are same as the other browsers only when no editor has
     270             :     //       focus.
     271             :     // NOTE: As mentioned above, for compatibility with the other browsers on
     272             :     //       macOS, we should keep MODIFIER_ALT and MODIFIER_CONTROL flags of
     273             :     //       eKeyPress events when no editor has focus.  However, Alt key,
     274             :     //       labeled "option" on keyboard for Mac, is AltGraph key on the other
     275             :     //       platforms.  So, even if MODIFIER_ALT is set, we need to dispatch
     276             :     //       eKeyPress event even on web content unless mCharCode is 0.
     277             :     //       Therefore, we need to ignore MODIFIER_ALT flag here only on macOS.
     278           0 :     return mMessage == eKeyPress &&
     279           0 :            mCharCode &&
     280           0 :            !(mModifiers & (
     281             : #ifndef XP_MACOSX
     282             :                            // So, ignore MODIFIER_ALT only on macOS since
     283             :                            // option key is used as AltGraph key on macOS.
     284             :                            MODIFIER_ALT |
     285             : #endif // #ifndef XP_MAXOSX
     286             :                            MODIFIER_CONTROL |
     287             :                            MODIFIER_META |
     288           0 :                            MODIFIER_OS));
     289             :   }
     290             : 
     291           0 :   bool IsInputtingLineBreak() const
     292             :   {
     293           0 :     return mMessage == eKeyPress &&
     294           0 :            mKeyNameIndex == KEY_NAME_INDEX_Enter &&
     295           0 :            !(mModifiers & (MODIFIER_ALT |
     296             :                            MODIFIER_CONTROL |
     297             :                            MODIFIER_META |
     298           0 :                            MODIFIER_OS));
     299             :   }
     300             : 
     301             :   /**
     302             :    * ShouldKeyPressEventBeFiredOnContent() should be called only when the
     303             :    * instance is eKeyPress event.  This returns true when the eKeyPress
     304             :    * event should be fired even on content in the default event group.
     305             :    */
     306           0 :   bool ShouldKeyPressEventBeFiredOnContent() const
     307             :   {
     308           0 :     MOZ_DIAGNOSTIC_ASSERT(mMessage == eKeyPress);
     309           0 :     if (IsInputtingText() || IsInputtingLineBreak()) {
     310             :       return true;
     311             :     }
     312             :     // Ctrl + Enter won't cause actual input in our editor.
     313             :     // However, the other browsers fire keypress event in any platforms.
     314             :     // So, for compatibility with them, we should fire keypress event for
     315             :     // Ctrl + Enter too.
     316           0 :     return mMessage == eKeyPress &&
     317           0 :            mKeyNameIndex == KEY_NAME_INDEX_Enter &&
     318           0 :            !(mModifiers & (MODIFIER_ALT |
     319             :                            MODIFIER_META |
     320             :                            MODIFIER_OS |
     321             :                            MODIFIER_SHIFT));
     322             :   }
     323             : 
     324           0 :   virtual WidgetEvent* Duplicate() const override
     325             :   {
     326           0 :     MOZ_ASSERT(mClass == eKeyboardEventClass,
     327             :                "Duplicate() must be overridden by sub class");
     328             :     // Not copying widget, it is a weak reference.
     329             :     WidgetKeyboardEvent* result =
     330           0 :       new WidgetKeyboardEvent(false, mMessage, nullptr);
     331           0 :     result->AssignKeyEventData(*this, true);
     332           0 :     result->mEditCommandsForSingleLineEditor = mEditCommandsForSingleLineEditor;
     333           0 :     result->mEditCommandsForMultiLineEditor = mEditCommandsForMultiLineEditor;
     334           0 :     result->mEditCommandsForRichTextEditor = mEditCommandsForRichTextEditor;
     335           0 :     result->mFlags = mFlags;
     336           0 :     return result;
     337             :   }
     338             : 
     339             :   // OS translated Unicode chars which are used for accesskey and accelkey
     340             :   // handling. The handlers will try from first character to last character.
     341             :   nsTArray<AlternativeCharCode> mAlternativeCharCodes;
     342             :   // DOM KeyboardEvent.key only when mKeyNameIndex is KEY_NAME_INDEX_USE_STRING.
     343             :   nsString mKeyValue;
     344             :   // DOM KeyboardEvent.code only when mCodeNameIndex is
     345             :   // CODE_NAME_INDEX_USE_STRING.
     346             :   nsString mCodeValue;
     347             : 
     348             : #ifdef XP_MACOSX
     349             :   // Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
     350             :   nsString mNativeCharacters;
     351             :   nsString mNativeCharactersIgnoringModifiers;
     352             :   // If this is non-empty, create a text event for plugins instead of a
     353             :   // keyboard event.
     354             :   nsString mPluginTextEventString;
     355             : #endif // #ifdef XP_MACOSX
     356             : 
     357             :   // OS-specific native event can optionally be preserved
     358             :   void* mNativeKeyEvent;
     359             :   // A DOM keyCode value or 0.  If a keypress event whose mCharCode is 0, this
     360             :   // should be 0.
     361             :   uint32_t mKeyCode;
     362             :   // If the instance is a keypress event of a printable key, this is a UTF-16
     363             :   // value of the key.  Otherwise, 0.  This value must not be a control
     364             :   // character when some modifiers are active.  Then, this value should be an
     365             :   // unmodified value except Shift and AltGr.
     366             :   uint32_t mCharCode;
     367             :   // mPseudoCharCode is valid only when mMessage is an eKeyDown event.
     368             :   // This stores mCharCode value of keypress event which is fired with same
     369             :   // key value and same modifier state.
     370             :   uint32_t mPseudoCharCode;
     371             :   // One of eKeyLocation*
     372             :   uint32_t mLocation;
     373             :   // Unique id associated with a keydown / keypress event. It's ok if this wraps
     374             :   // over long periods.
     375             :   uint32_t mUniqueId;
     376             : 
     377             : #ifdef XP_MACOSX
     378             :   // Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
     379             :   uint32_t mNativeModifierFlags;
     380             :   uint16_t mNativeKeyCode;
     381             : #endif // #ifdef XP_MACOSX
     382             : 
     383             :   // DOM KeyboardEvent.key
     384             :   KeyNameIndex mKeyNameIndex;
     385             :   // DOM KeyboardEvent.code
     386             :   CodeNameIndex mCodeNameIndex;
     387             : 
     388             :   // Indicates whether the event is generated by auto repeat or not.
     389             :   // if this is keyup event, always false.
     390             :   bool mIsRepeat;
     391             :   // Indicates whether the event is generated during IME (or deadkey)
     392             :   // composition.  This is initialized by EventStateManager.  So, key event
     393             :   // dispatchers don't need to initialize this.
     394             :   bool mIsComposing;
     395             :   // Indicates whether the event is synthesized from Text Input Processor
     396             :   // or an actual event from nsAppShell.
     397             :   bool mIsSynthesizedByTIP;
     398             :   // Indicates whether the event is skippable in remote process.
     399             :   // Don't refer this member directly when you need to check this.
     400             :   // Use CanSkipInRemoteProcess() instead.
     401             :   bool mMaybeSkippableInRemoteProcess;
     402             : 
     403           0 :   bool CanSkipInRemoteProcess() const
     404             :   {
     405             :     // If this is a repeat event (i.e., generated by auto-repeat feature of
     406             :     // the platform), remove process may skip to handle it because of
     407             :     // performances reasons..  However, if it's caused by odd keyboard utils,
     408             :     // we should not ignore any key events even marked as repeated since
     409             :     // generated key sequence may be important to input proper text.  E.g.,
     410             :     // "SinhalaTamil IME" on Windows emulates dead key like input with
     411             :     // generating WM_KEYDOWN for VK_PACKET (inputting any Unicode characters
     412             :     // without keyboard layout information) and VK_BACK (Backspace) to remove
     413             :     // previous character(s) and those messages may be marked as "repeat" by
     414             :     // their bug.
     415           0 :     return mIsRepeat && mMaybeSkippableInRemoteProcess;
     416             :   }
     417             : 
     418             :   /**
     419             :    * Retrieves all edit commands from mWidget.  This shouldn't be called when
     420             :    * the instance is an untrusted event, doesn't have widget or in non-chrome
     421             :    * process.
     422             :    */
     423             :   void InitAllEditCommands();
     424             : 
     425             :   /**
     426             :    * Retrieves edit commands from mWidget only for aType.  This shouldn't be
     427             :    * called when the instance is an untrusted event or doesn't have widget.
     428             :    */
     429             :   void InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType);
     430             : 
     431             :   /**
     432             :    * PreventNativeKeyBindings() makes the instance to not cause any edit
     433             :    * actions even if it matches with a native key binding.
     434             :    */
     435           0 :   void PreventNativeKeyBindings()
     436             :   {
     437           0 :     mEditCommandsForSingleLineEditor.Clear();
     438           0 :     mEditCommandsForMultiLineEditor.Clear();
     439           0 :     mEditCommandsForRichTextEditor.Clear();
     440           0 :     mEditCommandsForSingleLineEditorInitialized = true;
     441           0 :     mEditCommandsForMultiLineEditorInitialized = true;
     442           0 :     mEditCommandsForRichTextEditorInitialized = true;
     443           0 :   }
     444             : 
     445             :   /**
     446             :    * EditCommandsConstRef() returns reference to edit commands for aType.
     447             :    */
     448             :   const nsTArray<CommandInt>&
     449             :     EditCommandsConstRef(nsIWidget::NativeKeyBindingsType aType) const
     450             :   {
     451           0 :     return const_cast<WidgetKeyboardEvent*>(this)->EditCommandsRef(aType);
     452             :   }
     453             : 
     454             :   /**
     455             :    * IsEditCommandsInitialized() returns true if edit commands for aType
     456             :    * was already initialized.  Otherwise, false.
     457             :    */
     458           0 :   bool IsEditCommandsInitialized(
     459             :          nsIWidget::NativeKeyBindingsType aType) const
     460             :   {
     461             :     return const_cast<WidgetKeyboardEvent*>(this)->
     462           0 :              IsEditCommandsInitializedRef(aType);
     463             :   }
     464             : 
     465             : #ifdef DEBUG
     466             :   /**
     467             :    * AreAllEditCommandsInitialized() returns true if edit commands for all
     468             :    * types were already initialized.  Otherwise, false.
     469             :    */
     470           0 :   bool AreAllEditCommandsInitialized() const
     471             :   {
     472           0 :     return mEditCommandsForSingleLineEditorInitialized &&
     473           0 :            mEditCommandsForMultiLineEditorInitialized &&
     474           0 :            mEditCommandsForRichTextEditorInitialized;
     475             :   }
     476             : #endif // #ifdef DEBUG
     477             : 
     478             :   /**
     479             :    * Execute edit commands for aType.
     480             :    *
     481             :    * @return        true if the caller should do nothing anymore.
     482             :    *                false, otherwise.
     483             :    */
     484             :   typedef void (*DoCommandCallback)(Command, void*);
     485             :   bool ExecuteEditCommands(nsIWidget::NativeKeyBindingsType aType,
     486             :                            DoCommandCallback aCallback,
     487             :                            void* aCallbackData);
     488             : 
     489             :   // If the key should cause keypress events, this returns true.
     490             :   // Otherwise, false.
     491             :   bool ShouldCauseKeypressEvents() const;
     492             : 
     493             :   // mCharCode value of non-eKeyPress events is always 0.  However, if
     494             :   // non-eKeyPress event has one or more alternative char code values,
     495             :   // its first item should be the mCharCode value of following eKeyPress event.
     496             :   // PseudoCharCode() returns mCharCode value for eKeyPress event,
     497             :   // the first alternative char code value of non-eKeyPress event or 0.
     498           0 :   uint32_t PseudoCharCode() const
     499             :   {
     500           0 :     return mMessage == eKeyPress ? mCharCode : mPseudoCharCode;
     501             :   }
     502           0 :   void SetCharCode(uint32_t aCharCode)
     503             :   {
     504           0 :     if (mMessage == eKeyPress) {
     505           0 :       mCharCode = aCharCode;
     506             :     } else {
     507           0 :       mPseudoCharCode = aCharCode;
     508             :     }
     509           0 :   }
     510             : 
     511           0 :   void GetDOMKeyName(nsAString& aKeyName)
     512             :   {
     513           0 :     if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
     514           0 :       aKeyName = mKeyValue;
     515             :       return;
     516             :     }
     517           0 :     GetDOMKeyName(mKeyNameIndex, aKeyName);
     518             :   }
     519           0 :   void GetDOMCodeName(nsAString& aCodeName)
     520             :   {
     521           0 :     if (mCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
     522           0 :       aCodeName = mCodeValue;
     523             :       return;
     524             :     }
     525           0 :     GetDOMCodeName(mCodeNameIndex, aCodeName);
     526             :   }
     527             : 
     528             :   /**
     529             :    * GetFallbackKeyCodeOfPunctuationKey() returns a DOM keyCode value for
     530             :    * aCodeNameIndex.  This is keyCode value of the key when active keyboard
     531             :    * layout is ANSI (US), JIS or ABNT keyboard layout (the latter 2 layouts
     532             :    * are used only when ANSI doesn't have the key).  The result is useful
     533             :    * if the key doesn't produce ASCII character with active keyboard layout
     534             :    * nor with alternative ASCII capable keyboard layout.
     535             :    */
     536             :   static uint32_t
     537             :   GetFallbackKeyCodeOfPunctuationKey(CodeNameIndex aCodeNameIndex);
     538             : 
     539           0 :   bool IsModifierKeyEvent() const
     540             :   {
     541           0 :     return GetModifierForKeyName(mKeyNameIndex) != MODIFIER_NONE;
     542             :   }
     543             : 
     544             :   /**
     545             :    * Get the candidates for shortcut key.
     546             :    *
     547             :    * @param aCandidates [out] the candidate shortcut key combination list.
     548             :    *                          the first item is most preferred.
     549             :    */
     550             :   void GetShortcutKeyCandidates(ShortcutKeyCandidateArray& aCandidates) const;
     551             : 
     552             :   /**
     553             :    * Get the candidates for access key.
     554             :    *
     555             :    * @param aCandidates [out] the candidate access key list.
     556             :    *                          the first item is most preferred.
     557             :    */
     558             :   void GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates) const;
     559             : 
     560             :   /**
     561             :    * Check whether the modifiers match with chrome access key or
     562             :    * content access key.
     563             :    */
     564             :   bool ModifiersMatchWithAccessKey(AccessKeyType aType) const;
     565             : 
     566             :   /**
     567             :    * Return active modifiers which may match with access key.
     568             :    * For example, even if Alt is access key modifier, then, when Control,
     569             :    * CapseLock and NumLock are active, this returns only MODIFIER_CONTROL.
     570             :    */
     571             :   Modifiers ModifiersForAccessKeyMatching() const;
     572             : 
     573             :   /**
     574             :    * Return access key modifiers.
     575             :    */
     576             :   static Modifiers AccessKeyModifiers(AccessKeyType aType);
     577             : 
     578             :   static void Shutdown();
     579             : 
     580             :   /**
     581             :    * ComputeLocationFromCodeValue() returns one of .mLocation value
     582             :    * (eKeyLocation*) which is the most preferred value for the specified code
     583             :    * value.
     584             :    */
     585             :   static uint32_t ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex);
     586             : 
     587             :   /**
     588             :    * ComputeKeyCodeFromKeyNameIndex() return a .mKeyCode value which can be
     589             :    * mapped from the specified key value.  Note that this returns 0 if the
     590             :    * key name index is KEY_NAME_INDEX_Unidentified or KEY_NAME_INDEX_USE_STRING.
     591             :    * This means that this method is useful only for non-printable keys.
     592             :    */
     593             :   static uint32_t ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex);
     594             : 
     595             :   /**
     596             :    * GetModifierForKeyName() returns a value of Modifier which is activated
     597             :    * by the aKeyNameIndex.
     598             :    */
     599             :   static Modifier GetModifierForKeyName(KeyNameIndex aKeyNameIndex);
     600             : 
     601             :   /**
     602             :    * IsLockableModifier() returns true if aKeyNameIndex is a lockable modifier
     603             :    * key such as CapsLock and NumLock.
     604             :    */
     605             :   static bool IsLockableModifier(KeyNameIndex aKeyNameIndex);
     606             : 
     607             :   static void GetDOMKeyName(KeyNameIndex aKeyNameIndex,
     608             :                             nsAString& aKeyName);
     609             :   static void GetDOMCodeName(CodeNameIndex aCodeNameIndex,
     610             :                              nsAString& aCodeName);
     611             : 
     612             :   static KeyNameIndex GetKeyNameIndex(const nsAString& aKeyValue);
     613             :   static CodeNameIndex GetCodeNameIndex(const nsAString& aCodeValue);
     614             : 
     615             :   static const char* GetCommandStr(Command aCommand);
     616             : 
     617           0 :   void AssignKeyEventData(const WidgetKeyboardEvent& aEvent, bool aCopyTargets)
     618             :   {
     619           0 :     AssignInputEventData(aEvent, aCopyTargets);
     620             : 
     621           0 :     mKeyCode = aEvent.mKeyCode;
     622           0 :     mCharCode = aEvent.mCharCode;
     623           0 :     mPseudoCharCode = aEvent.mPseudoCharCode;
     624           0 :     mLocation = aEvent.mLocation;
     625           0 :     mAlternativeCharCodes = aEvent.mAlternativeCharCodes;
     626           0 :     mIsRepeat = aEvent.mIsRepeat;
     627           0 :     mIsComposing = aEvent.mIsComposing;
     628           0 :     mKeyNameIndex = aEvent.mKeyNameIndex;
     629           0 :     mCodeNameIndex = aEvent.mCodeNameIndex;
     630           0 :     mKeyValue = aEvent.mKeyValue;
     631           0 :     mCodeValue = aEvent.mCodeValue;
     632             :     // Don't copy mNativeKeyEvent because it may be referred after its instance
     633             :     // is destroyed.
     634           0 :     mNativeKeyEvent = nullptr;
     635           0 :     mUniqueId = aEvent.mUniqueId;
     636             : #ifdef XP_MACOSX
     637             :     mNativeKeyCode = aEvent.mNativeKeyCode;
     638             :     mNativeModifierFlags = aEvent.mNativeModifierFlags;
     639             :     mNativeCharacters.Assign(aEvent.mNativeCharacters);
     640             :     mNativeCharactersIgnoringModifiers.
     641             :       Assign(aEvent.mNativeCharactersIgnoringModifiers);
     642             :     mPluginTextEventString.Assign(aEvent.mPluginTextEventString);
     643             : #endif
     644           0 :     mIsSynthesizedByTIP = aEvent.mIsSynthesizedByTIP;
     645           0 :     mMaybeSkippableInRemoteProcess = aEvent.mMaybeSkippableInRemoteProcess;
     646             : 
     647             :     // Don't copy mEditCommandsFor*Editor because it may require a lot of
     648             :     // memory space.  For example, if the event is dispatched but grabbed by
     649             :     // a JS variable, they are not necessary anymore.
     650             : 
     651           0 :     mEditCommandsForSingleLineEditorInitialized =
     652           0 :       aEvent.mEditCommandsForSingleLineEditorInitialized;
     653           0 :     mEditCommandsForMultiLineEditorInitialized =
     654           0 :       aEvent.mEditCommandsForMultiLineEditorInitialized;
     655           0 :     mEditCommandsForRichTextEditorInitialized =
     656           0 :       aEvent.mEditCommandsForRichTextEditorInitialized;
     657           0 :   }
     658             : 
     659             : private:
     660             :   static const char16_t* const kKeyNames[];
     661             :   static const char16_t* const kCodeNames[];
     662             :   typedef nsDataHashtable<nsStringHashKey,
     663             :                           KeyNameIndex> KeyNameIndexHashtable;
     664             :   typedef nsDataHashtable<nsStringHashKey,
     665             :                           CodeNameIndex> CodeNameIndexHashtable;
     666             :   static KeyNameIndexHashtable* sKeyNameIndexHashtable;
     667             :   static CodeNameIndexHashtable* sCodeNameIndexHashtable;
     668             : 
     669             :   // mEditCommandsFor*Editor store edit commands.  This should be initialized
     670             :   // with InitEditCommandsFor().
     671             :   // XXX Ideally, this should be array of Command rather than CommandInt.
     672             :   //     However, ParamTraits isn't aware of enum array.
     673             :   nsTArray<CommandInt> mEditCommandsForSingleLineEditor;
     674             :   nsTArray<CommandInt> mEditCommandsForMultiLineEditor;
     675             :   nsTArray<CommandInt> mEditCommandsForRichTextEditor;
     676             : 
     677           0 :   nsTArray<CommandInt>& EditCommandsRef(nsIWidget::NativeKeyBindingsType aType)
     678             :   {
     679           0 :     switch (aType) {
     680             :       case nsIWidget::NativeKeyBindingsForSingleLineEditor:
     681           0 :         return mEditCommandsForSingleLineEditor;
     682             :       case nsIWidget::NativeKeyBindingsForMultiLineEditor:
     683           0 :         return mEditCommandsForMultiLineEditor;
     684             :       case nsIWidget::NativeKeyBindingsForRichTextEditor:
     685           0 :         return mEditCommandsForRichTextEditor;
     686             :       default:
     687           0 :         MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
     688             :           "Invalid native key binding type");
     689             :     }
     690             :   }
     691             : 
     692             :   // mEditCommandsFor*EditorInitialized are set to true when
     693             :   // InitEditCommandsFor() initializes edit commands for the type.
     694             :   bool mEditCommandsForSingleLineEditorInitialized;
     695             :   bool mEditCommandsForMultiLineEditorInitialized;
     696             :   bool mEditCommandsForRichTextEditorInitialized;
     697             : 
     698           0 :   bool& IsEditCommandsInitializedRef(nsIWidget::NativeKeyBindingsType aType)
     699             :   {
     700           0 :     switch (aType) {
     701             :       case nsIWidget::NativeKeyBindingsForSingleLineEditor:
     702           0 :         return mEditCommandsForSingleLineEditorInitialized;
     703             :       case nsIWidget::NativeKeyBindingsForMultiLineEditor:
     704           0 :         return mEditCommandsForMultiLineEditorInitialized;
     705             :       case nsIWidget::NativeKeyBindingsForRichTextEditor:
     706           0 :         return mEditCommandsForRichTextEditorInitialized;
     707             :       default:
     708           0 :         MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
     709             :           "Invalid native key binding type");
     710             :     }
     711             :   }
     712             : 
     713             :   static int32_t GenericAccessModifierKeyPref();
     714             :   static int32_t ChromeAccessModifierMaskPref();
     715             :   static int32_t ContentAccessModifierMaskPref();
     716             : };
     717             : 
     718             : /******************************************************************************
     719             :  * mozilla::WidgetCompositionEvent
     720             :  ******************************************************************************/
     721             : 
     722           0 : class WidgetCompositionEvent : public WidgetGUIEvent
     723             : {
     724             : private:
     725             :   friend class mozilla::dom::PBrowserParent;
     726             :   friend class mozilla::dom::PBrowserChild;
     727             : 
     728           0 :   WidgetCompositionEvent()
     729           0 :   {
     730           0 :   }
     731             : 
     732             : public:
     733           0 :   virtual WidgetCompositionEvent* AsCompositionEvent() override
     734             :   {
     735           0 :     return this;
     736             :   }
     737             : 
     738           0 :   WidgetCompositionEvent(bool aIsTrusted, EventMessage aMessage,
     739             :                          nsIWidget* aWidget)
     740           0 :     : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eCompositionEventClass)
     741             :     , mNativeIMEContext(aWidget)
     742           0 :     , mOriginalMessage(eVoidEvent)
     743             :   {
     744           0 :   }
     745             : 
     746           0 :   virtual WidgetEvent* Duplicate() const override
     747             :   {
     748           0 :     MOZ_ASSERT(mClass == eCompositionEventClass,
     749             :                "Duplicate() must be overridden by sub class");
     750             :     // Not copying widget, it is a weak reference.
     751             :     WidgetCompositionEvent* result =
     752           0 :       new WidgetCompositionEvent(false, mMessage, nullptr);
     753           0 :     result->AssignCompositionEventData(*this, true);
     754           0 :     result->mFlags = mFlags;
     755           0 :     return result;
     756             :   }
     757             : 
     758             :   // The composition string or the commit string.  If the instance is a
     759             :   // compositionstart event, this is initialized with selected text by
     760             :   // TextComposition automatically.
     761             :   nsString mData;
     762             : 
     763             :   RefPtr<TextRangeArray> mRanges;
     764             : 
     765             :   // mNativeIMEContext stores the native IME context which causes the
     766             :   // composition event.
     767             :   widget::NativeIMEContext mNativeIMEContext;
     768             : 
     769             :   // If the instance is a clone of another event, mOriginalMessage stores
     770             :   // the another event's mMessage.
     771             :   EventMessage mOriginalMessage;
     772             : 
     773           0 :   void AssignCompositionEventData(const WidgetCompositionEvent& aEvent,
     774             :                                   bool aCopyTargets)
     775             :   {
     776           0 :     AssignGUIEventData(aEvent, aCopyTargets);
     777             : 
     778           0 :     mData = aEvent.mData;
     779           0 :     mOriginalMessage = aEvent.mOriginalMessage;
     780           0 :     mRanges = aEvent.mRanges;
     781             : 
     782             :     // Currently, we don't need to copy the other members because they are
     783             :     // for internal use only (not available from JS).
     784           0 :   }
     785             : 
     786           0 :   bool IsComposing() const
     787             :   {
     788           0 :     return mRanges && mRanges->IsComposing();
     789             :   }
     790             : 
     791           0 :   uint32_t TargetClauseOffset() const
     792             :   {
     793           0 :     return mRanges ? mRanges->TargetClauseOffset() : 0;
     794             :   }
     795             : 
     796             :   uint32_t TargetClauseLength() const
     797             :   {
     798             :     uint32_t length = UINT32_MAX;
     799             :     if (mRanges) {
     800             :       length = mRanges->TargetClauseLength();
     801             :     }
     802             :     return length == UINT32_MAX ? mData.Length() : length;
     803             :   }
     804             : 
     805             :   uint32_t RangeCount() const
     806             :   {
     807             :     return mRanges ? mRanges->Length() : 0;
     808             :   }
     809             : 
     810           0 :   bool CausesDOMTextEvent() const
     811             :   {
     812           0 :     return mMessage == eCompositionChange ||
     813           0 :            mMessage == eCompositionCommit ||
     814           0 :            mMessage == eCompositionCommitAsIs;
     815             :   }
     816             : 
     817           0 :   bool CausesDOMCompositionEndEvent() const
     818             :   {
     819           0 :     return mMessage == eCompositionEnd ||
     820           0 :            mMessage == eCompositionCommit ||
     821           0 :            mMessage == eCompositionCommitAsIs;
     822             :   }
     823             : 
     824             :   bool IsFollowedByCompositionEnd() const
     825             :   {
     826           0 :     return IsFollowedByCompositionEnd(mOriginalMessage);
     827             :   }
     828             : 
     829             :   static bool IsFollowedByCompositionEnd(EventMessage aEventMessage)
     830             :   {
     831           0 :     return aEventMessage == eCompositionCommit ||
     832             :            aEventMessage == eCompositionCommitAsIs;
     833             :   }
     834             : };
     835             : 
     836             : /******************************************************************************
     837             :  * mozilla::WidgetQueryContentEvent
     838             :  ******************************************************************************/
     839             : 
     840           0 : class WidgetQueryContentEvent : public WidgetGUIEvent
     841             : {
     842             : private:
     843             :   friend class dom::PBrowserParent;
     844             :   friend class dom::PBrowserChild;
     845             : 
     846             :   WidgetQueryContentEvent()
     847             :     : mSucceeded(false)
     848             :     , mUseNativeLineBreak(true)
     849             :     , mWithFontRanges(false)
     850             :   {
     851             :     MOZ_CRASH("WidgetQueryContentEvent is created without proper arguments");
     852             :   }
     853             : 
     854             : public:
     855           0 :   virtual WidgetQueryContentEvent* AsQueryContentEvent() override
     856             :   {
     857           0 :     return this;
     858             :   }
     859             : 
     860           1 :   WidgetQueryContentEvent(bool aIsTrusted, EventMessage aMessage,
     861             :                           nsIWidget* aWidget)
     862           1 :     : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eQueryContentEventClass)
     863             :     , mSucceeded(false)
     864             :     , mUseNativeLineBreak(true)
     865           2 :     , mWithFontRanges(false)
     866             :   {
     867           1 :   }
     868             : 
     869           0 :   WidgetQueryContentEvent(EventMessage aMessage,
     870             :                           const WidgetQueryContentEvent& aOtherEvent)
     871           0 :     : WidgetGUIEvent(aOtherEvent.IsTrusted(), aMessage,
     872             :                      const_cast<nsIWidget*>(aOtherEvent.mWidget.get()),
     873             :                      eQueryContentEventClass)
     874             :     , mSucceeded(false)
     875           0 :     , mUseNativeLineBreak(aOtherEvent.mUseNativeLineBreak)
     876           0 :     , mWithFontRanges(false)
     877             :   {
     878           0 :   }
     879             : 
     880           0 :   virtual WidgetEvent* Duplicate() const override
     881             :   {
     882             :     // This event isn't an internal event of any DOM event.
     883           0 :     NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
     884             :       "WidgetQueryContentEvent needs to support Duplicate()");
     885           0 :     MOZ_CRASH("WidgetQueryContentEvent doesn't support Duplicate()");
     886             :   }
     887             : 
     888             :   struct Options final
     889             :   {
     890             :     bool mUseNativeLineBreak;
     891             :     bool mRelativeToInsertionPoint;
     892             : 
     893             :     explicit Options()
     894           0 :       : mUseNativeLineBreak(true)
     895           0 :       , mRelativeToInsertionPoint(false)
     896             :     {
     897             :     }
     898             : 
     899             :     explicit Options(const WidgetQueryContentEvent& aEvent)
     900           0 :       : mUseNativeLineBreak(aEvent.mUseNativeLineBreak)
     901           0 :       , mRelativeToInsertionPoint(aEvent.mInput.mRelativeToInsertionPoint)
     902             :     {
     903             :     }
     904             :   };
     905             : 
     906           0 :   void Init(const Options& aOptions)
     907             :   {
     908           0 :     mUseNativeLineBreak = aOptions.mUseNativeLineBreak;
     909           0 :     mInput.mRelativeToInsertionPoint = aOptions.mRelativeToInsertionPoint;
     910           0 :     MOZ_ASSERT(mInput.IsValidEventMessage(mMessage));
     911           0 :   }
     912             : 
     913           0 :   void InitForQueryTextContent(int64_t aOffset, uint32_t aLength,
     914             :                                const Options& aOptions = Options())
     915             :   {
     916           0 :     NS_ASSERTION(mMessage == eQueryTextContent,
     917             :                  "wrong initializer is called");
     918           0 :     mInput.mOffset = aOffset;
     919           0 :     mInput.mLength = aLength;
     920           0 :     Init(aOptions);
     921           0 :     MOZ_ASSERT(mInput.IsValidOffset());
     922           0 :   }
     923             : 
     924           0 :   void InitForQueryCaretRect(int64_t aOffset,
     925             :                              const Options& aOptions = Options())
     926             :   {
     927           0 :     NS_ASSERTION(mMessage == eQueryCaretRect,
     928             :                  "wrong initializer is called");
     929           0 :     mInput.mOffset = aOffset;
     930           0 :     Init(aOptions);
     931           0 :     MOZ_ASSERT(mInput.IsValidOffset());
     932           0 :   }
     933             : 
     934           0 :   void InitForQueryTextRect(int64_t aOffset, uint32_t aLength,
     935             :                             const Options& aOptions = Options())
     936             :   {
     937           0 :     NS_ASSERTION(mMessage == eQueryTextRect,
     938             :                  "wrong initializer is called");
     939           0 :     mInput.mOffset = aOffset;
     940           0 :     mInput.mLength = aLength;
     941           0 :     Init(aOptions);
     942           0 :     MOZ_ASSERT(mInput.IsValidOffset());
     943           0 :   }
     944             : 
     945           0 :   void InitForQuerySelectedText(SelectionType aSelectionType,
     946             :                                 const Options& aOptions = Options())
     947             :   {
     948           0 :     MOZ_ASSERT(mMessage == eQuerySelectedText);
     949           0 :     MOZ_ASSERT(aSelectionType != SelectionType::eNone);
     950           0 :     mInput.mSelectionType = aSelectionType;
     951           0 :     Init(aOptions);
     952           0 :   }
     953             : 
     954             :   void InitForQueryDOMWidgetHittest(const mozilla::LayoutDeviceIntPoint& aPoint)
     955             :   {
     956             :     NS_ASSERTION(mMessage == eQueryDOMWidgetHittest,
     957             :                  "wrong initializer is called");
     958             :     mRefPoint = aPoint;
     959             :   }
     960             : 
     961           0 :   void InitForQueryTextRectArray(uint32_t aOffset, uint32_t aLength,
     962             :                                  const Options& aOptions = Options())
     963             :   {
     964           0 :     NS_ASSERTION(mMessage == eQueryTextRectArray,
     965             :                  "wrong initializer is called");
     966           0 :     mInput.mOffset = aOffset;
     967           0 :     mInput.mLength = aLength;
     968           0 :     Init(aOptions);
     969           0 :   }
     970             : 
     971           0 :   void RequestFontRanges()
     972             :   {
     973           0 :     NS_ASSERTION(mMessage == eQueryTextContent,
     974             :                  "not querying text content");
     975           0 :     mWithFontRanges = true;
     976           0 :   }
     977             : 
     978             :   uint32_t GetSelectionStart(void) const
     979             :   {
     980             :     NS_ASSERTION(mMessage == eQuerySelectedText,
     981             :                  "not querying selection");
     982             :     return mReply.mOffset + (mReply.mReversed ? mReply.mString.Length() : 0);
     983             :   }
     984             : 
     985             :   uint32_t GetSelectionEnd(void) const
     986             :   {
     987             :     NS_ASSERTION(mMessage == eQuerySelectedText,
     988             :                  "not querying selection");
     989             :     return mReply.mOffset + (mReply.mReversed ? 0 : mReply.mString.Length());
     990             :   }
     991             : 
     992           1 :   mozilla::WritingMode GetWritingMode(void) const
     993             :   {
     994           1 :     NS_ASSERTION(mMessage == eQuerySelectedText ||
     995             :                  mMessage == eQueryCaretRect ||
     996             :                  mMessage == eQueryTextRect,
     997             :                  "not querying selection or text rect");
     998           1 :     return mReply.mWritingMode;
     999             :   }
    1000             : 
    1001             :   bool mSucceeded;
    1002             :   bool mUseNativeLineBreak;
    1003             :   bool mWithFontRanges;
    1004             :   struct Input final
    1005             :   {
    1006           0 :     uint32_t EndOffset() const
    1007             :     {
    1008             :       CheckedInt<uint32_t> endOffset =
    1009           0 :         CheckedInt<uint32_t>(mOffset) + mLength;
    1010           0 :       return NS_WARN_IF(!endOffset.isValid()) ? UINT32_MAX : endOffset.value();
    1011             :     }
    1012             : 
    1013             :     int64_t mOffset;
    1014             :     uint32_t mLength;
    1015             :     SelectionType mSelectionType;
    1016             :     // If mOffset is true, mOffset is relative to the start offset of
    1017             :     // composition if there is, otherwise, the start of the first selection
    1018             :     // range.
    1019             :     bool mRelativeToInsertionPoint;
    1020             : 
    1021             :     Input()
    1022           1 :       : mOffset(0)
    1023             :       , mLength(0)
    1024             :       , mSelectionType(SelectionType::eNormal)
    1025           0 :       , mRelativeToInsertionPoint(false)
    1026             :     {
    1027             :     }
    1028             : 
    1029           1 :     bool IsValidOffset() const
    1030             :     {
    1031           1 :       return mRelativeToInsertionPoint || mOffset >= 0;
    1032             :     }
    1033           0 :     bool IsValidEventMessage(EventMessage aEventMessage) const
    1034             :     {
    1035           0 :       if (!mRelativeToInsertionPoint) {
    1036             :         return true;
    1037             :       }
    1038           0 :       switch (aEventMessage) {
    1039             :         case eQueryTextContent:
    1040             :         case eQueryCaretRect:
    1041             :         case eQueryTextRect:
    1042             :           return true;
    1043             :         default:
    1044           0 :           return false;
    1045             :       }
    1046             :     }
    1047           0 :     bool MakeOffsetAbsolute(uint32_t aInsertionPointOffset)
    1048             :     {
    1049           0 :       if (NS_WARN_IF(!mRelativeToInsertionPoint)) {
    1050             :         return true;
    1051             :       }
    1052           0 :       mRelativeToInsertionPoint = false;
    1053             :       // If mOffset + aInsertionPointOffset becomes negative value,
    1054             :       // we should assume the absolute offset is 0.
    1055           0 :       if (mOffset < 0 && -mOffset > aInsertionPointOffset) {
    1056           0 :         mOffset = 0;
    1057           0 :         return true;
    1058             :       }
    1059             :       // Otherwise, we don't allow too large offset.
    1060           0 :       CheckedInt<uint32_t> absOffset = mOffset + aInsertionPointOffset;
    1061           0 :       if (NS_WARN_IF(!absOffset.isValid())) {
    1062           0 :         mOffset = UINT32_MAX;
    1063           0 :         return false;
    1064             :       }
    1065           0 :       mOffset = absOffset.value();
    1066           0 :       return true;
    1067             :     }
    1068             :   } mInput;
    1069             : 
    1070           4 :   struct Reply final
    1071             :   {
    1072             :     void* mContentsRoot;
    1073             :     uint32_t mOffset;
    1074             :     // mTentativeCaretOffset is used by only eQueryCharacterAtPoint.
    1075             :     // This is the offset where caret would be if user clicked at the mRefPoint.
    1076             :     uint32_t mTentativeCaretOffset;
    1077             :     nsString mString;
    1078             :     // mRect is used by eQueryTextRect, eQueryCaretRect, eQueryCharacterAtPoint
    1079             :     // and eQueryEditorRect. The coordinates is system coordinates relative to
    1080             :     // the top level widget of mFocusedWidget.  E.g., if a <xul:panel> which
    1081             :     // is owned by a window has focused editor, the offset of mRect is relative
    1082             :     // to the owner window, not the <xul:panel>.
    1083             :     mozilla::LayoutDeviceIntRect mRect;
    1084             :     // The return widget has the caret. This is set at all query events.
    1085             :     nsIWidget* mFocusedWidget;
    1086             :     // mozilla::WritingMode value at the end (focus) of the selection
    1087             :     mozilla::WritingMode mWritingMode;
    1088             :     // Used by eQuerySelectionAsTransferable
    1089             :     nsCOMPtr<nsITransferable> mTransferable;
    1090             :     // Used by eQueryTextContent with font ranges requested
    1091             :     AutoTArray<mozilla::FontRange, 1> mFontRanges;
    1092             :     // Used by eQueryTextRectArray
    1093             :     nsTArray<mozilla::LayoutDeviceIntRect> mRectArray;
    1094             :     // true if selection is reversed (end < start)
    1095             :     bool mReversed;
    1096             :     // true if the selection exists
    1097             :     bool mHasSelection;
    1098             :     // true if DOM element under mouse belongs to widget
    1099             :     bool mWidgetIsHit;
    1100             : 
    1101           1 :     Reply()
    1102           1 :       : mContentsRoot(nullptr)
    1103             :       , mOffset(NOT_FOUND)
    1104             :       , mTentativeCaretOffset(NOT_FOUND)
    1105             :       , mFocusedWidget(nullptr)
    1106             :       , mReversed(false)
    1107             :       , mHasSelection(false)
    1108           5 :       , mWidgetIsHit(false)
    1109             :     {
    1110           1 :     }
    1111             :   } mReply;
    1112             : 
    1113             :   enum
    1114             :   {
    1115             :     NOT_FOUND = UINT32_MAX
    1116             :   };
    1117             : 
    1118             :   // values of mComputedScrollAction
    1119             :   enum
    1120             :   {
    1121             :     SCROLL_ACTION_NONE,
    1122             :     SCROLL_ACTION_LINE,
    1123             :     SCROLL_ACTION_PAGE
    1124             :   };
    1125             : };
    1126             : 
    1127             : /******************************************************************************
    1128             :  * mozilla::WidgetSelectionEvent
    1129             :  ******************************************************************************/
    1130             : 
    1131           0 : class WidgetSelectionEvent : public WidgetGUIEvent
    1132             : {
    1133             : private:
    1134             :   friend class mozilla::dom::PBrowserParent;
    1135             :   friend class mozilla::dom::PBrowserChild;
    1136             : 
    1137           0 :   WidgetSelectionEvent()
    1138           0 :     : mOffset(0)
    1139             :     , mLength(0)
    1140             :     , mReversed(false)
    1141             :     , mExpandToClusterBoundary(true)
    1142             :     , mSucceeded(false)
    1143           0 :     , mUseNativeLineBreak(true)
    1144             :   {
    1145           0 :   }
    1146             : 
    1147             : public:
    1148           0 :   virtual WidgetSelectionEvent* AsSelectionEvent() override
    1149             :   {
    1150           0 :     return this;
    1151             :   }
    1152             : 
    1153           0 :   WidgetSelectionEvent(bool aIsTrusted, EventMessage aMessage,
    1154             :                        nsIWidget* aWidget)
    1155           0 :     : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eSelectionEventClass)
    1156             :     , mOffset(0)
    1157             :     , mLength(0)
    1158             :     , mReversed(false)
    1159             :     , mExpandToClusterBoundary(true)
    1160             :     , mSucceeded(false)
    1161             :     , mUseNativeLineBreak(true)
    1162           0 :     , mReason(nsISelectionListener::NO_REASON)
    1163             :   {
    1164           0 :   }
    1165             : 
    1166           0 :   virtual WidgetEvent* Duplicate() const override
    1167             :   {
    1168             :     // This event isn't an internal event of any DOM event.
    1169           0 :     NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
    1170             :       "WidgetSelectionEvent needs to support Duplicate()");
    1171           0 :     MOZ_CRASH("WidgetSelectionEvent doesn't support Duplicate()");
    1172             :     return nullptr;
    1173             :   }
    1174             : 
    1175             :   // Start offset of selection
    1176             :   uint32_t mOffset;
    1177             :   // Length of selection
    1178             :   uint32_t mLength;
    1179             :   // Selection "anchor" should be in front
    1180             :   bool mReversed;
    1181             :   // Cluster-based or character-based
    1182             :   bool mExpandToClusterBoundary;
    1183             :   // true if setting selection succeeded.
    1184             :   bool mSucceeded;
    1185             :   // true if native line breaks are used for mOffset and mLength
    1186             :   bool mUseNativeLineBreak;
    1187             :   // Fennec provides eSetSelection reason codes for downstream
    1188             :   // use in AccessibleCaret visibility logic.
    1189             :   int16_t mReason;
    1190             : };
    1191             : 
    1192             : /******************************************************************************
    1193             :  * mozilla::InternalEditorInputEvent
    1194             :  ******************************************************************************/
    1195             : 
    1196           0 : class InternalEditorInputEvent : public InternalUIEvent
    1197             : {
    1198             : private:
    1199             :   InternalEditorInputEvent()
    1200             :     : mIsComposing(false)
    1201             :   {
    1202             :   }
    1203             : 
    1204             : public:
    1205           0 :   virtual InternalEditorInputEvent* AsEditorInputEvent() override
    1206             :   {
    1207           0 :     return this;
    1208             :   }
    1209             : 
    1210           0 :   InternalEditorInputEvent(bool aIsTrusted, EventMessage aMessage,
    1211             :                            nsIWidget* aWidget = nullptr)
    1212           0 :     : InternalUIEvent(aIsTrusted, aMessage, aWidget, eEditorInputEventClass)
    1213           0 :     , mIsComposing(false)
    1214             :   {
    1215           0 :   }
    1216             : 
    1217             :   virtual WidgetEvent* Duplicate() const override
    1218             :   {
    1219             :     MOZ_ASSERT(mClass == eEditorInputEventClass,
    1220             :                "Duplicate() must be overridden by sub class");
    1221             :     // Not copying widget, it is a weak reference.
    1222             :     InternalEditorInputEvent* result =
    1223             :       new InternalEditorInputEvent(false, mMessage, nullptr);
    1224             :     result->AssignEditorInputEventData(*this, true);
    1225             :     result->mFlags = mFlags;
    1226             :     return result;
    1227             :   }
    1228             : 
    1229             :   bool mIsComposing;
    1230             : 
    1231             :   void AssignEditorInputEventData(const InternalEditorInputEvent& aEvent,
    1232             :                                   bool aCopyTargets)
    1233             :   {
    1234             :     AssignUIEventData(aEvent, aCopyTargets);
    1235             : 
    1236             :     mIsComposing = aEvent.mIsComposing;
    1237             :   }
    1238             : };
    1239             : 
    1240             : } // namespace mozilla
    1241             : 
    1242             : #endif // mozilla_TextEvents_h__

Generated by: LCOV version 1.13-14-ga5dd952