diff options
Diffstat (limited to 'dom/base/TextInputProcessor.h')
-rw-r--r-- | dom/base/TextInputProcessor.h | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/dom/base/TextInputProcessor.h b/dom/base/TextInputProcessor.h new file mode 100644 index 0000000000..10e0421953 --- /dev/null +++ b/dom/base/TextInputProcessor.h @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_textinputprocessor_h_ +#define mozilla_dom_textinputprocessor_h_ + +#include "mozilla/Attributes.h" +#include "mozilla/BasicEvents.h" +#include "mozilla/EventForwards.h" +#include "mozilla/Maybe.h" +#include "mozilla/TextEventDispatcher.h" +#include "mozilla/TextEventDispatcherListener.h" +#include "nsITextInputProcessor.h" +#include "nsITextInputProcessorCallback.h" +#include "nsTArray.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +namespace dom { +class KeyboardEvent; +} // namespace dom + +class TextInputProcessor final : public nsITextInputProcessor, + public widget::TextEventDispatcherListener { + typedef mozilla::widget::IMENotification IMENotification; + typedef mozilla::widget::IMENotificationRequests IMENotificationRequests; + typedef mozilla::widget::TextEventDispatcher TextEventDispatcher; + + public: + TextInputProcessor(); + + NS_DECL_ISUPPORTS + NS_DECL_NSITEXTINPUTPROCESSOR + + // TextEventDispatcherListener + MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD + NotifyIME(TextEventDispatcher* aTextEventDispatcher, + const IMENotification& aNotification) override; + + NS_IMETHOD_(IMENotificationRequests) GetIMENotificationRequests() override; + + NS_IMETHOD_(void) + OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override; + + NS_IMETHOD_(void) + WillDispatchKeyboardEvent(TextEventDispatcher* aTextEventDispatcher, + WidgetKeyboardEvent& aKeyboardEvent, + uint32_t aIndexOfKeypress, void* aData) override; + + /** + * TextInputProcessor manages modifier key state. E.g., when it dispatches + * a modifier keydown event, activates proper modifier state and when it + * dispatches a modifier keyup event, inactivates proper modifier state. + * This returns all active modifiers in the instance. + */ + Modifiers GetActiveModifiers() const { + return mModifierKeyDataArray ? mModifierKeyDataArray->GetActiveModifiers() + : MODIFIER_NONE; + } + + /** + * This begins transaction for fuzzing. This must be called only by + * FuzzingFunctions since this skips the permission check. + * See explanation of nsITextInputProcessor::BeginInputTransaction() for + * the detail. + */ + nsresult BeginInputTransactionForFuzzing( + nsPIDOMWindowInner* aWindow, nsITextInputProcessorCallback* aCallback, + bool* aSucceeded); + + /** + * The following Keydown() and KeyUp() are same as nsITextInputProcessor's + * same name methods except the type of event class. See explanation in + * nsITextInputProcessor for the detail. + */ + MOZ_CAN_RUN_SCRIPT nsresult Keydown(const WidgetKeyboardEvent& aKeyboardEvent, + uint32_t aKeyFlags, + uint32_t* aConsumedFlags = nullptr); + nsresult Keyup(const WidgetKeyboardEvent& aKeyboardEvent, uint32_t aKeyFlags, + bool* aDoDefault = nullptr); + + /** + * GuessCodeNameIndexOfPrintableKeyInUSEnglishLayout() returns CodeNameIndex + * of a printable key which is in usual keyboard of the platform and when + * active keyboard layout is US-English. + * Note that this does not aware of option key mapping on macOS. + * + * @param aKeyValue The key value. Must be a character which can + * be inputted with US-English keyboard layout. + * @param aLocation The location of the key. This is important + * to distinguish whether the key is in Standard + * or Numpad. If this is not some, treated as + * Standard. + * @return Returns CODE_NAME_INDEX_UNKNOWN if there is + * no proper key. + */ + static CodeNameIndex GuessCodeNameIndexOfPrintableKeyInUSEnglishLayout( + const nsAString& aKeyValue, const Maybe<uint32_t>& aLocation); + + /** + * GuessKeyCodeOfPrintableKeyInUSEnglishLayout() returns a key code value + * of a printable key which is in usual keyboard of the platform and when + * active keyboard layout is US-English. + * Note that this does not aware of option key mapping on macOS. + * + * @param aKeyValue The key value. Must be a character which can + * be inputted with US-English keyboard layout. + * @param aLocation The location of the key. This is important + * to distinguish whether the key is in Standard + * or Numpad. If this is not some, treated as + * Standard. + * @return Returns 0 if there is no proper key to input + * aKeyValue with US-English keyboard layout. + */ + static uint32_t GuessKeyCodeOfPrintableKeyInUSEnglishLayout( + const nsAString& aKeyValue, const Maybe<uint32_t>& aLocation); + + protected: + virtual ~TextInputProcessor(); + + private: + bool IsComposing() const; + nsresult BeginInputTransactionInternal( + mozIDOMWindow* aWindow, nsITextInputProcessorCallback* aCallback, + bool aForTests, bool& aSucceeded); + MOZ_CAN_RUN_SCRIPT nsresult CommitCompositionInternal( + const WidgetKeyboardEvent* aKeyboardEvent = nullptr, + uint32_t aKeyFlags = 0, const nsAString* aCommitString = nullptr, + bool* aSucceeded = nullptr); + MOZ_CAN_RUN_SCRIPT nsresult + CancelCompositionInternal(const WidgetKeyboardEvent* aKeyboardEvent = nullptr, + uint32_t aKeyFlags = 0); + MOZ_CAN_RUN_SCRIPT nsresult + KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent, uint32_t aKeyFlags, + bool aAllowToDispatchKeypress, uint32_t& aConsumedFlags); + nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent, + uint32_t aKeyFlags, bool& aDoDefault); + nsresult IsValidStateForComposition(); + void UnlinkFromTextEventDispatcher(); + nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent, + uint32_t aKeyFlags); + /** + * InitEditCommands() initializes edit commands of aKeyboardEvent. + * This must be called only in a content process, and aKeyboardEvent must + * be used only for `eKeyPress` event. + */ + MOZ_CAN_RUN_SCRIPT nsresult + InitEditCommands(WidgetKeyboardEvent& aKeyboardEvent) const; + + bool IsValidEventTypeForComposition( + const WidgetKeyboardEvent& aKeyboardEvent) const; + nsresult PrepareKeyboardEventForComposition( + dom::KeyboardEvent* aDOMKeyEvent, uint32_t& aKeyFlags, + uint8_t aOptionalArgc, WidgetKeyboardEvent*& aKeyboardEvent); + + struct EventDispatcherResult { + nsresult mResult; + bool mDoDefault; + bool mCanContinue; + + EventDispatcherResult() + : mResult(NS_OK), mDoDefault(true), mCanContinue(true) {} + }; + MOZ_CAN_RUN_SCRIPT EventDispatcherResult MaybeDispatchKeydownForComposition( + const WidgetKeyboardEvent* aKeyboardEvent, uint32_t aKeyFlags); + EventDispatcherResult MaybeDispatchKeyupForComposition( + const WidgetKeyboardEvent* aKeyboardEvent, uint32_t aKeyFlags); + + /** + * AutoPendingCompositionResetter guarantees to clear all pending composition + * data in its destructor. + */ + class MOZ_STACK_CLASS AutoPendingCompositionResetter { + public: + explicit AutoPendingCompositionResetter(TextInputProcessor* aTIP); + ~AutoPendingCompositionResetter(); + + private: + RefPtr<TextInputProcessor> mTIP; + }; + + /** + * TextInputProcessor manages modifier state both with .key and .code. + * For example, left shift key up shouldn't cause inactivating shift state + * while right shift key is being pressed. + */ + struct ModifierKeyData { + // One of modifier key name + KeyNameIndex mKeyNameIndex; + // Any code name is allowed. + CodeNameIndex mCodeNameIndex; + // A modifier key flag which is activated by the key. + Modifiers mModifier; + + explicit ModifierKeyData(const WidgetKeyboardEvent& aKeyboardEvent); + + bool operator==(const ModifierKeyData& aOther) const { + return mKeyNameIndex == aOther.mKeyNameIndex && + mCodeNameIndex == aOther.mCodeNameIndex; + } + }; + + class ModifierKeyDataArray : public nsTArray<ModifierKeyData> { + NS_INLINE_DECL_REFCOUNTING(ModifierKeyDataArray) + + public: + Modifiers GetActiveModifiers() const; + void ActivateModifierKey(const ModifierKeyData& aModifierKeyData); + void InactivateModifierKey(const ModifierKeyData& aModifierKeyData); + void ToggleModifierKey(const ModifierKeyData& aModifierKeyData); + + private: + virtual ~ModifierKeyDataArray() = default; + }; + + void EnsureModifierKeyDataArray() { + if (mModifierKeyDataArray) { + return; + } + mModifierKeyDataArray = new ModifierKeyDataArray(); + } + void ActivateModifierKey(const ModifierKeyData& aModifierKeyData) { + EnsureModifierKeyDataArray(); + mModifierKeyDataArray->ActivateModifierKey(aModifierKeyData); + } + void InactivateModifierKey(const ModifierKeyData& aModifierKeyData) { + if (!mModifierKeyDataArray) { + return; + } + mModifierKeyDataArray->InactivateModifierKey(aModifierKeyData); + } + void ToggleModifierKey(const ModifierKeyData& aModifierKeyData) { + EnsureModifierKeyDataArray(); + mModifierKeyDataArray->ToggleModifierKey(aModifierKeyData); + } + + TextEventDispatcher* mDispatcher; // [Weak] + nsCOMPtr<nsITextInputProcessorCallback> mCallback; + RefPtr<ModifierKeyDataArray> mModifierKeyDataArray; + + bool mForTests; +}; + +} // namespace mozilla + +#endif // #ifndef mozilla_dom_textinputprocessor_h_ |