зеркало из https://github.com/mozilla/gecko-dev.git
Bug 998941 - part 1-2: Make editor set InputEvent.data to inserting text when it sets InputEvent.inputType to "insertText" or "insertCompositionText" r=smaug,m_kato
This patch makes nsContentUtils::DispatchInputEvent() support to set InputEvent.data. Whether the its value should be null or DOMString depends on InputEvent.inputType value. - https://rawgit.com/w3c/input-events/v1/index.html#overview - https://rawgit.com/w3c/input-events/v1/index.html#dfn-data - https://w3c.github.io/input-events/#overview - https://w3c.github.io/input-events/#dfn-data According to the draft specs, InputEvent.data should be always inserting text when inputType is "insertText" or "insertCompositionText" (or "insertFromCompoition" if Level 2 support is enabled). Differential Revision: https://phabricator.services.mozilla.com/D19286 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0f145fc8e5
Коммит
a3484e40c0
|
@ -4128,13 +4128,14 @@ nsresult nsContentUtils::DispatchEvent(Document* aDoc, nsISupports* aTarget,
|
|||
nsresult nsContentUtils::DispatchInputEvent(Element* aEventTargetElement) {
|
||||
RefPtr<TextEditor> textEditor; // See bug 1506439
|
||||
return DispatchInputEvent(aEventTargetElement, EditorInputType::eUnknown,
|
||||
textEditor);
|
||||
textEditor, InputEventOptions());
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult nsContentUtils::DispatchInputEvent(Element* aEventTargetElement,
|
||||
EditorInputType aEditorInputType,
|
||||
TextEditor* aTextEditor) {
|
||||
TextEditor* aTextEditor,
|
||||
const InputEventOptions& aOptions) {
|
||||
if (NS_WARN_IF(!aEventTargetElement)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -4231,6 +4232,31 @@ nsresult nsContentUtils::DispatchInputEvent(Element* aEventTargetElement,
|
|||
inputEvent.mIsComposing =
|
||||
aTextEditor ? !!aTextEditor->GetComposition() : false;
|
||||
|
||||
if (!aTextEditor || !aTextEditor->AsHTMLEditor()) {
|
||||
if (IsDataAvailableOnTextEditor(aEditorInputType)) {
|
||||
inputEvent.mData = aOptions.mData;
|
||||
MOZ_ASSERT(!inputEvent.mData.IsVoid(),
|
||||
"inputEvent.mData shouldn't be void");
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
MOZ_ASSERT(inputEvent.mData.IsVoid(), "inputEvent.mData should be void");
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
} else {
|
||||
MOZ_ASSERT(aTextEditor->AsHTMLEditor());
|
||||
if (IsDataAvailableOnHTMLEditor(aEditorInputType)) {
|
||||
inputEvent.mData = aOptions.mData;
|
||||
MOZ_ASSERT(!inputEvent.mData.IsVoid(),
|
||||
"inputEvent.mData shouldn't be void");
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
MOZ_ASSERT(inputEvent.mData.IsVoid(), "inputEvent.mData should be void");
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
}
|
||||
|
||||
inputEvent.mInputType = aEditorInputType;
|
||||
|
||||
(new AsyncEventDispatcher(aEventTargetElement, inputEvent))
|
||||
|
|
|
@ -1415,13 +1415,23 @@ class nsContentUtils {
|
|||
* @param aTextEditor Optional. If this is called by editor,
|
||||
* editor should set this. Otherwise, leave
|
||||
* nullptr.
|
||||
* @param aOptions Optional. If aEditorInputType value requires
|
||||
* some additional data, they should be properly
|
||||
* set with this argument.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
static nsresult DispatchInputEvent(Element* aEventTarget);
|
||||
struct MOZ_STACK_CLASS InputEventOptions final {
|
||||
InputEventOptions() = default;
|
||||
explicit InputEventOptions(const nsAString& aData) : mData(aData) {}
|
||||
|
||||
nsString mData;
|
||||
};
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
static nsresult DispatchInputEvent(Element* aEventTarget,
|
||||
mozilla::EditorInputType aEditorInputType,
|
||||
mozilla::TextEditor* aTextEditor);
|
||||
mozilla::TextEditor* aTextEditor,
|
||||
const InputEventOptions& aOptions);
|
||||
|
||||
/**
|
||||
* This method creates and dispatches a untrusted event.
|
||||
|
|
|
@ -59,7 +59,7 @@ function onunload()
|
|||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function checkInputEvent(aEvent, aIsComposing, aInputType, aDescription) {
|
||||
function checkInputEvent(aEvent, aIsComposing, aInputType, aData, aDescription) {
|
||||
if (aEvent.type != "input") {
|
||||
return;
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ function checkInputEvent(aEvent, aIsComposing, aInputType, aDescription) {
|
|||
is(aEvent.bubbles, true, `${aDescription}"input" event should always bubble`);
|
||||
is(aEvent.isComposing, aIsComposing, `${aDescription}isComposing should be ${aIsComposing}`);
|
||||
is(aEvent.inputType, aInputType, `${aDescription}inputType should be "${aInputType}"`);
|
||||
is(aEvent.data, aData, `${aDescription}data should be "${aData}"`);
|
||||
}
|
||||
|
||||
const kIsMac = (navigator.platform.indexOf("Mac") == 0);
|
||||
|
@ -233,7 +234,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[2] should be text");
|
||||
is(events[3].type, "input",
|
||||
description + "events[3] should be input");
|
||||
checkInputEvent(events[3], true, "insertCompositionText", description);
|
||||
checkInputEvent(events[3], true, "insertCompositionText", composingStr, description);
|
||||
TIP1.cancelComposition();
|
||||
|
||||
// Let's check if beginInputTransaction() fails to steal the rights of TextEventDispatcher during commitComposition().
|
||||
|
@ -269,7 +270,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[1] should be compositionend");
|
||||
is(events[2].type, "input",
|
||||
description + "events[2] should be input");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[2], false, "insertCompositionText", composingStr, description);
|
||||
|
||||
// Let's check if beginInputTransaction() fails to steal the rights of TextEventDispatcher during commitCompositionWith("bar").
|
||||
events = [];
|
||||
|
@ -317,7 +318,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[3] should be compositionend");
|
||||
is(events[4].type, "input",
|
||||
description + "events[4] should be input");
|
||||
checkInputEvent(events[4], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[4], false, "insertCompositionText", "bar", description);
|
||||
|
||||
// Let's check if beginInputTransaction() fails to steal the rights of TextEventDispatcher during cancelComposition().
|
||||
events = [];
|
||||
|
@ -360,7 +361,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[2] should be compositionend");
|
||||
is(events[3].type, "input",
|
||||
description + "events[3] should be input");
|
||||
checkInputEvent(events[3], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[3], false, "insertCompositionText", "", description);
|
||||
|
||||
// Let's check if beginInputTransaction() fails to steal the rights of TextEventDispatcher during keydown() and keyup().
|
||||
events = [];
|
||||
|
@ -400,7 +401,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[1] should be keypress");
|
||||
is(events[2].type, "input",
|
||||
description + "events[2] should be input");
|
||||
checkInputEvent(events[2], false, "insertText", description);
|
||||
checkInputEvent(events[2], false, "insertText", "a", description);
|
||||
is(events[3].type, "keyup",
|
||||
description + "events[3] should be keyup");
|
||||
|
||||
|
@ -458,7 +459,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[2] should be text");
|
||||
is(events[3].type, "input",
|
||||
description + "events[3] should be input");
|
||||
checkInputEvent(events[3], true, "insertCompositionText", description);
|
||||
checkInputEvent(events[3], true, "insertCompositionText", composingStr, description);
|
||||
TIP1.cancelComposition();
|
||||
|
||||
// Let's check if beginInputTransactionForTests() fails to steal the rights of TextEventDispatcher during commitComposition().
|
||||
|
@ -494,7 +495,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[1] should be compositionend");
|
||||
is(events[2].type, "input",
|
||||
description + "events[2] should be input");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[2], false, "insertCompositionText", composingStr, description);
|
||||
|
||||
// Let's check if beginInputTransactionForTests() fails to steal the rights of TextEventDispatcher during commitCompositionWith("bar").
|
||||
events = [];
|
||||
|
@ -542,7 +543,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[3] should be compositionend");
|
||||
is(events[4].type, "input",
|
||||
description + "events[4] should be input");
|
||||
checkInputEvent(events[4], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[4], false, "insertCompositionText", "bar", description);
|
||||
|
||||
// Let's check if beginInputTransactionForTests() fails to steal the rights of TextEventDispatcher during cancelComposition().
|
||||
events = [];
|
||||
|
@ -585,7 +586,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[2] should be compositionend");
|
||||
is(events[3].type, "input",
|
||||
description + "events[3] should be input");
|
||||
checkInputEvent(events[3], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[3], false, "insertCompositionText", "", description);
|
||||
|
||||
// Let's check if beginInputTransactionForTests() fails to steal the rights of TextEventDispatcher during keydown() and keyup().
|
||||
events = [];
|
||||
|
@ -625,7 +626,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[1] should be keypress");
|
||||
is(events[2].type, "input",
|
||||
description + "events[2] should be input");
|
||||
checkInputEvent(events[2], false, "insertText", description);
|
||||
checkInputEvent(events[2], false, "insertText", "a", description);
|
||||
is(events[3].type, "keyup",
|
||||
description + "events[3] should be keyup");
|
||||
|
||||
|
@ -713,7 +714,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[2] should be text");
|
||||
is(events[3].type, "input",
|
||||
description + "events[3] should be input");
|
||||
checkInputEvent(events[3], true, "insertCompositionText", description);
|
||||
checkInputEvent(events[3], true, "insertCompositionText", composingStr, description);
|
||||
TIP1.cancelComposition();
|
||||
|
||||
// Let's check if beginInputTransaction() with another window fails to begin new input transaction with different TextEventDispatcher during commitComposition().
|
||||
|
@ -767,7 +768,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[1] should be compositionend");
|
||||
is(events[2].type, "input",
|
||||
description + "events[2] should be input");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[2], false, "insertCompositionText", composingStr, description);
|
||||
|
||||
// Let's check if beginInputTransaction() with another window fails to begin new input transaction with different TextEventDispatcher during commitCompositionWith("bar");.
|
||||
events = [];
|
||||
|
@ -845,7 +846,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[3] should be compositionend");
|
||||
is(events[4].type, "input",
|
||||
description + "events[4] should be input");
|
||||
checkInputEvent(events[4], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[4], false, "insertCompositionText", "bar", description);
|
||||
|
||||
// Let's check if beginInputTransaction() with another window fails to begin new input transaction with different TextEventDispatcher during cancelComposition();.
|
||||
events = [];
|
||||
|
@ -912,7 +913,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[2] should be compositionend");
|
||||
is(events[3].type, "input",
|
||||
description + "events[3] should be input");
|
||||
checkInputEvent(events[3], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[3], false, "insertCompositionText", "", description);
|
||||
|
||||
// Let's check if beginInputTransaction() with another window fails to begin new input transaction with different TextEventDispatcher during keydown() and keyup();.
|
||||
events = [];
|
||||
|
@ -976,7 +977,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[1] should be keypress");
|
||||
is(events[2].type, "input",
|
||||
description + "events[2] should be input");
|
||||
checkInputEvent(events[2], false, "insertText", description);
|
||||
checkInputEvent(events[2], false, "insertText", "a", description);
|
||||
is(events[3].type, "keyup",
|
||||
description + "events[3] should be keyup");
|
||||
|
||||
|
@ -1064,7 +1065,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[2] should be text");
|
||||
is(events[3].type, "input",
|
||||
description + "events[3] should be input");
|
||||
checkInputEvent(events[3], true, "insertCompositionText", description);
|
||||
checkInputEvent(events[3], true, "insertCompositionText", composingStr, description);
|
||||
TIP1.cancelComposition();
|
||||
|
||||
// Let's check if beginInputTransactionForTests() with another window fails to begin new input transaction with different TextEventDispatcher during commitComposition().
|
||||
|
@ -1118,7 +1119,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[1] should be compositionend");
|
||||
is(events[2].type, "input",
|
||||
description + "events[2] should be input");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[2], false, "insertCompositionText", composingStr, description);
|
||||
|
||||
// Let's check if beginInputTransactionForTests() with another window fails to begin new input transaction with different TextEventDispatcher during commitCompositionWith("bar");.
|
||||
events = [];
|
||||
|
@ -1196,7 +1197,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[3] should be compositionend");
|
||||
is(events[4].type, "input",
|
||||
description + "events[4] should be input");
|
||||
checkInputEvent(events[4], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[4], false, "insertCompositionText", "bar", description);
|
||||
|
||||
// Let's check if beginInputTransactionForTests() with another window fails to begin new input transaction with different TextEventDispatcher during cancelComposition();.
|
||||
events = [];
|
||||
|
@ -1263,7 +1264,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[2] should be compositionend");
|
||||
is(events[3].type, "input",
|
||||
description + "events[3] should be input");
|
||||
checkInputEvent(events[3], false, "insertCompositionText", description);
|
||||
checkInputEvent(events[3], false, "insertCompositionText", "", description);
|
||||
|
||||
// Let's check if beginInputTransactionForTests() with another window fails to begin new input transaction with different TextEventDispatcher during keydown() and keyup();.
|
||||
events = [];
|
||||
|
@ -1327,7 +1328,7 @@ function runBeginInputTransactionMethodTests()
|
|||
description + "events[1] should be keypress");
|
||||
is(events[2].type, "input",
|
||||
description + "events[2] should be input");
|
||||
checkInputEvent(events[2], false, "insertText", description);
|
||||
checkInputEvent(events[2], false, "insertText", "a", description);
|
||||
is(events[3].type, "keyup",
|
||||
description + "events[3] should be keyup");
|
||||
|
||||
|
|
|
@ -2434,7 +2434,8 @@ bool nsTextEditorState::SetValue(const nsAString& aValue,
|
|||
MOZ_ASSERT(element);
|
||||
RefPtr<TextEditor> textEditor; // See bug 1506439
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(
|
||||
element, EditorInputType::eInsertReplacementText, textEditor);
|
||||
element, EditorInputType::eInsertReplacementText, textEditor,
|
||||
nsContentUtils::InputEventOptions());
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
|
||||
|
||||
let expectedInputType = "";
|
||||
let expectedData = null;
|
||||
function checkIfInputIsInputEvent(aEvent, aToDo, aDescription) {
|
||||
if (aToDo) {
|
||||
// Probably, key operation should fire "input" event with InputEvent interface.
|
||||
|
@ -52,6 +53,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
`"input" event should be dispatched with InputEvent interface ${aDescription}`);
|
||||
is(aEvent.inputType, expectedInputType,
|
||||
`inputType should be "${expectedInputType}" ${aDescription}`);
|
||||
is(aEvent.data, expectedData,
|
||||
`data should be ${expectedData} ${aDescription}`);
|
||||
}
|
||||
is(aEvent.cancelable, false,
|
||||
`"input" event should be never cancelable ${aDescription}`);
|
||||
|
@ -132,17 +135,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
input = document.getElementById("input_" + textTypes[i]);
|
||||
input.focus();
|
||||
expectedInputType = "insertLineBreak";
|
||||
expectedData = null;
|
||||
synthesizeKey("KEY_Enter");
|
||||
is(textInput[i], 0, "input event shouldn't be dispatched on " + textTypes[i] + " input element");
|
||||
|
||||
expectedInputType = "insertText";
|
||||
expectedData = "m";
|
||||
sendString("m");
|
||||
is(textInput[i], 1, textTypes[i] + " input element should have dispatched input event.");
|
||||
expectedInputType = "insertLineBreak";
|
||||
expectedData = null;
|
||||
synthesizeKey("KEY_Enter");
|
||||
is(textInput[i], 1, "input event shouldn't be dispatched on " + textTypes[i] + " input element");
|
||||
|
||||
expectedInputType = "deleteContentBackward";
|
||||
expectedData = null;
|
||||
synthesizeKey("KEY_Backspace");
|
||||
is(textInput[i], 2, textTypes[i] + " input element should have dispatched input event.");
|
||||
}
|
||||
|
@ -151,13 +158,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
input = document.getElementById("input_text");
|
||||
input.focus();
|
||||
expectedInputType = "insertText";
|
||||
expectedData = "f";
|
||||
sendString("f");
|
||||
is(textInput[0], 3, "input event should have been dispatched");
|
||||
input.blur();
|
||||
is(textInput[0], 3, "input event should not have been dispatched");
|
||||
|
||||
input.focus();
|
||||
expectedInputType = "insertText";
|
||||
input.value = 'foo';
|
||||
is(textInput[0], 3, "input event should not have been dispatched");
|
||||
input.blur();
|
||||
|
@ -165,6 +172,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
|
||||
input.focus();
|
||||
expectedInputType = "insertText";
|
||||
expectedData = "f";
|
||||
sendString("f");
|
||||
is(textInput[0], 4, "input event should have been dispatched");
|
||||
input.value = 'bar';
|
||||
|
@ -176,6 +184,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
var textarea = document.getElementById("textarea");
|
||||
textarea.focus();
|
||||
expectedInputType = "insertText";
|
||||
expectedData = "f";
|
||||
sendString("f");
|
||||
is(textareaInput, 1, "input event should have been dispatched");
|
||||
textarea.blur();
|
||||
|
@ -189,11 +198,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
|
||||
textarea.focus();
|
||||
expectedInputType = "insertText";
|
||||
expectedData = "f";
|
||||
sendString("f");
|
||||
is(textareaInput, 2, "input event should have been dispatched");
|
||||
textarea.value = 'bar';
|
||||
is(textareaInput, 2, "input event should not have been dispatched");
|
||||
expectedInputType = "deleteContentBackward";
|
||||
expectedData = null;
|
||||
synthesizeKey("KEY_Backspace");
|
||||
is(textareaInput, 3, "input event should have been dispatched");
|
||||
textarea.blur();
|
||||
|
@ -277,6 +288,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
// <input type="number">'s inputType value hasn't been decided, see
|
||||
// https://github.com/w3c/input-events/issues/88
|
||||
expectedInputType = "";
|
||||
expectedData = null;
|
||||
synthesizeKey("KEY_ArrowUp");
|
||||
is(numberInput, 1, "input event should be dispatched for up/down arrow key keypress");
|
||||
is(number.value, "1", "sanity check value of number control after keypress");
|
||||
|
|
|
@ -2030,7 +2030,8 @@ void EditorBase::NotifyEditorObservers(
|
|||
}
|
||||
}
|
||||
|
||||
void EditorBase::FireInputEvent(EditAction aEditAction) {
|
||||
void EditorBase::FireInputEvent(EditAction aEditAction,
|
||||
const nsAString& aData) {
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// We don't need to dispatch multiple input events if there is a pending
|
||||
|
@ -2047,7 +2048,8 @@ void EditorBase::FireInputEvent(EditAction aEditAction) {
|
|||
}
|
||||
RefPtr<TextEditor> textEditor = AsTextEditor();
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(
|
||||
targetElement, ToInputType(aEditAction), textEditor);
|
||||
targetElement, ToInputType(aEditAction), textEditor,
|
||||
nsContentUtils::InputEventOptions(aData));
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
}
|
||||
|
@ -4818,6 +4820,7 @@ EditorBase::AutoEditActionDataSetter::AutoEditActionDataSetter(
|
|||
const EditorBase& aEditorBase, EditAction aEditAction)
|
||||
: mEditorBase(const_cast<EditorBase&>(aEditorBase)),
|
||||
mParentData(aEditorBase.mEditActionData),
|
||||
mData(VoidString()),
|
||||
mTopLevelEditSubAction(EditSubAction::eNone) {
|
||||
// If we're nested edit action, copies necessary data from the parent.
|
||||
if (mParentData) {
|
||||
|
|
|
@ -649,6 +649,9 @@ class EditorBase : public nsIEditor,
|
|||
const RefPtr<Selection>& SelectionRefPtr() const { return mSelection; }
|
||||
EditAction GetEditAction() const { return mEditAction; }
|
||||
|
||||
void SetData(const nsAString& aData) { mData = aData; }
|
||||
const nsString& GetData() const { return mData; }
|
||||
|
||||
void SetTopLevelEditSubAction(EditSubAction aEditSubAction,
|
||||
EDirection aDirection = eNone) {
|
||||
mTopLevelEditSubAction = aEditSubAction;
|
||||
|
@ -756,6 +759,9 @@ class EditorBase : public nsIEditor,
|
|||
// Utility class object for maintaining preserved ranges.
|
||||
RangeUpdater mRangeUpdater;
|
||||
|
||||
// The data should be set to InputEvent.data.
|
||||
nsString mData;
|
||||
|
||||
EditAction mEditAction;
|
||||
EditSubAction mTopLevelEditSubAction;
|
||||
EDirection mDirectionOfTopLevelEditSubAction;
|
||||
|
@ -800,6 +806,14 @@ class EditorBase : public nsIEditor,
|
|||
: EditAction::eNone;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetInputEventData() returns inserting or inserted text value with
|
||||
* current edit action. The result is proper for InputEvent.data value.
|
||||
*/
|
||||
const nsString& GetInputEventData() const {
|
||||
return mEditActionData ? mEditActionData->GetData() : VoidString();
|
||||
}
|
||||
|
||||
/**
|
||||
* GetTopLevelEditSubAction() returns the top level edit sub-action.
|
||||
* For example, if selected content is being replaced with inserted text,
|
||||
|
@ -1786,9 +1800,11 @@ class EditorBase : public nsIEditor,
|
|||
* asynchronously if it's not safe to dispatch.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void FireInputEvent() { FireInputEvent(GetEditAction()); }
|
||||
void FireInputEvent() {
|
||||
FireInputEvent(GetEditAction(), GetInputEventData());
|
||||
}
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void FireInputEvent(EditAction aEditAction);
|
||||
void FireInputEvent(EditAction aEditAction, const nsAString& aData);
|
||||
|
||||
/**
|
||||
* Called after a transaction is done successfully.
|
||||
|
|
|
@ -1814,6 +1814,8 @@ nsresult HTMLEditor::InsertTextWithQuotations(
|
|||
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
MOZ_ASSERT(!aStringToInsert.IsVoid());
|
||||
editActionData.SetData(aStringToInsert);
|
||||
|
||||
// The whole operation should be undoable in one transaction:
|
||||
// XXX Why isn't enough to use only AutoPlaceholderBatch here?
|
||||
|
@ -1924,6 +1926,8 @@ nsresult HTMLEditor::InsertAsQuotation(const nsAString& aQuotedText,
|
|||
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
MOZ_ASSERT(!aQuotedText.IsVoid());
|
||||
editActionData.SetData(aQuotedText);
|
||||
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
||||
nsresult rv = InsertAsPlaintextQuotation(aQuotedText, true, aNodeInserted);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -2112,6 +2116,8 @@ HTMLEditor::InsertAsCitedQuotation(const nsAString& aQuotedText,
|
|||
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
MOZ_ASSERT(!aQuotedText.IsVoid());
|
||||
editActionData.SetData(aQuotedText);
|
||||
|
||||
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
||||
nsresult rv = InsertAsPlaintextQuotation(aQuotedText, true, aNodeInserted);
|
||||
|
|
|
@ -406,6 +406,8 @@ nsresult TextEditor::OnInputText(const nsAString& aStringToInsert) {
|
|||
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
MOZ_ASSERT(!aStringToInsert.IsVoid());
|
||||
editActionData.SetData(aStringToInsert);
|
||||
|
||||
AutoPlaceholderBatch treatAsOneTransaction(*this, *nsGkAtoms::TypingTxnName);
|
||||
nsresult rv = InsertTextAsSubAction(aStringToInsert);
|
||||
|
@ -982,6 +984,10 @@ nsresult TextEditor::InsertTextAsAction(const nsAString& aStringToInsert) {
|
|||
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
// Note that we don't need to replace native line breaks with XP line breaks
|
||||
// here because Chrome does not do it.
|
||||
MOZ_ASSERT(!aStringToInsert.IsVoid());
|
||||
editActionData.SetData(aStringToInsert);
|
||||
|
||||
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
||||
nsresult rv = InsertTextAsSubAction(aStringToInsert);
|
||||
|
@ -1284,10 +1290,6 @@ nsresult TextEditor::OnCompositionChange(
|
|||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (!EnsureComposition(aCompositionChangeEvent)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If:
|
||||
// - new composition string is not empty,
|
||||
// - there is no composition string in the DOM tree,
|
||||
|
@ -1298,6 +1300,21 @@ nsresult TextEditor::OnCompositionChange(
|
|||
editActionData.UpdateEditAction(EditAction::eDeleteByComposition);
|
||||
}
|
||||
|
||||
// If Input Events Level 2 is enabled, EditAction::eDeleteByComposition is
|
||||
// mapped to EditorInputType::eDeleteByComposition and it requires null
|
||||
// for InputEvent.data. Therefore, only otherwise, we should set data.
|
||||
if (ToInputType(editActionData.GetEditAction()) !=
|
||||
EditorInputType::eDeleteByComposition) {
|
||||
MOZ_ASSERT(ToInputType(editActionData.GetEditAction()) ==
|
||||
EditorInputType::eInsertCompositionText);
|
||||
MOZ_ASSERT(!aCompositionChangeEvent.mData.IsVoid());
|
||||
editActionData.SetData(aCompositionChangeEvent.mData);
|
||||
}
|
||||
|
||||
if (!EnsureComposition(aCompositionChangeEvent)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (NS_WARN_IF(!presShell)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
@ -1361,6 +1378,16 @@ void TextEditor::OnCompositionEnd(
|
|||
if (NS_WARN_IF(!editActionData.CanHandle())) {
|
||||
return;
|
||||
}
|
||||
// If Input Events Level 2 is enabled, EditAction::eCancelComposition is
|
||||
// mapped to EditorInputType::eDeleteCompositionText and it requires null
|
||||
// for InputEvent.data. Therefore, only otherwise, we should set data.
|
||||
if (ToInputType(editAction) != EditorInputType::eDeleteCompositionText) {
|
||||
MOZ_ASSERT(
|
||||
ToInputType(editAction) == EditorInputType::eInsertCompositionText ||
|
||||
ToInputType(editAction) == EditorInputType::eInsertFromComposition);
|
||||
MOZ_ASSERT(!aCompositionEndEvent.mData.IsVoid());
|
||||
editActionData.SetData(aCompositionEndEvent.mData);
|
||||
}
|
||||
|
||||
// commit the IME transaction..we can get at it via the transaction mgr.
|
||||
// Note that this means IME won't work without an undo stack!
|
||||
|
|
|
@ -306,7 +306,7 @@ nsresult TextEditor::OnDrop(DragEvent* aDropEvent) {
|
|||
|
||||
// Let's fire "input" event for the deletion now.
|
||||
if (mDispatchInputEvent) {
|
||||
FireInputEvent(EditAction::eDeleteByDrag);
|
||||
FireInputEvent(EditAction::eDeleteByDrag, VoidString());
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by 'a' key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertText",
|
||||
aDescription + 'inputType should be "insertText" when typing "a"');
|
||||
is(inputEvent.data, "a",
|
||||
aDescription + 'data should be "a" when typing "a"');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("KEY_Backspace", { }, aWindow);
|
||||
|
@ -103,6 +105,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by BackSpace key wasn't trusted event");
|
||||
is(inputEvent.inputType, "deleteContentBackward",
|
||||
aDescription + 'inputType should be "deleteContentBackward" when pressing "Backspace" with collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Backspace" with collapsed selection');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("B", { shiftKey: true }, aWindow);
|
||||
|
@ -110,6 +114,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by 'B' key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertText",
|
||||
aDescription + 'inputType should be "insertText" when typing "B"');
|
||||
is(inputEvent.data, "B",
|
||||
aDescription + 'data should be "B" when typing "B"');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("KEY_Enter", { }, aWindow);
|
||||
|
@ -117,6 +123,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Enter key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertParagraph",
|
||||
aDescription + 'inputType should be "insertParagraph" when pressing "Enter"');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Enter"');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("C", { shiftKey: true }, aWindow);
|
||||
|
@ -124,6 +132,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by 'C' key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertText",
|
||||
aDescription + 'inputType should be "insertText" when typing "C"');
|
||||
is(inputEvent.data, "C",
|
||||
aDescription + 'data should be "C" when typing "C"');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("KEY_Enter", { }, aWindow);
|
||||
|
@ -131,6 +141,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Enter key (again) wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertParagraph",
|
||||
aDescription + 'inputType should be "insertParagraph" when pressing "Enter" again');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Enter" again');
|
||||
|
||||
inputEvent = null;
|
||||
editTarget.innerHTML = "foo-bar";
|
||||
|
@ -146,6 +158,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Space key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertText",
|
||||
aDescription + 'inputType should be "insertText" when typing " "');
|
||||
is(inputEvent.data, " ",
|
||||
aDescription + 'data should be " " when typing " "');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("KEY_Delete", { }, aWindow);
|
||||
|
@ -161,6 +175,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Delete key wasn't trusted event");
|
||||
is(inputEvent.inputType, "deleteContentForward",
|
||||
aDescription + 'inputType should be "deleteContentForward" when pressing "Delete" with collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Delete" with collapsed selection');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("z", { accelKey: true }, aWindow);
|
||||
|
@ -168,6 +184,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Undo wasn't trusted event");
|
||||
is(inputEvent.inputType, "historyUndo",
|
||||
aDescription + 'inputType should be "historyUndo" when doing "Undo"');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when doing "Undo"');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("z", { accelKey: true, shiftKey: true }, aWindow);
|
||||
|
@ -175,6 +193,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Redo wasn't trusted event");
|
||||
is(inputEvent.inputType, "historyRedo",
|
||||
aDescription + 'inputType should be "historyRedo" when doing "Redo"');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when doing "Redo"');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("KEY_Enter", {shiftKey: true}, aWindow);
|
||||
|
@ -182,6 +202,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Shift + Enter key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertLineBreak",
|
||||
aDescription + 'inputType should be "insertLineBreak" when pressing Shift + "Enter"');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing Shift + "Enter"');
|
||||
|
||||
// Backspace/Delete with non-collapsed selection.
|
||||
editTarget.innerHTML = "a";
|
||||
|
@ -195,6 +217,8 @@ function runTests() {
|
|||
aDescription + 'input event should be trusted when pressing "Backspace" with non-collapsed selection');
|
||||
is(inputEvent.inputType, "deleteContentBackward",
|
||||
aDescription + 'inputType should be "deleteContentBackward" when pressing "Backspace" with non-collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Backspace" with non-collapsed selection');
|
||||
|
||||
editTarget.innerHTML = "a";
|
||||
editTarget.focus();
|
||||
|
@ -207,6 +231,8 @@ function runTests() {
|
|||
aDescription + 'input event should be trusted when pressing "Delete" with non-collapsed selection');
|
||||
is(inputEvent.inputType, "deleteContentForward",
|
||||
aDescription + 'inputType should be "deleteContentBackward" when Delete "Backspace" with non-collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when Delete "Backspace" with non-collapsed selection');
|
||||
|
||||
// Delete to previous/next word boundary with collapsed selection.
|
||||
editTarget.innerHTML = "a";
|
||||
|
@ -221,6 +247,8 @@ function runTests() {
|
|||
aDescription + "input event should be trusted when deleting to previous word boundary with collapsed selection");
|
||||
is(inputEvent.inputType, "deleteWordBackward",
|
||||
aDescription + 'inputType should be "deleteWordBackward" when deleting to previous word boundary with collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + "data should be null when deleting to previous word boundary with collapsed selection");
|
||||
|
||||
editTarget.innerHTML = "a";
|
||||
editTarget.focus();
|
||||
|
@ -234,6 +262,8 @@ function runTests() {
|
|||
aDescription + "input event should be trusted when deleting to next word boundary with collapsed selection");
|
||||
is(inputEvent.inputType, "deleteWordForward",
|
||||
aDescription + 'inputType should be "deleteWordForward" when deleting to next word boundary with collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + "data should be null when deleting to next word boundary with collapsed selection");
|
||||
|
||||
// Delete to previous/next word boundary with non-collapsed selection.
|
||||
editTarget.innerHTML = "abc";
|
||||
|
@ -253,6 +283,8 @@ function runTests() {
|
|||
is(inputEvent.inputType, "deleteContentBackward",
|
||||
aDescription + 'inputType should be "deleteContentBackward" when deleting to previous word boundary with non-collapsed selection');
|
||||
}
|
||||
is(inputEvent.data, null,
|
||||
aDescription + "data should be null when deleting to previous word boundary with non-collapsed selection");
|
||||
|
||||
editTarget.innerHTML = "abc";
|
||||
editTarget.focus();
|
||||
|
@ -271,6 +303,8 @@ function runTests() {
|
|||
is(inputEvent.inputType, "deleteContentForward",
|
||||
aDescription + 'inputType should be "deleteContentForward" when deleting to next word boundary with non-collapsed selection');
|
||||
}
|
||||
is(inputEvent.data, null,
|
||||
aDescription + "data should be null when deleting to next word boundary with non-collapsed selection");
|
||||
|
||||
// Delete to previous/next visual line boundary with collapsed selection.
|
||||
editTarget.innerHTML = "a";
|
||||
|
@ -285,6 +319,8 @@ function runTests() {
|
|||
aDescription + "input event should be trusted when deleting to previous visual line boundary with collapsed selection");
|
||||
is(inputEvent.inputType, "deleteSoftLineBackward",
|
||||
aDescription + 'inputType should be "deleteSoftLineBackward" when deleting to previous visual line boundary with collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + "data should be null when deleting to previous visual line boundary with collapsed selection");
|
||||
|
||||
editTarget.innerHTML = "a";
|
||||
editTarget.focus();
|
||||
|
@ -298,6 +334,8 @@ function runTests() {
|
|||
aDescription + "input event should be trusted when deleting to next visual line boundary with collapsed selection");
|
||||
is(inputEvent.inputType, "deleteSoftLineForward",
|
||||
aDescription + 'inputType should be "deleteSoftLineForward" when deleting to visual line boundary with collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + "data should be null when deleting to visual line boundary with collapsed selection");
|
||||
|
||||
// Delete to previous/next visual line boundary with non-collapsed selection.
|
||||
editTarget.innerHTML = "abc";
|
||||
|
@ -317,6 +355,8 @@ function runTests() {
|
|||
is(inputEvent.inputType, "deleteContentBackward",
|
||||
aDescription + 'inputType should be "deleteContentBackward" when deleting to previous visual line boundary with non-collapsed selection');
|
||||
}
|
||||
is(inputEvent.data, null,
|
||||
aDescription + "data should be null when deleting to previous visual line boundary with non-collapsed selection");
|
||||
|
||||
editTarget.innerHTML = "abc";
|
||||
editTarget.focus();
|
||||
|
@ -335,6 +375,8 @@ function runTests() {
|
|||
is(inputEvent.inputType, "deleteContentForward",
|
||||
aDescription + 'inputType should be "deleteContentForward" when deleting to next visual line boundary with non-collapsed selection');
|
||||
}
|
||||
is(inputEvent.data, null,
|
||||
aDescription + "data should be null when deleting to next visual line boundary with non-collapsed selection");
|
||||
|
||||
aWindow.removeEventListener("input", handler, true);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by 'a' key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertText",
|
||||
aDescription + 'inputType should be "insertText" when typing "a"');
|
||||
is(inputEvent.data, "a",
|
||||
aDescription + 'data should be "a" when typing "a"');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("KEY_Backspace");
|
||||
|
@ -76,6 +78,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by BackSpace key wasn't trusted event");
|
||||
is(inputEvent.inputType, "deleteContentBackward",
|
||||
aDescription + 'inputType should be "deleteContentBackward" when pressing "Backspace" with collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Backspace" with collapsed selection');
|
||||
|
||||
if (aIsTextarea) {
|
||||
inputEvent = null;
|
||||
|
@ -85,6 +89,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Enter key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertLineBreak",
|
||||
aDescription + 'inputType should be "insertLineBreak" when pressing "Enter"');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Enter"');
|
||||
}
|
||||
|
||||
inputEvent = null;
|
||||
|
@ -104,6 +110,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Space key wasn't trusted event");
|
||||
is(inputEvent.inputType, "insertText",
|
||||
aDescription + 'inputType should be "insertText" when typing " "');
|
||||
is(inputEvent.data, " ",
|
||||
aDescription + 'data should be " " when typing " "');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("KEY_Delete");
|
||||
|
@ -122,6 +130,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Delete key wasn't trusted event");
|
||||
is(inputEvent.inputType, "deleteContentForward",
|
||||
aDescription + 'inputType should be "deleteContentForward" when pressing "Delete" with collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Delete" with collapsed selection');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("z", {accelKey: true});
|
||||
|
@ -130,6 +140,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Undo wasn't trusted event");
|
||||
is(inputEvent.inputType, "historyUndo",
|
||||
aDescription + 'inputType should be "historyUndo" when doing "Undo"');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when doing "Undo"');
|
||||
|
||||
inputEvent = null;
|
||||
synthesizeKey("Z", {accelKey: true, shiftKey: true});
|
||||
|
@ -138,6 +150,8 @@ function runTests() {
|
|||
ok(inputEvent.isTrusted, aDescription + "input event by Redo wasn't trusted event");
|
||||
is(inputEvent.inputType, "historyRedo",
|
||||
aDescription + 'inputType should be "historyRedo" when doing "Redo"');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when doing "Redo"');
|
||||
|
||||
// Backspace/Delete with non-collapsed selection.
|
||||
aElement.value = "a";
|
||||
|
@ -150,6 +164,8 @@ function runTests() {
|
|||
aDescription + 'input event should be trusted when pressing "Backspace" with non-collapsed selection');
|
||||
is(inputEvent.inputType, "deleteContentBackward",
|
||||
aDescription + 'inputType should be "deleteContentBackward" when pressing "Backspace" with non-collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when pressing "Backspace" with non-collapsed selection');
|
||||
|
||||
aElement.value = "a";
|
||||
aElement.select();
|
||||
|
@ -161,6 +177,8 @@ function runTests() {
|
|||
aDescription + 'input event should be trusted when pressing "Delete" with non-collapsed selection');
|
||||
is(inputEvent.inputType, "deleteContentForward",
|
||||
aDescription + 'inputType should be "deleteContentBackward" when Delete "Backspace" with non-collapsed selection');
|
||||
is(inputEvent.data, null,
|
||||
aDescription + 'data should be null when Delete "Backspace" with non-collapsed selection');
|
||||
|
||||
aElement.removeEventListener("input", handler, true);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ SimpleTest.waitForFocus(function() {
|
|||
'"input" event should always bubble after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor');
|
||||
is(inputEvents[0].inputType, "insertText",
|
||||
'inputType should be "insertText" after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor');
|
||||
is(inputEvents[0].data, "this is quoted text\nAnd here is second line.",
|
||||
"data should be the quoted text after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor");
|
||||
|
||||
// Tests when the editor is in HTML editor mode.
|
||||
getEditor().flags &= ~SpecialPowers.Ci.nsIPlaintextEditor.eEditorPlaintextMask;
|
||||
|
@ -80,6 +82,8 @@ SimpleTest.waitForFocus(function() {
|
|||
'"input" event should always bubble after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext)');
|
||||
is(inputEvents[0].inputType, "",
|
||||
"inputType should be empty string after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext)");
|
||||
is(inputEvents[0].data, null,
|
||||
"data should be null after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext)");
|
||||
|
||||
editor.innerHTML = "";
|
||||
|
||||
|
@ -104,6 +108,8 @@ SimpleTest.waitForFocus(function() {
|
|||
'"input" event should always bubble after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source)');
|
||||
is(inputEvents[0].inputType, "",
|
||||
"inputType should be empty string after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source)");
|
||||
is(inputEvents[0].data, null,
|
||||
"data should be null after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source)");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
|
|
@ -29,7 +29,7 @@ SimpleTest.waitForFocus(function() {
|
|||
document.getElementById("textarea"),
|
||||
];
|
||||
for (let editableElement of editableElements) {
|
||||
function checkInputEvent(aEvent, aInputType, aDescription) {
|
||||
function checkInputEvent(aEvent, aInputType, aData, aDescription) {
|
||||
ok(aEvent instanceof InputEvent,
|
||||
`"input" event should be dispatched with InputEvent interface ${aDescription}`);
|
||||
is(aEvent.cancelable, false,
|
||||
|
@ -38,6 +38,8 @@ SimpleTest.waitForFocus(function() {
|
|||
`"input" event should always bubble ${aDescription}`);
|
||||
is(aEvent.inputType, aInputType,
|
||||
`inputType should be "${aInputType}" ${aDescription}`);
|
||||
is(aEvent.data, aData,
|
||||
`data should be ${aData} ${aDescription}`);
|
||||
}
|
||||
|
||||
let inputEvents = [];
|
||||
|
@ -52,13 +54,13 @@ SimpleTest.waitForFocus(function() {
|
|||
synthesizeKey("a");
|
||||
is(inputEvents.length, 1,
|
||||
`Only one "input" event should be fired when inserting "a" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "insertText", `when inserting "a" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "insertText", "a", `when inserting "a" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
|
||||
inputEvents = [];
|
||||
synthesizeKey("c");
|
||||
is(inputEvents.length, 1,
|
||||
`Only one "input" event should be fired when inserting "c" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "insertText", `when inserting "c" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "insertText", "c", `when inserting "c" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
|
||||
inputEvents = [];
|
||||
synthesizeKey("KEY_ArrowLeft");
|
||||
|
@ -69,7 +71,7 @@ SimpleTest.waitForFocus(function() {
|
|||
synthesizeKey("b");
|
||||
is(inputEvents.length, 1,
|
||||
`Only one "input" event should be fired when inserting "b" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "insertText", `when inserting "b" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "insertText", "b", `when inserting "b" with key on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
|
||||
let editor = SpecialPowers.wrap(editableElement).editor;
|
||||
let transactionManager = editor.transactionManager;
|
||||
|
@ -93,7 +95,7 @@ SimpleTest.waitForFocus(function() {
|
|||
synthesizeKey("a");
|
||||
is(inputEvents.length, 1,
|
||||
`Only one "input" event should be fired when inserting "a" with key again on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "insertText", `when inserting "a" with key again on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "insertText", "a", `when inserting "a" with key again on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
|
||||
inputEvents = [];
|
||||
synthesizeKey("z", { accelKey: true });
|
||||
|
@ -101,7 +103,7 @@ SimpleTest.waitForFocus(function() {
|
|||
editableElement.tagName + ": undo should work after setting value");
|
||||
is(inputEvents.length, 1,
|
||||
`Only one "input" event should be fired when undoing on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "historyUndo", `when undoing on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
checkInputEvent(inputEvents[0], "historyUndo", null, `when undoing on <${editableElement.tagName.toLowerCase()}> element`);
|
||||
|
||||
// Disable undo/redo.
|
||||
editor.enableUndo(0);
|
||||
|
|
|
@ -96,6 +96,10 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
this._description + ", " + aTest.description + ': "input" event should be never cancelable');
|
||||
this._is(aInputEvents[i].bubbles, true,
|
||||
this._description + ", " + aTest.description + ': "input" event should always bubble');
|
||||
this._is(aInputEvents[i].inputType, aTest.inputEvents[i].inputType,
|
||||
this._description + ", " + aTest.description + ': inputType of "input" event should be "${aTest.inputEvents[i].inputType}"');
|
||||
this._is(aInputEvents[i].data, aTest.inputEvents[i].data,
|
||||
this._description + ", " + aTest.description + ': data of "input" event should be ${aTest.inputEvents[i].data}');
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -108,8 +112,8 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "Mo", searchString: "Mo",
|
||||
inputEvents: [
|
||||
{inputType: "insertText"},
|
||||
{inputType: "insertText"},
|
||||
{inputType: "insertText", data: "M"},
|
||||
{inputType: "insertText", data: "o"},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case: select 'Mozilla' to complete the word",
|
||||
|
@ -120,7 +124,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "Mozilla", searchString: "Mozilla",
|
||||
inputEvents: [
|
||||
{inputType: "insertReplacementText"},
|
||||
{inputType: "insertReplacementText", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case: undo the word, but typed text shouldn't be canceled",
|
||||
|
@ -130,7 +134,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "Mo", searchString: "Mo",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case: undo the typed text",
|
||||
|
@ -140,7 +144,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "", searchString: "",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case: redo the typed text",
|
||||
|
@ -150,7 +154,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "Mo", searchString: "Mo",
|
||||
inputEvents: [
|
||||
{inputType: "historyRedo"},
|
||||
{inputType: "historyRedo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case: redo the word",
|
||||
|
@ -160,7 +164,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "Mozilla", searchString: "Mozilla",
|
||||
inputEvents: [
|
||||
{inputType: "historyRedo"},
|
||||
{inputType: "historyRedo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case: removing all text for next test...",
|
||||
|
@ -171,7 +175,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "", searchString: "",
|
||||
inputEvents: [
|
||||
{inputType: "deleteContentBackward"},
|
||||
{inputType: "deleteContentBackward", data: null},
|
||||
],
|
||||
},
|
||||
|
||||
|
@ -183,8 +187,8 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "mo", searchString: "mo",
|
||||
inputEvents: [
|
||||
{inputType: "insertText"},
|
||||
{inputType: "insertText"},
|
||||
{inputType: "insertText", data: "m"},
|
||||
{inputType: "insertText", data: "o"},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case: select 'Mozilla' to complete the word",
|
||||
|
@ -195,7 +199,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "Mozilla", searchString: "Mozilla",
|
||||
inputEvents: [
|
||||
{inputType: "insertReplacementText"},
|
||||
{inputType: "insertReplacementText", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case: undo the word, but typed text shouldn't be canceled",
|
||||
|
@ -205,7 +209,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "mo", searchString: "mo",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case: undo the typed text",
|
||||
|
@ -215,7 +219,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "", searchString: "",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case: redo the typed text",
|
||||
|
@ -225,7 +229,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "mo", searchString: "mo",
|
||||
inputEvents: [
|
||||
{inputType: "historyRedo"},
|
||||
{inputType: "historyRedo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case: redo the word",
|
||||
|
@ -235,7 +239,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "Mozilla", searchString: "Mozilla",
|
||||
inputEvents: [
|
||||
{inputType: "historyRedo"},
|
||||
{inputType: "historyRedo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case: removing all text for next test...",
|
||||
|
@ -246,7 +250,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "", searchString: "",
|
||||
inputEvents: [
|
||||
{inputType: "deleteContentBackward"},
|
||||
{inputType: "deleteContentBackward", data: null},
|
||||
],
|
||||
},
|
||||
|
||||
|
@ -263,9 +267,9 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "Mozilla", searchString: "Mo",
|
||||
inputEvents: [
|
||||
{inputType: "insertText"},
|
||||
{inputType: "insertText"},
|
||||
{inputType: "insertReplacementText"},
|
||||
{inputType: "insertText", data: "M"},
|
||||
{inputType: "insertText", data: "o"},
|
||||
{inputType: "insertReplacementText", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): select 'Mozilla' to complete the word",
|
||||
|
@ -293,7 +297,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "Mo", searchString: "Mo",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): undo the typed text",
|
||||
|
@ -307,7 +311,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "", searchString: "",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): redo the typed text",
|
||||
|
@ -321,8 +325,8 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "Mozilla", searchString: "Mo",
|
||||
inputEvents: [
|
||||
{inputType: "historyRedo"},
|
||||
{inputType: "insertReplacementText"},
|
||||
{inputType: "historyRedo", data: null},
|
||||
{inputType: "insertReplacementText", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text exactly matches the case (completeDefaultIndex is true): redo the word",
|
||||
|
@ -350,7 +354,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "", searchString: "",
|
||||
inputEvents: [
|
||||
{inputType: "deleteContentBackward"},
|
||||
{inputType: "deleteContentBackward", data: null},
|
||||
],
|
||||
},
|
||||
|
||||
|
@ -366,9 +370,9 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "mozilla", searchString: "mo",
|
||||
inputEvents: [
|
||||
{inputType: "insertText"},
|
||||
{inputType: "insertText"},
|
||||
{inputType: "insertReplacementText"},
|
||||
{inputType: "insertText", data: "m"},
|
||||
{inputType: "insertText", data: "o"},
|
||||
{inputType: "insertReplacementText", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): select 'Mozilla' to complete the word",
|
||||
|
@ -383,7 +387,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "Mozilla", searchString: "Mozilla",
|
||||
inputEvents: [
|
||||
{inputType: "insertReplacementText"},
|
||||
{inputType: "insertReplacementText", data: null},
|
||||
],
|
||||
},
|
||||
// Different from "exactly matches the case" case, modifying the case causes one additional transaction.
|
||||
|
@ -399,7 +403,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "mozilla", searchString: "mozilla",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): undo the word, but typed text shouldn't be canceled",
|
||||
|
@ -413,7 +417,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "mo", searchString: "mo",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): undo the typed text",
|
||||
|
@ -427,7 +431,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "", searchString: "",
|
||||
inputEvents: [
|
||||
{inputType: "historyUndo"},
|
||||
{inputType: "historyUndo", data: null},
|
||||
],
|
||||
},
|
||||
// XXX This is odd case. Consistency with undo behavior, this should restore "mo".
|
||||
|
@ -445,8 +449,8 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: true, value: "mozilla", searchString: "mo",
|
||||
inputEvents: [
|
||||
{inputType: "historyRedo"},
|
||||
{inputType: "insertReplacementText"},
|
||||
{inputType: "historyRedo", data: null},
|
||||
{inputType: "insertReplacementText", data: null},
|
||||
],
|
||||
},
|
||||
{ description: "Undo/Redo behavior check when typed text does not match the case (completeDefaultIndex is true): redo the default index word",
|
||||
|
@ -487,7 +491,7 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
return true;
|
||||
}, popup: false, value: "", searchString: "",
|
||||
inputEvents: [
|
||||
{inputType: "deleteContentBackward"},
|
||||
{inputType: "deleteContentBackward", data: null},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -130,6 +130,36 @@ enum class EditorInputType : EditorInputTypeType {
|
|||
|
||||
#undef NS_DEFINE_INPUTTYPE
|
||||
|
||||
/**
|
||||
* IsDataAvailableOnTextEditor() returns true if aInputType on TextEditor
|
||||
* should have non-null InputEvent.data value.
|
||||
*/
|
||||
inline bool IsDataAvailableOnTextEditor(EditorInputType aInputType) {
|
||||
switch (aInputType) {
|
||||
case EditorInputType::eInsertText:
|
||||
case EditorInputType::eInsertCompositionText:
|
||||
case EditorInputType::eInsertFromComposition: // Only level 2
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IsDataAvailableOnHTMLEditor() returns true if aInputType on HTMLEditor
|
||||
* should have non-null InputEvent.data value.
|
||||
*/
|
||||
inline bool IsDataAvailableOnHTMLEditor(EditorInputType aInputType) {
|
||||
switch (aInputType) {
|
||||
case EditorInputType::eInsertText:
|
||||
case EditorInputType::eInsertCompositionText:
|
||||
case EditorInputType::eInsertFromComposition: // Only level 2
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define NS_DEFINE_COMMAND(aName, aCommandStr) , Command##aName
|
||||
#define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) , Command##aName
|
||||
|
||||
|
|
|
@ -385,6 +385,9 @@ nsresult TextEventDispatcher::CommitComposition(
|
|||
}
|
||||
if (message == eCompositionCommit) {
|
||||
compositionCommitEvent.mData = *aCommitString;
|
||||
// If aCommitString comes from TextInputProcessor, it may be void, but
|
||||
// editor requires non-void string even when it's empty.
|
||||
compositionCommitEvent.mData.SetIsVoid(false);
|
||||
// Don't send CRLF nor CR, replace it with LF here.
|
||||
compositionCommitEvent.mData.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
|
||||
NS_LITERAL_STRING("\n"));
|
||||
|
@ -908,6 +911,9 @@ nsresult TextEventDispatcher::PendingComposition::Flush(
|
|||
compChangeEvent.AssignEventTime(*aEventTime);
|
||||
}
|
||||
compChangeEvent.mData = mString;
|
||||
// If mString comes from TextInputProcessor, it may be void, but editor
|
||||
// requires non-void string even when it's empty.
|
||||
compChangeEvent.mData.SetIsVoid(false);
|
||||
if (mClauses) {
|
||||
MOZ_ASSERT(!mClauses->IsEmpty(),
|
||||
"mClauses must be non-empty array when it's not nullptr");
|
||||
|
|
|
@ -1140,7 +1140,9 @@ class WidgetSelectionEvent : public WidgetGUIEvent {
|
|||
class InternalEditorInputEvent : public InternalUIEvent {
|
||||
private:
|
||||
InternalEditorInputEvent()
|
||||
: mInputType(EditorInputType::eUnknown), mIsComposing(false) {}
|
||||
: mData(VoidString()),
|
||||
mInputType(EditorInputType::eUnknown),
|
||||
mIsComposing(false) {}
|
||||
|
||||
public:
|
||||
virtual InternalEditorInputEvent* AsEditorInputEvent() override {
|
||||
|
@ -1150,6 +1152,7 @@ class InternalEditorInputEvent : public InternalUIEvent {
|
|||
InternalEditorInputEvent(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget* aWidget = nullptr)
|
||||
: InternalUIEvent(aIsTrusted, aMessage, aWidget, eEditorInputEventClass),
|
||||
mData(VoidString()),
|
||||
mInputType(EditorInputType::eUnknown) {}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override {
|
||||
|
|
|
@ -643,7 +643,7 @@ function runUndoRedoTest()
|
|||
}
|
||||
}
|
||||
|
||||
function checkInputEvent(aEvent, aIsComposing, aInputType, aDescription) {
|
||||
function checkInputEvent(aEvent, aIsComposing, aInputType, aData, aDescription) {
|
||||
if (aEvent.type != "input") {
|
||||
return;
|
||||
}
|
||||
|
@ -652,6 +652,7 @@ function checkInputEvent(aEvent, aIsComposing, aInputType, aDescription) {
|
|||
is(aEvent.bubbles, true, `"input" event should always bubble: ${aDescription}`);
|
||||
is(aEvent.isComposing, aIsComposing, `isComposing should be ${aIsComposing}: ${aDescription}`);
|
||||
is(aEvent.inputType, aInputType, `inputType should be "${aInputType}": ${aDescription}`);
|
||||
is(aEvent.data, aData, `data should be ${aData}: ${aDescription}`);
|
||||
}
|
||||
|
||||
function runCompositionCommitAsIsTest()
|
||||
|
@ -700,7 +701,7 @@ function runCompositionCommitAsIsTest()
|
|||
"runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #1");
|
||||
is(result[2].type, "input",
|
||||
"runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #1");
|
||||
checkInputEvent(result[2], false, "insertCompositionText",
|
||||
checkInputEvent(result[2], false, "insertCompositionText", "\u3042",
|
||||
"runCompositionCommitAsIsTest: after dispatching compositioncommitasis #1");
|
||||
is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have committed string #1");
|
||||
|
||||
|
@ -740,7 +741,7 @@ function runCompositionCommitAsIsTest()
|
|||
"runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #2");
|
||||
is(result[1].type, "input",
|
||||
"runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #2");
|
||||
checkInputEvent(result[1], false, "insertCompositionText",
|
||||
checkInputEvent(result[1], false, "insertCompositionText", "\u3042",
|
||||
"runCompositionCommitAsIsTest: after dispatching compositioncommitasis #2");
|
||||
is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have committed string #2");
|
||||
|
||||
|
@ -780,7 +781,7 @@ function runCompositionCommitAsIsTest()
|
|||
"runCompositionCommitAsIsTest: compositionend shouldn't be fired after dispatching compositioncommitasis #3");
|
||||
is(result[1].type, "input",
|
||||
"runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #3");
|
||||
checkInputEvent(result[1], false, "insertCompositionText",
|
||||
checkInputEvent(result[1], false, "insertCompositionText", "",
|
||||
"runCompositionCommitAsIsTest: after dispatching compositioncommitasis #3");
|
||||
is(textarea.value, "", "runCompositionCommitAsIsTest: textarea doesn't have committed string #3");
|
||||
|
||||
|
@ -838,7 +839,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #1");
|
||||
is(result[3].type, "input",
|
||||
"runCompositionCommitTest: input should be fired after dispatching compositioncommit #1");
|
||||
checkInputEvent(result[3], false, "insertCompositionText",
|
||||
checkInputEvent(result[3], false, "insertCompositionText", "\u3043",
|
||||
"runCompositionCommitTest: after dispatching compositioncommit #1");
|
||||
is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #1");
|
||||
|
||||
|
@ -882,7 +883,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #2");
|
||||
is(result[3].type, "input",
|
||||
"runCompositionCommitTest: input should be fired after dispatching compositioncommit #2");
|
||||
checkInputEvent(result[3], false, "insertCompositionText",
|
||||
checkInputEvent(result[3], false, "insertCompositionText", "\u3043",
|
||||
"runCompositionCommitTest: after dispatching compositioncommit #2");
|
||||
is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #2");
|
||||
|
||||
|
@ -926,7 +927,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #3");
|
||||
is(result[3].type, "input",
|
||||
"runCompositionCommitTest: input should be fired after dispatching compositioncommit #3");
|
||||
checkInputEvent(result[3], false, "insertCompositionText",
|
||||
checkInputEvent(result[3], false, "insertCompositionText", "\u3043",
|
||||
"runCompositionCommitTest: after dispatching compositioncommit #3");
|
||||
is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #3");
|
||||
|
||||
|
@ -946,7 +947,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired when inserting empty string with composition");
|
||||
is(result[2].type, "input",
|
||||
"runCompositionCommitTest: input should be fired when inserting empty string with composition");
|
||||
checkInputEvent(result[2], false, "insertCompositionText",
|
||||
checkInputEvent(result[2], false, "insertCompositionText", "",
|
||||
"runCompositionCommitTest: when inserting empty string with composition");
|
||||
is(textarea.value, "abc",
|
||||
"runCompositionCommitTest: textarea should keep original value when inserting empty string with composition");
|
||||
|
@ -967,7 +968,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired when replacing with empty string with composition");
|
||||
is(result[2].type, "input",
|
||||
"runCompositionCommitTest: input should be fired when replacing with empty string with composition");
|
||||
checkInputEvent(result[2], false, "insertCompositionText",
|
||||
checkInputEvent(result[2], false, "insertCompositionText", "",
|
||||
"runCompositionCommitTest: when replacing with empty string with composition");
|
||||
is(textarea.value, "",
|
||||
"runCompositionCommitTest: textarea should become empty when replacing selection with empty string with composition");
|
||||
|
@ -990,7 +991,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired when replacing selection with same string with composition");
|
||||
is(result[3].type, "input",
|
||||
"runCompositionCommitTest: input should be fired when replacing selection with same string with composition");
|
||||
checkInputEvent(result[3], false, "insertCompositionText",
|
||||
checkInputEvent(result[3], false, "insertCompositionText", "abc",
|
||||
"runCompositionCommitTest: when replacing selection with same string with composition");
|
||||
is(textarea.value, "abc",
|
||||
"runCompositionCommitTest: textarea should keep same value when replacing selection with same string with composition");
|
||||
|
@ -1023,7 +1024,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #4");
|
||||
is(result[3].type, "input",
|
||||
"runCompositionCommitTest: input should be fired after dispatching compositioncommit #4");
|
||||
checkInputEvent(result[3], false, "insertCompositionText",
|
||||
checkInputEvent(result[3], false, "insertCompositionText", "",
|
||||
"runCompositionCommitTest: after dispatching compositioncommit #4");
|
||||
is(textarea.value, "", "runCompositionCommitTest: textarea should be empty #4");
|
||||
|
||||
|
@ -1043,7 +1044,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #5");
|
||||
is(result[3].type, "input",
|
||||
"runCompositionCommitTest: input should be fired after dispatching compositioncommit #5");
|
||||
checkInputEvent(result[3], false, "insertCompositionText",
|
||||
checkInputEvent(result[3], false, "insertCompositionText", "\u3042",
|
||||
"runCompositionCommitTest: after dispatching compositioncommit #5");
|
||||
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should be empty #5");
|
||||
|
||||
|
@ -1073,7 +1074,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #6");
|
||||
is(result[2].type, "input",
|
||||
"runCompositionCommitTest: input should be fired after dispatching compositioncommit #6");
|
||||
checkInputEvent(result[2], false, "insertCompositionText",
|
||||
checkInputEvent(result[2], false, "insertCompositionText", "\u3042",
|
||||
"runCompositionCommitTest: after dispatching compositioncommit #6");
|
||||
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should have committed string #6");
|
||||
|
||||
|
@ -1114,7 +1115,7 @@ function runCompositionCommitTest()
|
|||
"runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #7");
|
||||
is(result[1].type, "input",
|
||||
"runCompositionCommitTest: input should be fired after dispatching compositioncommit #7");
|
||||
checkInputEvent(result[1], false, "insertCompositionText",
|
||||
checkInputEvent(result[1], false, "insertCompositionText", "\u3042",
|
||||
"runCompositionCommitTest: after dispatching compositioncommit #7");
|
||||
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should have committed string #6");
|
||||
|
||||
|
@ -5055,7 +5056,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 3rd event must be text #1");
|
||||
is(events[3].type, "input",
|
||||
"runForceCommitTest: the 4th event must be input #1");
|
||||
checkInputEvent(events[3], true, "insertCompositionText", "runForceCommitTest #1");
|
||||
checkInputEvent(events[3], true, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #1");
|
||||
|
||||
events = [];
|
||||
synthesizeMouseAtCenter(textarea, {});
|
||||
|
@ -5068,7 +5070,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #2");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #2");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #2");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #2");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #2");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5109,7 +5112,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #3");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #3");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #3");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #3");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #3");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5153,7 +5157,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #4");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #4");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #4");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #4");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #4");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5194,7 +5199,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #5");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #5");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #5");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #5");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #5");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5239,7 +5245,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #6");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #6");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #6");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #6");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #6");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5284,7 +5291,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #7");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #7");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #7");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #7");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #7");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5330,7 +5338,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #8");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #8");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #8");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #8");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #8");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5375,7 +5384,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #9");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #9");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #9");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #9");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #9");
|
||||
is(events[0].target, iframe2.contentDocument.body,
|
||||
|
@ -5418,7 +5428,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #10");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #10");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #10");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #10");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #10");
|
||||
is(events[0].target, iframe2.contentDocument.body,
|
||||
|
@ -5466,7 +5477,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #11");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #11");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #11");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #11");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #11");
|
||||
is(events[0].target, iframe2.contentDocument.body,
|
||||
|
@ -5510,7 +5522,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #12");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #12");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #12");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #12");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #12");
|
||||
is(events[0].target, input,
|
||||
|
@ -5549,7 +5562,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #13");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #13");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #13");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #13");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #13");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5588,7 +5602,8 @@ function runForceCommitTest()
|
|||
"runForceCommitTest: the 2nd event must be compositionend #14");
|
||||
is(events[2].type, "input",
|
||||
"runForceCommitTest: the 3rd event must be input #14");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runForceCommitTest #14");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runForceCommitTest #14");
|
||||
is(events[1].data, "\u306E",
|
||||
"runForceCommitTest: compositionend has wrong data #14");
|
||||
is(events[0].target, input,
|
||||
|
@ -5701,7 +5716,8 @@ function runNestedSettingValue()
|
|||
"runNestedSettingValue: the 2nd event must be compositionend #1");
|
||||
is(events[2].type, "input",
|
||||
"runNestedSettingValue: the 3rd event must be input #1");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runNestedSettingValue #1");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runNestedSettingValue #1");
|
||||
is(events[1].data, "\u306E",
|
||||
"runNestedSettingValue: compositionend has wrong data #1");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5742,7 +5758,8 @@ function runNestedSettingValue()
|
|||
"runNestedSettingValue: the 2nd event must be compositionend #2");
|
||||
is(events[2].type, "input",
|
||||
"runNestedSettingValue: the 3rd event must be input #2");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runNestedSettingValue #2");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runNestedSettingValue #2");
|
||||
is(events[1].data, "\u306E",
|
||||
"runNestedSettingValue: compositionend has wrong data #2");
|
||||
is(events[0].target, input,
|
||||
|
@ -5783,7 +5800,8 @@ function runNestedSettingValue()
|
|||
"runNestedSettingValue: the 2nd event must be compositionend #3");
|
||||
is(events[2].type, "input",
|
||||
"runNestedSettingValue: the 3rd event must be input #3");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runNestedSettingValue #3");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runNestedSettingValue #3");
|
||||
is(events[1].data, "\u306E",
|
||||
"runNestedSettingValue: compositionend has wrong data #3");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5824,7 +5842,8 @@ function runNestedSettingValue()
|
|||
"runNestedSettingValue: the 2nd event must be compositionend #4");
|
||||
is(events[2].type, "input",
|
||||
"runNestedSettingValue: the 3rd event must be input #4");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runNestedSettingValue #4");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runNestedSettingValue #4");
|
||||
is(events[1].data, "\u306E",
|
||||
"runNestedSettingValue: compositionend has wrong data #4");
|
||||
is(events[0].target, input,
|
||||
|
@ -5917,7 +5936,8 @@ function runAsyncForceCommitTest()
|
|||
"runAsyncForceCommitTest: the 3rd event must be text #1");
|
||||
is(events[3].type, "input",
|
||||
"runAsyncForceCommitTest: the 4th event must be input #1");
|
||||
checkInputEvent(events[3], true, "insertCompositionText", "runAsyncForceCommitTest #1");
|
||||
checkInputEvent(events[3], true, "insertCompositionText", "\u306E",
|
||||
"runAsyncForceCommitTest #1");
|
||||
|
||||
events = [];
|
||||
commitRequested = false;
|
||||
|
@ -5933,7 +5953,8 @@ function runAsyncForceCommitTest()
|
|||
"runAsyncForceCommitTest: the 2nd event must be compositionend #2");
|
||||
is(events[2].type, "input",
|
||||
"runAsyncForceCommitTest: the 3rd event must be input #2");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "runAsyncForceCommitTest #2");
|
||||
checkInputEvent(events[2], false, "insertCompositionText", "\u306E",
|
||||
"runAsyncForceCommitTest #2");
|
||||
is(events[1].data, "\u306E",
|
||||
"runAsyncForceCommitTest: compositionend has wrong data #2");
|
||||
is(events[0].target, textarea,
|
||||
|
@ -5985,7 +6006,8 @@ function runIsComposingTest()
|
|||
is(aEvent.isComposing, false,
|
||||
"runIsComposingTest: " + description + " (type=" + aEvent.type + ")");
|
||||
} else {
|
||||
checkInputEvent(aEvent, expectedIsComposing, "insertCompositionText", `runIsComposingTest: ${description}`);
|
||||
checkInputEvent(aEvent, expectedIsComposing, "insertCompositionText", "\u3042",
|
||||
`runIsComposingTest: ${description}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6095,7 +6117,7 @@ function runRedundantChangeTest()
|
|||
"runRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string #1");
|
||||
is(result[2].type, "input",
|
||||
"runRedundantChangeTest: input should be fired after synthesizing composition change #1");
|
||||
checkInputEvent(result[2], true, "insertCompositionText",
|
||||
checkInputEvent(result[2], true, "insertCompositionText", "\u3042",
|
||||
"runRedundantChangeTest: after synthesizing composition change #1");
|
||||
is(textarea.value, "\u3042", "runRedundantChangeTest: textarea has uncommitted string #1");
|
||||
|
||||
|
@ -6120,7 +6142,7 @@ function runRedundantChangeTest()
|
|||
"runRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string #2");
|
||||
is(result[2].type, "input",
|
||||
"runRedundantChangeTest: input should be fired after synthesizing composition change #2");
|
||||
checkInputEvent(result[2], true, "insertCompositionText",
|
||||
checkInputEvent(result[2], true, "insertCompositionText", "\u3042\u3044",
|
||||
"runRedundantChangeTest: after synthesizing composition change #2");
|
||||
is(textarea.value, "\u3042\u3044", "runRedundantChangeTest: textarea has uncommitted string #2");
|
||||
|
||||
|
@ -6151,7 +6173,7 @@ function runRedundantChangeTest()
|
|||
"runRedundantChangeTest: compositionend should be fired after synthesizing composition commit-as-is");
|
||||
is(result[2].type, "input",
|
||||
"runRedundantChangeTest: input shouldn't be fired before compositionend at synthesizing commit-as-is");
|
||||
checkInputEvent(result[2], false, "insertCompositionText",
|
||||
checkInputEvent(result[2], false, "insertCompositionText", "\u3042\u3044",
|
||||
"runRedundantChangeTest: at synthesizing commit-as-is");
|
||||
is(textarea.value, "\u3042\u3044", "runRedundantChangeTest: textarea has the commit string");
|
||||
|
||||
|
@ -6204,7 +6226,7 @@ function runNotRedundantChangeTest()
|
|||
"runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges");
|
||||
is(result[2].type, "input",
|
||||
"runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges");
|
||||
checkInputEvent(result[2], true, "insertCompositionText",
|
||||
checkInputEvent(result[2], true, "insertCompositionText", "ABCDE",
|
||||
"runNotRedundantChangeTest: after synthesizing composition change with non-null ranges");
|
||||
is(textarea.value, "abcdeABCDE", "runNotRedundantChangeTest: textarea has uncommitted string #1");
|
||||
|
||||
|
@ -6225,7 +6247,7 @@ function runNotRedundantChangeTest()
|
|||
"runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with null ranges after non-null ranges");
|
||||
is(result[1].type, "input",
|
||||
"runNotRedundantChangeTest: input should be fired after synthesizing composition change with null ranges after non-null ranges");
|
||||
checkInputEvent(result[1], true, "insertCompositionText",
|
||||
checkInputEvent(result[1], true, "insertCompositionText", "ABCDE",
|
||||
"runNotRedundantChangeTest: after synthesizing composition change with null ranges after non-null ranges");
|
||||
is(textarea.value, "abcdeABCDE", "runNotRedundantChangeTest: textarea has uncommitted string #2");
|
||||
|
||||
|
@ -6248,7 +6270,7 @@ function runNotRedundantChangeTest()
|
|||
"runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges after null ranges");
|
||||
is(result[1].type, "input",
|
||||
"runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges after null ranges");
|
||||
checkInputEvent(result[1], true, "insertCompositionText",
|
||||
checkInputEvent(result[1], true, "insertCompositionText", "ABCDE",
|
||||
"runNotRedundantChangeTest: after synthesizing composition change with non-null ranges after null ranges");
|
||||
is(textarea.value, "abcdeABCDE", "runNotRedundantChangeTest: textarea has uncommitted string #3");
|
||||
|
||||
|
@ -6271,7 +6293,7 @@ function runNotRedundantChangeTest()
|
|||
"runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with empty data and null ranges after non-null ranges");
|
||||
is(result[2].type, "input",
|
||||
"runNotRedundantChangeTest: input should be fired after synthesizing composition change with empty data and null ranges after non-null ranges");
|
||||
checkInputEvent(result[2], true, "insertCompositionText",
|
||||
checkInputEvent(result[2], true, "insertCompositionText", "",
|
||||
"runNotRedundantChangeTest: after synthesizing composition change with empty data and null ranges after non-null ranges");
|
||||
is(textarea.value, "abcde", "runNotRedundantChangeTest: textarea doesn't have uncommitted string #1");
|
||||
|
||||
|
@ -6296,7 +6318,7 @@ function runNotRedundantChangeTest()
|
|||
"runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges after empty data and null ranges");
|
||||
is(result[2].type, "input",
|
||||
"runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges after empty data and null ranges");
|
||||
checkInputEvent(result[2], true, "insertCompositionText",
|
||||
checkInputEvent(result[2], true, "insertCompositionText", "ABCDE",
|
||||
"runNotRedundantChangeTest: after synthesizing composition change with non-null ranges after empty data and null ranges");
|
||||
is(textarea.value, "abcdeABCDE", "runNotRedundantChangeTest: textarea has uncommitted string #4");
|
||||
|
||||
|
@ -6313,7 +6335,7 @@ function runNotRedundantChangeTest()
|
|||
"runNotRedundantChangeTest: compositionend should be fired after synthesizing composition commit with empty data after non-empty data");
|
||||
is(result[3].type, "input",
|
||||
"runNotRedundantChangeTest: input should be fired after compositionend after synthesizing composition change with empty data after non-empty data");
|
||||
checkInputEvent(result[3], false, "insertCompositionText",
|
||||
checkInputEvent(result[3], false, "insertCompositionText", "",
|
||||
"runNotRedundantChangeTest: after synthesizing composition change with empty data after non-empty data");
|
||||
is(textarea.value, "abcde", "runNotRedundantChangeTest: textarea doesn't have uncommitted string #2");
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче