mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 968104, paste unformatted shortcut (shift+ctrl/cmd+v) should work in plain text contexts, such as input and textarea, r=masayuki
Differential Revision: https://phabricator.services.mozilla.com/D150806
This commit is contained in:
parent
65711751b2
commit
00acc7206b
@ -178,6 +178,12 @@ ShortcutKeyData ShortcutKeys::sInputHandlers[] = {
|
||||
{u"keypress", nullptr, u"z", u"accel", u"cmd_undo"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"z", u"accel,shift", u"cmd_redo"}, // Win, macOS, Linux, Android, Emacs
|
||||
|
||||
{u"keypress", nullptr, u"v", u"accel,shift", u"cmd_paste"}, // Win, macOS, Linux, Android, Emacs
|
||||
// Mac uses Option+Shift+Command+V for Paste and Match Style
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
{u"keypress", nullptr, u"v", u"accel,alt,shift", u"cmd_paste"}, // macOS
|
||||
#endif // MOZ_WIDGET_COCOA
|
||||
|
||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) ||\
|
||||
defined(USE_EMACS_KEY_BINDINGS)
|
||||
{u"keypress", nullptr, u"y", u"accel", u"cmd_redo"}, // Win, Linux, Emacs
|
||||
@ -315,6 +321,12 @@ ShortcutKeyData ShortcutKeys::sTextAreaHandlers[] = {
|
||||
{u"keypress", u"VK_INSERT", nullptr, u"shift", u"cmd_paste"}, // Win, Emacs
|
||||
#endif // XP_WIN || USE_EMACS_KEY_BINDINGS
|
||||
|
||||
{u"keypress", nullptr, u"v", u"accel,shift", u"cmd_paste"}, // Win, macOS, Linux, Android, Emacs
|
||||
// Mac uses Option+Shift+Command+V for Paste and Match Style
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
{u"keypress", nullptr, u"v", u"accel,alt,shift", u"cmd_paste"}, // macOS
|
||||
#endif // MOZ_WIDGET_COCOA
|
||||
|
||||
/**************************************************************************
|
||||
* Delete key in <textarea>.
|
||||
**************************************************************************/
|
||||
@ -544,11 +556,17 @@ ShortcutKeyData ShortcutKeys::sBrowserHandlers[] = {
|
||||
/**************************************************************************
|
||||
* Common editor commands in non-editable element.
|
||||
**************************************************************************/
|
||||
{u"keypress", nullptr, u"c", u"accel", u"cmd_copy"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"x", u"accel", u"cmd_cut"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"v", u"accel", u"cmd_paste"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"z", u"accel", u"cmd_undo"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"z", u"accel,shift", u"cmd_redo"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"c", u"accel", u"cmd_copy"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"x", u"accel", u"cmd_cut"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"v", u"accel", u"cmd_paste"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"v", u"accel,shift", u"cmd_pasteNoFormatting"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"z", u"accel", u"cmd_undo"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"z", u"accel,shift", u"cmd_redo"}, // Win, macOS, Linux, Android, Emacs
|
||||
|
||||
// Mac uses Option+Shift+Command+V for Paste and Match Style
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
{u"keypress", nullptr, u"v", u"accel,alt,shift", u"cmd_pasteNoFormatting"}, // macOS
|
||||
#endif // MOZ_WIDGET_COCOA
|
||||
|
||||
#if defined(XP_WIN)
|
||||
{u"keypress", nullptr, u"y", u"accel", u"cmd_redo"}, // Win
|
||||
@ -714,6 +732,7 @@ ShortcutKeyData ShortcutKeys::sEditorHandlers[] = {
|
||||
{u"keypress", nullptr, u"z", u"accel", u"cmd_undo"}, // Win, macOS, Linux, Android, Emacs
|
||||
{u"keypress", nullptr, u"z", u"accel,shift", u"cmd_redo"}, // Win, macOS, Linux, Android, Emacs
|
||||
|
||||
// Mac uses Option+Shift+Command+V for Paste and Match Style
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
{u"keypress", nullptr, u"v", u"accel,alt,shift", u"cmd_pasteNoFormatting"}, // macOS
|
||||
#endif // MOZ_WIDGET_COCOA
|
||||
|
@ -298,6 +298,10 @@ TEST(ShortcutKeyDefinitions, HTMLInputElement)
|
||||
{0, 'y', MODIFIER_ACCEL, u"cmd_redo", nullptr, u"cmd_redo", nullptr, u"cmd_redo"},
|
||||
{0, 'z', MODIFIER_ACCEL, u"cmd_undo", u"cmd_undo", u"cmd_undo", u"cmd_undo", u"cmd_undo"},
|
||||
|
||||
// charCode Modifiers, Windows macOS Linux Android Emacs
|
||||
{0, 'v', MODIFIER_SHIFT | MODIFIER_ACCEL, u"cmd_paste", u"cmd_paste", u"cmd_paste", u"cmd_paste", u"cmd_paste"},
|
||||
{0, 'v', MODIFIER_SHIFT | MODIFIER_ALT | MODIFIER_ACCEL, nullptr, u"cmd_paste", nullptr, nullptr, nullptr},
|
||||
|
||||
// charCode Modifiers Windows macOS Linux Android Emacs
|
||||
{0, 'z', MODIFIER_SHIFT | MODIFIER_ACCEL, u"cmd_redo", u"cmd_redo", u"cmd_redo", u"cmd_redo", u"cmd_redo"},
|
||||
|
||||
@ -396,6 +400,10 @@ TEST(ShortcutKeyDefinitions, HTMLTextAreaElement)
|
||||
{0, 'y', MODIFIER_ACCEL, u"cmd_redo", nullptr, u"cmd_redo", nullptr, u"cmd_redo"},
|
||||
{0, 'z', MODIFIER_ACCEL, u"cmd_undo", u"cmd_undo", u"cmd_undo", u"cmd_undo", u"cmd_undo"},
|
||||
|
||||
// charCode Modifiers, Windows macOS Linux Android Emacs
|
||||
{0, 'v', MODIFIER_SHIFT | MODIFIER_ACCEL, u"cmd_paste", u"cmd_paste", u"cmd_paste", u"cmd_paste", u"cmd_paste"},
|
||||
{0, 'v', MODIFIER_SHIFT | MODIFIER_ALT | MODIFIER_ACCEL, nullptr, u"cmd_paste", nullptr, nullptr, nullptr},
|
||||
|
||||
// charCode Modifiers Windows macOS Linux Android Emacs
|
||||
{0, 'z', MODIFIER_SHIFT | MODIFIER_ACCEL, u"cmd_redo", u"cmd_redo", u"cmd_redo", u"cmd_redo", u"cmd_redo"},
|
||||
|
||||
@ -497,6 +505,12 @@ TEST(ShortcutKeyDefinitions, Browser)
|
||||
{0, 'y', MODIFIER_ACCEL, u"cmd_redo", nullptr, nullptr, nullptr, nullptr},
|
||||
{0, 'z', MODIFIER_ACCEL, u"cmd_undo", u"cmd_undo", u"cmd_undo", u"cmd_undo", u"cmd_undo"},
|
||||
|
||||
// charCode Modifiers, Windows macOS Linux Android Emacs
|
||||
{0, 'v', MODIFIER_SHIFT | MODIFIER_ACCEL, u"cmd_pasteNoFormatting", u"cmd_pasteNoFormatting", u"cmd_pasteNoFormatting", u"cmd_pasteNoFormatting", u"cmd_pasteNoFormatting"},
|
||||
|
||||
// charCode Modifiers, Windows macOS Linux Android Emacs
|
||||
{0, 'v', MODIFIER_SHIFT | MODIFIER_ALT | MODIFIER_ACCEL, nullptr, u"cmd_pasteNoFormatting", nullptr, nullptr, nullptr},
|
||||
|
||||
// charCode Modifiers Windows macOS Linux Android Emacs
|
||||
{0, 'z', MODIFIER_SHIFT | MODIFIER_ACCEL, u"cmd_redo", u"cmd_redo", u"cmd_redo", u"cmd_redo", u"cmd_redo"},
|
||||
};
|
||||
|
@ -288,6 +288,7 @@ skip-if = headless
|
||||
[test_password_paste.html]
|
||||
[test_password_per_word_operation.html]
|
||||
[test_password_unmask_API.html]
|
||||
[test_paste_no_formatting.html]
|
||||
[test_pasting_in_root_element.xhtml]
|
||||
[test_pasting_in_temporarily_created_div_outside_body.html]
|
||||
[test_pasting_text_longer_than_maxlength.html]
|
||||
|
108
editor/libeditor/tests/test_paste_no_formatting.html
Normal file
108
editor/libeditor/tests/test_paste_no_formatting.html
Normal file
@ -0,0 +1,108 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test pasting formatted test into various fields</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<input id="input">
|
||||
<textarea id="textarea"></textarea>
|
||||
<div id="editable" contenteditable="true"></div>
|
||||
<div id="noneditable">Text</div>
|
||||
|
||||
<div id="source">Some <b>Bold</b> Text</div>
|
||||
<script>
|
||||
|
||||
const expectedText = "Some Bold Text";
|
||||
const expectedHTML = "<div id=\"source\">Some <b>Bold</b> Text</div>";
|
||||
|
||||
const htmlPrefix = navigator.platform.includes("Win")
|
||||
? "<html><body>\n<!--StartFragment-->"
|
||||
: "";
|
||||
const htmlPostfix = navigator.platform.includes("Win")
|
||||
? "<!--EndFragment-->\n</body>\n</html>"
|
||||
: "";
|
||||
|
||||
add_task(async function test_paste_formatted() {
|
||||
window.getSelection().selectAllChildren(document.getElementById("source"));
|
||||
synthesizeKey("c", { accelKey: true });
|
||||
|
||||
function doKey(element, withShiftKey)
|
||||
{
|
||||
let inputEventPromise = new Promise(resolve => {
|
||||
element.addEventListener("input", event => {
|
||||
is(event.inputType, "insertFromPaste", "correct inputType");
|
||||
resolve();
|
||||
}, { once: true });
|
||||
});
|
||||
synthesizeKey("v", { accelKey: true, shiftKey: withShiftKey });
|
||||
return inputEventPromise;
|
||||
}
|
||||
|
||||
// Paste into input and textarea
|
||||
for (let fieldid of ["input", "textarea"]) {
|
||||
let field = document.getElementById(fieldid);
|
||||
field.focus();
|
||||
|
||||
doKey(field, false);
|
||||
is(field.value, expectedText, "paste into " + fieldid);
|
||||
|
||||
doKey(field, true);
|
||||
is(field.value, expectedText + expectedText, "paste unformatted into " + field);
|
||||
}
|
||||
|
||||
const selection = window.getSelection();
|
||||
|
||||
// Paste into editable area
|
||||
let editable = document.getElementById("editable");
|
||||
selection.selectAllChildren(editable);
|
||||
selection.collapseToStart();
|
||||
doKey(editable, false);
|
||||
is(editable.innerHTML, expectedHTML, "paste into contenteditable");
|
||||
|
||||
// Unformatted paste into editable area
|
||||
selection.selectAllChildren(editable);
|
||||
selection.collapseToEnd();
|
||||
doKey(editable, true);
|
||||
is(editable.innerHTML, expectedHTML + expectedText, "paste unformatted into contenteditable");
|
||||
|
||||
let noneditable = document.getElementById("noneditable");
|
||||
selection.selectAllChildren(noneditable);
|
||||
selection.collapseToStart();
|
||||
|
||||
function getPasteResult() {
|
||||
return new Promise(resolve => {
|
||||
noneditable.addEventListener("paste", event => {
|
||||
resolve({
|
||||
text: event.clipboardData.getData("text/plain"),
|
||||
html: event.clipboardData.getData("text/html"),
|
||||
});
|
||||
}, { once: true});
|
||||
});
|
||||
}
|
||||
|
||||
// Normal paste into non-editable area
|
||||
let pastePromise = getPasteResult();
|
||||
doKey(noneditable, false);
|
||||
is(noneditable.innerHTML, "Text", "paste into non-editable");
|
||||
|
||||
let result = await pastePromise;
|
||||
is(result.text, expectedText, "paste text into non-editable");
|
||||
is(result.html, htmlPrefix + expectedHTML + htmlPostfix, "paste html into non-editable");
|
||||
|
||||
// Unformatted paste into non-editable area
|
||||
pastePromise = getPasteResult();
|
||||
doKey(noneditable, true);
|
||||
is(noneditable.innerHTML, "Text", "paste unformatted into non-editable");
|
||||
|
||||
result = await pastePromise;
|
||||
is(result.text, expectedText, "paste unformatted text into non-editable");
|
||||
// Formatted HTML text should not exist when pasting unformatted.
|
||||
is(result.html, "", "paste unformatted html into non-editable");
|
||||
});
|
||||
</script>
|
||||
</body>
|
Loading…
Reference in New Issue
Block a user