2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2015-01-28 09:27:32 +03:00
|
|
|
/* 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_
|
|
|
|
|
2015-02-19 09:50:20 +03:00
|
|
|
#include "mozilla/Attributes.h"
|
2015-02-19 09:50:19 +03:00
|
|
|
#include "mozilla/EventForwards.h"
|
2018-10-03 12:21:47 +03:00
|
|
|
#include "mozilla/Maybe.h"
|
2015-08-04 12:52:00 +03:00
|
|
|
#include "mozilla/TextEventDispatcher.h"
|
2015-01-28 09:27:32 +03:00
|
|
|
#include "mozilla/TextEventDispatcherListener.h"
|
2015-01-28 09:27:32 +03:00
|
|
|
#include "nsITextInputProcessor.h"
|
2015-01-28 09:27:33 +03:00
|
|
|
#include "nsITextInputProcessorCallback.h"
|
2015-02-19 09:50:19 +03:00
|
|
|
#include "nsTArray.h"
|
2015-01-28 09:27:32 +03:00
|
|
|
|
2018-10-02 15:16:45 +03:00
|
|
|
class nsPIDOMWindowInner;
|
|
|
|
|
2015-01-28 09:27:32 +03:00
|
|
|
namespace mozilla {
|
|
|
|
|
2018-02-09 19:17:10 +03:00
|
|
|
namespace dom {
|
|
|
|
class KeyboardEvent;
|
|
|
|
} // namespace dom
|
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class TextInputProcessor final : public nsITextInputProcessor,
|
2015-03-27 21:52:19 +03:00
|
|
|
public widget::TextEventDispatcherListener {
|
2015-01-28 09:27:32 +03:00
|
|
|
typedef mozilla::widget::IMENotification IMENotification;
|
2017-04-11 15:24:55 +03:00
|
|
|
typedef mozilla::widget::IMENotificationRequests IMENotificationRequests;
|
2015-01-28 09:27:32 +03:00
|
|
|
typedef mozilla::widget::TextEventDispatcher TextEventDispatcher;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TextInputProcessor();
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSITEXTINPUTPROCESSOR
|
|
|
|
|
2015-01-28 09:27:32 +03:00
|
|
|
// TextEventDispatcherListener
|
|
|
|
NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
2015-03-21 19:28:04 +03:00
|
|
|
const IMENotification& aNotification) override;
|
Bug 1343075 - Use GeckoEditableSupport from PuppetWidget; r=masayuki r=rbarker r=snorp r=esawin
Bug 1343075 - 1a. Add TextEventDispatcherListener::GetIMEUpdatePreference; r=masayuki
Add a GetIMEUpdatePreference method to TextEventDispatcherListener to
optionally control which IME notifications are received by NotifyIME.
This patch also makes nsBaseWidget forward its GetIMEUpdatePreference
call to the widget's native TextEventDispatcherListener.
Bug 1343075 - 1b. Implement GetIMEUpdatePreference for all TextEventDispatcherListener; r=masayuki
This patch implements GetIMEUpdatePreference for all
TextEventDispatcherListener implementations, by moving previous
implementations of nsIWidget::GetIMEUpdatePreference.
Bug 1343075 - 2. Allow setting a PuppetWidget's native TextEventDispatcherListener; r=masayuki
In PuppetWidget, add getter and setter for the widget's native
TextEventDispatcherListener. This allows overriding of PuppetWidget's
default IME handling. For example, on Android, the PuppetWidget's native
TextEventDispatcherListener will communicate directly with Java IME code
in the main process.
Bug 1343075 - 3. Add AIDL interface for main process; r=rbarker
Add AIDL definition and implementation for an interface for the main
process that child processes can access.
Bug 1343075 - 4. Set Gecko thread JNIEnv for child process; r=snorp
Add a JNIEnv* parameter to XRE_SetAndroidChildFds, which is used to set
the Gecko thread JNIEnv for child processes. XRE_SetAndroidChildFds is
the only Android-specific entry point for child processes, so I think
it's the most logical place to initialize JNI.
Bug 1343075 - 5. Support multiple remote GeckoEditableChild; r=esawin
Support remote GeckoEditableChild instances that are created in the
content processes and connect to the parent process GeckoEditableParent
through binders.
Support having multiple GeckoEditableChild instances in GeckoEditable by
keeping track of which child is currently focused, and only allow
calls to/from the focused child by using access tokens.
Bug 1343075 - 6. Add method to get GeckoEditableParent instance; r=esawin
Add IProcessManager.getEditableParent, which a content process can call
to get the GeckoEditableParent instance that corresponds to a given
content process tab, from the main process.
Bug 1343075 - 7. Support GeckoEditableSupport in content processes; r=esawin
Support creating and running GeckoEditableSupport attached to a
PuppetWidget in content processes.
Because we don't know PuppetWidget's lifetime as well as nsWindow's,
when attached to PuppetWidget, we need to attach/detach our native
object on focus/blur, respectively.
Bug 1343075 - 8. Connect GeckoEditableSupport on PuppetWidget creation; r=esawin
Listen to the "tab-child-created" notification and attach our content
process GeckoEditableSupport to the new PuppetWidget.
Bug 1343075 - 9. Update auto-generated bindings; r=me
2017-03-08 06:34:39 +03:00
|
|
|
|
2017-04-11 15:24:55 +03:00
|
|
|
NS_IMETHOD_(IMENotificationRequests) GetIMENotificationRequests() override;
|
Bug 1343075 - Use GeckoEditableSupport from PuppetWidget; r=masayuki r=rbarker r=snorp r=esawin
Bug 1343075 - 1a. Add TextEventDispatcherListener::GetIMEUpdatePreference; r=masayuki
Add a GetIMEUpdatePreference method to TextEventDispatcherListener to
optionally control which IME notifications are received by NotifyIME.
This patch also makes nsBaseWidget forward its GetIMEUpdatePreference
call to the widget's native TextEventDispatcherListener.
Bug 1343075 - 1b. Implement GetIMEUpdatePreference for all TextEventDispatcherListener; r=masayuki
This patch implements GetIMEUpdatePreference for all
TextEventDispatcherListener implementations, by moving previous
implementations of nsIWidget::GetIMEUpdatePreference.
Bug 1343075 - 2. Allow setting a PuppetWidget's native TextEventDispatcherListener; r=masayuki
In PuppetWidget, add getter and setter for the widget's native
TextEventDispatcherListener. This allows overriding of PuppetWidget's
default IME handling. For example, on Android, the PuppetWidget's native
TextEventDispatcherListener will communicate directly with Java IME code
in the main process.
Bug 1343075 - 3. Add AIDL interface for main process; r=rbarker
Add AIDL definition and implementation for an interface for the main
process that child processes can access.
Bug 1343075 - 4. Set Gecko thread JNIEnv for child process; r=snorp
Add a JNIEnv* parameter to XRE_SetAndroidChildFds, which is used to set
the Gecko thread JNIEnv for child processes. XRE_SetAndroidChildFds is
the only Android-specific entry point for child processes, so I think
it's the most logical place to initialize JNI.
Bug 1343075 - 5. Support multiple remote GeckoEditableChild; r=esawin
Support remote GeckoEditableChild instances that are created in the
content processes and connect to the parent process GeckoEditableParent
through binders.
Support having multiple GeckoEditableChild instances in GeckoEditable by
keeping track of which child is currently focused, and only allow
calls to/from the focused child by using access tokens.
Bug 1343075 - 6. Add method to get GeckoEditableParent instance; r=esawin
Add IProcessManager.getEditableParent, which a content process can call
to get the GeckoEditableParent instance that corresponds to a given
content process tab, from the main process.
Bug 1343075 - 7. Support GeckoEditableSupport in content processes; r=esawin
Support creating and running GeckoEditableSupport attached to a
PuppetWidget in content processes.
Because we don't know PuppetWidget's lifetime as well as nsWindow's,
when attached to PuppetWidget, we need to attach/detach our native
object on focus/blur, respectively.
Bug 1343075 - 8. Connect GeckoEditableSupport on PuppetWidget creation; r=esawin
Listen to the "tab-child-created" notification and attach our content
process GeckoEditableSupport to the new PuppetWidget.
Bug 1343075 - 9. Update auto-generated bindings; r=me
2017-03-08 06:34:39 +03:00
|
|
|
|
2015-01-28 09:27:32 +03:00
|
|
|
NS_IMETHOD_(void)
|
2015-03-21 19:28:04 +03:00
|
|
|
OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override;
|
2015-01-28 09:27:32 +03:00
|
|
|
|
2016-03-16 07:47:48 +03:00
|
|
|
NS_IMETHOD_(void)
|
|
|
|
WillDispatchKeyboardEvent(TextEventDispatcher* aTextEventDispatcher,
|
|
|
|
WidgetKeyboardEvent& aKeyboardEvent,
|
|
|
|
uint32_t aIndexOfKeypress, void* aData) override;
|
|
|
|
|
2018-10-02 15:16:45 +03:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
nsresult Keydown(const WidgetKeyboardEvent& aKeyboardEvent,
|
|
|
|
uint32_t aKeyFlags, uint32_t* aConsumedFlags = nullptr);
|
|
|
|
nsresult Keyup(const WidgetKeyboardEvent& aKeyboardEvent, uint32_t aKeyFlags,
|
|
|
|
bool* aDoDefault = nullptr);
|
|
|
|
|
2018-10-03 12:21:47 +03:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
|
2018-10-03 12:24:15 +03:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
|
2015-01-28 09:27:33 +03:00
|
|
|
protected:
|
|
|
|
virtual ~TextInputProcessor();
|
2015-01-28 09:27:32 +03:00
|
|
|
|
2015-01-28 09:27:33 +03:00
|
|
|
private:
|
2015-02-19 09:50:20 +03:00
|
|
|
bool IsComposing() const;
|
2015-02-10 11:09:29 +03:00
|
|
|
nsresult BeginInputTransactionInternal(
|
|
|
|
mozIDOMWindow* aWindow, nsITextInputProcessorCallback* aCallback,
|
|
|
|
bool aForTests, bool& aSucceeded);
|
2015-02-19 09:50:20 +03:00
|
|
|
nsresult CommitCompositionInternal(
|
|
|
|
const WidgetKeyboardEvent* aKeyboardEvent = nullptr,
|
|
|
|
uint32_t aKeyFlags = 0, const nsAString* aCommitString = nullptr,
|
|
|
|
bool* aSucceeded = nullptr);
|
|
|
|
nsresult CancelCompositionInternal(
|
|
|
|
const WidgetKeyboardEvent* aKeyboardEvent = nullptr,
|
|
|
|
uint32_t aKeyFlags = 0);
|
|
|
|
nsresult KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
|
|
|
|
uint32_t aKeyFlags, bool aAllowToDispatchKeypress,
|
2015-08-05 08:58:00 +03:00
|
|
|
uint32_t& aConsumedFlags);
|
2015-02-19 09:50:20 +03:00
|
|
|
nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
|
|
|
|
uint32_t aKeyFlags, bool& aDoDefault);
|
2015-01-28 09:27:32 +03:00
|
|
|
nsresult IsValidStateForComposition();
|
|
|
|
void UnlinkFromTextEventDispatcher();
|
2015-02-19 09:50:19 +03:00
|
|
|
nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent,
|
|
|
|
uint32_t aKeyFlags);
|
2015-02-19 09:50:20 +03:00
|
|
|
bool IsValidEventTypeForComposition(
|
|
|
|
const WidgetKeyboardEvent& aKeyboardEvent) const;
|
|
|
|
nsresult PrepareKeyboardEventForComposition(
|
2018-02-09 19:17:10 +03:00
|
|
|
dom::KeyboardEvent* aDOMKeyEvent, uint32_t& aKeyFlags,
|
2015-02-19 09:50:20 +03:00
|
|
|
uint8_t aOptionalArgc, WidgetKeyboardEvent*& aKeyboardEvent);
|
|
|
|
|
|
|
|
struct EventDispatcherResult {
|
|
|
|
nsresult mResult;
|
|
|
|
bool mDoDefault;
|
|
|
|
bool mCanContinue;
|
|
|
|
|
|
|
|
EventDispatcherResult()
|
|
|
|
: mResult(NS_OK), mDoDefault(true), mCanContinue(true) {}
|
|
|
|
};
|
|
|
|
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:
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<TextInputProcessor> mTIP;
|
2015-02-19 09:50:20 +03:00
|
|
|
};
|
2015-01-28 09:27:32 +03:00
|
|
|
|
2015-02-19 09:50:19 +03:00
|
|
|
/**
|
|
|
|
* 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> {
|
2015-02-19 09:50:19 +03:00
|
|
|
NS_INLINE_DECL_REFCOUNTING(ModifierKeyDataArray)
|
|
|
|
|
2015-02-19 09:50:19 +03:00
|
|
|
public:
|
|
|
|
Modifiers GetActiveModifiers() const;
|
|
|
|
void ActivateModifierKey(const ModifierKeyData& aModifierKeyData);
|
|
|
|
void InactivateModifierKey(const ModifierKeyData& aModifierKeyData);
|
|
|
|
void ToggleModifierKey(const ModifierKeyData& aModifierKeyData);
|
2015-02-19 09:50:19 +03:00
|
|
|
|
|
|
|
private:
|
2020-02-21 13:41:47 +03:00
|
|
|
virtual ~ModifierKeyDataArray() = default;
|
2015-02-19 09:50:19 +03:00
|
|
|
};
|
|
|
|
|
2015-02-19 09:50:19 +03:00
|
|
|
void EnsureModifierKeyDataArray() {
|
|
|
|
if (mModifierKeyDataArray) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mModifierKeyDataArray = new ModifierKeyDataArray();
|
2015-02-19 09:50:19 +03:00
|
|
|
}
|
|
|
|
void ActivateModifierKey(const ModifierKeyData& aModifierKeyData) {
|
2015-02-19 09:50:19 +03:00
|
|
|
EnsureModifierKeyDataArray();
|
|
|
|
mModifierKeyDataArray->ActivateModifierKey(aModifierKeyData);
|
2015-02-19 09:50:19 +03:00
|
|
|
}
|
|
|
|
void InactivateModifierKey(const ModifierKeyData& aModifierKeyData) {
|
2015-02-19 09:50:19 +03:00
|
|
|
if (!mModifierKeyDataArray) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mModifierKeyDataArray->InactivateModifierKey(aModifierKeyData);
|
2015-02-19 09:50:19 +03:00
|
|
|
}
|
|
|
|
void ToggleModifierKey(const ModifierKeyData& aModifierKeyData) {
|
2015-02-19 09:50:19 +03:00
|
|
|
EnsureModifierKeyDataArray();
|
|
|
|
mModifierKeyDataArray->ToggleModifierKey(aModifierKeyData);
|
2015-02-19 09:50:19 +03:00
|
|
|
}
|
|
|
|
|
2015-01-28 09:27:32 +03:00
|
|
|
TextEventDispatcher* mDispatcher; // [Weak]
|
2015-01-28 09:27:33 +03:00
|
|
|
nsCOMPtr<nsITextInputProcessorCallback> mCallback;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<ModifierKeyDataArray> mModifierKeyDataArray;
|
2015-02-19 09:50:19 +03:00
|
|
|
|
2015-01-28 09:27:32 +03:00
|
|
|
bool mForTests;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // #ifndef mozilla_dom_textinputprocessor_h_
|